
#include <exec/types.h>
#include <ctype.h>
#include "hh:template.h"

/******** Definition of KeyArgV(TEMPLATE) */

/* If "TEMPLATE" EXISTS {
      Return <TEMPLATE>   ( EMPTY IF NOT FILLED )
   Else 
      Return NULL
   EndIf
*/

/******** Definition of DefaultKeyArgV(TEMPLATE,DEFAULT) */

/* If "TEMPLATE" EXISTS
      If "TEMPLATE" NON EMPTY
         Return <TEMPLATE>
      Else
         Return KeyArgV(DEFAULT)  ( SEE DEFINITION ABOVE )
      EndIf
   Else
      Return NULL
   EndIf
*/


typedef struct PLATEARGV {
       TEXT *pa_ArgV;
       BOOL pa_Used;
} PLATEARGV;

static PLATEARGV PlateArgV[50]; /* 50 Arguments Are A Lot */
static LONG InitialCount, FinalCount = 0; /* ReleaseTemplate() Needs This */

 static BOOL
StrULCmp(str1,str2)
 TEXT *str1, *str2;
{
 BOOL same;
 UBYTE byte;

 do {
    byte = ((!!isalpha(*str1))) | ((!!isalpha(*str2))<<1) |
           ((!!isupper(*str1))<<2) | ((!!isupper(*str2))<<3);
    if (!(byte&0x03)) {
       same = *str1==*str2;
    } else if ((byte&0x03)!=0x03) {
       same = FALSE;
    } else {
       switch (byte) {
         case 0x03 :
         case 0x0f :
              same = *str1==*str2;
              break;
         case 0x07 :
              same = *str1==_toupper(*str2);
              break;
         case 0x0b :
              same = _toupper(*str1)==*str2;
              break;
       }
    }
    str1++;
    str2++;
 } while (same && *str1);

 return (!(same && !*str2)); /* Returning FALSE when same */
}

 TEXT *
KeyArgV(key)
 TEXT *key;
{
 LONG i = 0;

 while (!(Template[i].tp_Flags&EOTP)) {
       if (!StrULCmp(Template[i].tp_Key,key)) {
          return(Template[i].tp_ArgV);
       } else {
          i++;
       }
 }

 return(NULL);
}


 TEXT *
DefaultKeyArgV(key,defkey)
 TEXT *key, *defkey;
{
 TEXT *argv;

 return((argv = KeyArgV(key)) ? ((*argv)?argv:KeyArgV(defkey)) : NULL);
}


 static VOID
PressTemplate()
{
 LONG i = 0;
 BOOL eop = Template[0].tp_Flags&EOTP;

 while (!eop) {
       printf("%s",Template[i].tp_Key);
       if (Template[i].tp_Flags&A_FLAG) {
          printf("/a");
       }
       if (Template[i].tp_Flags&K_FLAG) {
          printf("/k");
       }
       if (Template[i].tp_Flags&S_FLAG) {
          printf("/s");
       }
       if (!(eop=Template[++i].tp_Flags&EOTP)) {
          printf(",");
       }
 }

}

 static LONG
GetMoreArgVs(pa)
 PLATEARGV pa[];
{
 LONG i =0;
 BOOL more = FALSE;

 do {
    PressTemplate();
    printf(": ");
    do {
       pa[i].pa_ArgV = (TEXT *)AllocMem(50);
       pa[i].pa_Used = FALSE;
       scanf("%s",pa[i++].pa_ArgV);
    } while (getchar()==' ');
    if ((more = !StrULCmp(pa[i-1].pa_ArgV,"?"))) {
       FreeMem(pa[--i].pa_ArgV,50);
    }
 } while (more);

 return(i);
}


 VOID
ReleaseTemplate()
{
 while (InitialCount<FinalCount) {
       FreeMem(PlateArgV[InitialCount++].pa_ArgV,50);
 }
}


 BOOL
FetchTemplate(ac,av)
 LONG ac;
 TEXT *av[];
{
 LONG mc = ac -1;
 LONG ArgVs, Plates = 0;
 LONG avn, pln;
 BOOL NoError, Match;

 pln = 0;
 while (!(Template[pln].tp_Flags&EOTP)) {
       if (Template[pln].tp_UserVar) {
          *Template[pln].tp_UserVar = "";
       }
       Template[pln].tp_ArgV = ""; /* Make Every Entry Empty */ 
       pln++;
 }

 while (ac>1) {
       PlateArgV[ac -2].pa_ArgV = av[ac -1];
       PlateArgV[ac -2].pa_Used = FALSE;
       ac--;
 }

 InitialCount = mc;

 if (mc && !StrULCmp(PlateArgV[mc -1].pa_ArgV,"?")) {
    InitialCount--;
    mc += GetMoreArgVs(&PlateArgV[mc -1]) -1;
 }

 FinalCount = mc;

 while (!(Template[Plates].tp_Flags&EOTP)) {
       Plates++;
 }

 ArgVs = FinalCount;
 NoError = TRUE;

 while (Plates && ArgVs && NoError) {
       /* Get First Free ArgV */
       avn = 0;
       while (PlateArgV[avn].pa_Used) {
             avn++;
       }

       /* Seek Into Plate For Identical KeyWord */
       pln = 0;
       while (!(Template[pln].tp_Flags&EOTP) &&
              (Template[pln].tp_Flags&FETCHED ||
              StrULCmp(Template[pln].tp_Key,PlateArgV[avn].pa_ArgV))) {
             pln++;
       }

       /* If Not Found, Try First Not /K/S */
       if (Template[pln].tp_Flags&EOTP) {
          Match = FALSE;
          pln = 0;
          while (!(Template[pln].tp_Flags&EOTP) &&
                 Template[pln].tp_Flags&(K_FLAG|S_FLAG|FETCHED)) {
                pln++;
          }
       } else {
          Match = TRUE;
       }

       /* If Found, Fill It, Else Error */
       if (Template[pln].tp_Flags&EOTP) {
          NoError = FALSE;
       } else {
          Template[pln].tp_Flags |= FETCHED;
          PlateArgV[avn].pa_Used = TRUE;
          ArgVs--;
          Plates--;

          if (Template[pln].tp_Flags&S_FLAG || !Match) {

             Template[pln].tp_ArgV = PlateArgV[avn].pa_ArgV;
             if (Template[pln].tp_UserVar) {
                *(Template[pln].tp_UserVar) = PlateArgV[avn].pa_ArgV;
             }

          } else { /* KeyWord, So Use Next ArgV */

             if (ArgVs) {
                PlateArgV[++avn].pa_Used = TRUE;
                ArgVs--;
         
                Template[pln].tp_ArgV = PlateArgV[avn].pa_ArgV;
                if (Template[pln].tp_UserVar) {
                   *(Template[pln].tp_UserVar) = PlateArgV[avn].pa_ArgV;
                }

             } else {
                NoError = FALSE;
             }
          }
  
       }
 }

 if (ArgVs) {
    NoError = FALSE;
 } else if (Plates) {
    pln = 0;
    while (NoError && !(Template[pln].tp_Flags&EOTP)) {
          if (!(Template[pln].tp_Flags&FETCHED) &&
              Template[pln].tp_Flags&A_FLAG) {
             NoError = FALSE;
          } else {
             pln++;
          }
    }
 }

 if (!NoError) {
    printf("Args no good for key \"");
    PressTemplate();
    printf("\"\n");
 }

 return(NoError);
}


