Annotation of src/usr.bin/bc/scan.l, Revision 1.25
1.1 otto 1: %{
1.25 ! otto 2: /* $OpenBSD: scan.l,v 1.24 2011/03/07 08:11:15 otto 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: #include <err.h>
1.24 otto 21: #include <histedit.h>
1.16 otto 22: #include <signal.h>
1.1 otto 23: #include <stdbool.h>
24: #include <string.h>
1.18 otto 25: #include <unistd.h>
1.1 otto 26:
27: #include "extern.h"
1.15 otto 28: #include "pathnames.h"
1.1 otto 29: #include "y.tab.h"
30:
31: int lineno;
1.21 otto 32: bool interactive;
1.1 otto 33:
1.24 otto 34: HistEvent he;
35: EditLine *el;
36: History *hist;
37:
1.2 deraadt 38: static char *strbuf = NULL;
1.1 otto 39: static size_t strbuf_sz = 1;
40: static bool dot_seen;
1.25 ! otto 41: static int use_el;
! 42: static volatile sig_atomic_t skipchars;
1.1 otto 43:
44: static void init_strbuf(void);
45: static void add_str(const char *);
46:
1.24 otto 47: static int bc_yyinput(char *, int);
48:
49: #undef YY_INPUT
50: #define YY_INPUT(buf,retval,max) \
51: (retval = bc_yyinput(buf, max))
52:
1.1 otto 53: %}
1.18 otto 54:
55: %option always-interactive
1.1 otto 56:
57: DIGIT [0-9A-F]
1.14 otto 58: ALPHA [a-z_]
59: ALPHANUM [a-z_0-9]
60:
1.1 otto 61: %x comment string number
62:
63: %%
64:
65: "/*" BEGIN(comment);
66: <comment>{
67: "*/" BEGIN(INITIAL);
68: \n lineno++;
69: \* ;
70: [^*\n]+ ;
1.5 otto 71: <<EOF>> fatal("end of file in comment");
1.1 otto 72: }
73:
74: \" BEGIN(string); init_strbuf();
75: <string>{
1.7 otto 76: [^"\n\\\[\]]+ add_str(yytext);
77: \[ add_str("\\[");
78: \] add_str("\\]");
79: \\ add_str("\\\\");
1.1 otto 80: \n add_str("\n"); lineno++;
81: \" BEGIN(INITIAL); yylval.str = strbuf; return STRING;
1.5 otto 82: <<EOF>> fatal("end of file in string");
1.1 otto 83: }
84:
85: {DIGIT}+ {
86: BEGIN(number);
87: dot_seen = false;
88: init_strbuf();
89: add_str(yytext);
90: }
91: \. {
92: BEGIN(number);
93: dot_seen = true;
94: init_strbuf();
95: add_str(".");
96: }
97: <number>{
98: {DIGIT}+ add_str(yytext);
99: \. {
100: if (dot_seen) {
101: BEGIN(INITIAL);
102: yylval.str = strbuf;
103: unput('.');
104: return NUMBER;
105: } else {
106: dot_seen = true;
107: add_str(".");
108: }
109: }
110: \\\n[ \t]* lineno++;
111: [^0-9A-F\.] {
1.6 otto 112: BEGIN(INITIAL);
113: unput(yytext[0]);
114: if (strcmp(strbuf, ".") == 0)
115: return DOT;
1.1 otto 116: else {
117: yylval.str = strbuf;
118: return NUMBER;
119: }
120: }
121: }
122:
123: "auto" return AUTO;
1.2 deraadt 124: "break" return BREAK;
1.8 otto 125: "continue" return CONTINUE;
1.1 otto 126: "define" return DEFINE;
1.8 otto 127: "else" return ELSE;
1.1 otto 128: "ibase" return IBASE;
129: "if" return IF;
1.10 otto 130: "last" return DOT;
1.1 otto 131: "for" return FOR;
132: "length" return LENGTH;
133: "obase" return OBASE;
1.11 otto 134: "print" return PRINT;
1.1 otto 135: "quit" return QUIT;
136: "return" return RETURN;
137: "scale" return SCALE;
138: "sqrt" return SQRT;
139: "while" return WHILE;
140:
141: "^" return EXPONENT;
142: "*" return MULTIPLY;
143: "/" return DIVIDE;
144: "%" return REMAINDER;
1.13 otto 145:
146: "!" return BOOL_NOT;
147: "&&" return BOOL_AND;
148: "||" return BOOL_OR;
1.1 otto 149:
150: "+" return PLUS;
151: "-" return MINUS;
152:
153: "++" return INCR;
154: "--" return DECR;
155:
1.4 deraadt 156: "=" yylval.str = ""; return ASSIGN_OP;
1.1 otto 157: "+=" yylval.str = "+"; return ASSIGN_OP;
158: "-=" yylval.str = "-"; return ASSIGN_OP;
159: "*=" yylval.str = "*"; return ASSIGN_OP;
160: "/=" yylval.str = "/"; return ASSIGN_OP;
161: "%=" yylval.str = "%"; return ASSIGN_OP;
162: "^=" yylval.str = "^"; return ASSIGN_OP;
163:
164: "==" return EQUALS;
165: "<=" return LESS_EQ;
166: ">=" return GREATER_EQ;
167: "!=" return UNEQUALS;
168: "<" return LESS;
169: ">" return GREATER;
170:
171: "," return COMMA;
172: ";" return SEMICOLON;
173:
174: "(" return LPAR;
175: ")" return RPAR;
176:
177: "[" return LBRACKET;
178: "]" return RBRACKET;
179:
180: "{" return LBRACE;
181: "}" return RBRACE;
182:
1.14 otto 183: {ALPHA}{ALPHANUM}* {
184: /* alloc an extra byte for the type marker */
185: char *p = malloc(yyleng + 2);
186: if (p == NULL)
187: err(1, NULL);
188: strlcpy(p, yytext, yyleng + 1);
189: yylval.astr = p;
190: return LETTER;
191: }
1.1 otto 192:
193: \\\n lineno++;
194: \n lineno++; return NEWLINE;
195:
1.12 otto 196: #[^\n]* ;
1.1 otto 197: [ \t] ;
1.14 otto 198: <<EOF>> return QUIT;
1.5 otto 199: . yyerror("illegal character");
1.1 otto 200:
201: %%
202:
203: static void
204: init_strbuf(void)
205: {
206: if (strbuf == NULL) {
207: strbuf = malloc(strbuf_sz);
208: if (strbuf == NULL)
1.9 otto 209: err(1, NULL);
1.1 otto 210: }
211: strbuf[0] = '\0';
212: }
213:
214: static void
215: add_str(const char *str)
216: {
217: size_t arglen;
218:
219: arglen = strlen(str);
220:
1.14 otto 221: if (strlen(strbuf) + arglen + 1 > strbuf_sz) {
1.1 otto 222: size_t newsize;
1.3 deraadt 223: char *p;
1.1 otto 224:
225: newsize = strbuf_sz + arglen + 1;
226: p = realloc(strbuf, newsize);
227: if (p == NULL) {
228: free(strbuf);
1.9 otto 229: err(1, NULL);
1.1 otto 230: }
231: strbuf_sz = newsize;
232: strbuf = p;
233: }
234: strlcat(strbuf, str, strbuf_sz);
235: }
236:
1.19 deraadt 237: /* ARGSUSED */
1.1 otto 238: void
239: abort_line(int sig)
240: {
1.25 ! otto 241: static const char str1[] = "[\n]P\n";
! 242: static const char str2[] = "[^C\n]P\n";
1.16 otto 243: int save_errno;
1.25 ! otto 244: const LineInfo *info;
1.16 otto 245:
1.21 otto 246: save_errno = errno;
1.25 ! otto 247: if (use_el) {
! 248: write(STDOUT_FILENO, str2, sizeof(str2) - 1);
! 249: info = el_line(el);
! 250: skipchars = info->lastchar - info->buffer;
! 251: } else
! 252: write(STDOUT_FILENO, str1, sizeof(str1) - 1);
1.21 otto 253: errno = save_errno;
1.1 otto 254: }
1.15 otto 255:
256: int
257: yywrap(void)
258: {
259: static int state;
260: static YY_BUFFER_STATE buf;
261:
262: if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) {
263: filename = sargv[fileindex++];
264: yyin = fopen(filename, "r");
265: lineno = 1;
266: if (yyin == NULL)
267: err(1, "cannot open %s", filename);
268: return (0);
269: }
270: if (state == 0 && cmdexpr[0] != '\0') {
271: buf = yy_scan_string(cmdexpr);
272: state++;
273: lineno = 1;
274: filename = "command line";
275: return (0);
276: } else if (state == 1) {
277: yy_delete_buffer(buf);
278: free(cmdexpr);
279: state++;
280: }
1.20 otto 281: if (yyin != NULL && yyin != stdin)
282: fclose(yyin);
1.15 otto 283: if (fileindex < sargc) {
284: filename = sargv[fileindex++];
285: yyin = fopen(filename, "r");
286: lineno = 1;
287: if (yyin == NULL)
288: err(1, "cannot open %s", filename);
289: return (0);
290: } else if (fileindex == sargc) {
291: fileindex++;
292: yyin = stdin;
1.21 otto 293: if (interactive)
294: signal(SIGINT, abort_line);
1.15 otto 295: lineno = 1;
296: filename = "stdin";
297: return (0);
298: }
299: return (1);
300: }
1.24 otto 301:
302: static int
303: bc_yyinput(char *buf, int maxlen)
304: {
305: int num;
1.25 ! otto 306:
! 307: if (el != NULL)
! 308: el_get(el, EL_EDITMODE, &use_el);
! 309:
! 310: if (yyin == stdin && interactive && use_el) {
1.24 otto 311: const char *bp;
1.25 ! otto 312: sigset_t oset, nset;
1.24 otto 313:
314: if ((bp = el_gets(el, &num)) == NULL || num == 0)
315: return (0);
1.25 ! otto 316: sigemptyset(&nset);
! 317: sigaddset(&nset, SIGINT);
! 318: sigprocmask(SIG_BLOCK, &nset, &oset);
! 319: if (skipchars < num) {
! 320: bp += skipchars;
! 321: num -= skipchars;
! 322: }
! 323: skipchars = 0;
! 324: sigprocmask(SIG_SETMASK, &oset, NULL);
1.24 otto 325: if (num > maxlen) {
326: el_push(el, (char *)(void *)bp + maxlen);
327: num = maxlen;
328: }
329: memcpy(buf, bp, num);
330: history(hist, &he, H_ENTER, bp);
1.25 ! otto 331: el_get(el, EL_EDITMODE, &use_el);
1.24 otto 332: } else {
333: int c = '*';
334: for (num = 0; num < maxlen &&
335: (c = getc(yyin)) != EOF && c != '\n'; ++num)
336: buf[num] = (char) c;
337: if (c == '\n')
338: buf[num++] = (char) c;
339: if (c == EOF && ferror(yyin))
340: YY_FATAL_ERROR( "input in flex scanner failed" );
341: }
342: return (num);
343: }
344:
1.15 otto 345: