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