aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/git-parser.c157
1 files changed, 102 insertions, 55 deletions
diff --git a/src/git-parser.c b/src/git-parser.c
index 37eeab7..4ab64be 100644
--- a/src/git-parser.c
+++ b/src/git-parser.c
@@ -37,9 +37,9 @@ static struct grecs_txtacc *acc;
struct token {
int type;
char *buf;
- char *tag;
char chbuf[2];
int putback;
+ struct grecs_list *path;
} tok;
#define ISSPACE(c) (strchr(" \t\r\f\n", c) != NULL)
@@ -50,10 +50,12 @@ static int
rawinput()
{
if (!infile || feof(infile))
- return 0;
+ return input_char = 0;
input_char = fgetc(infile);
if (input_char == '\n')
grecs_current_locus.line++;
+ else if (input_char < 0)
+ input_char == 0;
return input_char;
}
@@ -86,13 +88,23 @@ error_recovery()
}
static void
-collect_tag()
+collect_unquoted()
{
+ do
+ grecs_txtacc_grow_char(acc, input_char);
while (input() &&
- !(ISSPACE(input_char) || input_char == ']'))
+ !(ISSPACE(input_char) || input_char == ']'));
+
+}
+
+static void
+collect_subsection_name()
+{
+ do
grecs_txtacc_grow_char(acc, input_char);
- grecs_txtacc_grow_char(acc, 0);
- tok.tag = grecs_txtacc_finish(acc, 0);
+ while (input() &&
+ (isalnum(input_char) || input_char == '_' ||
+ input_char == '-'));
}
static void
@@ -122,14 +134,6 @@ collect_substring()
}
static void
-collect_string()
-{
- collect_substring();
- grecs_txtacc_grow_char(acc, 0);
- tok.tag = grecs_txtacc_finish(acc, 0);
-}
-
-static void
gettoken(void)
{
int putback = tok.putback;
@@ -137,7 +141,7 @@ gettoken(void)
if (putback)
return;
- tok.buf = tok.tag = NULL;
+ tok.buf = NULL;
/* Skip whitespace */
while (input() && ISSPACE(input_char))
;
@@ -148,38 +152,70 @@ gettoken(void)
}
if (input_char == '[') {
+ int dot_delimited = -1;
+
tok.type = TOK_SECTION;
- while (input() &&
- !(ISSPACE(input_char) || input_char == ']'))
- grecs_txtacc_grow_char(acc, input_char);
- grecs_txtacc_grow_char(acc, 0);
- tok.buf = grecs_txtacc_finish(acc, 0);
- if (input_char != ']') {
- while (input() && ISSPACE(input_char))
- ;
- if (input_char == '"')
- collect_string();
- else if (input_char != ']')
- collect_tag();
- }
- if (input_char != ']') {
- while (input() && ISSPACE(input_char))
- ;
- if (input_char != ']') {
- if (isascii(input_char) && isprint(input_char))
- grecs_error(&grecs_current_locus, 0,
- "expected `]' but found `%c'",
- input_char);
- else if (!input_char)
- grecs_error(&grecs_current_locus, 0,
- "expected `]' but found EOF");
- else
- grecs_error(&grecs_current_locus, 0,
- "expected `]' but found \\%03o",
- (unsigned char)input_char);
+ grecs_list_clear(tok.path);
+ input();
+ for (;;) {
+ char *p;
+
+ if (!dot_delimited)
+ while (ISSPACE(input_char))
+ input();
+ else {
+ if (input_char == ']')
+ break;
+ if (dot_delimited == 1)
+ input();
+ }
+
+ if (input_char == TOK_EOF) {
+ grecs_error(&grecs_current_locus, 0,
+ "unexpected EOF in section header");
+ tok.type = TOK_ERR;
+ return;
+ }
+ if (input_char == ']')
+ break;
+ if (input_char == '\n') {
+ grecs_error(&grecs_current_locus, 0,
+ "unexpect newline in in section header");
tok.type = TOK_ERR;
+ return;
}
+
+ if (dot_delimited != 1 && input_char == '"') {
+ collect_substring();
+ input();
+ dot_delimited = 0;
+ } else if (dot_delimited == 1)
+ collect_subsection_name();
+ else
+ collect_unquoted();
+ if (dot_delimited == -1)
+ dot_delimited = input_char == '.';
+ else if (dot_delimited == 1) {
+ if (input_char != '.' && input_char != ']') {
+ grecs_error(&grecs_current_locus, 0,
+ "unexpected character in section header");
+ tok.type = TOK_ERR;
+ return;
+ }
+ }
+ grecs_txtacc_grow_char(acc, 0);
+ p = grecs_txtacc_finish(acc, 0);
+ grecs_list_append(tok.path, p);
+ }
+
+ if (grecs_list_size(tok.path) == 0) {
+ grecs_error(&grecs_current_locus, 0,
+ "empty section header");
+ tok.type = TOK_ERR;
+ return;
}
+
+ tok.type = TOK_SECTION;
return;
}
@@ -293,6 +329,26 @@ read_statement_list(struct grecs_node *parent)
;
}
+struct grecs_node *
+create_subsection_node(struct grecs_node *root)
+{
+ struct grecs_list_entry *ep;
+ struct grecs_node *p;
+
+ for (ep = tok.path->head; ep; ep = ep->next) {
+ char *ident = ep->data;
+ p = grecs_find_node(root, ident);
+ if (!p) {
+ p = grecs_node_create(grecs_node_block,
+ &grecs_current_locus);
+ p->ident = grecs_strdup(ident);
+ grecs_node_bind(root, p, 1);
+ }
+ root = p;
+ }
+ return root;
+}
+
static int
read_section(struct grecs_node *parent)
{
@@ -300,17 +356,7 @@ read_section(struct grecs_node *parent)
if (tok.type == TOK_EOF)
return 0;
else if (tok.type == TOK_SECTION) {
- struct grecs_node *node =
- grecs_node_create(grecs_node_block,
- &grecs_current_locus);
- node->ident = grecs_strdup(tok.buf);
- if (tok.tag) {
- struct grecs_value *val= grecs_malloc(sizeof(val[0]));
- val->type = GRECS_TYPE_STRING;
- val->v.string = grecs_strdup(tok.tag);
- node->v.value = val;
- }
- grecs_node_bind(parent, node, 1);
+ struct grecs_node *node = create_subsection_node(parent);
read_statement_list(node);
} else if (tok.type == TOK_KEYWORD) {
read_statement(parent);
@@ -336,13 +382,14 @@ grecs_git_parser(const char *name, int traceflags)
grecs_current_locus.line = 1;
acc = grecs_txtacc_create();
-
+ tok.path = grecs_list_create();
root = grecs_node_create(grecs_node_root, &grecs_current_locus);
while (read_section(root))
;
fclose(infile);
grecs_txtacc_free(acc);
+ grecs_list_free(tok.path);
if (grecs_error_count) {
grecs_tree_free(root);
root = NULL;

Return to:

Send suggestions and report system problems to the System administrator.