=================================================================== RCS file: /cvs/cvs/blind/parse.y,v retrieving revision 1.10 retrieving revision 1.20 diff -u -p -r1.10 -r1.20 --- blind/parse.y 2022/03/25 22:43:43 1.10 +++ blind/parse.y 2022/04/19 02:16:17 1.20 @@ -17,65 +17,57 @@ %{ #include -#include -#include #include +#include +#include #include "blind.h" #include "config.h" #include "log.h" - //TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); -static struct file { - // TAILQ_ENTRY(file) entry; - FILE *stream; - char *name; - size_t ungetpos; - size_t ungetsize; - u_char *ungetbuf; - int eof_reached; - int lineno; - int errors; -} *file; -//, *top; +#define EXPAND_ON 1 +#define EXPAND_OFF 2 -int lookup(char *); -int igetc(void); -int lgetc(int); -int findeol(void); -void lungetc(int); -int kw_cmp(const void *, const void *); -int yyparse(void); -int yylex(void); -int yyerror(const char *, ...) - __attribute__((__format__ (printf, 1, 2))) - __attribute__((__nonnull__ (1))); +int lookup(char *); +int igetc(void); +int lgetc(int); +int findeol(void); +void lungetc(int); +int kw_cmp(const void *, const void *); +int yyparse(void); +int yylex(void); +int yyerror(const char *, ...) + __attribute__((__format__ (printf, 1, 2))) + __attribute__((__nonnull__ (1))); -int config_load(struct blind *); -struct file *config_push(const char *); -int config_pop(void); +int symset(const char *, const char *, int); +char *symget(const char *); -TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); +int config_load(struct blind *); +int config_close(void); + +TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); struct sym { - TAILQ_ENTRY(sym) entry; - int used; - int persist; - char *nam; - char *val; + TAILQ_ENTRY(sym) entry; + int used; + int persist; + char *nam; + char *val; }; -char *symget(const char *); -struct blind *env = NULL; -static int errors = 0; - typedef struct { union { - int64_t number; - char *string; + int64_t number; + char *string; } v; int lineno; } YYSTYPE; +static int expanding; +static int errors = 0; +struct blind *env = NULL; +static struct file *f = NULL; + %} %token ACTION ARROW DISABLE ENABLE EXPIRE ERROR SET @@ -86,40 +78,58 @@ typedef struct { grammar : | grammar '\n' - | grammar set '\n' - | grammar error '\n' { file->errors++; } - ; + | grammar varset '\n' + | grammar set '\n' + | grammar error '\n' { errors++; } + ; +varset : STRING '=' STRING { + char *s = $1; + while (*s++) { + if (isspace((unsigned char)*s)) { + yyerror("macro contain whitespace"); + free($1); + free($3); + YYERROR; + } + } + if (symset($1, $3, 0) == -1) + log_fatal("cannot store variable"); + free($1); + free($3); +} +; + set : SET EXPIRE NUMBER { - env->bl_ttl = $3; + env->bl_ttl = $3; } | SET ACTION ENABLE { - env->bl_opt |= BL_OPT_ACTION; + env->bl_opt |= BL_OPT_ACTION; } | SET ACTION DISABLE { - env->bl_opt |= !BL_OPT_ACTION; + env->bl_opt |= !BL_OPT_ACTION; } ; %% struct keywords { - const char *k_name; - int k_val; + const char *k_name; + int k_val; }; int yyerror(const char *fmt, ...) { - va_list ap; - char *msg; + va_list ap; + char *msg; - file->errors++; + errors++; va_start(ap, fmt); if (vasprintf(&msg, fmt, ap) == -1) log_fatal("yyerror vasprintf"); va_end(ap); - log_info("%s:%d: %s", file->name, yylval.lineno, msg); + log_info("%s:%d: %s", f->name, yylval.lineno, msg); free(msg); return (0); } @@ -133,15 +143,14 @@ kw_cmp(const void *k, const void *e) int lookup(char *s) { - /* this has to be sorted always */ static const struct keywords keywords[] = { - { "action", ACTION }, - { "disable", DISABLE }, - { "enable", ENABLE }, - { "expire", EXPIRE }, - { "set", SET }, + { "action", ACTION }, + { "disable", DISABLE }, + { "enable", ENABLE }, + { "expire", EXPIRE }, + { "set", SET }, }; - const struct keywords *p; + const struct keywords *p; p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), sizeof(keywords[0]), kw_cmp); @@ -152,11 +161,46 @@ lookup(char *s) return (STRING); } -#define START_EXPAND 1 -#define DONE_EXPAND 2 +int +symset(const char *nam, const char *val, int persist) +{ + struct sym *sym; -static int expanding; + TAILQ_FOREACH(sym, &symhead, entry) { + if (strcmp(nam, sym->nam) == 0) + break; + } + if (sym != NULL) { + if (sym->persist == 1) + return (0); + else { + free(sym->nam); + free(sym->val); + TAILQ_REMOVE(&symhead, sym, entry); + free(sym); + } + } + if ((sym = calloc(1, sizeof(*sym))) == NULL) + return (-1); + + sym->nam = strdup(nam); + if (sym->nam == NULL) { + free(sym); + return (-1); + } + sym->val = strdup(val); + if (sym->val == NULL) { + free(sym->nam); + free(sym); + return (-1); + } + sym->used = 0; + sym->persist = persist; + TAILQ_INSERT_TAIL(&symhead, sym, entry); + return (0); +} + char * symget(const char *nam) { @@ -177,14 +221,14 @@ igetc(void) int c; while (1) { - if (file->ungetpos > 0) - c = file->ungetbuf[--file->ungetpos]; + if (f->unpos > 0) + c = f->unbuf[--f->unpos]; else - c = getc(file->stream); + c = getc(f->stream); - if (c == START_EXPAND) + if (c == EXPAND_ON) expanding = 1; - else if (c == DONE_EXPAND) + else if (c == EXPAND_OFF) expanding = 0; else break; @@ -195,14 +239,13 @@ igetc(void) int lgetc(int quotec) { - int c, next; + int c, next; if (quotec) { if ((c = igetc()) == EOF) { yyerror("reached end of file while parsing " "quoted string"); - // if (file == top || config_pop() == EOF) - if (config_pop() == EOF) + if (config_close() == EOF) return (EOF); return (quotec); } @@ -215,26 +258,14 @@ lgetc(int quotec) c = next; break; } - yylval.lineno = file->lineno; - file->lineno++; + yylval.lineno = f->lineno; + f->lineno++; } if (c == EOF) { - /* - * Fake EOL when hit EOF for the first time. This gets line - * count right if last line in included file is syntactically - * invalid and has no newline. - */ - if (file->eof_reached == 0) { - file->eof_reached = 1; - return ('\n'); - } - while (c == EOF) { - //if (file == top || config_pop() == EOF) - if (config_pop() == EOF) - return (EOF); - c = igetc(); - } + if (config_close() == EOF) + return (EOF); + c = igetc(); } return (c); } @@ -245,14 +276,14 @@ lungetc(int c) if (c == EOF) return; - if (file->ungetpos >= file->ungetsize) { - void *p = reallocarray(file->ungetbuf, file->ungetsize, 2); + if (f->unpos >= f->unsize) { + void *p = reallocarray(f->unbuf, f->unsize, 2); if (p == NULL) log_fatal("cannot reallocate memory"); - file->ungetbuf = p; - file->ungetsize *= 2; + f->unbuf = p; + f->unsize *= 2; } - file->ungetbuf[file->ungetpos++] = c; + f->unbuf[f->unpos++] = c; } int @@ -260,11 +291,10 @@ findeol(void) { int c; - /* skip to either EOF or the first real EOL */ while (1) { c = lgetc(0); if (c == '\n') { - file->lineno++; + f->lineno++; break; } if (c == EOF) @@ -276,20 +306,21 @@ findeol(void) int yylex(void) { - char buf[8096]; - char *p, *val; - int quotec, next, c; - int token; + char buf[8096]; + char *p, *val; + int quotec, next, c; + int token; top: p = buf; while ((c = lgetc(0)) == ' ' || c == '\t') - ; /* nothing */ + ; - yylval.lineno = file->lineno; + yylval.lineno = f->lineno; if (c == '#') while ((c = lgetc(0)) != '\n' && c != EOF) - ; /* nothing */ + ; + if (c == '$' && !expanding) { while (1) { if ((c = lgetc(0)) == EOF) @@ -313,12 +344,12 @@ top: return (findeol()); } p = val + strlen(val) - 1; - lungetc(DONE_EXPAND); + lungetc(EXPAND_OFF); while (p >= val) { lungetc((unsigned char)*p); p--; } - lungetc(START_EXPAND); + lungetc(EXPAND_ON); goto top; } @@ -330,7 +361,7 @@ top: if ((c = lgetc(quotec)) == EOF) return (0); if (c == '\n') { - file->lineno++; + f->lineno++; continue; } else if (c == '\\') { if ((next = lgetc(quotec)) == EOF) @@ -339,7 +370,7 @@ top: next == '\t') c = next; else if (next == '\n') { - file->lineno++; + f->lineno++; continue; } else lungetc(next); @@ -368,7 +399,7 @@ top: if (c == '-' || isdigit(c)) { do { *p++ = c; - if ((size_t)(p-buf) >= sizeof(buf)) { + if ((size_t)(p-buf) >= sizeof(buf)) { yyerror("string too long"); return (findeol()); } @@ -427,8 +458,8 @@ nodigits: return (token); } if (c == '\n') { - yylval.lineno = file->lineno; - file->lineno++; + yylval.lineno = f->lineno; + f->lineno++; } if (c == EOF) return (0); @@ -438,85 +469,56 @@ nodigits: int config_load(struct blind *temp) { - env = temp; - errors = 0; + env = temp; + errors = 0; - if ((file = config_push(env->bl_conf)) == NULL) { - // config_purge(PURGE_ALL); - return (-1); - } - // top = file; + if ((f = calloc(1, sizeof(struct file))) == NULL) { + log_debug("cannot allocate memory"); + return (-1); + } + if ((f->name = strdup(env->bl_conf)) == NULL) { + log_debug("cannot duplicate name"); + free(f); + return (-1); + } + if ((f->stream = fopen(f->name, "r")) == NULL) { + log_debug("cannot open config file"); + free(f->name); + free(f); + return (-1); + } + if (config_perm(fileno(f->stream), f->name)) { + fclose(f->stream); + free(f->name); + free(f); + return (-1); + } + f->lineno = 1; + f->unsize = 16; + if ((f->unbuf = malloc(f->unsize)) == NULL) { + log_debug("cannot allocate buffer"); + fclose(f->stream); + free(f->name); + free(f); + return (-1); + } - yyparse(); + yyparse(); + // setup - errors = file->errors; - config_pop(); + if (errors) + return (-1); - // setup - - if (errors) { - // config_purge(PURGE_ALL); - return (-1); - } - - return (0); + return (0); } -struct file * -config_push(const char *name) -{ - struct file *nfile; - - if ((nfile = calloc(1, sizeof(struct file))) == NULL) { - log_debug("cannot allocate memory"); - return (NULL); - } - if ((nfile->name = strdup(name)) == NULL) { - log_debug("cannot duplicate name"); - free(nfile); - return (NULL); - } - if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { - log_debug("cannot open config file"); - free(nfile->name); - free(nfile); - return (NULL); - } - if (config_perm(fileno(nfile->stream), nfile->name)) { - fclose(nfile->stream); - free(nfile->name); - free(nfile); - return (NULL); - } - nfile->lineno = 1; // TAILQ_EMPTY(&files) ? 1 : 0; - nfile->ungetsize = 16; - nfile->ungetbuf = malloc(nfile->ungetsize); - if (nfile->ungetbuf == NULL) { - log_debug("cannot allocate buffer"); - fclose(nfile->stream); - free(nfile->name); - free(nfile); - return (NULL); - } - //TAILQ_INSERT_TAIL(&files, nfile, entry); - return (nfile); -} - int -config_pop(void) +config_close(void) { - // struct file *prv; + fclose(f->stream); + free(f->name); + free(f->unbuf); + free(f); - //if ((prv = TAILQ_PREV(file, files, entry)) != NULL) - // prv->errors += file->errors; - - // TAILQ_REMOVE(&files, file, entry); - fclose(file->stream); - free(file->name); - free(file->ungetbuf); - // free(file); - // file = prv; - - // return (file ? 0 : EOF); - return (EOF); + return (EOF); }