scan.l revision 202719
1%{ 2/* $OpenBSD: scan.l,v 1.23 2009/10/27 23:59:36 deraadt 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 <sys/cdefs.h> 21__FBSDID("$FreeBSD: head/usr.bin/bc/scan.l 202719 2010-01-20 21:30:52Z gabor $"); 22 23#include <err.h> 24#include <errno.h> 25#include <signal.h> 26#include <stdbool.h> 27#include <string.h> 28#include <unistd.h> 29 30#include "extern.h" 31#include "bc.h" 32#include "pathnames.h" 33 34int lineno; 35 36static char *strbuf = NULL; 37static size_t strbuf_sz = 1; 38static bool dot_seen; 39 40static void init_strbuf(void); 41static void add_str(const char *); 42 43%} 44 45%option always-interactive 46 47DIGIT [0-9A-F] 48ALPHA [a-z_] 49ALPHANUM [a-z_0-9] 50 51%x comment string number 52 53%% 54 55"/*" BEGIN(comment); 56<comment>{ 57 "*/" BEGIN(INITIAL); 58 \n lineno++; 59 \* ; 60 [^*\n]+ ; 61 <<EOF>> fatal("end of file in comment"); 62} 63 64\" BEGIN(string); init_strbuf(); 65<string>{ 66 [^"\n\\\[\]]+ add_str(yytext); 67 \[ add_str("\\["); 68 \] add_str("\\]"); 69 \\ add_str("\\\\"); 70 \n add_str("\n"); lineno++; 71 \" BEGIN(INITIAL); yylval.str = strbuf; return STRING; 72 <<EOF>> fatal("end of file in string"); 73} 74 75{DIGIT}+ { 76 BEGIN(number); 77 dot_seen = false; 78 init_strbuf(); 79 add_str(yytext); 80 } 81\. { 82 BEGIN(number); 83 dot_seen = true; 84 init_strbuf(); 85 add_str("."); 86 } 87<number>{ 88 {DIGIT}+ add_str(yytext); 89 \. { 90 if (dot_seen) { 91 BEGIN(INITIAL); 92 yylval.str = strbuf; 93 unput('.'); 94 return (NUMBER); 95 } else { 96 dot_seen = true; 97 add_str("."); 98 } 99 } 100 \\\n[ \t]* lineno++; 101 [^0-9A-F\.] { 102 BEGIN(INITIAL); 103 unput(yytext[0]); 104 if (strcmp(strbuf, ".") == 0) 105 return (DOT); 106 else { 107 yylval.str = strbuf; 108 return (NUMBER); 109 } 110 } 111} 112 113"auto" return (AUTO); 114"break" return (BREAK); 115"continue" return (CONTINUE); 116"define" return (DEFINE); 117"else" return (ELSE); 118"ibase" return (IBASE); 119"if" return (IF); 120"last" return (DOT); 121"for" return (FOR); 122"length" return (LENGTH); 123"obase" return (OBASE); 124"print" return (PRINT); 125"quit" return (QUIT); 126"return" return (RETURN); 127"scale" return (SCALE); 128"sqrt" return (SQRT); 129"while" return (WHILE); 130 131"^" return (EXPONENT); 132"*" return (MULTIPLY); 133"/" return (DIVIDE); 134"%" return (REMAINDER); 135 136"!" return (BOOL_NOT); 137"&&" return (BOOL_AND); 138"||" return (BOOL_OR); 139 140"+" return (PLUS); 141"-" return (MINUS); 142 143"++" return (INCR); 144"--" return (DECR); 145 146"=" yylval.str = ""; return (ASSIGN_OP); 147"+=" yylval.str = "+"; return (ASSIGN_OP); 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 154"==" return (EQUALS); 155"<=" return (LESS_EQ); 156">=" return (GREATER_EQ); 157"!=" return (UNEQUALS); 158"<" return (LESS); 159">" return (GREATER); 160 161"," return (COMMA); 162";" return (SEMICOLON); 163 164"(" return (LPAR); 165")" return (RPAR); 166 167"[" return (LBRACKET); 168"]" return (RBRACKET); 169 170"{" return (LBRACE); 171"}" return (RBRACE); 172 173{ALPHA}{ALPHANUM}* { 174 /* alloc an extra byte for the type marker */ 175 char *p = malloc(yyleng + 2); 176 if (p == NULL) 177 err(1, NULL); 178 strlcpy(p, yytext, yyleng + 1); 179 yylval.astr = p; 180 return (LETTER); 181 } 182 183\\\n lineno++; 184\n lineno++; return (NEWLINE); 185 186#[^\n]* ; 187[ \t] ; 188<<EOF>> return (QUIT); 189. yyerror("illegal character"); 190 191%% 192 193static void 194init_strbuf(void) 195{ 196 if (strbuf == NULL) { 197 strbuf = malloc(strbuf_sz); 198 if (strbuf == NULL) 199 err(1, NULL); 200 } 201 strbuf[0] = '\0'; 202} 203 204static void 205add_str(const char *str) 206{ 207 size_t arglen; 208 209 arglen = strlen(str); 210 211 if (strlen(strbuf) + arglen + 1 > strbuf_sz) { 212 size_t newsize; 213 char *p; 214 215 newsize = strbuf_sz + arglen + 1; 216 p = realloc(strbuf, newsize); 217 if (p == NULL) { 218 free(strbuf); 219 err(1, NULL); 220 } 221 strbuf_sz = newsize; 222 strbuf = p; 223 } 224 strlcat(strbuf, str, strbuf_sz); 225} 226 227/* ARGSUSED */ 228void 229abort_line(int sig) 230{ 231 static const char str[] = "[\n]P\n"; 232 int save_errno; 233 234 switch (sig) { 235 default: 236 save_errno = errno; 237 YY_FLUSH_BUFFER; /* XXX signal race? */ 238 write(STDOUT_FILENO, str, sizeof(str) - 1); 239 errno = save_errno; 240 } 241} 242 243int 244yywrap(void) 245{ 246 static int state; 247 static YY_BUFFER_STATE buf; 248 249 if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) { 250 filename = sargv[fileindex++]; 251 yyin = fopen(filename, "r"); 252 lineno = 1; 253 if (yyin == NULL) 254 err(1, "cannot open %s", filename); 255 return (0); 256 } 257 if (state == 0 && cmdexpr[0] != '\0') { 258 buf = yy_scan_string(cmdexpr); 259 state++; 260 lineno = 1; 261 filename = "command line"; 262 return (0); 263 } else if (state == 1) { 264 yy_delete_buffer(buf); 265 free(cmdexpr); 266 state++; 267 } 268 if (yyin != NULL && yyin != stdin) 269 fclose(yyin); 270 if (fileindex < sargc) { 271 filename = sargv[fileindex++]; 272 yyin = fopen(filename, "r"); 273 lineno = 1; 274 if (yyin == NULL) 275 err(1, "cannot open %s", filename); 276 return (0); 277 } else if (fileindex == sargc) { 278 fileindex++; 279 yyin = stdin; 280 if (interactive) 281 signal(SIGINT, abort_line); 282 lineno = 1; 283 filename = "stdin"; 284 return (0); 285 } 286 return (1); 287} 288 289