/*
 * MORE commands
 * Matt Dillon
 * version 2.01A (Manx ver) by Steve Drew 27 Sep 1986
 * mods for 16 bit compiling 4 Oct 1986. Steve Drew.
 */
 
#include "shell.h"

#define BPTR_TO_C(strtag, var)  ((struct strtag *)(BADDR( (ULONG) var)))

#define TO_ASC(n)       ((n) + '0')             /* make it printable! */

/* Casting conveniences */
#define PROC(task)              ((struct Process *)task)
#define ROOTNODE                ((struct RootNode *)DOSBase->dl_Root)
#define CLI(proc)               (BPTR_TO_C(CommandLineInterface, proc->pr_CLI))

/* Externs */
extern struct DosLibrary *DOSBase;      /* dos library base pointer */
 
do_return()
{
   if (Src_stack) {
      fseek (Src_base[Src_stack - 1], 0, 2);  /* ch to 2 fr 1 */
      Rval = (ac < 2) ? 1 : atoi(av[1]);
      return (-1);
   } else {
      main_exit ((ac < 2) ? 1 : atoi(av[1]));
   }
}
 
/*
 * STRHEAD
 *
 * place a string into a variable removing everything after and including
 * the 'break' character or until a space is found in the string.
 *
 * strhead varname breakchar string
 *
 */
 
do_strhead()
{
   register char *str = av[3];
   char bc = *av[2];
 
   while (*str && *str != bc)
      ++str;
   *str = '\0';
   set_var (LEVEL_SET, av[1], av[3]);
   return(0);
}
 
do_strtail()
{
   register char *str = av[3];
   char bc = *av[2];
 
   while (*str && *str != bc)
      ++str;
   if (*str)
      ++str;
   set_var (LEVEL_SET, av[1], str);
   return(0);
}
 
 
 
/*
 * if A < B   <, >, =, <=, >=, !=, where A and B are either:
 * nothing
 * a string
 * a value (begins w/ number)
 */
 
do_if(garbage, com)
char *garbage;
{
   char *v1, *v2, *v3, result, num;
   int n1, n2;
 
   switch (com) {
   case 0:
      if (If_stack && If_base[If_stack - 1]) {
         If_base[If_stack++] = 1;
         break;
      }
      result = num = 0;
      if (ac <= 2) {       /* if $var; */
         if (ac == 1 || strlen(av[1]) == 0 || (strlen(av[1]) == 1 && *av[1] == ' '))
            goto do_result;
         result = 1;
         goto do_result;
      }
      if (ac != 4) {
         ierror(NULL, 500);
         break;
      }
      v1 = av[1]; v2 = av[2]; v3 = av[3];
      while (*v1 == ' ')
         ++v1;
      while (*v2 == ' ')
         ++v2;
      while (*v3 == ' ')
         ++v3;
      if (*v1 >= '0' && *v1 <= '9') {
         num = 1;
         n1 = atoi(v1);
         n2 = atoi(v3);
      }
      while (*v2) {
         switch (*v2++) {
         case '>':
            result |= (num) ? (n1 >  n2) : (strcmp(v1, v3) > 0);
            break;
         case '<':
            result |= (num) ? (n1 <  n2) : (strcmp(v1, v3) < 0);
            break;
         case '=':
            result |= (num) ? (n1 == n2) : (strcmp(v1, v3) ==0);
            break;
         default:
            ierror (NULL, 503);
            break;
         }
      }
do_result:
      If_base[If_stack++] = !result;
      break;
   case 1:
      if (If_stack > 1 && If_base[If_stack - 2])
         break;
      if (If_stack)
         If_base[If_stack - 1] ^= 1;
      break;
   case 2:
      if (If_stack)
         --If_stack;
      break;
   }
   disable = (If_stack) ? If_base[If_stack - 1] : 0;
   return (0);
}
 
do_label()
{
   char aseek[32];
 
   if (Src_stack == 0) {
      ierror (NULL, 502);
      return (-1);
   }
   sprintf (aseek, "%ld %d", Src_pos[Src_stack-1], If_stack);
   set_var (LEVEL_LABEL + Src_stack - 1, av[1], aseek);
   return (0);
}
 
do_goto()
{
   int new;
   long pos;
   char *lab;
 
   if (Src_stack == 0) {
      ierror (NULL, 502);
   } else {
      lab = get_var (LEVEL_LABEL + Src_stack - 1, av[1]);
      if (lab == '\0') {
         ierror (NULL, 501);
      } else {
         pos = (long)atoi(lab);
         fseek (Src_base[Src_stack - 1], pos, 0);
         Src_pos[Src_stack - 1] = pos;
         new = atoi(next_word(lab));
         for (; If_stack < new; ++If_stack)
            If_base[If_stack] = 0;
         If_stack = new;
      }
   }
   return (-1);      /* Don't execute reset of this line */
}
 
 
do_failat()
{
   Faillevel = 1;
   fprintf (stderr, "NOT IMPLIMENTED YET\n");
}
 
do_checkbrk()
{
   fprintf (stderr,"NOT IMPLIMENTED YET\n");
}
 
do_inc(garbage, com)
char *garbage;
{
   char *var;
   char num[32];
 
   if (ac == 3)
      com = atoi(av[2]);
   var = get_var (LEVEL_SET, av[1]);
   if (var) {
      sprintf (num, "%d", atoi(var)+com);
      set_var (LEVEL_SET, av[1], num);
   }
   return(0);
}
 
do_input()
{
   char in[256];
 
   if ((gets(in)) != 0)
      set_var (LEVEL_SET, av[1], in);
   return (0);
}
 
do_ver()
{
   puts (VERSION);
   return (0);
}
 
 

do_ps()
{
	/* this code fragment based on ps.c command by Dewi Williams */

        register ULONG   *tt;           /* References TaskArray         */
        register int     count;         /* loop variable                */
        register UBYTE   *port;         /* msgport & ptr arith          */
        register struct Task *task;     /* EXEC descriptor              */
        char             strbuf[64];   /* scratch for btocstr()        */
        char             *btocstr();    /* BCPL BSTR to ASCIIZ          */

        tt = (unsigned long *)(BADDR(ROOTNODE->rn_TaskArray));

        printf("Proc Command Name         CLI Type    Pri.  Address  Directory\n");
        Forbid();               /* need linked list consistency */
        
        for (count = 1; count <= (int)tt[0] ; count++) {/* or just assume 20?*/
                if (tt[count] == 0) continue;           /* nobody home */

                /* Start by pulling out MsgPort addresses from the TaskArray
                 * area. By making unwarranted assumptions about the layout
                 * of Process and Task structures, we can derive these
                 * descriptors. Every task has an associated process, since
                 * this loop drives off a CLI data area.
                 */

                port = (UBYTE *)tt[count];
                task = (struct Task *)(port - sizeof(struct Task));

                /* Sanity check just in case */
                if (PROC(task)->pr_TaskNum == 0 || PROC(task)->pr_CLI == 0)
                        continue;               /* or complain? */

                        btocstr(CLI(PROC(task))->cli_CommandName, strbuf);
			printf("%2d   %-21s",count,strbuf);
			strcpy(strbuf,task->tc_Node.ln_Name);
                        strbuf[11] = '\0';
                        printf("%-11s",strbuf);
                        printf(" %3d  %8lx  %s\n",
                           task->tc_Node.ln_Pri,task,
                           btocstr(CLI(PROC(task))->cli_SetName, strbuf));
        }
        Permit();               /* outside critical region */
        return(0);
}


char *
btocstr(b, buf)
ULONG   b;
char    *buf;
{
        register char   *s;

        s = (char *)BADDR(b);   /* Shift & get length-prefixed str */
        bmov(s +1, buf, s[0]);
        buf[s[0]] = '\0';
        return buf;
}

