diff options
-rw-r--r-- | bin/chio/parse.y | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/bin/chio/parse.y b/bin/chio/parse.y index 552ebdee668..a3af5f7c9ca 100644 --- a/bin/chio/parse.y +++ b/bin/chio/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.4 2007/06/01 06:48:34 cnst Exp $ */ +/* $OpenBSD: parse.y,v 1.5 2007/09/11 22:16:15 deraadt Exp $ */ /* * Copyright (c) 2006 Bob Beck <beck@openbsd.org> @@ -58,7 +58,7 @@ int yylex(void); typedef struct { union { - u_int32_t number; + int64_t number; char *string; } v; int lineno; @@ -70,6 +70,7 @@ typedef struct { %token DRIVE %token ERROR %token <v.string> STRING +%token <v.number> NUMBER %% grammar : /* empty */ @@ -294,6 +295,42 @@ yylex(void) return (STRING); } +#define allowed_to_end_number(x) \ + (isspace(x) || c == ')' || c ==',' || c == '/' || c == '}') + + if (c == '-' || isdigit(c)) { + do { + *p++ = c; + if ((unsigned)(p-buf) >= sizeof(buf)) { + yyerror("string too long"); + return (findeol()); + } + } while ((c = lgetc(fin)) != EOF && isdigit(c)); + lungetc(c); + if (p == buf + 1 && buf[0] == '-') + goto nodigits; + if (c == EOF || allowed_to_end_number(c)) { + const char *errstr = NULL; + + *p = '\0'; + yylval.v.number = strtonum(buf, LLONG_MIN, + LLONG_MAX, &errstr); + if (errstr) { + yyerror("\"%s\" invalid number: %s", + buf, errstr); + return (findeol()); + } + return (NUMBER); + } else { +nodigits: + while (p > buf + 1) + lungetc(*--p); + c = *--p; + if (c == '-') + return (c); + } + } + #define allowed_in_string(x) \ (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ x != '{' && x != '}' && x != '<' && x != '>' && \ |