xref: /dragonfly/usr.bin/bc/scan.l (revision 5153f92b)
1 %{
2 /*
3  * $OpenBSD: scan.l,v 1.14 2003/12/02 09:00:07 otto Exp $
4  * $DragonFly: src/usr.bin/bc/scan.l,v 1.1 2004/09/20 04:20:34 dillon 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 <stdbool.h>
25 #include <string.h>
26 
27 #include "extern.h"
28 #include "y.tab.h"
29 
30 int		lineno;
31 
32 static char	*strbuf = NULL;
33 static size_t	strbuf_sz = 1;
34 static bool	dot_seen;
35 
36 static void	init_strbuf(void);
37 static void	add_str(const char *);
38 
39 %}
40 
41 DIGIT		[0-9A-F]
42 ALPHA		[a-z_]
43 ALPHANUM	[a-z_0-9]
44 
45 %x		comment string number
46 
47 %%
48 
49 "/*"		BEGIN(comment);
50 <comment>{
51 	"*/"	BEGIN(INITIAL);
52 	\n	lineno++;
53 	\*	;
54 	[^*\n]+	;
55 	<<EOF>>	fatal("end of file in comment");
56 }
57 
58 \"		BEGIN(string); init_strbuf();
59 <string>{
60 	[^"\n\\\[\]]+	add_str(yytext);
61 	\[	add_str("\\[");
62 	\]	add_str("\\]");
63 	\\	add_str("\\\\");
64 	\n	add_str("\n"); lineno++;
65 	\"	BEGIN(INITIAL); yylval.str = strbuf; return STRING;
66 	<<EOF>>	fatal("end of file in string");
67 }
68 
69 {DIGIT}+	{
70 			BEGIN(number);
71 			dot_seen = false;
72 			init_strbuf();
73 			add_str(yytext);
74 		}
75 \.		{
76 			BEGIN(number);
77 			dot_seen = true;
78 			init_strbuf();
79 			add_str(".");
80 		}
81 <number>{
82 	{DIGIT}+	add_str(yytext);
83 	\.	{
84 			if (dot_seen) {
85 				BEGIN(INITIAL);
86 				yylval.str = strbuf;
87 				unput('.');
88 				return NUMBER;
89 			} else {
90 				dot_seen = true;
91 				add_str(".");
92 			}
93 		}
94 	\\\n[ \t]*	lineno++;
95 	[^0-9A-F\.]	{
96 			BEGIN(INITIAL);
97 			unput(yytext[0]);
98 			if (strcmp(strbuf, ".") == 0)
99 				return DOT;
100 			else {
101 				yylval.str = strbuf;
102 				return NUMBER;
103 			}
104 		}
105 }
106 
107 "auto"		return AUTO;
108 "break"		return BREAK;
109 "continue"	return CONTINUE;
110 "define"	return DEFINE;
111 "else"		return ELSE;
112 "ibase"		return IBASE;
113 "if"		return IF;
114 "last"		return DOT;
115 "for"		return FOR;
116 "length"	return LENGTH;
117 "obase"		return OBASE;
118 "print"		return PRINT;
119 "quit"		return QUIT;
120 "return"	return RETURN;
121 "scale"		return SCALE;
122 "sqrt"		return SQRT;
123 "while"		return WHILE;
124 
125 "^"		return EXPONENT;
126 "*"		return MULTIPLY;
127 "/"		return DIVIDE;
128 "%"		return REMAINDER;
129 
130 "!"		return BOOL_NOT;
131 "&&"		return BOOL_AND;
132 "||"		return BOOL_OR;
133 
134 "+"		return PLUS;
135 "-"		return MINUS;
136 
137 "++"		return INCR;
138 "--"		return DECR;
139 
140 "="		yylval.str = ""; return ASSIGN_OP;
141 "+="		yylval.str = "+"; return ASSIGN_OP;
142 "-="		yylval.str = "-"; return ASSIGN_OP;
143 "*="		yylval.str = "*"; return ASSIGN_OP;
144 "/="		yylval.str = "/"; return ASSIGN_OP;
145 "%="		yylval.str = "%"; return ASSIGN_OP;
146 "^="		yylval.str = "^"; return ASSIGN_OP;
147 
148 "=="		return EQUALS;
149 "<="		return LESS_EQ;
150 ">="		return GREATER_EQ;
151 "!="		return UNEQUALS;
152 "<"		return LESS;
153 ">"		return GREATER;
154 
155 ","		return COMMA;
156 ";"		return SEMICOLON;
157 
158 "("		return LPAR;
159 ")"		return RPAR;
160 
161 "["		return LBRACKET;
162 "]"		return RBRACKET;
163 
164 "{"		return LBRACE;
165 "}"		return RBRACE;
166 
167 {ALPHA}{ALPHANUM}* {
168 			/* alloc an extra byte for the type marker */
169 			char *p = malloc(yyleng + 2);
170 			if (p == NULL)
171 				err(1, NULL);
172 			strlcpy(p, yytext, yyleng + 1);
173 			yylval.astr = p;
174 			return LETTER;
175 		}
176 
177 \\\n		lineno++;
178 \n		lineno++; return NEWLINE;
179 
180 #[^\n]*		;
181 [ \t]		;
182 <<EOF>>		return QUIT;
183 .		yyerror("illegal character");
184 
185 %%
186 
187 static void
188 init_strbuf(void)
189 {
190 	if (strbuf == NULL) {
191 		strbuf = malloc(strbuf_sz);
192 		if (strbuf == NULL)
193 			err(1, NULL);
194 	}
195 	strbuf[0] = '\0';
196 }
197 
198 static void
199 add_str(const char *str)
200 {
201 	size_t arglen;
202 
203 	arglen = strlen(str);
204 
205 	if (strlen(strbuf) + arglen + 1 > strbuf_sz) {
206 		size_t newsize;
207 		char *p;
208 
209 		newsize = strbuf_sz + arglen + 1;
210 		p = realloc(strbuf, newsize);
211 		if (p == NULL) {
212 			free(strbuf);
213 			err(1, NULL);
214 		}
215 		strbuf_sz = newsize;
216 		strbuf = p;
217 	}
218 	strlcat(strbuf, str, strbuf_sz);
219 }
220 
221 void
222 abort_line(int sig)
223 {
224 	if (isatty(fileno(yyin))) {
225 		YY_FLUSH_BUFFER;
226 		printf("[\n]P\n");
227 	}
228 }
229