198944Sobrien/* GDB CLI command scripting. 298944Sobrien 398944Sobrien Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 498944Sobrien 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software 598944Sobrien Foundation, Inc. 698944Sobrien 798944Sobrien This file is part of GDB. 898944Sobrien 998944Sobrien This program is free software; you can redistribute it and/or modify 1098944Sobrien it under the terms of the GNU General Public License as published by 1198944Sobrien the Free Software Foundation; either version 2 of the License, or 1298944Sobrien (at your option) any later version. 1398944Sobrien 1498944Sobrien This program is distributed in the hope that it will be useful, 1598944Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1698944Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1798944Sobrien GNU General Public License for more details. 1898944Sobrien 1998944Sobrien You should have received a copy of the GNU General Public License 2098944Sobrien along with this program; if not, write to the Free Software 2198944Sobrien Foundation, Inc., 59 Temple Place - Suite 330, 2298944Sobrien Boston, MA 02111-1307, USA. */ 2398944Sobrien 2498944Sobrien#include "defs.h" 2598944Sobrien#include "value.h" 2698944Sobrien#include "language.h" /* For value_true */ 2798944Sobrien#include <ctype.h> 2898944Sobrien 2998944Sobrien#include "ui-out.h" 30130803Smarcel#include "gdb_string.h" 3198944Sobrien 3298944Sobrien#include "top.h" 3398944Sobrien#include "cli/cli-cmds.h" 3498944Sobrien#include "cli/cli-decode.h" 3598944Sobrien#include "cli/cli-script.h" 3698944Sobrien 3798944Sobrien/* Prototypes for local functions */ 3898944Sobrien 3998944Sobrienstatic enum command_control_type 4098944Sobrien recurse_read_control_structure (struct command_line *current_cmd); 4198944Sobrien 4298944Sobrienstatic char *insert_args (char *line); 4398944Sobrien 4498944Sobrienstatic struct cleanup * setup_user_args (char *p); 4598944Sobrien 4698944Sobrienstatic void validate_comname (char *); 4798944Sobrien 4898944Sobrien/* Level of control structure. */ 4998944Sobrienstatic int control_level; 5098944Sobrien 5198944Sobrien/* Source command state variable. */ 5298944Sobrienstatic int source_error_allocated; 5398944Sobrien 5498944Sobrien/* Structure for arguments to user defined functions. */ 5598944Sobrien#define MAXUSERARGS 10 5698944Sobrienstruct user_args 5798944Sobrien { 5898944Sobrien struct user_args *next; 5998944Sobrien struct 6098944Sobrien { 6198944Sobrien char *arg; 6298944Sobrien int len; 6398944Sobrien } 6498944Sobrien a[MAXUSERARGS]; 6598944Sobrien int count; 6698944Sobrien } 6798944Sobrien *user_args; 6898944Sobrien 6998944Sobrien 7098944Sobrien/* Allocate, initialize a new command line structure for one of the 7198944Sobrien control commands (if/while). */ 7298944Sobrien 7398944Sobrienstatic struct command_line * 7498944Sobrienbuild_command_line (enum command_control_type type, char *args) 7598944Sobrien{ 7698944Sobrien struct command_line *cmd; 7798944Sobrien 7898944Sobrien if (args == NULL) 7998944Sobrien error ("if/while commands require arguments.\n"); 8098944Sobrien 8198944Sobrien cmd = (struct command_line *) xmalloc (sizeof (struct command_line)); 8298944Sobrien cmd->next = NULL; 8398944Sobrien cmd->control_type = type; 8498944Sobrien 8598944Sobrien cmd->body_count = 1; 8698944Sobrien cmd->body_list 8798944Sobrien = (struct command_line **) xmalloc (sizeof (struct command_line *) 8898944Sobrien * cmd->body_count); 8998944Sobrien memset (cmd->body_list, 0, sizeof (struct command_line *) * cmd->body_count); 9098944Sobrien cmd->line = savestring (args, strlen (args)); 9198944Sobrien return cmd; 9298944Sobrien} 9398944Sobrien 9498944Sobrien/* Build and return a new command structure for the control commands 9598944Sobrien such as "if" and "while". */ 9698944Sobrien 9798944Sobrienstatic struct command_line * 9898944Sobrienget_command_line (enum command_control_type type, char *arg) 9998944Sobrien{ 10098944Sobrien struct command_line *cmd; 10198944Sobrien struct cleanup *old_chain = NULL; 10298944Sobrien 10398944Sobrien /* Allocate and build a new command line structure. */ 10498944Sobrien cmd = build_command_line (type, arg); 10598944Sobrien 10698944Sobrien old_chain = make_cleanup_free_command_lines (&cmd); 10798944Sobrien 10898944Sobrien /* Read in the body of this command. */ 10998944Sobrien if (recurse_read_control_structure (cmd) == invalid_control) 11098944Sobrien { 11198944Sobrien warning ("error reading in control structure\n"); 11298944Sobrien do_cleanups (old_chain); 11398944Sobrien return NULL; 11498944Sobrien } 11598944Sobrien 11698944Sobrien discard_cleanups (old_chain); 11798944Sobrien return cmd; 11898944Sobrien} 11998944Sobrien 12098944Sobrien/* Recursively print a command (including full control structures). */ 12198944Sobrien 12298944Sobrienvoid 12398944Sobrienprint_command_lines (struct ui_out *uiout, struct command_line *cmd, 12498944Sobrien unsigned int depth) 12598944Sobrien{ 12698944Sobrien struct command_line *list; 12798944Sobrien 12898944Sobrien list = cmd; 12998944Sobrien while (list) 13098944Sobrien { 13198944Sobrien 13298944Sobrien if (depth) 13398944Sobrien ui_out_spaces (uiout, 2 * depth); 13498944Sobrien 13598944Sobrien /* A simple command, print it and continue. */ 13698944Sobrien if (list->control_type == simple_control) 13798944Sobrien { 13898944Sobrien ui_out_field_string (uiout, NULL, list->line); 13998944Sobrien ui_out_text (uiout, "\n"); 14098944Sobrien list = list->next; 14198944Sobrien continue; 14298944Sobrien } 14398944Sobrien 14498944Sobrien /* loop_continue to jump to the start of a while loop, print it 14598944Sobrien and continue. */ 14698944Sobrien if (list->control_type == continue_control) 14798944Sobrien { 14898944Sobrien ui_out_field_string (uiout, NULL, "loop_continue"); 14998944Sobrien ui_out_text (uiout, "\n"); 15098944Sobrien list = list->next; 15198944Sobrien continue; 15298944Sobrien } 15398944Sobrien 15498944Sobrien /* loop_break to break out of a while loop, print it and continue. */ 15598944Sobrien if (list->control_type == break_control) 15698944Sobrien { 15798944Sobrien ui_out_field_string (uiout, NULL, "loop_break"); 15898944Sobrien ui_out_text (uiout, "\n"); 15998944Sobrien list = list->next; 16098944Sobrien continue; 16198944Sobrien } 16298944Sobrien 16398944Sobrien /* A while command. Recursively print its subcommands and continue. */ 16498944Sobrien if (list->control_type == while_control) 16598944Sobrien { 16698944Sobrien ui_out_field_fmt (uiout, NULL, "while %s", list->line); 16798944Sobrien ui_out_text (uiout, "\n"); 16898944Sobrien print_command_lines (uiout, *list->body_list, depth + 1); 16998944Sobrien if (depth) 17098944Sobrien ui_out_spaces (uiout, 2 * depth); 17198944Sobrien ui_out_field_string (uiout, NULL, "end"); 17298944Sobrien ui_out_text (uiout, "\n"); 17398944Sobrien list = list->next; 17498944Sobrien continue; 17598944Sobrien } 17698944Sobrien 17798944Sobrien /* An if command. Recursively print both arms before continueing. */ 17898944Sobrien if (list->control_type == if_control) 17998944Sobrien { 18098944Sobrien ui_out_field_fmt (uiout, NULL, "if %s", list->line); 18198944Sobrien ui_out_text (uiout, "\n"); 18298944Sobrien /* The true arm. */ 18398944Sobrien print_command_lines (uiout, list->body_list[0], depth + 1); 18498944Sobrien 18598944Sobrien /* Show the false arm if it exists. */ 18698944Sobrien if (list->body_count == 2) 18798944Sobrien { 18898944Sobrien if (depth) 18998944Sobrien ui_out_spaces (uiout, 2 * depth); 19098944Sobrien ui_out_field_string (uiout, NULL, "else"); 19198944Sobrien ui_out_text (uiout, "\n"); 19298944Sobrien print_command_lines (uiout, list->body_list[1], depth + 1); 19398944Sobrien } 19498944Sobrien 19598944Sobrien if (depth) 19698944Sobrien ui_out_spaces (uiout, 2 * depth); 19798944Sobrien ui_out_field_string (uiout, NULL, "end"); 19898944Sobrien ui_out_text (uiout, "\n"); 19998944Sobrien list = list->next; 20098944Sobrien continue; 20198944Sobrien } 20298944Sobrien 20398944Sobrien /* ignore illegal command type and try next */ 20498944Sobrien list = list->next; 20598944Sobrien } /* while (list) */ 20698944Sobrien} 20798944Sobrien 208130803Smarcel/* Handle pre-post hooks. */ 209130803Smarcel 210130803Smarcelstatic void 211130803Smarcelclear_hook_in_cleanup (void *data) 212130803Smarcel{ 213130803Smarcel struct cmd_list_element *c = data; 214130803Smarcel c->hook_in = 0; /* Allow hook to work again once it is complete */ 215130803Smarcel} 216130803Smarcel 217130803Smarcelvoid 218130803Smarcelexecute_cmd_pre_hook (struct cmd_list_element *c) 219130803Smarcel{ 220130803Smarcel if ((c->hook_pre) && (!c->hook_in)) 221130803Smarcel { 222130803Smarcel struct cleanup *cleanups = make_cleanup (clear_hook_in_cleanup, c); 223130803Smarcel c->hook_in = 1; /* Prevent recursive hooking */ 224130803Smarcel execute_user_command (c->hook_pre, (char *) 0); 225130803Smarcel do_cleanups (cleanups); 226130803Smarcel } 227130803Smarcel} 228130803Smarcel 229130803Smarcelvoid 230130803Smarcelexecute_cmd_post_hook (struct cmd_list_element *c) 231130803Smarcel{ 232130803Smarcel if ((c->hook_post) && (!c->hook_in)) 233130803Smarcel { 234130803Smarcel struct cleanup *cleanups = make_cleanup (clear_hook_in_cleanup, c); 235130803Smarcel c->hook_in = 1; /* Prevent recursive hooking */ 236130803Smarcel execute_user_command (c->hook_post, (char *) 0); 237130803Smarcel do_cleanups (cleanups); 238130803Smarcel } 239130803Smarcel} 240130803Smarcel 24198944Sobrien/* Execute the command in CMD. */ 242130803Smarcelstatic void 243130803Smarceldo_restore_user_call_depth (void * call_depth) 244130803Smarcel{ 245130803Smarcel int * depth = call_depth; 246130803Smarcel /* We will be returning_to_top_level() at this point, so we want to 247130803Smarcel reset our depth. */ 248130803Smarcel (*depth) = 0; 249130803Smarcel} 25098944Sobrien 251130803Smarcel 25298944Sobrienvoid 25398944Sobrienexecute_user_command (struct cmd_list_element *c, char *args) 25498944Sobrien{ 255130803Smarcel struct command_line *cmdlines; 25698944Sobrien struct cleanup *old_chain; 25798944Sobrien enum command_control_type ret; 258130803Smarcel static int user_call_depth = 0; 259130803Smarcel extern int max_user_call_depth; 26098944Sobrien 26198944Sobrien old_chain = setup_user_args (args); 26298944Sobrien 26398944Sobrien cmdlines = c->user_commands; 26498944Sobrien if (cmdlines == 0) 26598944Sobrien /* Null command */ 26698944Sobrien return; 26798944Sobrien 268130803Smarcel if (++user_call_depth > max_user_call_depth) 269130803Smarcel error ("Max user call depth exceeded -- command aborted\n"); 270130803Smarcel 271130803Smarcel old_chain = make_cleanup (do_restore_user_call_depth, &user_call_depth); 272130803Smarcel 27398944Sobrien /* Set the instream to 0, indicating execution of a 27498944Sobrien user-defined function. */ 27598944Sobrien old_chain = make_cleanup (do_restore_instream_cleanup, instream); 27698944Sobrien instream = (FILE *) 0; 27798944Sobrien while (cmdlines) 27898944Sobrien { 27998944Sobrien ret = execute_control_command (cmdlines); 28098944Sobrien if (ret != simple_control && ret != break_control) 28198944Sobrien { 28298944Sobrien warning ("Error in control structure.\n"); 28398944Sobrien break; 28498944Sobrien } 28598944Sobrien cmdlines = cmdlines->next; 28698944Sobrien } 28798944Sobrien do_cleanups (old_chain); 288130803Smarcel 289130803Smarcel user_call_depth--; 29098944Sobrien} 29198944Sobrien 29298944Sobrienenum command_control_type 29398944Sobrienexecute_control_command (struct command_line *cmd) 29498944Sobrien{ 29598944Sobrien struct expression *expr; 29698944Sobrien struct command_line *current; 297130803Smarcel struct cleanup *old_chain = make_cleanup (null_cleanup, 0); 29898944Sobrien struct value *val; 29998944Sobrien struct value *val_mark; 30098944Sobrien int loop; 30198944Sobrien enum command_control_type ret; 30298944Sobrien char *new_line; 30398944Sobrien 304130803Smarcel /* Start by assuming failure, if a problem is detected, the code 305130803Smarcel below will simply "break" out of the switch. */ 306130803Smarcel ret = invalid_control; 307130803Smarcel 30898944Sobrien switch (cmd->control_type) 30998944Sobrien { 31098944Sobrien case simple_control: 31198944Sobrien /* A simple command, execute it and return. */ 31298944Sobrien new_line = insert_args (cmd->line); 31398944Sobrien if (!new_line) 314130803Smarcel break; 315130803Smarcel make_cleanup (free_current_contents, &new_line); 31698944Sobrien execute_command (new_line, 0); 31798944Sobrien ret = cmd->control_type; 31898944Sobrien break; 31998944Sobrien 32098944Sobrien case continue_control: 32198944Sobrien case break_control: 32298944Sobrien /* Return for "continue", and "break" so we can either 32398944Sobrien continue the loop at the top, or break out. */ 32498944Sobrien ret = cmd->control_type; 32598944Sobrien break; 32698944Sobrien 32798944Sobrien case while_control: 32898944Sobrien { 32998944Sobrien /* Parse the loop control expression for the while statement. */ 33098944Sobrien new_line = insert_args (cmd->line); 33198944Sobrien if (!new_line) 332130803Smarcel break; 333130803Smarcel make_cleanup (free_current_contents, &new_line); 33498944Sobrien expr = parse_expression (new_line); 33598944Sobrien make_cleanup (free_current_contents, &expr); 33698944Sobrien 33798944Sobrien ret = simple_control; 33898944Sobrien loop = 1; 33998944Sobrien 34098944Sobrien /* Keep iterating so long as the expression is true. */ 34198944Sobrien while (loop == 1) 34298944Sobrien { 34398944Sobrien int cond_result; 34498944Sobrien 34598944Sobrien QUIT; 34698944Sobrien 34798944Sobrien /* Evaluate the expression. */ 34898944Sobrien val_mark = value_mark (); 34998944Sobrien val = evaluate_expression (expr); 35098944Sobrien cond_result = value_true (val); 35198944Sobrien value_free_to_mark (val_mark); 35298944Sobrien 35398944Sobrien /* If the value is false, then break out of the loop. */ 35498944Sobrien if (!cond_result) 35598944Sobrien break; 35698944Sobrien 35798944Sobrien /* Execute the body of the while statement. */ 35898944Sobrien current = *cmd->body_list; 35998944Sobrien while (current) 36098944Sobrien { 36198944Sobrien ret = execute_control_command (current); 36298944Sobrien 36398944Sobrien /* If we got an error, or a "break" command, then stop 36498944Sobrien looping. */ 36598944Sobrien if (ret == invalid_control || ret == break_control) 36698944Sobrien { 36798944Sobrien loop = 0; 36898944Sobrien break; 36998944Sobrien } 37098944Sobrien 37198944Sobrien /* If we got a "continue" command, then restart the loop 37298944Sobrien at this point. */ 37398944Sobrien if (ret == continue_control) 37498944Sobrien break; 37598944Sobrien 37698944Sobrien /* Get the next statement. */ 37798944Sobrien current = current->next; 37898944Sobrien } 37998944Sobrien } 38098944Sobrien 38198944Sobrien /* Reset RET so that we don't recurse the break all the way down. */ 38298944Sobrien if (ret == break_control) 38398944Sobrien ret = simple_control; 38498944Sobrien 38598944Sobrien break; 38698944Sobrien } 38798944Sobrien 38898944Sobrien case if_control: 38998944Sobrien { 39098944Sobrien new_line = insert_args (cmd->line); 39198944Sobrien if (!new_line) 392130803Smarcel break; 393130803Smarcel make_cleanup (free_current_contents, &new_line); 39498944Sobrien /* Parse the conditional for the if statement. */ 39598944Sobrien expr = parse_expression (new_line); 39698944Sobrien make_cleanup (free_current_contents, &expr); 39798944Sobrien 39898944Sobrien current = NULL; 39998944Sobrien ret = simple_control; 40098944Sobrien 40198944Sobrien /* Evaluate the conditional. */ 40298944Sobrien val_mark = value_mark (); 40398944Sobrien val = evaluate_expression (expr); 40498944Sobrien 40598944Sobrien /* Choose which arm to take commands from based on the value of the 40698944Sobrien conditional expression. */ 40798944Sobrien if (value_true (val)) 40898944Sobrien current = *cmd->body_list; 40998944Sobrien else if (cmd->body_count == 2) 41098944Sobrien current = *(cmd->body_list + 1); 41198944Sobrien value_free_to_mark (val_mark); 41298944Sobrien 41398944Sobrien /* Execute commands in the given arm. */ 41498944Sobrien while (current) 41598944Sobrien { 41698944Sobrien ret = execute_control_command (current); 41798944Sobrien 41898944Sobrien /* If we got an error, get out. */ 41998944Sobrien if (ret != simple_control) 42098944Sobrien break; 42198944Sobrien 42298944Sobrien /* Get the next statement in the body. */ 42398944Sobrien current = current->next; 42498944Sobrien } 42598944Sobrien 42698944Sobrien break; 42798944Sobrien } 42898944Sobrien 42998944Sobrien default: 43098944Sobrien warning ("Invalid control type in command structure."); 431130803Smarcel break; 43298944Sobrien } 43398944Sobrien 434130803Smarcel do_cleanups (old_chain); 43598944Sobrien 43698944Sobrien return ret; 43798944Sobrien} 43898944Sobrien 43998944Sobrien/* "while" command support. Executes a body of statements while the 44098944Sobrien loop condition is nonzero. */ 44198944Sobrien 44298944Sobrienvoid 44398944Sobrienwhile_command (char *arg, int from_tty) 44498944Sobrien{ 44598944Sobrien struct command_line *command = NULL; 44698944Sobrien 44798944Sobrien control_level = 1; 44898944Sobrien command = get_command_line (while_control, arg); 44998944Sobrien 45098944Sobrien if (command == NULL) 45198944Sobrien return; 45298944Sobrien 45398944Sobrien execute_control_command (command); 45498944Sobrien free_command_lines (&command); 45598944Sobrien} 45698944Sobrien 45798944Sobrien/* "if" command support. Execute either the true or false arm depending 45898944Sobrien on the value of the if conditional. */ 45998944Sobrien 46098944Sobrienvoid 46198944Sobrienif_command (char *arg, int from_tty) 46298944Sobrien{ 46398944Sobrien struct command_line *command = NULL; 46498944Sobrien 46598944Sobrien control_level = 1; 46698944Sobrien command = get_command_line (if_control, arg); 46798944Sobrien 46898944Sobrien if (command == NULL) 46998944Sobrien return; 47098944Sobrien 47198944Sobrien execute_control_command (command); 47298944Sobrien free_command_lines (&command); 47398944Sobrien} 47498944Sobrien 47598944Sobrien/* Cleanup */ 47698944Sobrienstatic void 47798944Sobrienarg_cleanup (void *ignore) 47898944Sobrien{ 47998944Sobrien struct user_args *oargs = user_args; 48098944Sobrien if (!user_args) 48198944Sobrien internal_error (__FILE__, __LINE__, 48298944Sobrien "arg_cleanup called with no user args.\n"); 48398944Sobrien 48498944Sobrien user_args = user_args->next; 48598944Sobrien xfree (oargs); 48698944Sobrien} 48798944Sobrien 48898944Sobrien/* Bind the incomming arguments for a user defined command to 48998944Sobrien $arg0, $arg1 ... $argMAXUSERARGS. */ 49098944Sobrien 49198944Sobrienstatic struct cleanup * 49298944Sobriensetup_user_args (char *p) 49398944Sobrien{ 49498944Sobrien struct user_args *args; 49598944Sobrien struct cleanup *old_chain; 49698944Sobrien unsigned int arg_count = 0; 49798944Sobrien 49898944Sobrien args = (struct user_args *) xmalloc (sizeof (struct user_args)); 49998944Sobrien memset (args, 0, sizeof (struct user_args)); 50098944Sobrien 50198944Sobrien args->next = user_args; 50298944Sobrien user_args = args; 50398944Sobrien 50498944Sobrien old_chain = make_cleanup (arg_cleanup, 0/*ignored*/); 50598944Sobrien 50698944Sobrien if (p == NULL) 50798944Sobrien return old_chain; 50898944Sobrien 50998944Sobrien while (*p) 51098944Sobrien { 51198944Sobrien char *start_arg; 51298944Sobrien int squote = 0; 51398944Sobrien int dquote = 0; 51498944Sobrien int bsquote = 0; 51598944Sobrien 51698944Sobrien if (arg_count >= MAXUSERARGS) 51798944Sobrien { 51898944Sobrien error ("user defined function may only have %d arguments.\n", 51998944Sobrien MAXUSERARGS); 52098944Sobrien return old_chain; 52198944Sobrien } 52298944Sobrien 52398944Sobrien /* Strip whitespace. */ 52498944Sobrien while (*p == ' ' || *p == '\t') 52598944Sobrien p++; 52698944Sobrien 52798944Sobrien /* P now points to an argument. */ 52898944Sobrien start_arg = p; 52998944Sobrien user_args->a[arg_count].arg = p; 53098944Sobrien 53198944Sobrien /* Get to the end of this argument. */ 53298944Sobrien while (*p) 53398944Sobrien { 53498944Sobrien if (((*p == ' ' || *p == '\t')) && !squote && !dquote && !bsquote) 53598944Sobrien break; 53698944Sobrien else 53798944Sobrien { 53898944Sobrien if (bsquote) 53998944Sobrien bsquote = 0; 54098944Sobrien else if (*p == '\\') 54198944Sobrien bsquote = 1; 54298944Sobrien else if (squote) 54398944Sobrien { 54498944Sobrien if (*p == '\'') 54598944Sobrien squote = 0; 54698944Sobrien } 54798944Sobrien else if (dquote) 54898944Sobrien { 54998944Sobrien if (*p == '"') 55098944Sobrien dquote = 0; 55198944Sobrien } 55298944Sobrien else 55398944Sobrien { 55498944Sobrien if (*p == '\'') 55598944Sobrien squote = 1; 55698944Sobrien else if (*p == '"') 55798944Sobrien dquote = 1; 55898944Sobrien } 55998944Sobrien p++; 56098944Sobrien } 56198944Sobrien } 56298944Sobrien 56398944Sobrien user_args->a[arg_count].len = p - start_arg; 56498944Sobrien arg_count++; 56598944Sobrien user_args->count++; 56698944Sobrien } 56798944Sobrien return old_chain; 56898944Sobrien} 56998944Sobrien 57098944Sobrien/* Given character string P, return a point to the first argument ($arg), 57198944Sobrien or NULL if P contains no arguments. */ 57298944Sobrien 57398944Sobrienstatic char * 57498944Sobrienlocate_arg (char *p) 57598944Sobrien{ 57698944Sobrien while ((p = strchr (p, '$'))) 57798944Sobrien { 57898944Sobrien if (strncmp (p, "$arg", 4) == 0 && isdigit (p[4])) 57998944Sobrien return p; 58098944Sobrien p++; 58198944Sobrien } 58298944Sobrien return NULL; 58398944Sobrien} 58498944Sobrien 58598944Sobrien/* Insert the user defined arguments stored in user_arg into the $arg 58698944Sobrien arguments found in line, with the updated copy being placed into nline. */ 58798944Sobrien 58898944Sobrienstatic char * 58998944Sobrieninsert_args (char *line) 59098944Sobrien{ 59198944Sobrien char *p, *save_line, *new_line; 59298944Sobrien unsigned len, i; 59398944Sobrien 59498944Sobrien /* First we need to know how much memory to allocate for the new line. */ 59598944Sobrien save_line = line; 59698944Sobrien len = 0; 59798944Sobrien while ((p = locate_arg (line))) 59898944Sobrien { 59998944Sobrien len += p - line; 60098944Sobrien i = p[4] - '0'; 60198944Sobrien 60298944Sobrien if (i >= user_args->count) 60398944Sobrien { 60498944Sobrien error ("Missing argument %d in user function.\n", i); 60598944Sobrien return NULL; 60698944Sobrien } 60798944Sobrien len += user_args->a[i].len; 60898944Sobrien line = p + 5; 60998944Sobrien } 61098944Sobrien 61198944Sobrien /* Don't forget the tail. */ 61298944Sobrien len += strlen (line); 61398944Sobrien 61498944Sobrien /* Allocate space for the new line and fill it in. */ 61598944Sobrien new_line = (char *) xmalloc (len + 1); 61698944Sobrien if (new_line == NULL) 61798944Sobrien return NULL; 61898944Sobrien 61998944Sobrien /* Restore pointer to beginning of old line. */ 62098944Sobrien line = save_line; 62198944Sobrien 62298944Sobrien /* Save pointer to beginning of new line. */ 62398944Sobrien save_line = new_line; 62498944Sobrien 62598944Sobrien while ((p = locate_arg (line))) 62698944Sobrien { 62798944Sobrien int i, len; 62898944Sobrien 62998944Sobrien memcpy (new_line, line, p - line); 63098944Sobrien new_line += p - line; 63198944Sobrien i = p[4] - '0'; 63298944Sobrien 63398944Sobrien len = user_args->a[i].len; 63498944Sobrien if (len) 63598944Sobrien { 63698944Sobrien memcpy (new_line, user_args->a[i].arg, len); 63798944Sobrien new_line += len; 63898944Sobrien } 63998944Sobrien line = p + 5; 64098944Sobrien } 64198944Sobrien /* Don't forget the tail. */ 64298944Sobrien strcpy (new_line, line); 64398944Sobrien 64498944Sobrien /* Return a pointer to the beginning of the new line. */ 64598944Sobrien return save_line; 64698944Sobrien} 64798944Sobrien 64898944Sobrien 64998944Sobrien/* Expand the body_list of COMMAND so that it can hold NEW_LENGTH 65098944Sobrien code bodies. This is typically used when we encounter an "else" 65198944Sobrien clause for an "if" command. */ 65298944Sobrien 65398944Sobrienstatic void 65498944Sobrienrealloc_body_list (struct command_line *command, int new_length) 65598944Sobrien{ 65698944Sobrien int n; 65798944Sobrien struct command_line **body_list; 65898944Sobrien 65998944Sobrien n = command->body_count; 66098944Sobrien 66198944Sobrien /* Nothing to do? */ 66298944Sobrien if (new_length <= n) 66398944Sobrien return; 66498944Sobrien 66598944Sobrien body_list = (struct command_line **) 66698944Sobrien xmalloc (sizeof (struct command_line *) * new_length); 66798944Sobrien 66898944Sobrien memcpy (body_list, command->body_list, sizeof (struct command_line *) * n); 66998944Sobrien 67098944Sobrien xfree (command->body_list); 67198944Sobrien command->body_list = body_list; 67298944Sobrien command->body_count = new_length; 67398944Sobrien} 67498944Sobrien 67598944Sobrien/* Read one line from the input stream. If the command is an "else" or 67698944Sobrien "end", return such an indication to the caller. */ 67798944Sobrien 67898944Sobrienstatic enum misc_command_type 67998944Sobrienread_next_line (struct command_line **command) 68098944Sobrien{ 68198944Sobrien char *p, *p1, *prompt_ptr, control_prompt[256]; 68298944Sobrien int i = 0; 68398944Sobrien 68498944Sobrien if (control_level >= 254) 68598944Sobrien error ("Control nesting too deep!\n"); 68698944Sobrien 68798944Sobrien /* Set a prompt based on the nesting of the control commands. */ 68898944Sobrien if (instream == stdin || (instream == 0 && readline_hook != NULL)) 68998944Sobrien { 69098944Sobrien for (i = 0; i < control_level; i++) 69198944Sobrien control_prompt[i] = ' '; 69298944Sobrien control_prompt[i] = '>'; 69398944Sobrien control_prompt[i + 1] = '\0'; 69498944Sobrien prompt_ptr = (char *) &control_prompt[0]; 69598944Sobrien } 69698944Sobrien else 69798944Sobrien prompt_ptr = NULL; 69898944Sobrien 69998944Sobrien p = command_line_input (prompt_ptr, instream == stdin, "commands"); 70098944Sobrien 70198944Sobrien /* Not sure what to do here. */ 70298944Sobrien if (p == NULL) 70398944Sobrien return end_command; 70498944Sobrien 70598944Sobrien /* Strip leading and trailing whitespace. */ 70698944Sobrien while (*p == ' ' || *p == '\t') 70798944Sobrien p++; 70898944Sobrien 70998944Sobrien p1 = p + strlen (p); 71098944Sobrien while (p1 != p && (p1[-1] == ' ' || p1[-1] == '\t')) 71198944Sobrien p1--; 71298944Sobrien 71398944Sobrien /* Blanks and comments don't really do anything, but we need to 71498944Sobrien distinguish them from else, end and other commands which can be 71598944Sobrien executed. */ 71698944Sobrien if (p1 == p || p[0] == '#') 71798944Sobrien return nop_command; 71898944Sobrien 71998944Sobrien /* Is this the end of a simple, while, or if control structure? */ 72098944Sobrien if (p1 - p == 3 && !strncmp (p, "end", 3)) 72198944Sobrien return end_command; 72298944Sobrien 72398944Sobrien /* Is the else clause of an if control structure? */ 72498944Sobrien if (p1 - p == 4 && !strncmp (p, "else", 4)) 72598944Sobrien return else_command; 72698944Sobrien 72798944Sobrien /* Check for while, if, break, continue, etc and build a new command 72898944Sobrien line structure for them. */ 72998944Sobrien if (p1 - p > 5 && !strncmp (p, "while", 5)) 73098944Sobrien *command = build_command_line (while_control, p + 6); 73198944Sobrien else if (p1 - p > 2 && !strncmp (p, "if", 2)) 73298944Sobrien *command = build_command_line (if_control, p + 3); 73398944Sobrien else if (p1 - p == 10 && !strncmp (p, "loop_break", 10)) 73498944Sobrien { 73598944Sobrien *command = (struct command_line *) 73698944Sobrien xmalloc (sizeof (struct command_line)); 73798944Sobrien (*command)->next = NULL; 73898944Sobrien (*command)->line = NULL; 73998944Sobrien (*command)->control_type = break_control; 74098944Sobrien (*command)->body_count = 0; 74198944Sobrien (*command)->body_list = NULL; 74298944Sobrien } 74398944Sobrien else if (p1 - p == 13 && !strncmp (p, "loop_continue", 13)) 74498944Sobrien { 74598944Sobrien *command = (struct command_line *) 74698944Sobrien xmalloc (sizeof (struct command_line)); 74798944Sobrien (*command)->next = NULL; 74898944Sobrien (*command)->line = NULL; 74998944Sobrien (*command)->control_type = continue_control; 75098944Sobrien (*command)->body_count = 0; 75198944Sobrien (*command)->body_list = NULL; 75298944Sobrien } 75398944Sobrien else 75498944Sobrien { 75598944Sobrien /* A normal command. */ 75698944Sobrien *command = (struct command_line *) 75798944Sobrien xmalloc (sizeof (struct command_line)); 75898944Sobrien (*command)->next = NULL; 75998944Sobrien (*command)->line = savestring (p, p1 - p); 76098944Sobrien (*command)->control_type = simple_control; 76198944Sobrien (*command)->body_count = 0; 76298944Sobrien (*command)->body_list = NULL; 76398944Sobrien } 76498944Sobrien 76598944Sobrien /* Nothing special. */ 76698944Sobrien return ok_command; 76798944Sobrien} 76898944Sobrien 76998944Sobrien/* Recursively read in the control structures and create a command_line 77098944Sobrien structure from them. 77198944Sobrien 77298944Sobrien The parent_control parameter is the control structure in which the 77398944Sobrien following commands are nested. */ 77498944Sobrien 77598944Sobrienstatic enum command_control_type 77698944Sobrienrecurse_read_control_structure (struct command_line *current_cmd) 77798944Sobrien{ 77898944Sobrien int current_body, i; 77998944Sobrien enum misc_command_type val; 78098944Sobrien enum command_control_type ret; 78198944Sobrien struct command_line **body_ptr, *child_tail, *next; 78298944Sobrien 78398944Sobrien child_tail = NULL; 78498944Sobrien current_body = 1; 78598944Sobrien 78698944Sobrien /* Sanity checks. */ 78798944Sobrien if (current_cmd->control_type == simple_control) 78898944Sobrien { 78998944Sobrien error ("Recursed on a simple control type\n"); 79098944Sobrien return invalid_control; 79198944Sobrien } 79298944Sobrien 79398944Sobrien if (current_body > current_cmd->body_count) 79498944Sobrien { 79598944Sobrien error ("Allocated body is smaller than this command type needs\n"); 79698944Sobrien return invalid_control; 79798944Sobrien } 79898944Sobrien 79998944Sobrien /* Read lines from the input stream and build control structures. */ 80098944Sobrien while (1) 80198944Sobrien { 80298944Sobrien dont_repeat (); 80398944Sobrien 80498944Sobrien next = NULL; 80598944Sobrien val = read_next_line (&next); 80698944Sobrien 80798944Sobrien /* Just skip blanks and comments. */ 80898944Sobrien if (val == nop_command) 80998944Sobrien continue; 81098944Sobrien 81198944Sobrien if (val == end_command) 81298944Sobrien { 81398944Sobrien if (current_cmd->control_type == while_control 81498944Sobrien || current_cmd->control_type == if_control) 81598944Sobrien { 81698944Sobrien /* Success reading an entire control structure. */ 81798944Sobrien ret = simple_control; 81898944Sobrien break; 81998944Sobrien } 82098944Sobrien else 82198944Sobrien { 82298944Sobrien ret = invalid_control; 82398944Sobrien break; 82498944Sobrien } 82598944Sobrien } 82698944Sobrien 82798944Sobrien /* Not the end of a control structure. */ 82898944Sobrien if (val == else_command) 82998944Sobrien { 83098944Sobrien if (current_cmd->control_type == if_control 83198944Sobrien && current_body == 1) 83298944Sobrien { 83398944Sobrien realloc_body_list (current_cmd, 2); 83498944Sobrien current_body = 2; 83598944Sobrien child_tail = NULL; 83698944Sobrien continue; 83798944Sobrien } 83898944Sobrien else 83998944Sobrien { 84098944Sobrien ret = invalid_control; 84198944Sobrien break; 84298944Sobrien } 84398944Sobrien } 84498944Sobrien 84598944Sobrien if (child_tail) 84698944Sobrien { 84798944Sobrien child_tail->next = next; 84898944Sobrien } 84998944Sobrien else 85098944Sobrien { 85198944Sobrien body_ptr = current_cmd->body_list; 85298944Sobrien for (i = 1; i < current_body; i++) 85398944Sobrien body_ptr++; 85498944Sobrien 85598944Sobrien *body_ptr = next; 85698944Sobrien 85798944Sobrien } 85898944Sobrien 85998944Sobrien child_tail = next; 86098944Sobrien 86198944Sobrien /* If the latest line is another control structure, then recurse 86298944Sobrien on it. */ 86398944Sobrien if (next->control_type == while_control 86498944Sobrien || next->control_type == if_control) 86598944Sobrien { 86698944Sobrien control_level++; 86798944Sobrien ret = recurse_read_control_structure (next); 86898944Sobrien control_level--; 86998944Sobrien 87098944Sobrien if (ret != simple_control) 87198944Sobrien break; 87298944Sobrien } 87398944Sobrien } 87498944Sobrien 87598944Sobrien dont_repeat (); 87698944Sobrien 87798944Sobrien return ret; 87898944Sobrien} 87998944Sobrien 88098944Sobrien/* Read lines from the input stream and accumulate them in a chain of 88198944Sobrien struct command_line's, which is then returned. For input from a 88298944Sobrien terminal, the special command "end" is used to mark the end of the 88398944Sobrien input, and is not included in the returned chain of commands. */ 88498944Sobrien 88598944Sobrien#define END_MESSAGE "End with a line saying just \"end\"." 88698944Sobrien 88798944Sobrienstruct command_line * 88898944Sobrienread_command_lines (char *prompt_arg, int from_tty) 88998944Sobrien{ 89098944Sobrien struct command_line *head, *tail, *next; 89198944Sobrien struct cleanup *old_chain; 89298944Sobrien enum command_control_type ret; 89398944Sobrien enum misc_command_type val; 89498944Sobrien 89598944Sobrien control_level = 0; 89698944Sobrien if (readline_begin_hook) 89798944Sobrien { 89898944Sobrien /* Note - intentional to merge messages with no newline */ 89998944Sobrien (*readline_begin_hook) ("%s %s\n", prompt_arg, END_MESSAGE); 90098944Sobrien } 90198944Sobrien else if (from_tty && input_from_terminal_p ()) 90298944Sobrien { 90398944Sobrien printf_unfiltered ("%s\n%s\n", prompt_arg, END_MESSAGE); 90498944Sobrien gdb_flush (gdb_stdout); 90598944Sobrien } 90698944Sobrien 90798944Sobrien head = tail = NULL; 90898944Sobrien old_chain = NULL; 90998944Sobrien 91098944Sobrien while (1) 91198944Sobrien { 91298944Sobrien val = read_next_line (&next); 91398944Sobrien 91498944Sobrien /* Ignore blank lines or comments. */ 91598944Sobrien if (val == nop_command) 91698944Sobrien continue; 91798944Sobrien 91898944Sobrien if (val == end_command) 91998944Sobrien { 92098944Sobrien ret = simple_control; 92198944Sobrien break; 92298944Sobrien } 92398944Sobrien 92498944Sobrien if (val != ok_command) 92598944Sobrien { 92698944Sobrien ret = invalid_control; 92798944Sobrien break; 92898944Sobrien } 92998944Sobrien 93098944Sobrien if (next->control_type == while_control 93198944Sobrien || next->control_type == if_control) 93298944Sobrien { 93398944Sobrien control_level++; 93498944Sobrien ret = recurse_read_control_structure (next); 93598944Sobrien control_level--; 93698944Sobrien 93798944Sobrien if (ret == invalid_control) 93898944Sobrien break; 93998944Sobrien } 94098944Sobrien 94198944Sobrien if (tail) 94298944Sobrien { 94398944Sobrien tail->next = next; 94498944Sobrien } 94598944Sobrien else 94698944Sobrien { 94798944Sobrien head = next; 94898944Sobrien old_chain = make_cleanup_free_command_lines (&head); 94998944Sobrien } 95098944Sobrien tail = next; 95198944Sobrien } 95298944Sobrien 95398944Sobrien dont_repeat (); 95498944Sobrien 95598944Sobrien if (head) 95698944Sobrien { 95798944Sobrien if (ret != invalid_control) 95898944Sobrien { 95998944Sobrien discard_cleanups (old_chain); 96098944Sobrien } 96198944Sobrien else 96298944Sobrien do_cleanups (old_chain); 96398944Sobrien } 96498944Sobrien 96598944Sobrien if (readline_end_hook) 96698944Sobrien { 96798944Sobrien (*readline_end_hook) (); 96898944Sobrien } 96998944Sobrien return (head); 97098944Sobrien} 97198944Sobrien 97298944Sobrien/* Free a chain of struct command_line's. */ 97398944Sobrien 97498944Sobrienvoid 97598944Sobrienfree_command_lines (struct command_line **lptr) 97698944Sobrien{ 977130803Smarcel struct command_line *l = *lptr; 978130803Smarcel struct command_line *next; 97998944Sobrien struct command_line **blist; 98098944Sobrien int i; 98198944Sobrien 98298944Sobrien while (l) 98398944Sobrien { 98498944Sobrien if (l->body_count > 0) 98598944Sobrien { 98698944Sobrien blist = l->body_list; 98798944Sobrien for (i = 0; i < l->body_count; i++, blist++) 98898944Sobrien free_command_lines (blist); 98998944Sobrien } 99098944Sobrien next = l->next; 99198944Sobrien xfree (l->line); 99298944Sobrien xfree (l); 99398944Sobrien l = next; 99498944Sobrien } 99598944Sobrien *lptr = NULL; 99698944Sobrien} 99798944Sobrien 99898944Sobrienstatic void 99998944Sobriendo_free_command_lines_cleanup (void *arg) 100098944Sobrien{ 100198944Sobrien free_command_lines (arg); 100298944Sobrien} 100398944Sobrien 1004130803Smarcelstruct cleanup * 100598944Sobrienmake_cleanup_free_command_lines (struct command_line **arg) 100698944Sobrien{ 100798944Sobrien return make_cleanup (do_free_command_lines_cleanup, arg); 100898944Sobrien} 1009130803Smarcel 1010130803Smarcelstruct command_line * 1011130803Smarcelcopy_command_lines (struct command_line *cmds) 1012130803Smarcel{ 1013130803Smarcel struct command_line *result = NULL; 1014130803Smarcel 1015130803Smarcel if (cmds) 1016130803Smarcel { 1017130803Smarcel result = (struct command_line *) xmalloc (sizeof (struct command_line)); 1018130803Smarcel 1019130803Smarcel result->next = copy_command_lines (cmds->next); 1020130803Smarcel result->line = xstrdup (cmds->line); 1021130803Smarcel result->control_type = cmds->control_type; 1022130803Smarcel result->body_count = cmds->body_count; 1023130803Smarcel if (cmds->body_count > 0) 1024130803Smarcel { 1025130803Smarcel int i; 1026130803Smarcel 1027130803Smarcel result->body_list = (struct command_line **) 1028130803Smarcel xmalloc (sizeof (struct command_line *) * cmds->body_count); 1029130803Smarcel 1030130803Smarcel for (i = 0; i < cmds->body_count; i++) 1031130803Smarcel result->body_list[i] = copy_command_lines (cmds->body_list[i]); 1032130803Smarcel } 1033130803Smarcel else 1034130803Smarcel result->body_list = NULL; 1035130803Smarcel } 1036130803Smarcel 1037130803Smarcel return result; 1038130803Smarcel} 103998944Sobrien 104098944Sobrienstatic void 104198944Sobrienvalidate_comname (char *comname) 104298944Sobrien{ 1043130803Smarcel char *p; 104498944Sobrien 104598944Sobrien if (comname == 0) 104698944Sobrien error_no_arg ("name of command to define"); 104798944Sobrien 104898944Sobrien p = comname; 104998944Sobrien while (*p) 105098944Sobrien { 105198944Sobrien if (!isalnum (*p) && *p != '-' && *p != '_') 105298944Sobrien error ("Junk in argument list: \"%s\"", p); 105398944Sobrien p++; 105498944Sobrien } 105598944Sobrien} 105698944Sobrien 105798944Sobrien/* This is just a placeholder in the command data structures. */ 105898944Sobrienstatic void 105998944Sobrienuser_defined_command (char *ignore, int from_tty) 106098944Sobrien{ 106198944Sobrien} 106298944Sobrien 106398944Sobrienvoid 106498944Sobriendefine_command (char *comname, int from_tty) 106598944Sobrien{ 106698944Sobrien#define MAX_TMPBUF 128 106798944Sobrien enum cmd_hook_type 106898944Sobrien { 106998944Sobrien CMD_NO_HOOK = 0, 107098944Sobrien CMD_PRE_HOOK, 107198944Sobrien CMD_POST_HOOK 107298944Sobrien }; 1073130803Smarcel struct command_line *cmds; 1074130803Smarcel struct cmd_list_element *c, *newc, *oldc, *hookc = 0; 107598944Sobrien char *tem = comname; 107698944Sobrien char *tem2; 107798944Sobrien char tmpbuf[MAX_TMPBUF]; 107898944Sobrien int hook_type = CMD_NO_HOOK; 107998944Sobrien int hook_name_size = 0; 108098944Sobrien 108198944Sobrien#define HOOK_STRING "hook-" 108298944Sobrien#define HOOK_LEN 5 108398944Sobrien#define HOOK_POST_STRING "hookpost-" 108498944Sobrien#define HOOK_POST_LEN 9 108598944Sobrien 108698944Sobrien validate_comname (comname); 108798944Sobrien 108898944Sobrien /* Look it up, and verify that we got an exact match. */ 108998944Sobrien c = lookup_cmd (&tem, cmdlist, "", -1, 1); 1090130803Smarcel if (c && strcmp (comname, c->name) != 0) 109198944Sobrien c = 0; 109298944Sobrien 109398944Sobrien if (c) 109498944Sobrien { 1095130803Smarcel int q; 109698944Sobrien if (c->class == class_user || c->class == class_alias) 1097130803Smarcel q = query ("Redefine command \"%s\"? ", c->name); 109898944Sobrien else 1099130803Smarcel q = query ("Really redefine built-in command \"%s\"? ", c->name); 1100130803Smarcel if (!q) 110198944Sobrien error ("Command \"%s\" not redefined.", c->name); 110298944Sobrien } 110398944Sobrien 110498944Sobrien /* If this new command is a hook, then mark the command which it 110598944Sobrien is hooking. Note that we allow hooking `help' commands, so that 110698944Sobrien we can hook the `stop' pseudo-command. */ 110798944Sobrien 110898944Sobrien if (!strncmp (comname, HOOK_STRING, HOOK_LEN)) 110998944Sobrien { 111098944Sobrien hook_type = CMD_PRE_HOOK; 111198944Sobrien hook_name_size = HOOK_LEN; 111298944Sobrien } 111398944Sobrien else if (!strncmp (comname, HOOK_POST_STRING, HOOK_POST_LEN)) 111498944Sobrien { 111598944Sobrien hook_type = CMD_POST_HOOK; 111698944Sobrien hook_name_size = HOOK_POST_LEN; 111798944Sobrien } 111898944Sobrien 111998944Sobrien if (hook_type != CMD_NO_HOOK) 112098944Sobrien { 112198944Sobrien /* Look up cmd it hooks, and verify that we got an exact match. */ 112298944Sobrien tem = comname + hook_name_size; 112398944Sobrien hookc = lookup_cmd (&tem, cmdlist, "", -1, 0); 1124130803Smarcel if (hookc && strcmp (comname + hook_name_size, hookc->name) != 0) 112598944Sobrien hookc = 0; 112698944Sobrien if (!hookc) 112798944Sobrien { 112898944Sobrien warning ("Your new `%s' command does not hook any existing command.", 112998944Sobrien comname); 113098944Sobrien if (!query ("Proceed? ")) 113198944Sobrien error ("Not confirmed."); 113298944Sobrien } 113398944Sobrien } 113498944Sobrien 113598944Sobrien comname = savestring (comname, strlen (comname)); 113698944Sobrien 113798944Sobrien /* If the rest of the commands will be case insensitive, this one 113898944Sobrien should behave in the same manner. */ 113998944Sobrien for (tem = comname; *tem; tem++) 114098944Sobrien if (isupper (*tem)) 114198944Sobrien *tem = tolower (*tem); 114298944Sobrien 114398944Sobrien sprintf (tmpbuf, "Type commands for definition of \"%s\".", comname); 114498944Sobrien cmds = read_command_lines (tmpbuf, from_tty); 114598944Sobrien 114698944Sobrien if (c && c->class == class_user) 114798944Sobrien free_command_lines (&c->user_commands); 114898944Sobrien 114998944Sobrien newc = add_cmd (comname, class_user, user_defined_command, 115098944Sobrien (c && c->class == class_user) 115198944Sobrien ? c->doc : savestring ("User-defined.", 13), &cmdlist); 115298944Sobrien newc->user_commands = cmds; 115398944Sobrien 115498944Sobrien /* If this new command is a hook, then mark both commands as being 115598944Sobrien tied. */ 115698944Sobrien if (hookc) 115798944Sobrien { 115898944Sobrien switch (hook_type) 115998944Sobrien { 116098944Sobrien case CMD_PRE_HOOK: 116198944Sobrien hookc->hook_pre = newc; /* Target gets hooked. */ 116298944Sobrien newc->hookee_pre = hookc; /* We are marked as hooking target cmd. */ 116398944Sobrien break; 116498944Sobrien case CMD_POST_HOOK: 116598944Sobrien hookc->hook_post = newc; /* Target gets hooked. */ 116698944Sobrien newc->hookee_post = hookc; /* We are marked as hooking target cmd. */ 116798944Sobrien break; 116898944Sobrien default: 116998944Sobrien /* Should never come here as hookc would be 0. */ 117098944Sobrien internal_error (__FILE__, __LINE__, "bad switch"); 117198944Sobrien } 117298944Sobrien } 117398944Sobrien} 117498944Sobrien 117598944Sobrienvoid 117698944Sobriendocument_command (char *comname, int from_tty) 117798944Sobrien{ 117898944Sobrien struct command_line *doclines; 1179130803Smarcel struct cmd_list_element *c; 118098944Sobrien char *tem = comname; 118198944Sobrien char tmpbuf[128]; 118298944Sobrien 118398944Sobrien validate_comname (comname); 118498944Sobrien 118598944Sobrien c = lookup_cmd (&tem, cmdlist, "", 0, 1); 118698944Sobrien 118798944Sobrien if (c->class != class_user) 118898944Sobrien error ("Command \"%s\" is built-in.", comname); 118998944Sobrien 119098944Sobrien sprintf (tmpbuf, "Type documentation for \"%s\".", comname); 119198944Sobrien doclines = read_command_lines (tmpbuf, from_tty); 119298944Sobrien 119398944Sobrien if (c->doc) 119498944Sobrien xfree (c->doc); 119598944Sobrien 119698944Sobrien { 1197130803Smarcel struct command_line *cl1; 1198130803Smarcel int len = 0; 119998944Sobrien 120098944Sobrien for (cl1 = doclines; cl1; cl1 = cl1->next) 120198944Sobrien len += strlen (cl1->line) + 1; 120298944Sobrien 120398944Sobrien c->doc = (char *) xmalloc (len + 1); 120498944Sobrien *c->doc = 0; 120598944Sobrien 120698944Sobrien for (cl1 = doclines; cl1; cl1 = cl1->next) 120798944Sobrien { 120898944Sobrien strcat (c->doc, cl1->line); 120998944Sobrien if (cl1->next) 121098944Sobrien strcat (c->doc, "\n"); 121198944Sobrien } 121298944Sobrien } 121398944Sobrien 121498944Sobrien free_command_lines (&doclines); 121598944Sobrien} 121698944Sobrien 121798944Sobrienstruct source_cleanup_lines_args 121898944Sobrien{ 121998944Sobrien int old_line; 122098944Sobrien char *old_file; 122198944Sobrien char *old_pre_error; 122298944Sobrien char *old_error_pre_print; 122398944Sobrien}; 122498944Sobrien 122598944Sobrienstatic void 1226130803Smarcelsource_cleanup_lines (void *args) 122798944Sobrien{ 122898944Sobrien struct source_cleanup_lines_args *p = 122998944Sobrien (struct source_cleanup_lines_args *) args; 123098944Sobrien source_line_number = p->old_line; 123198944Sobrien source_file_name = p->old_file; 123298944Sobrien source_pre_error = p->old_pre_error; 123398944Sobrien error_pre_print = p->old_error_pre_print; 123498944Sobrien} 123598944Sobrien 123698944Sobrienstatic void 123798944Sobriendo_fclose_cleanup (void *stream) 123898944Sobrien{ 123998944Sobrien fclose (stream); 124098944Sobrien} 124198944Sobrien 124298944Sobrien/* Used to implement source_command */ 124398944Sobrien 124498944Sobrienvoid 124598944Sobrienscript_from_file (FILE *stream, char *file) 124698944Sobrien{ 124798944Sobrien struct cleanup *old_cleanups; 124898944Sobrien struct source_cleanup_lines_args old_lines; 124998944Sobrien int needed_length; 125098944Sobrien 125198944Sobrien if (stream == NULL) 125298944Sobrien { 125398944Sobrien internal_error (__FILE__, __LINE__, "called with NULL file pointer!"); 125498944Sobrien } 125598944Sobrien 125698944Sobrien old_cleanups = make_cleanup (do_fclose_cleanup, stream); 125798944Sobrien 125898944Sobrien old_lines.old_line = source_line_number; 125998944Sobrien old_lines.old_file = source_file_name; 126098944Sobrien old_lines.old_pre_error = source_pre_error; 126198944Sobrien old_lines.old_error_pre_print = error_pre_print; 126298944Sobrien make_cleanup (source_cleanup_lines, &old_lines); 126398944Sobrien source_line_number = 0; 126498944Sobrien source_file_name = file; 126598944Sobrien source_pre_error = error_pre_print == NULL ? "" : error_pre_print; 126698944Sobrien source_pre_error = savestring (source_pre_error, strlen (source_pre_error)); 126798944Sobrien make_cleanup (xfree, source_pre_error); 126898944Sobrien /* This will get set every time we read a line. So it won't stay "" for 126998944Sobrien long. */ 127098944Sobrien error_pre_print = ""; 127198944Sobrien 127298944Sobrien needed_length = strlen (source_file_name) + strlen (source_pre_error) + 80; 127398944Sobrien if (source_error_allocated < needed_length) 127498944Sobrien { 127598944Sobrien source_error_allocated *= 2; 127698944Sobrien if (source_error_allocated < needed_length) 127798944Sobrien source_error_allocated = needed_length; 127898944Sobrien if (source_error == NULL) 127998944Sobrien source_error = xmalloc (source_error_allocated); 128098944Sobrien else 128198944Sobrien source_error = xrealloc (source_error, source_error_allocated); 128298944Sobrien } 128398944Sobrien 128498944Sobrien read_command_file (stream); 128598944Sobrien 128698944Sobrien do_cleanups (old_cleanups); 128798944Sobrien} 128898944Sobrien 128998944Sobrienvoid 129098944Sobrienshow_user_1 (struct cmd_list_element *c, struct ui_file *stream) 129198944Sobrien{ 1292130803Smarcel struct command_line *cmdlines; 129398944Sobrien 129498944Sobrien cmdlines = c->user_commands; 129598944Sobrien if (!cmdlines) 129698944Sobrien return; 129798944Sobrien fputs_filtered ("User command ", stream); 129898944Sobrien fputs_filtered (c->name, stream); 129998944Sobrien fputs_filtered (":\n", stream); 130098944Sobrien 130198944Sobrien print_command_lines (uiout, cmdlines, 1); 130298944Sobrien fputs_filtered ("\n", stream); 130398944Sobrien} 130498944Sobrien 1305