/* This file is part of Eclat. Copyright (C) 2012 Sergey Poznyakoff. Eclat 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, or (at your option) any later version. Eclat 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 Eclat. If not, see . */ #include #include #include #include #ifdef HAVE_GETOPT_H # include #endif #include #include #include #include #include "forlan.h" #include void usage() { printf("usage: %s [OPTIONS] FILE [INPUT]\n", program_name); printf("OPTIONS are:\n"); printf(" -D dump parse tree\n"); printf(" -d LEVEL set debug level\n"); printf(" -f use file interface\n"); printf(" -s sort XML tree\n"); printf(" -h produce this help list\n"); } struct grecs_node * parse_xml(FILE *fp) { XML_Parser parser; eclat_partial_tree_t part; size_t size; char buffer[256]; parser = XML_ParserCreate("UTF-8"); if (!parser) die(EX_SOFTWARE, "cannot create XML parser"); XML_SetElementHandler(parser, eclat_partial_tree_start_handler, eclat_partial_tree_end_handler); XML_SetCharacterDataHandler(parser, eclat_partial_tree_data_handler); part = eclat_partial_tree_create(); XML_SetUserData(parser, part); while ((size = fread(buffer, 1, sizeof(buffer), fp)) > 0) { enum XML_Status status = XML_Parse(parser, buffer, size, 0); if (status == XML_STATUS_ERROR) { enum XML_Error error = XML_GetErrorCode(parser); int line = XML_GetCurrentLineNumber(parser); int column = XML_GetCurrentColumnNumber(parser); die(EX_SOFTWARE, "XML parse error at %d:%d: %s", line, column, XML_ErrorString(error)); } } XML_Parse(parser, "", 0, 1); return eclat_partial_tree_finish(part); } static int node_ident_cmp(struct grecs_node const *a, struct grecs_node const *b) { return strcmp(a->ident, b->ident); } #define OPT_DUMP 0x01 #define OPT_SORT 0x02 #define OPT_FILE 0x04 int main(int argc, char **argv) { FILE *fp; char *buf; size_t len; struct stat st; struct grecs_locus_point pt; int rc; int options = 0; forlan_eval_env_t env; set_program_name(argv[0]); forlan_init(); while ((rc = getopt(argc, argv, "Dd:fhs")) != EOF) switch (rc) { case 'D': options |= OPT_DUMP; break; case 'd': if (parse_debug_level(optarg)) die(EX_USAGE, "bad debug category or level"); break; case 'f': options |= OPT_FILE; break; case 'h': usage(); return 0; case 's': options |= OPT_SORT; break; default: exit(EX_USAGE); } argc -= optind; argv += optind; if (argc == 0 || argc > 2) die(EX_USAGE, "one or two arguments expected"); if (stat(argv[0], &st)) die(EX_UNAVAILABLE, "cannot stat input file \"%s\": %s", argv[0], strerror(errno)); fp = fopen(argv[0], "r"); if (!fp) die(EX_UNAVAILABLE, "cannot open input file \"%s\": %s", argv[0], strerror(errno)); pt.file = argv[0]; pt.line = 1; pt.col = 0; if (options & OPT_FILE) { env = forlan_parse_file(fp, &pt); } else { len = st.st_size; buf = grecs_malloc(len); if (fread(buf, len, 1, fp) != 1) die(EX_UNAVAILABLE, "error reading from \"%s\": %s", argv[0], strerror(errno)); env = forlan_parse_buffer(buf, len, &pt); } fclose(fp); if (!env) return EX_UNAVAILABLE; if (options & OPT_DUMP) forlan_dump_tree(stdout, env); if (argv[1]) { struct grecs_node *tree; fp = fopen(argv[1], "r"); if (!fp) die(EX_UNAVAILABLE, "cannot open input file \"%s\": %s", argv[1], strerror(errno)); tree = parse_xml(fp); fclose(fp); if (options & OPT_SORT) grecs_tree_sort(tree, node_ident_cmp); rc = forlan_run(env, tree); grecs_tree_free(tree); } else rc = 0; forlan_free_environment(env); return rc; }