]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.bin/bc/scan.l
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / usr.bin / bc / scan.l
1 %{
2 /*      $OpenBSD: scan.l,v 1.23 2009/10/27 23:59:36 deraadt Exp $       */
3
4 /*
5  * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19
20 #include <sys/cdefs.h>
21 __FBSDID("$FreeBSD$");
22
23 #include <err.h>
24 #include <errno.h>
25 #include <histedit.h>
26 #include <stdbool.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 #include "extern.h"
31 #include "bc.h"
32 #include "pathnames.h"
33
34 int              lineno;
35
36 bool             interactive;
37 HistEvent        he;
38 EditLine        *el;
39 History         *hist;
40
41 static char     *strbuf = NULL;
42 static size_t    strbuf_sz = 1;
43 static bool      dot_seen;
44
45 static void      init_strbuf(void);
46 static void      add_str(const char *);
47 static int       bc_yyinput(char *, int);
48
49 #define YY_DECL int yylex(void)
50 #define YY_NO_INPUT
51 #undef YY_INPUT
52 #define YY_INPUT(buf,retval,max) \
53         (retval = bc_yyinput(buf, max))
54 %}
55
56 %option always-interactive
57
58 DIGIT           [0-9A-F]
59 ALPHA           [a-z_]
60 ALPHANUM        [a-z_0-9]
61
62 %x              comment string number
63
64 %%
65
66 "/*"            BEGIN(comment);
67 <comment>{
68         "*/"    BEGIN(INITIAL);
69         \n      lineno++;
70         \*      ;
71         [^*\n]+ ;
72         <<EOF>> fatal("end of file in comment");
73 }
74
75 \"              BEGIN(string); init_strbuf();
76 <string>{
77         [^"\n\\\[\]]+   add_str(yytext);
78         \[      add_str("\\[");
79         \]      add_str("\\]");
80         \\      add_str("\\\\");
81         \n      add_str("\n"); lineno++;
82         \"      BEGIN(INITIAL); yylval.str = strbuf; return STRING;
83         <<EOF>> fatal("end of file in string");
84 }
85
86 {DIGIT}+        {
87                         BEGIN(number);
88                         dot_seen = false;
89                         init_strbuf();
90                         add_str(yytext);
91                 }
92 \.              {
93                         BEGIN(number);
94                         dot_seen = true;
95                         init_strbuf();
96                         add_str(".");
97                 }
98 <number>{
99         {DIGIT}+        add_str(yytext);
100         \.      {
101                         if (dot_seen) {
102                                 BEGIN(INITIAL);
103                                 yylval.str = strbuf;
104                                 unput('.');
105                                 return (NUMBER);
106                         } else {
107                                 dot_seen = true;
108                                 add_str(".");
109                         }
110                 }
111         \\\n[ \t]*      lineno++;
112         [^0-9A-F\.]     {
113                         BEGIN(INITIAL);
114                         unput(yytext[0]);
115                         if (strcmp(strbuf, ".") == 0)
116                                 return (DOT);
117                         else {
118                                 yylval.str = strbuf;
119                                 return (NUMBER);
120                         }
121                 }
122 }
123
124 "auto"          return (AUTO);
125 "break"         return (BREAK);
126 "continue"      return (CONTINUE);
127 "define"        return (DEFINE);
128 "else"          return (ELSE);
129 "ibase"         return (IBASE);
130 "if"            return (IF);
131 "last"          return (DOT);
132 "for"           return (FOR);
133 "length"        return (LENGTH);
134 "obase"         return (OBASE);
135 "print"         return (PRINT);
136 "quit"          return (QUIT);
137 "return"        return (RETURN);
138 "scale"         return (SCALE);
139 "sqrt"          return (SQRT);
140 "while"         return (WHILE);
141
142 "^"             return (EXPONENT);
143 "*"             return (MULTIPLY);
144 "/"             return (DIVIDE);
145 "%"             return (REMAINDER);
146
147 "!"             return (BOOL_NOT);
148 "&&"            return (BOOL_AND);
149 "||"            return (BOOL_OR);
150
151 "+"             return (PLUS);
152 "-"             return (MINUS);
153
154 "++"            return (INCR);
155 "--"            return (DECR);
156
157 "="             yylval.str = ""; return (ASSIGN_OP);
158 "+="            yylval.str = "+"; return (ASSIGN_OP);
159 "-="            yylval.str = "-"; return (ASSIGN_OP);
160 "*="            yylval.str = "*"; return (ASSIGN_OP);
161 "/="            yylval.str = "/"; return (ASSIGN_OP);
162 "%="            yylval.str = "%"; return (ASSIGN_OP);
163 "^="            yylval.str = "^"; return (ASSIGN_OP);
164
165 "=="            return (EQUALS);
166 "<="            return (LESS_EQ);
167 ">="            return (GREATER_EQ);
168 "!="            return (UNEQUALS);
169 "<"             return (LESS);
170 ">"             return (GREATER);
171
172 ","             return (COMMA);
173 ";"             return (SEMICOLON);
174
175 "("             return (LPAR);
176 ")"             return (RPAR);
177
178 "["             return (LBRACKET);
179 "]"             return (RBRACKET);
180
181 "{"             return (LBRACE);
182 "}"             return (RBRACE);
183
184 {ALPHA}{ALPHANUM}* {
185                         /* alloc an extra byte for the type marker */
186                         char *p = malloc(yyleng + 2);
187                         if (p == NULL)
188                                 err(1, NULL);
189                         strlcpy(p, yytext, yyleng + 1);
190                         yylval.astr = p;
191                         return (LETTER);
192                 }
193
194 \\\n            lineno++;
195 \n              lineno++; return (NEWLINE);
196
197 #[^\n]*         ;
198 [ \t]           ;
199 <<EOF>>         return (QUIT);
200 .               yyerror("illegal character");
201
202 %%
203
204 static void
205 init_strbuf(void)
206 {
207
208         if (strbuf == NULL) {
209                 strbuf = malloc(strbuf_sz);
210                 if (strbuf == NULL)
211                         err(1, NULL);
212         }
213         strbuf[0] = '\0';
214 }
215
216 static void
217 add_str(const char *str)
218 {
219         size_t arglen;
220
221         arglen = strlen(str);
222
223         if (strlen(strbuf) + arglen + 1 > strbuf_sz) {
224                 size_t   newsize;
225                 char    *p;
226
227                 newsize = strbuf_sz + arglen + 1;
228                 p = realloc(strbuf, newsize);
229                 if (p == NULL) {
230                         free(strbuf);
231                         err(1, NULL);
232                 }
233                 strbuf_sz = newsize;
234                 strbuf = p;
235         }
236         strlcat(strbuf, str, strbuf_sz);
237 }
238
239 int
240 yywrap(void)
241 {
242         static YY_BUFFER_STATE buf;
243         static int state;
244
245         if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) {
246                 filename = sargv[fileindex++];
247                 yyin = fopen(filename, "r");
248                 lineno = 1;
249                 if (yyin == NULL)
250                         err(1, "cannot open %s", filename);
251                 return (0);
252         }
253         if (state == 0 && cmdexpr[0] != '\0') {
254                 buf = yy_scan_string(cmdexpr);
255                 state++;
256                 lineno = 1;
257                 filename = "command line";
258                 return (0);
259         } else if (state == 1) {
260                 yy_delete_buffer(buf);
261                 free(cmdexpr);
262                 state++;
263         }
264         if (yyin != NULL && yyin != stdin)
265                 fclose(yyin);
266         if (fileindex < sargc) {
267                 filename = sargv[fileindex++];
268                 yyin = fopen(filename, "r");
269                 lineno = 1;
270                 if (yyin == NULL)
271                         err(1, "cannot open %s", filename);
272                 return (0);
273         } else if (fileindex == sargc) {
274                 fileindex++;
275                 yyin = stdin;
276                 lineno = 1;
277                 filename = "stdin";
278                 return (0);
279         }
280         return (1);
281 }
282
283 static int
284 bc_yyinput(char *buf, int maxlen)
285 {
286         int num;
287         if (yyin == stdin && interactive) {
288                 const char *bp;
289
290                 if ((bp = el_gets(el, &num)) == NULL || num == 0)
291                         return (0);
292                 if (num > maxlen) {
293                         el_push(el, (char *)(uintptr_t)(bp) + maxlen);
294                         num = maxlen;
295                 }
296                 memcpy(buf, bp, num);
297                 history(hist, &he, H_ENTER, bp);
298         } else {
299                 int c = '*';
300                 for (num = 0; num < maxlen &&
301                     (c = getc(yyin)) != EOF && c != '\n'; ++num)
302                         buf[num] = (char) c;
303                 if (c == '\n')
304                         buf[num++] = (char) c;
305                 if (c == EOF && ferror(yyin))
306                         YY_FATAL_ERROR( "input in flex scanner failed" );
307         }
308         return (num);
309 }
310