scan.l revision 202719
1202719Sgabor%{ 2202719Sgabor/* $OpenBSD: scan.l,v 1.23 2009/10/27 23:59:36 deraadt Exp $ */ 3202719Sgabor 4202719Sgabor/* 5202719Sgabor * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net> 6202719Sgabor * 7202719Sgabor * Permission to use, copy, modify, and distribute this software for any 8202719Sgabor * purpose with or without fee is hereby granted, provided that the above 9202719Sgabor * copyright notice and this permission notice appear in all copies. 10202719Sgabor * 11202719Sgabor * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12202719Sgabor * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13202719Sgabor * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14202719Sgabor * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15202719Sgabor * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16202719Sgabor * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17202719Sgabor * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18202719Sgabor */ 19202719Sgabor 20202719Sgabor#include <sys/cdefs.h> 21202719Sgabor__FBSDID("$FreeBSD: head/usr.bin/bc/scan.l 202719 2010-01-20 21:30:52Z gabor $"); 22202719Sgabor 23202719Sgabor#include <err.h> 24202719Sgabor#include <errno.h> 25202719Sgabor#include <signal.h> 26202719Sgabor#include <stdbool.h> 27202719Sgabor#include <string.h> 28202719Sgabor#include <unistd.h> 29202719Sgabor 30202719Sgabor#include "extern.h" 31202719Sgabor#include "bc.h" 32202719Sgabor#include "pathnames.h" 33202719Sgabor 34202719Sgaborint lineno; 35202719Sgabor 36202719Sgaborstatic char *strbuf = NULL; 37202719Sgaborstatic size_t strbuf_sz = 1; 38202719Sgaborstatic bool dot_seen; 39202719Sgabor 40202719Sgaborstatic void init_strbuf(void); 41202719Sgaborstatic void add_str(const char *); 42202719Sgabor 43202719Sgabor%} 44202719Sgabor 45202719Sgabor%option always-interactive 46202719Sgabor 47202719SgaborDIGIT [0-9A-F] 48202719SgaborALPHA [a-z_] 49202719SgaborALPHANUM [a-z_0-9] 50202719Sgabor 51202719Sgabor%x comment string number 52202719Sgabor 53202719Sgabor%% 54202719Sgabor 55202719Sgabor"/*" BEGIN(comment); 56202719Sgabor<comment>{ 57202719Sgabor "*/" BEGIN(INITIAL); 58202719Sgabor \n lineno++; 59202719Sgabor \* ; 60202719Sgabor [^*\n]+ ; 61202719Sgabor <<EOF>> fatal("end of file in comment"); 62202719Sgabor} 63202719Sgabor 64202719Sgabor\" BEGIN(string); init_strbuf(); 65202719Sgabor<string>{ 66202719Sgabor [^"\n\\\[\]]+ add_str(yytext); 67202719Sgabor \[ add_str("\\["); 68202719Sgabor \] add_str("\\]"); 69202719Sgabor \\ add_str("\\\\"); 70202719Sgabor \n add_str("\n"); lineno++; 71202719Sgabor \" BEGIN(INITIAL); yylval.str = strbuf; return STRING; 72202719Sgabor <<EOF>> fatal("end of file in string"); 73202719Sgabor} 74202719Sgabor 75202719Sgabor{DIGIT}+ { 76202719Sgabor BEGIN(number); 77202719Sgabor dot_seen = false; 78202719Sgabor init_strbuf(); 79202719Sgabor add_str(yytext); 80202719Sgabor } 81202719Sgabor\. { 82202719Sgabor BEGIN(number); 83202719Sgabor dot_seen = true; 84202719Sgabor init_strbuf(); 85202719Sgabor add_str("."); 86202719Sgabor } 87202719Sgabor<number>{ 88202719Sgabor {DIGIT}+ add_str(yytext); 89202719Sgabor \. { 90202719Sgabor if (dot_seen) { 91202719Sgabor BEGIN(INITIAL); 92202719Sgabor yylval.str = strbuf; 93202719Sgabor unput('.'); 94202719Sgabor return (NUMBER); 95202719Sgabor } else { 96202719Sgabor dot_seen = true; 97202719Sgabor add_str("."); 98202719Sgabor } 99202719Sgabor } 100202719Sgabor \\\n[ \t]* lineno++; 101202719Sgabor [^0-9A-F\.] { 102202719Sgabor BEGIN(INITIAL); 103202719Sgabor unput(yytext[0]); 104202719Sgabor if (strcmp(strbuf, ".") == 0) 105202719Sgabor return (DOT); 106202719Sgabor else { 107202719Sgabor yylval.str = strbuf; 108202719Sgabor return (NUMBER); 109202719Sgabor } 110202719Sgabor } 111202719Sgabor} 112202719Sgabor 113202719Sgabor"auto" return (AUTO); 114202719Sgabor"break" return (BREAK); 115202719Sgabor"continue" return (CONTINUE); 116202719Sgabor"define" return (DEFINE); 117202719Sgabor"else" return (ELSE); 118202719Sgabor"ibase" return (IBASE); 119202719Sgabor"if" return (IF); 120202719Sgabor"last" return (DOT); 121202719Sgabor"for" return (FOR); 122202719Sgabor"length" return (LENGTH); 123202719Sgabor"obase" return (OBASE); 124202719Sgabor"print" return (PRINT); 125202719Sgabor"quit" return (QUIT); 126202719Sgabor"return" return (RETURN); 127202719Sgabor"scale" return (SCALE); 128202719Sgabor"sqrt" return (SQRT); 129202719Sgabor"while" return (WHILE); 130202719Sgabor 131202719Sgabor"^" return (EXPONENT); 132202719Sgabor"*" return (MULTIPLY); 133202719Sgabor"/" return (DIVIDE); 134202719Sgabor"%" return (REMAINDER); 135202719Sgabor 136202719Sgabor"!" return (BOOL_NOT); 137202719Sgabor"&&" return (BOOL_AND); 138202719Sgabor"||" return (BOOL_OR); 139202719Sgabor 140202719Sgabor"+" return (PLUS); 141202719Sgabor"-" return (MINUS); 142202719Sgabor 143202719Sgabor"++" return (INCR); 144202719Sgabor"--" return (DECR); 145202719Sgabor 146202719Sgabor"=" yylval.str = ""; return (ASSIGN_OP); 147202719Sgabor"+=" yylval.str = "+"; return (ASSIGN_OP); 148202719Sgabor"-=" yylval.str = "-"; return (ASSIGN_OP); 149202719Sgabor"*=" yylval.str = "*"; return (ASSIGN_OP); 150202719Sgabor"/=" yylval.str = "/"; return (ASSIGN_OP); 151202719Sgabor"%=" yylval.str = "%"; return (ASSIGN_OP); 152202719Sgabor"^=" yylval.str = "^"; return (ASSIGN_OP); 153202719Sgabor 154202719Sgabor"==" return (EQUALS); 155202719Sgabor"<=" return (LESS_EQ); 156202719Sgabor">=" return (GREATER_EQ); 157202719Sgabor"!=" return (UNEQUALS); 158202719Sgabor"<" return (LESS); 159202719Sgabor">" return (GREATER); 160202719Sgabor 161202719Sgabor"," return (COMMA); 162202719Sgabor";" return (SEMICOLON); 163202719Sgabor 164202719Sgabor"(" return (LPAR); 165202719Sgabor")" return (RPAR); 166202719Sgabor 167202719Sgabor"[" return (LBRACKET); 168202719Sgabor"]" return (RBRACKET); 169202719Sgabor 170202719Sgabor"{" return (LBRACE); 171202719Sgabor"}" return (RBRACE); 172202719Sgabor 173202719Sgabor{ALPHA}{ALPHANUM}* { 174202719Sgabor /* alloc an extra byte for the type marker */ 175202719Sgabor char *p = malloc(yyleng + 2); 176202719Sgabor if (p == NULL) 177202719Sgabor err(1, NULL); 178202719Sgabor strlcpy(p, yytext, yyleng + 1); 179202719Sgabor yylval.astr = p; 180202719Sgabor return (LETTER); 181202719Sgabor } 182202719Sgabor 183202719Sgabor\\\n lineno++; 184202719Sgabor\n lineno++; return (NEWLINE); 185202719Sgabor 186202719Sgabor#[^\n]* ; 187202719Sgabor[ \t] ; 188202719Sgabor<<EOF>> return (QUIT); 189202719Sgabor. yyerror("illegal character"); 190202719Sgabor 191202719Sgabor%% 192202719Sgabor 193202719Sgaborstatic void 194202719Sgaborinit_strbuf(void) 195202719Sgabor{ 196202719Sgabor if (strbuf == NULL) { 197202719Sgabor strbuf = malloc(strbuf_sz); 198202719Sgabor if (strbuf == NULL) 199202719Sgabor err(1, NULL); 200202719Sgabor } 201202719Sgabor strbuf[0] = '\0'; 202202719Sgabor} 203202719Sgabor 204202719Sgaborstatic void 205202719Sgaboradd_str(const char *str) 206202719Sgabor{ 207202719Sgabor size_t arglen; 208202719Sgabor 209202719Sgabor arglen = strlen(str); 210202719Sgabor 211202719Sgabor if (strlen(strbuf) + arglen + 1 > strbuf_sz) { 212202719Sgabor size_t newsize; 213202719Sgabor char *p; 214202719Sgabor 215202719Sgabor newsize = strbuf_sz + arglen + 1; 216202719Sgabor p = realloc(strbuf, newsize); 217202719Sgabor if (p == NULL) { 218202719Sgabor free(strbuf); 219202719Sgabor err(1, NULL); 220202719Sgabor } 221202719Sgabor strbuf_sz = newsize; 222202719Sgabor strbuf = p; 223202719Sgabor } 224202719Sgabor strlcat(strbuf, str, strbuf_sz); 225202719Sgabor} 226202719Sgabor 227202719Sgabor/* ARGSUSED */ 228202719Sgaborvoid 229202719Sgaborabort_line(int sig) 230202719Sgabor{ 231202719Sgabor static const char str[] = "[\n]P\n"; 232202719Sgabor int save_errno; 233202719Sgabor 234202719Sgabor switch (sig) { 235202719Sgabor default: 236202719Sgabor save_errno = errno; 237202719Sgabor YY_FLUSH_BUFFER; /* XXX signal race? */ 238202719Sgabor write(STDOUT_FILENO, str, sizeof(str) - 1); 239202719Sgabor errno = save_errno; 240202719Sgabor } 241202719Sgabor} 242202719Sgabor 243202719Sgaborint 244202719Sgaboryywrap(void) 245202719Sgabor{ 246202719Sgabor static int state; 247202719Sgabor static YY_BUFFER_STATE buf; 248202719Sgabor 249202719Sgabor if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) { 250202719Sgabor filename = sargv[fileindex++]; 251202719Sgabor yyin = fopen(filename, "r"); 252202719Sgabor lineno = 1; 253202719Sgabor if (yyin == NULL) 254202719Sgabor err(1, "cannot open %s", filename); 255202719Sgabor return (0); 256202719Sgabor } 257202719Sgabor if (state == 0 && cmdexpr[0] != '\0') { 258202719Sgabor buf = yy_scan_string(cmdexpr); 259202719Sgabor state++; 260202719Sgabor lineno = 1; 261202719Sgabor filename = "command line"; 262202719Sgabor return (0); 263202719Sgabor } else if (state == 1) { 264202719Sgabor yy_delete_buffer(buf); 265202719Sgabor free(cmdexpr); 266202719Sgabor state++; 267202719Sgabor } 268202719Sgabor if (yyin != NULL && yyin != stdin) 269202719Sgabor fclose(yyin); 270202719Sgabor if (fileindex < sargc) { 271202719Sgabor filename = sargv[fileindex++]; 272202719Sgabor yyin = fopen(filename, "r"); 273202719Sgabor lineno = 1; 274202719Sgabor if (yyin == NULL) 275202719Sgabor err(1, "cannot open %s", filename); 276202719Sgabor return (0); 277202719Sgabor } else if (fileindex == sargc) { 278202719Sgabor fileindex++; 279202719Sgabor yyin = stdin; 280202719Sgabor if (interactive) 281202719Sgabor signal(SIGINT, abort_line); 282202719Sgabor lineno = 1; 283202719Sgabor filename = "stdin"; 284202719Sgabor return (0); 285202719Sgabor } 286202719Sgabor return (1); 287202719Sgabor} 288202719Sgabor 289