scan.l revision 250926
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 250926 2013-05-23 05:42:35Z jkim $"); 22202719Sgabor 23202719Sgabor#include <err.h> 24202719Sgabor#include <errno.h> 25203498Sdelphij#include <histedit.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 36203498Sdelphijbool interactive; 37203498SdelphijHistEvent he; 38203498SdelphijEditLine *el; 39203498SdelphijHistory *hist; 40203498Sdelphij 41202719Sgaborstatic char *strbuf = NULL; 42202719Sgaborstatic size_t strbuf_sz = 1; 43202719Sgaborstatic bool dot_seen; 44202719Sgabor 45202719Sgaborstatic void init_strbuf(void); 46202719Sgaborstatic void add_str(const char *); 47203498Sdelphijstatic int bc_yyinput(char *, int); 48202719Sgabor 49250926Sjkim#define YY_DECL int yylex(void) 50215704Sbrucec#define YY_NO_INPUT 51203498Sdelphij#undef YY_INPUT 52203498Sdelphij#define YY_INPUT(buf,retval,max) \ 53203498Sdelphij (retval = bc_yyinput(buf, max)) 54202719Sgabor%} 55202719Sgabor 56202719Sgabor%option always-interactive 57202719Sgabor 58202719SgaborDIGIT [0-9A-F] 59202719SgaborALPHA [a-z_] 60202719SgaborALPHANUM [a-z_0-9] 61202719Sgabor 62202719Sgabor%x comment string number 63202719Sgabor 64202719Sgabor%% 65202719Sgabor 66202719Sgabor"/*" BEGIN(comment); 67202719Sgabor<comment>{ 68202719Sgabor "*/" BEGIN(INITIAL); 69202719Sgabor \n lineno++; 70202719Sgabor \* ; 71202719Sgabor [^*\n]+ ; 72202719Sgabor <<EOF>> fatal("end of file in comment"); 73202719Sgabor} 74202719Sgabor 75202719Sgabor\" BEGIN(string); init_strbuf(); 76202719Sgabor<string>{ 77202719Sgabor [^"\n\\\[\]]+ add_str(yytext); 78202719Sgabor \[ add_str("\\["); 79202719Sgabor \] add_str("\\]"); 80202719Sgabor \\ add_str("\\\\"); 81202719Sgabor \n add_str("\n"); lineno++; 82202719Sgabor \" BEGIN(INITIAL); yylval.str = strbuf; return STRING; 83202719Sgabor <<EOF>> fatal("end of file in string"); 84202719Sgabor} 85202719Sgabor 86202719Sgabor{DIGIT}+ { 87202719Sgabor BEGIN(number); 88202719Sgabor dot_seen = false; 89202719Sgabor init_strbuf(); 90202719Sgabor add_str(yytext); 91202719Sgabor } 92202719Sgabor\. { 93202719Sgabor BEGIN(number); 94202719Sgabor dot_seen = true; 95202719Sgabor init_strbuf(); 96202719Sgabor add_str("."); 97202719Sgabor } 98202719Sgabor<number>{ 99202719Sgabor {DIGIT}+ add_str(yytext); 100202719Sgabor \. { 101202719Sgabor if (dot_seen) { 102202719Sgabor BEGIN(INITIAL); 103202719Sgabor yylval.str = strbuf; 104202719Sgabor unput('.'); 105202719Sgabor return (NUMBER); 106202719Sgabor } else { 107202719Sgabor dot_seen = true; 108202719Sgabor add_str("."); 109202719Sgabor } 110202719Sgabor } 111202719Sgabor \\\n[ \t]* lineno++; 112202719Sgabor [^0-9A-F\.] { 113202719Sgabor BEGIN(INITIAL); 114202719Sgabor unput(yytext[0]); 115202719Sgabor if (strcmp(strbuf, ".") == 0) 116202719Sgabor return (DOT); 117202719Sgabor else { 118202719Sgabor yylval.str = strbuf; 119202719Sgabor return (NUMBER); 120202719Sgabor } 121202719Sgabor } 122202719Sgabor} 123202719Sgabor 124202719Sgabor"auto" return (AUTO); 125202719Sgabor"break" return (BREAK); 126202719Sgabor"continue" return (CONTINUE); 127202719Sgabor"define" return (DEFINE); 128202719Sgabor"else" return (ELSE); 129202719Sgabor"ibase" return (IBASE); 130202719Sgabor"if" return (IF); 131202719Sgabor"last" return (DOT); 132202719Sgabor"for" return (FOR); 133202719Sgabor"length" return (LENGTH); 134202719Sgabor"obase" return (OBASE); 135202719Sgabor"print" return (PRINT); 136202719Sgabor"quit" return (QUIT); 137202719Sgabor"return" return (RETURN); 138202719Sgabor"scale" return (SCALE); 139202719Sgabor"sqrt" return (SQRT); 140202719Sgabor"while" return (WHILE); 141202719Sgabor 142202719Sgabor"^" return (EXPONENT); 143202719Sgabor"*" return (MULTIPLY); 144202719Sgabor"/" return (DIVIDE); 145202719Sgabor"%" return (REMAINDER); 146202719Sgabor 147202719Sgabor"!" return (BOOL_NOT); 148202719Sgabor"&&" return (BOOL_AND); 149202719Sgabor"||" return (BOOL_OR); 150202719Sgabor 151202719Sgabor"+" return (PLUS); 152202719Sgabor"-" return (MINUS); 153202719Sgabor 154202719Sgabor"++" return (INCR); 155202719Sgabor"--" return (DECR); 156202719Sgabor 157202719Sgabor"=" yylval.str = ""; return (ASSIGN_OP); 158202719Sgabor"+=" yylval.str = "+"; return (ASSIGN_OP); 159202719Sgabor"-=" yylval.str = "-"; return (ASSIGN_OP); 160202719Sgabor"*=" yylval.str = "*"; return (ASSIGN_OP); 161202719Sgabor"/=" yylval.str = "/"; return (ASSIGN_OP); 162202719Sgabor"%=" yylval.str = "%"; return (ASSIGN_OP); 163202719Sgabor"^=" yylval.str = "^"; return (ASSIGN_OP); 164202719Sgabor 165202719Sgabor"==" return (EQUALS); 166202719Sgabor"<=" return (LESS_EQ); 167202719Sgabor">=" return (GREATER_EQ); 168202719Sgabor"!=" return (UNEQUALS); 169202719Sgabor"<" return (LESS); 170202719Sgabor">" return (GREATER); 171202719Sgabor 172202719Sgabor"," return (COMMA); 173202719Sgabor";" return (SEMICOLON); 174202719Sgabor 175202719Sgabor"(" return (LPAR); 176202719Sgabor")" return (RPAR); 177202719Sgabor 178202719Sgabor"[" return (LBRACKET); 179202719Sgabor"]" return (RBRACKET); 180202719Sgabor 181202719Sgabor"{" return (LBRACE); 182202719Sgabor"}" return (RBRACE); 183202719Sgabor 184202719Sgabor{ALPHA}{ALPHANUM}* { 185202719Sgabor /* alloc an extra byte for the type marker */ 186202719Sgabor char *p = malloc(yyleng + 2); 187202719Sgabor if (p == NULL) 188202719Sgabor err(1, NULL); 189202719Sgabor strlcpy(p, yytext, yyleng + 1); 190202719Sgabor yylval.astr = p; 191202719Sgabor return (LETTER); 192202719Sgabor } 193202719Sgabor 194202719Sgabor\\\n lineno++; 195202719Sgabor\n lineno++; return (NEWLINE); 196202719Sgabor 197202719Sgabor#[^\n]* ; 198202719Sgabor[ \t] ; 199202719Sgabor<<EOF>> return (QUIT); 200202719Sgabor. yyerror("illegal character"); 201202719Sgabor 202202719Sgabor%% 203202719Sgabor 204202719Sgaborstatic void 205202719Sgaborinit_strbuf(void) 206202719Sgabor{ 207203443Sgabor 208202719Sgabor if (strbuf == NULL) { 209202719Sgabor strbuf = malloc(strbuf_sz); 210202719Sgabor if (strbuf == NULL) 211202719Sgabor err(1, NULL); 212202719Sgabor } 213202719Sgabor strbuf[0] = '\0'; 214202719Sgabor} 215202719Sgabor 216202719Sgaborstatic void 217202719Sgaboradd_str(const char *str) 218202719Sgabor{ 219203443Sgabor size_t arglen; 220202719Sgabor 221202719Sgabor arglen = strlen(str); 222202719Sgabor 223202719Sgabor if (strlen(strbuf) + arglen + 1 > strbuf_sz) { 224202719Sgabor size_t newsize; 225202719Sgabor char *p; 226202719Sgabor 227202719Sgabor newsize = strbuf_sz + arglen + 1; 228202719Sgabor p = realloc(strbuf, newsize); 229202719Sgabor if (p == NULL) { 230202719Sgabor free(strbuf); 231202719Sgabor err(1, NULL); 232202719Sgabor } 233202719Sgabor strbuf_sz = newsize; 234202719Sgabor strbuf = p; 235202719Sgabor } 236202719Sgabor strlcat(strbuf, str, strbuf_sz); 237202719Sgabor} 238202719Sgabor 239202719Sgaborint 240202719Sgaboryywrap(void) 241202719Sgabor{ 242203443Sgabor static YY_BUFFER_STATE buf; 243203443Sgabor static int state; 244202719Sgabor 245202719Sgabor if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) { 246202719Sgabor filename = sargv[fileindex++]; 247202719Sgabor yyin = fopen(filename, "r"); 248202719Sgabor lineno = 1; 249202719Sgabor if (yyin == NULL) 250202719Sgabor err(1, "cannot open %s", filename); 251202719Sgabor return (0); 252202719Sgabor } 253202719Sgabor if (state == 0 && cmdexpr[0] != '\0') { 254202719Sgabor buf = yy_scan_string(cmdexpr); 255202719Sgabor state++; 256202719Sgabor lineno = 1; 257202719Sgabor filename = "command line"; 258202719Sgabor return (0); 259202719Sgabor } else if (state == 1) { 260202719Sgabor yy_delete_buffer(buf); 261202719Sgabor free(cmdexpr); 262202719Sgabor state++; 263202719Sgabor } 264202719Sgabor if (yyin != NULL && yyin != stdin) 265202719Sgabor fclose(yyin); 266202719Sgabor if (fileindex < sargc) { 267202719Sgabor filename = sargv[fileindex++]; 268202719Sgabor yyin = fopen(filename, "r"); 269202719Sgabor lineno = 1; 270202719Sgabor if (yyin == NULL) 271202719Sgabor err(1, "cannot open %s", filename); 272202719Sgabor return (0); 273202719Sgabor } else if (fileindex == sargc) { 274202719Sgabor fileindex++; 275202719Sgabor yyin = stdin; 276202719Sgabor lineno = 1; 277202719Sgabor filename = "stdin"; 278202719Sgabor return (0); 279202719Sgabor } 280202719Sgabor return (1); 281202719Sgabor} 282203498Sdelphij 283203498Sdelphijstatic int 284203498Sdelphijbc_yyinput(char *buf, int maxlen) 285203498Sdelphij{ 286203498Sdelphij int num; 287203531Sdelphij if (yyin == stdin && interactive) { 288203498Sdelphij const char *bp; 289203498Sdelphij 290203498Sdelphij if ((bp = el_gets(el, &num)) == NULL || num == 0) 291203498Sdelphij return (0); 292203498Sdelphij if (num > maxlen) { 293203498Sdelphij el_push(el, (char *)(uintptr_t)(bp) + maxlen); 294203498Sdelphij num = maxlen; 295203498Sdelphij } 296203498Sdelphij memcpy(buf, bp, num); 297203498Sdelphij history(hist, &he, H_ENTER, bp); 298203498Sdelphij } else { 299203498Sdelphij int c = '*'; 300203498Sdelphij for (num = 0; num < maxlen && 301203498Sdelphij (c = getc(yyin)) != EOF && c != '\n'; ++num) 302203498Sdelphij buf[num] = (char) c; 303203498Sdelphij if (c == '\n') 304203498Sdelphij buf[num++] = (char) c; 305203498Sdelphij if (c == EOF && ferror(yyin)) 306203498Sdelphij YY_FATAL_ERROR( "input in flex scanner failed" ); 307203498Sdelphij } 308203498Sdelphij return (num); 309203498Sdelphij} 310203498Sdelphij 311