2 /* $FreeBSD: src/contrib/bc/bc/scan.l,v 1.4.2.1 2001/03/04 09:34:54 kris Exp $ */
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;
147 _PROTOTYPE(char *readline, (char *));
149 /* rl_input puts upto MAX characters into BUF with the number put in
150 BUF placed in *RESULT. If the yy input file is the same as
151 rl_instream (stdin), use readline. Otherwise, just read it.
155 rl_input (buf, result, max)
160 if (yyin != rl_instream)
162 while ( (*result = read( fileno(yyin), buf, max )) < 0 )
165 yyerror( "read() in flex scanner failed" );
171 /* Do we need a new string? */
176 rl_start = readline ("");
177 if (rl_start == NULL) {
184 rl_len = strlen (rl_line)+1;
186 add_history (rl_line);
187 rl_line[rl_len-1] = '\n';
193 strncpy (buf, rl_line, rl_len);
199 strncpy (buf, rl_line, max);
207 #if !defined(READLINE) && !defined(LIBEDIT)
209 /* MINIX returns from read with < 0 if SIGINT is encountered.
210 In flex, we can redefine YY_INPUT to the following. In lex, this
213 #define YY_INPUT(buf,result,max_size) \
214 while ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \
215 if (errno != EINTR) \
216 YY_FATAL_ERROR( "read() in flex scanner failed" );
228 yyerror ("illegal character: #");
230 <slcomment>[^\n]* { BEGIN(INITIAL); }
231 <slcomment>"\n" { line_no++; BEGIN(INITIAL); return(ENDOFLINE); }
232 define return(Define);
235 length return(Length);
236 return return(Return);
250 #if defined(READLINE) || defined(LIBEDIT)
253 yylval.s_value = strcopyof(yytext); return(NAME);
257 warranty return(Warranty);
258 continue return(Continue);
260 limits return(Limits);
265 yyerror ("illegal character: %s",yytext);
268 "+"|"-"|";"|"("|")"|"{"|"}"|"["|"]"|","|"^" { yylval.c_value = yytext[0];
269 return((int)yytext[0]); }
273 "*"|"/"|"%" { yylval.c_value = yytext[0]; return((int)yytext[0]); }
274 "="|\+=|-=|\*=|\/=|%=|\^= { yylval.c_value = yytext[0]; return(ASSIGN_OP); }
275 =\+|=-|=\*|=\/|=%|=\^ {
278 warn_save = warn_not_std;
280 warn ("Old fashioned =<op>");
281 warn_not_std = warn_save;
282 yylval.c_value = yytext[1];
284 yylval.c_value = '=';
289 ==|\<=|\>=|\!=|"<"|">" { yylval.s_value = strcopyof(yytext); return(REL_OP); }
290 \+\+|-- { yylval.c_value = yytext[0]; return(INCR_DECR); }
291 "\n" { line_no++; return(ENDOFLINE); }
292 \\\n { line_no++; /* ignore a "quoted" newline */ }
293 [ \t]+ { /* ignore spaces and tabs */ }
299 while ( ((c=input()) != '*') && (c != EOF))
301 if (c == '\n') line_no++;
304 while ( (c=input()) == '*') /* eat it*/;
305 if (c == '/') break; /* at end of comment */
306 if (c == '\n') line_no++;
310 fprintf (stderr,"EOF encountered in a comment.\n");
315 [a-z][a-z0-9_]* { yylval.s_value = strcopyof(yytext); return(NAME); }
319 yylval.s_value = strcopyof(yytext);
320 for (look = yytext; *look != 0; look++)
322 if (*look == '\n') line_no++;
323 if (*look == '"') count++;
325 if (count != 2) yyerror ("NUL character in string.");
328 {DIGIT}({DIGIT}|\\\n)*("."({DIGIT}|\\\n)*)?|"."(\\\n)*{DIGIT}({DIGIT}|\\\n)* {
329 unsigned char *src, *dst;
331 /* remove a trailing decimal point. */
332 len = strlen(yytext);
333 if (yytext[len-1] == '.')
335 /* remove leading zeros. */
338 while (*src == '0') src++;
339 if (*src == 0) src--;
340 /* Copy strings removing the newlines. */
352 yylval.s_value = strcopyof(yytext);
357 yyerror ("illegal character: ^%c",yytext[0] + '@');
360 yyerror ("illegal character: \\%03o", (int) yytext[0]);
362 yyerror ("illegal character: %s",yytext);
368 /* This is the way to get multiple files input into lex. */
373 if (!open_new_file ()) return (1); /* EOF on standard in. */
374 return (0); /* We have more input. */