52e585d9946f6b40aa94194ff67b410dd92b8ca6
[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 int             lineno;
35 bool            interactive;
36
37 static char     *strbuf = NULL;
38 static size_t   strbuf_sz = 1;
39 static bool     dot_seen;
40
41 static void     init_strbuf(void);
42 static void     add_str(const char *);
43
44 %}
45
46 %option always-interactive
47
48 DIGIT           [0-9A-F]
49 ALPHA           [a-z_]
50 ALPHANUM        [a-z_0-9]
51
52 %x              comment string number
53
54 %%
55
56 "/*"            BEGIN(comment);
57 <comment>{
58         "*/"    BEGIN(INITIAL);
59         \n      lineno++;
60         \*      ;
61         [^*\n]+ ;
62         <<EOF>> fatal("end of file in comment");
63 }
64
65 \"              BEGIN(string); init_strbuf();
66 <string>{
67         [^"\n\\\[\]]+   add_str(yytext);
68         \[      add_str("\\[");
69         \]      add_str("\\]");
70         \\      add_str("\\\\");
71         \n      add_str("\n"); lineno++;
72         \"      BEGIN(INITIAL); yylval.str = strbuf; return STRING;
73         <<EOF>> fatal("end of file in string");
74 }
75
76 {DIGIT}+        {
77                         BEGIN(number);
78                         dot_seen = false;
79                         init_strbuf();
80                         add_str(yytext);
81                 }
82 \.              {
83                         BEGIN(number);
84                         dot_seen = true;
85                         init_strbuf();
86                         add_str(".");
87                 }
88 <number>{
89         {DIGIT}+        add_str(yytext);
90         \.      {
91                         if (dot_seen) {
92                                 BEGIN(INITIAL);
93                                 yylval.str = strbuf;
94                                 unput('.');
95                                 return NUMBER;
96                         } else {
97                                 dot_seen = true;
98                                 add_str(".");
99                         }
100                 }
101         \\\n[ \t]*      lineno++;
102         [^0-9A-F\.]     {
103                         BEGIN(INITIAL);
104                         unput(yytext[0]);
105                         if (strcmp(strbuf, ".") == 0)
106                                 return DOT;
107                         else {
108                                 yylval.str = strbuf;
109                                 return NUMBER;
110                         }
111                 }
112 }
113
114 "auto"          return AUTO;
115 "break"         return BREAK;
116 "continue"      return CONTINUE;
117 "define"        return DEFINE;
118 "else"          return ELSE;
119 "ibase"         return IBASE;
120 "if"            return IF;
121 "last"          return DOT;
122 "for"           return FOR;
123 "length"        return LENGTH;
124 "obase"         return OBASE;
125 "print"         return PRINT;
126 "quit"          return QUIT;
127 "return"        return RETURN;
128 "scale"         return SCALE;
129 "sqrt"          return SQRT;
130 "while"         return WHILE;
131
132 "^"             return EXPONENT;
133 "*"             return MULTIPLY;
134 "/"             return DIVIDE;
135 "%"             return REMAINDER;
136
137 "!"             return BOOL_NOT;
138 "&&"            return BOOL_AND;
139 "||"            return BOOL_OR;
140
141 "+"             return PLUS;
142 "-"             return MINUS;
143
144 "++"            return INCR;
145 "--"            return DECR;
146
147 "="             yylval.str = ""; return ASSIGN_OP;
148 "+="            yylval.str = "+"; return ASSIGN_OP;
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
155 "=="            return EQUALS;
156 "<="            return LESS_EQ;
157 ">="            return GREATER_EQ;
158 "!="            return UNEQUALS;
159 "<"             return LESS;
160 ">"             return GREATER;
161
162 ","             return COMMA;
163 ";"             return SEMICOLON;
164
165 "("             return LPAR;
166 ")"             return RPAR;
167
168 "["             return LBRACKET;
169 "]"             return RBRACKET;
170
171 "{"             return LBRACE;
172 "}"             return RBRACE;
173
174 {ALPHA}{ALPHANUM}* {
175                         /* alloc an extra byte for the type marker */
176                         char *p = malloc(yyleng + 2);
177                         if (p == NULL)
178                                 err(1, NULL);
179                         strlcpy(p, yytext, yyleng + 1);
180                         yylval.astr = p;
181                         return LETTER;
182                 }
183
184 \\\n            lineno++;
185 \n              lineno++; return NEWLINE;
186
187 #[^\n]*         ;
188 [ \t]           ;
189 <<EOF>>         return QUIT;
190 .               yyerror("illegal character");
191
192 %%
193
194 static void
195 init_strbuf(void)
196 {
197         if (strbuf == NULL) {
198                 strbuf = malloc(strbuf_sz);
199                 if (strbuf == NULL)
200                         err(1, NULL);
201         }
202         strbuf[0] = '\0';
203 }
204
205 static void
206 add_str(const char *str)
207 {
208         size_t arglen;
209
210         arglen = strlen(str);
211
212         if (strlen(strbuf) + arglen + 1 > strbuf_sz) {
213                 size_t newsize;
214                 char *p;
215
216                 newsize = strbuf_sz + arglen + 1;
217                 p = realloc(strbuf, newsize);
218                 if (p == NULL) {
219                         free(strbuf);
220                         err(1, NULL);
221                 }
222                 strbuf_sz = newsize;
223                 strbuf = p;
224         }
225         strlcat(strbuf, str, strbuf_sz);
226 }
227
228 /* ARGSUSED */
229 void
230 abort_line(int sig)
231 {
232         const char str[] = "[\n]P\n";
233         int save_errno;
234
235         save_errno = errno;
236         YY_FLUSH_BUFFER;        /* XXX signal race? */
237         write(STDOUT_FILENO, str, sizeof(str) - 1);
238         errno = save_errno;
239 }
240
241 int
242 yywrap(void)
243 {
244         static int state;
245         static YY_BUFFER_STATE buf;
246
247         if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) {
248                 filename = sargv[fileindex++];
249                 yyin = fopen(filename, "r");
250                 lineno = 1;
251                 if (yyin == NULL)
252                         err(1, "cannot open %s", filename);
253                 return (0);
254         }
255         if (state == 0 && cmdexpr[0] != '\0') {
256                 buf = yy_scan_string(cmdexpr);
257                 state++;
258                 lineno = 1;
259                 filename = "command line";
260                 return (0);
261         } else if (state == 1) {
262                 yy_delete_buffer(buf);
263                 free(cmdexpr);
264                 state++;
265         }
266         if (yyin != NULL && yyin != stdin)
267                 fclose(yyin);
268         if (fileindex < sargc) {
269                 filename = sargv[fileindex++];
270                 yyin = fopen(filename, "r");
271                 lineno = 1;
272                 if (yyin == NULL)
273                         err(1, "cannot open %s", filename);
274                 return (0);
275         } else if (fileindex == sargc) {
276                 fileindex++;
277                 yyin = stdin;
278                 if (interactive)
279                         signal(SIGINT, abort_line);
280                 lineno = 1;
281                 filename = "stdin";
282                 return (0);
283         }
284         return (1);
285 }