#include #include #include "lex.h" #include "parser.h" #include "ps_graph.h" #include "error_buffer.h" static void print_usage(FILE *f, const char *name) { fprintf(f, "Usage: %s []\n", name); fprintf(f, " ..... The function to plot the graph of.\n"); fprintf(f, " .. Name of the output PostScript file.\n"); fprintf(f, " ........ Ranges of the graph in the format of \"xMin:xMax:yMin:yMax\". Optional.\n"); } static int read_double(const char **str, double *out) { char *end; *out = strtod(*str, &end); if (*str == end) return 0; *str = end; return 1; } #define EXPECT_DOUBLE(str, out) \ if (!read_double(&str, out)) \ return 0; #define EXPECT_CHAR(str, c) \ if (*str++ != c) \ return 0; static int parse_range(const char *str, struct graph_range *range) { EXPECT_DOUBLE(str, &range->xmin); EXPECT_CHAR(str, ':'); EXPECT_DOUBLE(str, &range->xmax); EXPECT_CHAR(str, ':'); EXPECT_DOUBLE(str, &range->ymin); EXPECT_CHAR(str, ':'); EXPECT_DOUBLE(str, &range->ymax); EXPECT_CHAR(str, '\0'); return 1; } static enum error_code export_to_file(const struct expr_node *node, const struct graph_range *range, const char *function, const char *out_name) { FILE *file; if (!(file = fopen(out_name, "w"))) { fprintf(stderr, "Cannot open \"%s\" for writing!\n", out_name); return ERR_INVALID_FILENAME; } ps_generate_graph(file, node, range, function); fclose(file); return ERR_NO_ERR; } #ifdef ENABLE_GRAPHVIZ_EXPORT static void export_gv(const struct expr_node *node, const char *out_name) { FILE *file; if (!(file = fopen(out_name, "w"))) { fprintf(stderr, "GV: Cannot open \"%s\" for writing!\n", out_name); return; } node_debug_print_gv(node, file); fclose(file); } #endif /* ENABLE_GRAPHVIZ_EXPORT */ int main(int argc, char *argv[]) { enum error_code err; struct parser parser; struct expr_node *node; struct graph_range range; if (argc < 3) { print_usage(stderr, argv[0]); return ERR_INVALID_ARGS; } if (argc > 3) { if (!parse_range(argv[3], &range)) { fprintf(stderr, "Invalid format of ranges! The correct format is \"xMin:xMax:yMin:yMax\".\n"); return ERR_INVALID_LIMITS; } } else { range.xmin = -10.0; range.xmax = 10.0; range.ymin = -10.0; range.ymax = 10.0; } node = parser_parse(&parser, argv[1], "x"); if (!node) { fprintf(stderr, "%s", parser_get_error_text(&parser)); return parser_get_error(&parser); } err = export_to_file(node, &range, argv[1], argv[2]); #ifdef ENABLE_GRAPHVIZ_EXPORT export_gv(node, "graph.dot"); #endif /* ENABLE_GRAPHVIZ_EXPORT */ node_free(node); return err; }