scan.l (256281) | scan.l (265533) |
---|---|
1%{ | 1%{ |
2/* $OpenBSD: scan.l,v 1.23 2009/10/27 23:59:36 deraadt Exp $ */ | 2/* $OpenBSD: scan.l,v 1.28 2013/09/19 16:12:01 otto 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> | 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: stable/10/usr.bin/bc/scan.l 250926 2013-05-23 05:42:35Z jkim $"); | 21__FBSDID("$FreeBSD: stable/10/usr.bin/bc/scan.l 265533 2014-05-07 08:06:54Z delphij $"); |
22 23#include <err.h> 24#include <errno.h> 25#include <histedit.h> 26#include <stdbool.h> | 22 23#include <err.h> 24#include <errno.h> 25#include <histedit.h> 26#include <stdbool.h> |
27#include <signal.h> |
|
27#include <string.h> 28#include <unistd.h> 29 30#include "extern.h" 31#include "bc.h" 32#include "pathnames.h" 33 | 28#include <string.h> 29#include <unistd.h> 30 31#include "extern.h" 32#include "bc.h" 33#include "pathnames.h" 34 |
34int lineno; | 35int lineno; 36bool interactive; |
35 | 37 |
36bool interactive; | |
37HistEvent he; 38EditLine *el; 39History *hist; 40 41static char *strbuf = NULL; | 38HistEvent he; 39EditLine *el; 40History *hist; 41 42static char *strbuf = NULL; |
42static size_t strbuf_sz = 1; 43static bool dot_seen; | 43static size_t strbuf_sz = 1; 44static bool dot_seen; 45static int use_el; 46static volatile sig_atomic_t skipchars; |
44 | 47 |
45static void init_strbuf(void); 46static void add_str(const char *); | 48static void init_strbuf(void); 49static void add_str(const char *); 50 |
47static int bc_yyinput(char *, int); 48 49#define YY_DECL int yylex(void) 50#define YY_NO_INPUT 51#undef YY_INPUT 52#define YY_INPUT(buf,retval,max) \ 53 (retval = bc_yyinput(buf, max)) | 51static int bc_yyinput(char *, int); 52 53#define YY_DECL int yylex(void) 54#define YY_NO_INPUT 55#undef YY_INPUT 56#define YY_INPUT(buf,retval,max) \ 57 (retval = bc_yyinput(buf, max)) |
58 |
|
54%} 55 56%option always-interactive 57 58DIGIT [0-9A-F] 59ALPHA [a-z_] 60ALPHANUM [a-z_0-9] 61 --- 35 unchanged lines hidden (view full) --- 97 } 98<number>{ 99 {DIGIT}+ add_str(yytext); 100 \. { 101 if (dot_seen) { 102 BEGIN(INITIAL); 103 yylval.str = strbuf; 104 unput('.'); | 59%} 60 61%option always-interactive 62 63DIGIT [0-9A-F] 64ALPHA [a-z_] 65ALPHANUM [a-z_0-9] 66 --- 35 unchanged lines hidden (view full) --- 102 } 103<number>{ 104 {DIGIT}+ add_str(yytext); 105 \. { 106 if (dot_seen) { 107 BEGIN(INITIAL); 108 yylval.str = strbuf; 109 unput('.'); |
105 return (NUMBER); | 110 return NUMBER; |
106 } else { 107 dot_seen = true; 108 add_str("."); 109 } 110 } 111 \\\n[ \t]* lineno++; 112 [^0-9A-F\.] { 113 BEGIN(INITIAL); 114 unput(yytext[0]); 115 if (strcmp(strbuf, ".") == 0) | 111 } else { 112 dot_seen = true; 113 add_str("."); 114 } 115 } 116 \\\n[ \t]* lineno++; 117 [^0-9A-F\.] { 118 BEGIN(INITIAL); 119 unput(yytext[0]); 120 if (strcmp(strbuf, ".") == 0) |
116 return (DOT); | 121 return DOT; |
117 else { 118 yylval.str = strbuf; | 122 else { 123 yylval.str = strbuf; |
119 return (NUMBER); | 124 return NUMBER; |
120 } 121 } 122} 123 | 125 } 126 } 127} 128 |
124"auto" return (AUTO); 125"break" return (BREAK); 126"continue" return (CONTINUE); 127"define" return (DEFINE); 128"else" return (ELSE); 129"ibase" return (IBASE); 130"if" return (IF); 131"last" return (DOT); 132"for" return (FOR); 133"length" return (LENGTH); 134"obase" return (OBASE); 135"print" return (PRINT); 136"quit" return (QUIT); 137"return" return (RETURN); 138"scale" return (SCALE); 139"sqrt" return (SQRT); 140"while" return (WHILE); | 129"auto" return AUTO; 130"break" return BREAK; 131"continue" return CONTINUE; 132"define" return DEFINE; 133"else" return ELSE; 134"ibase" return IBASE; 135"if" return IF; 136"last" return DOT; 137"for" return FOR; 138"length" return LENGTH; 139"obase" return OBASE; 140"print" return PRINT; 141"quit" return QUIT; 142"return" return RETURN; 143"scale" return SCALE; 144"sqrt" return SQRT; 145"while" return WHILE; |
141 | 146 |
142"^" return (EXPONENT); 143"*" return (MULTIPLY); 144"/" return (DIVIDE); 145"%" return (REMAINDER); | 147"^" return EXPONENT; 148"*" return MULTIPLY; 149"/" return DIVIDE; 150"%" return REMAINDER; |
146 | 151 |
147"!" return (BOOL_NOT); 148"&&" return (BOOL_AND); 149"||" return (BOOL_OR); | 152"!" return BOOL_NOT; 153"&&" return BOOL_AND; 154"||" return BOOL_OR; |
150 | 155 |
151"+" return (PLUS); 152"-" return (MINUS); | 156"+" return PLUS; 157"-" return MINUS; |
153 | 158 |
154"++" return (INCR); 155"--" return (DECR); | 159"++" return INCR; 160"--" return DECR; |
156 | 161 |
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"%=" yylval.str = "%"; return (ASSIGN_OP); 163"^=" yylval.str = "^"; return (ASSIGN_OP); | 162"=" yylval.str = ""; return ASSIGN_OP; 163"+=" yylval.str = "+"; return ASSIGN_OP; 164"-=" yylval.str = "-"; return ASSIGN_OP; 165"*=" yylval.str = "*"; return ASSIGN_OP; 166"/=" yylval.str = "/"; return ASSIGN_OP; 167"%=" yylval.str = "%"; return ASSIGN_OP; 168"^=" yylval.str = "^"; return ASSIGN_OP; |
164 | 169 |
165"==" return (EQUALS); 166"<=" return (LESS_EQ); 167">=" return (GREATER_EQ); 168"!=" return (UNEQUALS); 169"<" return (LESS); 170">" return (GREATER); | 170"==" return EQUALS; 171"<=" return LESS_EQ; 172">=" return GREATER_EQ; 173"!=" return UNEQUALS; 174"<" return LESS; 175">" return GREATER; |
171 | 176 |
172"," return (COMMA); 173";" return (SEMICOLON); | 177"," return COMMA; 178";" return SEMICOLON; |
174 | 179 |
175"(" return (LPAR); 176")" return (RPAR); | 180"(" return LPAR; 181")" return RPAR; |
177 | 182 |
178"[" return (LBRACKET); 179"]" return (RBRACKET); | 183"[" return LBRACKET; 184"]" return RBRACKET; |
180 | 185 |
181"{" return (LBRACE); 182"}" return (RBRACE); | 186"{" return LBRACE; 187"}" return RBRACE; |
183 184{ALPHA}{ALPHANUM}* { 185 /* alloc an extra byte for the type marker */ 186 char *p = malloc(yyleng + 2); 187 if (p == NULL) 188 err(1, NULL); 189 strlcpy(p, yytext, yyleng + 1); 190 yylval.astr = p; | 188 189{ALPHA}{ALPHANUM}* { 190 /* alloc an extra byte for the type marker */ 191 char *p = malloc(yyleng + 2); 192 if (p == NULL) 193 err(1, NULL); 194 strlcpy(p, yytext, yyleng + 1); 195 yylval.astr = p; |
191 return (LETTER); | 196 return LETTER; |
192 } 193 194\\\n lineno++; | 197 } 198 199\\\n lineno++; |
195\n lineno++; return (NEWLINE); | 200\n lineno++; return NEWLINE; |
196 197#[^\n]* ; 198[ \t] ; | 201 202#[^\n]* ; 203[ \t] ; |
199<<EOF>> return (QUIT); | 204<<EOF>> return QUIT; |
200. yyerror("illegal character"); 201 202%% 203 204static void 205init_strbuf(void) 206{ | 205. yyerror("illegal character"); 206 207%% 208 209static void 210init_strbuf(void) 211{ |
207 | |
208 if (strbuf == NULL) { 209 strbuf = malloc(strbuf_sz); 210 if (strbuf == NULL) 211 err(1, NULL); 212 } 213 strbuf[0] = '\0'; 214} 215 216static void 217add_str(const char *str) 218{ 219 size_t arglen; 220 221 arglen = strlen(str); 222 223 if (strlen(strbuf) + arglen + 1 > strbuf_sz) { | 212 if (strbuf == NULL) { 213 strbuf = malloc(strbuf_sz); 214 if (strbuf == NULL) 215 err(1, NULL); 216 } 217 strbuf[0] = '\0'; 218} 219 220static void 221add_str(const char *str) 222{ 223 size_t arglen; 224 225 arglen = strlen(str); 226 227 if (strlen(strbuf) + arglen + 1 > strbuf_sz) { |
224 size_t newsize; 225 char *p; | 228 size_t newsize; 229 char *p; |
226 227 newsize = strbuf_sz + arglen + 1; 228 p = realloc(strbuf, newsize); 229 if (p == NULL) { 230 free(strbuf); 231 err(1, NULL); 232 } 233 strbuf_sz = newsize; 234 strbuf = p; 235 } 236 strlcat(strbuf, str, strbuf_sz); 237} 238 | 230 231 newsize = strbuf_sz + arglen + 1; 232 p = realloc(strbuf, newsize); 233 if (p == NULL) { 234 free(strbuf); 235 err(1, NULL); 236 } 237 strbuf_sz = newsize; 238 strbuf = p; 239 } 240 strlcat(strbuf, str, strbuf_sz); 241} 242 |
243/* ARGSUSED */ 244void 245abort_line(int sig __unused) 246{ 247 static const char str1[] = "[\n]P\n"; 248 static const char str2[] = "[^C\n]P\n"; 249 int save_errno; 250 const LineInfo *info; 251 252 save_errno = errno; 253 if (use_el) { 254 write(STDOUT_FILENO, str2, sizeof(str2) - 1); 255 info = el_line(el); 256 skipchars = info->lastchar - info->buffer; 257 } else 258 write(STDOUT_FILENO, str1, sizeof(str1) - 1); 259 errno = save_errno; 260} 261 262/* 263 * Avoid the echo of ^D by the default code of editline and take 264 * into account skipchars to make ^D work when the cursor is at start of 265 * line after a ^C. 266 */ 267unsigned char 268bc_eof(EditLine *e, int ch __unused) 269{ 270 const struct lineinfo *info = el_line(e); 271 272 if (info->buffer + skipchars == info->cursor && 273 info->cursor == info->lastchar) 274 return (CC_EOF); 275 else 276 return (CC_ERROR); 277} 278 |
|
239int 240yywrap(void) 241{ | 279int 280yywrap(void) 281{ |
242 static YY_BUFFER_STATE buf; | |
243 static int state; | 282 static int state; |
283 static YY_BUFFER_STATE buf; |
|
244 245 if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) { 246 filename = sargv[fileindex++]; 247 yyin = fopen(filename, "r"); 248 lineno = 1; 249 if (yyin == NULL) 250 err(1, "cannot open %s", filename); 251 return (0); --- 16 unchanged lines hidden (view full) --- 268 yyin = fopen(filename, "r"); 269 lineno = 1; 270 if (yyin == NULL) 271 err(1, "cannot open %s", filename); 272 return (0); 273 } else if (fileindex == sargc) { 274 fileindex++; 275 yyin = stdin; | 284 285 if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) { 286 filename = sargv[fileindex++]; 287 yyin = fopen(filename, "r"); 288 lineno = 1; 289 if (yyin == NULL) 290 err(1, "cannot open %s", filename); 291 return (0); --- 16 unchanged lines hidden (view full) --- 308 yyin = fopen(filename, "r"); 309 lineno = 1; 310 if (yyin == NULL) 311 err(1, "cannot open %s", filename); 312 return (0); 313 } else if (fileindex == sargc) { 314 fileindex++; 315 yyin = stdin; |
316 if (interactive) { 317 signal(SIGINT, abort_line); 318 signal(SIGTSTP, tstpcont); 319 } |
|
276 lineno = 1; 277 filename = "stdin"; 278 return (0); 279 } 280 return (1); 281} 282 283static int 284bc_yyinput(char *buf, int maxlen) 285{ 286 int num; | 320 lineno = 1; 321 filename = "stdin"; 322 return (0); 323 } 324 return (1); 325} 326 327static int 328bc_yyinput(char *buf, int maxlen) 329{ 330 int num; |
287 if (yyin == stdin && interactive) { | 331 332 if (el != NULL) 333 el_get(el, EL_EDITMODE, &use_el); 334 335 if (yyin == stdin && interactive && use_el) { |
288 const char *bp; | 336 const char *bp; |
337 sigset_t oset, nset; |
|
289 290 if ((bp = el_gets(el, &num)) == NULL || num == 0) 291 return (0); | 338 339 if ((bp = el_gets(el, &num)) == NULL || num == 0) 340 return (0); |
341 sigemptyset(&nset); 342 sigaddset(&nset, SIGINT); 343 sigprocmask(SIG_BLOCK, &nset, &oset); 344 if (skipchars < num) { 345 bp += skipchars; 346 num -= skipchars; 347 } 348 skipchars = 0; 349 sigprocmask(SIG_SETMASK, &oset, NULL); |
|
292 if (num > maxlen) { | 350 if (num > maxlen) { |
293 el_push(el, (char *)(uintptr_t)(bp) + maxlen); | 351 el_push(el, bp + maxlen); |
294 num = maxlen; 295 } 296 memcpy(buf, bp, num); 297 history(hist, &he, H_ENTER, bp); | 352 num = maxlen; 353 } 354 memcpy(buf, bp, num); 355 history(hist, &he, H_ENTER, bp); |
356 el_get(el, EL_EDITMODE, &use_el); |
|
298 } else { 299 int c = '*'; 300 for (num = 0; num < maxlen && 301 (c = getc(yyin)) != EOF && c != '\n'; ++num) 302 buf[num] = (char) c; 303 if (c == '\n') 304 buf[num++] = (char) c; 305 if (c == EOF && ferror(yyin)) 306 YY_FATAL_ERROR( "input in flex scanner failed" ); 307 } 308 return (num); 309} 310 | 357 } else { 358 int c = '*'; 359 for (num = 0; num < maxlen && 360 (c = getc(yyin)) != EOF && c != '\n'; ++num) 361 buf[num] = (char) c; 362 if (c == '\n') 363 buf[num++] = (char) c; 364 if (c == EOF && ferror(yyin)) 365 YY_FATAL_ERROR( "input in flex scanner failed" ); 366 } 367 return (num); 368} 369 |
370 |
|