#include <stdio.h>
#include <libraries/dos.h>

extern char *strrchr(),*stpblk(),*strchr();

char curr_dir[100];
char tmpbuf[256];

int old_lock,new_lock;

struct CMD {
   struct CMD *Next_CMD;
   char   *string;
   char   *replace;
} *CMD_List[16], *End[16], temp;

char buff[256];
char buff2[256];

FILE *cf;

int input_file,output_file;

extern char *malloc();

long *
alloc(lth)
register unsigned lth;
{
   register char *ptr;

   if(!(ptr = malloc(lth)))
   {  printf("Not enough memory for getting %d bytes", lth);
      exit(20);
   }
   return((long *) ptr);
}

void exec_cmd(p)
   char *p;
{
      char *q;

      if ((*p == 'c') && (*(p+1) == 'd') && ((*(p+2) == ' ')
          || (*(p+2) == '\0')))
      {  q = p + 1;
         while (*++q == ' ') ;     /* skip blanks */
         if (*q == '\0')
         {  printf(curr_dir);
            printf("\n");
         } else {
            while (*q == '/')
            {  register char *t;

               q++;
               t = strrchr(curr_dir,'/');
               if (t == NULL)
               {  t = strchr(curr_dir,':');
                  if (t++ == NULL)
                  {  printf("Bad Dir Name!");
                     break;
                  }
               }
               *t = '\0';
            }
            if ((*q != ' ') && (*q != '\0'))
            {  if (strchr(q,':') != NULL)
                  if (*q == ':')
                  {  *(strchr(curr_dir,':')) = '\0';
                     strcat(curr_dir,q);
                  } else strcpy(curr_dir,q);
               else {
                  if (curr_dir[strlen(curr_dir)-1] != ':')
                     strcat(curr_dir,"/");
                  strcat(curr_dir,q);
               }
            }
            new_lock = Lock(curr_dir,SHARED_LOCK);
            if (new_lock != NULL)
            {  old_lock = CurrentDir(new_lock);
               UnLock(old_lock);
            } else printf("Directory %s does not exist\n",q);
         }
      } else Execute(p,0,output_file);
}

void command_loop()
{
   strcpy(curr_dir,"df0:");
   new_lock = Lock(curr_dir,SHARED_LOCK);
   old_lock = CurrentDir(new_lock);
   UnLock(old_lock);
   for(;;)
   {  int total;
      struct CMD *ptr;
      int i;
      register char *p,*q,*s,*t;

      printf("cpp> ");
      total = 0;
      fgets(tmpbuf,256,stdin);  /* get an input line */
      s = p = tmpbuf;
      while ((*p != '\n') && (*p != '\0'))
         p++;
      *p = '\0';                /* strip newline */
      if (tmpbuf[0] == '\0') continue;
      if (!strcmp(tmpbuf,"stop")) break;
      while (*s != NULL)
      {  q = strchr(s,';'); /* break multiple input cmds  */
         if (q == NULL)     /* copy 1 at a time into buff */
         {  strcpy(buff,s);
            *s = NULL;
         } else {
            t = buff;
            while (s < q)
               *t++ = *s++; /* copy first command into buff */
            s++;
            *t = '\0';
         }
         sscanf(buff,"%s",temp.string);
         for (i=0;i<strlen(temp.string);i++)
            total += temp.string[i];
         total &= 15;
         ptr = CMD_List[total];
         while (ptr != NULL)
         {  if (!strcmp(ptr->string,temp.string))
            {  char *u;
               struct { char *x;} args[10];
               int n;
               int m = -1;
               strcpy(buff2,ptr->replace);
               u = buff2;
               break_buff(&buff[strlen(ptr->string)],args);
               while ((u = strchr(u,'%')) != NULL)
               {  n = *(u+1) - '0' - 1;
                  insstr(u,args[n].x,args[n+1].x);
                  if (n > m)
                     m = n;
               }
               strcat(buff2," ");
               strcat(buff2,args[m+1].x);
               break;
            }
            ptr = ptr->Next_CMD;
         }
         if (ptr == NULL)
            p = buff;
         else
            p = buff2;
         printf("total cmd: %s\n",p);
         for (;p != NULL;)
         {  q = strchr(p,';');
            if (q != NULL)
               *q++ = '\0';
            printf("cmd: %s\n",p);
            exec_cmd(p);
            p = q;
         }   
      }
   }
}

main(argc, argv)
   int argc;
   char *argv[];
{
   char *FileName;
   char NullFile[30];
   register int i;

   NullFile[0] = '\0';
   temp.Next_CMD = NULL;
   for (i=0;i<16;i++)
   {
      CMD_List[i] = NULL;
      End[i] = NULL;
   }
   if (argc < 2)
      FileName = "sys:commands\0";
   else {
      argv++;
      if ((*argv)[0] == '?')
      {
         printf("command_file/K: ");
         FileName = NullFile;
         scanf("%s",FileName);
      }
      else FileName = argv[0];
   }
   printf("Filename: ");
   printf(FileName);
   printf("\n");
   cf = fopen(FileName,"r");
   if (cf == NULL)
   {  printf("Command file not found!\n");
      return(10);
   }
   while (fgets(buff,255,cf) != NULL)
   {
      register int total = 0;
      register char *p = buff;
      register char *s = temp.replace;
      
      while ((*p != '\n') && (*p != '\0'))
         p++;
      *p = '\0';                  /* drop newline char   */
      sscanf(buff,"%s",temp.string);
      p = &buff[strlen(temp.string)+2];
      while (*p == ' ')           /* drop leading spaces */
         p++;
      strcpy(s,p);                /* copy p to s */
      for (i=0;i<strlen(temp.string);i++)
         total += temp.string[i]; /* calculate hash index */
      total &= 15;
/*
 * insert abbreviation into 1 of 16 linked lists.  This is
 * done to reduce search time, and may not be needed.
 */
      if (CMD_List[total] == NULL)
      {  CMD_List[total] = (struct CMD *)
                                  alloc(sizeof(struct CMD));
         End[total] = CMD_List[total];
         *CMD_List[total] = temp;
      } else {
         End[total]->Next_CMD = (struct CMD *)
                                  alloc(sizeof(struct CMD));
         End[total] = End[total]->Next_CMD;
         *End[total] = temp;
      }
      End[total]->string = (char *)
                                 alloc(strlen(temp.string));
      strcpy(End[total]->string,temp.string);
      End[total]->replace = (char *)
                                alloc(strlen(temp.replace));
      strcpy(End[total]->replace,temp.replace);
   }
/* get input and output files */
   input_file = Input();
   output_file = Output();
   printf("Command Pre-Processor v1.00\n");
   printf(" courtesy Lunge Software Development\n");
   buff[0] = '\0';
   buff2[0] = '\0';
   command_loop();
   printf("Command Pre-Processing terminated\n");
}

break_buff(src,args)   /* parse arguments */
   char *src;
   struct { char *x;} args[];
{
   int i = 0;

   src = stpblk(src);         /* skip leading blanks */
   args[0].x = src;
   while (*src != '\0')       /* delims = \0 and space */
   {  if (*src == ' ')
      {  args[++i].x = ++src;
         src = stpblk(src);
      } else
         ++src;
   }
   for (i++;i<10;i++)         /* all others are null */
      args[i].x = src;
/* for (i=0;i<10;i++)
      printf("arg[%d] = %s\n",i,args[i].x);  */
}

insstr(dest,src,end)
/*
 * insert a string at a given position.  string starts at
 * src and goes to end-1
 */
   char *dest,*src,*end;
{
   char tmp[256];

   strcpy(tmp,&dest[2]);
/*   printf("start=%d, end=%d, remainder=%s, replace=%s\n",
           src,end,tmp,src);           */
   while (src != end)
      *dest++ = *src++;
   strcpy(dest,tmp);
}

/* ------------- eof -------------- */
