116 lines
3.0 KiB
C
116 lines
3.0 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "lex.h"
|
|
#include "parser.h"
|
|
#include "ps_graph.h"
|
|
#include "errors.h"
|
|
|
|
static void print_usage(FILE *f, const char *name) {
|
|
fprintf(f, "Usage: %s <function> <output file> [<range>]\n", name);
|
|
fprintf(f, " <function> ..... The function to plot the graph of.\n");
|
|
fprintf(f, " <output file> .. Name of the output PostScript file.\n");
|
|
fprintf(f, " <range> ........ 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;
|
|
} |