enum command_control_type execute_control_command (struct command_line *cmd) { struct expression *expr; struct command_line *current; struct cleanup *old_chain = make_cleanup (null_cleanup, 0); struct value *val; struct value *val_mark; int loop; enum command_control_type ret; char *new_line; /* Start by assuming failure, if a problem is detected, the code below will simply "break" out of the switch. */ ret = invalid_control; switch (cmd->control_type) { case simple_control: /* A simple command, execute it and return. */ new_line = insert_args (cmd->line); if (!new_line) break; make_cleanup (free_current_contents, &new_line); execute_command (new_line, 0); ret = cmd->control_type; break; case continue_control: print_command_trace ("loop_continue"); /* Return for "continue", and "break" so we can either continue the loop at the top, or break out. */ ret = cmd->control_type; break; case break_control: print_command_trace ("loop_break"); /* Return for "continue", and "break" so we can either continue the loop at the top, or break out. */ ret = cmd->control_type; break; case while_control: { char *buffer = alloca (strlen (cmd->line) + 7); sprintf (buffer, "while %s", cmd->line); print_command_trace (buffer); /* Parse the loop control expression for the while statement. */ new_line = insert_args (cmd->line); if (!new_line) break; make_cleanup (free_current_contents, &new_line); expr = parse_expression (new_line); make_cleanup (free_current_contents, &expr); ret = simple_control; loop = 1; /* Keep iterating so long as the expression is true. */ while (loop == 1) { int cond_result; QUIT; /* Evaluate the expression. */ val_mark = value_mark (); val = evaluate_expression (expr); cond_result = value_true (val); value_free_to_mark (val_mark); /* If the value is false, then break out of the loop. */ if (!cond_result) break; /* Execute the body of the while statement. */ current = *cmd->body_list; while (current) { command_nest_depth++; ret = execute_control_command (current); command_nest_depth--; /* If we got an error, or a "break" command, then stop looping. */ if (ret == invalid_control || ret == break_control) { loop = 0; break; } /* If we got a "continue" command, then restart the loop at this point. */ if (ret == continue_control) break; /* Get the next statement. */ current = current->next; } } /* Reset RET so that we don't recurse the break all the way down. */ if (ret == break_control) ret = simple_control; break; } case if_control: { char *buffer = alloca (strlen (cmd->line) + 4); sprintf (buffer, "if %s", cmd->line); print_command_trace (buffer); new_line = insert_args (cmd->line); if (!new_line) break; make_cleanup (free_current_contents, &new_line); /* Parse the conditional for the if statement. */ expr = parse_expression (new_line); make_cleanup (free_current_contents, &expr); current = NULL; ret = simple_control; /* Evaluate the conditional. */ val_mark = value_mark (); val = evaluate_expression (expr); /* Choose which arm to take commands from based on the value of the conditional expression. */ if (value_true (val)) current = *cmd->body_list; else if (cmd->body_count == 2) current = *(cmd->body_list + 1); value_free_to_mark (val_mark); /* Execute commands in the given arm. */ while (current) { command_nest_depth++; ret = execute_control_command (current); command_nest_depth--; /* If we got an error, get out. */ if (ret != simple_control) break; /* Get the next statement in the body. */ current = current->next; } break; } case commands_control: { /* Breakpoint commands list, record the commands in the breakpoint's command list and return. */ new_line = insert_args (cmd->line); if (!new_line) break; make_cleanup (free_current_contents, &new_line); ret = commands_from_control_command (new_line, cmd); break; } case python_control: { eval_python_from_control_command (cmd); ret = simple_control; break; } default: warning (_("Invalid control type in canned commands structure.")); break; } do_cleanups (old_chain); return ret; }
int perform_call_on_node (node *proc, node *arglist, library *lib, exec_env *env) { int res; block *last_block = env->block_stack; block *b = malloc(sizeof(block)); if(!b) { env->error.code = ERROR_BAD_ALLOC; env->error.static_msg = "couldn't allocate block for proc call."; E_SET_ERROR(*env); return -1; } memset(b, 0, sizeof(*b)); b->label = proc->sym; b->body_node = proc->right; b->stmt = proc->right->left; b->next = env->block_stack; env->block_stack = b; env->skip_advance = 1; if(arglist) { b->values = create_symbol_map(); if(!b->values) { pop_block(env); env->error.code = ERROR_BAD_ALLOC; env->error.static_msg = "couldn't create value table " "for new block in proc call"; FIAL_set_error(env); return -1; } if((res = insert_args(proc->left, arglist, b->values, last_block, env)) < 0) { pop_block(env); switch(res) { case -1: env->error.code = ERROR_BAD_ALLOC; env->error.static_msg = "bad alloc setting " "arguments"; FIAL_set_error(env); return -1; case -2: assert(res == -2); env->error.code = ERROR_UNDECLARED_VAR; env->error.static_msg = "undeclared variable " "in arglist"; FIAL_set_error(env); return -1; case -5: env->error.code = ERROR_UNDECLARED_VAR; env->error.static_msg = "Map access error when generating arglist"; FIAL_set_error(env); return -1; default: assert(res == -3 || res == -4); return -1; } } } if(lib) { b->last_lib = env->lib; env->lib = lib; } return 0; }