aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2011-05-16 01:08:45 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2011-05-16 01:17:20 +0300
commite559f3f36c99988ee80ac4ec01f80ea6578beebe (patch)
treee9cd0ab93dc2901fce901a062c7c1ee7442979e5 /src
parenta0826b4c7cd66c4862d9b61bb7e14d73fcba28f6 (diff)
downloadgrecs-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/.gitignore4
-rw-r--r--src/Make.am13
-rw-r--r--src/bind-gram.y296
-rw-r--r--src/bind-lex.l224
-rw-r--r--src/format.c54
-rw-r--r--src/grecs.h10
-rw-r--r--src/meta1-gram.y1
-rw-r--r--src/parser.c2
-rw-r--r--src/preproc.c8
-rw-r--r--src/tree.c4
-rw-r--r--src/yytrans5
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
@@ -3,9 +3,13 @@ grecs-gram.h
grecs-gram.output
grecs-lex.c
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
@@ -16,12 +16,17 @@
if GRECS_COND_META1_PARSER
GRECS_PARSER_META1 = meta1-gram.y meta1-lex.l
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\
format.c\
grecs-gram.y\
grecs-lex.l\
@@ -36,17 +41,23 @@ GRECS_SRC = \
symtab.c\
text.c\
tree.c\
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
AM_LFLAGS = -d
incdir=$(pkgdatadir)/$(VERSION)/include
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
@@ -259,12 +259,66 @@ grecs_format_value(struct grecs_value *val, int flags, FILE *fp)
grecs_format_value(val->v.arg.v[i], flags, 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;
if (!flags)
flags = GRECS_NODE_FLAG_DEFAULT;
diff --git a/src/grecs.h b/src/grecs.h
index ff47698..48b53ae 100644
--- a/src/grecs.h
+++ b/src/grecs.h
@@ -214,12 +214,13 @@ struct grecs_node *grecs_parse(const char *name);
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);
struct grecs_list *grecs_value_list_create(void);
void grecs_line_acc_create(void);
@@ -285,12 +286,16 @@ void grecs_format_statement_array(struct grecs_keyword *kwp,
unsigned level, FILE *stream);
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
#define GRECS_NODE_FLAG_QUOTE 0x0800
#define GRECS_NODE_FLAG_NOQUOTE 0x1000
#define GRECS_NODE_FLAG_QUOTE_HEX 0x2000
@@ -317,12 +322,17 @@ int grecs_vasprintf(char **pbuf, size_t *psize, const char *fmt, va_list ap);
int grecs_asprintf(char **pbuf, size_t *psize, const char *fmt, ...);
#define GRECS_TXTACC_BUFSIZE 1024
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);
struct grecs_symtab;
struct grecs_syment {
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
@@ -195,13 +195,12 @@ grecs_meta1_parser(const char *name, int traceflags)
fp = fopen(name, "r");
if (!fp) {
grecs_error(NULL, errno, _("Cannot open `%s'"), name);
return NULL;
}
yyset_in(fp);
-
yy_flex_debug = traceflags & GRECS_TRACE_LEX;
yydebug = traceflags & GRECS_TRACE_GRAM;
parse_tree = NULL;
grecs_line_acc_create();
rc = yyparse();
fclose(fp);
diff --git a/src/parser.c b/src/parser.c
index 6f84bd8..5d8bdf3 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -53,8 +53,10 @@ grecs_lex_trace(int n)
}
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
@@ -45,13 +45,13 @@ struct buffer_ctx {
size_t namelen; /* Length of the file name */
size_t xlines; /* Number of #line directives output so far */
struct input_file_ident id;
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;
#define INFILE context_stack->infile
#define LOCUS context_stack->locus
@@ -429,13 +429,13 @@ push_source(const char *name, int once)
ctx->id.i_node = st.st_ino;
ctx->id.device = st.st_dev;
ctx->infile = fp;
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();
return 0;
}
@@ -453,20 +453,20 @@ pop_source()
/* Restore previous context */
ctx = context_stack->prev;
grecs_free(context_stack);
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);
pp_line_stmt();
return 0;
diff --git a/src/tree.c b/src/tree.c
index ceb6688..58b34a5 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -63,13 +63,15 @@ grecs_node_create(enum grecs_node_type type, grecs_locus_t *loc)
}
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;
node->prev = NULL;
} else {
for (np = master->down; np->next; np = np->next)
diff --git a/src/yytrans b/src/yytrans
index d78fe26..9de7462 100644
--- a/src/yytrans
+++ b/src/yytrans
@@ -13,8 +13,9 @@
#
# You should have received a copy of the GNU General Public License
# along with Grecs. If not, see <http://www.gnu.org/licenses/>.
#
# 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_

Return to:

Send suggestions and report system problems to the System administrator.