# include "opihi.h"
# define DEBUG 0

int command (char *line, char **outline, int VERBOSE) {

  int i, status, argc;
  char **argv, **targv;
  Command *cmd;

  /* force a space between ! and first word: !ls becomes ! ls */
  if (line[0] == '!') {
    REALLOCATE (line, char, strlen(line) + 5);
    memmove (&line[2], &line[1], strlen(&line[1]) + 1);
    line[1] = ' ';
  }

  /* expand anything of the form $fred or $fred$sam, etc */ 
  line = expand_vars (line);     /* line is freed here, new one allocated */
  /* expand anything of the form fred[N] */ 
  line = expand_vectors (line);  /* line is freed here, new one allocated */
  /* solve math expresions, assign variable, if needed */
  line = parse (line);        /* line is freed here, new one allocated */
  /* any entry in line of the form {foo} returns value or tmp vector / buffer */

  /* we may have reallocated line, return new pointer */
  *outline = line;
  
  # if (DEBUG) 
  fprintf (stderr, "line: %s\n", line);
  # endif

  argv = parse_commands (line, &argc);
  if (argc == 0) return (TRUE);  /* empty command or assignment */

  /* save the original values of argv since command may modify the array */
  ALLOCATE (targv, char *, argc);
  for (i = 0; i < argc; i++) targv[i] = argv[i];

  cmd = MatchCommand (argv[0], VERBOSE, FALSE);
  if (cmd == NULL) {
    status = -1;
  } else {
    free (argv[0]);
    argv[0] = strcreate (cmd[0].name);
    targv[0] = argv[0];
    status = (*cmd[0].func) (argc, argv);
  }
  for (i = 0; i < argc; i++) free (targv[i]);
  free (targv);
  free (argv);

  if (!status) {
    char *msg;
    msg = get_variable_ptr ("ERRORMSG");
    if (msg != (char *) NULL) gprint (GP_ERR, "%s\n", msg);
  }

  set_int_variable ("STATUS", status);

  # if (DEBUG) 
  gprint (GP_ERR, "command: %s, status: %d\n", line, status);
  # endif

  return (status);
}

/* parse the input line, search for the corresponding command, and execute it
   if no match is found, return -1; this is used above to distinguish between
   a command error and an unknown command.  if VERBOSE is true, unknown commands
   result in an error message.  The input line is freed and the resulting parsed
   line is returned on 'outline'
*/
