/* @(#)midkeyb.c 17.1.1.2 (ESO-DMD) 02/25/02 17:53:49 */ /*=========================================================================== 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 ===========================================================================*/ /*+++++++++++++++++++++ Module MIDKEYB +++++++++++++++++++++++++++++++++++++++ .LANGUAGE C .IDENTIFICATION Module MIDKEYB .AUTHOR Klaus Banse ESO - Garching .KEYWORDS Midas keyword utility routines. .ENVIRONMENT VMS and UNIX .COMMENT holds DEFKEY, DELKEY, PACKY, TSTKEY .VERSION [1.00] 920211: pulled out from midkey.c 020215 last modif ------------------------------------------------------------------------*/ #include #define READ 0 #define WRITE 1 #define READ_WRITE 2 #define APPEND 3 #define MAX_LEVEL 25 /* synchronize with midback.h ...*/ static struct KEY_STRUCT *keypntr; static char level[MAX_LEVEL+4] = "ABCDEFGHIJKLMNOPQRSTUVWXY"; /* synchronize with MID_FNDKEY + CLEAR_LOCAL... */ /* */ int MID_TSTKEY(name) /*++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE check name of local keyword against reserved keyword names .ALGORITHM loop from index 0 to KEYALL->SYSNO and compare the names .RETURNS status: I*4 Return status if = 0, everything is o.k. --------------------------------------------------*/ char *name /* IN: Name of local keyword */; { register int nr, cdif, kstrn; char kname[20]; register char nc; cdif = 'A' - 'a'; for (nr=0; nr<=KEY_NAMELEN; nr++) { nc = name[nr]; if (nc == '\0') { kstrn = nr; goto step_a; } if ((nc >= 'a') && (nc <= 'z')) /* convert to upper case */ nc += cdif; kname[nr] = nc; } return (-1); /* bad (too long) keyname */ step_a: if (kstrn < KEY_NAMELEN) kname[kstrn++] = ' '; /* append a blank */ /* loop through KEYNAMES from 0 till KEYALL.SYSNO and compare the key names */ keypntr = KEYALL.KEYNAMES; for (nr=0; nr<=KEYALL.SYSNO; nr++) { if (strncmp(keypntr->IDENT,kname,kstrn) == 0) return (-1); keypntr ++; } return (0); } /* */ #ifdef __STDC__ int MID_DEFKEY(char * name , char loco , char * type , int actval , int * unit) #else int MID_DEFKEY(name,loco,type,actval,unit) /*++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE define + create a user keyword .ALGORITHM check input parameters and update pointers do not fill the data block also take care of local keywords .RETURNS status: I*4 Return status if = 0, everything is o.k. --------------------------------------------------*/ char *name /* IN: Name of keyword */; char loco /* IN: = 'L' or 'l' for local keyword */; char *type /* IN: type of keyword = I or R or CHAR*len or D */; int actval /* IN: No. of elements in keyword : actual length of keyword depends on its type */; int *unit /* IN: unit pointer of keyword */; #endif { int status, noelem, bytelem, proglevel; int byt_len, kstrn, cdif, koffs, sizbyt, pad, tot_len; register int nr; long int oshtime(); char k_typ[4], kname[20]; char kc, loclevel, loclow; register char nc; /* name should not begin with '\' (that's how we mark deleted keys...) */ if ( *name == '\\') { status = ERR_INPINV; goto end_of_it; } cdif = 'A' - 'a'; for (nr=0; nr<=KEY_NAMELEN; nr++) { nc = name[nr]; if (nc == '\0') { kstrn = nr; goto step_a; } if ((nc >= 'a') && (nc <= 'z')) /* convert to upper case */ nc += cdif; kname[nr] = nc; } return (-1); /* bad (too long) keyname */ /* check type + length */ step_a: if (kstrn < KEY_NAMELEN) kname[kstrn++] = ' '; /* append a blank */ MID_TYPCHK(type,k_typ,&bytelem); if (k_typ[0] == ' ') /* invalid type was given... */ { status = ERR_INPINV; goto end_of_it; } noelem = actval; /* -------------------------- */ /* now for local keys */ /* -------------------------- */ if ((loco == 'L') || (loco == 'l')) { proglevel = KIWORDS[OFF_MODE+6] - 1; /* get current program level */ if (proglevel < 0) { status = ERR_INPINV; /* DEFINE/LOCAL only in procedure ! */ goto end_of_it; } loclevel = level[proglevel]; loclow = loclevel + ('a' - 'A'); /* e.g. 'B' -> 'b' */ /* loop through LOCNAMES from KEYALL.LOCNO till KEYALL.LOCENT and compare the key names as well as the procedure level */ keypntr = KEYALL.KEYNAMES + KEYALL.GLOBENT; for (nr=KEYALL.GLOBENT; nr<=KEYALL.LOCNO; nr++) { if ( (strncmp(keypntr->IDENT,kname,kstrn) == 0) ) { kc = keypntr->IDENT[16]; if ((kc == loclevel) || (kc == loclow)) { /* name already there... */ status = ERR_KEYBAD; goto end_of_it; } } keypntr ++; } /* calculate length in bytes + eventual front padding bytes */ if (k_typ[0] == 'C') { pad = 0; byt_len = noelem*bytelem; } else { if (k_typ[0] == 'I') sizbyt = II_SIZE; else if (k_typ[0] == 'R') sizbyt = RR_SIZE; else sizbyt = DD_SIZE; pad = sizbyt - 1 - (KEYALL.LOCEND % sizbyt); byt_len = noelem * sizbyt; } /* check, if LOCNAMES full */ if (KEYALL.LOCNO >= KEYALL.LOCENT-1) { MID_PACKY(); /* try a garbage collection... */ if (KEYALL.LOCNO >= KEYALL.LOCENT-1) { status = ERR_KEYOVN; goto end_of_it; } } /* look, if LOCWORDS full */ tot_len = pad + byt_len; if (KEYALL.LOCEND+tot_len >= KEYALL.LOCDAT) { MID_PACKY(); /* try a garbage collection... */ if (KEYALL.LOCEND+tot_len >= KEYALL.LOCDAT) { status = ERR_KEYOVL; goto end_of_it; } } /* everything o.k. - do what's necessary */ KEYALL.LOCNO ++; koffs = KEYALL.LOCEND + 1; KEYALL.LOCEND += tot_len; keypntr = KEYALL.KEYNAMES + KEYALL.LOCNO; /* point to new entry */ if (loco == 'L') keypntr->IDENT[16] = loclevel; /* only defined for this very level */ else keypntr->IDENT[16] = loclow; /* also defined for lower levels */ } /* -------------------------- */ /* now for global keys */ /* -------------------------- */ else { /* calculate length in bytes + eventual front padding bytes */ if (k_typ[0] == 'C') { pad = 0; byt_len = noelem*bytelem; } else { if (k_typ[0] == 'I') sizbyt = II_SIZE; else if (k_typ[0] == 'R') sizbyt = RR_SIZE; else sizbyt = DD_SIZE; pad = sizbyt - 1 - (KEYALL.GLOBEND % sizbyt); byt_len = noelem * sizbyt; } /* check, if KEYNAMES full */ if (KEYALL.GLOBNO >= KEYALL.GLOBENT-1) { MID_PACKY(); /* try a garbage collection... */ if (KEYALL.GLOBNO >= KEYALL.GLOBENT-1) { status = ERR_KEYOVN; goto end_of_it; } } /* look, if KEYWORDS full */ tot_len = pad + byt_len; if (KEYALL.GLOBEND+tot_len >= KEYALL.GLOBDAT) { MID_PACKY(); /* try a garbage collection... */ if (KEYALL.GLOBEND+tot_len >= KEYALL.GLOBDAT) { status = ERR_KEYOVL; goto end_of_it; } } /* everything o.k. - do what's necessary */ KEYALL.GLOBNO ++; koffs = KEYALL.GLOBEND + 1; KEYALL.GLOBEND += tot_len; keypntr = KEYALL.KEYNAMES + KEYALL.GLOBNO; /* point to new entry */ keypntr->IDENT[16] = ' '; } /* -------------------------- */ /* now the common section */ /* -------------------------- */ CGN_FILL(keypntr->IDENT,' ',KEY_NAMELEN); /* fill up with ' ' */ (void) strncpy(keypntr->IDENT,kname,kstrn); keypntr->IDENT[15] = k_typ[0]; keypntr->BYTELEM = (short int) bytelem; keypntr->NOELEM = noelem; keypntr->LEN = byt_len; if (k_typ[0] == 'C') keypntr->OFFSET = koffs; else keypntr->OFFSET = (koffs + pad) /sizbyt; keypntr->FRPAD = (short int) pad; keypntr->KLOCK = 0; keypntr->MODTIME = oshtime(); keypntr->UNIT = 0; /* (keypntr->UNIT = *unit) not used yet... */ return ERR_NORMAL; /* That's it folks... */ end_of_it: MID_ERROR("MIDAS","MID_DEFKEY:",status,0); return status; } /* */ int MID_DELKEY(name) /*++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE delete a user defined keyword .ALGORITHM check input parameters and update pointers do not fill the data block .RETURN status: I*4 Return status if = 0, everything is o.k. --------------------------------------------------*/ char *name; /* single keyword name, or list of keyword names separated by a comma, or name of file containing keyword names (file.cat) */ { int status, kentry, n, mm, nval, sta, all; int kid, kunit; long int modtim; char kname[18], k_typ[4], work[40], prombuf[84]; n = CGN_INDEXS(name,".cat"); /* check for keyword catalog */ if (n < 1) { sta = 0; all = 0; nval = CGN_COPY(prombuf,name); goto extra_key; } /* so we have a catalog */ all = 2; kid = CGN_OPEN(name,READ); if (kid < 0) return (ERR_INPINV); cat_loop: sta = 0; nval = osaread(kid,prombuf,80); if (nval < 1) /* EOF - get out */ { osaclose(kid); return (ERR_NORMAL); } extra_key: n = CGN_EXTRSS(prombuf,nval,',',&sta,kname,KEY_NAMELEN); if (n <= 0) /* line finished */ { if (all == 2) goto cat_loop; /* get next record from catalog */ return (ERR_NORMAL); } /* find keyword entry */ kentry = MID_FNDKEY(kname,k_typ,&mm,&mm,&modtim,&kunit); if (kentry <= KEYALL.SYSNO) { if (kentry < 0) { (void) sprintf(work,"keyword %s not found...",kname); SCTPUT(work); goto extra_key; /* see, if we can extract more */ } else { status = ERR_KEYBAD; /* system keys may not be deleted... */ goto erro_end; } } keypntr = KEYALL.KEYNAMES + kentry; /* everything o.k. - point to entry */ if ((keypntr->KLOCK != 0) && (keypntr->KLOCK != KIWORDS[OFF_MONPAR+9])) { (void) sprintf(work,"keyword %s is locked...",kname); SCTPUT(work); goto extra_key; /* see, if we can extract more */ } keypntr->IDENT[0] = '\\'; /* mark keyname as deleted */ /* if we delete last key, just change pointers */ if (kentry == KEYALL.GLOBNO) { while(keypntr->IDENT[0] == '\\') /* may be more to delete... */ { KEYALL.GLOBEND -= (keypntr->LEN + keypntr->FRPAD); KEYALL.GLOBNO --; keypntr --; } } goto extra_key; /* see, if we can extract more */ erro_end: if (all == 2) osaclose(kid); return status; } /* */ void MID_PACKY() /*+++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE remove delete keywords (header + data space) .ALGORITHM move through keyword structure + recalculate data offset copy header + data into space freed by deleted keyword .RETURNS nothing. -------------------------------------------------------*/ { int globend, tot_len, sizbyt, pad; int keyno, koffs; register int nr, mr; char *cpntra, *cpntrb; int *ipntra, *ipntrb; float *fpntra, *fpntrb; double *dpntra, *dpntrb; struct KEY_STRUCT *keypntra; /* loop through GLOBNAMES from 0 till current KEYALL.GLOBNO */ keypntr = KEYALL.KEYNAMES; keyno = -1; globend = -1; for (nr=0; nr<=KEYALL.GLOBNO; nr++) /* KEYALL.GLOBNO is last entry used */ { if(keypntr->IDENT[0] == '\\') { keypntra = keypntr + 1; for (mr=nr+1; mr<=KEYALL.GLOBNO; mr++) { /* search for 1. rela entry */ if(keypntra->IDENT[0] != '\\') { koffs = globend + 1; (void) strncpy(keypntr->IDENT,keypntra->IDENT,16); keypntr->BYTELEM = keypntra->BYTELEM; keypntr->NOELEM = keypntra->NOELEM; keypntr->LEN = keypntra->LEN; keypntr->KLOCK = keypntra->KLOCK; keypntr->MODTIME = keypntra->MODTIME; keypntr->UNIT = keypntra->UNIT; if (keypntr->IDENT[15] == 'C') { keypntr->FRPAD = 0; keypntr->OFFSET = koffs; tot_len = keypntr->BYTELEM * keypntr->NOELEM; cpntra = KCWORDS + keypntr->OFFSET; cpntrb = KCWORDS + keypntra->OFFSET; CGN_COPYALL(cpntra,cpntrb,tot_len); } else { register int kr; if (keypntr->IDENT[15] == 'I') sizbyt = II_SIZE; else if (keypntr->IDENT[15] == 'R') sizbyt = RR_SIZE; else sizbyt = DD_SIZE; pad = sizbyt - 1 - (globend % sizbyt); keypntr->FRPAD = pad; keypntr->OFFSET = (koffs + pad) / sizbyt; tot_len = pad + (keypntr->NOELEM * sizbyt); if (keypntr->IDENT[15] == 'I') { ipntra = KIWORDS + keypntr->OFFSET; ipntrb = KIWORDS + keypntra->OFFSET; for (kr=0; krNOELEM; kr++) *ipntra++ = *ipntrb++; } else if (keypntr->IDENT[15] == 'R') { fpntra = KRWORDS + keypntr->OFFSET; fpntrb = KRWORDS + keypntra->OFFSET; for (kr=0; krNOELEM; kr++) *fpntra++ = *fpntrb++; } else { dpntra = KDWORDS + keypntr->OFFSET; dpntrb = KDWORDS + keypntra->OFFSET; for (kr=0; krNOELEM; kr++) *dpntra++ = *dpntrb++; } } keypntra->IDENT[0] = '\\'; /* mark copied key as deleted */ goto join; } keypntra ++; } goto end_of_it; /* only deleted keys in the end */ } else { /* calculate last byte of data space */ if (keypntr->IDENT[15] == 'C') tot_len = keypntr->BYTELEM * keypntr->NOELEM; else { if (keypntr->IDENT[15] == 'I') sizbyt = II_SIZE; else if (keypntr->IDENT[15] == 'R') sizbyt = RR_SIZE; else sizbyt = DD_SIZE; if (globend < 0) pad = 0; else pad = sizbyt - 1 -(globend % sizbyt); tot_len = pad + (keypntr->NOELEM * sizbyt); } } join: globend += tot_len; keyno ++; keypntr ++; } end_of_it: KEYALL.GLOBNO = keyno; KEYALL.GLOBEND = globend; }