/*===========================================================================
  Copyright (C) 1995-2011 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.LANGUAGE      C
.IDENTIFICATION    MIDAS Monitor module PREPX
.AUTHOR  K. Banse                  	ESO - Garching
.KEYWORDS  MIDAS monitor
.ENVIRONMENT  VMS and UNIX
.PURPOSE
synchronize fore- and background processes; 
get the MIDAS command string + take action accordingly
.ALGORITHM
loop on command input (from front end or procedure file),
system commands are executed directly,
all others are executed as command procedures

.RETURNS
  = 0 			normal return
  = -1			if we're finished (command BYE)

  = 1			CLEAR/BUFFER		 )
  = 2			READ/COMMANDS		 )
  = 3			SET/BUFFER		 ) to be done in front end !
  = 4			WRITE/COMMANDS		 )
  = 5			PLAYBACK/LOG, PLAY/FILE  )
  = 7			PLAYBACK terminated via Cntrl C
  = 8			CLEAR/BACKGROUND
  = 99			tell frontend a batch run is finished

.VERSION  [1.00] 930124: pulled out from main prepa

 110802		last modif
------------------------------------------------------------------------*/
 
 
#include <fileexts.h>
#include <osyparms.h>
#include <monitdef.h>
#include <xconndef.h>
#include <proto_xcon.h>
#include <midback.h>
#include <commdef.h>
#include <stackdef.h>
 
#include <fsydef.h>

#include <stdlib.h>
#include <string.h>

#include <signal.h>
#ifndef SIGUSR1
#define SIGUSR1 30
#endif
#ifndef SIGUSR2
#define SIGUSR2 31
#endif


extern int  is_a_tty;           /* Is this a terminal, (yes=1) set in prepa.c */

int  IDI_SINI(), IISSIN_C(), DYNA_COM(), DSC_write(), CATALO();

void IDI_SCLS(), pipe_mess();


/*

*/

void clear_batch()

{
CLEAR_LOCAL(1);                              /* clear all local keys  */
MONIT.LEVEL = 0;
MONIT.TOPLEVL = 0;
KIWORDS[OFF_MODE+6] = 0;             /* clear overall program level */
KIWORDS[OFF_LOG+3] = 0;              /* make sure to enable display */
fixout(0,0);
}

/*

*/

int prepx(kswitch,cxpntr,ixpntr)
int  kswitch;		/* IN: = -1; initialize 
			       = -2; as -1 but for UNIX command line input...
			       = -3; begin by doing "@ login"
			       = -4; playback finished 
			       = -5; there was a timeout
			       = 0;  process input normally (LINE.STR, TOKEN)
			       = 1;  return from front end command */
char *cxpntr;		/* OUT = any char. info on output  */
int  *ixpntr;		/* IN/OUT = any int info on output */
 
{
 
extern void  intmonit();
void DIR_Expand();

 
static int   sysdskl, appadskl, appsdskl, appcdskl, appgdskl, dflowdskl;
static int   pipedskl, palias, salias, calias;
static int   submit, returnval=0, idiserver_flag;

int   unit, nullo;
int   abbrev, proc_flag;
int   iav, iwa, iwb[3];
int   mm, m, n, nb, defset, nbra;
int   kk, jj, stat, fid;
 
register int nr;
register char cr;
		
float	rwa;
	
double	dwa;

char    firstchar;
char	*progpntr, *cpntr, *cpntra, *cpntrb;
char    prog[100], string[35], bigstr[200];
char    save[82], command[6], qualif[4], defqual[4];
char    cbuf[20];

static char     sysdisk[120], appadisk[120], appsdisk[120], appcdisk[120];
static char     appgdisk[120], dflowdisk[132], pipedisk[120], midwork[80];
static char     bcomnd[3], *tok0str, *tok0str1;




if (kswitch == 0)          /* that's the normal input */
   {
   if (PARSE(1,0,0) != 0)		/* full parsing of interactive input */
      return (0);

   LOG_line(LINE.STR,LINE.LEN);                   /* log input */
   MONIT.CTRLC = 0;
   goto join_forces;
   }

else if (kswitch < 0)
   {
   kswitch = -kswitch;
   switch(kswitch)
      {
     case 1:				/*  first time activities here...  */
     case 2:	
      INPREPA();                                   /* init what we can */
      (void) OSY_TRNLOG("MID_PROC",sysdisk,120,&sysdskl);
      (void) OSY_TRNLOG("APP_PROC",appadisk,120,&appadskl);
      (void) OSY_TRNLOG("STD_PROC",appsdisk,120,&appsdskl);
      (void) OSY_TRNLOG("CON_PROC",appcdisk,120,&appcdskl);
      (void) OSY_TRNLOG("GUI_PROC",appgdisk,120,&appgdskl);
      (void) OSY_TRNLOG("PIPE_HOME",pipedisk,120,&pipedskl);

#if vms
      dflowdisk[0] = '\0';
      dflowdskl = 0;
#else

      /* just one '/' in the end... */

      if (sysdisk[sysdskl-1] != FSY_DIREND)
         {
         sysdisk[sysdskl++] = FSY_DIREND;
         sysdisk[sysdskl] = '\0';
         }
      (void) strcpy(dflowdisk,sysdisk);
      (void) strcpy(&dflowdisk[sysdskl],"pipeline");
      dflowdskl = sysdskl + 8;
      dflowdisk[dflowdskl++] = FSY_DIREND;
      dflowdisk[dflowdskl] = '\0';              /*  ->  $MID_PROC/pipeline/ */

      if (appadisk[appadskl-1] != FSY_DIREND)
         {
         appadisk[appadskl++] = FSY_DIREND;
         appadisk[appadskl] = '\0';
         }
      if (appsdisk[appsdskl-1] != FSY_DIREND)
         {
         appsdisk[appsdskl++] = FSY_DIREND;
         appsdisk[appsdskl] = '\0';
         }
      if (appcdisk[appcdskl-1] != FSY_DIREND)
         {
         appcdisk[appcdskl++] = FSY_DIREND;
         appcdisk[appcdskl] = '\0';
         }
      if (appgdisk[appgdskl-1] != FSY_DIREND)
         {
         appgdisk[appgdskl++] = FSY_DIREND;
         appgdisk[appgdskl] = '\0';
         }
      if (pipedisk[pipedskl-1] != FSY_DIREND)
         {
         pipedisk[pipedskl++] = FSY_DIREND;
         pipedisk[pipedskl] = '\0';
         }
      (void) strcpy(PIPE.HOME,pipedisk);
      PIPE.HOME_LEN = pipedskl;

#endif

      (void) OSY_TRNLOG("MID_WORK",midwork,80,&jj);

      palias = salias = calias = 0;	/* no alias for @p, @s, @c */

      if (INITCOM() != 0) return(-1);	/* get the commands/qualifiers */

      bcomnd[0] = 'N';			/* initialize command for MYBATCH  */
      bcomnd[1] = 'X';   bcomnd[2] = '\0';

      idiserver_flag = 0;
      submit = 0;
      tok0str = TOKEN[0].STR;			/* point to of TOKEN[0].STR[0] */
      tok0str1 = tok0str + 1;			/* => TOKEN[0].STR[1] */

      if (kswitch == 2)
         {
         KIWORDS[OFF_MODE+2] = 1;               /* this is a job! */
         KIWORDS[OFF_MODE+4] = 1;               /* no MIDAS header */
         KIWORDS[OFF_LOG] = 0;			/* no logging */
         
         MONIT.CTRLC = 0;
         clear_batch();

         if (*cxpntr == 'Y')
            {
            (void) printf("Execute Midas command: %s\n",LINE.STR);
            }

         if (*(cxpntr+1) == 'Y')		/* update also FITS files */
            KIWORDS[OFF_AUX+13] = 1;
         else
            KIWORDS[OFF_AUX+13] = 0;
         if (*(cxpntr+2) == 'Y')		/* resframes will be FITS */
            {
            (void) SCKWRC("MID$TYPES",1,"fits    tfits   ",1,16,&unit);
            KIWORDS[OFF_AUX+12] = 1;
            }
         else
            KIWORDS[OFF_AUX+12] = 0;

         (void) PARSE(1,0,0);		/* parse input string  */

         kswitch = 0;
         goto join_forces;		/* continue as command input */
         }
#if vms
#else
      (void) strcpy(KAUX.STR,"MIDASJOB");	/* see, if "submitted" */
      (void) OSY_TRNLOG("MIDASJOB",KAUX.STR,250,&mm);
      if (strcmp(KAUX.STR,"MIDASJOB") != 0) 
         {
         KIWORDS[OFF_MODE+2] = 1;		/* this is a job! */
         KIWORDS[OFF_MODE+4] = 1;		/* no MIDAS header */
         KIWORDS[OFF_AUX+7] = 0;		/* clear AUX_MODE(8) */
         submit = 1;
         }
      else if (!is_a_tty )			/* see, if via pipe */
         {
         KIWORDS[OFF_MODE+2] = 1;               /* this is a job! */
         KIWORDS[OFF_MODE+4] = 1;               /* no MIDAS header */
         KIWORDS[OFF_AUX+7] = 0;                /* clear AUX_MODE(8) */
         }

#endif

      (void) strcpy(TOKEN[0].STR,"MIDASHD");	/* see, if "-noh" was given */
      (void) OSY_TRNLOG("MIDASHD",TOKEN[0].STR,80,&mm);	
      if ((TOKEN[0].STR[0] == 'n') && (TOKEN[0].STR[1] == 'o'))
         KIWORDS[OFF_MODE+4] = 1;		/* no MIDAS header */

      ixpntr[0] = 0;
      ixpntr[1] = KIWORDS[OFF_MODE+2];
      ixpntr[2] = KIWORDS[OFF_MODE+4];
      
      KIWORDS[OFF_AUX+2] = oshpid();		/* AUX_MODE(3) = process id */


      /* prepare return buffer for front end */

      ixpntr[3] =  KIWORDS[OFF_AUX+7];             /* get AUX_MODE(8) + save */
      (void) strncpy(cxpntr,&KCWORDS[OFF_SESS+14],13);  /* (P) + MIDAS vers. */
      cxpntr += 13;
      (void) strncpy(cxpntr,&KCWORDS[OFF_SYS],20);
      return(0);

     case 4:
      return (0);

     case 3:				/* do the initial @ login */
      if (submit > 0)
         {              /* test first for very special job "@ compile.all" */
         n = strncmp(KAUX.STR,"@ compile.all",13);
         if (n == 0)
            {				/* do a brute force job... */
            TOKEN[0].LEN = CGN_COPY(TOKEN[0].STR,"@");
            TOKEN[1].LEN = CGN_COPY(TOKEN[1].STR,"compile.all");
            MONIT.COUNT = 2;
            goto join_forces;		/* now, looks like interactive input */
            }

         nr = CGN_JNDEXC(KAUX.STR,';') + 1;
         while (nr > 0)			/* test if cmd_string is "xyz; bye" */
            {
            if ((KAUX.STR[nr] == ' ') || (KAUX.STR[nr] == '\t'))
               nr++;			/* skip white space */
            else
               {
               register char c1, c2, c3;

               c1 = KAUX.STR[nr++];
               c2 = KAUX.STR[nr++];
               c3 = KAUX.STR[nr];
               if ( ((c1 == 'b') || (c1 == 'B')) &&
                    ((c2 == 'y') || (c2 == 'Y')) && 
                    ((c3 == 'e') || (c3 == 'E')) )
                  returnval = -1;	/* ensure that "BYE" leads to exit! */
               break;
               }
            }

         ERRORS.SYS = build_prg(3,0);	/* build procedure midjobXY.prg */
         if (ERRORS.SYS == 0)
            {
            LINE.LEN = CGN_COPY(LINE.STR,"@ login midjob  ");
            LINE.STR[14] = FRONT.DAZUNIT[0];
            LINE.STR[15] = FRONT.DAZUNIT[1];
            TOKEN[0].STR[0] = '@';		/* instead of PARSE ... */
            TOKEN[0].STR[1] = '\0';
            TOKEN[0].LEN = 1;
            TOKEN[1].LEN = CGN_COPY(TOKEN[1].STR,"login");
            TOKEN[2].LEN = CGN_COPY(TOKEN[2].STR,&LINE.STR[8]);
            MONIT.COUNT = 3;
            }
         else
            goto error_1;
         }
      else
         {
         LINE.LEN = CGN_COPY(LINE.STR,"@ login");
         TOKEN[0].LEN = CGN_COPY(TOKEN[0].STR,"@");
         TOKEN[1].LEN = CGN_COPY(TOKEN[1].STR,&LINE.STR[2]);
         MONIT.COUNT = 2;
         }

      goto join_forces;		/* do not log */
      }
   }


/* as default (kswitch = 1) we returned from a front end command */

main_loop:
if (MONIT.CTRLC == 1)			/* if Cntrl/C clean up everything  */
   {
   if (MONIT.LEVEL > 0) clear_batch();
   MONIT.CTRLC = 0;

   if (FRONT.PLAYBACK > 0)			/* if PLAYBACK mode, stop it */
      {
      FRONT.PLAYBACK = 0;
      return (7);
      }
   else
      return (0);			/* get new input from user */
   }

if (KIWORDS[OFF_OUTFLG] == MONIT.LEVEL)
   fixout(0,MONIT.LEVEL);			/* close ASCII out-file */

if (MONIT.LEVEL > 0) 		/* get new input from procedure */
   MYBATCH(bcomnd,TOKEN[0].STR);

if (MONIT.LEVEL < 1)
   return(returnval);			/* get new input from user */

join_forces:
abbrev = 0;
cpntr = 0;
firstchar = *tok0str;			/* get 1. char. of 1. token */

cpntrb = tok0str + TOKEN[0].LEN - 1;	/* => last char of TOKEN[0].STR[0] */
if (unlikely(*cpntrb == '?'))		/* handle comm/qualif ?? */
   {
   *cpntrb = '\0';         /* take away the '?'  */
   CGN_UPCOPY(save,TOKEN[0].STR,10);
   (void) SHOWCOM(-1,"A ",save);
   goto main_loop;
   }


/*  if we are in the host environment, just fall through to host opsys  */
 
if (FRONT.ENV == '$')
   {
   if (firstchar == '$')
      {
      progpntr = LINE.STR;
      while (*progpntr == ' ') progpntr ++;	/* skip leading blanks  */
      if (*(progpntr+1) == '$') 
         *(progpntr+1) = ' ';			/* remove the `$' */
      }
   else
      {
      CGN_UPSTR(TOKEN[0].STR);
      if (strncmp(TOKEN[0].STR,"SET/MID",7) != 0)
         {
         prog[0] = '$';
         LINE.STR[98] = '\0';		/* make sure, we don't override prog */
         (void) strcpy(&prog[1],LINE.STR);
         progpntr = prog;
         }
      else
         {
         FRONT.ENV = '>';		/* return to Midas environment */
         goto main_loop;
         }
      }
   goto final_act;
   }
	
 
/*  look for the special and very important commands  @, $, -...  */
 
if (firstchar == '@')
   {
   MONIT.COMPILED = 0;			/* always reset */

   cr = *tok0str1;			/* cr = TOKEN[0].STR[1] */
   if (cr == '\0')
      abbrev = 1;
   else if (cr == '%') 
      {
      abbrev = -1;
      MONIT.COMPILED = 1;
      }
   else if (cr == '@') 
      abbrev = 0;
   else
      {
      if (unlikely((cr >= 'A') && (cr <= 'Z')))
         {
         if (cr == 'A') 
            abbrev = 2;
         else if ((cr == 'S') && (salias == 0))
            abbrev = 3;
         else if ((cr == 'C') && (calias == 0))
            abbrev = 4;
         else if (cr == 'G')
            abbrev = 5;
         else if (cr == 'D')
            abbrev = 6;
         else if ((cr == 'P') && (palias == 0))
               abbrev = 7;
         else
            goto immedia;			/* none of the above */
         }
      else
         {
         if (cr == 'a') 
            abbrev = 2;
         else if ((cr == 's') && (salias == 0))
            abbrev = 3;
         else if ((cr == 'c') && (calias == 0))
            abbrev = 4;
         else if (cr == 'g')
            abbrev = 5;
         else if (cr == 'd')
            abbrev = 6;
         else if ((cr == 'p') && (palias == 0))
               abbrev = 7;
         else
            goto immedia;			/* none of the above */
         }
      }
   goto sect_41000;
   }

else if (firstchar == '$')
   {
   progpntr = LINE.STR;
   while (*progpntr == ' ') progpntr ++;	/* skip leading blanks  */
   if (*(progpntr+1) == '$') 
      *(progpntr+1) = ' ';			/* remove the `$' */
   goto final_act;
   }

else if (unlikely(firstchar == '-'))
   {
   jj = OSYCOMP(bigstr);
   if (jj == 0)
      {
      progpntr = bigstr;
      firstchar = '$';			/* indicate, that's a host op  */
      goto final_act;
      }
   else if (jj == 1)		/* a host command we do not support here */
      goto main_loop;
   }
 

/*  look for c,command/qualif => we send command to a `background' MIDAS */

if (*tok0str1 == ',')
   {
   cr = CGN_LOWER(TOKEN[0].STR[0]);
   for (nr=0; nr<MAX_BACK; nr++)
      {
      if ( (BKMIDAS[nr].UNIT[0] != ' ') &&
           (BKMIDAS[nr].COMC == cr) )
         {
         save[0] = BKMIDAS[nr].UNIT[0];
         save[1] = BKMIDAS[nr].UNIT[1];
         save[2] = '\0';

         TOKEN[0].STR[0] = FRONT.DAZUNIT[0];        /* `c,' => sender unit */
         TOKEN[0].STR[1] = FRONT.DAZUNIT[1];
         LINE.LEN = TOKBLD(0,LINE.STR,MAX_LINE,1,MONIT.COUNT);

         trigback(nr);			/* activate `bkstat[nr]' */
         stat = outmail(1,LINE.STR,nr,iwb);	/* send comnd to other Midas */

         if (stat == 1)            /* BUSY */
            {
            (void) sprintf(KAUX.STR,
                    "MIDAS unit %s currently busy - retry later...",save);
            (void) SCTSYS(4,KAUX.STR);
            }
         else if (stat == 2)                 /* Timeout */
            {
            (void) sprintf(KAUX.STR,
                   "Timeout: MIDAS unit %s did not respond yet...",save);
            (void) SCTSYS(4,KAUX.STR);
            }
         else if (stat == 3)            /* command before hit BUSY */
            {
            (void) sprintf(KAUX.STR,
                    "last command ignored, MIDAS unit %s was busy...",save);
            (void) SCTSYS(4,KAUX.STR);
            }
         else if (stat > 3)
            {
            (void) sprintf(KAUX.STR,
            "Could not send command to Midas unit %s, ret-status = %d",
             save,stat);
            (void) SCTSYS(4,KAUX.STR);
            if (stat == 4)		/* problems with socket connection */
               ERRORS.SYS = 58;
            else			/* problems with file connection */
               ERRORS.SYS = stat;
            ERRORS.INDEX = -2;		/* avoid printing of command line */
            goto error_1;
            }
         else if (iwb[0] != 0)               /* error in Background Midas */
            {
            (void) sprintf(KAUX.STR,"Midas unit %s sent back status = %d",
                    save,iwb[0]);
            (void) SCTSYS(4,KAUX.STR);
            if (iwb[1] == 10)             /* Midas error */
               {
               ERRORS.SYS = iwb[0];
               goto error_1;
               }
            }
         goto main_loop;
         }
      }
   }


/*  catch immediate commands ( ...  =  ... )  */

immedia:
ERRORS.INDEX = 2;
if ( (TOKEN[1].STR[0] == '=') && (TOKEN[1].LEN == 1) )
   {
   kk = IMMEDIATE();
   if (kk == 0)				/* kk = 0 is: key = ...  */
      {
      ERRORS.SYS = KEYCOMP(0,2,string);	/* TOKEN[2].STR holds first operand */
      if (ERRORS.SYS != 0)
         goto error_1;
      else
         goto main_loop;
      }
   else if (kk < 0)			/* soemthing went wrong */
      goto error_1;
   else
      goto main_loop;
   }

 
/*  extract command + qualifier and  search through command table  */
 
ERRORS.INDEX = 0;	    	/* init for TOKEN[0].STR for all the rest */
EXTRACOM(TOKEN[0].STR,command,qualif);
ERRORS.SYS = FINDCOM(command,qualif,defqual,&defset,&nbra,&cpntra,&kk);
if (ERRORS.SYS > 1) 
   {
   if ((FRONT.ENV == ':') && (MONIT.LEVEL < 1))		/* interactive only */
      {
      prog[0] = '$';
      LINE.STR[98] = '\0';           /* make sure, we don't override prog */
      (void) strcpy(&prog[1],LINE.STR);

      if (KIWORDS[OFF_OUTFLG] != 99) 	/* add >file again to end of line... */
         {
         (void) strcat(prog," > ");
         (void) strcat(prog,&KCWORDS[OFF_OUTNAM]);
         KIWORDS[OFF_OUTFLG] = 99;
         }
      progpntr = prog;
      goto final_act;
      }
   goto error_1;	
   }
 
if (unlikely(defset > 0))		/*  look for user defined defaults  */
   {
   (void) strncpy(save,command,6);
   (void) strncpy(&save[6],qualif,4);
   stat = PARDEFS('F',save);
   }
 
 
/*  see, if short help wanted, i.e. command/qualif ??  */
 
if (unlikely( (TOKEN[1].STR[0] == '?') &&
              (TOKEN[1].STR[1] == '?') &&
              (TOKEN[1].STR[2] == '\0') ))
   {
   mm = CGN_INDEXC(command,' ');
   if (mm < 0) mm = 6;				/* truncate command...  */
   memset((void *)save,32,(size_t)40);
   save[0] = '?';			/* build string  `?? command/qualif' */
   save[1] = '?';
   (void) strncpy(&save[3],command,mm);
   mm += 3;
   save[mm++] = '/';
   (void) strncpy(&save[mm],qualif,4);
   save[mm+4] = '\0';
   goto sect_48080;				/* continue like HELP  */
   }
	
/*  see, if primitive command or added  */
 
if (nbra < 0)
   nbra = -nbra;			/* get sequential command no.  */
	
else
   {
 
   /* we have to translate the command + parse again,
                   so save complete line + command + qualif */
 
   if (*(cpntra+kk-1) == ' ')		/*  but only if it's not a D_command */
      {
      (void) strncpy(&KCWORDS[OFF_LINE],LINE.STR,256);	/* MID$LINE is 256 */
      (void) strncpy(&KCWORDS[OFF_CMND],command,6);
      (void) strncpy(&KCWORDS[OFF_CMND+10],qualif,4);
      }
	
   (void) strncpy(LINE.STR,cpntra,kk);		/* fill command LINE.STR  */
   LINE.STR[kk] = '\0';
 
   if (MONIT.COUNT > 1)				/* more parameters?  */
      {					/* Yes, append parameters to command */
      LINE.LEN = TOKBLD(1,&LINE.STR[kk],MAX_LINE-kk,1,MONIT.COUNT);
      if (LINE.LEN < 0)
         {
         ERRORS.SYS = 27;
         goto error_1;
         }
      else
         LINE.LEN += kk;
      }
   else
      LINE.LEN = kk;
	
   /*  now parse command string again - no need to look for {xyz} 
       before it was: 			ERRORS.SYS = PARSE(3,0,0); */

   MONIT.COUNT = Parse2(3,0);
   if (MONIT.COUNT < 0)
      {
      ERRORS.INDEX = 0;
      ERRORS.SYS = MONIT.COUNT;
      goto error_1;
      }
   goto join_forces;
   }

/*

*/

/*                                                    */
/*   here we end up with a system (basic) command     */
/*   and branch to relevant code		      */
/*                                                    */
	
if (nbra > 57) goto branch_58;
if (nbra > 28) goto branch_29;

switch(nbra)
   {
   case 1:
 
   /*  READ/KEY keyword [no_header_flag] [since] [M_unit] */
   /*  ---------------------------------------------------*/

   iwa = MONIT.COUNT - 1;
   if (TOKEN[iwa].STR[0] == '<')
      {
      proc_flag = 1;
      goto do_list;
      }

   if (likely(TOKEN[4].STR[0] == '?'))
      DO_KEYS('R',cbuf);                        /* simple read... */

   else
      {
      (void) MID_MOVKEY("O",bigstr);             /* close own keyfile */
      m = CGN_COPY(bigstr,FRONT.STARTUP);
      (void) strcpy(&bigstr[m],"FORGR  .KEY");
      bigstr[m+5] = CGN_UPPER(TOKEN[4].STR[0]);
      bigstr[m+6] = CGN_UPPER(TOKEN[4].STR[1]);

      stat = MID_MOVKEY("IM",bigstr);          /* get keyfile from M_unit in */

      bigstr[m+5] = FRONT.DAZUNIT[0];          /* reset it to own unit */
      bigstr[m+6] = FRONT.DAZUNIT[1];
      if ( stat != ERR_NORMAL)
         {
         stat = MID_MOVKEY("IM",bigstr);
         ERRORS.SYS = 23;
         ERRORS.INDEX = -1;
         goto error_1;
         }

      DO_KEYS('R',cbuf);			/*  now read the keyword */
      (void) MID_MOVKEY("O",bigstr);		/* close background keyfile */
      (void) MID_MOVKEY("IM",bigstr);
      }

   goto main_loop;

 
   case 2:
 
   /*  WRITE/KEY    keyword/type/1.elem/noval values   */
   /*  ------------------------------------------------*/

write_key:
   iwa = MONIT.COUNT - 1;
   if ((TOKEN[iwa].STR[0] == '<')
      &&
        (TOKEN[iwa].STR[1] != ',')
      &&
        (TOKEN[iwa].LEN > 1))
      {
      TOKEN[0].LEN = CGN_COPY(TOKEN[0].STR,"WRITE/KEYW");   /* clean command */
      proc_flag = 1;
      goto do_list;
      }

   DO_KEYS('W',cbuf);
   goto main_loop;


   case 3:

   /*   BYE or EXIT  [procedure]         */
   /*  ----------------------------------*/

   if (FRONT.PLAYBACK != 0)
      {
      (void) printf("command BYE ignored in playback mode...\n");
      goto main_loop;                   /* ignore BYE in playback mode  */
      }

   if (FRONT.INTERM != 0)                       /* in background mode */
      {                                         /* no BYE from front end !  */  
      ERRORS.SYS = 35;
      ERRORS.INDEX = 0;
      goto error_1;
      }

   if ((MONIT.COUNT >= 2) || (idiserver_flag == 0))
      {
      (void) strcpy(LINE.STR,"@ bye ");
      if (MONIT.COUNT > 1)
         {
         (void) strcpy(&LINE.STR[6],TOKEN[1].STR);  /* execute BYE procedure */ 
         LINE.LEN = 6 + TOKEN[1].LEN;
         }
      else
         LINE.LEN = 6;

      idiserver_flag = 1;
      (void) PARSE(1,0,0);         /* parse input string  */
      goto join_forces;
      }

   KIWORDS[OFF_MODE+2] = 0;		/* always reset batch mode flag */

   stat = INTERNAL("CL"," ",&mm);		/* close internal code file */ 
   (void) MID_LOG('O',LINE.STR,2);		/* close logfile */ 
   (void) MID_MOVKEY("O"," ");              /* write keywords out to keyfile */ 

   /* delete the files Midas_osxab and MIDASab.PID */

   (void) sprintf(prog,"%sMIDAS%c%c.PID",midwork,
                  FRONT.DAZUNIT[0],FRONT.DAZUNIT[1]);
   (void) osfdelete(prog);
   (void) sprintf(prog,"%sMidas_osx%c%c",midwork,
                  FRONT.DAZUNIT[0],FRONT.DAZUNIT[1]);
   (void) osfdelete(prog);

#if vms
   STOP_IT();                   /* stop foreground process  */
#endif
   return (-1);                 /* tell front end, that we finished */


   case 4:

   /*  CHANGE/DIREC   directory        */
   /*  --------------------------------*/

   if (TOKEN[1].STR[0] == '?')

#if vms
      (void) strcpy(TOKEN[1].STR,"SYS$LOGIN");
#else
      (void) strcpy(TOKEN[1].STR,"$HOME");
#endif

   DIR_Expand(TOKEN[1].STR,TOKEN[2].STR);

   mm = oshchdir(TOKEN[2].STR);
   if (mm != 0)
      {
      ERRORS.SYS = 37;
      ERRORS.INDEX = 1;
      goto error_1;
      }

   (void) SCKRDI("IDIDEV",1,1,&iav,&iwa,&unit,&nullo);  /* test IDIDEV(1) */
   if (iwa >= 0)
      {
      n = IDI_SINI();
      if (n == 0)
         {
         IISSIN_C(iwa,1,TOKEN[2].STR);		/* send also to IDI-server */
         IDI_SCLS();
         }
      }

#if vms
   (void) strcpy(LINE.STR,"$SET DEF ");
   (void) strcat(LINE.STR,TOKEN[2].STR);
   progpntr = LINE.STR;
   goto final_act;
#else
   (void) system((const char *)"echo current dir. now: `pwd`");
   goto main_loop;
#endif


   case 5:

   /*  CLEAR/BACKGROUND no_secs                                     */
   /*  -----------------------------------------------------*/

   if (TOKEN[1].STR[0] != '?')
      {                                 /* we wait some time */
      n = CGN_CNVT(TOKEN[1].STR,2,1,&iwa,&rwa,&dwa);
      if (n < 1)
         {
         ERRORS.SYS = 100;
         ERRORS.INDEX = 1;
         goto error_1;
         }
      if (rwa > 0.0)
         {
         m = (int) (rwa * 1000.0);
         OSY_SLEEP(m,0);
         }
      }

   /* create fresh file $MID_WORK/RUNNINGxy */

   (void) sprintf(prog,"%sRUNNING%c%c",midwork,FRONT.DAZUNIT[0],
                  FRONT.DAZUNIT[1]);

   (void) osfdelete(prog);		/* get rid of old one */

   fid = osaopen(prog,WRITE);
   if (fid > -1)
      {
      (void) sprintf(save,"                ");
      (void) osawrite(fid,save,(int)strlen(save));
      (void) osaclose(fid);
      }

   if (server.MODE != 0)
      {                         /* send last receive box + close connection */
      ERRORS.SYS = inmail(9,cxpntr,ixpntr);

      server.MODE = 0;                     /* clear server mode */
      FRONT.INTERM = 0;                    /* and reset mail_interrupt_flag */
      osscatch(SIGUSR1,intermail);         /* use `intermail' for interrupts */
      if (ERRORS.SYS != 0) PREPERR("OSY"," "," ");
      }

   goto main_loop;


   case 6:
 
   /*  CLEAR/BUFFER   */
   /*  ---------------*/
 
   return (1);
 

   case 7:

   /*  CLEAR/CONTEXT  */
   /*  ---------------*/

   kk = Contexter(0);
   if (kk == -1)
      goto error_1;             /* wrong syntax */
   else if (kk == 1)
      goto main_loop;           /* parsing error, nothing to do */
   else
      goto join_forces;

 
   case 8:
 
   /*  COMPUTE/KEYWORD   result_key = key  op  key     */
   /*  ------------------------------------------------*/
	
   ERRORS.SYS = KEYCOMP(0,3,string);	/* expr. stored from TOKEN[3] on */
   if (ERRORS.SYS != 0)
      goto error_1;
   else
      goto main_loop;


   case 9:

   /*   CONNECT/BACK_MIDAS unit wait,secs back_char method display */
   /*  ------------------------------------------------------------*/

   ERRORS.INDEX = 1;                    /* point to unit */
   if (MONIT.COUNT < 2)                 /* we need parameters ... */
      {
      ERRORS.SYS = 5;
      goto error_2;
      }

   if (TOKEN[3].STR[0] == '?') TOKEN[3].STR[0] = 'b';
   iwa = 0;
   if (CGN_INDEXC(TOKEN[1].STR,':') < 1)
      stat = Mrunning(TOKEN[1].STR,1);	/* backMidas already running? */
   else
      stat = 0;				/* backMidas is on remote host */
   
   if (stat < 0)       /* no such Midas session found on local host */
      {
      char vstr[40], wstr[120], xbuf[80];

      iwa = 99;
      (void) strcpy(xbuf,"-geometry =80x25+500+500 -e inmidas");
      if (TOKEN[5].STR[0] != '?')
         (void) sprintf(vstr,"xterm -d %s ",TOKEN[5].STR);
      else
         (void) strcpy(vstr,"xterm ");

      if ((TOKEN[4].STR[0] == 'S') || (TOKEN[4].STR[0] == 's'))
         {                                      /* socket connection */
         n = CGN_INDEXC(TOKEN[1].STR,':');
         if (n > 0)				/* host given */
            {
            TOKEN[1].STR[n] = '\0';
            (void) sprintf(wstr,
                           "%s %s -j \"SET/BACKGR sockets,remote\" %s -p &",
                           vstr,xbuf,TOKEN[1].STR);
            TOKEN[1].STR[n] = ':';		/* reset to original */
            }
         else
            (void) sprintf(wstr,"%s %s -j \"SET/BACKGR sockets\" %s -p &",
                           vstr,xbuf,TOKEN[1].STR);
         }

      else                                      /* file connection */
         (void) sprintf(wstr,"%s %s -j \"SET/BACKGR files\" %s -p &",
                        vstr,xbuf,TOKEN[1].STR);

      /*  printf("%s\n",wstr);  */

      (void) oshcmd(wstr,(char *) 0,(char *) 0,(char *) 0);

      stat = Mrunning(TOKEN[1].STR,10);         /* wait 10 seconds */
      if (stat < 1)
         {
         (void) SCTSYS(2,"Could not start new, parallel Midas session ...\n");
         ERRORS.INDEX = -1;
         goto error_1;
         }
      }


   /* now add new entry to internal background table */
    
   stat = msetup(1,TOKEN[1].STR,TOKEN[2].STR,TOKEN[3].STR,TOKEN[4].STR);
   if (stat != 0)
      {
      if (stat == 90)
         {
         (void) sprintf(KAUX.STR,
                 "Could not get Pid from file MIDAS%c%c.PID ...",
                 TOKEN[1].STR[0],TOKEN[1].STR[1]);
         (void) SCTSYS(0,KAUX.STR);
         goto main_loop;                /* not necessarily an error */
         }
      else if (stat == 100)
         {
         ERRORS.INDEX = 2;
         ERRORS.SYS = 100;
         }
      else if (stat == 4)
         {
         ERRORS.INDEX = -1;
         ERRORS.SYS = 58;
         }
      else if (stat == 34)
         ERRORS.SYS = 59;
      goto error_1;
      }
       
   if (iwa == 99)			/* we started a new Midas session */
      {
      (void) sprintf(KAUX.STR,"New Midas session with unit = %s started...",
                     TOKEN[1].STR);
      (void) SCTSYS(0,KAUX.STR);
      }
   goto main_loop;

 
   case 10:
 
   /*  CONTINUE or CONTINUE/CLEAR      */
   /*  --------------------------------*/
 
   if (MONIT.PAUSLEVL < 1)
      {
      SCTPUT("command CONTINUE out of sync and ignored!");
      goto main_loop;			/* ignore out_of_sync CONTINUEs  */
      }
 
   CODE_FREE(0,0);			/* release all memory */
   MONIT.INTERRUPT = 0;
   KIWORDS[OFF_PRSTAT] = 0;		/* clear error flag */

   if (qualif[0] == 'C')	    /* clear everything -> back to terminal */
      {
      CODE_FREE(0,1);		    /* release memory of PAUSEd procedure */
      MONIT.LEVEL = 0;
      MONIT.PAUSLEVL = -1;
      goto main_loop;
      }
   else
      {
      for (nr=0; nr<MAX_LEVEL; nr++)
         {
         MONIT.PDEBUG[nr+1] = MONIT.QDEBUG[nr+1];
         MONIT.PCODE[nr] = MONIT.QCODE[nr];
         TRANSLATE[nr].LEN[0] = TRANSLATE[nr].LEN[1];
         TRANSLATE[nr].PNTR[0] = TRANSLATE[nr].PNTR[1];
         }
      (void) strcpy(PROC.FNAME,PROC.QNAME);	/* get original proc. name */
      MONIT.LEVEL = MONIT.PAUSLEVL;
      KIWORDS[OFF_MODE+6] = MONIT.LEVEL;
      MONIT.PAUSLEVL = -1;
      nb = MONIT.LEVEL - 1;
      CODE.CODE = TRANSLATE[nb].PNTR[0];
      CODE.LEN = TRANSLATE[nb].LEN[0];

      LINE.LEN = CGN_COPY(LINE.STR,"@ copylocal in");
      (void) PARSE(1,0,0);	
      goto join_forces;
      }


   case 11:
 
   /*  	COPY/KEYWORD sourcekey destkey [source_M_unit]           */
   /*  ----------------------------------------------------------*/
 
   DO_KEYS('C',cbuf);
   goto main_loop;


   case 12:
   case 13:
 
   /*  CREATE/COMMAND [D_COMMAND)  user_command command LINE.STR ...   */
   /*  ----------------------------------------------------------------*/
 
   ERRORS.INDEX = 1;
   ERRORS.SYS = DYNA_COM(qualif);
   KIWORDS[OFF_MODE+9] = 1;	/* currently only needed for PyMidas */

   if (ERRORS.SYS != 0)
      goto error_1;
   else
      {
      if ((TOKEN[1].STR[0] == '@') && (TOKEN[1].LEN == 2))
         {
         if ((TOKEN[1].STR[1] == 'p') || (TOKEN[1].STR[1] == 'P'))
            palias = 1;
         else if ((TOKEN[1].STR[1] == 's') || (TOKEN[1].STR[1] == 'S'))
            salias = 1;
         else if ((TOKEN[1].STR[1] == 'c') || (TOKEN[1].STR[1] == 'C'))
            calias = 1;
         }
      goto main_loop; 
      }
 
 
   case	14:
 
   /*  CREATE/DEFAULTS command/qualif default1 ... default8   */
   /*  -------------------------------------------------------*/
 
   if (MONIT.COUNT > 2)
      {
      EXTRACOM(TOKEN[1].STR,save,&save[6]);
      ERRORS.SYS = FINDCOM(save,&save[6],cbuf,&defset,&nbra,&cpntra,&jj);
      if (ERRORS.SYS > 1)
         {
         ERRORS.INDEX = 1;
         goto error_1;	
         }
      if ((nbra < 0) && (KIWORDS[OFF_ERROR+1] < 2))
         {
         (void)printf("defaults for system commands reserved for Experts...\n");
         goto main_loop;
         }

      ERRORS.SYS = PARDEFS('A',save);
      if (ERRORS.SYS != 0)
         {
         if (ERRORS.SYS == 1)
            break;		/* memory allocation error already reported */
         else if (ERRORS.SYS == 3)
            {
            ERRORS.INDEX = 2;
            ERRORS.SYS = 12;
            }
         else if (ERRORS.SYS < 0)
            {
            ERRORS.INDEX = 1;
            ERRORS.SYS = -ERRORS.SYS;		/* errors from SETDFF */
            }
         goto error_1;
         }
      }
   goto main_loop;
 
 
   case 15:
   case 16:
 
   /*  	DEBUG/MODULE or /PROCEDURE  level  OFF   */
   /*  ------------------------------------------*/
 
   if (DEBUGGY(0,qualif) != 0)
      goto error_1;
   else
      goto main_loop;

   
   case 17:
 
   /*  DEFINE/LOCAL_KEY  key/type/first/noval  data_string  ALL  */
   /*  ----------------------------------------------------------*/
	
   iwa = MONIT.COUNT - 1;
   if ((TOKEN[iwa].STR[0] == '<')
      &&
        (TOKEN[iwa].STR[1] != ',')
      &&
        (TOKEN[iwa].LEN > 1))
      {
      TOKEN[0].LEN = CGN_COPY(TOKEN[0].STR,"DEFINE/LOCAL"); /* clean command */
      proc_flag = 1;
      goto do_list;
      }

   DO_KEYS('L',cbuf);
   goto main_loop;
 

   case 18:    

   /*  DEFINE/MAXPAR maxnopar       */
   /*  -----------------------------*/

   mm = CGN_CNVT(TOKEN[1].STR,1,1,&iwa,&rwa,&dwa);
   if ((mm == 1) && (iwa > 0) && (iwa < 9))
      {
      kk = KIWORDS[OFF_PCOUNT] - iwa;
      if (kk > 0)
         {
         (void) sprintf(KAUX.OUT,
         "Warning: %d parameter(s) more entered than required...",kk);
         (void) SCTSYS(0,KAUX.OUT);
         }
      }
   goto main_loop;
 

   case 19:
 
   /*  DEFINE/PARAM   Pi default type/option prompt_str limits lim_label  */
   /*  -------------------------------------------------------------------*/
 
   ERRORS.INDEX = 1;
   ERRORS.SYS = DEFIPAR();
 
   if (likely(ERRORS.SYS == 0))
      goto main_loop;
   else
      goto error_1;
 
 
   case 20:
 
   /*  DELETE/COMMAND	user_command   */
   /*  --------------------------------*/
 
   if (MONIT.COUNT > 1)
      {
      (void) DYNA_COM("X");		/* try to delete...  */
      if ((TOKEN[1].STR[0] == '@') && (TOKEN[1].LEN == 2))
         {
         if ((TOKEN[1].STR[1] == 'p') || (TOKEN[1].STR[1] == 'P'))
            palias = 0;
         else if ((TOKEN[1].STR[1] == 's') || (TOKEN[1].STR[1] == 'S'))
            salias = 0;
         else if ((TOKEN[1].STR[1] == 'c') || (TOKEN[1].STR[1] == 'C'))
            calias = 0;
         }
      }
   else
      {
      palias = salias = calias = 0;
      INITCOM();				/* clear everything */
      }

   KIWORDS[OFF_MODE+9] = 2;	/* currently only needed for PyMidas */
   goto main_loop;
 
 
   case 21:
 
   /*  DELETE/DEFAULTS command/qualif   */
   /*  ---------------------------------*/
 
   EXTRACOM(TOKEN[1].STR,save,&save[6]);
   ERRORS.SYS = PARDEFS('D',save);
   if (ERRORS.SYS != 0)
      {
      ERRORS.INDEX = 1;
      goto error_1;	
      }
   else
      goto main_loop;
 

   case 22:

   /*  DELETE/KEYWORD   keyword     */
   /*  -----------------------------*/

   iwa = MONIT.COUNT - 1;
   if (TOKEN[iwa].STR[0] == '<')
      {
      proc_flag = 0;
      goto do_list;
      }

   DO_KEYS('D',cbuf);
   goto main_loop;

 
   case 23:
 
   /*  DELETE/LOGFILE    */
   /*  ------------------*/
 
   (void) MID_LOG('O',KAUX.OUT,2);		/* first close logfile  */
   (void) MID_LOG('S',FRONT.DAZUNIT,2);		/* then reinitialize it  */
   (void) MID_LOG('I',FRONT.DAZUNIT,2);		/* finally reopen it  */
   goto main_loop;
 
 
   case 24:

   /*  DISCONNECT/BACK_MIDAS  unit discon_server_flag */
   /*  -----------------------------------------------*/

   ERRORS.INDEX = 1;                    /* point to unit */
   ERRORS.SYS = 100;

   if (MONIT.COUNT > 2)
      {
      cr = CGN_UPPER(TOKEN[2].STR[0]);
      if ((cr == 'X') || (cr == 'Z'))	   /* only with valid flag */
         {
         if ((TOKEN[1].STR[0] != '?') && (TOKEN[1].STR[0] != '*'))
            {
            char  ua, ub;

            ua = TOKEN[1].STR[0];
            ub = TOKEN[1].STR[1];
            for (nr=0; nr<MAX_BACK; nr++)
               {
               if ((BKMIDAS[nr].UNIT[0] == ua) && (BKMIDAS[nr].UNIT[1] == ub))
                  {					/* unit found */
                  if (BKMIDAS[nr].FLAG == 'Y')
                     {
                     (void) sprintf(KAUX.OUT,
                     "Connection to unit %c%c is with wait...",
                     BKMIDAS[nr].UNIT[0],BKMIDAS[nr].UNIT[1]);
                     SCTPUT(KAUX.OUT);
                     SCTPUT("Disconnect + reconnect without wait!");
                     goto main_loop;
                     }

                  if (BKMIDAS[nr].METHOD == 'f')
                     save[0] = 'F';		/* local files */
                  else
                     {
                     if (BKMIDAS[nr].HOST[0] != '\0')
                        save[0] = 'R';		/* remote sockets */
                     else
                        save[0] = 'S';		/* local sockets */
                     }
                  LINE.LEN = sprintf(LINE.STR,
                         "@ disconnect %c%c %c %c %c",
                         ua,ub,BKMIDAS[nr].COMC,save[0],cr);

                  ERRORS.SYS = PARSE(1,0,0);
                  goto join_forces;
                  }
               }
            goto error_1;
            }

         else
            {
            int  iu, ib, iw;
            char  cu[64], cb[32], cw[32];

            iu = -1; ib = -1; iw = -1;
            for (nr=0; nr<MAX_BACK; nr++)
               {
               if (BKMIDAS[nr].UNIT[0] != ' ')		/* a unit found */
                  {
                  if (BKMIDAS[nr].FLAG == 'Y')
                     {
                     (void) sprintf(KAUX.OUT,
                     "Connection to unit %c%c is with wait...",
                     BKMIDAS[nr].UNIT[0],BKMIDAS[nr].UNIT[1]);
                     SCTPUT(KAUX.OUT);
                     SCTPUT("Disconnect + reconnect without wait!");
                     goto main_loop;
                     }

                  if (BKMIDAS[nr].METHOD == 'f')
                     save[0] = 'F';             /* local files */
                  else
                     {
                     if (BKMIDAS[nr].HOST[0] != '\0')
                        save[0] = 'R';          /* remote sockets */
                     else
                        save[0] = 'S';          /* local sockets */
                     }

                  cu[++iu] = BKMIDAS[nr].UNIT[0];
                  cu[++iu] = BKMIDAS[nr].UNIT[1];
                  cu[++iu] = ',';
                  cb[++ib] = BKMIDAS[nr].COMC;
                  cb[++ib] = ',';
                  cw[++iw] = save[0];
                  cw[++iw] = ',';
                  }
               }
            if (iu == -1)
               {
               SCTPUT("No background Midas to disconnect from...");
               goto main_loop;
               }
            cu[iu] = '\0';
            cb[ib] = '\0';
            cw[iw] = '\0';
            LINE.LEN = sprintf(LINE.STR,"@ alldisconn %s %s %s %c",cu,cb,cw,cr);
            ERRORS.SYS = PARSE(1,0,0);
            goto join_forces;
            }
         }

      else
         goto error_1;
      }
          
   stat = msetup(0,TOKEN[1].STR,TOKEN[2].STR,TOKEN[3].STR,TOKEN[4].STR);
   if (stat != 0)
      {
      ERRORS.INDEX = -1;
      if (stat == 4) 
         ERRORS.SYS = 58;
      else 
         ERRORS.SYS = 100;
      goto error_1;
      } 
   goto main_loop;


   case 25:
   case 26:
   case 27:

   /*   ECHO/OFF or /ON  or /FULL   level    */
   /*  --------------------------------------*/

   kk = DEBUGGY(1,qualif);
   if (kk != 0)
      goto error_1;
   else
      goto main_loop;


   case 28:

   /*  EXECUTE/TABLE table command-string    */
   /*  --------------------------------------*/

   ERRORS.INDEX = 1;
   ERRORS.SYS = build_prg(1,0);         /* build procedure from table */
   if (ERRORS.SYS != 0) 
      goto error_1;
   else
      {
      (void) PARSE(1,0,0);		/* LINE.STR filled by `build_prg' */
      goto join_forces;
      }
   }


branch_29:


switch(nbra)
   {
   case 29:
   case 30:
   case 31:
   case 32:
   case 33:
 
   /*  HELP, HELP/APPL, /CL, /CONTRIB, /KEYW  help_string      */
   /*  ---------------------------------------------------------*/
 

   if (MONIT.COUNT == 1)
      {
      TOKEN[1].STR[0] = '?';
      TOKEN[1].STR[1] = '\0';
      TOKEN[1].LEN = 1;
      }

   else if (strcmp(TOKEN[1].STR,"-1") != 0)	  /* for "help -1" see below */
      {
      CGN_LOWSTR(TOKEN[1].STR);
      if (qualif[0] == ' ')	 /* only for HELP string (IMAG is def-qualif */
         {
         memset((void *)cbuf,32,(size_t)20);	/* clear auxiliary variables */
         mm = CGN_INDEXC(TOKEN[1].STR,'/');
         EXTRACOM(TOKEN[1].STR,save,&save[10]);	/* separate comnd + qualif  */
         n = FINDCOM(save,&save[10],cbuf,&defset,&nbra,&cpntra,&jj);

         if (n <= 1)				/* command found  */
            {
            save[6] = ' ';
            n = CGN_INDEXC(save,' ');
            if (mm > 0)				/* with command and qualif  */
               {
               save[n] = '/';
               if (TOKEN[1].LEN == (mm+1))        /* was it HELP command/  ? */
                  (void) strcpy(&save[n+1],"    ");
               else
                  {
                  save[14] = '\0';
                  CGN_strcpy(&save[n+1],&save[10]);
                  }
               }
            else
               save[n] = '\0';

            CGN_LOWCOPY(TOKEN[1].STR,save,40);	/* copy + put to lower case  */
            TOKEN[1].LEN = (int) strlen(TOKEN[1].STR);
            }
         }
      }
	
   memset((void *)save,32,(size_t)80);
   kk = TOKEN[0].LEN;
   (void) strncpy(save,TOKEN[0].STR,kk);
   kk ++;					/* leave a blank */
   iav = TOKEN[1].LEN;
   stat = 80 - kk;
   if (iav > stat) iav = stat;			/* avoid overflow */
   (void) strncpy(&save[kk],TOKEN[1].STR,iav);	/* build HELP/... string  */
   save[kk+iav] = '\0';
 
  sect_48080:
   (void) SCKWRC("IN_A",1,save,1,60,&unit);	           /* store input... */

   cpntr = CONTXT.NAME;		/* context names -> INPUTC + OUTPUTC */
   kk = 0;
   mm = 0;
   memset((void *)prog,32,(size_t)80);
   prog[80] = '\0';
   for (nr=0; nr<MAX_CONTXT; nr++)
      {
      if (*cpntr != ' ')		/* only copy the contexts */
         {
         (void) strncpy(&prog[mm],cpntr,8);
         mm += 8;
         if (mm >= 80)			/* fill first keyword */
            {
            if (kk == 0)
               {
               (void) SCKWRC("INPUTC",1,prog,1,80,&unit);
               kk = 1;
               mm = 0;
               memset((void *)prog,32,(size_t)80);
               prog[80] = '\0';
               }
            else
               break;
            }
         }
      cpntr += 8;
      }

   if (kk == 1)
      (void) SCKWRC("OUTPUTC",1,prog,1,80,&unit);
   else
      {
      (void) SCKWRC("INPUTC",1,prog,1,80,&unit);
      memset((void *)prog,32,(size_t)80);
      (void) SCKWRC("OUTPUTC",1,prog,1,80,&unit);
      }

   if (strcmp(TOKEN[1].STR,"-1") != 0)
      {
      (void) strcpy(TOKEN[1].STR,"MID_MONIT:helper");
      goto run_prog;				      /* jump to command RUN */
      }
   else					/* "help -1" only to get contexts */
      goto main_loop;			/* for XHelp in keys INPUTC, OUTPUTC */
 

   case 34:
       
   /*  HELP/qualif      qualif   */
   /*  --------------------------*/

   if (TOKEN[1].STR[0] == '/')
      n = 1;
   else
      n = 0;
   CGN_UPCOPY(TOKEN[2].STR,&TOKEN[1].STR[n],6);
   (void) SHOWCOM(-1,"Q ",TOKEN[2].STR);
   goto main_loop;


   case 35:

   /*  INFO/DESCR frame descr     */
   /*  ---------------------------*/

   iwb[0] = -1;
   FRAMACC('O',TOKEN[1].STR,0,&iwa);		/* may be image or table */
   if (iwa >= 0)
      {
      (void) SCDFND(iwa,TOKEN[2].STR,string,&iwb[1],&iwb[2]);
      if (string[0] == 'I')
         iwb[0] = 1;                    /* integer */
      else if (string[0] == 'R')
         iwb[0] = 2;                    /* real */
      else if (string[0] == 'C')
         iwb[0] = 3;                    /* character */
      else if (string[0] == 'D')
         iwb[0] = 4;                    /* double */
      else if (string[0] == 'S')
         iwb[0] = 5;                    /* size_t */
      else
         iwb[0] = 0;
      }

   KIWORDS[OFF_INFO] = iwb[0];
   KIWORDS[OFF_INFO+1] = iwb[1];
   KIWORDS[OFF_INFO+2] = iwb[2];
   goto main_loop;


   case 36:

   /*  INFO/KEYWORD  keyword    */
   /*  -------------------------*/

   if (MONIT.COUNT == 1)
      {
      ERRORS.SYS = 1;
      goto error_1;
      }

   MID_SHOKEY(1,TOKEN[1].STR);
   goto main_loop;


   case 37:
 
   /* INQUIRE	key prompt-string      */
   /*  --------------------------------*/
 
   if (MONIT.COUNT < 3) TOKEN[2].STR[0] = ' ';		/* no prompt given */
   DO_KEYS('I',TOKEN[2].STR);
   goto main_loop;
 

   case 38:
 
   /*   LOG/OFF     */
   /*  -------------*/
 
   (void) MID_LOG('O',LINE.STR,2);	  /* make sure log file is closed  */
   KIWORDS[OFF_LOG] = KIWORDS[OFF_LOG+7] = 0;
   goto main_loop;
 
 
   case 39:
 
   /*   LOG/ON      */
   /*  -------------*/
 
   KIWORDS[OFF_LOG] = KIWORDS[OFF_LOG+7] = 1;
   (void) MID_LOG('I',FRONT.DAZUNIT,2);
   goto main_loop;
 
 
   case 40:
 
   /*   LOG/TOF     */
   /*  -------------*/
 
   (void) MID_LOG('P',LINE.STR,2);		/* start new page in logfile */
   goto main_loop;
 
 
   case 41:

   /*  PRINT/KEYWORD    keyword[,keyword,...] [since]  */
   /*  ------------------------------------------------*/

   (void) SCKRDC("MID$PRNT",1,1,52,&iav,prog,&unit,&nullo);  /* get (1:52) */
   prog[52] = '\0';
   (void) SCKWRC("MID$PRNT",1,&prog[2],53,50,&unit); /* (3:52) -> (53:102) */

   if ((prog[0] != 'F') || (prog[1] != ':'))    /* do same things as  */
      {                                         /* in print.prg !     */
      memset((void *)prog,32,(size_t)50);	/* prog[52] already '\0' */
      (void) strncpy(prog,"midtemp  .print",15);
      prog[7] = FRONT.DAZUNIT[0];
      prog[8] = FRONT.DAZUNIT[1];
      (void) SCKWRC("MID$PRNT",1,prog,3,50,&unit);       /* modify (3:52) */
      }

   (void) MID_LOG('O',cbuf,2);                        /* close logfile */
   KIWORDS[OFF_LOG+8] = 1;           /* set print flag */
   (void) MID_LOG('I',FRONT.DAZUNIT,2);                /* open logfile again */
   KIWORDS[OFF_ERROR+5] = KIWORDS[OFF_ERROR+2];  /* E(6) = E(3) */

   stat = DO_KEYS('R',cbuf);

   (void) MID_LOG('O',cbuf,2);
   KIWORDS[OFF_LOG+8] = 0;           /* clear print flag again */
   (void) MID_LOG('I',FRONT.DAZUNIT,2);             /* open logfile again */

   if (stat == 0)
      {
      LINE.LEN = CGN_COPY(LINE.STR,"@ print.prg out");	/* now print */
      ERRORS.SYS = PARSE(1,0,0);			/* via @ print out */
      if (ERRORS.SYS == 0) goto join_forces;
      }
   goto main_loop;                      /* not all o.k. - get next input */


   case 42:	
 
   /*  PLAYBACK/...    MIDAS_logfile (i.e. with Midas xyz> ... )   */
   /*  (PLAYBACK/FILE or PLAYBACK/FILE)                            */
   /*  ------------------------------------------------------------*/
 
   if ( (FRONT.PLAYBACK != 0) || (MONIT.LEVEL > 0) )
      {			 	     /* no playback from command procedures  */
      ERRORS.SYS = 100;			/* and no playback nesting possible  */
      ERRORS.INDEX = 0;
      goto error_1;
      }

   (void) CGN_CLEANF(TOKEN[1].STR,5,cxpntr,64,&m,&n);	 /* append defaults */
   if (qualif[0] == 'L')
      FRONT.PLAYBACK = 11;			/* PLAYBACK/LOGFILE */
   else
      FRONT.PLAYBACK = 1;			/* PLAYBACK/FILE */

   return (5);			/* tell front end: PLAYBACK/LOG */
 
 
   case 43:
	
   /*   READ/COMMANDS  procedure       */
   /*  --------------------------------*/
 
   return (2);				/* done in front end ... */
 

   case 44:
 
   /*  RUN 	application-program     */
   /*  ---------------------------------*/
 
   if (unlikely(MONIT.MDEBUG[MONIT.LEVEL] == 1))
      goto main_loop;				 /* skip the execution...  */

run_prog:
   if (strncmp(TOKEN[1].STR,"PIPE_EXE:",9) == 0)	/* look for PIPE_EXE */
      {						/* replace it by what's in */
      (void) strcpy(bigstr,PIPE.HOME);		/* PIPE.HOME + PIPE.EXE */
      (void) strcpy(&bigstr[PIPE.HOME_LEN],PIPE.EXE);
      (void) strcat(bigstr,&TOKEN[1].STR[9]);	/* repaste executable */
      }
   else
      CGN_LOGNAM(TOKEN[1].STR,bigstr,200);

	
   /*  search for '/' or ']' backwards  */
  
   kk = CGN_JNDEXC(bigstr,FSY_DIREND);
   if (kk < 0) kk = 0;
   progpntr = bigstr;
   cpntrb = progpntr + kk;

#if vms
#else
   CGN_LOWSTR(cpntrb);			/* in Unix we want lower case */
#endif

   n = CGN_INDEXC(cpntrb,'.');
   if (n < 0) (void) strcat(progpntr,".exe");

   if (MONIT.COUNT > 2)
      {
      n = CGN_COPY(LINE.STR,progpntr);
      cpntr = LINE.STR + n;
      *cpntr++ = ' ';
      for (n=2; n<MONIT.COUNT; n++)
         {
         (void) strcpy(cpntr,TOKEN[n].STR);
         cpntr += TOKEN[n].LEN;
         *cpntr++ = ' ';
         }
      *cpntr = '\0';
      progpntr = LINE.STR;
      }

   goto final_act;
 

   case 45:

   /*  SET/BACKGROUND   service[,remote]  echo  sleep-time  */
   /*  -----------------------------------------------------*/

   if (TOKEN[3].STR[0] == '?')
      iwa = 1;                  /* default to 1 sec */
   else
      {
      if ((CGN_CNVT(TOKEN[3].STR,1,1,&iwa,&rwa,&dwa) <= 0) || (iwa <= 0))
         {
         ERRORS.SYS = 100;
         ERRORS.INDEX = 1;
         goto error_1;
         }
      }
   server.SLEEP =  iwa;

   if ( (TOKEN[2].STR[1] == 'F') || (TOKEN[2].STR[1] == 'f') )
      server.ECKO = 'N';                        /* echo = off */
   else
      server.ECKO = 'Y';

   if (server.MODE != 0)                        /* already in background */
      goto main_loop;                           /* method cannot be updated! */

   if ((TOKEN[1].STR[0] == 'S') || (TOKEN[1].STR[0] == 's'))
      {
      ERRORS.SYS = setback(TOKEN[1].STR);
      if (ERRORS.SYS != 0) goto error_2;
      server.MODE = 1;                  /* sockets */
      }
   else
      {
      (void) strcpy(string,"/FORGR__xx.RBOX");
      string[8] = FRONT.DAZUNIT[0];
      string[9] = FRONT.DAZUNIT[1];
 
      fid = osaopen("receive_dummy",WRITE);              /* open for writing  */
      if (fid == -1)
         {
         (void)printf("Could not create file %s ...\n",&string[1]);
         goto main_loop;
         }

      (void) strcpy(KAUX.STR,"Now in background mode (via ASCII files)");
      osawrite(fid,KAUX.STR,(int)strlen(KAUX.STR));
      osaclose(fid);

      (void) strcpy(save,midwork);
      (void) strcat(save,string);		/* append to MID_WORK */
      stat = osfrename("receive_dummy",save);	/* move to real name */
      if (stat != 0)
         {
         unsigned int time;

         time = 5;                      /* wait some time + try again */
         sleep(time);

         stat = osfrename("receive_dummy",save);
         if (stat != 0)
            {
            (void)printf("Could not create %s ...\n",save);
            goto main_loop;
            }
         }

      server.MODE = 2;                  /* files+interrupts */
      FRONT.INTERM = 2;
      (void)printf("%s\n",KAUX.STR);
      }

      /* put PID into file $MID_WORK/RUNNINGxy */

   (void) sprintf(prog,"%sRUNNING%c%c",midwork,FRONT.DAZUNIT[0],
                  FRONT.DAZUNIT[1]);
   fid = osaopen(prog,WRITE);
   if (fid > -1)
      {
      (void) sprintf(save,"%d (Mrunning looks for 20 chars...)",FRONT.PID);
      (void) osawrite(fid,save,(int)strlen(save));
      (void) osaclose(fid);
      }
   else
      {
      (void) printf("Could not access file %s...\n",prog);
      goto main_loop;
      }

   goto main_loop;

 
   case 46:
 
   /*  SET/BUFFER	no_of_lines     */
   /*  ---------------------------------*/
 
   return (3);

 
   case 47:
 
   /*  SET/CONTEXT	new_context     */
   /*  ---------------------------------*/
 
 
   kk = Contexter(1);
   if (kk == -1)
      goto error_1;             /* wrong syntax */
   else if (kk == 1)
      goto main_loop;           /* nothing to do ... */
   else
      goto join_forces;

 
   case 48:
 
   /*  SET/FORMAT       I-format  G-format   F-format  */
   /*  ------------------------------------------------*/
 
   if (MONIT.COUNT < 2)
      {							/* use defaults */
      TOKEN[1].LEN = CGN_COPY(TOKEN[1].STR,"I4");
      TOKEN[2].LEN = CGN_COPY(TOKEN[2].STR,"E15.5,E15.5");
      }

   ERRORS.SYS = COMPILE(7,&mm);
   if (likely(ERRORS.SYS == 0) )
      goto main_loop;
   else
      goto error_1;


   case 49:

   /*  SET/MIDAS_SYSTEM  option=input      */
   /* -------------------------------------*/


   ERRORS.SYS = SETMID(iwb);
   if (ERRORS.SYS != 0) goto error_1;
  
#if vms
   if (iwb[0] == 77)			/* SET/MIDAS INSERT=... */
      {					/* only for VAX/VMS     */
      ixpntr[0] = iwb[1];
      return (6);			/* has to be done at FrontEnd */
      }
#endif

   goto main_loop;

 
   case 50:
 
   /*  SHOW/BACK_MIDAS unit disp_flag  */
   /*  --------------------------------*/
 
   if ((TOKEN[2].STR[0] == 'N') || (TOKEN[2].STR[0] == 'n'))
      iwa = 0;				/* no display */
   else
      iwa = 1;

   n = showback(TOKEN[1].STR,iwa);	/* get status from backgr. Midas */
   KIWORDS[OFF_INFO] = n;		/* save in keyword MID$INFO(1) */

   goto main_loop;

 
   case 51:
 
   /*  SHOW/COMMANDS	'  ', ALL, PRI, FIX or DIAG   */
   /*  -----------------------------------------------*/
 
   if (MONIT.COUNT < 2)
      {
      TOKEN[1].STR[0] = ' ';			/* change ? to ' '  */
      TOKEN[1].STR[1] = ' ';
      }
   else if (TOKEN[1].LEN == 1)
      TOKEN[1].STR[1] = ' ';
 
   iav = SHOWCOM(-1,TOKEN[1].STR,TOKEN[3].STR);
   (void) SCKWRI("OUTPUTI",&iav,9,1,&unit);

   goto main_loop;
 
 
   case 52:
 
   /*  SHOW/CONTEXT [context]         */
   /*  -------------------------------*/
 
   iav = 0;
   if ((TOKEN[1].STR[0] == '-') && (TOKEN[1].STR[1] == 'a'))
      {
      char   contxt_dir[120];

      SCTPUT("available contexts:");
      SCTPUT("------------------:");
      (void) OSY_TRNLOG("MID_HOME",contxt_dir,120,&iav);
      (void) strcat(contxt_dir,"/context; ");
      (void) strcpy(bigstr,"cd ");
      (void) strcat(bigstr,contxt_dir);
      (void) strcat(bigstr,"ls -c1 *.ctx");
      (void) system((const char *)bigstr);
      goto main_loop;
      }
   if (CONTXT.QUEUE[0] == 0)
      {
      if (MONIT.COUNT < 2)
         (void) SCTSYS(0,"currently no context enabled ...");
      else
         (void) SCKWRI("OUTPUTI",&iav,5,1,&unit);
      }
   else
      {
      cpntr = CONTXT.NAME;                 /* point to structure CONTEXT */
      if (MONIT.COUNT < 2)
         {
         for (nr=0; nr<MAX_CONTXT; nr++)
            {
            if (*cpntr != ' ')
               {
               mm = nr + 1;
               (void) sprintf
               (KAUX.OUT,"(%d) %8.8s  from %s",mm,cpntr,CONTXT.pdirec[nr]);
               (void) SCTSYS(0,KAUX.OUT);
               }
            cpntr += 8;
            }
         }
      else
         {
         CGN_LOWSTR(TOKEN[1].STR);
         for (nr=TOKEN[1].LEN; nr<8; nr++) TOKEN[1].STR[nr] = ' '; 
         for (nr=0; nr<MAX_CONTXT; nr++)
            {
            if (*cpntr != ' ')
               {
               if (strncmp(cpntr,TOKEN[1].STR,8) == 0)
                  {
                  iav = nr + 1;
                  break;
                  }
               }
            cpntr += 8;
            }
         (void) SCKWRI("OUTPUTI",&iav,5,1,&unit);
         }
      }
   goto main_loop;
 
 
   case 53:
 
   /*  SHOW/DEFAULTS      */
   /*  -------------------*/
 
   (void) PARDEFS('S',cbuf);
   goto main_loop;
 

   case 54:
 
   /*  SHOW/KEYWORDS keyword       */
   /*  ----------------------------*/
 
   iwa = MONIT.COUNT - 1;
   if (TOKEN[iwa].STR[0] == '<')
      {
      proc_flag = 0;
      goto do_list;
      }

   MID_SHOKEY(0,TOKEN[1].STR);
   goto main_loop;
 

   case 55:

   /* STORE/FRAME key input element_no exit_label      */
   /*  ------------------------------------------------*/
 
   ERRORS.SYS = STORE_FR(&iwa);
   if (ERRORS.SYS != 0)
      {
      ERRORS.INDEX = 3;
      goto error_1;
      }

   if (iwa == 1) 
      goto write_key;
   else
      {
      bcomnd[1] = '*';
      goto main_loop;			/* now execute a GOTO command */
      }
 

   case 56:
   case 57:

   /*  SYNCHRONIZE/MIDAS [time_stamp]                       */
   /*  SYNCHRONIZE/TIME flag                                */
   /*  -----------------------------------------------------*/

   iwa = SYNCHRO(qualif);
   if (iwa == 1)
      MYBATCH(bcomnd,TOKEN[0].STR);	/* only for SYNC/TIME possible */

   goto main_loop;
   }

branch_58:

switch(nbra)
   {
   case 58:
   case 59:
   case 60:
   case 61:
   case 62:
 
   /*  TRANSLATE/ADD, /SHOW /PROC  procedure
       or 	/OPEN, /CLOSE                             */
   /*  ---------------------------------------------------*/
 
   command[0] = '#';
 
   if (qualif[0] == 'S') 	/* show `compiled' procedure */
      { 
      iwa = MONIT.COUNT - 1;
      if (TOKEN[iwa].STR[0] == '<')
         {
         proc_flag = 0;
         goto do_list;
         }

      abbrev = 0;
      command[1] = 'S';
      goto sect_41500;
      }
   
   else if (qualif[0] == 'P')	/* compile individual procedure */
      { 
      abbrev = 0;
      command[1] = 'C';
      MONIT.COMPILED = 0;	/* make sure it's not set */
      goto sect_41500;
      }


/*  all other options for super_user only...  */

   if (KIWORDS[OFF_ERROR+1] <= 2)
      (void)printf("command TRANSLATE reserved for MIDAS system manager\n");
 
   else if ( (qualif[0] == 'O') || (qualif[0] == 'C') )
      (void) INTERNAL(qualif,TOKEN[1].STR,&mm);   /* open/close internal.cod */

   else
      {
      abbrev = 1;
      command[1] = 'A';			/* mark "compilation" for MYBATCH  */
      goto sect_41500;
      }
 
   goto main_loop;
 

   case 63:
	
   /*   WAIT/SECS    no_of_secs                        */
   /*  ------------------------------------------------*/

   (void) WAIT_SECS(TOKEN[1].STR);
   goto main_loop;			/* no error return anymore (060213) */


   case 64:

   /*   WAIT/BACK_MIDAS       unit                     */
   /*  ------------------------------------------------*/

   waitback(TOKEN[1].STR,iwb);
   goto main_loop;


   case 65:
 
   /*  WRITE/COMMANDS	com_no1,com_no2,...,com_noN 	P1 P2 P3 ... P8   */
   /*  -------------------------------------------------------------------*/
 
   ixpntr[0] = MONIT.COUNT;		/* save parameter count */
   return (4);                          /* done in front end ... */
 

   case 66:
   case 67:
 
   /*  WRITE/OUT  text  or  file.txt section label    */
   /*  WRITE/_OUT  file section label   (no special file type required) */
   /*  ------------------------------------------------*/
 
   iwa = MONIT.COUNT - 1;
   if (TOKEN[iwa].STR[0] == '<')		/* check input from file */
      {						/* via ... <file */
      cbuf[0] = CGN_UPPER(TOKEN[iwa].STR[1]);
      if ((cbuf[0] >= 'A') && (cbuf[0] <= 'Z')) 
         {
         proc_flag = 0;
         goto do_list;
         }
      }
   
   WRITE_QU(qualif,&iav);
   goto main_loop;
 
 
   case 68:
 
   /*  WRITE/ERROR	error no.  [text ... ]         */
   /*  ------------------------------------------------*/
 
   WRITE_QU(qualif,&iav);
   if (iav == 100)
      {                                 /* avoid monitor error handling */
      iwa = ERRORS.SYS;
      ERRORS.SYS = -1;
      PREPERR("MIDAS",KAUX.OUT,"");
      KIWORDS[OFF_PRSTAT] = iwa;        /* reset to original value */
      KIWORDS[OFF_PRSTAT+1] = iav;      /* PREPERR always sets it to 10 */
      }
   else
      PREPERR("MIDAS",KAUX.OUT,"");
   goto clean_up;

 
   case 69:
   case 70:
   case 71:
   case 72:
   case 73:

   /*  OPEN/FILE    file_name READ/WRITE/APPEND file_control_key  */
   /*  CLOSE/FILE   file_id                                       */
   /*  WRITE/FILE   file_id  char.buff                            */
   /*  READ/FILE    file_id  char.buff_key [max_rd]               */
   /*  INFO/FILE    file_name/file_id                             */
   /*  -----------------------------------------------------------*/

   m = nbra - 69;		/* open=0, close=1, write=2, read=3, info=4 */
   ERRORS.SYS = ascfiles(m,&ERRORS.INDEX);
   if (ERRORS.SYS != 0)
      goto error_1;
   else
      goto main_loop;


   case 74:

   /*  CONVERT/COORDS image coord_string  */
   /*  ---------------------------------  */

   (void) worldcnv();
   goto main_loop;


   case 75:
   case 76:

   /*  MESSAGE/OUT severity caller text indent_flag  */
   /*  APPEND/OUT text CLRF_flag */
   /*  --------------------------------------------  */

   pipe_mess(command[0]);
   goto main_loop;


   case 77:

   /*  WRITE/DHELP  frame  descr help_text   */
   /*  --------------------------------------*/

   (void) memcpy(save,TOKEN[2].STR,(size_t)(TOKEN[2].LEN+1));
   TOKEN[2].LEN = sprintf(TOKEN[2].STR,"%s/h/1/%d",save,(int)TOKEN[3].LEN);
   /* fall through to WRITE/DESCR command ... */

   case 78:

   /*  WRITE/DESCR  frame  descr/type/1.elem/noval values   */
   /*  -----------------------------------------------------*/

   iwa = MONIT.COUNT - 1;
   if ((TOKEN[iwa].STR[0] == '<')	/* handle file input via <abc.dat */
      &&
        (TOKEN[iwa].STR[1] != ',')
      &&
        (TOKEN[iwa].LEN > 1))
      {
      if (qualif[1] == 'H')			/* clean command */
         TOKEN[0].LEN = CGN_COPY(TOKEN[0].STR,"WRITE/DHELP");
      else
         TOKEN[0].LEN = CGN_COPY(TOKEN[0].STR,"WRITE/DESCR"); 
      proc_flag = 1;
      goto do_list;
      }

   if (unlikely(MONIT.COUNT < 4))	/* emulate `define/param p3 + c ...' */
      {					/* of the procedure: descr.prg       */
      TOKEN[3].STR[0] = '+';
      TOKEN[3].STR[1] = '\0';
      TOKEN[3].LEN = 1;
      }

   (void) SCKRDC("MID$IN",1,1,1,&iav,cbuf,&unit,&n);	/* get input stream */
   if (unlikely(cbuf[0] == 'F'))
      {
      if (unlikely(qualif[1] == 'H')) 
         {
         SCTPUT("file input for WRITE/DHELP not supported yet...");
         goto main_loop;
         }
      else
         {
         LINE.STR[0] = 'F';			/* WRITE/DESC => FRITE/DESC */
         TOKEN[0].STR[0] = 'F';
         goto join_forces;			/* reexecute the command */
         }
      }
   else
      {
      (void) DSC_write();
      goto main_loop;
      }


   case 79:
   case 80:
   case 81:
   case 82:
   case 83:
   case 84:
   case 85:
   case 86:

   /*   ADD,SUBTRACT/xCATAL catal inframes low,hi  */
   /*  ------------------------------------------  */

   (void) CATALO(command[0],qualif[0]);
   goto main_loop;

 
   case 87:

   /*  MOVE/LOCAL direc Pause_option  */
   /*  -----------------------------  */

   if ((TOKEN[1].STR[0] == 'I') || (TOKEN[1].STR[0] == 'i'))
      {
      LINE.LEN = CGN_COPY(LINE.STR,"@ copylocal in");
      (void) PARSE(1,0,0);	
      goto join_forces;
      }

   kk = osaopen("localkd.copy",WRITE);
   if (kk < 0) 
      {
      (void)printf("Could not create `localkd.copy' file...\n");
      goto main_loop;
      }

   jj = 0;					/* move local keys out */
   MID_GETLOCAL(&jj,string,&mm,&m);
   if (jj == -1)
      {
      (void) strcpy(save,"_NO_LOCAL_KEYS_");
      (void) osawrite(kk,save,(int)strlen(save));
      (void) osaclose(kk);
      goto main_loop;		/* no local keys there */
      }

   jj = 0;
   for (;;)			/* loop forever */
      {
      MID_GETLOCAL(&jj,string,&mm,&m);	/* get local keys */
      if (jj == -1) 
         {
         (void) osaclose(kk);

         LINE.LEN = 			/* build new command line */
              CGN_COPY(LINE.STR,"@ copylocal out");
         (void) PARSE(1,0,0);		/* parse this input string  */
         goto join_forces;	/* and execute it */
         }

      string[16] = ' ';				/* prepare records as: */
      n = CGN_INDEXC(string,' ');	/* l_key_nam/type/1/noelem l_key_nam */
      if (n == 16) n = 15;
      (void) strncpy(save,string,n);
      if ((string[15] == 'C') && (mm > 1))
         (void) sprintf(&save[n],"/%c*%d/1/%d ",string[15],mm,m);
      else
         (void) sprintf(&save[n],"/%c/1/%d ",string[15],m);
      string[15] = '\0';
      (void) strcat(save,string);
      (void) osawrite(kk,save,(int)strlen(save));
      }

   }		/* end of switch statement */
 

sect_41000:
 
/*  command = @, @%, @a, @s, @c, @g, @d, @p and @@    (@p is NOT static)
    execute a MIDAS procedure                                            */
/*  ---------------------------------------------------------------------*/

 
if (unlikely(TOKEN[1].STR[0] == '?'))            /* look for "@@ ??" */
   {
   (void) strcpy(save,"?? @@");
   goto sect_48080;
   }

iwa = MONIT.COUNT - 1;
if (unlikely(TOKEN[iwa].STR[0] == '<'))		/* test for "@@ proc <file" */
   {
   cbuf[0] = CGN_UPPER(TOKEN[iwa].STR[1]);
   if ((cbuf[0] >= 'A') && (cbuf[0] <= 'Z')) 
      {
      MONIT.COMPILED = 0;
      proc_flag = 0;
      goto do_list;
      }
   }
    
command[0] = TOKEN[0].STR[0];
command[1] = TOKEN[0].STR[1];
command[2] = TOKEN[0].STR[2]; 			/* we need to save that  */


/*  take care of "procedure,entry"  */
 
sect_41500:
 
memset((void *)PROC.ENTRY,32,(size_t)8);	/* clear ENTRY string first */
mm = CGN_INDEXC(TOKEN[1].STR,',');

if (mm > 0)
   {
   CGN_UPCOPY(PROC.ENTRY,&TOKEN[1].STR[mm+1],8);/* save entry in upper case */
   CGN_REPLA(PROC.ENTRY,8,'\0',' ');		/* we want blanks ...  */
   TOKEN[1].LEN = mm;				/* update length of token  */
   TOKEN[1].STR[mm] = '\0';
   }
	
	
/*  handle procedures   */
 
if (abbrev < 0)
   (void) strcpy(bigstr,TOKEN[1].STR);	

else if (abbrev == 0)
   (void) CGN_CLEANF(TOKEN[1].STR,6,bigstr,164,&kk,&jj);   /* append type */

else
   {	
   (void) CGN_CLEANF(TOKEN[1].STR,6,save,64,&kk,&jj);    /* append type */
   jj = 0;
   if (abbrev == 1)
      {
      iav = sysdskl;
      cpntr = sysdisk;
      }
   else if (abbrev == 2)
      {
      iav = appadskl;
      cpntr = appadisk;
      }
   else if (abbrev == 3)
      {
      iav = appsdskl;
      cpntr = appsdisk;
      }
   else if (abbrev == 4)
      {
      iav = appcdskl;
      cpntr = appcdisk;
      }
   else if (abbrev == 5)
      {
      iav = appgdskl;
      cpntr = appgdisk;
      }
   else if (abbrev == 6)
      {
      iav = dflowdskl;
      cpntr = dflowdisk;
      }
   else if (abbrev == 7)
      {
      (void) strcpy(bigstr,PIPE.HOME);
      jj = PIPE.HOME_LEN;
      iav = jj + (int) strlen(PIPE.PROC);
      cpntr = PIPE.PROC;
      }

   (void) strcpy(&bigstr[jj],cpntr);
   (void) strcpy(&bigstr[iav],save);
   }
	

/*  set PROC.FNAME + get procedure code   */
 
(void) strncpy(PROC.FNAME,bigstr,167);
PROC.FNAME[167] = '\0';
if (MONIT.LEVEL <= 0) 
   {
   KIWORDS[OFF_PRSTAT] = 0;		/* clear PROGSTAT(1) + (4) */
   KIWORDS[OFF_PRSTAT+3] = 0;
   }
 

/* Statistics                                                     \\

StatProc();

\\                                                     Statistics */


MYBATCH(command,bigstr);
goto main_loop;

 
/*   .................................................................    */
 
/*   run given image in subprocess                                        */
 
/*   .................................................................    */
	
 
final_act:
stat = MID_CCLO(-1);				/* close all open catalogs  */
if (MONIT.FRAME_USED != ' ')		/* close all open images/tables */
   FRAMACC('X',KAUX.OUT,0,&iav);

if (firstchar != '$') 
   {
   KIWORDS[OFF_PRSTAT] = 999;			/* init to trouble  */
   iav = OFF_APPLIC;
   (void) strcpy(&KCWORDS[iav],"r ");
   iav += 2;
   (void) strncpy(&KCWORDS[iav],progpntr,58);	/* save prog_name in APPLIC */
   }

RUN_IT(progpntr);				/* run in subprocess  */
goto main_loop;					/*  and loop again */

/*

*/

do_list:
ERRORS.INDEX = 1;
ERRORS.SYS = build_prg(2,proc_flag);	/* build procedure from file */
if (ERRORS.SYS != 0) goto error_1;	/* + store new comnd into LINE.STR */
 
PARSE(1,0,0);				/* parse this input string again */
goto join_forces;


/*    come here to display error messages      */
 
error_1:	
if (ERRORS.INDEX == -1)
   PREPERR("MIDAS",LINE.STR," ");
else if (ERRORS.INDEX == -2)
   PREPERR("MIDAS",""," ");
else
   PREPERR("MIDAS",LINE.STR,TOKEN[ERRORS.INDEX].STR);
goto clean_up;

error_2:
PREPERR("OSY",""," ");


/*  now clean up any procedure executing  */

clean_up:
if ((ERRORS.SYS == 8) && (KIWORDS[OFF_ERROR+1] < 2))
   {				/* if ambiguous command and non-experts  */
   (void) strncpy(string,command,6);
   string[6] = '\0';
   m = CGN_INDEXC(string,' ');
   if (m > 0) string[m] = '\0';
   (void) SHOWCOM(-1,"A ",string);
   }

if (MONIT.LEVEL > 0) clear_batch();	/* clear all procedure flags */

goto main_loop;				/* look for next command   */
}
 
