Annotation of src/usr.bin/bc/scan.l, Revision 1.18
1.1 otto 1: %{
1.18 ! otto 2: /* $OpenBSD: scan.l,v 1.17 2005/03/28 17:43:28 deraadt Exp $ */
1.1 otto 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: #ifndef lint
1.18 ! otto 21: static const char rcsid[] = "$OpenBSD: scan.l,v 1.17 2005/03/28 17:43:28 deraadt Exp $";
1.1 otto 22: #endif /* not lint */
23:
24: #include <err.h>
1.16 otto 25: #include <signal.h>
1.1 otto 26: #include <stdbool.h>
27: #include <string.h>
1.18 ! otto 28: #include <unistd.h>
1.1 otto 29:
30: #include "extern.h"
1.15 otto 31: #include "pathnames.h"
1.1 otto 32: #include "y.tab.h"
33:
34: int lineno;
35:
1.2 deraadt 36: static char *strbuf = NULL;
1.1 otto 37: static size_t strbuf_sz = 1;
38: static bool dot_seen;
1.16 otto 39: static volatile sig_atomic_t interactive = 0;
1.1 otto 40:
41: static void init_strbuf(void);
42: static void add_str(const char *);
43:
44: %}
1.18 ! otto 45:
! 46: %option always-interactive
1.1 otto 47:
48: DIGIT [0-9A-F]
1.14 otto 49: ALPHA [a-z_]
50: ALPHANUM [a-z_0-9]
51:
1.1 otto 52: %x comment string number
53:
54: %%
55:
56: "/*" BEGIN(comment);
57: <comment>{
58: "*/" BEGIN(INITIAL);
59: \n lineno++;
60: \* ;
61: [^*\n]+ ;
1.5 otto 62: <<EOF>> fatal("end of file in comment");
1.1 otto 63: }
64:
65: \" BEGIN(string); init_strbuf();
66: <string>{
1.7 otto 67: [^"\n\\\[\]]+ add_str(yytext);
68: \[ add_str("\\[");
69: \] add_str("\\]");
70: \\ add_str("\\\\");
1.1 otto 71: \n add_str("\n"); lineno++;
72: \" BEGIN(INITIAL); yylval.str = strbuf; return STRING;
1.5 otto 73: <<EOF>> fatal("end of file in string");
1.1 otto 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\.] {
1.6 otto 103: BEGIN(INITIAL);
104: unput(yytext[0]);
105: if (strcmp(strbuf, ".") == 0)
106: return DOT;
1.1 otto 107: else {
108: yylval.str = strbuf;
109: return NUMBER;
110: }
111: }
112: }
113:
114: "auto" return AUTO;
1.2 deraadt 115: "break" return BREAK;
1.8 otto 116: "continue" return CONTINUE;
1.1 otto 117: "define" return DEFINE;
1.8 otto 118: "else" return ELSE;
1.1 otto 119: "ibase" return IBASE;
120: "if" return IF;
1.10 otto 121: "last" return DOT;
1.1 otto 122: "for" return FOR;
123: "length" return LENGTH;
124: "obase" return OBASE;
1.11 otto 125: "print" return PRINT;
1.1 otto 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;
1.13 otto 136:
137: "!" return BOOL_NOT;
138: "&&" return BOOL_AND;
139: "||" return BOOL_OR;
1.1 otto 140:
141: "+" return PLUS;
142: "-" return MINUS;
143:
144: "++" return INCR;
145: "--" return DECR;
146:
1.4 deraadt 147: "=" yylval.str = ""; return ASSIGN_OP;
1.1 otto 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:
1.14 otto 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: }
1.1 otto 183:
184: \\\n lineno++;
185: \n lineno++; return NEWLINE;
186:
1.12 otto 187: #[^\n]* ;
1.1 otto 188: [ \t] ;
1.14 otto 189: <<EOF>> return QUIT;
1.5 otto 190: . yyerror("illegal character");
1.1 otto 191:
192: %%
193:
194: static void
195: init_strbuf(void)
196: {
197: if (strbuf == NULL) {
198: strbuf = malloc(strbuf_sz);
199: if (strbuf == NULL)
1.9 otto 200: err(1, NULL);
1.1 otto 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:
1.14 otto 212: if (strlen(strbuf) + arglen + 1 > strbuf_sz) {
1.1 otto 213: size_t newsize;
1.3 deraadt 214: char *p;
1.1 otto 215:
216: newsize = strbuf_sz + arglen + 1;
217: p = realloc(strbuf, newsize);
218: if (p == NULL) {
219: free(strbuf);
1.9 otto 220: err(1, NULL);
1.1 otto 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: {
1.16 otto 231: const char str[] = "[\n]P\n";
232: int save_errno;
233:
234: if (interactive) {
235: save_errno = errno;
1.17 deraadt 236: YY_FLUSH_BUFFER; /* XXX signal race? */
1.16 otto 237: write(STDOUT_FILENO, str, sizeof(str) - 1);
238: errno = save_errno;
1.1 otto 239: }
240: }
1.15 otto 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;
1.16 otto 277: interactive = isatty(fileno(yyin));
1.15 otto 278: lineno = 1;
279: filename = "stdin";
280: return (0);
281: }
282: return (1);
283: }
284: