
/*
 * COMMAND.C
 *
 *	(C)Copyright 1987 by Matthew Dillon, All Rights Reserved
 *
 *    Modified for use with testrh by Vidhyanath Rao 
 *
 * \c		     single character (escape)
 * `string'          string of characters w/ embedded `' allowed!
 * (string)             same thing w/ embedded () allowed!
 *
 * name arg arg      command name. The arguments are interpreted as strings
 *		     for the command.
 *
 * $		     insert saved string.
 *			 [mostly returns from REXX macros].
 *
 * Any string arguments not part of a command are considered to be typed
 * text.
 */


#include <stdio.h>
#include "defs.h"

#define CF_NRX  8   /*  NOT OK to do from inside REXX			*/
#define NESTMAX 4
 
extern char *breakout();

typedef struct {
   char *name;	    /* command name	  */
   ubyte args;
   ubyte flags;
   int (*func)();   /* function           */
} COMM;

extern int
	do_execute(),	do_null(),	do_quit(),	do_show(),
	do_rxc(),	do_rxo(),	do_rhlocks(),	do_rximpld(),
	do_set();

ubyte hindex[26];   /*	alpha hash into table	*/

	/*	  args flags	*/

COMM Comm[] = {
    "clrrhlocks",    0, CF_NRX, do_rhlocks,
    "execute",       1, CF_NRX, do_execute,
    "lockrh",	     0, CF_NRX, do_rhlocks,
    "null",          0,      0, do_null,
    "quit",          0, CF_NRX, do_quit,
    "rxc",           1,      0, do_rxc,      /* explicit ARexx macro
						invocation      */
    "rxo",           2,      0, do_rxo,     /* explicit, ARexx macro
						invocation, with options */
    "set",	     1,	     0, do_set,
    "show",	     0,	     0, do_show,
    "unlockrh",	     0, CF_NRX, do_rhlocks,
    NULL, 0, 0, NULL
};

init_command()
{
    register short hi;
    register COMM *comm;

    hi = sizeof(Comm)/sizeof(Comm[0]) - 2;
    comm = Comm + hi;

    while (hi >= 0) {
	hindex[comm->name[0] - 'a'] = hi;
	--hi;
	--comm;
    }
}


do_command(str)
char *str;

{
    register char *arg;
    register short i, j;
    static int level;
    char *tbf[8], quoted;

    if (level == 0)
	CmdErr = 0; /*Clear command error at start. */

    if (++level > NESTMAX) {
	puts("Recursion Too Deep!");
	--level;
	CmdErr |= RDE_BADCMD;
	return(0);
    }
    while ( (tbf[0] = arg = breakout(&str, &quoted)) != NULL) {
	switch (quoted) {
	  case '\3':
	    CmdErr |= RDE_NOMEM; /* malloc() failed */
	  case '\2': /* Nesting error for `' or () /*
	    goto fail;
	  case '\1': /*quoted string. enter into file */
	    puts(arg);
	    free(arg);
	    continue; /*the while loop. [no continue for switch()] */
	  default:
	    ;
	}

	for (i = 0; arg[i]; ++i) {
	    if (arg[i] >= 'A' && arg[i] <= 'Z')
		arg[i] += 'a' - 'A';
	}

	j = 1;

	if (arg[0] >= 'a' && arg[0] <= 'z') {
	    register COMM *comm = &Comm[hindex[arg[0]-'a']];
	    for (; comm->name && comm->name[0] == arg[0]; ++comm) {
		if (strcmp(arg, comm->name) == 0) {
		    av[0] = (ubyte *)comm->name;
		    if ( ((comm->flags & CF_NRX) != 0) &&
			  (RHFlags & RHF_ACTIVE) ) {
			puts ("No can do from inside the Rexx server");
			CmdErr |= RDE_NESTRX;
			goto fail;
		    }
		    for (; (j <= comm->args) && (j < 8); ++j) {
			av[j] = (ubyte *)
				  (tbf[j] = breakout(&str, &quoted));
			switch (quoted) {
			  case '\3':
			    CmdErr |= RDE_NOMEM; /* malloc() failed */
			  case '\2': /* Nesting error for `' or () */
			    goto fail;
			  default:
			    ;
			}
			if (av[j] == NULL) {
			    puts("Bad argument");
			    CmdErr |= RDE_BADARG;
			    goto fail;
			}
		    }
		    av[j] = NULL;   /* end of arglist */

		
		    if ( ((*comm->func)(-1) != 0) && (CmdErr == 0) ) {
			goto loop;
		    } else {
			goto fail;
		    }
		}
	    }
	}


	/* Command not found, check for macro	*/

	/* Command still not found, and if no errors, try ARexx macro  */
	if (CmdErr == 0)
	    do_rximpld(arg, str);

	if (CmdErr != 0) {
fail:
	    --level;
	    CmdErr |= RDE_CMDERR;
	    for (--j; j >= 0; --j)
		free(tbf[j]);
	    return(0);
	}
loop:
	    for (--j; j >= 0; --j)
		free(tbf[j]);
    }
    --level;
    return(1);
}

do_execute()

{
    Execute(av[1], 0L, 0L);
}

do_quit()

{
    Quitflag = 1;
    RHFlags |= RHF_HALTED;
}

do_show()

{
    printf("Rexx Result: %s \n", String);
}

do_null()

{
    return(1);
}

do_set()

{
    if (String != NULL) {
	free(String);
    }
    if ( (String = malloc(strlen(av[1]) + 1)) != NULL) {
	strcpy(String, av[1]);
	return(1);
    } else {
	CmdErr |= RDE_NOMEM;
	return(0);
    }
}

