diff options
Diffstat (limited to '')
-rw-r--r-- | libparser-generate.c | 146 |
1 files changed, 103 insertions, 43 deletions
diff --git a/libparser-generate.c b/libparser-generate.c index f5f19ae..25fb8a9 100644 --- a/libparser-generate.c +++ b/libparser-generate.c @@ -1,10 +1,20 @@ /* See LICENSE file for copyright and license details. */ -#include <libsimple.h> +#include <ctype.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> #include <libsimple-arg.h> USAGE("main-rule"); +#define eprintf(...) (fprintf(stderr, __VA_ARGS__), exit(1)) + + struct token { size_t lineno; size_t column; @@ -30,6 +40,55 @@ static size_t nwant_rules = 0; static size_t want_rules_size = 0; +static void * +emalloc(size_t n) +{ + void *ret = malloc(n); + if (!ret) + eprintf("%s: malloc %zu: %s\n", argv0, n, strerror(errno)); + return ret; +} + +static void * +ecalloc(size_t n, size_t m) +{ + void *ret = calloc(n, m); + if (!ret) + eprintf("%s: calloc %zu %zu: %s\n", argv0, n, m, strerror(errno)); + return ret; +} + +static void * +erealloc(void *ptr, size_t n) +{ + void *ret = realloc(ptr, n); + if (!ret) + eprintf("%s: realloc %p %zu: %s\n", argv0, ptr, n, strerror(errno)); + return ret; +} + +static void * +ereallocarray(void *ptr, size_t n, size_t m) +{ + void *ret; + if (n && m > SIZE_MAX / n) + eprintf("%s: realloc %p %zu*%zu: %s\n", argv0, ptr, n, m, strerror(EOVERFLOW)); + ret = realloc(ptr, n * n); + if (!ret) + eprintf("%s: realloc %p %zu*%zu: %s\n", argv0, ptr, n, m, strerror(errno)); + return ret; +} + +static char * +estrdup(char *s) +{ + size_t n = strlen(s) + 1; + char *ret = emalloc(n); + memcpy(ret, s, n); + return ret; +} + + static int strpcmp(const void *av, const void *bv) { @@ -101,7 +160,7 @@ readall_and_validate(int fd, const char *fname) if (r <= 0) { if (!r) break; - eprintf("read %s:", fname); + eprintf("%s: read %s: %s\n", argv0, fname, strerror(errno)); } } @@ -114,24 +173,24 @@ readall_and_validate(int fd, const char *fname) column += 8 - column % 8; character += 1; } else if (buf[i] == '\r') { - eprintf("%s contains a CR character on line %zu at column %zu (character %zu)\n", - fname, lineno, column, character); + eprintf("%s: %s contains a CR character on line %zu at column %zu (character %zu)\n", + argv0, fname, lineno, column, character); } else if ((0 < buf[i] && buf[i] < ' ') || buf[i] == 0x7F) { - eprintf("%s contains a illegal character on line %zu at column %zu (character %zu)\n", - fname, lineno, column, character); + eprintf("%s: %s contains a illegal character on line %zu at column %zu (character %zu)\n", + argv0, fname, lineno, column, character); } else if (buf[i] == '\0') { - eprintf("%s contains a NUL byte on line %zu at column %zu (character %zu)\n", - fname, lineno, column, character); + eprintf("%s: %s contains a NUL byte on line %zu at column %zu (character %zu)\n", + argv0, fname, lineno, column, character); } else if (!(buf[i] & 0x80)) { character += 1; column += 1; } else if ((buf[i] & 0xC0) == 0x80) { - eprintf("%s contains a illegal byte on line %zu at column %zu (character %zu)\n", - fname, lineno, column, character); + eprintf("%s: %s contains a illegal byte on line %zu at column %zu (character %zu)\n", + argv0, fname, lineno, column, character); } else { if (!check_utf8(buf, &i, len)) { - eprintf("%s contains a illegal byte sequence on line %zu at column %zu (character %zu)\n", - fname, lineno, column, character); + eprintf("%s: %s contains a illegal byte sequence on line %zu at column %zu (character %zu)\n", + argv0, fname, lineno, column, character); } i--; character += 1; @@ -180,8 +239,8 @@ tokenise(const char *data) } else if (data[i] == '"') { state = STRING; if (data[i + 1] == '"') { - eprintf("empty string token on line %zu at column %zu (character %zu)\n", - lineno, column, character); + eprintf("%s: empty string token on line %zu at column %zu (character %zu)\n", + argv0, lineno, column, character); } } else { add_token: @@ -189,7 +248,7 @@ tokenise(const char *data) token = erealloc(token, token_size += 16); token[token_len++] = '\0'; if (ntokens == tokens_size) - tokens = ereallocn(tokens, tokens_size += 16, sizeof(*tokens), 0); + tokens = ereallocarray(tokens, tokens_size += 16, sizeof(*tokens)); tokens[ntokens] = emalloc(offsetof(struct token, s) + token_len); tokens[ntokens]->lineno = token_lineno; tokens[ntokens]->column = token_column; @@ -212,7 +271,7 @@ tokenise(const char *data) token = erealloc(token, token_size += 16); token[token_len++] = '\0'; if (ntokens == tokens_size) - tokens = ereallocn(tokens, tokens_size += 16, sizeof(*tokens), 0); + tokens = ereallocarray(tokens, tokens_size += 16, sizeof(*tokens)); tokens[ntokens] = emalloc(offsetof(struct token, s) + token_len); tokens[ntokens]->lineno = token_lineno; tokens[ntokens]->column = token_column; @@ -226,8 +285,8 @@ tokenise(const char *data) case STRING: if (data[i] == '\n' || data[i] == '\t') { - eprintf("illegal whitespace on line %zu at column %zu (character %zu)\n", - lineno, column, character); + eprintf("%s: illegal whitespace on line %zu at column %zu (character %zu)\n", + argv0, lineno, column, character); } else if (data[i] == '"') { goto add_token; } else if (data[i] == '\\') { @@ -240,8 +299,8 @@ tokenise(const char *data) case STRING_ESC: if (data[i] == '\n' || data[i] == '\t') { - eprintf("illegal whitespace on line %zu at column %zu (character %zu)\n", - lineno, column, character); + eprintf("%s: illegal whitespace on line %zu at column %zu (character %zu)\n", + argv0, lineno, column, character); } if (token_len == token_size) token = erealloc(token, token_size += 16); @@ -274,9 +333,9 @@ tokenise(const char *data) } } if (state != NEW_TOKEN && state != SPACE) - eprintf("premature end of file\n"); + eprintf("%s: premature end of file\n", argv0); - tokens = ereallocn(tokens, ntokens + 1, sizeof(*tokens), 0); + tokens = ereallocarray(tokens, ntokens + 1, sizeof(*tokens)); tokens[ntokens] = NULL; free(token); @@ -324,7 +383,7 @@ emit_and_free_sentence(struct node *node, size_t *indexp) nrule_names, index); } else { if (nwant_rules == want_rules_size) - want_rules = ereallocn(want_rules, want_rules_size += 16, sizeof(*want_rules), 0); + want_rules = ereallocarray(want_rules, want_rules_size += 16, sizeof(*want_rules)); want_rules[nwant_rules++] = estrdup(node->token->s); printf("static union libparser_sentence sentence_%zu_%zu = {.rule = {" ".type = LIBPARSER_SENTENCE_TYPE_RULE, .rule = \"%s\"" @@ -410,7 +469,7 @@ emit_and_free_rule(struct node *rule) printf("static struct libparser_rule rule_%zu = {\"%s\", &sentence_%zu_0};\n", nrule_names, rule->token->s, nrule_names); if (nrule_names == rule_names_size) - rule_names = ereallocn(rule_names, rule_names_size += 16, sizeof(*rule_names), 0); + rule_names = ereallocarray(rule_names, rule_names_size += 16, sizeof(*rule_names)); rule_names[nrule_names++] = estrdup(rule->token->s); free(rule->token); free(rule); @@ -464,7 +523,7 @@ again: goto again; } } - eprintf("premature end of file\n"); + eprintf("%s: premature end of file\n", argv0); } if (tokens[i]->s[0] == '"') { @@ -481,8 +540,8 @@ again: switch (state) { case NEW_RULE: if (type != IDENTIFIER) { - eprintf("expected an identifier on line %zu at column %zu (character %zu)\n", - tokens[i]->lineno, tokens[i]->column, tokens[i]->character); + eprintf("%s: expected an identifier on line %zu at column %zu (character %zu)\n", + argv0, tokens[i]->lineno, tokens[i]->column, tokens[i]->character); } stack = calloc(1, sizeof(*stack)); stack->token = tokens[i]; @@ -490,16 +549,16 @@ again: state = EXPECT_EQUALS; for (j = 0; j < nrule_names; j++) { if (!strcmp(rule_names[j], tokens[i]->s)) { - eprintf("duplicate definition of \"%s\" on line %zu at column %zu (character %zu)\n", - tokens[i]->s, tokens[i]->lineno, tokens[i]->column, tokens[i]->character); + eprintf("%s: duplicate definition of \"%s\" on line %zu at column %zu (character %zu)\n", + argv0, tokens[i]->s, tokens[i]->lineno, tokens[i]->column, tokens[i]->character); } } break; case EXPECT_EQUALS: if (type != SYMBOL || tokens[i]->s[0] != '=') { - eprintf("expected an '=' on line %zu at column %zu (character %zu)\n", - tokens[i]->lineno, tokens[i]->column, tokens[i]->character); + eprintf("%s: expected an '=' on line %zu at column %zu (character %zu)\n", + argv0, tokens[i]->lineno, tokens[i]->column, tokens[i]->character); } free(tokens[i]); state = EXPECT_OPERAND; @@ -517,8 +576,8 @@ again: goto add; } else { stray: - eprintf("stray '%c' on line %zu at column %zu (character %zu)\n", - tokens[i]->s[0], tokens[i]->lineno, tokens[i]->column, tokens[i]->character); + eprintf("%s: stray '%c' on line %zu at column %zu (character %zu)\n", + argv0, tokens[i]->s[0], tokens[i]->lineno, tokens[i]->column, tokens[i]->character); } } else { add: @@ -553,15 +612,16 @@ again: stack = stack->parent; } else if (tokens[i]->s[0] == ';') { if (stack->token->s[0] == ')' || stack->token->s[0] == ']' || stack->token->s[0] == '}') - eprintf("premature end of rule on line %zu at column %zu (character %zu): " + eprintf("%s: premature end of rule on line %zu at column %zu (character %zu): " "'%s' on line %zu at column %zu (character %zu) not closed\n", - tokens[i]->lineno, tokens[i]->column, tokens[i]->character, stack->token->s, + argv0, tokens[i]->lineno, tokens[i]->column, tokens[i]->character, stack->token->s, stack->token->lineno, stack->token->column, stack->token->character); emit_and_free_rule(stack); free(tokens[i]); state = NEW_RULE; } else { - eprintf("expected a '|', ',', or '%c' on line %zu at column %zu (character %zu)\n", + eprintf("%s: expected a '|', ',', or '%c' on line %zu at column %zu (character %zu)\n", + argv0, stack->token->s[0] == '(' ? ')' : stack->token->s[0] == '[' ? ']' : stack->token->s[0] == '{' ? '}' : ';', @@ -575,7 +635,7 @@ again: } free(tokens); if (state != NEW_RULE) - eprintf("premature end of file\n"); + eprintf("%s: premature end of file\n", argv0); err = 0; qsort(rule_names, nrule_names, sizeof(*rule_names), strpcmp); @@ -588,23 +648,23 @@ again: } else if (!strcmp(rule_names[i], argv[0])) { i++; } else if (cmp < 0) { - weprintf("rule \"%s\" defined but not used\n", rule_names[i]); + eprintf("%s: rule \"%s\" defined but not used\n", argv0, rule_names[i]); i++; err = 1; } else { - weprintf("rule \"%s\" used but not defined\n", want_rules[j]); + eprintf("%s: rule \"%s\" used but not defined\n", argv0, want_rules[j]); for (j++; j < nwant_rules && !strcmp(want_rules[j - 1], want_rules[j]); j++); err = 1; } } for (; i < nrule_names; i++) { if (strcmp(rule_names[i], argv[0])) { - weprintf("rule \"%s\" defined but not used\n", rule_names[i]); + eprintf("%s: rule \"%s\" defined but not used\n", argv0, rule_names[i]); err = 1; } } while (j < nwant_rules) { - weprintf("rule \"%s\" used but not defined\n", want_rules[j]); + eprintf("%s: rule \"%s\" used but not defined\n", argv0, want_rules[j]); for (j++; j < nwant_rules && !strcmp(want_rules[j - 1], want_rules[j]); j++); err = 1; } @@ -614,7 +674,7 @@ again: for (i = 0; i < nrule_names; i++) if (!strcmp(rule_names[i], argv[0])) goto found_main; - eprintf("specified main rule (\"%s\") was not defined\n", argv[0]); + eprintf("%s: specified main rule (\"%s\") was not defined\n", argv0, argv[0]); found_main: printf("static union libparser_sentence noeof_sentence = {.type = LIBPARSER_SENTENCE_TYPE_EXCEPTION};\n"); @@ -659,6 +719,6 @@ found_main: free(want_rules); if (ferror(stdout) || fflush(stdout) || fclose(stdout)) - eprintf("printf:"); + eprintf("%s: printf: %s\n", argv0, strerror(errno)); return 0; } |