#include #include #include #include #include #include #include "mapcalc.h" #include "globals.h" #include "func_proto.h" /****************************************************************************/ int current_depth, current_row; int depths, rows; /* Local variables for map management */ static expression **map_list = NULL; static int num_maps = 0; static int max_maps = 0; /****************************************************************************/ static void extract_maps(expression *e); static void initialize(expression *e); static void evaluate(expression *e); static int append_map(expression *e); /****************************************************************************/ int append_map(expression *e) { /* \brief Append a map to the global map list and reallocate if necessary */ if (num_maps >= max_maps) { max_maps += 10; map_list = G_realloc(map_list, max_maps * sizeof(struct expression*)); } map_list[num_maps] = e; return num_maps++; } void extract_maps(expression * e) { /* \brief Search for map names in the expression and add them to the global map list */ int i; switch (e->type) { case expr_type_map: G_debug(1, "Found map %s", e->data.map.name); append_map(e); break; case expr_type_function: for (i = 1; i <= e->data.func.argc; i++) { extract_maps(e->data.func.args[i]); } break; case expr_type_binding: extract_maps(e->data.bind.val); break; } } /****************************************************************************/ static void allocate_buf(expression * e) { e->buf = G_malloc(columns * Rast_cell_size(e->res_type)); } static void set_buf(expression * e, void *buf) { e->buf = buf; } /****************************************************************************/ static void initialize_constant(expression * e) { allocate_buf(e); } static void initialize_variable(expression * e) { set_buf(e, e->data.var.bind->data.bind.val->buf); } static void initialize_map(expression * e) { allocate_buf(e); e->data.map.idx = open_map(e->data.map.name, e->data.map.mod, e->data.map.row, e->data.map.col); } static void initialize_function(expression * e) { int i; allocate_buf(e); e->data.func.argv = G_malloc((e->data.func.argc + 1) * sizeof(void *)); e->data.func.argv[0] = e->buf; for (i = 1; i <= e->data.func.argc; i++) { initialize(e->data.func.args[i]); e->data.func.argv[i] = e->data.func.args[i]->buf; } } static void initialize_binding(expression * e) { initialize(e->data.bind.val); set_buf(e, e->data.bind.val->buf); } static void initialize(expression * e) { switch (e->type) { case expr_type_constant: initialize_constant(e); break; case expr_type_variable: initialize_variable(e); break; case expr_type_map: initialize_map(e); break; case expr_type_function: initialize_function(e); break; case expr_type_binding: initialize_binding(e); break; default: G_fatal_error(_("Unknown type: %d"), e->type); } } /****************************************************************************/ static void do_evaluate(void *p) { evaluate((struct expression *) p); } static void begin_evaluate(struct expression *e) { G_begin_execute(do_evaluate, e, &e->worker, 0); } static void end_evaluate(struct expression *e) { G_end_execute(&e->worker); } /****************************************************************************/ static void evaluate_constant(expression * e) { int *ibuf = e->buf; float *fbuf = e->buf; double *dbuf = e->buf; int i; switch (e->res_type) { case CELL_TYPE: for (i = 0; i < columns; i++) ibuf[i] = e->data.con.ival; break; case FCELL_TYPE: for (i = 0; i < columns; i++) fbuf[i] = e->data.con.fval; break; case DCELL_TYPE: for (i = 0; i < columns; i++) dbuf[i] = e->data.con.fval; break; default: G_fatal_error(_("Invalid type: %d"), e->res_type); } } static void evaluate_variable(expression * e) { /* this is a no-op */ } static void evaluate_map(expression * e) { get_map_row(e->data.map.idx, e->data.map.mod, current_depth + e->data.map.depth, current_row + e->data.map.row, e->data.map.col, e->buf, e->res_type); } static void evaluate_function(expression * e) { int i; int res; if (e->data.func.argc > 1 && e->data.func.func != f_eval) { for (i = 1; i <= e->data.func.argc; i++) begin_evaluate(e->data.func.args[i]); for (i = 1; i <= e->data.func.argc; i++) end_evaluate(e->data.func.args[i]); } else for (i = 1; i <= e->data.func.argc; i++) evaluate(e->data.func.args[i]); res = (*e->data.func.func) (e->data.func.argc, e->data.func.argt, e->data.func.argv); switch (res) { case E_ARG_LO: G_fatal_error(_("Too few arguments for function '%s'"), e->data.func.name); break; case E_ARG_HI: G_fatal_error(_("Too many arguments for function '%s'"), e->data.func.name); break; case E_ARG_TYPE: G_fatal_error(_("Invalid argument type for function '%s'"), e->data.func.name); break; case E_RES_TYPE: G_fatal_error(_("Invalid return type for function '%s'"), e->data.func.name); break; case E_INV_TYPE: G_fatal_error(_("Unknown type for function '%s'"), e->data.func.name); break; case E_ARG_NUM: G_fatal_error(_("Number of arguments for function '%s'"), e->data.func.name); break; case E_WTF: G_fatal_error(_("Unknown error for function '%s'"), e->data.func.name); break; } } static void evaluate_binding(expression * e) { evaluate(e->data.bind.val); } /****************************************************************************/ static void evaluate(expression * e) { switch (e->type) { case expr_type_constant: evaluate_constant(e); break; case expr_type_variable: evaluate_variable(e); break; case expr_type_map: evaluate_map(e); break; case expr_type_function: evaluate_function(e); break; case expr_type_binding: evaluate_binding(e); break; default: G_fatal_error(_("Unknown type: %d"), e->type); } } /****************************************************************************/ static expr_list *exprs; /****************************************************************************/ static void error_handler(void *p) { expr_list *l; for (l = exprs; l; l = l->next) { expression *e = l->exp; int fd = e->data.bind.fd; if (fd >= 0) unopen_output_map(fd); } } void execute(expr_list * ee) { int verbose = isatty(2); expr_list *l; int count, n; exprs = ee; G_add_error_handler(error_handler, NULL); for (l = ee; l; l = l->next) { expression *e = l->exp; const char *var; if (e->type != expr_type_binding && e->type != expr_type_function) G_fatal_error("internal error: execute: invalid type: %d", e->type); if (e->type != expr_type_binding) continue; var = e->data.bind.var; if (!overwrite_flag && check_output_map(var)) G_fatal_error(_("output map <%s> exists. To overwrite, " "use the --overwrite flag"), var); } /* Parse each expression and extract all raster maps */ for (l = ee; l; l = l->next) { expression *e = l->exp; extract_maps(e); } /* Set the region from the input maps*/ if (region_approach == 2) prepare_region_from_maps_union(map_list, num_maps); if (region_approach == 3) prepare_region_from_maps_intersect(map_list, num_maps); setup_region(); /* Parse each expression and initialize the maps, buffers and variables */ for (l = ee; l; l = l->next) { expression *e = l->exp; const char *var; expression *val; initialize(e); if (e->type != expr_type_binding) continue; var = e->data.bind.var; val = e->data.bind.val; e->data.bind.fd = open_output_map(var, val->res_type); } setup_maps(); count = rows * depths; n = 0; G_init_workers(); for (current_depth = 0; current_depth < depths; current_depth++) { for (current_row = 0; current_row < rows; current_row++) { if (verbose) G_percent(n, count, 2); for (l = ee; l; l = l->next) { expression *e = l->exp; int fd; evaluate(e); if (e->type != expr_type_binding) continue; fd = e->data.bind.fd; put_map_row(fd, e->buf, e->res_type); } n++; } } G_finish_workers(); if (verbose) G_percent(n, count, 2); close_maps(); for (l = ee; l; l = l->next) { expression *e = l->exp; const char *var; expression *val; int fd; if (e->type != expr_type_binding) continue; var = e->data.bind.var; val = e->data.bind.val; fd = e->data.bind.fd; close_output_map(fd); e->data.bind.fd = -1; if (val->type == expr_type_map) { if (val->data.map.mod == 'M') { copy_cats(var, val->data.map.idx); copy_colors(var, val->data.map.idx); } copy_history(var, val->data.map.idx); } else create_history(var, val); } G_unset_error_routine(); } void describe_maps(FILE *fp, expr_list *ee) { expr_list *l; fprintf(fp, "output="); for (l = ee; l; l = l->next) { expression *e = l->exp; const char *var; if (e->type != expr_type_binding && e->type != expr_type_function) G_fatal_error("internal error: execute: invalid type: %d", e->type); initialize(e); if (e->type != expr_type_binding) continue; var = e->data.bind.var; fprintf(fp, "%s%s", l != ee ? "," : "", var); } fprintf(fp, "\n"); fprintf(fp, "input="); list_maps(fp, ","); fprintf(fp, "\n"); } /****************************************************************************/