void define() { register int start_token; /* the 1st token in the function definition */ register struct udvt_entry *udv; register struct udft_entry *udf; if (equals(c_token + 1, "(")) { /* function ! */ int dummy_num = 0; struct at_type *at_tmp; char save_dummy[MAX_NUM_VAR][MAX_ID_LEN + 1]; memcpy(save_dummy, c_dummy_var, sizeof(save_dummy)); start_token = c_token; do { c_token += 2; /* skip to the next dummy */ copy_str(c_dummy_var[dummy_num++], c_token, MAX_ID_LEN); } while (equals(c_token + 1, ",") && (dummy_num < MAX_NUM_VAR)); if (equals(c_token + 1, ",")) int_error("function contains too many parameters", c_token + 2); c_token += 3; /* skip (, dummy, ) and = */ if (END_OF_COMMAND) int_error("function definition expected", c_token); udf = dummy_func = add_udf(start_token); if ((at_tmp = perm_at()) == (struct at_type *) NULL) int_error("not enough memory for function", start_token); if (udf->at) /* already a dynamic a.t. there */ free((char *) udf->at); /* so free it first */ udf->at = at_tmp; /* before re-assigning it. */ memcpy(c_dummy_var, save_dummy, sizeof(save_dummy)); m_capture(&(udf->definition), start_token, c_token - 1); dummy_func = NULL; /* dont let anyone else use our workspace */ } else { /* variable ! */ start_token = c_token; c_token += 2; udv = add_udv(start_token); (void) const_express(&(udv->udv_value)); udv->udv_undef = FALSE; } }
/* * Syntax: set link {x2|y2} {via <expression1> inverse <expression2>} * Create action code tables for the functions linking primary and secondary axes. * expression1 maps primary coordinates into the secondary coordinate space. * expression2 maps secondary coordinates into the primary coordinate space. */ void parse_link_via( struct udft_entry *udf ) { int start_token; /* Caller left us pointing at "via" or "inverse" */ c_token++; start_token = c_token; if (END_OF_COMMAND) int_error(c_token,"Missing expression"); /* Save action table for the linkage mapping */ strcpy(c_dummy_var[0], "x"); strcpy(c_dummy_var[1], "y"); dummy_func = udf; free_at(udf->at); udf->at = perm_at(); dummy_func = NULL; /* Save the mapping expression itself */ m_capture(&(udf->definition), start_token, c_token - 1); }
/* create action code for 'sum' expressions */ static void parse_sum_expression() { /* sum [<var>=<range>] <expr> * - Pass a udf to f_sum (with action code (for <expr>) that is not added * to the global action table). * - f_sum uses a newly created udv (<var>) to pass the current value of * <var> to <expr> (resp. its ac). * - The original idea was to treat <expr> as function f(<var>), but there * was the following problem: Consider 'g(x) = sum [k=1:4] f(k)'. There * are two dummy variables 'x' and 'k' from different functions 'g' and * 'f' which would require changing the parsing of dummy variables. */ char *errormsg = "Expecting 'sum [<var> = <start>:<end>] <expression>'\n"; char *varname = NULL; union argument *arg; struct udft_entry *udf; struct at_type * save_at; int save_at_size; int i; /* Caller already checked for string "sum [" so skip both tokens */ c_token += 2; /* <var> */ if (!isletter(c_token)) int_error(c_token, errormsg); /* create a user defined variable and pass it to f_sum via PUSHC, since the * argument of f_sum is already used by the udf */ m_capture(&varname, c_token, c_token); add_udv(c_token); arg = add_action(PUSHC); Gstring(&(arg->v_arg), varname); c_token++; if (!equals(c_token, "=")) int_error(c_token, errormsg); c_token++; /* <start> */ parse_expression(); if (!equals(c_token, ":")) int_error(c_token, errormsg); c_token++; /* <end> */ parse_expression(); if (!equals(c_token, "]")) int_error(c_token, errormsg); c_token++; /* parse <expr> and convert it to a new action table. */ /* modeled on code from temp_at(). */ /* 1. save environment to restart parsing */ save_at = at; save_at_size = at_size; at = NULL; /* 2. save action table in a user defined function */ udf = (struct udft_entry *) gp_alloc(sizeof(struct udft_entry), "sum"); udf->next_udf = (struct udft_entry *) NULL; udf->udf_name = NULL; /* TODO maybe add a name and definition */ udf->at = perm_at(); udf->definition = NULL; udf->dummy_num = 0; for (i = 0; i < MAX_NUM_VAR; i++) (void) Ginteger(&(udf->dummy_values[i]), 0); /* 3. restore environment */ at = save_at; at_size = save_at_size; /* pass the udf to f_sum using the argument */ add_action(SUM)->udf_arg = udf; }