scan.l revision 208868
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 208868 2010-06-06 11:36:08Z gabor $"); 22 23#include <err.h> 24#include <errno.h> 25#include <histedit.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 36bool interactive; 37HistEvent he; 38EditLine *el; 39History *hist; 40 41static char *strbuf = NULL; 42static size_t strbuf_sz = 1; 43static bool dot_seen; 44 45static void init_strbuf(void); 46static void add_str(const char *); 47static int bc_yyinput(char *, int); 48 49#undef YY_INPUT 50#define YY_INPUT(buf,retval,max) \ 51 (retval = bc_yyinput(buf, max)) 52%} 53 54%option always-interactive 55 56DIGIT [0-9A-F] 57ALPHA [a-z_] 58ALPHANUM [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 202static void 203init_strbuf(void) 204{ 205 206 if (strbuf == NULL) { 207 strbuf = malloc(strbuf_sz); 208 if (strbuf == NULL) 209 err(1, NULL); 210 } 211 strbuf[0] = '\0'; 212} 213 214static void 215add_str(const char *str) 216{ 217 size_t arglen; 218 219 arglen = strlen(str); 220 221 if (strlen(strbuf) + arglen + 1 > strbuf_sz) { 222 size_t newsize; 223 char *p; 224 225 newsize = strbuf_sz + arglen + 1; 226 p = realloc(strbuf, newsize); 227 if (p == NULL) { 228 free(strbuf); 229 err(1, NULL); 230 } 231 strbuf_sz = newsize; 232 strbuf = p; 233 } 234 strlcat(strbuf, str, strbuf_sz); 235} 236 237int 238yywrap(void) 239{ 240 static YY_BUFFER_STATE buf; 241 static int state; 242 243 if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) { 244 filename = sargv[fileindex++]; 245 yyin = fopen(filename, "r"); 246 lineno = 1; 247 if (yyin == NULL) 248 err(1, "cannot open %s", filename); 249 return (0); 250 } 251 if (state == 0 && cmdexpr[0] != '\0') { 252 buf = yy_scan_string(cmdexpr); 253 state++; 254 lineno = 1; 255 filename = "command line"; 256 return (0); 257 } else if (state == 1) { 258 yy_delete_buffer(buf); 259 free(cmdexpr); 260 state++; 261 } 262 if (yyin != NULL && yyin != stdin) 263 fclose(yyin); 264 if (fileindex < sargc) { 265 filename = sargv[fileindex++]; 266 yyin = fopen(filename, "r"); 267 lineno = 1; 268 if (yyin == NULL) 269 err(1, "cannot open %s", filename); 270 return (0); 271 } else if (fileindex == sargc) { 272 fileindex++; 273 yyin = stdin; 274 lineno = 1; 275 filename = "stdin"; 276 return (0); 277 } 278 return (1); 279} 280 281static int 282bc_yyinput(char *buf, int maxlen) 283{ 284 int num; 285 if (yyin == stdin && interactive) { 286 const char *bp; 287 288 if ((bp = el_gets(el, &num)) == NULL || num == 0) 289 return (0); 290 if (num > maxlen) { 291 el_push(el, (char *)(uintptr_t)(bp) + maxlen); 292 num = maxlen; 293 } 294 memcpy(buf, bp, num); 295 history(hist, &he, H_ENTER, bp); 296 } else { 297 int c = '*'; 298 for (num = 0; num < maxlen && 299 (c = getc(yyin)) != EOF && c != '\n'; ++num) 300 buf[num] = (char) c; 301 if (c == '\n') 302 buf[num++] = (char) c; 303 if (c == EOF && ferror(yyin)) 304 YY_FATAL_ERROR( "input in flex scanner failed" ); 305 } 306 return (num); 307} 308 309