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