1f2d37758SMatthew Dillon %{ 2f2d37758SMatthew Dillon /* 3db555d9aSPeter Avalos * $OpenBSD: scan.l,v 1.21 2006/03/18 20:44:43 otto Exp $ 4f2d37758SMatthew Dillon */ 5f2d37758SMatthew Dillon 6f2d37758SMatthew Dillon /* 7f2d37758SMatthew Dillon * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net> 8f2d37758SMatthew Dillon * 9f2d37758SMatthew Dillon * Permission to use, copy, modify, and distribute this software for any 10f2d37758SMatthew Dillon * purpose with or without fee is hereby granted, provided that the above 11f2d37758SMatthew Dillon * copyright notice and this permission notice appear in all copies. 12f2d37758SMatthew Dillon * 13f2d37758SMatthew Dillon * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14f2d37758SMatthew Dillon * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15f2d37758SMatthew Dillon * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16f2d37758SMatthew Dillon * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17f2d37758SMatthew Dillon * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18f2d37758SMatthew Dillon * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19f2d37758SMatthew Dillon * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20f2d37758SMatthew Dillon */ 21f2d37758SMatthew Dillon 22f2d37758SMatthew Dillon #include <err.h> 23b6d9cda5SSascha Wildner #include <errno.h> 24ac3cc18cSSascha Wildner #include <histedit.h> 25b6d9cda5SSascha Wildner #include <signal.h> 26f2d37758SMatthew Dillon #include <stdbool.h> 27f2d37758SMatthew Dillon #include <string.h> 28b6d9cda5SSascha Wildner #include <unistd.h> 29f2d37758SMatthew Dillon 30f2d37758SMatthew Dillon #include "extern.h" 31b6d9cda5SSascha Wildner #include "pathnames.h" 32f2d37758SMatthew Dillon #include "y.tab.h" 33f2d37758SMatthew Dillon 34f2d37758SMatthew Dillon int lineno; 35db555d9aSPeter Avalos bool interactive; 36f2d37758SMatthew Dillon 37ac3cc18cSSascha Wildner HistEvent he; 38ac3cc18cSSascha Wildner EditLine *el; 39ac3cc18cSSascha Wildner History *hist; 40ac3cc18cSSascha Wildner 41f2d37758SMatthew Dillon static char *strbuf = NULL; 42f2d37758SMatthew Dillon static size_t strbuf_sz = 1; 43f2d37758SMatthew Dillon static bool dot_seen; 44*cb7e3b3cSJoris Giovannangeli static int use_el; 45*cb7e3b3cSJoris Giovannangeli static volatile sig_atomic_t skipchars; 46f2d37758SMatthew Dillon 47f2d37758SMatthew Dillon static void init_strbuf(void); 48f2d37758SMatthew Dillon static void add_str(const char *); 49ac3cc18cSSascha Wildner static int bc_yyinput(char *, int); 50ac3cc18cSSascha Wildner 51ac3cc18cSSascha Wildner #undef YY_INPUT 52ac3cc18cSSascha Wildner #define YY_INPUT(buf,retval,max) \ 53ac3cc18cSSascha Wildner (retval = bc_yyinput(buf, max)) 54f2d37758SMatthew Dillon 55f2d37758SMatthew Dillon %} 56f2d37758SMatthew Dillon 57b6d9cda5SSascha Wildner %option always-interactive 58eb74dec6SJohn Marino %option noinput 59b6d9cda5SSascha Wildner 60f2d37758SMatthew Dillon DIGIT [0-9A-F] 61f2d37758SMatthew Dillon ALPHA [a-z_] 62f2d37758SMatthew Dillon ALPHANUM [a-z_0-9] 63f2d37758SMatthew Dillon 64f2d37758SMatthew Dillon %x comment string number 65f2d37758SMatthew Dillon 66f2d37758SMatthew Dillon %% 67f2d37758SMatthew Dillon 68f2d37758SMatthew Dillon "/*" BEGIN(comment); 69f2d37758SMatthew Dillon <comment>{ 70f2d37758SMatthew Dillon "*/" BEGIN(INITIAL); 71f2d37758SMatthew Dillon \n lineno++; 72f2d37758SMatthew Dillon \* ; 73f2d37758SMatthew Dillon [^*\n]+ ; 74f2d37758SMatthew Dillon <<EOF>> fatal("end of file in comment"); 75f2d37758SMatthew Dillon } 76f2d37758SMatthew Dillon 77f2d37758SMatthew Dillon \" BEGIN(string); init_strbuf(); 78f2d37758SMatthew Dillon <string>{ 79f2d37758SMatthew Dillon [^"\n\\\[\]]+ add_str(yytext); 80f2d37758SMatthew Dillon \[ add_str("\\["); 81f2d37758SMatthew Dillon \] add_str("\\]"); 82f2d37758SMatthew Dillon \\ add_str("\\\\"); 83f2d37758SMatthew Dillon \n add_str("\n"); lineno++; 84f2d37758SMatthew Dillon \" BEGIN(INITIAL); yylval.str = strbuf; return STRING; 85f2d37758SMatthew Dillon <<EOF>> fatal("end of file in string"); 86f2d37758SMatthew Dillon } 87f2d37758SMatthew Dillon 88f2d37758SMatthew Dillon {DIGIT}+ { 89f2d37758SMatthew Dillon BEGIN(number); 90f2d37758SMatthew Dillon dot_seen = false; 91f2d37758SMatthew Dillon init_strbuf(); 92f2d37758SMatthew Dillon add_str(yytext); 93f2d37758SMatthew Dillon } 94f2d37758SMatthew Dillon \. { 95f2d37758SMatthew Dillon BEGIN(number); 96f2d37758SMatthew Dillon dot_seen = true; 97f2d37758SMatthew Dillon init_strbuf(); 98f2d37758SMatthew Dillon add_str("."); 99f2d37758SMatthew Dillon } 100f2d37758SMatthew Dillon <number>{ 101f2d37758SMatthew Dillon {DIGIT}+ add_str(yytext); 102f2d37758SMatthew Dillon \. { 103f2d37758SMatthew Dillon if (dot_seen) { 104f2d37758SMatthew Dillon BEGIN(INITIAL); 105f2d37758SMatthew Dillon yylval.str = strbuf; 106f2d37758SMatthew Dillon unput('.'); 107f2d37758SMatthew Dillon return NUMBER; 108f2d37758SMatthew Dillon } else { 109f2d37758SMatthew Dillon dot_seen = true; 110f2d37758SMatthew Dillon add_str("."); 111f2d37758SMatthew Dillon } 112f2d37758SMatthew Dillon } 113f2d37758SMatthew Dillon \\\n[ \t]* lineno++; 114f2d37758SMatthew Dillon [^0-9A-F\.] { 115f2d37758SMatthew Dillon BEGIN(INITIAL); 116f2d37758SMatthew Dillon unput(yytext[0]); 117f2d37758SMatthew Dillon if (strcmp(strbuf, ".") == 0) 118f2d37758SMatthew Dillon return DOT; 119f2d37758SMatthew Dillon else { 120f2d37758SMatthew Dillon yylval.str = strbuf; 121f2d37758SMatthew Dillon return NUMBER; 122f2d37758SMatthew Dillon } 123f2d37758SMatthew Dillon } 124f2d37758SMatthew Dillon } 125f2d37758SMatthew Dillon 126f2d37758SMatthew Dillon "auto" return AUTO; 127f2d37758SMatthew Dillon "break" return BREAK; 128f2d37758SMatthew Dillon "continue" return CONTINUE; 129f2d37758SMatthew Dillon "define" return DEFINE; 130f2d37758SMatthew Dillon "else" return ELSE; 131f2d37758SMatthew Dillon "ibase" return IBASE; 132f2d37758SMatthew Dillon "if" return IF; 133f2d37758SMatthew Dillon "last" return DOT; 134f2d37758SMatthew Dillon "for" return FOR; 135f2d37758SMatthew Dillon "length" return LENGTH; 136f2d37758SMatthew Dillon "obase" return OBASE; 137f2d37758SMatthew Dillon "print" return PRINT; 138f2d37758SMatthew Dillon "quit" return QUIT; 139f2d37758SMatthew Dillon "return" return RETURN; 140f2d37758SMatthew Dillon "scale" return SCALE; 141f2d37758SMatthew Dillon "sqrt" return SQRT; 142f2d37758SMatthew Dillon "while" return WHILE; 143f2d37758SMatthew Dillon 144f2d37758SMatthew Dillon "^" return EXPONENT; 145f2d37758SMatthew Dillon "*" return MULTIPLY; 146f2d37758SMatthew Dillon "/" return DIVIDE; 147f2d37758SMatthew Dillon "%" return REMAINDER; 148f2d37758SMatthew Dillon 149f2d37758SMatthew Dillon "!" return BOOL_NOT; 150f2d37758SMatthew Dillon "&&" return BOOL_AND; 151f2d37758SMatthew Dillon "||" return BOOL_OR; 152f2d37758SMatthew Dillon 153f2d37758SMatthew Dillon "+" return PLUS; 154f2d37758SMatthew Dillon "-" return MINUS; 155f2d37758SMatthew Dillon 156f2d37758SMatthew Dillon "++" return INCR; 157f2d37758SMatthew Dillon "--" return DECR; 158f2d37758SMatthew Dillon 159f2d37758SMatthew Dillon "=" yylval.str = ""; return ASSIGN_OP; 160f2d37758SMatthew Dillon "+=" yylval.str = "+"; return ASSIGN_OP; 161f2d37758SMatthew Dillon "-=" yylval.str = "-"; return ASSIGN_OP; 162f2d37758SMatthew Dillon "*=" yylval.str = "*"; return ASSIGN_OP; 163f2d37758SMatthew Dillon "/=" yylval.str = "/"; return ASSIGN_OP; 164f2d37758SMatthew Dillon "%=" yylval.str = "%"; return ASSIGN_OP; 165f2d37758SMatthew Dillon "^=" yylval.str = "^"; return ASSIGN_OP; 166f2d37758SMatthew Dillon 167f2d37758SMatthew Dillon "==" return EQUALS; 168f2d37758SMatthew Dillon "<=" return LESS_EQ; 169f2d37758SMatthew Dillon ">=" return GREATER_EQ; 170f2d37758SMatthew Dillon "!=" return UNEQUALS; 171f2d37758SMatthew Dillon "<" return LESS; 172f2d37758SMatthew Dillon ">" return GREATER; 173f2d37758SMatthew Dillon 174f2d37758SMatthew Dillon "," return COMMA; 175f2d37758SMatthew Dillon ";" return SEMICOLON; 176f2d37758SMatthew Dillon 177f2d37758SMatthew Dillon "(" return LPAR; 178f2d37758SMatthew Dillon ")" return RPAR; 179f2d37758SMatthew Dillon 180f2d37758SMatthew Dillon "[" return LBRACKET; 181f2d37758SMatthew Dillon "]" return RBRACKET; 182f2d37758SMatthew Dillon 183f2d37758SMatthew Dillon "{" return LBRACE; 184f2d37758SMatthew Dillon "}" return RBRACE; 185f2d37758SMatthew Dillon 186f2d37758SMatthew Dillon {ALPHA}{ALPHANUM}* { 187f2d37758SMatthew Dillon /* alloc an extra byte for the type marker */ 188f2d37758SMatthew Dillon char *p = malloc(yyleng + 2); 189f2d37758SMatthew Dillon if (p == NULL) 190f2d37758SMatthew Dillon err(1, NULL); 191f2d37758SMatthew Dillon strlcpy(p, yytext, yyleng + 1); 192f2d37758SMatthew Dillon yylval.astr = p; 193f2d37758SMatthew Dillon return LETTER; 194f2d37758SMatthew Dillon } 195f2d37758SMatthew Dillon 196f2d37758SMatthew Dillon \\\n lineno++; 197f2d37758SMatthew Dillon \n lineno++; return NEWLINE; 198f2d37758SMatthew Dillon 199f2d37758SMatthew Dillon #[^\n]* ; 200f2d37758SMatthew Dillon [ \t] ; 201f2d37758SMatthew Dillon <<EOF>> return QUIT; 202f2d37758SMatthew Dillon . yyerror("illegal character"); 203f2d37758SMatthew Dillon 204f2d37758SMatthew Dillon %% 205f2d37758SMatthew Dillon 206f2d37758SMatthew Dillon static void 207f2d37758SMatthew Dillon init_strbuf(void) 208f2d37758SMatthew Dillon { 209f2d37758SMatthew Dillon if (strbuf == NULL) { 210f2d37758SMatthew Dillon strbuf = malloc(strbuf_sz); 211f2d37758SMatthew Dillon if (strbuf == NULL) 212f2d37758SMatthew Dillon err(1, NULL); 213f2d37758SMatthew Dillon } 214f2d37758SMatthew Dillon strbuf[0] = '\0'; 215f2d37758SMatthew Dillon } 216f2d37758SMatthew Dillon 217f2d37758SMatthew Dillon static void 218f2d37758SMatthew Dillon add_str(const char *str) 219f2d37758SMatthew Dillon { 220f2d37758SMatthew Dillon size_t arglen; 221f2d37758SMatthew Dillon 222f2d37758SMatthew Dillon arglen = strlen(str); 223f2d37758SMatthew Dillon 224f2d37758SMatthew Dillon if (strlen(strbuf) + arglen + 1 > strbuf_sz) { 225f2d37758SMatthew Dillon size_t newsize; 226f2d37758SMatthew Dillon char *p; 227f2d37758SMatthew Dillon 228f2d37758SMatthew Dillon newsize = strbuf_sz + arglen + 1; 229f2d37758SMatthew Dillon p = realloc(strbuf, newsize); 230f2d37758SMatthew Dillon if (p == NULL) { 231f2d37758SMatthew Dillon free(strbuf); 232f2d37758SMatthew Dillon err(1, NULL); 233f2d37758SMatthew Dillon } 234f2d37758SMatthew Dillon strbuf_sz = newsize; 235f2d37758SMatthew Dillon strbuf = p; 236f2d37758SMatthew Dillon } 237f2d37758SMatthew Dillon strlcat(strbuf, str, strbuf_sz); 238f2d37758SMatthew Dillon } 239f2d37758SMatthew Dillon 240db555d9aSPeter Avalos /* ARGSUSED */ 241f2d37758SMatthew Dillon void 242f2d37758SMatthew Dillon abort_line(int sig) 243f2d37758SMatthew Dillon { 244*cb7e3b3cSJoris Giovannangeli const char str1[] = "[\n]P\n"; 245*cb7e3b3cSJoris Giovannangeli const char str2[] = "[^C\n]P\n"; 246b6d9cda5SSascha Wildner int save_errno; 247*cb7e3b3cSJoris Giovannangeli const LineInfo *info; 248b6d9cda5SSascha Wildner 249b6d9cda5SSascha Wildner save_errno = errno; 250*cb7e3b3cSJoris Giovannangeli if (use_el) { 251*cb7e3b3cSJoris Giovannangeli write(STDOUT_FILENO, str2, sizeof(str2) - 1); 252*cb7e3b3cSJoris Giovannangeli info = el_line(el); 253*cb7e3b3cSJoris Giovannangeli skipchars = info->lastchar - info->buffer; 254*cb7e3b3cSJoris Giovannangeli } else 255*cb7e3b3cSJoris Giovannangeli write(STDOUT_FILENO, str1, sizeof(str1) - 1); 256b6d9cda5SSascha Wildner errno = save_errno; 257f2d37758SMatthew Dillon } 258b6d9cda5SSascha Wildner 259*cb7e3b3cSJoris Giovannangeli /* 260*cb7e3b3cSJoris Giovannangeli * Avoid the echo of ^D by the default code of editline and take 261*cb7e3b3cSJoris Giovannangeli * into account skipchars to make ^D work when the cursor is at start of 262*cb7e3b3cSJoris Giovannangeli * line after a ^C. 263*cb7e3b3cSJoris Giovannangeli */ 264*cb7e3b3cSJoris Giovannangeli unsigned char 265*cb7e3b3cSJoris Giovannangeli bc_eof(EditLine *e, int ch) 266*cb7e3b3cSJoris Giovannangeli { 267*cb7e3b3cSJoris Giovannangeli const struct lineinfo *info = el_line(e); 268*cb7e3b3cSJoris Giovannangeli 269*cb7e3b3cSJoris Giovannangeli if (info->buffer + skipchars == info->cursor && 270*cb7e3b3cSJoris Giovannangeli info->cursor == info->lastchar) 271*cb7e3b3cSJoris Giovannangeli return (CC_EOF); 272*cb7e3b3cSJoris Giovannangeli else 273*cb7e3b3cSJoris Giovannangeli return (CC_ERROR); 274*cb7e3b3cSJoris Giovannangeli } 275*cb7e3b3cSJoris Giovannangeli 276b6d9cda5SSascha Wildner int 277b6d9cda5SSascha Wildner yywrap(void) 278b6d9cda5SSascha Wildner { 279b6d9cda5SSascha Wildner static int state; 280b6d9cda5SSascha Wildner static YY_BUFFER_STATE buf; 281b6d9cda5SSascha Wildner 282b6d9cda5SSascha Wildner if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) { 283b6d9cda5SSascha Wildner filename = sargv[fileindex++]; 284b6d9cda5SSascha Wildner yyin = fopen(filename, "r"); 285b6d9cda5SSascha Wildner lineno = 1; 286b6d9cda5SSascha Wildner if (yyin == NULL) 287b6d9cda5SSascha Wildner err(1, "cannot open %s", filename); 288b6d9cda5SSascha Wildner return (0); 289b6d9cda5SSascha Wildner } 290b6d9cda5SSascha Wildner if (state == 0 && cmdexpr[0] != '\0') { 291b6d9cda5SSascha Wildner buf = yy_scan_string(cmdexpr); 292b6d9cda5SSascha Wildner state++; 293b6d9cda5SSascha Wildner lineno = 1; 294b6d9cda5SSascha Wildner filename = "command line"; 295b6d9cda5SSascha Wildner return (0); 296b6d9cda5SSascha Wildner } else if (state == 1) { 297b6d9cda5SSascha Wildner yy_delete_buffer(buf); 298b6d9cda5SSascha Wildner free(cmdexpr); 299b6d9cda5SSascha Wildner state++; 300b6d9cda5SSascha Wildner } 301db555d9aSPeter Avalos if (yyin != NULL && yyin != stdin) 302db555d9aSPeter Avalos fclose(yyin); 303b6d9cda5SSascha Wildner if (fileindex < sargc) { 304b6d9cda5SSascha Wildner filename = sargv[fileindex++]; 305b6d9cda5SSascha Wildner yyin = fopen(filename, "r"); 306b6d9cda5SSascha Wildner lineno = 1; 307b6d9cda5SSascha Wildner if (yyin == NULL) 308b6d9cda5SSascha Wildner err(1, "cannot open %s", filename); 309b6d9cda5SSascha Wildner return (0); 310b6d9cda5SSascha Wildner } else if (fileindex == sargc) { 311b6d9cda5SSascha Wildner fileindex++; 312b6d9cda5SSascha Wildner yyin = stdin; 313*cb7e3b3cSJoris Giovannangeli if (interactive) { 314db555d9aSPeter Avalos signal(SIGINT, abort_line); 315*cb7e3b3cSJoris Giovannangeli signal(SIGTSTP, tstpcont); 316*cb7e3b3cSJoris Giovannangeli } 317b6d9cda5SSascha Wildner lineno = 1; 318b6d9cda5SSascha Wildner filename = "stdin"; 319b6d9cda5SSascha Wildner return (0); 320b6d9cda5SSascha Wildner } 321b6d9cda5SSascha Wildner return (1); 322b6d9cda5SSascha Wildner } 323ac3cc18cSSascha Wildner 324ac3cc18cSSascha Wildner static int 325ac3cc18cSSascha Wildner bc_yyinput(char *buf, int maxlen) 326ac3cc18cSSascha Wildner { 327ac3cc18cSSascha Wildner int num; 328*cb7e3b3cSJoris Giovannangeli 329*cb7e3b3cSJoris Giovannangeli if (el != NULL) 330*cb7e3b3cSJoris Giovannangeli el_get(el, EL_EDITMODE, &use_el); 331*cb7e3b3cSJoris Giovannangeli 332*cb7e3b3cSJoris Giovannangeli if (yyin == stdin && interactive && use_el) { 333ac3cc18cSSascha Wildner const char *bp; 334*cb7e3b3cSJoris Giovannangeli sigset_t oset, nset; 335ac3cc18cSSascha Wildner 336ac3cc18cSSascha Wildner if ((bp = el_gets(el, &num)) == NULL || num == 0) 337ac3cc18cSSascha Wildner return (0); 338*cb7e3b3cSJoris Giovannangeli sigemptyset(&nset); 339*cb7e3b3cSJoris Giovannangeli sigaddset(&nset, SIGINT); 340*cb7e3b3cSJoris Giovannangeli sigprocmask(SIG_BLOCK, &nset, &oset); 341*cb7e3b3cSJoris Giovannangeli if (skipchars < num) { 342*cb7e3b3cSJoris Giovannangeli bp += skipchars; 343*cb7e3b3cSJoris Giovannangeli num -= skipchars; 344*cb7e3b3cSJoris Giovannangeli } 345*cb7e3b3cSJoris Giovannangeli skipchars = 0; 346*cb7e3b3cSJoris Giovannangeli sigprocmask(SIG_SETMASK, &oset, NULL); 347ac3cc18cSSascha Wildner if (num > maxlen) { 348ac3cc18cSSascha Wildner el_push(el, (char *)(uintptr_t)(bp) + maxlen); 349ac3cc18cSSascha Wildner num = maxlen; 350ac3cc18cSSascha Wildner } 351ac3cc18cSSascha Wildner memcpy(buf, bp, num); 352ac3cc18cSSascha Wildner history(hist, &he, H_ENTER, bp); 353*cb7e3b3cSJoris Giovannangeli el_get(el, EL_EDITMODE, &use_el); 354ac3cc18cSSascha Wildner } else { 355ac3cc18cSSascha Wildner int c = '*'; 356ac3cc18cSSascha Wildner for (num = 0; num < maxlen && 357ac3cc18cSSascha Wildner (c = getc(yyin)) != EOF && c != '\n'; ++num) 358ac3cc18cSSascha Wildner buf[num] = (char) c; 359ac3cc18cSSascha Wildner if (c == '\n') 360ac3cc18cSSascha Wildner buf[num++] = (char) c; 361ac3cc18cSSascha Wildner if (c == EOF && ferror(yyin)) 362ac3cc18cSSascha Wildner YY_FATAL_ERROR( "input in flex scanner failed" ); 363ac3cc18cSSascha Wildner } 364ac3cc18cSSascha Wildner return (num); 365ac3cc18cSSascha Wildner } 366