3 /* scan.l: the (f)lex description file for the scanner. */
5 /* This file is part of GNU bc.
6 Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License , or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING. If not, write to
20 The Free Software Foundation, Inc.
21 59 Temple Place, Suite 330
24 You may contact the author by:
25 e-mail: philnelson@acm.org
26 us-mail: Philip A. Nelson
27 Computer Science Department, 9062
28 Western Washington University
29 Bellingham, WA 98226-9062
31 *************************************************************************/
39 /* Using flex, we can ask for a smaller input buffer. With lex, this
43 #undef YY_READ_BUF_SIZE
44 #define YY_READ_BUF_SIZE 512
47 /* Force . as last for now. */
50 /* We want to define our own yywrap. */
52 _PROTOTYPE(int yywrap, (void));
55 /* Support for the BSD libedit with history for
56 nicer input on the interactive part of input. */
60 /* Have input call the following function. */
62 #define YY_INPUT(buf,result,max_size) \
63 bcel_input((char *)buf, &result, max_size)
65 /* Variables to help interface editline with bc. */
66 static const char *bcel_line = (char *)NULL;
67 static int bcel_len = 0;
70 /* Required to get rid of that ugly ? default prompt! */
72 null_prompt (EditLine *el)
78 /* bcel_input puts upto MAX characters into BUF with the number put in
79 BUF placed in *RESULT. If the yy input file is the same as
80 stdin, use editline. Otherwise, just read it.
84 bcel_input (buf, result, max)
89 if (!edit || yyin != stdin)
91 while ( (*result = read( fileno(yyin), buf, max )) < 0 )
94 yyerror( "read() in flex scanner failed" );
100 /* Do we need a new string? */
103 bcel_line = el_gets(edit, &bcel_len);
104 if (bcel_line == NULL) {
111 history (hist, &histev, H_ENTER, bcel_line);
117 strncpy (buf, bcel_line, bcel_len);
123 strncpy (buf, bcel_line, max);
132 /* Support for the readline and history libraries. This allows
133 nicer input on the interactive part of input. */
135 /* Have input call the following function. */
137 #define YY_INPUT(buf,result,max_size) \
138 rl_input((char *)buf, &result, max_size)
140 /* Variables to help interface readline with bc. */
141 static char *rl_line = (char *)NULL;
142 static char *rl_start = (char *)NULL;
143 static int rl_len = 0;
145 /* Definitions for readline access. */
146 extern FILE *rl_instream;
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. */