xref: /dragonfly/usr.bin/bc/scan.l (revision 49781055)
1 %{
2 /*
3  * $OpenBSD: scan.l,v 1.18 2005/04/13 06:36:03 otto Exp $
4  * $DragonFly: src/usr.bin/bc/scan.l,v 1.2 2005/04/21 18:50:22 swildner 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 
36 static char	*strbuf = NULL;
37 static size_t	strbuf_sz = 1;
38 static bool	dot_seen;
39 static volatile sig_atomic_t	interactive = 0;
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 void
229 abort_line(int sig)
230 {
231 	const char str[] = "[\n]P\n";
232 	int save_errno;
233 
234 	if (interactive) {
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 
242 int
243 yywrap(void)
244 {
245 	static int state;
246 	static YY_BUFFER_STATE buf;
247 
248 	if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) {
249 		filename = sargv[fileindex++];
250 		yyin = fopen(filename, "r");
251 		lineno = 1;
252 		if (yyin == NULL)
253 			err(1, "cannot open %s", filename);
254 		return (0);
255 	}
256 	if (state == 0 && cmdexpr[0] != '\0') {
257 		buf = yy_scan_string(cmdexpr);
258 		state++;
259 		lineno = 1;
260 		filename = "command line";
261 		return (0);
262 	} else if (state == 1) {
263 		yy_delete_buffer(buf);
264 		free(cmdexpr);
265 		state++;
266 	}
267 	if (fileindex < sargc) {
268 		filename = sargv[fileindex++];
269 		yyin = fopen(filename, "r");
270 		lineno = 1;
271 		if (yyin == NULL)
272 			err(1, "cannot open %s", filename);
273 		return (0);
274 	} else if (fileindex == sargc) {
275 		fileindex++;
276 		yyin = stdin;
277 		interactive = isatty(fileno(yyin));
278 		lineno = 1;
279 		filename = "stdin";
280 		return (0);
281 	}
282 	return (1);
283 }
284