/* Haktar-Checker V1.6
   The reality simulation language interpreter adventure text file tester.
°ª°by Guido Wegener      Mar.1992

   This program is Freeware, it may be copied aslong as no profit is made
   and the .doc-file is included.

   Compile with Aztec C 5.0b
     simply by calling : Caos Hakcheck.c
   CaoS'cc HakCheck.c -ff -m0c -m0d -pb -pe -ps -q0f -sn -sp -su -wa -wp -wr'
   CaoS'ln HakCheck.o -lc16'

   Commodore Amiga :
   Hast du zwei,
   hol' dir drei !
   
   Ein toter Kerl dank Schlappi !
*/
#include <pragmas.h>
#include <functions.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libraries/dosextens.h>
#include <exec/types.h>
#include <exec/memory.h>

#define ATINTEGER (UBYTE)0 /* +no number -> stop */
#define ATWORD    (UBYTE)1 /* +' ' as stops */
#define ATNAME    (UBYTE)2 /* +[|], as stops */
#define ATSTRING  (UBYTE)3 /* '\n' and · as stops, keep leading spaces */
#define ATUNIMP   128      /* arg is not important */
#define ATLONG    64       /* 80 */
#define ATMEDIUM  96       /* 79 */
#define ATSHORT   32       /* 77 */
#define ATXL      0        /* 9999...9999 */
#define CODE 1
#define DECODE 2
#define NOCODE 0
#define SPLIT 3
#define QUIET 4
#define MAXBDEP 300

struct DOSBase *DOSBase=NULL;

struct item
 {
  struct item *nextitem;
  char name[81];
 };

struct item *unfiles=NULL,*files=NULL,*flags=NULL,*vars=NULL,*unvars=NULL;
char head[81]="";
long int nfiles=0,nbytes=0;
int extra=NOCODE;
char *argx=NULL;
UBYTE ccode;
char brac[MAXBDEP];
int bdep;
clevel=0;

void ope(void); /* open everything, init even more */
void clos(char *text); /* close and free and unlock everything */
void analyse(char *file);
void readarg(char **act,char *arg,UBYTE flags,char *file,long *line); /* Put one arguement into arg and move act.*/
void clearlist(struct item *list); /* Frees the memory of an item-list.*/
void list(void); /* display lists */
BOOL search(struct item *list,char *file); /* TRUE if file is in list */
void addlist(struct item **list,struct item **unlist,char *string); /* add string to list, if not there */
void lowcase(char *string);
void headex(void);
void bracer(char c,char *file,long *line);
void putin(int c);  /* Hello, fucking Aztecs ! 'x' statements are ints ? */
void cutout(void);
void iffi(char **act,char *name,long *line);
void isthere(char *file,char *name,long *line);

void headpath(char **act,char *file,long *line);  /* N    path for everything */
void maxweight(char **act,char *file,long *line); /* I    maximum weight to carry */
void addweight(char **act,char *file,long *line); /* I    add weight of item */
void ifweight(char **act,char *file,long *line);  /* I    if item can be carried */
void print(char **act,char *file,long *line);     /* S    display line */
void cprint(char **act,char *file,long *line);    /* S    centred display line */
void textwait(char **act,char *file,long *line);      /*      wait for continue */
void create(char **act,char *file,long *line);    /* NN   create item in room {or pocket} */
void gone(char **act,char *file,long *line);      /* NN   delete item in room {or pocket} */
void ifflag(char **act,char *file,long *line);    /* NBB  if flag is set */
void setflag(char **act,char *file,long *line);   /* N    set flag */
void delflag(char **act,char *file,long *line);   /* N    unset flag */
void showpic(char **act,char *file,long *line);   /* NI   display IFF-file */
void showpicsub(char **act,char *file,long *line);/* NI   display IFF-file */
void simpleface(char **act,char *file,long *line);
void settime(char **act,char *file,long *line);   /* I    set time */
void addtime(char **act,char *file,long *line);   /* I    add to time */
void ifitemin(char **act,char *file,long *line);  /* NNBB if item is in room {or pocket} */
void sys(char **act,char *file,long *line);       /* S    open slot for hard-routines */
void dead(char **act,char *file,long *line);      /*      game over */
void input(char **act,char *file,long *line);     /*      read a string as last input */
void move(char **act,char *file,long *line);      /* NNN  move item from room {o.p.} to r.{op} */
void fdo(char **act,char *file,long *line);       /* NB  one of the #do choices */
void ifinput(char **act,char *file,long *line);   /* NBB  if the last input equals $ */
void iftime(char **act,char *file,long *line);    /* IIBB if time is between values */
void items(char **act,char *file,long *line);     /* n*N  list of items in room */
void ifin(char **act,char *file,long *line);      /* NBB  if character is in room */
void go(char **act,char *file,long *line);        /* N    move character to room */
void rem(char **act,char *file,long *line);       /* S    remark */
void execute(char **act,char *file,long *line);   /* N    file will be executed */
void handle(char **act,char *file,long *line);    /* I  standard get/drop procedure; int=weight */
void getphrase(char **act,char *file,long *line); /* S    text to take | §=actname*/
void dropphrase(char **act,char *file,long *line);/* S    text to drop */
void cantgetphrase(char **act,char *file,long *line);/*S  text id too heavy */
void setvar(char **act,char *file,long *line);    /* NI   set var to */
void addvar(char **act,char *file,long *line);    /* NI   adds const to var */
void ifvar(char **act,char *file,long *line);     /* NIIBB if var between */
void eachmove(char **act,char *file,long *line);  /* N    file is to be executed each turn */
void multi(char **act,char *file,long *line);     /* n*N  files include several things */
void thing(char **act,char *file,long *line);     /* NB   thing in file */
void printfile(char **act,char *file,long *line); /* N    prints the file */
void ifchance(char **act,char *file,long *line);
void doscall(char **act,char *file,long *line);
void font(char **act,char *file,long *line);
void noautowait(char **act,char *file,long *line);
void printvar(char **act,char *file,long *line);
void startchoose(char **act,char *file,long *line);
void choose(char **act,char *file,long *line);
void endchoose(char **act,char *file,long *line);
void storevars(char **act,char *file,long *line);
void getvars(char **act,char *file,long *line);
void locoff(char **act,char *file,long *line);
void locon(char **act,char *file,long *line);

void main(int argc,char *argv[])
 {
  long i;
  char argcop[81];
  
  Enable_Abort=0;
  puts("Haktar-Checker V1.6 for Haktar V1.6 by Guido Wegener");
  if(argc<2 || argc>4)
   {
    puts("Usage : HakCheck <filename> [SPLIT|(CODE|DECODE <Code>)]");
    puts(" <filename> is the head-file of the adventure you want to check.");
    return;
   }
  if(argc>2)
   {
    strncpy(argcop,argv[2],(size_t)80);
    lowcase(argcop);
    if(!strcmp("code",argcop)) extra=CODE;
    else if(!strcmp("decode",argcop)) extra=DECODE;
    else if(!strcmp("split",argcop)) extra=SPLIT;
    else if(!strcmp("quiet",argcop)) extra=QUIET;
    else clos("Unknown 2nd parameter !");
    if(extra==DECODE || extra==CODE)
     {
      if(argc!=4) clos("What code ?");
      if(strlen(argv[3])!=4) clos("Code must have exactly 4 characters !");
      argx=argv[3];
      argx[0]+=1;
      argx[1]-=1;
      argx[2]+=4;
      argx[3]+=2;
      ccode=argx[0]+2*argx[1]+5*argx[2]+3*argx[3];
     }
   }
  ope();
  analyse(argv[1]);
  list();
  clos(NULL);
 }

void ope()
 {
  int i;
  
  DOSBase=(struct DOSBase *)OpenLibrary("dos.library",0L);
  if(!DOSBase) clos("Can't open DOS !");
  for(i=0;i<MAXBDEP;i++) brac[i]=0;
  bdep=0;
 }
 
void clos(char *text)
 {
  clearlist(unfiles);
  clearlist(files);
  clearlist(flags);
  clearlist(vars);
  clearlist(unvars);
  if(text) puts(text);
  if(DOSBase) CloseLibrary(DOSBase);
  exit(0);
 }

void lowcase(char *str)
 {
  while(*str)
   {
    if(*str==215 || *str==247);
    else if(*str>='A' && *str<='Z') *str+=32;
    else if(*str>=192 && *str<=222) *str+=32;
    str++;
   }
 }

void headex()
 {
  int p;
  char c;
  
  p=strlen(head);
  if(p)
   {
    c=head[p-1];
    if(c!=':' && c!='/')
     {
      head[p]='/';
      p++;
      if(p>81) p=81;
      head[p]=0;
     }
   }
 }

void cutout()
 {
  int i;
  
  if(bdep<=0)
   {
    puts("Negative bdepth !");
   }
  bdep--;
  brac[bdep]=0;
 }

void putin(int c)
 {
  int i;

  brac[bdep]=c;
  bdep++;
  if(bdep>=MAXBDEP)
   {
    puts("Too complex adventure structure !!!  (Can't check it.)");
    puts("I don't think that ANY normal adventure will reach this error,");
    puts("but you did it ! So, PLEASE send the listing to the athor !!!");
    puts("Thanx   °ª°");
   }
 }

void bracer(char c,char *file,long *line)
 {
  if(c=='\n') (*line)++;
  if(c!='[' && c!=']' && c!='|') return;
  if(!bdep)
   {
    printf("Wrong parantheses ! In [%s] , line %ld\n  Expected nothing , found : %c\n",file,*line,c);
    return;
   }
  if(brac[bdep-1]==c) cutout();
  else
   {
    printf("Wrong parantheses ! In [%s] , line %ld\n  Expected : %c , found : %c\n",file,*line,brac[bdep-1],c);
   }
 }

void analyse(char *file)
 {
  struct FileHandle *fh;
  char *buffer;
  char fullname[162];
  struct FileInfoBlock *fib;
  long lock;
  long size,check;
  char comand[21]; /* I know that it is spelled «command», but this way it is shorter...*/
  long i;
  char *c;
  char **act;
  BOOL coded;
  char code[6];
  long ix;
  UBYTE dcode;
  int enterdep;
  char enterbrac[MAXBDEP];
  long line;
  
  if(!(*file) || *file=='¡' || search(files,file)) return;

  enterdep=bdep;
  strncpy(enterbrac,brac,(size_t)MAXBDEP);
  act=&c;
  strncpy(fullname,head,(size_t)81);
  strncpy(&(fullname[strlen(fullname)]),file,(size_t)81);

  lock=Lock(fullname,-2L);
  if(!lock)
   {
    addlist(&unfiles,NULL,file);
    return;
   }
  addlist(&files,&unfiles,file);
  fib=AllocMem(sizeof(struct FileInfoBlock),NULL);
  if(!fib) {UnLock(lock);clos("analyse() : no memory for FileInfoBlock !");}
  if(!Examine(lock,fib)) {UnLock(lock);FreeMem(fib,sizeof(struct FileInfoBlock));clos("analyse() : trouble with Examine !");}
  UnLock(lock);
  size=(long)(fib->fib_Size);
  nbytes+=size;
  nfiles++;
  FreeMem(fib,sizeof(struct FileInfoBlock));

  line=0;
  if(extra!=QUIET) printf("  Checking file : [%s]\n",file);
  if(strcmp("Hütte",file))
   {
    fh=(struct FileHandle *)Open(fullname,(long)MODE_OLDFILE);
   }
  else
   {
    fh=(struct FileHandle *)Open("haktar:beispiel/hütte",(long)MODE_OLDFILE);
   }
  if(!fh)
   {
    clos("analyse() : can't Open file !");
   }
  check=Read((BPTR)fh,code,6L);
  if(!strncmp(code,"cOdE01",(size_t)6))
   {
    if(extra!=DECODE) {printf("File %s is coded !\n",fullname);Close((BPTR)fh);return;}
    coded=TRUE;
    check=Read((BPTR)fh,code,4L);
    if(check!=4) {Close((BPTR)fh);clos("analyse() : can't Read Code !");}
    if(strncmp(code,argx,(size_t)4)) {printf("Wrong code for %s !\n",fullname);Close((BPTR)fh);return;}
    dcode=code[0]+2*code[1]+5*code[2]+3*code[3];
    size-=10;
   }
  else
   {
    coded=FALSE;
    check=Seek((BPTR)fh,0L,(long)OFFSET_BEGINNING);
   }
  buffer=AllocMem(size+1,NULL);
  if(!buffer) clos("analyse() : no memory for buffer !");
  check=Read((BPTR)fh,buffer,size);
  if(check!=size) {Close((BPTR)fh);clos("analyse() : can't Read !");}
  Close((BPTR)fh);
  buffer[size]=0;
  size++;
  if(coded) for(ix=0;ix<size-1;ix++) buffer[ix]=buffer[ix] ^ ((UBYTE)ix+dcode);

  c=buffer;
  bracer(*c,fullname,&line);
  while(*c)
   {
    i=0;
    while(*c==' ' || *c=='\t' || *c=='\n' || *c==',' || *c=='·' || *c==']' || *c=='|' || *c=='[')
     {
      c++;
      bracer(*c,fullname,&line);
     }
    while(i<20 && *c && *c!=' ' && *c!='\n' && *c!=',' && *c!='·' && *c!=']' && *c!='|' && *c!='[' && *c!='\t')
     {
      comand[i]=*c;
      c++;
      i++;
      bracer(*c,fullname,&line);
     }
    comand[i]=0;
    lowcase(comand);
         if(!strcmp(comand,"do")) fdo(act,fullname,&line);
    else if(!strcmp(comand,"ifweight")      || !strcmp(comand,"iw")) ifweight(act,fullname,&line);
    else if(!strcmp(comand,"items")         || !strcmp(comand,"i")) items(act,fullname,&line);
    else if(!strcmp(comand,"print")         || !strcmp(comand,"?") || !strcmp(comand,"p")) print(act,fullname,&line);
    else if(!strcmp(comand,"move")          || !strcmp(comand,"m")) move(act,fullname,&line);
    else if(!strcmp(comand,"addtime")       || !strcmp(comand,"at")) addtime(act,fullname,&line);
    else if(!strcmp(comand,"go")) go(act,fullname,&line);
    else if(!strcmp(comand,"wait")          || !strcmp(comand,"w")) textwait(act,fullname,&line);
    else if(!strcmp(comand,"noautowait")    || !strcmp(comand,"naw")) noautowait(act,fullname,&line);
    else if(!strcmp(comand,"addweight")     || !strcmp(comand,"aw")) addweight(act,fullname,&line);
    else if(!strcmp(comand,"rem")           || !strcmp(comand,";")) rem(act,fullname,&line);
    else if(!strcmp(comand,"create")        || !strcmp(comand,"c")) create(act,fullname,&line);
    else if(!strcmp(comand,"gone")          || !strcmp(comand,"g") || !strcmp(comand,"lost")) gone(act,fullname,&line);
    else if(!strcmp(comand,"ifflag")        || !strcmp(comand,"if")) ifflag(act,fullname,&line);
    else if(!strcmp(comand,"setflag")       || !strcmp(comand,"sf")) setflag(act,fullname,&line);
    else if(!strcmp(comand,"delflag")       || !strcmp(comand,"df")) delflag(act,fullname,&line);
    else if(!strcmp(comand,"setvar")        || !strcmp(comand,"sv")) setvar(act,fullname,&line);
    else if(!strcmp(comand,"storevars")     || !strcmp(comand,"stv")) storevars(act,fullname,&line);
    else if(!strcmp(comand,"getvars")       || !strcmp(comand,"gv")) getvars(act,fullname,&line);
    else if(!strcmp(comand,"ifvar")         || !strcmp(comand,"iv")) ifvar(act,fullname,&line);
    else if(!strcmp(comand,"addvar")        || !strcmp(comand,"av")) addvar(act,fullname,&line);
    else if(!strcmp(comand,"showpic")       || !strcmp(comand,"sp")) showpic(act,fullname,&line);
    else if(!strcmp(comand,"showpicsub")    || !strcmp(comand,"sps")) showpicsub(act,fullname,&line);
    else if(!strcmp(comand,"simpleface")    || !strcmp(comand,"sif")) simpleface(act,fullname,&line);
    else if(!strcmp(comand,"settime")       || !strcmp(comand,"st")) settime(act,fullname,&line);
    else if(!strcmp(comand,"ifitemin")      || !strcmp(comand,"iii")) ifitemin(act,fullname,&line);
    else if(!strcmp(comand,"sys")           || !strcmp(comand,"s")) sys(act,fullname,&line);
    else if(!strcmp(comand,"dead")          || !strcmp(comand,"d")) dead(act,fullname,&line);
    else if(!strcmp(comand,"input")         || !strcmp(comand,"inp")) input(act,fullname,&line);
    else if(!strcmp(comand,"ifinput")       || !strcmp(comand,"iinp")) ifinput(act,fullname,&line);
    else if(!strcmp(comand,"iftime")        || !strcmp(comand,"it")) iftime(act,fullname,&line);
    else if(!strcmp(comand,"ifin")          || !strcmp(comand,"ii")) ifin(act,fullname,&line);
    else if(!strcmp(comand,"headpath")      || !strcmp(comand,"hp")) headpath(act,fullname,&line);
    else if(!strcmp(comand,"maxweight")     || !strcmp(comand,"mw")) maxweight(act,fullname,&line);
    else if(!strcmp(comand,"execute")       || !strcmp(comand,"e")) execute(act,fullname,&line);
    else if(!strcmp(comand,"handle")        || !strcmp(comand,"h")) handle(act,fullname,&line);
    else if(!strcmp(comand,"multi")         || !strcmp(comand,"mf")) multi(act,fullname,&line);
    else if(!strcmp(comand,"thing")         || !strcmp(comand,"t")) thing(act,fullname,&line);
    else if(!strcmp(comand,"eachmove")      || !strcmp(comand,"em")) eachmove(act,fullname,&line);
    else if(!strcmp(comand,"getphrase")     || !strcmp(comand,"gp")) getphrase(act,fullname,&line);
    else if(!strcmp(comand,"dropphrase")    || !strcmp(comand,"dp")) dropphrase(act,fullname,&line);
    else if(!strcmp(comand,"cantgetphrase") || !strcmp(comand,"cgp")) cantgetphrase(act,fullname,&line);
    else if(!strcmp(comand,"printfile")     || !strcmp(comand,"pf")) printfile(act,fullname,&line);
    else if(!strcmp(comand,"font")          || !strcmp(comand,"fo")) font(act,fullname,&line);
    else if(!strcmp(comand,"ifchance")      || !strcmp(comand,"ic")) ifchance(act,fullname,&line);
    else if(!strcmp(comand,"doscall")       || !strcmp(comand,"dc")) doscall(act,fullname,&line);
    else if(!strcmp(comand,"cprint")        || !strcmp(comand,"c?") || !strcmp(comand,"!")) cprint(act,fullname,&line);
    else if(!strcmp(comand,"printvar")      || !strcmp(comand,"?v") || !strcmp(comand,"pv")) printvar(act,fullname,&line);
    else if(!strcmp(comand,"choose")        || !strcmp(comand,"c")) choose(act,fullname,&line);
    else if(!strcmp(comand,"startchoose")   || !strcmp(comand,"sc")) endchoose(act,fullname,&line);
    else if(!strcmp(comand,"locoff")        || !strcmp(comand,"loff")) locoff(act,fullname,&line);
    else if(!strcmp(comand,"locon")         || !strcmp(comand,"lon")) locoff(act,fullname,&line);
    else if(!strcmp(comand,"endchoose")     || !strcmp(comand,"ec")) startchoose(act,fullname,&line);
    else if(*comand) printf("Syntax Error in [%s], line %ld :\n [%s] is no command !!!\n",fullname,line,comand);
   }
  if(extra==CODE || extra==DECODE)
   {
    fh=(struct FileHandle *)Open(fullname,(long)MODE_NEWFILE);
    if(!fh) {FreeMem(buffer,size);clos("analyse() : can't Reopen file !");}
    if(extra==CODE)
     {
      check=Write((BPTR)fh,"cOdE01",6L);
      if(check!=6) {Close((BPTR)fh);FreeMem(buffer,size);clos("Can't Rewrite mark !");}
      check=Write((BPTR)fh,argx,4L);
      if(check!=4) {Close((BPTR)fh);FreeMem(buffer,size);clos("Can't Rewrite Code !");}
      for(ix=0;ix<size-1;ix++) buffer[ix]=buffer[ix] ^ ((UBYTE)ix+ccode);
     }
    check=Write((BPTR)fh,buffer,size-1);
    if(check!=size-1) puts("Can't write back !");
    Close((BPTR)fh);
   }
  FreeMem(buffer,size);
  if(clevel>0) printf("Missing endchoose in [%s]\n",fullname);
  if(clevel<0) printf("Missing startchoose in [s]\n",fullname);
  clevel=0;
  if(bdep!=enterdep)
   {
    printf("Missing parantheses in [%s] : %s\n",fullname,brac);
    bdep=enterdep;
    strncpy(brac,enterbrac,(size_t)MAXBDEP);
   }
 }

void iffi(char **act,char *name,long *line)
 {
  char *pact;
  char nextif[81];
  
  pact=*act;
  readarg(act,nextif,(UBYTE)(ATWORD | ATUNIMP|ATSHORT),name,line);
  *act=pact;
  if(!*nextif)
   {
    putin(']');
    putin('|');
    putin('[');
   }
 }

void list()
 {
  struct item *point;

  point=flags;
  if(extra!=QUIET) puts(" - Used flags :");
  while(point)
   {
    if(extra!=QUIET) printf("  [%s]\n",point->name);
    point=point->nextitem;
   }

  point=vars;
  if(extra!=QUIET) puts(" - Used vars :");
  while(point)
   {
    if(extra!=QUIET) printf("  [%s]\n",point->name);
    point=point->nextitem;
   }

  if(unvars)
   {
    point=unvars;
    if(extra!=QUIET) puts(" - Bad var-references :");
    while(point)
     {
      if(extra!=QUIET) printf("  [%s]\n",point->name);
      point=point->nextitem;
     }
   }

  if(unfiles)
   {  
    point=unfiles;
    puts(" - References to not existing files :");
    while(point)
     {
      printf("  [%s]\n",point->name);
      point=point->nextitem;
     }
   }
  else if(extra!=QUIET) puts(" All referenced files exist ! (That's good !)");
  if(extra!=QUIET)
   {
    printf(" Number of files : %ld\n",nfiles);
    printf(" Total length (bytes) : %ld\n",nbytes);
    if(nfiles) printf(" Average length : %ld\n",nbytes/nfiles);
   }
 }

BOOL search(struct item *list,char *file)
 {
  struct item *point;
  
  point=list;
  while(point)
   {
    if(!strcmp(point->name,file)) return TRUE;
    point=point->nextitem;
   }
  return FALSE;
 }

void addlist(struct item **list,struct item **unlist,char *string)
 {
  struct item *point,**prev;
  
  if(search(*list,string)) return;
  if(unlist)
   {
    if(search(*unlist,string))
     {
      point=*unlist;
      prev=unlist;
      while(point)
       {
        if(!strcmp(string,point->name))
         {
          *prev=point->nextitem;
          FreeMem(point,sizeof(struct item));
          point=*prev;
         }
        else
         {
          prev=&(point->nextitem);
          point=point->nextitem;
         }
       }
     }
   }
  
  point=AllocMem(sizeof(struct item),NULL);
  if(!point) clos("addlist() : No memory for item !");
  point->nextitem=*list;
  strcpy(point->name,string);
  *list=point;
 }

void readarg(char **act,char *arg,UBYTE flags,char *name,long *line)
 {
  char c;
  int i;
  BOOL cont;
  UBYTE upflag;
  BOOL unimp;
  int max;
  
  upflag=flags & (ATLONG|ATSHORT|ATMEDIUM|ATXL);
  unimp=flags&ATUNIMP;
  flags=flags & (255-(ATLONG|ATSHORT|ATMEDIUM|ATXL|ATUNIMP));
  switch(upflag)
   {
    case ATLONG   : max=80;break;
    case ATMEDIUM : max=79;break;
    case ATSHORT  : max=77;break;
    case ATXL     : max=1;break;
    default : max=80;break;
   }
  c=**act;
  if(!c)
   {
    *arg=0;
    if(!unimp) printf("Missing argument ! File : %s , Line : %ld\n",name,*line);
    return;
   }
  if(c=='\n' || c=='·' || c=='[' || c=='|' || c==']')
   {
    *arg=0;
    if(!unimp) (*act)++;
    bracer(**act,name,line);
    if(!unimp) printf("Missing argument ! File : %s , Line %ld\n",name,*line);
    return;
   }
  (*act)++;
  bracer(**act,name,line);
  c=**act;
  if(!c || c=='\n' || c==']' || c=='·' || c=='|' || c=='[' || (flags!=ATSTRING && c==','))
   {
    *arg=0;
    if(!unimp) printf("Missing argument ! File : %s , Line %ld\n",name,*line);
    return;
   }
  if(flags!=ATSTRING)
    while(**act==' ' && **act)
     {
      (*act)++;
      bracer(**act,name,line);
     }
  i=0;
  c=**act;
  cont=TRUE;
  while(cont && c && c!='\n' && c!='·' && c!='[' && c!='|' && c!=']' && i<max+1)
   {
    if(i>=max)
     {
      printf("Argument too long! File : %s , Line %ld\n",name,*line);
      break;
     }
    arg[i]=c;
    if(upflag!=ATXL) i++;
    (*act)++;
    bracer(**act,name,line);
    c=**act;
    if(flags==ATNAME && c==',') cont=FALSE;
    else if(flags==ATWORD && (c==' ' || c==',')) cont=FALSE;
    else if(flags==ATINTEGER && (c<'0' || c>'9') && c!='-' && c!='+') cont=FALSE;
   }
  arg[i]=0;
  i--;
  if(flags!=ATSTRING)
    while(i>=0 && arg[i]==' ')
     {
      arg[i]=0;
      i--;
     }
  if(!*arg && !unimp) printf("Missing argument ! File : %s , Line %ld\n",name,*line);
  if(flags==ATNAME && (!strcmp(arg,"INV") || !strcmp(arg,"ACTROOM"))) *arg=0;
  if(upflag!=ATXL) arg[max]=0;
 }
 
void clearlist(struct item *list)
 {
  struct item *point;
  
  while(list)
   {
    point=list;
    list=list->nextitem;
    FreeMem(point,sizeof(struct item));
   }
 }

void storevars(char **act,char *name,long *line)
 {
  char file[81];
  
  readarg(act,file,(UBYTE)(ATNAME|ATLONG),name,line);
  while(*file)
   {
    readarg(act,file,(UBYTE)(ATNAME|ATLONG|ATUNIMP),name,line);
   }
 }

void getvars(char **act,char *name,long *line)
 {
  char file[81];
  
  readarg(act,file,(UBYTE)(ATNAME|ATLONG),name,line);
  while(*file)
   {
    readarg(act,file,(UBYTE)(ATNAME|ATLONG|ATUNIMP),name,line);
   }
 }

void choose(char **act,char *name,long *line)
 {
  char choice[81];
  
  readarg(act,choice,(UBYTE)(ATSTRING|ATSHORT),name,line);
  putin(']');
  putin('[');
 }

void startchoose(char **act,char *name,long *line)
 {
  clevel++;
  if(clevel>9) printf("More than 10 choose levels in [%s]\n",name);
 }

void endchoose(char **act,char *name,long *line)
 {
  clevel--;
 }
 
void printfile(char **act,char *name,long *line)
 {
  char file[81],fullname[161];
  struct FileInfoBlock *fib;
  long lock;
  long size;
  
  readarg(act,file,(UBYTE)(ATNAME|ATLONG),name,line);

  strncpy(fullname,head,(size_t)81);
  strncpy(&(fullname[strlen(fullname)]),file,(size_t)81);

  lock=Lock(fullname,-2L);
  if(!lock)
   {
    addlist(&unfiles,NULL,name);
    return;
   }
  fib=AllocMem(sizeof(struct FileInfoBlock),NULL);
  if(!fib) {UnLock(lock);clos("analyse() : no memory for FileInfoBlock !");}
  if(!Examine(lock,fib)) {UnLock(lock);FreeMem(fib,sizeof(struct FileInfoBlock));clos("analyse() : trouble with Examine !");}
  UnLock(lock);
  size=(long)(fib->fib_Size);
  nbytes+=size;
  nfiles++;
  FreeMem(fib,sizeof(struct FileInfoBlock));
 }

void getphrase(char **act,char *name,long *line)
 {
  char str[81];
  
  readarg(act,str,(UBYTE)(ATSTRING|ATSHORT),name,line);
 }

void cantgetphrase(char **act,char *name,long *line)
 {
  char str[81];
  
  readarg(act,str,(UBYTE)(ATSTRING|ATMEDIUM),name,line);
 }

void font(char **act,char *name,long *line)
 {
  char fname[81];
  
  readarg(act,fname,(UBYTE)(ATSTRING|ATLONG),name,line);
 }

void dropphrase(char **act,char *name,long *line)
 {
  char str[81];
  
  readarg(act,str,(UBYTE)(ATSTRING|ATSHORT),name,line);
 }

void multi(char **act,char *name,long *line)
 {
  BOOL args;
  char file[81];
  
  do
   {
    readarg(act,file,(UBYTE)(ATNAME | ATUNIMP|ATLONG),name,line);
    if(!(*file))
     {
      args=FALSE;
/*      (*act)--;
*/     }
    else
     {
      analyse(file);
      args=TRUE;
     }
   }
  while(args);
 }

void thing(char **act,char *name,long *line)
 {
  char tname[81];
  char *start,*rem;
  long length,check;
  int a;
  struct FileHandle *fh;
  char fullname[161];
  
  readarg(act,tname,(UBYTE)(ATNAME|ATSHORT),name,line);
  addlist(&files,&unfiles,tname);
  putin(']');
  putin('[');
  if(extra==SPLIT)
   {
    rem=*act;
    while(**act!='[' && **act)
     {
      (*act)++;
     }
    length=-2;
    start=*act+1;
    a=0;
    while(a>=0 && **act)
     {
      if(**act=='[') a++;
      if(**act==']')
       {
        if(a==1) a=-1;
        a--;
       }
      (*act)++;
      length++;
     }
    strncpy(fullname,head,(size_t)81);
    strncpy(&(fullname[strlen(fullname)]),tname,(size_t)81);
    fh=(struct FileHandle *)Open(fullname,(long)MODE_NEWFILE);
    if(!fh) {puts("Can't open splitter !");return;}
    if(!**act) puts("END");
    check=Write((BPTR)fh,start,length);
    if(check!=length) puts("Can't write splitter !");
    Close((BPTR)fh);
    *act=rem;
   }
 }

void eachmove(char **act,char *name,long *line)
 {
  char file[81];
  
  readarg(act,file,(UBYTE)(ATNAME | ATUNIMP|ATLONG),name,line);
  analyse(file);
 }

void doscall(char **act,char *name,long *line)
 {
  char var[81];
  char com[81];
  
  readarg(act,com,(UBYTE)(ATNAME|ATLONG),name,line);
 }

void setvar(char **act,char *name,long *line)
 {
  char var[81];
  char val[78];
  
  readarg(act,var,(UBYTE)(ATNAME|ATLONG),name,line);
  readarg(act,val,(UBYTE)(ATINTEGER|ATSHORT),name,line);
  addlist(&vars,&unvars,var);
 }

void addvar(char **act,char *name,long *line)
 {
  char var[81],num[78];
  
  readarg(act,var,(UBYTE)(ATNAME|ATLONG),name,line);
  readarg(act,num,(UBYTE)(ATINTEGER|ATSHORT),name,line);
  if(!search(vars,var)) addlist(&unvars,NULL,var);
 }

void printvar(char **act,char *name,long *line)
 {
  char text1[81],text2[81],var[81];
  
  readarg(act,text1,(UBYTE)(ATNAME|ATSHORT),name,line);
  readarg(act,var,(UBYTE)(ATNAME|ATLONG),name,line);
  readarg(act,text2,(BYTE)(ATNAME | ATUNIMP|ATSHORT),name,line);
  if(!search(vars,var)) addlist(&unvars,NULL,var);
 }

void ifvar(char **act,char *name,long *line)
 {
  char var[81],low[81],high[81];
  
  readarg(act,var,(UBYTE)(ATNAME|ATLONG),name,line);
  readarg(act,low,(UBYTE)(ATINTEGER|ATSHORT),name,line);
  readarg(act,high,(UBYTE)(ATINTEGER | ATUNIMP|ATSHORT),name,line);
  if(!search(vars,var)) addlist(&unvars,NULL,var);
  iffi(act,name,line);
 }

void items(char **act,char *name,long *line)
 {
  BOOL args;
  char file[81];
  
  do
   {
    readarg(act,file,(UBYTE)(ATNAME | ATUNIMP|ATSHORT),name,line);
    if(!(*file))
     {
      args=FALSE;
/*      (*act)--;
*/     }
    else
     {
      analyse(file);
      args=TRUE;
     }
   }
  while(args);
 }

void fdo(char **act,char *name,long *line)
 {
  char doer[81];
  
  readarg(act,doer,(UBYTE)(ATSTRING|ATSHORT),name,line);
  putin(']');
  putin('[');
 }

void ifflag(char **act,char *name,long *line)
 {
  char arg[81];
  
  readarg(act,arg,(UBYTE)(ATNAME|ATLONG),name,line);
  addlist(&flags,NULL,arg);
  iffi(act,name,line);
 }

void ifchance(char **act,char *name,long *line)
 {
  char arg[78];
  
  readarg(act,arg,(UBYTE)(ATINTEGER|ATSHORT),name,line);
  iffi(act,name,line);
 }

void iftime(char **act,char *name,long *line)
 {
  char low[78],high[78];
  
  readarg(act,low,(UBYTE)(ATINTEGER|ATSHORT),name,line);
  readarg(act,high,(UBYTE)(ATINTEGER|ATUNIMP|ATSHORT),name,line);
  iffi(act,name,line);
 }

void ifin(char **act,char *name,long *line)
 {
  char arg[81];
  
  readarg(act,arg,(UBYTE)(ATNAME|ATSHORT),name,line);
  analyse(arg);
  iffi(act,name,line);
 }

void ifinput(char **act,char *name,long *line)
 {
  char arg[81];
  
  readarg(act,arg,(UBYTE)(ATNAME|ATLONG),name,line);
  iffi(act,name,line);
 }

void ifweight(char **act,char *name,long *line)
 {
  char arg[78];
  
  readarg(act,arg,(UBYTE)(ATINTEGER|ATSHORT),name,line);
  iffi(act,name,line);
 }

void ifitemin(char **act,char *name,long *line)
 {
  char item[78],room[78];
  
  readarg(act,item,(UBYTE)(ATNAME|ATSHORT),name,line);
  readarg(act,room,(UBYTE)(ATNAME|ATSHORT),name,line);
  analyse(item);
  if(strcmp(room,"INVACT")) analyse(room);
  iffi(act,name,line);
 }

void sys(char **act,char *name,long *line)
 {
  char code[81];
  
  readarg(act,code,(UBYTE)(ATSTRING|ATLONG),name,line);
 }

void execute(char **act,char *name,long *line)
 {
  char file[81];

  readarg(act,file,(UBYTE)(ATNAME|ATLONG),name,line);
  analyse(file);
 }

void headpath(char **act,char *name,long *line)
 {
  char file[81];
  
  readarg(act,file,(UBYTE)(ATNAME | ATUNIMP|ATLONG),name,line);

  strncpy(head,file,(size_t)81);
  headex();
 }

void maxweight(char **act,char *name,long *line)
 {
  char str[78];
  
  readarg(act,str,(UBYTE)(ATINTEGER|ATSHORT),name,line);
 }

void go(char **act,char *name,long *line)
 {
  char room[78];
  
  readarg(act,room,(UBYTE)(ATNAME|ATSHORT),name,line);
  analyse(room);
 }

void addweight(char **act,char *name,long *line)
 {
  char val[78];
  
  readarg(act,val,(UBYTE)(ATINTEGER|ATSHORT),name,line);
 }

void addtime(char **act,char *name,long *line)
 {
  char val[78];
  
  readarg(act,val,(UBYTE)(ATINTEGER|ATSHORT),name,line);
 }

void settime(char **act,char *name,long *line)
 {
  char val[78];
  
  readarg(act,val,(UBYTE)(ATINTEGER|ATSHORT),name,line);
 }

void dead(char **act,char *name,long *line)
 {
 }

void textwait(char **act,char *name,long *line)
 {
 }

void noautowait(char **act,char *name,long *line)
 {
 }

void locoff(char **act,char *name,long *line)
 {
 }

void locon(char **act,char *name,long *line)
 {
 }

void print(char **act,char *name,long *line)
 {
  char buf[81];
  
  readarg(act,buf,(UBYTE)(ATSTRING | ATUNIMP|ATMEDIUM),name,line);
 }

void cprint(char **act,char *name,long *line)
 {
  char buf[81];
  
  readarg(act,buf,(UBYTE)(ATSTRING | ATUNIMP|ATMEDIUM),name,line);
 }

void rem(char **act,char *name,long *line)
 {
  char buf[2];
  
  readarg(act,buf,(UBYTE)(ATSTRING | ATUNIMP|ATXL),name,line);
 }

void simpleface(char **act,char *name,long *line)
 {
  char file[81],fullname[161];
  
  readarg(act,file,(UBYTE)(ATNAME|ATLONG|ATUNIMP),name,line);
  if(*file) isthere(file,name,line);
 }

void showpic(char **act,char *name,long *line)
 {
  char file[81];
  char time[78];
  
  readarg(act,file,(UBYTE)(ATNAME|ATLONG),name,line);
  isthere(file,name,line);
  readarg(act,time,(UBYTE)(ATINTEGER|ATSHORT|ATUNIMP),name,line);
 }

void showpicsub(char **act,char *name,long *line)
 {
  char file[81];
  char time[78];
  
  readarg(act,file,(UBYTE)(ATNAME|ATLONG|ATUNIMP),name,line);
  isthere(file,name,line);
  readarg(act,time,(UBYTE)(ATINTEGER|ATSHORT|ATUNIMP),name,line);
 }

void isthere(char *file,char *name,long *line)
 {
  char fullname[161];
  struct FileInfoBlock *fib;
  long lock;
  long size;

  strncpy(fullname,head,(size_t)81);
  strncpy(&(fullname[strlen(fullname)]),file,(size_t)81);

  lock=Lock(fullname,-2L);
  if(!lock)
   {
    addlist(&unfiles,NULL,name);
    return;
   }
  fib=AllocMem(sizeof(struct FileInfoBlock),NULL);
  if(!fib) {UnLock(lock);clos("analyse() : no memory for FileInfoBlock !");}
  if(!Examine(lock,fib)) {UnLock(lock);FreeMem(fib,sizeof(struct FileInfoBlock));clos("analyse() : trouble with Examine !");}
  UnLock(lock);
  size=(long)(fib->fib_Size);
  FreeMem(fib,sizeof(struct FileInfoBlock));
 }

void input(char **act,char *name,long *line)
 {
 }

void setflag(char **act,char *name,long *line)
 {
  char arg[81];
  
  readarg(act,arg,(UBYTE)(ATNAME|ATLONG),name,line);
  addlist(&flags,NULL,arg);
 }

void delflag(char **act,char *name,long *line)
 {
  char arg[81];
  
  readarg(act,arg,(UBYTE)(ATNAME|ATLONG),name,line);
  addlist(&flags,NULL,arg);
 }

void handle(char **act,char *name,long *line)
 {
  char arg[78];
  
  readarg(act,arg,(UBYTE)(ATINTEGER|ATSHORT),name,line);
 }

void move(char **act,char *name,long *line)
 {
  char itm[78],from[78],where[78];
  
  readarg(act,itm,(UBYTE)(ATNAME|ATSHORT),name,line);
  readarg(act,from,(UBYTE)(ATNAME|ATSHORT),name,line);
  readarg(act,where,(UBYTE)(ATNAME|ATSHORT),name,line);
  analyse(itm);
  analyse(from);
  analyse(where);
 }

void gone(char **act,char *name,long *line)
 {
  char itm[78],where[78];
  
  readarg(act,itm,(UBYTE)(ATNAME|ATSHORT),name,line);
  readarg(act,where,(UBYTE)(ATNAME|ATSHORT),name,line);
  analyse(itm);
  if(strcmp(where,"INVACT")) analyse(where);
 }

void create(char **act,char *name,long *line)
 {
  char itm[78],where[78];
  
  readarg(act,itm,(UBYTE)(ATNAME|ATSHORT),name,line);
  readarg(act,where,(UBYTE)(ATNAME|ATSHORT),name,line);
  analyse(itm);
  analyse(where);
 }

