2
/* scan.l: the (f)lex description file for the scanner. */
4
/* This file is part of GNU bc.
5
Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
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.
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.
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
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
30
*************************************************************************/
38
/* Using flex, we can ask for a smaller input buffer. With lex, this
42
#undef YY_READ_BUF_SIZE
43
#define YY_READ_BUF_SIZE 512
46
/* Force . as last for now. */
49
/* We want to define our own yywrap. */
51
_PROTOTYPE(int yywrap, (void));
54
/* Support for the BSD libedit with history for
55
nicer input on the interactive part of input. */
59
/* Have input call the following function. */
61
#define YY_INPUT(buf,result,max_size) \
62
bcel_input((char *)buf, &result, max_size)
64
/* Variables to help interface editline with bc. */
65
static const char *bcel_line = (char *)NULL;
66
static int bcel_len = 0;
69
/* Required to get rid of that ugly ? default prompt! */
71
null_prompt (EditLine *el)
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.
83
bcel_input (buf, result, max)
88
if (!edit || yyin != stdin)
90
while ( (*result = read( fileno(yyin), buf, max )) < 0 )
93
yyerror( "read() in flex scanner failed" );
99
/* Do we need a new string? */
102
bcel_line = el_gets(edit, &bcel_len);
103
if (bcel_line == NULL) {
110
history (hist, &histev, H_ENTER, bcel_line);
116
strncpy (buf, bcel_line, bcel_len);
122
strncpy (buf, bcel_line, max);
131
/* Support for the readline and history libraries. This allows
132
nicer input on the interactive part of input. */
134
/* Have input call the following function. */
136
#define YY_INPUT(buf,result,max_size) \
137
rl_input((char *)buf, &result, max_size)
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;
144
/* Definitions for readline access. */
145
extern FILE *rl_instream;
146
_PROTOTYPE(char *readline, (char *));
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.
154
rl_input (buf, result, max)
159
if (yyin != rl_instream)
161
while ( (*result = read( fileno(yyin), buf, max )) < 0 )
164
yyerror( "read() in flex scanner failed" );
170
/* Do we need a new string? */
175
rl_start = readline ("");
176
if (rl_start == NULL) {
183
rl_len = strlen (rl_line)+1;
185
add_history (rl_line);
186
rl_line[rl_len-1] = '\n';
192
strncpy (buf, rl_line, rl_len);
198
strncpy (buf, rl_line, max);
206
#if !defined(READLINE) && !defined(LIBEDIT)
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
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" );
227
yyerror ("illegal character: #");
229
<slcomment>[^\n]* { BEGIN(INITIAL); }
230
<slcomment>"\n" { line_no++; BEGIN(INITIAL); return(ENDOFLINE); }
231
define return(Define);
234
length return(Length);
235
return return(Return);
249
#if defined(READLINE) || defined(LIBEDIT)
252
yylval.s_value = strcopyof(yytext); return(NAME);
256
warranty return(Warranty);
257
continue return(Continue);
259
limits return(Limits);
264
yyerror ("illegal character: %s",yytext);
267
"+"|"-"|";"|"("|")"|"{"|"}"|"["|"]"|","|"^" { yylval.c_value = yytext[0];
268
return((int)yytext[0]); }
272
"*"|"/"|"%" { yylval.c_value = yytext[0]; return((int)yytext[0]); }
273
"="|\+=|-=|\*=|\/=|%=|\^= { yylval.c_value = yytext[0]; return(ASSIGN_OP); }
274
=\+|=-|=\*|=\/|=%|=\^ {
277
warn_save = warn_not_std;
279
warn ("Old fashioned =<op>");
280
warn_not_std = warn_save;
281
yylval.c_value = yytext[1];
283
yylval.c_value = '=';
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 */ }
298
while ( ((c=input()) != '*') && (c != EOF))
300
if (c == '\n') line_no++;
303
while ( (c=input()) == '*') /* eat it*/;
304
if (c == '/') break; /* at end of comment */
305
if (c == '\n') line_no++;
309
fprintf (stderr,"EOF encountered in a comment.\n");
314
[a-z][a-z0-9_]* { yylval.s_value = strcopyof(yytext); return(NAME); }
318
yylval.s_value = strcopyof(yytext);
319
for (look = yytext; *look != 0; look++)
321
if (*look == '\n') line_no++;
322
if (*look == '"') count++;
324
if (count != 2) yyerror ("NUL character in string.");
327
{DIGIT}({DIGIT}|\\\n)*("."({DIGIT}|\\\n)*)?|"."(\\\n)*{DIGIT}({DIGIT}|\\\n)* {
328
unsigned char *src, *dst;
330
/* remove a trailing decimal point. */
331
len = strlen(yytext);
332
if (yytext[len-1] == '.')
334
/* remove leading zeros. */
337
while (*src == '0') src++;
338
if (*src == 0) src--;
339
/* Copy strings removing the newlines. */
351
yylval.s_value = strcopyof(yytext);
356
yyerror ("illegal character: ^%c",yytext[0] + '@');
359
yyerror ("illegal character: \\%03o", (int) yytext[0]);
361
yyerror ("illegal character: %s",yytext);
367
/* This is the way to get multiple files input into lex. */
372
if (!open_new_file ()) return (1); /* EOF on standard in. */
373
return (0); /* We have more input. */