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