diff options
author | delphij <delphij@FreeBSD.org> | 2014-05-07 08:06:54 +0000 |
---|---|---|
committer | delphij <delphij@FreeBSD.org> | 2014-05-07 08:06:54 +0000 |
commit | ebef83dbd2b82b4ddf471e1d2b423eef86ccf414 (patch) | |
tree | 10b2f68e28cd9e992a4ec257c552c27e4588d64c /usr.bin/bc/scan.l | |
parent | d6c003e92088f30bee1dd2cb9013d5686ad0de3d (diff) | |
download | FreeBSD-src-ebef83dbd2b82b4ddf471e1d2b423eef86ccf414.zip FreeBSD-src-ebef83dbd2b82b4ddf471e1d2b423eef86ccf414.tar.gz |
MFC r264573+264608+264609:
Sync with OpenBSD.
Diffstat (limited to 'usr.bin/bc/scan.l')
-rw-r--r-- | usr.bin/bc/scan.l | 216 |
1 files changed, 138 insertions, 78 deletions
diff --git a/usr.bin/bc/scan.l b/usr.bin/bc/scan.l index 71cb295..cb1977a 100644 --- a/usr.bin/bc/scan.l +++ b/usr.bin/bc/scan.l @@ -1,5 +1,5 @@ %{ -/* $OpenBSD: scan.l,v 1.23 2009/10/27 23:59:36 deraadt Exp $ */ +/* $OpenBSD: scan.l,v 1.28 2013/09/19 16:12:01 otto Exp $ */ /* * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net> @@ -24,6 +24,7 @@ __FBSDID("$FreeBSD$"); #include <errno.h> #include <histedit.h> #include <stdbool.h> +#include <signal.h> #include <string.h> #include <unistd.h> @@ -31,19 +32,22 @@ __FBSDID("$FreeBSD$"); #include "bc.h" #include "pathnames.h" -int lineno; +int lineno; +bool interactive; -bool interactive; HistEvent he; EditLine *el; History *hist; static char *strbuf = NULL; -static size_t strbuf_sz = 1; -static bool dot_seen; +static size_t strbuf_sz = 1; +static bool dot_seen; +static int use_el; +static volatile sig_atomic_t skipchars; + +static void init_strbuf(void); +static void add_str(const char *); -static void init_strbuf(void); -static void add_str(const char *); static int bc_yyinput(char *, int); #define YY_DECL int yylex(void) @@ -51,6 +55,7 @@ static int bc_yyinput(char *, int); #undef YY_INPUT #define YY_INPUT(buf,retval,max) \ (retval = bc_yyinput(buf, max)) + %} %option always-interactive @@ -102,7 +107,7 @@ ALPHANUM [a-z_0-9] BEGIN(INITIAL); yylval.str = strbuf; unput('.'); - return (NUMBER); + return NUMBER; } else { dot_seen = true; add_str("."); @@ -113,73 +118,73 @@ ALPHANUM [a-z_0-9] BEGIN(INITIAL); unput(yytext[0]); if (strcmp(strbuf, ".") == 0) - return (DOT); + return DOT; else { yylval.str = strbuf; - return (NUMBER); + return NUMBER; } } } -"auto" return (AUTO); -"break" return (BREAK); -"continue" return (CONTINUE); -"define" return (DEFINE); -"else" return (ELSE); -"ibase" return (IBASE); -"if" return (IF); -"last" return (DOT); -"for" return (FOR); -"length" return (LENGTH); -"obase" return (OBASE); -"print" return (PRINT); -"quit" return (QUIT); -"return" return (RETURN); -"scale" return (SCALE); -"sqrt" return (SQRT); -"while" return (WHILE); - -"^" return (EXPONENT); -"*" return (MULTIPLY); -"/" return (DIVIDE); -"%" return (REMAINDER); - -"!" return (BOOL_NOT); -"&&" return (BOOL_AND); -"||" return (BOOL_OR); - -"+" return (PLUS); -"-" return (MINUS); - -"++" return (INCR); -"--" return (DECR); - -"=" yylval.str = ""; return (ASSIGN_OP); -"+=" yylval.str = "+"; return (ASSIGN_OP); -"-=" yylval.str = "-"; return (ASSIGN_OP); -"*=" yylval.str = "*"; return (ASSIGN_OP); -"/=" yylval.str = "/"; return (ASSIGN_OP); -"%=" yylval.str = "%"; return (ASSIGN_OP); -"^=" yylval.str = "^"; return (ASSIGN_OP); - -"==" return (EQUALS); -"<=" return (LESS_EQ); -">=" return (GREATER_EQ); -"!=" return (UNEQUALS); -"<" return (LESS); -">" return (GREATER); - -"," return (COMMA); -";" return (SEMICOLON); - -"(" return (LPAR); -")" return (RPAR); - -"[" return (LBRACKET); -"]" return (RBRACKET); - -"{" return (LBRACE); -"}" return (RBRACE); +"auto" return AUTO; +"break" return BREAK; +"continue" return CONTINUE; +"define" return DEFINE; +"else" return ELSE; +"ibase" return IBASE; +"if" return IF; +"last" return DOT; +"for" return FOR; +"length" return LENGTH; +"obase" return OBASE; +"print" return PRINT; +"quit" return QUIT; +"return" return RETURN; +"scale" return SCALE; +"sqrt" return SQRT; +"while" return WHILE; + +"^" return EXPONENT; +"*" return MULTIPLY; +"/" return DIVIDE; +"%" return REMAINDER; + +"!" return BOOL_NOT; +"&&" return BOOL_AND; +"||" return BOOL_OR; + +"+" return PLUS; +"-" return MINUS; + +"++" return INCR; +"--" return DECR; + +"=" yylval.str = ""; return ASSIGN_OP; +"+=" yylval.str = "+"; return ASSIGN_OP; +"-=" yylval.str = "-"; return ASSIGN_OP; +"*=" yylval.str = "*"; return ASSIGN_OP; +"/=" yylval.str = "/"; return ASSIGN_OP; +"%=" yylval.str = "%"; return ASSIGN_OP; +"^=" yylval.str = "^"; return ASSIGN_OP; + +"==" return EQUALS; +"<=" return LESS_EQ; +">=" return GREATER_EQ; +"!=" return UNEQUALS; +"<" return LESS; +">" return GREATER; + +"," return COMMA; +";" return SEMICOLON; + +"(" return LPAR; +")" return RPAR; + +"[" return LBRACKET; +"]" return RBRACKET; + +"{" return LBRACE; +"}" return RBRACE; {ALPHA}{ALPHANUM}* { /* alloc an extra byte for the type marker */ @@ -188,15 +193,15 @@ ALPHANUM [a-z_0-9] err(1, NULL); strlcpy(p, yytext, yyleng + 1); yylval.astr = p; - return (LETTER); + return LETTER; } \\\n lineno++; -\n lineno++; return (NEWLINE); +\n lineno++; return NEWLINE; #[^\n]* ; [ \t] ; -<<EOF>> return (QUIT); +<<EOF>> return QUIT; . yyerror("illegal character"); %% @@ -204,7 +209,6 @@ ALPHANUM [a-z_0-9] static void init_strbuf(void) { - if (strbuf == NULL) { strbuf = malloc(strbuf_sz); if (strbuf == NULL) @@ -221,8 +225,8 @@ add_str(const char *str) arglen = strlen(str); if (strlen(strbuf) + arglen + 1 > strbuf_sz) { - size_t newsize; - char *p; + size_t newsize; + char *p; newsize = strbuf_sz + arglen + 1; p = realloc(strbuf, newsize); @@ -236,11 +240,47 @@ add_str(const char *str) strlcat(strbuf, str, strbuf_sz); } +/* ARGSUSED */ +void +abort_line(int sig __unused) +{ + static const char str1[] = "[\n]P\n"; + static const char str2[] = "[^C\n]P\n"; + int save_errno; + const LineInfo *info; + + save_errno = errno; + if (use_el) { + write(STDOUT_FILENO, str2, sizeof(str2) - 1); + info = el_line(el); + skipchars = info->lastchar - info->buffer; + } else + write(STDOUT_FILENO, str1, sizeof(str1) - 1); + errno = save_errno; +} + +/* + * Avoid the echo of ^D by the default code of editline and take + * into account skipchars to make ^D work when the cursor is at start of + * line after a ^C. + */ +unsigned char +bc_eof(EditLine *e, int ch __unused) +{ + const struct lineinfo *info = el_line(e); + + if (info->buffer + skipchars == info->cursor && + info->cursor == info->lastchar) + return (CC_EOF); + else + return (CC_ERROR); +} + int yywrap(void) { - static YY_BUFFER_STATE buf; static int state; + static YY_BUFFER_STATE buf; if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) { filename = sargv[fileindex++]; @@ -273,6 +313,10 @@ yywrap(void) } else if (fileindex == sargc) { fileindex++; yyin = stdin; + if (interactive) { + signal(SIGINT, abort_line); + signal(SIGTSTP, tstpcont); + } lineno = 1; filename = "stdin"; return (0); @@ -284,17 +328,32 @@ static int bc_yyinput(char *buf, int maxlen) { int num; - if (yyin == stdin && interactive) { + + if (el != NULL) + el_get(el, EL_EDITMODE, &use_el); + + if (yyin == stdin && interactive && use_el) { const char *bp; + sigset_t oset, nset; if ((bp = el_gets(el, &num)) == NULL || num == 0) return (0); + sigemptyset(&nset); + sigaddset(&nset, SIGINT); + sigprocmask(SIG_BLOCK, &nset, &oset); + if (skipchars < num) { + bp += skipchars; + num -= skipchars; + } + skipchars = 0; + sigprocmask(SIG_SETMASK, &oset, NULL); if (num > maxlen) { - el_push(el, (char *)(uintptr_t)(bp) + maxlen); + el_push(el, bp + maxlen); num = maxlen; } memcpy(buf, bp, num); history(hist, &he, H_ENTER, bp); + el_get(el, EL_EDITMODE, &use_el); } else { int c = '*'; for (num = 0; num < maxlen && @@ -308,3 +367,4 @@ bc_yyinput(char *buf, int maxlen) return (num); } + |