]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/bc/scan.l
Merge ^vendor/binutils/dist@214082 into contrib/binutils.
[FreeBSD/FreeBSD.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 #undef YY_INPUT
50 #define YY_INPUT(buf,retval,max) \
51         (retval = bc_yyinput(buf, max))
52 %}
53
54 %option always-interactive
55
56 DIGIT           [0-9A-F]
57 ALPHA           [a-z_]
58 ALPHANUM        [a-z_0-9]
59
60 %x              comment string number
61
62 %%
63
64 "/*"            BEGIN(comment);
65 <comment>{
66         "*/"    BEGIN(INITIAL);
67         \n      lineno++;
68         \*      ;
69         [^*\n]+ ;
70         <<EOF>> fatal("end of file in comment");
71 }
72
73 \"              BEGIN(string); init_strbuf();
74 <string>{
75         [^"\n\\\[\]]+   add_str(yytext);
76         \[      add_str("\\[");
77         \]      add_str("\\]");
78         \\      add_str("\\\\");
79         \n      add_str("\n"); lineno++;
80         \"      BEGIN(INITIAL); yylval.str = strbuf; return STRING;
81         <<EOF>> fatal("end of file in string");
82 }
83
84 {DIGIT}+        {
85                         BEGIN(number);
86                         dot_seen = false;
87                         init_strbuf();
88                         add_str(yytext);
89                 }
90 \.              {
91                         BEGIN(number);
92                         dot_seen = true;
93                         init_strbuf();
94                         add_str(".");
95                 }
96 <number>{
97         {DIGIT}+        add_str(yytext);
98         \.      {
99                         if (dot_seen) {
100                                 BEGIN(INITIAL);
101                                 yylval.str = strbuf;
102                                 unput('.');
103                                 return (NUMBER);
104                         } else {
105                                 dot_seen = true;
106                                 add_str(".");
107                         }
108                 }
109         \\\n[ \t]*      lineno++;
110         [^0-9A-F\.]     {
111                         BEGIN(INITIAL);
112                         unput(yytext[0]);
113                         if (strcmp(strbuf, ".") == 0)
114                                 return (DOT);
115                         else {
116                                 yylval.str = strbuf;
117                                 return (NUMBER);
118                         }
119                 }
120 }
121
122 "auto"          return (AUTO);
123 "break"         return (BREAK);
124 "continue"      return (CONTINUE);
125 "define"        return (DEFINE);
126 "else"          return (ELSE);
127 "ibase"         return (IBASE);
128 "if"            return (IF);
129 "last"          return (DOT);
130 "for"           return (FOR);
131 "length"        return (LENGTH);
132 "obase"         return (OBASE);
133 "print"         return (PRINT);
134 "quit"          return (QUIT);
135 "return"        return (RETURN);
136 "scale"         return (SCALE);
137 "sqrt"          return (SQRT);
138 "while"         return (WHILE);
139
140 "^"             return (EXPONENT);
141 "*"             return (MULTIPLY);
142 "/"             return (DIVIDE);
143 "%"             return (REMAINDER);
144
145 "!"             return (BOOL_NOT);
146 "&&"            return (BOOL_AND);
147 "||"            return (BOOL_OR);
148
149 "+"             return (PLUS);
150 "-"             return (MINUS);
151
152 "++"            return (INCR);
153 "--"            return (DECR);
154
155 "="             yylval.str = ""; return (ASSIGN_OP);
156 "+="            yylval.str = "+"; return (ASSIGN_OP);
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
163 "=="            return (EQUALS);
164 "<="            return (LESS_EQ);
165 ">="            return (GREATER_EQ);
166 "!="            return (UNEQUALS);
167 "<"             return (LESS);
168 ">"             return (GREATER);
169
170 ","             return (COMMA);
171 ";"             return (SEMICOLON);
172
173 "("             return (LPAR);
174 ")"             return (RPAR);
175
176 "["             return (LBRACKET);
177 "]"             return (RBRACKET);
178
179 "{"             return (LBRACE);
180 "}"             return (RBRACE);
181
182 {ALPHA}{ALPHANUM}* {
183                         /* alloc an extra byte for the type marker */
184                         char *p = malloc(yyleng + 2);
185                         if (p == NULL)
186                                 err(1, NULL);
187                         strlcpy(p, yytext, yyleng + 1);
188                         yylval.astr = p;
189                         return (LETTER);
190                 }
191
192 \\\n            lineno++;
193 \n              lineno++; return (NEWLINE);
194
195 #[^\n]*         ;
196 [ \t]           ;
197 <<EOF>>         return (QUIT);
198 .               yyerror("illegal character");
199
200 %%
201
202 static void
203 init_strbuf(void)
204 {
205
206         if (strbuf == NULL) {
207                 strbuf = malloc(strbuf_sz);
208                 if (strbuf == NULL)
209                         err(1, NULL);
210         }
211         strbuf[0] = '\0';
212 }
213
214 static void
215 add_str(const char *str)
216 {
217         size_t arglen;
218
219         arglen = strlen(str);
220
221         if (strlen(strbuf) + arglen + 1 > strbuf_sz) {
222                 size_t   newsize;
223                 char    *p;
224
225                 newsize = strbuf_sz + arglen + 1;
226                 p = realloc(strbuf, newsize);
227                 if (p == NULL) {
228                         free(strbuf);
229                         err(1, NULL);
230                 }
231                 strbuf_sz = newsize;
232                 strbuf = p;
233         }
234         strlcat(strbuf, str, strbuf_sz);
235 }
236
237 int
238 yywrap(void)
239 {
240         static YY_BUFFER_STATE buf;
241         static int state;
242
243         if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) {
244                 filename = sargv[fileindex++];
245                 yyin = fopen(filename, "r");
246                 lineno = 1;
247                 if (yyin == NULL)
248                         err(1, "cannot open %s", filename);
249                 return (0);
250         }
251         if (state == 0 && cmdexpr[0] != '\0') {
252                 buf = yy_scan_string(cmdexpr);
253                 state++;
254                 lineno = 1;
255                 filename = "command line";
256                 return (0);
257         } else if (state == 1) {
258                 yy_delete_buffer(buf);
259                 free(cmdexpr);
260                 state++;
261         }
262         if (yyin != NULL && yyin != stdin)
263                 fclose(yyin);
264         if (fileindex < sargc) {
265                 filename = sargv[fileindex++];
266                 yyin = fopen(filename, "r");
267                 lineno = 1;
268                 if (yyin == NULL)
269                         err(1, "cannot open %s", filename);
270                 return (0);
271         } else if (fileindex == sargc) {
272                 fileindex++;
273                 yyin = stdin;
274                 lineno = 1;
275                 filename = "stdin";
276                 return (0);
277         }
278         return (1);
279 }
280
281 static int
282 bc_yyinput(char *buf, int maxlen)
283 {
284         int num;
285         if (yyin == stdin && interactive) {
286                 const char *bp;
287
288                 if ((bp = el_gets(el, &num)) == NULL || num == 0)
289                         return (0);
290                 if (num > maxlen) {
291                         el_push(el, (char *)(uintptr_t)(bp) + maxlen);
292                         num = maxlen;
293                 }
294                 memcpy(buf, bp, num);
295                 history(hist, &he, H_ENTER, bp);
296         } else {
297                 int c = '*';
298                 for (num = 0; num < maxlen &&
299                     (c = getc(yyin)) != EOF && c != '\n'; ++num)
300                         buf[num] = (char) c;
301                 if (c == '\n')
302                         buf[num++] = (char) c;
303                 if (c == EOF && ferror(yyin))
304                         YY_FATAL_ERROR( "input in flex scanner failed" );
305         }
306         return (num);
307 }
308