/****************************************************************/ 
/*                                                              */ 
/*                FILE : PARSE.C                                */ 
/*                                                              */ 
/*        Updated :  8 - 6 - 87  R. de Vries                    */ 
/*                   2- 10 - 87  F. Groen                       */ 
/*                                                              */ 
/*      CONTENTS :                                              */ 
/*      getbool(), getchr(), gethex(), getint(), hexarg(),      */ 
/*      intarg(), stablk(), stlmatch(), prstab(), atox(),       */ 
/*      getstab(), boolarg(), chrarg(), stabarg(), getdouble(), */ 
/*      doublearg(), nxtarg(), skipover(), getstr(), strarg(),  */ 
/*      strchr(), getline()                                      */ 
/*                                                              */ 
/****************************************************************/ 
 
#include <string.h> 
#include <ctype.h> 
#include <setjmp.h>
#include <stdlib.h> 
#include "window.h" 
#include "swis.h"
#include "arthur.h"

#include "cmd_list.h" 
#include "parse.h" 
 
#define EOS '\0'           /* End Of String teken      */
#define BREAK ", \n" 
#define ESC   0x27         /* Ascii waarde voor escape */
 
extern char _argbreak; 
extern jmp_buf main_loop; 
extern int prompt_flag; 
extern int  gl_wchar, gl_hchar; 
extern char help_file[]; 
extern int max_col;
 
long help_index[HEADSIZE]; 
 
/*--------------------------------------------------------------------*/
/* De functie verhoogt de pointer zolang hij ' ' (spatie) is          */

char* stpblk(char *p) 
{ 
 for(; *p == ' '; p++); 
 return (p); 
} 
 
/*--------------------------------------------------------------------*/

char* skipover(char *string, char *charset) 
{ 
   char *s, *brk; 
   s = string; 
   while (*s != EOS) 
      { 
      brk = charset; 
      while ( (*brk != EOS) && ( *s != *brk)) 
          brk++; 
      if (*brk == EOS) 
        return(s); 
      s++; 
      } 
      return(s); 
} 

/*-----------------------------------------------------*/
 
int getbool(char *prompt, int deflt) 
{ 
char *p,s[128]; 
wimp_eventstr *evnt;
 
   while (TRUE) 
   { 
      printw("%s [%c] >", prompt, deflt ? 'Y' : 'N'); 
      p = poll_loop(s,0,evnt); 
      if (_argbreak == ESC) longjmp(main_loop, 1); 
 
      if ((p == NULL) || (*p == EOS)) return (deflt); 
 
      p = skipover(s," \t"); 
      if (strchr ("yYtT", *p) != NULL) return TRUE; 
      if (strchr ("nNfF", *p) != NULL) return FALSE; 
   } 
} 

/*-----------------------------------------------------*/
 
int getchr(char *prompt, char *legals, int deflt) 
{ 
   char *p, *w; 
   char buffer[80];
   wimp_eventstr *evnt; 
 
      while ( TRUE) 
      { 
         printw("%s [%c] >", prompt, legals[deflt]); 
         p = poll_loop(buffer,0,evnt); 
         if (_argbreak == ESC) longjmp(main_loop, 1); 
 
         if (( p == NULL) || (*p == EOS)) 
            return(deflt); 
         w = strchr (legals, toupper(*p)); 
         if (w != NULL) 
            return( (int) (w-legals)); 
      } 
} 
 
/*-----------------------------------------------------*/

double getdouble(char *prompt, double mn, double mx, double deflt) 
{ 
   char *p,s[128]; 
   wimp_eventstr *evnt;
   double   f; 
   f=mn-1; 
 
   while ( (f<mn) || (f>mx) ) 
   { 
      printw("%s [%g] >", prompt, deflt); 
      p = poll_loop(s,0,evnt); 
      if (_argbreak == ESC) longjmp(main_loop, 1); 
 
      if (p == NULL)  return(deflt); 
      if (*p == EOS)   return(deflt); 
 
      f = atof (p); 
   } 
   return(f); 
} 
 
/*-----------------------------------------------------*/

int atox(char *s) 
{ 
   char *p; 
   int i; 
   p = skipover(s ," \t"); 
   sscanf( p ,"%o", &i); 
   return(i); 
} 
 

/*-----------------------------------------------------*/

int gethex(char *prompt, int mn, int mx, int deflt) 
{ 
   char *p,s[128]; 
   wimp_eventstr *evnt;
   int   i; 
   i=mn-1; 
 
   while ( (i<mn) ||(i>mx) ) 
   { 
      printw("%s [%x] >", prompt, deflt); 
      p = poll_loop(s,0,evnt); 
      if (_argbreak == ESC) longjmp(main_loop, 1); 
 
      if (p == NULL) return (deflt); 
      if (*p == EOS) return(deflt); 
 
      i = atox (p); 
   } 
   return(i); 
} 
 
int 
getint(char *prompt, int mn, int mx, int deflt) 
{ 
   char *p,s[128]; 
   wimp_eventstr *evnt;
   int   i; 
   i=mn-1; 
 
   while ( (i<mn) ||(i>mx) ) 
   { 
      printw("%s [%d] >", prompt, deflt); 
      p = poll_loop(s,0,evnt); 
      if (_argbreak == ESC) longjmp(main_loop, 1); 
 
      if (p == NULL) return (deflt); 
      if (*p == EOS) return(deflt); 
 
      i = atoi (p); 
   } 
   return(i); 
} 
 
/* 
int 
getstab(char *prompt, char **table, int deflt) 
{ 
   char *p,s[128]; 
   wimp_eventstr *evnt;
   int   i; 
   i= -1; 
 
   while ( i < 0 ) 
   { 
      printw(prompt); 
      p = poll_loop(s,0,evnt); 
      if (_argbreak == ESC) longjmp(main_loop, 1); 
 
      if (p == NULL) return (deflt); 
      if (*p == EOS) return(deflt); 
 
      i = stablk (p , table, 0); 
      if ( i >= 0 ) return(i); 
    } 
    return(0); 
} 
*/ 
 
char * getstr(char *prompt, char *deflt, char *buffer) 
{ 
  char * p; 
  wimp_eventstr *evnt;
 
      printw("%s [%s] >", prompt, deflt); 
      p = poll_loop(buffer,0,evnt); 
      if (_argbreak == ESC) longjmp(main_loop,1); 
      if (p == NULL ||*p == EOS) return(deflt); 
   return(p); 
} 
 
/*---------------------------------------------------------*/
/* Deze functie bepaald het argument uit een string        */
/*                                                         */

char* nxtarg(char **s_add, char *brk) 
{ 
   char *p, *s, *pbrk; 
   p = s = stpblk(*s_add); 
   /* skip over blanks  */ 
 
   if (brk == NULL) 
      brk = BREAK;  
   while (*s != EOS) 
   { 
   pbrk = brk; 
   while (*pbrk != EOS) 
         if ( *s == (*pbrk++)) 
         { 
            _argbreak = *s; 
            *s = EOS; 
            *s_add = ++s; 
            return(p); 
          } 
   s++; 
   } 
   *s_add = s; 
   return(p); 
} 
 
/*---------------------------------------------------------*/

int boolarg(char **s_add, char *brk, char *prompt, int deflt) 
{ 
   char *p; 
 
   if (_argbreak == ESC) longjmp(main_loop, 1); 
 
   p = nxtarg(s_add,brk); 
 
   if (!prompt_flag && (*p != '?')) 
   { 
      if (*p == EOS) return(deflt); 
 
      if (strchr("yYtT", *p) != NULL) return TRUE; 
      if (strchr("nNfF", *p) != NULL) return FALSE; 
   } 
   return getbool(prompt, deflt); 
} 
 
int 
chrarg(char **s_add, char *brk, char *prompt, char *legals, int deflt) 
{ 
   char *p, *w; 
 
   if (_argbreak == ESC) longjmp(main_loop, 1); 
 
   p = nxtarg(s_add,brk); 
 
   if (!prompt_flag && (*p != '?')) 
   { 
      if (*p == EOS) return(deflt); 
      w = strchr (legals, toupper(*p)); 
      if ( w != NULL ) 
         return ( (int) (w-legals)); 
   } 
   return getchr(prompt,legals,deflt); 
} 
 
double 
doublearg(char **s_add, char *brk, char *prompt, double mn, double mx, double deflt) 
{ 
   char *p; 
   double f; 
 
   if (_argbreak == ESC) longjmp(main_loop, 1); 
 
   p = nxtarg(s_add,brk); 
 
   if (!prompt_flag && (*p != '?')) 
   { 
      if (*p == EOS) return(deflt); 
 
      f = atof(p); 
      if ((f>=mn) && (f <= mx)) return f; 
   } 
   return getdouble(prompt,mn,mx,deflt); 
} 
 
int 
hexarg(char **s_add, char *brk, char *prompt, int mn, int mx, int deflt) 
{ 
   char *p; 
   int i; 
 
   if (_argbreak == ESC) longjmp(main_loop, 1); 
 
   p = nxtarg(s_add,brk); 
 
   if ( !prompt_flag && (*p != '?')) 
   { 
      if (*p == EOS) return(deflt); 
 
      i = atox(p); 
      if ((i>=mn) && (i<=mn)) return i; 
   } 
   return getint(prompt,mn,mx,deflt); 
} 
 
int 
intarg(char **s_add, char *brk, char *prompt, int mn, int mx, int deflt) 
{ 
   char *p; 
   int i; 
 
   if (_argbreak == ESC) longjmp(main_loop, 1); 
 
   p = nxtarg(s_add,brk); 
 
   if ( !prompt_flag && (*p != '?')) 
   { 
      if (*p == EOS) return(deflt); 
 
      i = atoi(p); 
      if ((i>=mn) && (i<=mx)) return i; 
   } 
   return getint(prompt,mn,mx,deflt); 
} 
 
/* 
int 
stabarg(char **s_add, char *brk, char *prompt, char **table, int deflt) 
{ 
   char *p; 
   int i; 
 
   if (_argbreak == ESC) longjmp(main_loop, 1); 
 
   p = nxtarg(s_add,brk); 
   if ( !prompt_flag && (*p != '?')) 
   { 
      if (*p == EOS) return(deflt); 
 
      i = stablk( p, table, 0); 
      if ( i > 0 )  return (i); 
   } 
   return getstab(prompt,table,deflt); 
} 
*/ 
 
char* strarg(char **s_add, char *brk, char *prompt, char *deflt, char *buffer) 
{ 
   char *p; 
 
   if (_argbreak == ESC) longjmp(main_loop, 1); 
 
   p = nxtarg(s_add,brk); 
 
   if ( !prompt_flag && (*p != '?')) 
      if (*p != EOS) 
        return(p); 
   return getstr(prompt,deflt,buffer); 
} 
 

/*------------------------------------------------------*/
/* Deze functie toont de lijst met de commando's uit    */
/* MainList. Ze worden neergezet met wprintf in drie    */
/* kolommen.                                            */

void prstab(void)
{ 
char *s; 
static char space[] = "                   "; 
int i, col, maxlen, maxcol, len; 
 
   maxlen =max_col; 
   maxcol = maxlen/19; 
 
   col = 0; 
   for (i=0; i<N_CMDS; i++) 
   { 
      s = Mainlist[i].Ename; 
      len = (int)strlen(s); 
      printw(s); 
      col ++; 
      if (col >= maxcol) 
      { 
         wvdu('\n'); 
         col = 0; 
      } 
      else printw(space + len); 
   } 
   printw("\n"); 
} 
 

/*-----------------------------------------------------*/


typedef struct { 
 char *search_string; 
 size_t length; 
} search_key; 
 

int keycmp(const void *key, const void *elem) 
{ 
 return strncmp(((search_key*)key)->search_string, 
  ((CIENTRY*)elem)->Ename, ((search_key*)key)->length); 
} 
 
/*------------------------------------------------------*/
/* Deze functie zoekt het commando op in de Mainlist en */
/* geeft de index ervan terug, of een error-waarde als  */
/* hij niet is gevonden (-2)                            */

int stablk(char *string, int prompt_flag) 
{ 
CIENTRY *res; 
int index, retval; 
search_key key; 
 
   key.search_string = string; 
   key.length = strlen(string); 
 
   /* binary search naar het commando */ 
   res = bsearch((const void *)&key, (const void *)Mainlist, (size_t)N_CMDS,    (size_t)sizeof(CIENTRY), keycmp); 
 
   /* Als het resultaat niet gelijk is aan NULL -> found */ 
   
   if (res != NULL) 
   { 
      /* compute index in CIENTRY table */ 
      index = (int)(res - Mainlist); 
 
      /* check if it is an exact match, if it is: return it's index */ 
      if (strcmp(string, res->Ename) == 0) return index; 
 
          /* check for ambiguity no. 1 */ 
          if (index > 0) 
              if (strncmp((res-1)->Ename, string, key.length) == 0) 
                  retval = -2; 
 
                  /* check for ambiguity no. 2 */ 
                  if (index < N_CMDS-1) 
                      if (strncmp((res+1)->Ename, string, key.length) == 0) 
                          retval = -2; 
 
                          /* everything is ok */ 
                          if (retval != -2) return index; 
    } 
    
    /* Als het resultaat gelijk is aan NULL dan: */
    else retval = -1; 

    if (prompt_flag) prstab(); 
    return retval; 
} 
 

/*-------------------------------------------------------*/

char* getline(char *s, FILE *fp)      /* get line into s, return s */ 
{ 
   int c,i; 
   i = 0; 
/*   if ((j=wkey())== 27) {
   longjmp(main_loop,1); 
} */
   while ( (c=getc(fp)) != EOF && c != '\n') 
      s[i++] = c; 
   s[i] = '\0'; 
   return(s); 
} 
 

/*********************************************************/

/* getline2 : gets a command line and returns a pointer to it */

char * getline2(char *s, FILE *fp)
{
   interact(s,fp,0,NULL,NULL,NULL);
   return(s);
}






/*-------------------------------------------------------*/

int cmdcmp(const void *p1, const void *p2) 
{ 
 return strcmp(((CIENTRY*) p1)->Ename, ((CIENTRY*) p2)->Ename); 
} 
 
/*-------------------------------------------------------*/

int init_cmds(void)
{
FILE * help_fd; 
char fil[80]; 
 qsort((void *)Mainlist,(size_t) N_CMDS, (size_t)sizeof(CIENTRY), cmdcmp); 
 
 /* load indices of helpfile */ 
 strcpy(fil,help_file);
 strcat(fil,"AIMHELP"); 
 if ((help_fd = fopen(fil, "r")) == NULL) return 0;  
 if (fread(help_index, sizeof(long),HEADSIZE,help_fd) !=  
  HEADSIZE) return -1;
 fclose(help_fd); 
 return(1); 
} 
 
/*------------------------------------------------------*/
/* Deze functie start DE routine met het gevonden       */
/* commando. De return-waarde = 0 als er geen errors    */
/* plaats hebben gevonden                               */

int cmd_exec(int index, char* args) 
{ 
 int ret;
 os_regset regs;

 regs.r[0] = 229; /* Programmers reference manual volume 2 page 522 */
 regs.r[1] = 0;   /* Programmers reference manual volume 3 page 1145 */
 regs.r[2] = 0;
 os_swi(OS_Byte,&regs); 
 ret=Mainlist[index].Estruct(args); 
 regs.r[0] = 229;
 regs.r[1] = 1;
 regs.r[2] = 0;
 os_swi(OS_Byte,&regs);
 regs.r[0] = 124;
 os_swi(OS_Byte,&regs);
 return(ret);
} 
 

/*-----------------------------------------------------*/

int cmd_help(int index)
{ 
 return Mainlist[index].Help; 
} 

/*-----------------------------------------------------*/
 
char* strsave(char *s) 
{ 
char *new = (char *)malloc(strlen(s)+1); 
 
 if (!new) return NULL; 
 strcpy(new, s); 
 return new; 
} 
