diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-16 01:08:45 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-16 01:17:20 +0300 |
commit | e559f3f36c99988ee80ac4ec01f80ea6578beebe (patch) | |
tree | e9cd0ab93dc2901fce901a062c7c1ee7442979e5 /src | |
parent | a0826b4c7cd66c4862d9b61bb7e14d73fcba28f6 (diff) | |
download | grecs-e559f3f36c99988ee80ac4ec01f80ea6578beebe.tar.gz grecs-e559f3f36c99988ee80ac4ec01f80ea6578beebe.tar.bz2 |
Implement BIND config parser.
* am/grecs.m4: New option: parser-bind.
* src/.gitignore: Update.
* src/Make.am [GRECS_COND_BIND_PARSER]: Set GRECS_PARSER_BIND
and GRECS_EXTRA_BIND.
(GRECS_SRC): Include GRECS_PARSER_BIND.
(EXTRA_DIST): Include GRECS_EXTRA_BIND.
* src/bind-gram.y: New file.
* src/bind-lex.l: New file.
* src/format.c (grecs_txtacc_format_value): New function.
* src/grecs.h (grecs_bind_parser): New proto.
* src/parser.c: Set grecs_current_locus.
* src/tree.c (grecs_node_bind): Return immediately if node==NULL.
* src/yytrans: Update.
Diffstat (limited to 'src')
-rw-r--r-- | src/.gitignore | 4 | ||||
-rw-r--r-- | src/Make.am | 13 | ||||
-rw-r--r-- | src/bind-gram.y | 296 | ||||
-rw-r--r-- | src/bind-lex.l | 224 | ||||
-rw-r--r-- | src/format.c | 54 | ||||
-rw-r--r-- | src/grecs.h | 10 | ||||
-rw-r--r-- | src/meta1-gram.y | 1 | ||||
-rw-r--r-- | src/parser.c | 2 | ||||
-rw-r--r-- | src/preproc.c | 8 | ||||
-rw-r--r-- | src/tree.c | 4 | ||||
-rw-r--r-- | src/yytrans | 5 |
11 files changed, 612 insertions, 9 deletions
diff --git a/src/.gitignore b/src/.gitignore index feb5040..0f52326 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -6,6 +6,10 @@ meta1-gram.c meta1-gram.h meta1-gram.output meta1-lex.c +bind-gram.c +bind-gram.h +bind-gram.output +bind-lex.c Make-inst.in Make-shared.in Make-static.in diff --git a/src/Make.am b/src/Make.am index 60c0f06..e05afc5 100644 --- a/src/Make.am +++ b/src/Make.am @@ -19,6 +19,11 @@ if GRECS_COND_META1_PARSER GRECS_EXTRA_META1 = meta1-gram.h endif +if GRECS_COND_BIND_PARSER + GRECS_PARSER_BIND = bind-gram.y bind-lex.l + GRECS_EXTRA_BIND = bind-gram.h +endif + GRECS_SRC = \ asprintf.c\ diag.c\ @@ -39,11 +44,17 @@ GRECS_SRC = \ txtacc.c\ version.c\ wordsplit.c\ + $(GRECS_PARSER_BIND)\ $(GRECS_PARSER_META1) noinst_HEADERS = -EXTRA_DIST=grecs-gram.h $(GRECS_EXTRA_META1) $(PP_SETUP_FILE) Make.am Make-inst.am Make-shared.am Make-static.am +EXTRA_DIST=\ + grecs-gram.h\ + $(GRECS_EXTRA_BIND)\ + $(GRECS_EXTRA_META1)\ + $(PP_SETUP_FILE)\ + Make.am Make-inst.am Make-shared.am Make-static.am INCLUDES = -I$(srcdir) -I$(top_srcdir)/@GRECS_SUBDIR@ @GRECS_INCLUDES@ @GRECS_HOST_PROJECT_INCLUDES@ AM_YFLAGS = -dtv diff --git a/src/bind-gram.y b/src/bind-gram.y new file mode 100644 index 0000000..621070e --- /dev/null +++ b/src/bind-gram.y @@ -0,0 +1,296 @@ +%{ +/* grecs - Gray's Extensible Configuration System + Copyright (C) 2007-2011 Sergey Poznyakoff + + Grecs is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3 of the License, or (at your + option) any later version. + + Grecs is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Grecs. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <grecs.h> +#include <grecs-gram.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> + +int yylex(void); +int yyerror(char *s); + +static struct grecs_node *parse_tree; +extern int yy_flex_debug; +extern int grecs_bind_new_source(const char *name); +extern void grecs_bind_close_sources(void); + +static struct grecs_value *stmtlist_to_value(struct grecs_node *node); +%} + +%union { + struct { + grecs_locus_t locus; + char *string; + } ident; + char *string; + grecs_value_t svalue, *pvalue; + struct grecs_list *list; + struct grecs_node *node; + grecs_locus_t locus; + struct { struct grecs_node *head, *tail; } node_list; +} + +%token <ident> BIND_IDENT +%token <string> BIND_STRING +%type <string> string +%type <svalue> value +%type <pvalue> vallist tag +%type <list> vlist +%type <node> stmt simple block +%type <node_list> stmtlist + +%% + +input : stmtlist + { + parse_tree = grecs_node_create(grecs_node_root, + &grecs_current_locus); + parse_tree->v.texttab = grecs_text_table(); + grecs_node_bind(parse_tree, $1.head, 1); + } + ; + +stmtlist: stmt + { + $$.head = $$.tail = $1; + } + | stmtlist stmt + { + if ($2) { + if (!$1.head) + $1.head = $1.tail = $2; + else + grecs_node_bind($1.tail, $2, 0); + } + $$ = $1; + } + ; + +stmt : simple + | block + ; + +simple : BIND_IDENT vallist ';' + { + if (strcmp($1.string, "include") == 0 && + $2->type == GRECS_TYPE_STRING) { + grecs_bind_new_source($2->v.string); + $$ = NULL; + } else { + $$ = grecs_node_create(grecs_node_stmt, &$1.locus); + $$->ident = $1.string; + $$->v.value = $2; + } + } + | string ';' + { + $$ = grecs_node_create(grecs_node_stmt, + &grecs_current_locus); + $$->ident = $1; + $$->v.value = NULL; + } + ; + +block : BIND_IDENT tag '{' stmtlist '}' opt_sc + { + $$ = grecs_node_create(grecs_node_block, &$1.locus); + $$->ident = $1.string; + $$->v.value = $2; + grecs_node_bind($$, $4.head, 1); + } + ; + +tag : /* empty */ + { + $$ = NULL; + } + | BIND_IDENT + { + $$ = grecs_malloc(sizeof($$[0])); + $$->type = GRECS_TYPE_STRING; + $$->v.string = $1.string; + } + | BIND_STRING + { + $$ = grecs_malloc(sizeof($$[0])); + $$->type = GRECS_TYPE_STRING; + $$->v.string = $1; + } + ; + +vallist : vlist + { + size_t n; + + if ((n = grecs_list_size($1)) == 1) { + $$ = grecs_list_index($1, 0); + } else { + size_t i; + struct grecs_list_entry *ep; + + $$ = grecs_malloc(sizeof($$[0])); + $$->type = GRECS_TYPE_ARRAY; + $$->v.arg.c = n; + $$->v.arg.v = grecs_calloc(n, + sizeof($$->v.arg.v[0])); + for (i = 0, ep = $1->head; ep; i++, ep = ep->next) + $$->v.arg.v[i] = ep->data; + } + $1->free_entry = NULL; + grecs_list_free($1); + } + ; + +vlist : value + { + $$ = grecs_value_list_create(); + grecs_list_append($$, grecs_value_ptr_from_static(&$1)); + } + | vlist value + { + grecs_list_append($1, grecs_value_ptr_from_static(&$2)); + } + | vlist BIND_IDENT '{' stmtlist '}' + /* This production handles constructs that don't fit well into + hierarchical structure, namely, the "controls" statement, e.g.: + + controls { + inet 127.0.0.1 port 953 + allow { 127.0.0.1; 127.0.0.2; } keys { "rndc-key"; }; + }; + + This statement produces: + + .controls.inet: 127.0.0.1 port 953 allow (127.0.0.1) keys + (rndc-key) + */ + { + struct grecs_value *val = grecs_malloc(sizeof(*val)); + val->type = GRECS_TYPE_STRING; + val->v.string = $2.string; + grecs_list_append($1, val); + + val = stmtlist_to_value($4.head); + /* FIXME: Free $4 */ + grecs_list_append($1, val); + } + ; + +value : string + { + $$.type = GRECS_TYPE_STRING; + $$.v.string = $1; + } + ; + +string : BIND_STRING + | BIND_IDENT + { + $$ = $1.string; + } + ; + +opt_sc : /* empty */ + | ';' + ; + +%% + +int +yyerror(char *s) +{ + grecs_error(&grecs_current_locus, 0, "%s", s); + return 0; +} + +struct grecs_node * +grecs_bind_parser(const char *name, int traceflags) +{ + int rc; + + if (grecs_bind_new_source(name)) + return NULL; + yy_flex_debug = traceflags & GRECS_TRACE_LEX; + yydebug = traceflags & GRECS_TRACE_GRAM; + parse_tree = NULL; + grecs_line_acc_create(); + rc = yyparse(); + grecs_bind_close_sources(); + if (grecs_error_count) + rc = 1; + grecs_line_acc_free(); + if (rc) { + grecs_tree_free(parse_tree); + parse_tree = NULL; + } + return parse_tree; +} + +static struct grecs_value * +node_to_value(struct grecs_node *node, struct grecs_txtacc *acc) +{ + struct grecs_value *val = grecs_malloc(sizeof(*val)); + int delim = 0; + + if (node->ident) { + grecs_txtacc_grow(acc, node->ident, strlen(node->ident)); + delim = 1; + } + + if (node->v.value) { + if (delim) + grecs_txtacc_grow_char(acc, ' '); + grecs_txtacc_format_value(node->v.value, 0, acc); + delim = 1; + } + if (node->type == grecs_node_stmt) { + val->type = GRECS_TYPE_STRING; + grecs_txtacc_grow_char(acc, 0); + val->v.string = grecs_txtacc_finish(acc, 1); + } else if (node->down) { + struct grecs_list *list = grecs_value_list_create(); + struct grecs_node *np; + + if (delim) + grecs_txtacc_grow_char(acc, ' '); + for (np = node->down; np; np = np->next) + grecs_list_append(list, node_to_value(np, acc)); + val->type = GRECS_TYPE_LIST; + val->v.list = list; + } + return val; +} + +static struct grecs_value * +stmtlist_to_value(struct grecs_node *node) +{ + struct grecs_txtacc *acc = grecs_txtacc_create(); + struct grecs_value *val; + struct grecs_node parent; + + memset(&parent, 0, sizeof(parent)); + parent.type = grecs_node_block; + parent.down = node; + val = node_to_value(&parent, acc); + grecs_txtacc_free(acc); + return val; +} diff --git a/src/bind-lex.l b/src/bind-lex.l new file mode 100644 index 0000000..12dddf7 --- /dev/null +++ b/src/bind-lex.l @@ -0,0 +1,224 @@ +/* grecs - Gray's Extensible Configuration System -*- c -*- */ +%top { +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +} +%{ +/* grecs - Gray's Extensible Configuration System + Copyright (C) 2007-2011 Sergey Poznyakoff + + Grecs is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3 of the License, or (at your + option) any later version. + + Grecs is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Grecs. If not, see <http://www.gnu.org/licenses/>. */ + +#include <grecs.h> +#include <bind-gram.h> +#include <unistd.h> +#include <fcntl.h> +#include <ctype.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/stat.h> + +#include <wordsplit.h> + +%} + +%x COMMENT STR + +WS [ \t\f][ \t\f]* +ID [a-zA-Z_][a-zA-Z_0-9-]* +P [1-9][0-9]* + +%% + /* C-style comments */ +"/*" BEGIN(COMMENT); +<COMMENT>[^*\n]* /* eat anything that's not a '*' */ +<COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */ +<COMMENT>\n ++grecs_current_locus.line; +<COMMENT>"*"+"/" BEGIN(INITIAL); + /* End-of-line comments */ +#.*\n { grecs_current_locus.line++; } +#.* /* end-of-file comment */; +"//".*\n { grecs_current_locus.line++; } +"//".* /* end-of-file comment */; + /* Identifiers */ +{ID} { grecs_line_begin(); + grecs_line_add(yytext, yyleng); + yylval.ident.string = grecs_line_finish(); + yylval.ident.locus = grecs_current_locus; + return BIND_IDENT; + } + /* Strings */ +[a-zA-Z0-9_\.\*/:@-]+ { grecs_line_begin(); + grecs_line_add(yytext, yyleng); + yylval.string = grecs_line_finish(); + return BIND_STRING; } + /* Quoted strings */ +\"[^\\"\n]*\" { grecs_line_begin(); + grecs_line_add(yytext + 1, yyleng - 2); + yylval.string = grecs_line_finish(); + return BIND_STRING; } +\"[^\\"\n]*\\. | +\"[^\\"\n]*\\\n { BEGIN(STR); + grecs_line_begin(); + grecs_line_acc_grow_unescape_last(yytext + 1, + yyleng - 1); } +\"[^\\"\n]*\n { BEGIN(STR); + grecs_line_begin(); + grecs_line_acc_grow(yytext + 1, yyleng - 1); } +<STR>[^\\"\n]*\\. | +<STR>\"[^\\"\n]*\\\n { grecs_line_acc_grow_unescape_last(yytext, yyleng); } +<STR>[^\\"\n]*\n | +<STR>\"[^\\"\n]*\n { grecs_line_acc_grow(yytext, yyleng); } +<STR>[^\\"\n]*\" { BEGIN(INITIAL); + if (yyleng > 1) + grecs_line_add(yytext, yyleng - 1); + yylval.string = grecs_line_finish(); + return BIND_STRING; } +{WS} ; + /* Other tokens */ +\n { grecs_current_locus.line++; } +[,;{}()] return yytext[0]; +. { if (isascii(yytext[0]) && isprint(yytext[0])) + grecs_error(&grecs_current_locus, 0, + _("stray character %c"), yytext[0]); + else + grecs_error(&grecs_current_locus, 0, _("stray character \\%03o"), + (unsigned char) yytext[0]); } +%% + +struct bind_input_context { + ino_t i_node; + dev_t i_dev; + grecs_locus_t locus; /* Current input location */ + YY_BUFFER_STATE state; + FILE *input; +}; + +static struct grecs_list *input_stack; +static ino_t i_node; +static dev_t i_dev; + +static void +free_context(void *ptr) +{ + free(ptr); +} + +static int +cmp_context(const void *a, const void *b) +{ + struct bind_input_context const *ac = a; + struct bind_input_context const *bc = b; + + return !(ac->i_node == bc->i_node && ac->i_dev == bc->i_dev); +} + +static int +_push_context(const char *name, ino_t i_node, dev_t i_dev) +{ + struct bind_input_context ctx, *pctx; + + if (!input_stack) { + input_stack = grecs_list_create(); + input_stack->free_entry = free_context; + input_stack->cmp = cmp_context; + } else { + ctx.i_dev = i_dev; + ctx.i_node = i_node; + pctx = grecs_list_locate(input_stack, &ctx); + if (pctx) { + grecs_error(&grecs_current_locus, 0, + _("%s has already been included"), name); + grecs_error(&pctx->locus, 0, + _("this is where the previous inclusion occurred")); + return 1; + } + + pctx = grecs_malloc(sizeof(*pctx)); + pctx->i_node = i_node; + pctx->i_dev = i_dev; + pctx->locus = grecs_current_locus; + pctx->state = YY_CURRENT_BUFFER; + pctx->input = yyin; + grecs_list_push(input_stack, pctx); + } + return 0; +} + +static int +_pop_context() +{ + struct bind_input_context *pctx; + + if (!yyin) + return 1; + fclose(yyin); + pctx = grecs_list_pop(input_stack); + if (!pctx) { + yyin = NULL; + return 1; + } + i_node = pctx->i_node; + i_dev = pctx->i_dev; + grecs_current_locus = pctx->locus; + yyin = pctx->input; + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(pctx->state); + grecs_free(pctx); + return 0; +} + +int +yywrap() +{ + return _pop_context(); +} + +int +grecs_bind_new_source(const char *name) +{ + grecs_locus_t *loc = grecs_current_locus.file ? + &grecs_current_locus : NULL; + struct stat st; + FILE *fp = fopen(name, "r"); + if (!fp) { + grecs_error(loc, errno, _("cannot open `%s'"), name); + return 1; + } + if (fstat(fileno(fp), &st)) { + grecs_error(loc, errno, _("can't state %s"), name); + fclose(fp); + return 1; + } + if (_push_context(name, st.st_ino, st.st_dev)) { + fclose(fp); + return 1; + } + i_node = st.st_ino; + i_dev = st.st_dev; + yyin = fp; + yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); + grecs_current_locus.file = grecs_install_text(name); + grecs_current_locus.line = 1; + return 0; +} + +void +grecs_bind_close_sources() +{ + while (!_pop_context()) + ; + grecs_list_free(input_stack); +} diff --git a/src/format.c b/src/format.c index 1302520..a6b3bd9 100644 --- a/src/format.c +++ b/src/format.c @@ -262,6 +262,60 @@ grecs_format_value(struct grecs_value *val, int flags, FILE *fp) } void +grecs_txtacc_format_value(struct grecs_value *val, int flags, + struct grecs_txtacc *acc) +{ + int i; + struct grecs_list_entry *ep; + size_t clen; + int need_quote; + + if (!val) + return; + switch (val->type) { + case GRECS_TYPE_STRING: + clen = wordsplit_c_quoted_length(val->v.string, + flags & GRECS_NODE_FLAG_QUOTE_HEX, + &need_quote); + if (flags & GRECS_NODE_FLAG_QUOTE) + need_quote = 1; + else if (flags & GRECS_NODE_FLAG_NOQUOTE) + need_quote = 0; + if (need_quote) { + char *cbuf = grecs_malloc(clen + 1); + wordsplit_c_quote_copy(cbuf, val->v.string, + flags & GRECS_NODE_FLAG_QUOTE_HEX); + grecs_txtacc_grow_char(acc, '"'); + grecs_txtacc_grow(acc, cbuf, clen); + grecs_txtacc_grow_char(acc, '"'); + grecs_free(cbuf); + } else + grecs_txtacc_grow(acc, val->v.string, + strlen(val->v.string)); + break; + + case GRECS_TYPE_LIST: + grecs_txtacc_grow_char(acc, '('); + for (ep = val->v.list->head; ep; ep = ep->next) { + grecs_txtacc_format_value(ep->data, flags, acc); + if (ep->next) { + grecs_txtacc_grow_char(acc, ','); + grecs_txtacc_grow_char(acc, ' '); + } + } + grecs_txtacc_grow_char(acc, ')'); + break; + + case GRECS_TYPE_ARRAY: + for (i = 0; i < val->v.arg.c; i++) { + if (i) + grecs_txtacc_grow_char(acc, ' '); + grecs_txtacc_format_value(val->v.arg.v[i], flags, acc); + } + } +} + +void grecs_format_node(struct grecs_node *node, int flags, FILE *fp) { const char *delim_str = NULL; diff --git a/src/grecs.h b/src/grecs.h index ff47698..48b53ae 100644 --- a/src/grecs.h +++ b/src/grecs.h @@ -217,6 +217,7 @@ extern struct grecs_node *(*grecs_parser_fun)(const char *name, int trace); /* Parsers: */ struct grecs_node *grecs_grecs_parser(const char *name, int traceflags); struct grecs_node *grecs_meta1_parser(const char *name, int traceflags); +struct grecs_node *grecs_bind_parser(const char *name, int traceflags); struct grecs_list *_grecs_simple_list_create(int dispose); @@ -288,6 +289,10 @@ void grecs_format_locus(grecs_locus_t *locus, FILE *fp); void grecs_format_node_path(struct grecs_node *node, int flag, FILE *fp); void grecs_format_value(struct grecs_value *val, int flags, FILE *fp); +struct grecs_txtacc; +void grecs_txtacc_format_value(struct grecs_value *val, int flags, + struct grecs_txtacc *acc); + #define GRECS_NODE_FLAG_LOCUS 0x0100 #define GRECS_NODE_FLAG_PATH 0x0200 #define GRECS_NODE_FLAG_VALUE 0x0400 @@ -320,6 +325,11 @@ int grecs_asprintf(char **pbuf, size_t *psize, const char *fmt, ...); struct grecs_txtacc *grecs_txtacc_create(void); void grecs_txtacc_free(struct grecs_txtacc *acc); void grecs_txtacc_grow(struct grecs_txtacc *acc, const char *buf, size_t size); +#define grecs_txtacc_grow_char(acc,c) \ + do { \ + char __ch = c; \ + grecs_txtacc_grow(acc,&__ch,1); \ + } while (0) char *grecs_txtacc_finish(struct grecs_txtacc *acc, int steal); void grecs_txtacc_free_string(struct grecs_txtacc *acc, char *str); diff --git a/src/meta1-gram.y b/src/meta1-gram.y index 8ddcbfb..2983221 100644 --- a/src/meta1-gram.y +++ b/src/meta1-gram.y @@ -198,7 +198,6 @@ grecs_meta1_parser(const char *name, int traceflags) return NULL; } yyset_in(fp); - yy_flex_debug = traceflags & GRECS_TRACE_LEX; yydebug = traceflags & GRECS_TRACE_GRAM; parse_tree = NULL; diff --git a/src/parser.c b/src/parser.c index 6f84bd8..5d8bdf3 100644 --- a/src/parser.c +++ b/src/parser.c @@ -56,5 +56,7 @@ struct grecs_node * grecs_parse(const char *name) { grecs_error_count = 0; + grecs_current_locus.file = grecs_install_text(name); + grecs_current_locus.line = 0; return grecs_parser_fun(name, grecs_trace_flags); } diff --git a/src/preproc.c b/src/preproc.c index ea77506..8debdcf 100644 --- a/src/preproc.c +++ b/src/preproc.c @@ -48,7 +48,7 @@ struct buffer_ctx { FILE *infile; }; -extern int grecs_yy_flex_debug; +extern int grecs_grecs__flex_debug; static struct buffer_ctx *context_stack; static char *linebufbase = NULL; static size_t linebufsize = 0; @@ -432,7 +432,7 @@ push_source(const char *name, int once) ctx->prev = context_stack; context_stack = ctx; - if (grecs_yy_flex_debug) + if (grecs_grecs__flex_debug) fprintf (stderr, "Processing file `%s'\n", name); pp_line_stmt(); @@ -456,14 +456,14 @@ pop_source() context_stack = ctx; if (!context_stack) { - if (grecs_yy_flex_debug) + if (grecs_grecs__flex_debug) fprintf(stderr, "End of input\n"); return 1; } LOCUS.line++; - if (grecs_yy_flex_debug) + if (grecs_grecs__flex_debug) fprintf(stderr, "Resuming file `%s' at line %lu\n", LOCUS.file, (unsigned long) LOCUS.line); @@ -66,7 +66,9 @@ void grecs_node_bind(struct grecs_node *master, struct grecs_node *node, int dn) { struct grecs_node *np; - + + if (!node) + return; if (dn) { if (!master->down) { master->down = node; diff --git a/src/yytrans b/src/yytrans index d78fe26..9de7462 100644 --- a/src/yytrans +++ b/src/yytrans @@ -16,5 +16,6 @@ # # See build-aux/yyrename for a description of this file. -grecs grecs_yy -meta1 grecs_meta1_yy +grecs grecs_grecs_ +meta1 grecs_meta1_ +bind grecs_bind_ |