~ubuntu-branches/ubuntu/trusty/bc/trusty

« back to all changes in this revision

Viewing changes to bc/scan.l

  • Committer: Bazaar Package Importer
  • Author(s): Dirk Eddelbuettel
  • Date: 2002-04-13 11:33:49 UTC
  • Revision ID: james.westby@ubuntu.com-20020413113349-hl2r1t730b91ov68
Tags: upstream-1.06
ImportĀ upstreamĀ versionĀ 1.06

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
%{
 
2
/* scan.l: the (f)lex description file for the scanner. */
 
3
 
 
4
/*  This file is part of GNU bc.
 
5
    Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
 
6
 
 
7
    This program is free software; you can redistribute it and/or modify
 
8
    it under the terms of the GNU General Public License as published by
 
9
    the Free Software Foundation; either version 2 of the License , or
 
10
    (at your option) any later version.
 
11
 
 
12
    This program is distributed in the hope that it will be useful,
 
13
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
    GNU General Public License for more details.
 
16
 
 
17
    You should have received a copy of the GNU General Public License
 
18
    along with this program; see the file COPYING.  If not, write to
 
19
      The Free Software Foundation, Inc.
 
20
      59 Temple Place, Suite 330
 
21
      Boston, MA 02111 USA
 
22
 
 
23
    You may contact the author by:
 
24
       e-mail:  philnelson@acm.org
 
25
      us-mail:  Philip A. Nelson
 
26
                Computer Science Department, 9062
 
27
                Western Washington University
 
28
                Bellingham, WA 98226-9062
 
29
       
 
30
*************************************************************************/
 
31
 
 
32
#include "bcdefs.h"
 
33
#include "bc.h"
 
34
#include "global.h"
 
35
#include "proto.h"
 
36
#include <errno.h>
 
37
 
 
38
/* Using flex, we can ask for a smaller input buffer.  With lex, this
 
39
   does nothing! */
 
40
 
 
41
#ifdef SMALL_BUF
 
42
#undef YY_READ_BUF_SIZE
 
43
#define YY_READ_BUF_SIZE 512
 
44
#endif
 
45
 
 
46
/* Force . as last for now. */
 
47
#define DOT_IS_LAST
 
48
 
 
49
/* We want to define our own yywrap. */
 
50
#undef yywrap
 
51
_PROTOTYPE(int yywrap, (void));
 
52
 
 
53
#if defined(LIBEDIT)
 
54
/* Support for the BSD libedit with history for
 
55
   nicer input on the interactive part of input. */
 
56
 
 
57
#include <histedit.h>
 
58
 
 
59
/* Have input call the following function. */
 
60
#undef  YY_INPUT
 
61
#define YY_INPUT(buf,result,max_size) \
 
62
                bcel_input((char *)buf, &result, max_size)
 
63
 
 
64
/* Variables to help interface editline with bc. */
 
65
static const char *bcel_line = (char *)NULL;
 
66
static int   bcel_len = 0;
 
67
 
 
68
 
 
69
/* Required to get rid of that ugly ? default prompt! */
 
70
char *
 
71
null_prompt (EditLine *el)
 
72
{
 
73
  return "";
 
74
}
 
75
 
 
76
 
 
77
/* bcel_input puts upto MAX characters into BUF with the number put in
 
78
   BUF placed in *RESULT.  If the yy input file is the same as
 
79
   stdin, use editline.  Otherwise, just read it.
 
80
*/
 
81
 
 
82
static void
 
83
bcel_input (buf, result, max)
 
84
        char *buf;
 
85
        int  *result;
 
86
        int   max;
 
87
{
 
88
  if (!edit || yyin != stdin)
 
89
    {
 
90
      while ( (*result = read( fileno(yyin), buf, max )) < 0 )
 
91
        if (errno != EINTR)
 
92
          {
 
93
            yyerror( "read() in flex scanner failed" );
 
94
            exit (1);
 
95
          }
 
96
      return;
 
97
    }
 
98
 
 
99
  /* Do we need a new string? */
 
100
  if (bcel_len == 0)
 
101
    {
 
102
      bcel_line = el_gets(edit, &bcel_len);
 
103
      if (bcel_line == NULL) {
 
104
        /* end of file */
 
105
        *result = 0;
 
106
        bcel_len = 0;
 
107
        return;
 
108
      }
 
109
      if (bcel_len != 0)
 
110
        history (hist, &histev, H_ENTER, bcel_line); 
 
111
      fflush (stdout);
 
112
    }
 
113
 
 
114
  if (bcel_len <= max)
 
115
    {
 
116
      strncpy (buf, bcel_line, bcel_len);
 
117
      *result = bcel_len;
 
118
      bcel_len = 0;
 
119
    }
 
120
  else
 
121
    {
 
122
      strncpy (buf, bcel_line, max);
 
123
      *result = max;
 
124
      bcel_line += max;
 
125
      bcel_len -= max;
 
126
    }
 
127
}
 
128
#endif
 
129
 
 
130
#ifdef READLINE
 
131
/* Support for the readline and history libraries.  This allows
 
132
   nicer input on the interactive part of input. */
 
133
 
 
134
/* Have input call the following function. */
 
135
#undef  YY_INPUT
 
136
#define YY_INPUT(buf,result,max_size) \
 
137
                rl_input((char *)buf, &result, max_size)
 
138
 
 
139
/* Variables to help interface readline with bc. */
 
140
static char *rl_line = (char *)NULL;
 
141
static char *rl_start = (char *)NULL;
 
142
static int   rl_len = 0;
 
143
 
 
144
/* Definitions for readline access. */
 
145
extern FILE *rl_instream;
 
146
_PROTOTYPE(char *readline, (char *));
 
147
 
 
148
/* rl_input puts upto MAX characters into BUF with the number put in
 
149
   BUF placed in *RESULT.  If the yy input file is the same as
 
150
   rl_instream (stdin), use readline.  Otherwise, just read it.
 
151
*/
 
152
 
 
153
static void
 
154
rl_input (buf, result, max)
 
155
        char *buf;
 
156
        int  *result;
 
157
        int   max;
 
158
{
 
159
  if (yyin != rl_instream)
 
160
    {
 
161
      while ( (*result = read( fileno(yyin), buf, max )) < 0 )
 
162
        if (errno != EINTR)
 
163
          {
 
164
            yyerror( "read() in flex scanner failed" );
 
165
            exit (1);
 
166
          }
 
167
      return;
 
168
    }
 
169
 
 
170
  /* Do we need a new string? */
 
171
  if (rl_len == 0)
 
172
    {
 
173
      if (rl_start)
 
174
        free(rl_start);
 
175
      rl_start = readline ("");
 
176
      if (rl_start == NULL) {
 
177
        /* end of file */
 
178
        *result = 0;
 
179
        rl_len = 0;
 
180
        return;
 
181
      }
 
182
      rl_line = rl_start;
 
183
      rl_len = strlen (rl_line)+1;
 
184
      if (rl_len != 1)
 
185
        add_history (rl_line); 
 
186
      rl_line[rl_len-1] = '\n';
 
187
      fflush (stdout);
 
188
    }
 
189
 
 
190
  if (rl_len <= max)
 
191
    {
 
192
      strncpy (buf, rl_line, rl_len);
 
193
      *result = rl_len;
 
194
      rl_len = 0;
 
195
    }
 
196
  else
 
197
    {
 
198
      strncpy (buf, rl_line, max);
 
199
      *result = max;
 
200
      rl_line += max;
 
201
      rl_len -= max;
 
202
    }
 
203
}
 
204
#endif
 
205
 
 
206
#if !defined(READLINE) && !defined(LIBEDIT)
 
207
 
 
208
/* MINIX returns from read with < 0 if SIGINT is  encountered.
 
209
   In flex, we can redefine YY_INPUT to the following.  In lex, this
 
210
   does nothing! */
 
211
#undef  YY_INPUT
 
212
#define YY_INPUT(buf,result,max_size) \
 
213
        while ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \
 
214
            if (errno != EINTR) \
 
215
                YY_FATAL_ERROR( "read() in flex scanner failed" );
 
216
#endif
 
217
 
 
218
%}
 
219
DIGIT [0-9A-F]
 
220
LETTER [a-z]
 
221
%s slcomment
 
222
%%
 
223
"#"             {
 
224
                  if (!std_only)
 
225
                    BEGIN(slcomment);
 
226
                  else
 
227
                    yyerror ("illegal character: #");
 
228
                }
 
229
<slcomment>[^\n]* { BEGIN(INITIAL); }
 
230
<slcomment>"\n" { line_no++; BEGIN(INITIAL); return(ENDOFLINE); }
 
231
define return(Define);
 
232
break  return(Break);
 
233
quit   return(Quit);
 
234
length return(Length);
 
235
return return(Return);
 
236
for    return(For);
 
237
if     return(If);
 
238
while  return(While);
 
239
sqrt   return(Sqrt);
 
240
scale  return(Scale);
 
241
ibase  return(Ibase);
 
242
obase  return(Obase);
 
243
auto   return(Auto);
 
244
else   return(Else);
 
245
read   return(Read);
 
246
halt   return(Halt);
 
247
last   return(Last);
 
248
history {
 
249
#if defined(READLINE) || defined(LIBEDIT)
 
250
          return(HistoryVar);
 
251
#else
 
252
          yylval.s_value = strcopyof(yytext); return(NAME);
 
253
#endif
 
254
        }
 
255
 
 
256
warranty return(Warranty);
 
257
continue return(Continue);
 
258
print  return(Print);
 
259
limits return(Limits);
 
260
"." {
 
261
#ifdef DOT_IS_LAST
 
262
       return(Last);
 
263
#else
 
264
       yyerror ("illegal character: %s",yytext);
 
265
#endif
 
266
    }
 
267
"+"|"-"|";"|"("|")"|"{"|"}"|"["|"]"|","|"^" { yylval.c_value = yytext[0]; 
 
268
                                              return((int)yytext[0]); }
 
269
&& { return(AND); }
 
270
\|\| { return(OR); }
 
271
"!" { return(NOT); }
 
272
"*"|"/"|"%" { yylval.c_value = yytext[0]; return((int)yytext[0]); }
 
273
"="|\+=|-=|\*=|\/=|%=|\^=  { yylval.c_value = yytext[0]; return(ASSIGN_OP); }
 
274
=\+|=-|=\*|=\/|=%|=\^  { 
 
275
#ifdef OLD_EQ_OP
 
276
                         char warn_save;
 
277
                         warn_save = warn_not_std;
 
278
                         warn_not_std = TRUE;
 
279
                         warn ("Old fashioned =<op>");
 
280
                         warn_not_std = warn_save;
 
281
                         yylval.c_value = yytext[1];
 
282
#else
 
283
                         yylval.c_value = '=';
 
284
                         yyless (1);
 
285
#endif
 
286
                         return(ASSIGN_OP);
 
287
                       }
 
288
==|\<=|\>=|\!=|"<"|">" { yylval.s_value = strcopyof(yytext); return(REL_OP); }
 
289
\+\+|-- { yylval.c_value = yytext[0]; return(INCR_DECR); }
 
290
"\n" { line_no++; return(ENDOFLINE); }
 
291
\\\n {  line_no++;  /* ignore a "quoted" newline */ }
 
292
[ \t]+  { /* ignore spaces and tabs */ }
 
293
"/*"  {
 
294
        int c;
 
295
 
 
296
        for (;;)
 
297
          {
 
298
            while ( ((c=input()) != '*') && (c != EOF)) 
 
299
              /* eat it */
 
300
              if (c == '\n') line_no++;
 
301
            if (c == '*')
 
302
              {
 
303
                while ( (c=input()) == '*') /* eat it*/;
 
304
                if (c == '/') break; /* at end of comment */
 
305
                if (c == '\n') line_no++;
 
306
              }
 
307
            if (c == EOF)
 
308
              {
 
309
                fprintf (stderr,"EOF encountered in a comment.\n");
 
310
                break;
 
311
              }
 
312
          }
 
313
      }
 
314
[a-z][a-z0-9_]* { yylval.s_value = strcopyof(yytext); return(NAME); }
 
315
\"[^\"]*\"  {
 
316
              unsigned char *look;
 
317
              int count = 0;
 
318
              yylval.s_value = strcopyof(yytext);
 
319
              for (look = yytext; *look != 0; look++)
 
320
                {
 
321
                  if (*look == '\n') line_no++;
 
322
                  if (*look == '"')  count++;
 
323
                }
 
324
              if (count != 2) yyerror ("NUL character in string.");
 
325
              return(STRING);
 
326
            }
 
327
{DIGIT}({DIGIT}|\\\n)*("."({DIGIT}|\\\n)*)?|"."(\\\n)*{DIGIT}({DIGIT}|\\\n)* {
 
328
              unsigned char *src, *dst;
 
329
              int len;
 
330
              /* remove a trailing decimal point. */
 
331
              len = strlen(yytext);
 
332
              if (yytext[len-1] == '.')
 
333
                yytext[len-1] = 0;
 
334
              /* remove leading zeros. */
 
335
              src = yytext;
 
336
              dst = yytext;
 
337
              while (*src == '0') src++;
 
338
              if (*src == 0) src--;
 
339
              /* Copy strings removing the newlines. */
 
340
              while (*src != 0)
 
341
                {
 
342
                  if (*src == '\\')
 
343
                    {
 
344
                      src++; src++;
 
345
                      line_no++;
 
346
                    }
 
347
                  else
 
348
                    *dst++ = *src++;
 
349
                }
 
350
              *dst = 0;
 
351
              yylval.s_value = strcopyof(yytext); 
 
352
              return(NUMBER);
 
353
            }
 
354
.       {
 
355
          if (yytext[0] < ' ')
 
356
            yyerror ("illegal character: ^%c",yytext[0] + '@');
 
357
          else
 
358
            if (yytext[0] > '~')
 
359
              yyerror ("illegal character: \\%03o", (int) yytext[0]);
 
360
            else
 
361
              yyerror ("illegal character: %s",yytext);
 
362
        }
 
363
%%
 
364
 
 
365
 
 
366
 
 
367
/* This is the way to get multiple files input into lex. */
 
368
 
 
369
int
 
370
yywrap()
 
371
{
 
372
  if (!open_new_file ()) return (1);    /* EOF on standard in. */
 
373
  return (0);                           /* We have more input. */
 
374
}