/* @(#)prepk.c 17.1.1.1 (ESO-DMD) 01/25/02 17:37:41 */ /*=========================================================================== Copyright (C) 1995 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 ===========================================================================*/ /*+++++++++++++++++++ MIDAS monitor routines PREPK +++++++++++++++++++++++++ .LANGUAGE C .IDENTIFICATION Module PREPK .AUTHOR K. Banse ESO - Garching .KEYWORDS MIDAS monitor .COMMENTS holds DEFIPAR, TYPE_CHECK, OSYCOMP, DEBUGGY, Contexter .VERSION [1.00] 870724: built from FORTRAN version 020111 last modif .DOC handling of Pipeline contexts in Midas (Contexter) Since 000919 the following scheme concerning the instrument pipelines is implemented in Midas: a) the @p command looks for procedures in: $PIPE_HOME//proc b) Midas> run PIPE_EXE:module will look for module.exe in: $PIPE_HOME//exec c) Midas will (besides MID_CONTEXT, MID_WORK, current direc) also search for contexts in: $PIPE_HOME//context The env. variable PIPE_HOME is set by the user beforehand. If not set, Midas defaults it to /midas//pipeline. a), b), c) will be updated each time the Midas command Midas> set/context is executed - that happens when a RB with the line INSTRUMENT: is executed. may be one of: fors1, fors2, uves Up to version 01FEB there was a problem with PIPE_HOME if given in the form "abc/.../" (i.e. with closing "/") - it had to be given as "abc/...", that is fixed since 01SEP. Internally, in `prepx.c' the contents of the env. var. PIPE_HOME is saved to PIPE.HOME (always with closing "/"). In Contexter() the following variables are set as: PIPE.INSTRUM = PIPE.CONT = /context/ PIPE.EXE = /exec/ PIPE.PROC = /proc/ Finally keyword PIPE_PROC is set to PIPE.HOME // PIPE.PROC for the "@p" command. -------------------------------------------------------------------------*/ #include #include #include #include #include #include #include /* */ int DEFIPAR() /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE handle all tasks related to DEFINE/PARAMETER ... .ALGORITHM use all exisiting facilities .RETURNS return status: 0 = o.k. ------------------------------------------------------------------*/ { register int nr; int ikey, inaux; int ioff, k, stat, parno; float fkey; double dkey, dval[2]; char save; static char pi[8] = {'1','2','3','4','5','6','7','8'}; static char shtype[] = {"NITF"}; static char *oktype[] = {"Number","Image","Table","FitFile"}; /* DEFINE/PAR Pi default type/option prompt_str limits */ save = TOKEN[1].STR[1]; for (nr=0; nr<8; nr++) { if (save == pi[nr]) { parno = nr + 1; ioff = MONIT.POFF[nr]; goto go_on; } } return (5); /* invalid Pi given ... */ /* if no parameter passed, we have to do something */ go_on: /* in PROMPT mode, we ask for it and show the current defaults (if any) */ if ( (KCWORDS[ioff] == '?') && (KCWORDS[ioff+1] == ' ') ) { if ( (KIWORDS[OFF_ERROR+4] == 1) && (MONIT.LEVEL == 1) ) { if (TOKEN[4].STR[0] == '"') { (void) strcpy(TOKEN[4].STR,&TOKEN[4].STR[1]); k = TOKEN[4].LEN - 2; } else k = TOKEN[4].LEN; (void) memcpy(&TOKEN[4].STR[k]," (default: ",(size_t)11); k += 11; (void) memcpy(&TOKEN[4].STR[k],TOKEN[2].STR,(size_t)TOKEN[2].LEN); k += TOKEN[2].LEN; TOKEN[4].STR[k++] = ')'; TOKEN[4].STR[k++] = ' '; TOKEN[4].STR[k] = '\0'; TOKEN[4].LEN = k; DO_KEYS('I',TOKEN[4].STR); /* prompt for input */ inaux = KIWORDS[OFF_AUX+6]; if (inaux < 1) { if ( (TOKEN[2].STR[0] == '?') && (TOKEN[2].LEN == 1) ) { stat = 31; goto badreturn; } } else goto sect_29000; /* continue like the others */ } /* if not in PROMPT mode, we only have to ask if no defaults given */ else if ( (TOKEN[2].STR[0] == '?') && (TOKEN[2].LEN == 1) ) { DO_KEYS('I',TOKEN[4].STR); /* prompt for input */ inaux = KIWORDS[OFF_AUX+6]; if (inaux < 1) { stat = 31; goto badreturn; /* nothing entered */ } sect_29000: (void) strncpy(TOKEN[2].STR,&KCWORDS[ioff],(size_t)inaux); KCWORDS[ioff] = '?'; KCWORDS[ioff+1] = ' '; /* will be filled via DEFAULTS */ TOKEN[2].LEN = inaux; } TOKEN[2].STR[TOKEN[2].LEN] = '\0'; stat = COMPILE(6,&parno); /* do the default business */ if (stat != 0) goto badreturn; } stat = TYPE_CHECK(parno); /* now do the type checking */ if (stat != 0) { if (stat != 30) goto badreturn; save = CGN_UPPER(TOKEN[3].STR[0]); for (nr=0; nr<4; nr++) { if (save == shtype[nr]) break; } (void) sprintf(KAUX.OUT,"parameter %d has invalid type - should be %s", parno,oktype[nr]); SCTPUT(KAUX.OUT); DO_KEYS('I',TOKEN[4].STR); /* prompt for new input */ inaux = KIWORDS[OFF_AUX+6]; if (inaux < 1) { stat = 31; goto badreturn; /* nothing entered */ } (void) strncpy(TOKEN[2].STR,&KCWORDS[ioff],(size_t)inaux); KCWORDS[ioff] = '?'; KCWORDS[ioff+1] = ' '; /* will be filled via DEFAULTS */ TOKEN[2].LEN = inaux; TOKEN[2].STR[inaux] = '\0'; stat = COMPILE(6,&parno); /* do the default business */ if (stat != 0) goto badreturn; stat = TYPE_CHECK(parno); /* now do the type checking */ if (stat != 0) goto badreturn; } if (TOKEN[4].STR[0] == '"') /* check correct prompt string */ { k = TOKEN[4].LEN - 1; if ((TOKEN[4].STR[k] != '"') && (MONIT.COUNT > 5)) { stat = 5; goto badreturn; } } else if (MONIT.COUNT > 6) { stat = 5; goto badreturn; } if (TOKEN[5].STR[0] != '?') /* do the limit checks, if required */ { int jj; once_more: for (nr=ioff; nr') /* <,> is always o.k. */ return (0); k = CGN_CNVT(&TOKEN[5].STR[2],4,1,&ikey,&fkey,&dval[1]); if (k == 1) { if (dkey <= dval[1]) return (0); else goto try_again; } } else if ( (TOKEN[5].STR[jj] == '>') && (TOKEN[5].STR[jj-1] == ',') ) { k = CGN_CNVT(TOKEN[5].STR,4,1,&ikey,&fkey,dval); if (k == 1) { if (dkey >= dval[0]) return (0); else goto try_again; } } else { k = CGN_CNVT(TOKEN[5].STR,4,2,&ikey,&fkey,dval); if (k == 2) { if (dval[0] <= dval[1]) { if ( (dkey >= dval[0]) && (dkey <= dval[1]) ) return (0); else goto try_again; } } } stat = 5; /* invalid limits */ ERRORS.INDEX = 5; goto badreturn; /* display error message and prompt for input if TOKEN[6].STR = '?' */ try_again: (void) sprintf(KAUX.OUT, "parameter %d is out of range - legal limits are %s", parno,TOKEN[5].STR); SCTPUT(KAUX.OUT); if (KIWORDS[OFF_MODE+2] != 0) /* no retry in batch mode */ TOKEN[6].STR[0] = 'x'; if (TOKEN[6].STR[0] == '?' ) { TOKEN[6].STR[0] = 'x'; /* so we only do it once */ DO_KEYS('I',TOKEN[4].STR); /* prompt for new input */ inaux = KIWORDS[OFF_AUX+6]; if (inaux < 1) { stat = 31; goto badreturn; /* nothing entered */ } (void) strncpy(TOKEN[2].STR,&KCWORDS[ioff],(size_t)inaux); KCWORDS[ioff] = '?'; KCWORDS[ioff+1] = ' '; /* will be filled via DEFAULTS */ TOKEN[2].LEN = inaux; TOKEN[2].STR[inaux] = '\0'; stat = COMPILE(6,&parno); /* do the default business */ if (stat != 0) goto badreturn; stat = TYPE_CHECK(parno); /* also do type checking again */ if (stat != 0) goto badreturn; goto once_more; /* try one more time */ } stat = 16; /* out of bounds... */ goto badreturn; } return (0); /* everything o.k. */ badreturn: (void) sprintf(KAUX.OUT,"In Midas procedure: %s",PROC.FNAME); SCTPUT(KAUX.OUT); KIWORDS[OFF_PRSTAT] = parno - 1; KIWORDS[OFF_PRSTAT+1] = 10; /* show error from monitor */ return (stat); } /* */ int TYPE_CHECK(parno) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE check type of keys P1 or P2,...,P8 set key PARSTAT(i) to 1 or 0, if match or not .ALGORITHM types to check are: N(umber), I(mage), M(ask) or T(able) utilities CGN_NUMBER and CGN_singleframe are used .RETURN status = 0 o.k, else problems... -------------------------------------------------------------------*/ int parno /* IN: parameter no. (1,2,..,8) */; { int lparm, offset, off2, n, mm, kl, typno; char savdef[MAX_TOKEN+2], *savpntr, name[MAX_TOKEN+2], tok1; lparm = KIWORDS[OFF_PCOUNT+parno]; /* parno is in [1,8] */ n = parno - 1; /* this is the parameter no. - 1 */ off2 = OFF_PSTAT + n; /* offset of key PARSTAT(n) */ KIWORDS[off2] = 1; /* default to correct type */ tok1 = TOKEN[3].STR[0]; /* get ?, C, N, I, M or T */ if ( (tok1 >= 'a') && (tok1 <= 'z') ) /* force to upper case */ tok1 += ('A' - 'a'); if ((tok1 == '?') || (tok1 == 'C')) /* default or */ return (0); /* character strings may be anything */ offset = MONIT.POFF[n]; /* offset of key Pn */ (void) strncpy(savdef,&KCWORDS[offset],(size_t)lparm); savpntr = savdef; /* default to 1. element */ n = lparm; /* avoid updating of lparm */ if ( (*savpntr == '"') && /* take care of " ... " */ (tok1 != 'I') && (tok1 != 'T') && (tok1 != 'F') ) { savpntr ++; n --; } savdef[n] = '\0'; if ((*savpntr == '+') && (*(savpntr+1) == '\0')) return (0); /* no checking for "+" */ if (tok1 == 'N') { if (CGN_NUMBER(savpntr) == 0) /* if not a number... */ { typno = 5; KIWORDS[off2] = 0; /* turn PARSTAT(n) bad */ } } else { if (tok1 == 'I') typno = F_IMA_TYPE; else if (tok1 == 'T') typno = F_TBL_TYPE; else if (tok1 == 'F') typno = F_FIT_TYPE; else return (5); /* undefined type ... */ mm = CGN_singleframe(savpntr,typno,name); /* try to translate name */ if (mm == 1) { TOKEN[2].LEN = CGN_COPY(TOKEN[2].STR,name); n = COMPILE(6,&parno); /* update the default */ if (n != 0) return (n); kl = TOKEN[2].LEN; if (kl < lparm) /* do we have to clear? */ CGN_FILL(KCWORDS+offset,' ',lparm); else if (kl > MAX_TOKEN) kl = MAX_TOKEN; /* at most MAX_TOKEN chars. */ (void) strncpy(&KCWORDS[offset],name,kl); /* update key Pn */ KIWORDS[OFF_PCOUNT+parno] = kl; /* and PCOUNT */ } } /* now check via key PARSTAT, if wrong typed parameter entered */ if ((MONIT.LEVEL > 0) && (KIWORDS[off2] != 1)) { kl = CGN_INDEXC(TOKEN[3].STR,'/'); /* first look for /CONT */ if (kl > 0) { tok1 = TOKEN[3].STR[++kl]; if ((tok1 == 'C') || (tok1 == 'c')) return (0); /* it's o.k. */ } return (30); /* type bad */ } else return (0); } /* */ int OSYCOMP(comstring) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE translate commands for different host systems and translate logical names .ALGORITHM use translation table in osycoms.h .RETURNS status: 0 = o.k. : 1 = o.k., but a noop command : else not a recognized host command ----------------------------------------------------------------------*/ char *comstring; /* OUT: cleaned host command line */ { register int nr, mr; int clen, kk; char savbuff[200]; CGN_UPSTR(TOKEN[0].STR); for (nr=0; nr MAX_LEVEL) ibuf[0] = MAX_LEVEL; if (kk < 2) ibuf[1] = ibuf[0]; else { if (ibuf[1] < ibuf[0]) ibuf[1] = ibuf[0]; else if (ibuf[1] > MAX_LEVEL) ibuf[1] = MAX_LEVEL; } } if (qualif[0] == 'M') /* DEBUG/MODULE */ { if (nbra == 0) kk = 0; else { if ((TOKEN[2].STR[0] == 'N') || (TOKEN[2].STR[0] == 'n')) kk = 1; else if ((TOKEN[2].STR[0] == 'T') || (TOKEN[2].STR[0] == 't')) kk = 3; else kk = 2; } for (n=ibuf[0]; n<=ibuf[1]; n++) MONIT.MDEBUG[n] = kk; for (i=n; i MAX_LEVEL) ibuf[0] = MAX_LEVEL; if (kk < 2) ibuf[1] = ibuf[0]; else { if (ibuf[1] < ibuf[0]) ibuf[1] = ibuf[0]; else if (ibuf[1] > MAX_LEVEL) ibuf[1] = MAX_LEVEL; } } if (qualif[1] == 'F') kk = 0; /* ECHO/OFF */ else if (qualif[0] == 'F') kk = 2; /* ECHO/FULL */ else kk = 1; /* ECHO/ON */ for (n=ibuf[0]; n<=ibuf[1]; n++) MONIT.ECHO[n] = kk; for (i=n; i 8) /* context name length */ { ERRORS.SYS = 5; return (-1); } for (nr=TOKEN[1].LEN; nr<8; nr++) /* pad with blanks till length 8 */ TOKEN[1].STR[nr] = ' '; TOKEN[1].STR[8] = '\0'; cpntrb = TOKEN[1].STR; CGN_LOWSTR(cpntrb); /* we need it in lower case */ jj = 0; if (strcmp(cpntrb,"fors1 ") == 0) /* check, if we execute */ { /* a VLT pipeline context */ (void) strcpy(PIPE.INSTRUM,"fors1"); jj = 9; } else if (strcmp(cpntrb,"fors2 ") == 0) { (void) strcpy(PIPE.INSTRUM,"fors2"); jj = 9; } else if (strcmp(cpntrb,"uves ") == 0) { (void) strcpy(PIPE.INSTRUM,"uves"); jj = 9; } if (jj == 9) /* Yes, so update the PIPE structure */ { (void) strcpy(PIPE.CONT,PIPE.INSTRUM); (void) strcpy(PIPE.EXE,PIPE.INSTRUM); (void) strcpy(PIPE.PROC,PIPE.INSTRUM); (void) strcat(PIPE.CONT,"/context/"); /* e.g. "uves/context/" */ (void) strcat(PIPE.EXE,"/exec/"); (void) strcat(PIPE.PROC,"/proc/"); (void) strcpy(save,PIPE.HOME); /* change key PIPE_HOME */ (void) strcpy(&save[PIPE.HOME_LEN],PIPE.PROC); (void) SCKWRC("PIPE_PROC",1,save,1,150,&n); } (void) strcpy(ctxfile,cpntrb); (void) strcpy(&ctxfile[TOKEN[1].LEN],".ctx"); /* context file */ cpntra = CONTXT.NAME; /* point to CONTEXT names */ cpntr = cpntra; jj = -1; for (nr=0; nr -1) { (void) osaclose(n); iswi = 1; } else { n = CGN_OPEN(ctxfile,0); /* try to open in current dir. */ if (n > -1) { (void) osaclose(n); iswi = 2; } else /* try to open in: */ { /* $PIPE_HOME/instrum/context/ */ (void) strcpy(save,PIPE.HOME); (void) strcpy(&save[PIPE.HOME_LEN],PIPE.CONT); (void) strcat(save,ctxfile); n = CGN_OPEN(save,0); /* try in pipeline-context dir */ if (n > -1) { (void) osaclose(n); iswi = 3; } } } if (iswi == 2) /* get current directory */ { #if vms DIR_Expand("[.]",TOKEN[2].STR); /* is that correct? */ #else (void) osfdelete("Mid_Pipe"); (void) oshcmd("echo `pwd` > Mid_Pipe",(char *) 0,(char *) 0,(char *) 0); m = osaopen("Mid_Pipe",0); if (m > -1) { (void) osaread(m,TOKEN[2].STR,80); (void) osaclose(m); } else (void) strcpy(TOKEN[2].STR,"./"); #endif m = (int) strlen(TOKEN[2].STR); if (TOKEN[2].STR[m-1] != FSY_DIREND) { TOKEN[2].STR[m++] = FSY_DIREND; TOKEN[2].STR[m] = '\0'; } } else if (iswi == 3) { (void) strcpy(save,PIPE.HOME); (void) strcpy(&save[PIPE.HOME_LEN],PIPE.CONT); m = (int) strlen(save); } else m = 15; cptr = malloc((unsigned int) ++m); if (cptr == (char *) 0) { ERRORS.SYS = 80; return (-1); } if (iswi == 0) (void) strcpy(cptr,"MID_WORK:"); else if (iswi == 1) (void) strcpy(cptr,"MID_CONTEXT:"); else if (iswi == 3) (void) strcpy(cptr,save); else (void) strcpy(cptr,TOKEN[2].STR); CONTXT.pdirec[jj] = cptr; } mm = (int) strlen(LINE.STR); LINE.STR[mm++] = ' '; (void) strcpy(&LINE.STR[mm],cptr); } else if (actio == 0) { cpntra = CONTXT.NAME; /* point to CONTEXT names */ (void) strcpy(LINE.STR,"@ context dele "); if (MONIT.COUNT > 1) { CGN_LOWCOPY(cbuf,TOKEN[1].STR,8); /* get context name or flag */ if (cbuf[0] == '-') /* it's a flag */ { /* `-all' or `-total' */ int fid; fid = osaopen("middummclear.prg",1); /* open for writing */ if (fid < 0) { fid = CGN_OPEN("MID_WORK:middummclear.prg",1); if (fid < 0) goto bad_a; /* here it should have worked */ } if (cbuf[1] == 't') /* -total */ { INITCOM(); goto clear_a; } else if (cbuf[1] == 'a') /* -all */ { CLEANCOM(0); /* clear all context comnds */ goto clear_a; } bad_a: ERRORS.INDEX = 1; ERRORS.SYS = 100; return (-1); clear_a: jj = 0; cpntr = cpntra; for (nr=0; nr0; m--) { if (*(cpntr+m) != ' ') { jj = m + 1; break; } } (void) strncpy(TOKEN[1].STR,cpntr,8); TOKEN[1].STR[8] = ' '; m = CGN_INDEXC(TOKEN[1].STR,' '); (void) strcpy(&TOKEN[1].STR[m],".ctx"); m = CGN_COPY(&LINE.STR[15],TOKEN[1].STR) + 15; LINE.STR[m++] = ' '; (void) strcpy(&LINE.STR[m],CONTXT.pdirec[nr]); (void) osawrite(fid,LINE.STR,(int)strlen(LINE.STR)); } cpntr += 8; } CONTXT.STACK = 0; /* now no more context there */ mm = MAX_CONTXT * 8; CGN_FILL(cpntra,' ',mm); (void) osaclose(fid); if (jj > 0) /* so we found a context */ { (void) strcpy(LINE.STR,"@@ middummclear.prg"); goto send_command; } else return (1); } else { /* search for context name */ if (TOKEN[1].LEN < 8) { /* pad with blanks */ for (nr=TOKEN[1].LEN; nr<8; nr++) cbuf[nr] = ' '; } cpntr = cpntra; for (nr=0; nr