2 /* $OpenBSD: scan.l,v 1.28 2013/09/19 16:12:01 otto Exp $ */
5 * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
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.
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.
20 #include <sys/cdefs.h>
21 __FBSDID("$FreeBSD$");
33 #include "pathnames.h"
42 static char *strbuf = NULL;
43 static size_t strbuf_sz = 1;
46 static volatile sig_atomic_t skipchars;
48 static void init_strbuf(void);
49 static void add_str(const char *);
51 static int bc_yyinput(char *, int);
53 #define YY_DECL int yylex(void)
56 #define YY_INPUT(buf,retval,max) \
57 (retval = bc_yyinput(buf, max))
61 %option always-interactive
67 %x comment string number
77 <<EOF>> fatal("end of file in comment");
80 \" BEGIN(string); init_strbuf();
82 [^"\n\\\[\]]+ add_str(yytext);
86 \n add_str("\n"); lineno++;
87 \" BEGIN(INITIAL); yylval.str = strbuf; return STRING;
88 <<EOF>> fatal("end of file in string");
104 {DIGIT}+ add_str(yytext);
120 if (strcmp(strbuf, ".") == 0)
130 "break" return BREAK;
131 "continue" return CONTINUE;
132 "define" return DEFINE;
134 "ibase" return IBASE;
138 "length" return LENGTH;
139 "obase" return OBASE;
140 "print" return PRINT;
142 "return" return RETURN;
143 "scale" return SCALE;
145 "while" return WHILE;
150 "%" return REMAINDER;
153 "&&" return BOOL_AND;
162 "=" yylval.str = ""; return ASSIGN_OP;
163 "+=" yylval.str = "+"; return ASSIGN_OP;
164 "-=" yylval.str = "-"; return ASSIGN_OP;
165 "*=" yylval.str = "*"; return ASSIGN_OP;
166 "/=" yylval.str = "/"; return ASSIGN_OP;
167 "%=" yylval.str = "%"; return ASSIGN_OP;
168 "^=" yylval.str = "^"; return ASSIGN_OP;
172 ">=" return GREATER_EQ;
173 "!=" return UNEQUALS;
178 ";" return SEMICOLON;
190 /* alloc an extra byte for the type marker */
191 char *p = malloc(yyleng + 2);
194 strlcpy(p, yytext, yyleng + 1);
200 \n lineno++; return NEWLINE;
205 . yyerror("illegal character");
212 if (strbuf == NULL) {
213 strbuf = malloc(strbuf_sz);
221 add_str(const char *str)
225 arglen = strlen(str);
227 if (strlen(strbuf) + arglen + 1 > strbuf_sz) {
231 newsize = strbuf_sz + arglen + 1;
232 p = realloc(strbuf, newsize);
240 strlcat(strbuf, str, strbuf_sz);
245 abort_line(int sig __unused)
247 static const char str1[] = "[\n]P\n";
248 static const char str2[] = "[^C\n]P\n";
250 const LineInfo *info;
254 write(STDOUT_FILENO, str2, sizeof(str2) - 1);
256 skipchars = info->lastchar - info->buffer;
258 write(STDOUT_FILENO, str1, sizeof(str1) - 1);
263 * Avoid the echo of ^D by the default code of editline and take
264 * into account skipchars to make ^D work when the cursor is at start of
268 bc_eof(EditLine *e, int ch __unused)
270 const struct lineinfo *info = el_line(e);
272 if (info->buffer + skipchars == info->cursor &&
273 info->cursor == info->lastchar)
283 static YY_BUFFER_STATE buf;
285 if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) {
286 filename = sargv[fileindex++];
287 yyin = fopen(filename, "r");
290 err(1, "cannot open %s", filename);
293 if (state == 0 && cmdexpr[0] != '\0') {
294 buf = yy_scan_string(cmdexpr);
297 filename = "command line";
299 } else if (state == 1) {
300 yy_delete_buffer(buf);
304 if (yyin != NULL && yyin != stdin)
306 if (fileindex < sargc) {
307 filename = sargv[fileindex++];
308 yyin = fopen(filename, "r");
311 err(1, "cannot open %s", filename);
313 } else if (fileindex == sargc) {
317 signal(SIGINT, abort_line);
318 signal(SIGTSTP, tstpcont);
328 bc_yyinput(char *buf, int maxlen)
333 el_get(el, EL_EDITMODE, &use_el);
335 if (yyin == stdin && interactive && use_el) {
339 if ((bp = el_gets(el, &num)) == NULL || num == 0)
342 sigaddset(&nset, SIGINT);
343 sigprocmask(SIG_BLOCK, &nset, &oset);
344 if (skipchars < num) {
349 sigprocmask(SIG_SETMASK, &oset, NULL);
351 el_push(el, bp + maxlen);
354 memcpy(buf, bp, num);
355 history(hist, &he, H_ENTER, bp);
356 el_get(el, EL_EDITMODE, &use_el);
359 for (num = 0; num < maxlen &&
360 (c = getc(yyin)) != EOF && c != '\n'; ++num)
363 buf[num++] = (char) c;
364 if (c == EOF && ferror(yyin))
365 YY_FATAL_ERROR( "input in flex scanner failed" );