fatbase

portable OpenBSD tools
git clone git://git.2f30.org/fatbase
Log | Files | Refs

scan.l (7268B)


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