X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/6bc35ae56a34c075b00fdc0c14c0cd8c14bf80ca..107f7dfbd0baaaceee887cbaea2041a9f7f5db66:/src/lex.c diff --git a/src/lex.c b/src/lex.c index c18042d4..78b8a8f3 100644 --- a/src/lex.c +++ b/src/lex.c @@ -21,31 +21,37 @@ #include "system.h" #include "getargs.h" #include "files.h" -#include "getopt.h" /* for optarg */ #include "symtab.h" #include "options.h" #include "lex.h" -#include "xalloc.h" #include "complain.h" #include "gram.h" #include "quote.h" /* Buffer for storing the current token. */ -struct obstack token_obstack; +static struct obstack token_obstack; const char *token_buffer = NULL; -bucket *symval; +bucket *symval = NULL; int numval; -static int unlexed; /* these two describe a token to be reread */ -static bucket *unlexed_symval; /* by the next call to lex */ - +/* A token to be reread, see unlex and lex. */ +static token_t unlexed = tok_undef; +static bucket *unlexed_symval = NULL; +static const char *unlexed_token_buffer = NULL; void -init_lex (void) +lex_init (void) { obstack_init (&token_obstack); - unlexed = -1; + unlexed = tok_undef; +} + + +void +lex_free (void) +{ + obstack_free (&token_obstack, NULL); } @@ -146,7 +152,7 @@ xgetc (FILE *f) being, I prefer have literalchar behave like quotearg, and change my mind later if I was wrong. */ -static int +int literalchar (struct obstack *out, int *pcode, char term) { int c; @@ -314,9 +320,10 @@ literalchar (struct obstack *out, int *pcode, char term) void -unlex (int token) +unlex (token_t token) { unlexed = token; + unlexed_token_buffer = token_buffer; unlexed_symval = symval; } @@ -357,12 +364,13 @@ lex (void) /* Just to make sure. */ token_buffer = NULL; - if (unlexed >= 0) + if (unlexed != tok_undef) { + token_t res = unlexed; symval = unlexed_symval; - c = unlexed; - unlexed = -1; - return c; + token_buffer = unlexed_token_buffer; + unlexed = tok_undef; + return res; } c = skip_white_space (); @@ -418,9 +426,8 @@ lex (void) case '\'': /* parse the literal token and compute character code in code */ - translations = -1; { - int code, discode; + int code; obstack_1grow (&token_obstack, '\''); literalchar (&token_obstack, &code, '\''); @@ -428,6 +435,7 @@ lex (void) c = getc (finput); if (c != '\'') { + int discode; complain (_("use \"...\" for multi-character literal tokens")); while (1) if (!literalchar (0, &discode, '\'')) @@ -438,7 +446,7 @@ lex (void) token_buffer = obstack_finish (&token_obstack); symval = getsym (token_buffer); symval->class = token_sym; - if (!symval->user_token_number) + if (symval->user_token_number == SUNDEF) symval->user_token_number = code; return tok_identifier; } @@ -446,7 +454,6 @@ lex (void) case '\"': /* parse the literal string token and treat as an identifier */ - translations = -1; { int code; /* ignored here */ @@ -464,32 +471,40 @@ lex (void) } case ',': + token_buffer = ","; return tok_comma; case ':': + token_buffer = ":"; return tok_colon; case ';': + token_buffer = ";"; return tok_semicolon; case '|': + token_buffer = "|"; return tok_bar; case '{': + token_buffer = "{"; return tok_left_curly; case '=': + obstack_1grow (&token_obstack, c); do { c = getc (finput); + obstack_1grow (&token_obstack, c); if (c == '\n') lineno++; } while (c == ' ' || c == '\n' || c == '\t'); + obstack_1grow (&token_obstack, '\0'); + token_buffer = obstack_finish (&token_obstack); if (c == '{') { - token_buffer = "={"; return tok_left_curly; } else @@ -506,6 +521,9 @@ lex (void) return parse_percent_token (); default: + obstack_1grow (&token_obstack, c); + obstack_1grow (&token_obstack, '\0'); + token_buffer = obstack_finish (&token_obstack); return tok_illegal; } } @@ -516,28 +534,31 @@ lex (void) static int option_strcmp (const char *left, const char *right) { - const unsigned char *l, *r; - int c; - - assert(left != NULL && right != NULL); - l = (const unsigned char *)left; - r = (const unsigned char *)right; - while (((c = *l - *r++) == 0 && *l != '\0') - || ((*l == '-' || *l == '_') && (*r == '_' || *r == '-'))) - l++; - return c; + const unsigned char *l, *r; + int c; + + assert (left); + assert (right); + l = (const unsigned char *)left; + r = (const unsigned char *)right; + while (((c = *l - *r++) == 0 && *l != '\0') + || ((*l == '-' || *l == '_') && (*r == '_' || *r == '-'))) + l++; + return c; } /* Parse a token which starts with %. Assumes the % has already been read and discarded. */ -int +token_t parse_percent_token (void) { - int c; - const struct option_table_struct *tx; + const struct option_table_struct *tx = NULL; + const char *arg = NULL; + /* Where the ARG was found in token_buffer. */ + size_t arg_offset = 0; - c = getc (finput); + int c = getc (finput); switch (c) { @@ -547,6 +568,8 @@ parse_percent_token (void) case '{': return tok_percent_left_curly; + /* FIXME: Who the heck are those 5 guys!?! `%<' = `%left'!!! + Let's ask for there removal. */ case '<': return tok_left; @@ -575,9 +598,34 @@ parse_percent_token (void) c = getc (finput); } - ungetc (c, finput); + /* %DIRECTIVE="ARG". Separate into + TOKEN_BUFFER = `%DIRECTIVE\0ARG\0'. + This is a bit hackish, but once we move to a Bison parser, + things will be cleaned up. */ + if (c == '=') + { + /* End of the directive. We skip the `='. */ + obstack_1grow (&token_obstack, '\0'); + /* Fetch the ARG if present. */ + c = getc (finput); + if (c == '"') + { + int code; + arg_offset = obstack_object_size (&token_obstack); + /* Read up to and including `"'. Do not append the closing + `"' in the output: it's not part of the ARG. */ + while (literalchar (NULL, &code, '"')) + obstack_1grow (&token_obstack, code); + } + /* else: should be an error. */ + } + else + ungetc (c, finput); + obstack_1grow (&token_obstack, '\0'); token_buffer = obstack_finish (&token_obstack); + if (arg_offset) + arg = token_buffer + arg_offset; /* table lookup % directive */ for (tx = option_table; tx->name; tx++) @@ -585,23 +633,42 @@ parse_percent_token (void) && option_strcmp (token_buffer + 1, tx->name) == 0) break; - if (tx->set_flag) - { - *((int *) (tx->set_flag)) = 1; - return tok_noop; - } + if (arg && tx->ret_val != tok_stropt) + fatal (_("`%s' supports no argument: %s"), token_buffer, quote (arg)); + switch (tx->ret_val) { - case tok_setopt: - *((char **) (tx->set_flag)) = optarg; + case tok_stropt: + assert (tx->set_flag); + if (arg) + { + /* Keep only the first assignment: command line options have + already been processed, and we want them to have + precedence. Side effect: if this %-option is used + several times, only the first is honored. Bah. */ + if (!*((char **) (tx->set_flag))) + *((char **) (tx->set_flag)) = xstrdup (arg); + } + else + fatal (_("`%s' requires an argument"), token_buffer); + return tok_noop; + break; + + case tok_intopt: + assert (tx->set_flag); + *((int *) (tx->set_flag)) = 1; return tok_noop; break; case tok_obsolete: fatal (_("`%s' is no longer supported"), token_buffer); + return tok_noop; break; - } - return tx->ret_val; + default: + return tx->ret_val; + break; + } + abort (); }