/*************************************************************
 * vt100 terminal emulator - Script file support
 *
 *	     860823 DBW - Integrated and rewrote lots of code
 *	     860815 Steve Drew: Initial version written of SCRIPT.C
 *	v2.0 860809 DBW - Major rewrite
 *	v1.1 860720 DBW	- Switches, 80 cols, colors, bug fixes
 *	v1.0 860712 DBW	- First version released
 *
 *************************************************************/

#define MODULE_SCRIPT 1

#include "vt100.h"

extern	char *fgets(),*malloc();
extern	long ftell();

struct COMMAND {
                 int (*func)();
                 char *cname;
};

struct LABEL  {
                 struct LABEL *next;
                 char *name;
                 long pos;
};



/****************  globals  needed  ******************/

char		on_string[20];       /* string to match on for on cmd    */
char 		wait_string[20];     /* string to match of for wait cmd  */
char 		golabel[20];         /* label we are looking for in goto */
char 		on_cmd[255];         /* command to execute when on matchs*/
int 		onsize;		     /* size of on_string                */
int 		waitsize;            /* size of wait_string              */
int 		onpos;               /* position in on string for search */
int 		waitpos;             /* pos in wait_string for search    */
int 		on_match;            /* flag set while doing on_cmd      */
FILE 		*sf;                 /* file pointer for script file     */
struct LABEL 	*lbase = NULL;       /* will point to first label        */
struct LABEL 	*labels;             /* current label pointer            */

int  cmd_send(), cmd_wait(), cmd_on(), cmd_goto(), cmd_delay(), cmd_done(),
     cmd_ks(), cmd_kg(), cmd_kr(), cmd_xs(), cmd_xr(), cmd_cap(), cmd_as(),
     cmd_null(), cmd_kb();

char *next_wrd(), *tostring();


/********************** command table **********************************/

static struct COMMAND commands[]= {
                 cmd_send,   "SEND",         /* send string to host      */
                 cmd_wait,   "WAIT",         /* wait for a string from host */
                 cmd_on,     "ON", 	     /* on a 'string' do a cmd   */
                 cmd_goto,   "GOTO",         /* goto label               */
                 cmd_delay,  "DELAY",        /* delay amount of seconds  */
                 cmd_done,   "EXIT",         /* exit script file         */
                 cmd_ks,     "KS",           /* kermit send file         */
                 cmd_kr,     "KR",           /* kermit receive file      */
                 cmd_kg,     "KG",           /* kermit get file          */
		 cmd_kb,     "KB",	     /* kermit bye (for server)	 */
                 cmd_xs,     "XS",           /* xmodem send file         */
                 cmd_xr,     "XR",           /* xmodem receive file      */
                 cmd_cap,    "CAPTURE",      /* ascii capture on/off     */
                 cmd_as,     "ASCII_SEND",   /* ascii send               */
		 cmd_null,   NULL
};

/********************************************************************/
/* checks char to see if match with on string or wait_string        */
/* if on string match oncmd gets executed imediately,               */
/* if wait_string match script_wait is set.                         */
/********************************************************************/

chk_script(c)
char c;
{
    if (on_string[0] != '\0') {
        if (on_string[onpos] == c) {
            onpos++;
            if (onpos == onsize) {
                on_match = TRUE;
                do_script_cmd(ONCOMMAND); 
                on_match = FALSE;
                return(0);
            }
        }
        else onpos = 0;
    }

    if (wait_string[0] != '\0') {
       if (wait_string[waitpos] != c) {
            waitpos = 0;
            return(0);
        }
        waitpos++;
        if (waitpos != waitsize) return(0);
        wait_string[0] = '\0';
        script_wait = FALSE;
    }
}

script_start(file)
char *file;
{
    if ((sf = fopen(file, "r")) == NULL) {
        emits("Can't open script file\n");
        return(0);
    }
    script_on = TRUE;
    script_wait = FALSE;
    wait_string[0] = '\0';
    on_string[0] = '\0';
    on_match = FALSE;
    lbase = NULL;
}

/* return pointer to next word. set l to size of the word */

char *next_wrd(s,l)
char *s;
int *l;
{
    char *p;
    while(*s && (*s == ' ' || *s == 9)) s++;
    p = s;
    while(*s && (*s != ' ' && *s != 9)) s++;
    *l = s-p;
    return(p);
}

exe_cmd(p,l)
char *p;
int l;
{
    int i;
    
    for (i=0; commands[i].func != cmd_null; ++i) 
        if (strncmp(p, commands[i].cname, l) == 0) {
            (*commands[i].func)(next_wrd(p+l, &l));
            return(TRUE);
	}
        emits ("\nScript - unknown command: ");
        emits (p);
        emits ("\n"); 
}

struct LABEL *find_label(lname)
char *lname;
{
    struct LABEL *label;
  
    label = lbase;
    while(label != NULL) {
       if (strcmp(label->name, lname) == 0) return (label);
       label = label->next;
    }
    return(NULL);
}


do_script_cmd(stat)
int stat;
{
    int len,l;
    char line[256];
    char *p;

    if (stat == ONCOMMAND) {    /* if ON command is matched and we were     */
        strcpy(line,on_cmd);    /* doing a DELAY then abort the delay timer,*/
        p = next_wrd(line,&l);  /* except if on_cmd was just a SEND.        */
	if (*p != 'S' && script_wait == WAIT_TIMER)  {
            AbortIO((char *) &Script_Timer);
            Wait (1L << Script_Timer_Port->mp_SigBit);
            script_wait = FALSE; /* script will proceed after on command    */
        }
	exe_cmd(p,l);
        return(0);
    }

    script_wait = FALSE;
    while(fgets(line,256,sf) != NULL) {
       len = strlen(line);
       line[--len] = '\0';
       p = next_wrd(&line[0], &l);
       if (*(p + l - 1) == ':') {       	/* its a label */
           *(p + l - 1) = '\0';
           if (find_label(p) == NULL) {   	/* it's a new label */
               if (lbase == NULL)  {  		/* it's the first label */
                   labels = lbase = (struct LABEL *) malloc (sizeof (struct LABEL));
               }
               else {
                   labels->next = 
                           (struct LABEL *) malloc (sizeof (struct LABEL));
                   labels = labels->next;
               }
               labels->pos  = ftell(sf);
               labels->name = malloc(l);
               labels->next = NULL;
               strcpy(labels->name, p);
               if (stat == GOTOLABEL && strcmp(p, golabel) == 0) 
                      stat = NEXTCOMMAND;
           }
           if (l < len) p = next_wrd(p+l+1, &l);
           else return(0);
       } 	/* end of it's a label */
       if (stat == GOTOLABEL || *p == '#') continue;
       if (*p) exe_cmd(p,l);
       return(0);
    } 		/* end of while */
    if (stat == GOTOLABEL) {
          emits("\nScript - label not found: ");
          emits(golabel);
          emits("\n");
    }         
    exit_script();
}

exit_script()
{
    if (script_wait == WAIT_TIMER)      /* timer not done yet */
       AbortIO((char *) &Script_Timer); /* so abort it */
    emits("\nScript - terminated\n");    
    script_on = FALSE;
    script_wait = TRUE;
    fclose(sf);
}

/* remove quotes terminate string & return pointer to start */

char *tostring(ptr)
char *ptr;
{
    char *s;

    s = ptr;
    if (*ptr == '"') {
         while(*ptr++  && *ptr !='"');
         if (*ptr == '"') {
             *ptr = '\0';  
             ptr = s+1;
             while(*s++)  if (*s == '|') *s = '\r';
             return(ptr);
         }
    }
    if (*s == '^') {
        *s = *(s+1)-64;
        *(s+1) = '\0';
        return(s);
        }
    *(s+1) = '\0';
    return(s);
}   
        
cmd_goto(lname)
char *lname;
{
    struct LABEL *label;
   	                    /* if on_cmd was a goto kill wait state */
    if (on_match) { wait_string[0] = '\0'; script_wait = FALSE; }
    if ((label = find_label(lname)) == NULL) {  /* is it forward */
        strcpy(golabel,lname);
        do_script_cmd(GOTOLABEL);
    }
    else {
        fseek(sf,(long)(label->pos),0);
    }
}

cmd_send(str)
char *str;
{
  sendstring(tostring(str));
}

 
cmd_wait(str)
char *str;
{
        str = tostring(str);
        *(str+20) = '\0';         /* 20 characters max */
        strcpy(wait_string, str);
        waitsize = strlen(str);
        script_wait = WAIT_STRING;
}

cmd_on(str)
char *str;
{
   char *p;

   p = tostring(str);
   strcpy(on_string, p);
   onsize = strlen(p);
   *(p+onsize+2+20) = '\0';        /* 20 characters max */
   strcpy(on_cmd,p+onsize+2);
}

cmd_delay(seconds)
char *seconds;
{
    script_wait = WAIT_TIMER;
    Script_Timer.tr_time.tv_secs = atoi(seconds);
    Script_Timer.tr_time.tv_micro = 0;
    SendIO((char *) &Script_Timer.tr_node);
}

cmd_done()
{
    exit_script();
}

cmd_ks(file)
char *file;
{
   multi_xfer(file, doksend, 1);
}

cmd_kr(file)
char *file;
{
   multi_xfer(file, dokreceive, 0);
}

cmd_kg(file)
char *file;
{
   server = TRUE;
   multi_xfer(file, dokreceive, 0);
}

cmd_kb()
{
   saybye();
}

cmd_xs(file)
char *file;
{
   multi_xfer(file, XMODEM_Send_File, 1);
}

cmd_xr(file)
char *file;
{
   multi_xfer(file, XMODEM_Read_File, 1);
}

cmd_cap(file)
char *file;
{
do_capture(file);
}

cmd_as(file)
char *file;
{
do_send(file);
}

cmd_null(file)
char *file;
{
}

