scan.l revision 252181
1163976Sdougb%{ 2135446Strhodes/* $OpenBSD: scan.l,v 1.23 2009/10/27 23:59:36 deraadt Exp $ */ 3135446Strhodes 4135446Strhodes/* 5135446Strhodes * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net> 6135446Strhodes * 7135446Strhodes * Permission to use, copy, modify, and distribute this software for any 8135446Strhodes * purpose with or without fee is hereby granted, provided that the above 9135446Strhodes * copyright notice and this permission notice appear in all copies. 10135446Strhodes * 11135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12135446Strhodes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13135446Strhodes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14135446Strhodes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15135446Strhodes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16135446Strhodes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17135446Strhodes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18135446Strhodes */ 19135446Strhodes 20135446Strhodes#include <sys/cdefs.h> 21163976Sdougb__FBSDID("$FreeBSD: stable/9/usr.bin/bc/scan.l 252181 2013-06-24 21:33:19Z marius $"); 22135446Strhodes 23135446Strhodes#include <err.h> 24135446Strhodes#include <errno.h> 25135446Strhodes#include <histedit.h> 26135446Strhodes#include <stdbool.h> 27135446Strhodes#include <string.h> 28135446Strhodes#include <unistd.h> 29135446Strhodes 30135446Strhodes#include "extern.h" 31135446Strhodes#include "bc.h" 32135446Strhodes#include "pathnames.h" 33135446Strhodes 34135446Strhodesint lineno; 35135446Strhodes 36135446Strhodesbool interactive; 37135446StrhodesHistEvent he; 38135446StrhodesEditLine *el; 39135446StrhodesHistory *hist; 40135446Strhodes 41135446Strhodesstatic char *strbuf = NULL; 42135446Strhodesstatic size_t strbuf_sz = 1; 43135446Strhodesstatic bool dot_seen; 44135446Strhodes 45135446Strhodesstatic void init_strbuf(void); 46135446Strhodesstatic void add_str(const char *); 47135446Strhodesstatic int bc_yyinput(char *, int); 48135446Strhodes 49135446Strhodes#define YY_DECL int yylex(void) 50135446Strhodes#define YY_NO_INPUT 51135446Strhodes#undef YY_INPUT 52135446Strhodes#define YY_INPUT(buf,retval,max) \ 53135446Strhodes (retval = bc_yyinput(buf, max)) 54135446Strhodes%} 55135446Strhodes 56135446Strhodes%option always-interactive 57135446Strhodes 58135446StrhodesDIGIT [0-9A-F] 59135446StrhodesALPHA [a-z_] 60135446StrhodesALPHANUM [a-z_0-9] 61135446Strhodes 62135446Strhodes%x comment string number 63135446Strhodes 64135446Strhodes%% 65135446Strhodes 66135446Strhodes"/*" BEGIN(comment); 67135446Strhodes<comment>{ 68135446Strhodes "*/" BEGIN(INITIAL); 69135446Strhodes \n lineno++; 70135446Strhodes \* ; 71135446Strhodes [^*\n]+ ; 72135446Strhodes <<EOF>> fatal("end of file in comment"); 73135446Strhodes} 74135446Strhodes 75135446Strhodes\" BEGIN(string); init_strbuf(); 76135446Strhodes<string>{ 77135446Strhodes [^"\n\\\[\]]+ add_str(yytext); 78135446Strhodes \[ add_str("\\["); 79135446Strhodes \] add_str("\\]"); 80135446Strhodes \\ add_str("\\\\"); 81135446Strhodes \n add_str("\n"); lineno++; 82135446Strhodes \" BEGIN(INITIAL); yylval.str = strbuf; return STRING; 83135446Strhodes <<EOF>> fatal("end of file in string"); 84135446Strhodes} 85135446Strhodes 86135446Strhodes{DIGIT}+ { 87135446Strhodes BEGIN(number); 88135446Strhodes dot_seen = false; 89135446Strhodes init_strbuf(); 90135446Strhodes add_str(yytext); 91135446Strhodes } 92135446Strhodes\. { 93135446Strhodes BEGIN(number); 94135446Strhodes dot_seen = true; 95135446Strhodes init_strbuf(); 96135446Strhodes add_str("."); 97135446Strhodes } 98135446Strhodes<number>{ 99135446Strhodes {DIGIT}+ add_str(yytext); 100135446Strhodes \. { 101135446Strhodes if (dot_seen) { 102135446Strhodes BEGIN(INITIAL); 103135446Strhodes yylval.str = strbuf; 104135446Strhodes unput('.'); 105135446Strhodes return (NUMBER); 106135446Strhodes } else { 107135446Strhodes dot_seen = true; 108135446Strhodes add_str("."); 109135446Strhodes } 110135446Strhodes } 111135446Strhodes \\\n[ \t]* lineno++; 112135446Strhodes [^0-9A-F\.] { 113135446Strhodes BEGIN(INITIAL); 114135446Strhodes unput(yytext[0]); 115135446Strhodes if (strcmp(strbuf, ".") == 0) 116135446Strhodes return (DOT); 117135446Strhodes else { 118135446Strhodes yylval.str = strbuf; 119135446Strhodes return (NUMBER); 120135446Strhodes } 121135446Strhodes } 122135446Strhodes} 123135446Strhodes 124135446Strhodes"auto" return (AUTO); 125135446Strhodes"break" return (BREAK); 126135446Strhodes"continue" return (CONTINUE); 127135446Strhodes"define" return (DEFINE); 128135446Strhodes"else" return (ELSE); 129135446Strhodes"ibase" return (IBASE); 130135446Strhodes"if" return (IF); 131135446Strhodes"last" return (DOT); 132135446Strhodes"for" return (FOR); 133135446Strhodes"length" return (LENGTH); 134135446Strhodes"obase" return (OBASE); 135135446Strhodes"print" return (PRINT); 136135446Strhodes"quit" return (QUIT); 137135446Strhodes"return" return (RETURN); 138135446Strhodes"scale" return (SCALE); 139135446Strhodes"sqrt" return (SQRT); 140135446Strhodes"while" return (WHILE); 141135446Strhodes 142135446Strhodes"^" return (EXPONENT); 143135446Strhodes"*" return (MULTIPLY); 144135446Strhodes"/" return (DIVIDE); 145135446Strhodes"%" return (REMAINDER); 146135446Strhodes 147135446Strhodes"!" return (BOOL_NOT); 148135446Strhodes"&&" return (BOOL_AND); 149135446Strhodes"||" return (BOOL_OR); 150135446Strhodes 151135446Strhodes"+" return (PLUS); 152135446Strhodes"-" return (MINUS); 153135446Strhodes 154135446Strhodes"++" return (INCR); 155135446Strhodes"--" return (DECR); 156135446Strhodes 157135446Strhodes"=" yylval.str = ""; return (ASSIGN_OP); 158135446Strhodes"+=" yylval.str = "+"; return (ASSIGN_OP); 159135446Strhodes"-=" yylval.str = "-"; return (ASSIGN_OP); 160135446Strhodes"*=" yylval.str = "*"; return (ASSIGN_OP); 161135446Strhodes"/=" yylval.str = "/"; return (ASSIGN_OP); 162135446Strhodes"%=" yylval.str = "%"; return (ASSIGN_OP); 163135446Strhodes"^=" yylval.str = "^"; return (ASSIGN_OP); 164135446Strhodes 165135446Strhodes"==" return (EQUALS); 166135446Strhodes"<=" return (LESS_EQ); 167135446Strhodes">=" return (GREATER_EQ); 168135446Strhodes"!=" return (UNEQUALS); 169135446Strhodes"<" return (LESS); 170135446Strhodes">" return (GREATER); 171135446Strhodes 172135446Strhodes"," return (COMMA); 173135446Strhodes";" return (SEMICOLON); 174135446Strhodes 175135446Strhodes"(" return (LPAR); 176135446Strhodes")" return (RPAR); 177135446Strhodes 178135446Strhodes"[" return (LBRACKET); 179135446Strhodes"]" return (RBRACKET); 180135446Strhodes 181135446Strhodes"{" return (LBRACE); 182135446Strhodes"}" return (RBRACE); 183135446Strhodes 184135446Strhodes{ALPHA}{ALPHANUM}* { 185135446Strhodes /* alloc an extra byte for the type marker */ 186135446Strhodes char *p = malloc(yyleng + 2); 187135446Strhodes if (p == NULL) 188135446Strhodes err(1, NULL); 189135446Strhodes strlcpy(p, yytext, yyleng + 1); 190135446Strhodes yylval.astr = p; 191135446Strhodes return (LETTER); 192135446Strhodes } 193135446Strhodes 194135446Strhodes\\\n lineno++; 195135446Strhodes\n lineno++; return (NEWLINE); 196135446Strhodes 197135446Strhodes#[^\n]* ; 198135446Strhodes[ \t] ; 199135446Strhodes<<EOF>> return (QUIT); 200135446Strhodes. yyerror("illegal character"); 201135446Strhodes 202135446Strhodes%% 203135446Strhodes 204135446Strhodesstatic void 205135446Strhodesinit_strbuf(void) 206135446Strhodes{ 207135446Strhodes 208135446Strhodes if (strbuf == NULL) { 209135446Strhodes strbuf = malloc(strbuf_sz); 210135446Strhodes if (strbuf == NULL) 211135446Strhodes err(1, NULL); 212135446Strhodes } 213135446Strhodes strbuf[0] = '\0'; 214135446Strhodes} 215135446Strhodes 216135446Strhodesstatic void 217135446Strhodesadd_str(const char *str) 218135446Strhodes{ 219135446Strhodes size_t arglen; 220135446Strhodes 221135446Strhodes arglen = strlen(str); 222135446Strhodes 223135446Strhodes if (strlen(strbuf) + arglen + 1 > strbuf_sz) { 224135446Strhodes size_t newsize; 225135446Strhodes char *p; 226135446Strhodes 227135446Strhodes newsize = strbuf_sz + arglen + 1; 228135446Strhodes p = realloc(strbuf, newsize); 229135446Strhodes if (p == NULL) { 230135446Strhodes free(strbuf); 231135446Strhodes err(1, NULL); 232135446Strhodes } 233135446Strhodes strbuf_sz = newsize; 234135446Strhodes strbuf = p; 235135446Strhodes } 236135446Strhodes strlcat(strbuf, str, strbuf_sz); 237135446Strhodes} 238135446Strhodes 239135446Strhodesint 240135446Strhodesyywrap(void) 241135446Strhodes{ 242135446Strhodes static YY_BUFFER_STATE buf; 243135446Strhodes static int state; 244135446Strhodes 245135446Strhodes if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) { 246135446Strhodes filename = sargv[fileindex++]; 247135446Strhodes yyin = fopen(filename, "r"); 248135446Strhodes lineno = 1; 249135446Strhodes if (yyin == NULL) 250135446Strhodes err(1, "cannot open %s", filename); 251135446Strhodes return (0); 252135446Strhodes } 253135446Strhodes if (state == 0 && cmdexpr[0] != '\0') { 254135446Strhodes buf = yy_scan_string(cmdexpr); 255135446Strhodes state++; 256135446Strhodes lineno = 1; 257135446Strhodes filename = "command line"; 258135446Strhodes return (0); 259135446Strhodes } else if (state == 1) { 260135446Strhodes yy_delete_buffer(buf); 261135446Strhodes free(cmdexpr); 262135446Strhodes state++; 263135446Strhodes } 264153816Sdougb if (yyin != NULL && yyin != stdin) 265143731Sdougb fclose(yyin); 266143731Sdougb if (fileindex < sargc) { 267143731Sdougb filename = sargv[fileindex++]; 268143731Sdougb yyin = fopen(filename, "r"); 269143731Sdougb lineno = 1; 270143731Sdougb if (yyin == NULL) 271143731Sdougb err(1, "cannot open %s", filename); 272143731Sdougb return (0); 273143731Sdougb } else if (fileindex == sargc) { 274143731Sdougb fileindex++; 275143731Sdougb yyin = stdin; 276143731Sdougb lineno = 1; 277143731Sdougb filename = "stdin"; 278143731Sdougb return (0); 279143731Sdougb } 280143731Sdougb return (1); 281143731Sdougb} 282135446Strhodes 283135446Strhodesstatic int 284135446Strhodesbc_yyinput(char *buf, int maxlen) 285135446Strhodes{ 286135446Strhodes int num; 287135446Strhodes if (yyin == stdin && interactive) { 288135446Strhodes const char *bp; 289135446Strhodes 290135446Strhodes if ((bp = el_gets(el, &num)) == NULL || num == 0) 291135446Strhodes return (0); 292135446Strhodes if (num > maxlen) { 293135446Strhodes el_push(el, (char *)(uintptr_t)(bp) + maxlen); 294135446Strhodes num = maxlen; 295135446Strhodes } 296135446Strhodes memcpy(buf, bp, num); 297135446Strhodes history(hist, &he, H_ENTER, bp); 298135446Strhodes } else { 299135446Strhodes int c = '*'; 300135446Strhodes for (num = 0; num < maxlen && 301135446Strhodes (c = getc(yyin)) != EOF && c != '\n'; ++num) 302135446Strhodes buf[num] = (char) c; 303135446Strhodes if (c == '\n') 304135446Strhodes buf[num++] = (char) c; 305135446Strhodes if (c == EOF && ferror(yyin)) 306135446Strhodes YY_FATAL_ERROR( "input in flex scanner failed" ); 307135446Strhodes } 308135446Strhodes return (num); 309135446Strhodes} 310135446Strhodes 311135446Strhodes