/*------------------------------------------------------------------------- * * main.c * Standalone driver for the BKI bootstrap parser (Lime version). * * This program reads BKI input from stdin or a file and parses it * using the Lime-generated bootstrap parser, printing the parsed * commands to stdout. * * Usage: * boot_parser # read from stdin * boot_parser file.bki # read from file * boot_parser -q file.bki # quiet mode (no output, just validate) * *------------------------------------------------------------------------- */ #include "boot_gram_defs.h" #include "boot_grammar.h" #include /* * Lime parser interface functions (generated by Lime). * These are declared with the prefix from %name boot. */ void *bootAlloc(void *(*mallocProc)(size_t)); void bootFree(void *p, void (*freeProc)(void *)); void boot(void *yyp, int yymajor, BootToken yyminor, BootParseState *pstate); /* * Read entire contents of a FILE into a malloc'd buffer. * Returns the buffer and sets *out_len to the length. */ static char * read_file(FILE *fp, int *out_len) { size_t capacity = 4096; size_t length = 0; char *buf = malloc(capacity); if (!buf) { fprintf(stderr, "out of memory\n"); exit(1); } while (!feof(fp)) { if (length + 1024 > capacity) { capacity *= 2; buf = realloc(buf, capacity); if (!buf) { fprintf(stderr, "out of memory\n"); exit(1); } } size_t n = fread(buf + length, 1, 1024, fp); length += n; if (n == 0) break; } buf[length] = '\0'; *out_len = (int)length; return buf; } /* * Parse a BKI input string. * Returns 0 on success, non-zero on error. */ static int parse_bki(const char *input, int length, int quiet) { BootParseState *pstate; void *parser; BootToken token; int token_type; int result; /* Create parser state */ pstate = boot_parse_state_create(); boot_parse_state_set_input(pstate, input, length); /* Suppress output in quiet mode */ if (quiet) { /* Redirect stdout to /dev/null for quiet mode */ /* (In a real implementation, we'd use a flag in pstate) */ } /* Create the Lime parser */ parser = bootAlloc(malloc); if (!parser) { fprintf(stderr, "failed to allocate parser\n"); boot_parse_state_destroy(pstate); return 1; } /* Feed tokens to the parser */ while ((token_type = boot_scan_next(pstate, &token)) != 0) { boot(parser, token_type, token, pstate); if (pstate->error_count > 0) break; } /* Send EOF to the parser */ if (pstate->error_count == 0) { BootToken eof_token = {0}; boot(parser, 0, eof_token, pstate); } result = pstate->error_count; /* Clean up */ bootFree(parser, free); boot_parse_state_destroy(pstate); return result; } int main(int argc, char *argv[]) { FILE *input_file = stdin; int quiet = 0; int argidx = 1; char *input; int length; int result; /* Parse command-line options */ while (argidx < argc && argv[argidx][0] == '-') { if (strcmp(argv[argidx], "-q") == 0) { quiet = 1; argidx++; } else if (strcmp(argv[argidx], "-h") == 0 || strcmp(argv[argidx], "--help") == 0) { fprintf(stderr, "Usage: %s [-q] [file.bki]\n", argv[0]); fprintf(stderr, " -q Quiet mode (validate only)\n"); return 0; } else { fprintf(stderr, "Unknown option: %s\n", argv[argidx]); return 1; } } /* Open input file if specified */ if (argidx < argc) { input_file = fopen(argv[argidx], "r"); if (!input_file) { fprintf(stderr, "Cannot open '%s': %s\n", argv[argidx], strerror(errno)); return 1; } } /* Read input */ input = read_file(input_file, &length); if (input_file != stdin) fclose(input_file); /* Parse */ result = parse_bki(input, length, quiet); free(input); if (result == 0 && !quiet) fprintf(stderr, "Parse successful.\n"); else if (result != 0) fprintf(stderr, "Parse failed with %d error(s).\n", result); return result ? 1 : 0; }