/*===========================================================================
  Copyright (C) 1995-2010 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
===========================================================================*/

/*++++++++++++++++++ DRSWrapper module for Midas, RBEXEC.C  ++++++++++++++++++
.LANGUAGE  C
.IDENTIFICATION  Module RBEXEC.C
.AUTHOR  K. Banse                       ESO - Garching
.ENVIRONMENT  UNIX/Linux
.KEYWORDS
  ReductionBlock, parsing, MIDAS 
.COMMENTS
  uses the parsing routines of prototype RB Scheduler (converted to C) 

.VERSION  [1.00]  990705: created

 100616		last modif
---------------------------------------------------------------------------*/


#include <stdio.h>
#include <fileexts.h>
#include <fsydef.h>

#define READ            0

#define OK              0
#define BAD_INPUT       1
#define BAD_SYNTAX      3
#define BAD_CREATE      4

#define RB_DEFBAD       201
#define RB_RECIPBAD     202

#define LOG_WARNING     301
#define LOG_ERROR       302

#define  PARTYP_SOF     10
#define  PARTYP_FRAME   1
#define  PARTYP_STR     2
#define  PARTYP_FLOAT   3
#define  PARTYP_INT     4
#define  PARTYP_DBL     5

#define  MAX_TOKS       12



char  ddir[132], idir[132];

struct  RB_STRUCT
        {
        char  id_string[32];		/* RB id as string */
        char  start[32];		/* start, end time */
        char  end[32];
        char  instrum[64];		/* instrument of this RB */
        char  recipe[132];		/* name or Reduction Recipe */
        int   priority;
        int   pcount;
        };

struct  RB_STRUCT    RedBlock;

struct  RECIP_STRUCT
        {
        char  script[128];
        char  workdir[128];
        int   timeout;
        int   nopars;
        };

struct  RECIP_STRUCT    Recipe;

struct  PARM_STRUCT
        {
        char    generic[64];
        char    content[100];
        int     type;
        int     infoA;
        };

struct  PARM_STRUCT    Param[8];

/*

*/

#ifdef __STDC__
   void logMessage(int errflg, char *mess)
#else
   void logMessage(errflg,mess)
   int  errflg;
   char  *mess;
#endif

{
char  cbuf[200];


if (errflg == LOG_WARNING)
   (void) strcpy(cbuf,"WARNING: ");
else
   (void) strcpy(cbuf,"ERROR: ");

(void) strcat(cbuf,mess);
SCTPUT(cbuf);
}
/* 

*/

#ifdef __STDC__
   int parmfill(int no, char *cnt, int ty)
#else
   int parmfill(no,cnt,ty)
   int no, ty;
   char *cnt;
#endif

{
int  len;
register int  nr;

register char cc;



for (nr=0; nr<100; nr++)
   {
   cc = cnt[nr];
   if ((cc == ';') || (cc == ' ') || (cc == '\t'))
      {
      (void) strncpy(Param[no].content,cnt,nr);
      Param[no].content[nr] = '\0';
      len = nr - 1;
      goto cont_ok;
      }
   else if (cc == '\0')
      {
      len = CGN_COPY(Param[no].content,cnt);
      len--;
      goto cont_ok;
      }
   }
return (-2);                            /* indicate bad contents */

cont_ok:
Param[no].type = ty;
if ((Param[no].content[0] == '\'') && (Param[no].content[len] == '\''))
   {
   if (CGN_INDEXC(Param[no].content,' ') > 0)
      {
      Param[no].content[0] = Param[no].content[len] = '"';
      }
   else
      {
      Param[no].content[len] = '\0';
      CGN_strcpy(Param[no].content,&Param[no].content[1]);
      }
   }
return 0;
}
/*

*/

#ifdef __STDC__
   int translate(char *logdir, char *dir)
#else
   int translate(logdir,dir)
   char *logdir, *dir;
#endif

{
char  temp[132];


if (logdir[0] == '$')
   {
   int  m;

   m = CGN_INDEXC(logdir,'/');
   if (m > 0)
      {
      char  tempa[132];

      (void) strncpy(tempa,logdir,m);
      tempa[m] = '\0';
      if (osfphname(&tempa[1],temp) != 0) return (-1);

      (void) strcat(temp,logdir+m);
      }
   else
      {
      if (osfphname(logdir+1,temp) != 0) return (-1);
      }

   (void) strcpy(dir,temp);
   }

else
   (void) strcpy(dir,logdir);

return (0);
}

/*

*/

#ifdef __STDC__
   int parseRB(char *name,char **cptr, int *elno)
#else
   int parseRB(name,cptr,elno)
   char *name, **cptr;
   int  *elno;
#endif

{
int  m, k, status, reclen, mycount, notset, fid, flaggy;
register int  nr;

char  tmp[128], reco[120], label[80], sofname[100];



mycount = 0;
notset = 0;

fid = osaopen(name,0);                  /* open for reading */
if (fid < 0) return (BAD_INPUT);

status = BAD_SYNTAX;

m = CGN_JNDEXC(name,'/');		/* position at last '/' */
if (m > 0)
   {
   m++;
   (void) strcpy(RedBlock.id_string,&name[m]);
   }
else
   (void) strcpy(RedBlock.id_string,name);

m = CGN_JNDEXC(RedBlock.id_string,'.');		/* position at .rb */
RedBlock.id_string[m] = '\0';		/* def. ID = (pure) name of deffile */

sofname[0] = ' ';			/* show it's not filled yet */
flaggy = 0;                             /* set flow flag */


read_loop:				/* here we read the xxx.rb file */
reclen = osaread(fid,reco,116);

if (reclen < 0)
   {
   if (flaggy > 0) status = OK;
   goto close_it;			/* EOF encountered */
   }

for (nr=0; nr<reclen; nr++)             /* skip leading white space */
   {
   if ((reco[nr] != ' ') && (reco[nr] != '\t'))
      {
      if (nr > 0) reclen = CGN_COPY(reco,&reco[nr]);
      goto comment_check;
      }
   }


/* blank or empty line found */

if (flaggy > 1)				/* parameters are separated by at */
   {					/* least 1 blank line */
   if (notset == 0)
      {
      notset = 1;
      mycount ++;			/* one more parameter */
      }
   }
goto read_loop;                         /* blank or empty line */


comment_check:
if ( ((reco[0] == '/') && (reco[1] == '/')) ||
     (reco[0] == '#') )
   goto read_loop;			/* skip comment lines */


if (flaggy < 2)				/* we're in the header section */
   {
   flaggy = 1; 
   CGN_UPCOPY(label,reco,20);		/* eventual label -> upper case */

   if (strncmp(label,"IDLABEL:",8) == 0)
      {
      CGN_strcpy(reco,&reco[8]);
      nr = 0;
      while ((reco[nr] == ' ') || (reco[nr] == '\t')) nr++;
      if (reco[nr] == '\0') 
         {
         logMessage(LOG_ERROR,"invalid IDLABEL:");
         goto close_it;
         }

      (void) strcpy(RedBlock.id_string,&reco[nr]);
      goto read_loop;
      }

   if (strncmp(label,"INSTRUMENT:",11) == 0)
      {
      CGN_strcpy(reco,&reco[11]);
      nr = 0;
      while ((reco[nr] == ' ') || (reco[nr] == '\t')) nr++;
      if (reco[nr] == '\0')
         {
         logMessage(LOG_ERROR,"invalid INSTRUMENT:");
         goto close_it;
         }

      (void) strcpy(RedBlock.instrum,&reco[nr]);
      goto read_loop;
      }

   if (strncmp(label,"PRIORITY:",9) == 0)
      {
      float  rv;
      double dv;

      CGN_strcpy(reco,&reco[9]);
      nr = 0;
      while((reco[nr] == ' ') || (reco[nr] == '\t')) nr++;
      if (reco[nr] == '\0')
         {
         logMessage(LOG_ERROR,"invalid PRIORITY:");
         goto close_it;
         }

      m = CGN_CNVT(&reco[nr],1,1,&RedBlock.priority,&rv,&dv);
      if (m < 1) RedBlock.priority = 1;		/* lowest priority */
      goto read_loop;
      }

   if (strncmp(label,"RECIPE:",7) == 0)
      {
      CGN_strcpy(reco,&reco[7]);
      nr = 0;
      while((reco[nr] == ' ') || (reco[nr] == '\t')) nr++;
      if (reco[nr] == '\0')
         {
         logMessage(LOG_ERROR,"invalid RECIPE:");
         goto close_it;
         }

      (void) strcpy(RedBlock.recipe,&reco[nr]);
      goto read_loop;
      }

   mycount = 0;				/* no more labels */
   notset = 1;
   flaggy = 2;				/* move to parameter section */
   }

if (flaggy > 1)
   {
   notset = 0;

   /* check, if we have a Set of Frames */

   if (reco[0] == '{')				/* Yes */
      {
      int  sid, scount;

      scount = 0;
      if (sofname[0] == ' ')			/* init sofname */
         (void) strcpy(sofname,RedBlock.id_string);
      (void) strcat(sofname,"_sof");
      sid = osaopen(sofname,1);                 /* open for writing */
      if (sid < 0) 
         {
         status = BAD_CREATE;
         goto close_it;
         }

      set_read_loop:
      reclen = osaread(fid,reco,116);
      if (reclen < 0)
         {
         (void) osaclose(sid);
         (void) 
         logMessage(LOG_ERROR,"unfinished Set of Frames...");
         goto close_it;                         /* that's BAD... */
         }

      nr = 0;
      while((reco[nr] == ' ') || (reco[nr] == '\t')) nr++;
      if (reco[nr] == '\0') goto set_read_loop;
      
      if (nr > 0) CGN_strcpy(reco,&reco[nr]);
      if ( ((reco[0] == '/') && (reco[1] == '/')) ||
           (reco[0] == '#') )
         goto set_read_loop;                      /* skip comment lines */


      if (reco[0] == '}')
         {
         (void) osaclose(sid);
         if (scount > 0)
            {
            elno[mycount] = scount;
            (void) sprintf(cptr[mycount],"../%s",sofname);
            }
         }
      else
         {
         m = CGN_JNDEXC(reco,'/');
         if ((m >0) && (reco[0] == '$'))
            {  
            (void) strcpy(label,&reco[m]);	/* save remainder */
            (void) strncpy(tmp,reco,m);		/* copy first dir_spec */
            tmp[m] = '\0';
            translate(tmp,reco);
            (void) strcat(reco,label);		/* glue together again  */
            }
         k = (int)strlen(reco);
         reclen = osawrite(sid,reco,k);
         scount ++;
         goto set_read_loop;
         }
      }

   else						/* single frame or token */
      {
      m = CGN_JNDEXC(reco,'/');
      if ((m >0) && (reco[0] == '$'))
         {
         (void) strcpy(label,&reco[m]);		/* save remainder */
         (void) strncpy(tmp,reco,m);		/* copy first dir_spec */
         tmp[m] = '\0';
         translate(tmp,reco);
         (void) strcat(reco,label);		/* glue together again */
         }
      (void) strcpy(cptr[mycount],reco);
      }
   }

goto read_loop;


close_it:
if (fid > -1) (void) osaclose(fid);

RedBlock.pcount = mycount;
return (status);
}

/*

*/

#ifdef __STDC__
   int parseRecipe(int *elno,char **p)
#else
   int parseRecipe(elno,p)
   int  *elno;
   char **p;
#endif

{
int  m, reclen, rstat, ptype;
int   fid, flaggy;
register int  nr;

float  rv;

double dv;

char  fname[128], tmp[160], cbuf[160], defname[100];

void  setparm();



Recipe.nopars = 0;
Recipe.timeout = -1;
ptype = 0;

(void) strcpy(Recipe.script,"?");
(void) strcpy(Recipe.workdir,"?");


/* build up name of definition file*/

(void) strcpy(defname,ddir);
(void) strcat(defname,RedBlock.recipe);
(void) strcat(defname,".rrd");

fid = osaopen(defname,READ);
if (fid < 0)
   {
   (void) sprintf(tmp,"could not open definition file: %s",defname);
   logMessage(LOG_ERROR,tmp);

   return (-1);
   }

flaggy = 0;			/* set flow flag*/
rstat = 0;


read_loop:
reclen = osaread(fid,fname,120);
if (reclen < 0) goto close_it;


for (nr=0; nr<reclen; nr++)             /* skip leading white space*/
   {
   if ((fname[nr] != ' ') && (fname[nr] != '\t'))
      {
      if (nr > 0) reclen = CGN_COPY(fname,&fname[nr]);
      goto comment_check;
      }
   }
goto read_loop;                         /* blank or empty line*/


comment_check:
if ( ((fname[0] == '/') && (fname[1] == '/')) ||
     (fname[0] == '#') )
   goto read_loop;                      /* skip comment lines*/


/*
printf("Recipe.rrd record: %s\n",fname);
*/


if (flaggy == 0)
   {
   if (strncmp(fname,"result_frame",12) == 0)
      {
      if (strncmp(&fname[12],"_set",4) == 0)
         ptype = PARTYP_SOF;
      else
         ptype = PARTYP_FRAME;
      flaggy = 1;
      }
   goto read_loop;
   }

if (flaggy == 1)			/* process generic name*/
   {
   setparm(Recipe.nopars,fname);
   m = parmfill(Recipe.nopars,*p,ptype);
   if (m != 0)
      {
      rstat = -6;
      goto close_it;
      }
   p++;
   Recipe.nopars++;

   flaggy = 2;
   goto read_loop;
   }


if (flaggy == 2)
   {
   if (strncmp(fname,"input_frame",11) == 0)
      {
      if (strncmp(&fname[11],"_set",4) == 0)
         ptype = PARTYP_SOF;
      else
         ptype = PARTYP_FRAME;
      flaggy = 3;
      }
   goto read_loop;
   }

if (flaggy == 3)                        /* process generic name*/
   {
   setparm(Recipe.nopars,fname);
   m = parmfill(Recipe.nopars,*p,ptype);
   if (m != 0)
      {
      rstat = -6;
      goto close_it;
      }
   p++;
   Recipe.nopars++;

   flaggy = 4;
   goto read_loop;
   }


if (flaggy == 4)			/* ref frames may not be there...*/
   {

   if ( (strncmp(fname,"ref_image",9) == 0) ||
        (strncmp(fname,"ref_frame",9) == 0) )
      {
      if (strncmp(&fname[9],"_set",4) == 0)
         ptype = PARTYP_SOF;
      else
         ptype = PARTYP_FRAME;
      flaggy = 5;
      goto read_loop;
      }
   }

if (flaggy == 5)                        /* process generic name*/
   {
   setparm(Recipe.nopars,fname);
   m = parmfill(Recipe.nopars,*p,ptype);
   if (m != 0)
      {
      rstat = -6;
      goto close_it;
      }
   p++;
   Recipe.nopars++;

   flaggy = 6;
   goto read_loop;
   }


if ((flaggy > 3) && (flaggy < 7))
   {
   if (strncmp(fname,"parameter:",10) == 0) 
      flaggy = 8;
   else if (strncmp(fname,"parameters:",11) == 0) 
      flaggy = 8;
   else if (strncmp(fname,"variable:",9) == 0)
      flaggy = 9;
   else if (strncmp(fname,"variables:",10) == 0)
      flaggy = 9;
   goto read_loop;
   }

if (flaggy == 8)
   {
   if (strncmp(fname,"variable:",9) == 0)
      flaggy = 9;
   else if (strncmp(fname,"variables:",10) == 0)
      flaggy = 9;
   else
      {
      int  iav;

      for (m=0; m<reclen; m++)
         {
         if (fname[m] == '\t') fname[m] = ' ';
         }

      m = CGN_INDEXC(fname,' ');
      if (m < 1)
         {
         rstat = -3;
         goto close_it;
         }

      fname[m] = '\0';
      setparm(Recipe.nopars,fname);
      fname[m] = ' ';

      m = CGN_INDEXS(fname,"type=");
      if (m < 2)
         {
         rstat = -4;
         goto close_it;
         }
      (void) strncpy(cbuf,&fname[m+5],3);
      if (cbuf[0] == 's')
         ptype = PARTYP_STR;
      else if (cbuf[0] == 'f')
         ptype = PARTYP_FLOAT;
      else if (cbuf[0] == 'd')
         ptype = PARTYP_DBL;
      else
         ptype = PARTYP_INT;

      if (**p == '?')
         {
         m = CGN_INDEXS(fname,"default=");
         if (m > 0)
            {
            m += 8;					/* point to data*/
            iav = parmfill(Recipe.nopars,&fname[m],ptype);
            }
         else
            {
            rstat = -5;
            goto close_it;
            }
         }
      else
         iav = parmfill(Recipe.nopars,*p,ptype);

      if (iav != 0)
         {
         rstat = -6;
         goto close_it;
         }
      p++;
      Recipe.nopars++;
      }
   goto read_loop;
   }
    
if (flaggy == 9)
   {
   if (strncmp(fname,"MAX_TIME",8) == 0)
      {
      int   timeref=-1;
      char  time_ref[32];

      m = CGN_INDEXS(&fname[8],"default=");
      if (m < 0)
         {
         rstat = -5;
         goto close_it;
         }

      m += 8;			/* we started at index 8 ...*/
      (void) strncpy(cbuf,&fname[m+8],32);
      if ((cbuf[0] == '-') && (cbuf[1] == '1'))
         {
         m = 2;
         goto convert_time;
         }
      cbuf[32] = '\0';
      for (m=0; m<33; m++)
         {
         if ((cbuf[m] <'0') || (cbuf[m] > '9'))		/* `\0' is caught here*/
            {
            if (cbuf[m] == '*')
               {					/* isolate reference*/
               reclen = CGN_COPY(time_ref,&cbuf[m+1]);
               for (nr=0; nr<reclen; nr++)
                  {
                  if ((time_ref[nr] == ' ') || (time_ref[nr] == '\t')
                      ||
                      (time_ref[nr] == ';'))
                     {
                     time_ref[nr] = '\0';
                     break;
                     }
                  }
               for (nr=0; nr<Recipe.nopars; nr++)
                  {
                  if (strcmp(Param[nr].generic,time_ref) == 0)
                     {
                     timeref = nr;
                     goto convert_time;
                     }
                  }
               rstat = -2;
               goto close_it;
               }

      convert_time:
            cbuf[m] = '\0';
            break;
            }
         }

      if (CGN_CNVT(cbuf,1,1,&Recipe.timeout,&rv,&dv) != 1)
         {
         rstat = -2;
         goto close_it;
         }
      if (timeref > -1) Recipe.timeout *= elno[timeref];
      }

   else if (strncmp(fname,"WORK_DIR",8) == 0)
      {
      m = CGN_INDEXS(fname,"default=");
      if (m > 0)
         {
         (void) strcpy(cbuf,&fname[m+8]);
         for (nr=0; nr<128; nr++)
            {
            if ( (cbuf[nr] == '\t') || (cbuf[nr] == ' ')
                || (cbuf[nr] == '\0') )
               {
               cbuf[nr] = '\0';
               (void) strcpy(Recipe.workdir,cbuf);
               break;
               }
            }
         }
      }
   }
goto read_loop;


close_it:
(void) osaclose(fid);


if (rstat != 0)
   {
   (void) sprintf(tmp,"Processing definition file: %s ...",defname);
   SCTPUT(tmp);
   switch (rstat)
      {
     case -2:
      (void) sprintf(tmp,"default for MAX_TIME (%s) invalid",cbuf);
      break;
     case -3:
      (void) sprintf(tmp,"missing parameter: %s",fname); 
      break;
     case -4:
      (void) sprintf(tmp,"missing type: %s",fname); 
      break;
     case -5:
      (void) sprintf(tmp,"missing default: %s",fname); 
      break;
     default:
      (void) sprintf(tmp,"RB param_count (= %d) < Recipe count (= %d)\n",
                     RedBlock.pcount,Recipe.nopars);
      }
   logMessage(LOG_ERROR,tmp);
   }

return rstat;
}

/* 

*/

#ifdef __STDC__
   void setparm(int no, char *name)
#else
   void setparm(no,name)
   int  no;
   char *name;
#endif

{
register int nr;

register char  cc;



Param[no].generic[0] = '\0';
Param[no].content[0] = '\0';

Param[no].type = 0;
Param[no].infoA = -1;                     /* init failure... */


for (nr=0; nr<64; nr++)                 /* copy max. 64 chars. */
   {
   cc = name[nr];
   if ((cc == ';') || (cc == ' ') || (cc == '\t'))
      {
      (void) strncpy(Param[no].generic,name,nr);
      Param[no].generic[nr] = '\0';
      goto name_ok;
      }
   else if (cc == '\0')
      {
      (void) strcpy(Param[no].generic,name);
      goto name_ok;
      }
   }
return;


name_ok:
Param[no].infoA = 0;
}
/* 

*/

#ifdef __STDC__
   int  swparams(int from, int to)
#else
   int  swparams(from,to)
   int  from, to;
#endif

{
char   tgen[64], tcont[100];

int    ttype, tinfoA;



if ((from < 0) || (from > 7) || (to < 0) || (to > 7)) return (-1);
if (from == to) return 0;				/* nothing to do...*/


(void) strcpy(tgen,Param[to].generic);
(void) strcpy(Param[to].generic,Param[from].generic);
(void) strcpy(Param[from].generic,tgen);

(void) strcpy(tcont,Param[to].content);
(void) strcpy(Param[to].content,Param[from].content);
(void) strcpy(Param[from].content,tcont);

ttype = Param[to].type;
Param[to].type = Param[from].type;
Param[from].type = ttype;

tinfoA = Param[to].infoA;
Param[to].infoA = Param[from].infoA;
Param[from].infoA = tinfoA;

return 0;
}

/*

*/

#ifdef __STDC__
   int checkRecImp(char *recname, char *script)
#else
   int checkRecImp(recname,script)
   char *recname, *script;
#endif

{
int   rstat, fid, reclen, flaggy, nr, m;

char  fname[124], impname[132], cbuf[80], tmp[160];



rstat = 0;
script[0] = '\0';


/* build up name of implementation file */

(void) strcpy(impname,idir);
(void) strcat(impname,recname);
(void) strcat(impname,".rri");

fid = osaopen(impname,READ); 

if (fid < 0) 
   {
   (void) sprintf(tmp,"could not open implementation file: %s",impname);
   logMessage(LOG_ERROR,tmp);
   return (-1);
   }

flaggy = 0;				/* set flow flag */


read_loop:
reclen = osaread(fid,fname,120);
if (reclen < 0)	goto close_it;		/* EOF */


for (nr=0; nr<reclen; nr++)		/* skip leading white space */
   {
   if ((fname[nr] != ' ') && (fname[nr] != '\t'))
      {
      if (nr > 0) reclen = CGN_COPY(fname,&fname[nr]);
      goto comment_check;
      }
   }
goto read_loop;				/* blank or empty line */


comment_check:
if ( ((fname[0] == '/') && (fname[1] == '/')) ||
     (fname[0] == '#') )
   goto read_loop;			/* skip comment lines */


if (flaggy == 0)
   {
   if (strncmp(fname,"drs",3) == 0)		/* work on `drs:' */
      {
      m = CGN_INDEXC(fname,' ') + 1;		/* move to DRS name */
      (void) CGN_UPCOPY(cbuf,&fname[m],20);
      if (strcmp(cbuf,"MIDAS") != 0)		/* and compare */
         {
         rstat = 11;
         goto close_it;
         }
      flaggy = 1;
      }
   goto read_loop; 
   }

else if (flaggy == 1)				/* check for `{' */
   {
   if (fname[0] == '{') flaggy = 2;
   goto read_loop;
   }

else if (flaggy == 2)
   {
   if (strncmp(fname,"version:",8) == 0)
      flaggy = 4;
   else
      flaggy = 3;		/* actual version must be on next line */
   goto read_loop;
   }

else if (flaggy == 3)
   {
   if (strncmp(fname,"version:",8) != 0)
      {
      (void) strcpy(cbuf,fname);
      rstat = 12;
      goto close_it;
      }
   flaggy = 4;
   goto read_loop;
   }

else if (flaggy == 4)
   {
   if (strncmp(fname,"procedure:",10) == 0)
      {						/* work on `procedure:' */
      for (nr=10; nr<reclen; nr++)
         {
         if ((fname[nr] != ' ') && (fname[nr] != '\t'))
            {
            (void) strcpy(script,&fname[nr]);
            flaggy = 6;
            goto read_loop;
            }
         }
      flaggy = 5;
      goto read_loop;
      }
   }

else if (flaggy == 5)
   {
   if ((strncmp(fname,"mapping:",8) == 0) || (fname[0] == '}'))
      {
      rstat = 13;
      goto close_it;
      }
   else
      (void) strcpy(script,fname);
   flaggy = 6;
   goto read_loop;
   }

else if (flaggy == 6)
   {
   if (strncmp(fname,"mapping:",8) == 0) 
   flaggy = 7;
   goto read_loop;
   }

else if (flaggy == 7)
   {
   if ((m = CGN_INDEXS(fname,"->")) > 0)
      {
      int  j, ppcount;


      fname[m] = '\0';
      rstat = 19;

      for (nr=m-1; nr>0; nr--)
         {
         if ((fname[nr] != ' ') && (fname[nr] != '\t'))
            {
            fname[nr+1] = '\0';
            break;
            }
         }
      for (nr=m+2; ; nr++)
         {
         if (fname[nr] == '\0') goto close_it;

         if ((fname[nr] != ' ') && (fname[nr] != '\t'))
            {
            ppcount = CGN_INDEXC("12345678",fname[nr+1]);
            if (ppcount > -1)
               break;
            else
               goto close_it;
            }
         }

      for (nr=0; nr<Recipe.nopars; nr++)
         {
         if (strcmp(fname,Param[nr].generic) == 0)
            {
            if (nr != ppcount)
               {
               j = swparams(nr,ppcount);	/* P.nr <-> P.ppcount */
               if (j != 0) break;
               }
            rstat = 0;
            goto read_loop;
            }
         }
      goto close_it;
      }

   else
      goto read_loop;			/* ignore that line */
   }

goto read_loop;				/* skip all other lines */


close_it:
(void) osaclose(fid);

if (flaggy < 7) rstat = 22;


if (rstat != 0)				/* something wrong */
   {
   (void) sprintf(tmp,"Processing implementation file: %s ...",impname);
   SCTPUT(tmp);
   if (rstat == 11)
      (void) sprintf(tmp,"required DRS `%s' not installed",cbuf);
   else if (rstat == 12)
      (void) sprintf(tmp,"required DRS version `%s' not installed",cbuf);
   else if (rstat == 22)
      (void) sprintf(tmp,"some section is missing");
   else if (rstat == 13)
      (void) sprintf(tmp,"the DRS script is missing");
   else if (rstat == 19)
      (void) sprintf(tmp,"invalid var. -> param. mapping: %s",fname);
   else 
      (void) sprintf(tmp,"invalid syntax (internal flag = %d)",flaggy);
   logMessage(LOG_ERROR,tmp);
   }

else
   {
   m = CGN_JNDEXC(script,'/');
   if (m > -1)
      {
      if ((m == 1) && (script[0] == '.'))		/* ./file */
         CGN_strcpy(script,&script[2]);
      else
         {
         (void) strcpy(cbuf,&script[m]);		/* save /file_name */
         (void) strncpy(tmp,script,m);		/* copy directory */
         tmp[m] = '\0';
         translate(tmp,script);
         (void) strcat(script,cbuf);
         }
      }
   else
      {
      (void) strcpy(tmp,idir);		/* use CalibDB */
      (void) strcat(tmp,script);
      (void) strcpy(script,tmp);
      }
   }

return rstat;
}
/*

*/

int main()

{
int  status, iav, nr, m, prflag;
int  elno[8];                        /* no. of elements in a set_of_frame */

char  RBdeffile[132];                     /* name of RB definition file */
char  work[MAX_TOKS*102];
char  cbuff[200], tmp[200], curdir[100], *tptr;
char  calibd[104], calibi[104];
char  *cptr[MAX_TOKS];
char  comline[100], midasparm[8];



(void) SCSPRO("RBexec");

(void) SCKRDI("INPUTI",1,1,&m,&prflag,&m,&m);

(void) SCKGETC("IN_A",1,100,&m,cbuff);
(void) SCKGETC("CALIBDB_REC",1,100,&m,calibi);
if (calibi[m-1] != FSY_DIREND)			/* make sure we end with '/' */
   {
   calibi[m++] = FSY_DIREND;
   calibi[m] = '\0';
   }
(void) SCKGETC("CALIBDB_RUL",1,100,&m,calibd);
if (calibd[m-1] != FSY_DIREND)
   {
   calibd[m++] = FSY_DIREND;
   calibd[m] = '\0';
   }

m = 0;
for (nr=0; nr<MAX_TOKS; nr++) 
   {
   cptr[nr] = &work[m];
   tptr = cptr[nr];
   *tptr++ = '?';
   *tptr = '\0';
   m += 100;
   }


/* initialize variables */

for (nr=0; nr<8; nr++) elno[nr] = 0;

RedBlock.priority = 1;
(void) strcpy(RedBlock.instrum,"? ");
(void) strcpy(RBdeffile,"? ");

(void) OSY_ASCTIM(RedBlock.start);               /* record time of creation */
(void) strcpy(RedBlock.end,"?");

(void) strcpy(RedBlock.id_string,"? ");
(void) strcpy(RedBlock.recipe,"? ");


/* process RB deffile spec to get always full file path */

m = CGN_JNDEXC(cbuff,'/');
if (m > 0)
   {
   if (*cbuff == '$') 
      {
      (void) strncpy(tmp,cbuff,m);		/* isolate dir_specs */
      tmp[m] = '\0';
      translate(tmp,RBdeffile);
      nr = (int) strlen(RBdeffile);
      (void) strcpy(&RBdeffile[nr],&cbuff[m]);
      goto workon_RB;
      }
   else
      {
      if (*cbuff != '.') 			/* not ./abc => full spec */
         {
         (void) strcpy(RBdeffile,cbuff);
         goto workon_RB;
         }
      else if (cbuff[1] == '.')			/* we have ../abc */
         iav = 3;
      else
         iav = 2;				/* we have  ./abc */
      }
   }
else
   iav = 0;

 
(void) osfdelete("Mid_Pipe");			/* get current directory */
(void) oshcmd("echo `pwd` > Mid_Pipe",(char *) 0,(char *) 0,(char *) 0);

m = osaopen("Mid_Pipe",0);
if (m < 0)
   {
   (void) sprintf(tmp,"could not get current directory...");
   logMessage(LOG_ERROR,tmp);
   status = RB_DEFBAD;				/* so the RB will be deleted */
   goto eof;
   }
(void) osaread(m,curdir,98);			/* that's where we are now */
(void) osaclose(m);

m = (int) strlen(curdir);
if (curdir[m-1] != FSY_DIREND)
   {
   curdir[m++] = FSY_DIREND;
   curdir[m] = '\0';
   }
if (iav == 3)				/* find parent directory */
   {
   for (nr=m-2; nr>0; nr--)
      {
      if (curdir[nr] == FSY_DIREND)
         {
         curdir[nr+1] = '\0';
         break;
         }
      }
   }

(void) strcpy(RBdeffile,curdir);
(void) strcat(RBdeffile,&cbuff[iav]);


workon_RB:
m = (int) strlen(RBdeffile);			/* ensure `.rb' in the end.. */
if (strcmp(&RBdeffile[m-3],".rb") != 0)
   (void) strcat(RBdeffile,".rb");


/* parse RB definition file */

status = parseRB(RBdeffile,cptr,elno);
if (status != OK)
   {
   if (status == BAD_INPUT)
      (void) sprintf(tmp,"could not open RB definition file %s",cbuff);
   else if (status == BAD_SYNTAX)
      (void) sprintf(tmp,"bad syntax in RB definition file %s",cbuff);
   else 
      (void) sprintf(tmp,"could not create SetOfFrames file");
   logMessage(LOG_ERROR,tmp);
   
   status = RB_DEFBAD;			/* so the RB will be deleted */
   goto eof;
   }


if (prflag == 1)
   {
   printf(
   "RB contents:\nID = %s\ninstrument = %s\nrecipe = %s\nprio = %d\n",
   RedBlock.id_string,RedBlock.instrum,RedBlock.recipe,RedBlock.priority);
   printf("no. of params in RBdeffile = %d\n",RedBlock.pcount);
   for (nr=0; nr < RedBlock.pcount; nr++)
      {
      printf("RB-par%d = %s\n",nr,cptr[nr]);
      }
   printf("\n");
   }

if ((RedBlock.priority < 1) || (RedBlock.priority > 99))
   {
   (void) sprintf(tmp,"bad priority of RB (=%d), set to 1",RedBlock.priority);
   RedBlock.priority = 1;
   logMessage(LOG_WARNING,tmp);
   }

if (*RedBlock.instrum == '?')			/* check instrument */
   {
   (void) strcpy(RedBlock.instrum,"FORS1");
   (void) sprintf(tmp,"label INSTRUMENT: missing, defaulted to FORS1");
   logMessage(LOG_WARNING,tmp);
   }
else
   {
   CGN_UPSTR(RedBlock.instrum);		/* CalibDB wants instrument UpperCase */
   if (strcmp(RedBlock.instrum,"FORS") == 0)
      (void) strcpy(RedBlock.instrum,"FORS1");		/* FORS -> FORS1 */
   }

   

/*  extract directory for *.rrd files (ddir)
    and               for *.rri files (idir)   */

(void) strcpy(cbuff,RedBlock.recipe);
m = CGN_JNDEXC(cbuff,'/');
if (m < 0)				/* use pipeline specified directories */
   {	
   m = CGN_COPY(tmp,cbuff);
   CGN_LOWSTR(tmp);
   (void) strcpy(ddir,calibd);
   (void) strcpy(idir,calibi);
   }
else   
   {						/* use specific directory */
   (void) strncpy(tmp,cbuff,m);		/* isolate dir_specs */
   tmp[m] = '\0';
   translate(tmp,ddir);
   nr = (int) strlen(ddir);
   ddir[nr++] = '/';
   ddir[nr] = '\0';
   (void) strcpy(idir,ddir);
   CGN_strcpy(cbuff,&cbuff[m+1]);		/* skip dir_specs */
   }
CGN_LOWCOPY(RedBlock.recipe,cbuff,132);		/* name of recipe only */



/* parse Recipe definition file */

status = parseRecipe(elno,cptr);
if (status != OK)
   {
   status = RB_RECIPBAD;
   goto eof;
   }

if (RedBlock.pcount > Recipe.nopars) logMessage(LOG_WARNING,
             "RB has more parameters than Recipe definition file...");

RedBlock.pcount = Recipe.nopars;
for (nr=0; nr<RedBlock.pcount; nr++)
   Param[nr].infoA = elno[nr];		/* no. of elements in SoF */

if (prflag == 1)
   {
   for (nr=0; nr<RedBlock.pcount; nr++)
      {
      printf
      ("Parameter nr %d:  generic name: %s\ncontents: %s\n  type %d, no. of frames %d\n",
      nr+1,Param[nr].generic,Param[nr].content,Param[nr].type,Param[nr].infoA);
      }
 
   printf("ddir = %s\nidir = %s\nrecipe = %s\n",ddir,idir,RedBlock.recipe);
   }

status = checkRecImp(RedBlock.recipe,Recipe.script);
if (status != OK) goto eof;

if (prflag == 1)
   (void) printf("DRS script used: %s\n",Recipe.script);


/* prepare Midas commands */

iav = 0;
nr = (int)strlen(RBdeffile) + 1;
if (nr > 100) nr = 100;
(void) SCKWRC("COMMAND1",1,RBdeffile,1,nr,&iav);
nr = (int)strlen(RedBlock.recipe) + 1;
if (nr > 100) nr = 100;
(void) SCKWRC("COMMAND2",1,RedBlock.recipe,1,nr,&iav);
(void) sprintf(comline,"%s %d",RedBlock.instrum,Recipe.timeout);
nr = (int)strlen(comline) + 1;
if (nr > 100) nr = 100;
(void) SCKWRC("COMMAND3",1,comline,1,nr,&iav);

(void) SCKWRC("RBS_RECIPE",1,Recipe.script,1,(int)strlen(Recipe.script),&iav);

for (nr=0; nr<Recipe.nopars; nr++)            /* get parameters */
   {
   (void) sprintf(midasparm,"RBS_P%d",(nr+1));
   m = (int)strlen(Param[nr].content);
   if ((m < 1) || (m > 100))
      {
      (void) 
      sprintf(comline,"Param %d has invalid length (= %d) - skipped...",nr,m);
      SCTPUT(comline);
      }
   else
      (void) SCKWRC(midasparm,1,Param[nr].content,1,m,&iav);
   }
(void) SCKWRI("RBS_PCOUNT",&Recipe.nopars,1,1,&iav);


eof:
(void) SCKWRI("OUTPUTI",&status,1,1,&iav);

if (status != 0)
   {
   (void) sprintf(comline,"RB %s could not be wrapped for DRS...",RBdeffile);
   SCTPUT(comline);
   }


return SCSEPI();
}


