/* @(#)midkey.c 14.2 (ESO-DMD) 01/21/00 17:52:33 */ /*=========================================================================== 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 MIDKEY +++++++++++++++++++++++++++++++++++++++ .LANGUAGE C .IDENTIFICATION Module MIDKEY .AUTHOR Klaus Banse ESO - Garching .KEYWORDS Midas keyword utility routines. .ENVIRONMENT VMS and UNIX .COMMENT holds FNDKEY, MOVKEY, TYPCHK, GETLOCAL .VERSION 020215 last modif ------------------------------------------------------------------------*/ #include #include #include #include #if vms #else #include #include #include #include #include #endif #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_DEFKEY + CLEAR_LOCAL... */ /* */ int MID_FNDKEY(name,type,bytelm,noelm,modtim,unit) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE find the entry of a given keyword + return related info, if found .ALGORITHM first search IDENT[0 - 14] for matching name + level (in IDENT[16]) equal current procedure (i.e. treat as local key); if not found search as global key the current procedure level is stored (as integer) in keyword MODE(7) global keys are stored bottom-up, local keys top-down... .RETURN kentry: I*4 no. of entry, if found; -1, if not found -----------------------------------------------------------------------------*/ char *name /* IN : name of keyword */; char *type /* OUT: type of keyword, currently I,R,C,D are recognized for\ I*4,R*4,CHAR*n,R*8 */; int *bytelm /* OUT: no. of bytes per element of keyword data */; int *noelm /* OUT: no. of elements connected to keyword */; long int *modtim /* OUT: time keyword was last modified */; int *unit /* OUT: pointer to units-pointer */; { int kstrn, proglevel; register int nr, cdif; static int lastoff = 0; char loclevel, 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 */ proglevel = KIWORDS[OFF_MODE+6] - 1; /* get procedure level */ if (proglevel >= 0) { /* first loop through LOCNAMES from KEYALL.LOCENT till KEYALL.LOCNO and compare the key names as well as the levels */ keypntr = KEYALL.KEYNAMES + KEYALL.LOCNO; loclevel = level[proglevel]; for (nr=KEYALL.LOCNO; nr>=KEYALL.GLOBENT; nr--) { if ( (keypntr->IDENT[16] >= loclevel) && (strncmp(keypntr->IDENT,kname,kstrn) == 0) ) goto gotcha; keypntr --; } } /* first see, if it's last keyword name again */ keypntr = KEYALL.KEYNAMES + lastoff; if (strncmp(keypntr->IDENT,kname,kstrn) == 0) { nr = lastoff; goto gotcha; } /* then also loop through GLOBNAMES from 0 till KEYALL.GLOBNO */ keypntr = KEYALL.KEYNAMES; /* restart at beginning */ for (nr=0; nr<=KEYALL.GLOBNO; nr++) /* KEYALL.GLOBNO is last entry used */ { if (strncmp(keypntr->IDENT,kname,kstrn) == 0) { lastoff = nr; /* save offset of last global key */ goto gotcha; } keypntr ++; } /* arriving here means, that we didn't find it */ return (-1); gotcha: *type = keypntr->IDENT[15]; *bytelm = keypntr->BYTELEM; *noelm = keypntr->NOELEM; *modtim = keypntr->MODTIME; *unit = 0; /* not used currently */ return nr; /* keyword found */ } /* */ #if vms int MID_MOVKEY(direc,option) /*++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE initialize the system keywords from binary file FORGRxy.KEY or write keywords to that file .ALGORITHM either use par. 'option' as keyfile name or build name .RETURNS status: I*4 return status --------------------------------------------------*/ char *direc /* IN: [0] = direction of moving, I or O \ [1] = M(onitor) or X(tension) or A(pplication) */; char *option /* IN: if not blank, it's already the name of the keyfile */; { static int initflg = -1; static int gp; int ksz, dsz, totsize, keysize, datsize; int ggp, status, n, mm; char *tmpntr; char buf[4], work[200], *cpntr; struct KEY_STRUCT *keyname; totsize = sizeof(struct KEY_ALL); /* --------------------------------*/ /* move keywords in */ /* --------------------------------*/ if (*direc++ == 'I') /* already move to direc[1] */ { initflg ++; ggp = -1; /* if Midas from Unix command line => DAZUNIT is not defined */ if (*direc == 'A') { ksz = 0; /* MIDAS application */ OSY_GETSYMB("DAZUNIT",buf,4); if ((buf[0] == 'D') && (buf[1] == 'A') && (buf[2] == 'Z')) { (void) strcpy(work,"FORGRdrs.KEY"); ggp = 0; ksz += 10; } else { (void) OSY_TRNLOG("MID_WORK",work,168,&mm); if (work[mm-1] != FSY_DIREND) work[mm++] = FSY_DIREND; (void) strcpy(&work[mm],"FORGR .KEY"); work[mm+5] = buf[0]; work[mm+6] = buf[1]; } } else { ksz = 1; /* MIDAS monitor */ if (*option == ' ') /* use default keyword file */ { (void) OSY_TRNLOG("MID_WORK",work,168,&mm); if (work[mm-1] != FSY_DIREND) work[mm++] = FSY_DIREND; (void) strcpy(&work[mm],"FORGR .KEY"); OSY_GETSYMB("DAZUNIT",buf,4); work[mm+5] = buf[0]; work[mm+6] = buf[1]; } else if (*option == '*') /* use fixed (for Unix) keyword file */ { (void) strcpy(work,"FORGRdrs.KEY"); ggp = 0; ksz += 10; } else (void) strcpy(work,option); } keyname = KEYALL.KEYNAMES; /* save pointers in case of need */ KDWORDS = KEYALL.KEYWORDS; gp = osdopen(work,READ_WRITE); if (gp == -1) { if (ggp == 0) { /* get FORGRdrs.KEY from MID_MONIT */ (void) OSY_TRNLOG("MID_MONIT",work,156,&mm); if (work[mm-1] != FSY_DIREND) work[mm++] = FSY_DIREND; (void) strcpy(&work[mm],"FORGRdrs.KEY"); ggp = osdopen(work,READ); if (ggp == -1) { /* we can't use MID_ERROR yet... */ (void) printf("Could not open keyfile %s \n\r",work); return ERR_KEYBAD; } gp = ggp; } else { (void) printf("Could not open keyfile %s \n\r",work); return ERR_KEYBAD; } } else ggp = -1; /* avoid using ggp */ /* read binary keyfile via 3 osdread's */ cpntr = (char *) &KEYALL; status = osdread(gp,cpntr,(unsigned int)totsize); if (status < totsize) goto osd_rerror; /* printf("totsize = %d\n",totsize); */ keysize = sizeof(struct KEY_STRUCT) * (KEYALL.LOCENT+1); datsize = KEYALL.LOCDAT + 2; /* synchronize with midasgo.c */ KEYALL.ORIGIN = ksz; /* 0 (applic) or 1 (monitor) */ /* now also check, if we extend the keyword area */ if (*direc == 'X') { n = KIWORDS[OFF_MONPAR+2]; /* new no. of global keys */ mm = KIWORDS[OFF_MONPAR+3]; /* new no. of local keys */ KEYALL.GLOBENT = n; KEYALL.GLOBDAT = KEYALL.GLOBENT * KEY_FACT; KEYALL.LOCENT = n + mm; KEYALL.LOCDAT = KEYALL.LOCENT * KEY_FACT; KEYALL.LOCNO = KEYALL.GLOBENT - 1; /* reset local keywords */ KEYALL.LOCEND = KEYALL.GLOBDAT - 1; ksz = sizeof(struct KEY_STRUCT) * (KEYALL.LOCENT+1); dsz = KEYALL.LOCDAT + 2; cpntr = (char *) KEYALL.KEYNAMES; /* release previous memory */ free(cpntr); cpntr = (char *) KEYALL.KEYWORDS; free(cpntr); initflg = 0; /* enforce memory allocation */ } else { ksz = keysize; dsz = datsize; } if (initflg == 0) { tmpntr = malloc((unsigned int)ksz); if (tmpntr == NULL) { (void) printf("could not allocate %d bytes for key_names\n",ksz); ospexit(0); } memset(tmpntr,0,ksz); KEYALL.KEYNAMES = (struct KEY_STRUCT *) tmpntr; tmpntr = malloc((unsigned int)dsz); if (tmpntr == NULL) { (void) printf("could not allocate %d bytes for key_data\n",dsz); ospexit(0); } memset(tmpntr,0,dsz); KEYALL.KEYWORDS = (double *) tmpntr; } else if ((KEYALL.ORIGIN == 1) || (KEYALL.ORIGIN == 11)) { /* for monitor reuse old pointers */ KEYALL.KEYNAMES = keyname; KEYALL.KEYWORDS = KDWORDS; } status = osdread(gp,(char *) KEYALL.KEYNAMES,(unsigned int)keysize); if (status < keysize) goto osd_rerror; status = osdread(gp,(char *) KEYALL.KEYWORDS,(unsigned int)datsize); if (status < datsize) goto osd_rerror; /* printf("keysize = %d, "datsize = %d\n",keysize,datsize); */ if (ggp > -1) { /* we must create local FORGRdrs.KEY */ (void) osdclose(ggp); gp = osdopen("FORGRdrs.KEY",WRITE); if (gp == -1) { /* we can't use MID_ERROR yet... */ (void) printf("Could not create local keyfile FORGRdrs.KEY\n\r"); return ERR_KEYBAD; } } /* initialize the data pointers */ KDWORDS = KEYALL.KEYWORDS; KIWORDS = (int *) KEYALL.KEYWORDS; KRWORDS = (float *) KEYALL.KEYWORDS; KCWORDS = (char *) KEYALL.KEYWORDS; } /* --------------------------------*/ /* move keywords out */ /* --------------------------------*/ else { status = osdseek(gp,0L,FILE_START); /* rewind file */ cpntr = (char *) &KEYALL; status = osdwrite(gp,cpntr,(unsigned int)totsize); if (status < totsize) goto osd_werror; keysize = sizeof(struct KEY_STRUCT) * (KEYALL.LOCENT+1); cpntr = (char *) KEYALL.KEYNAMES; status = osdwrite(gp,cpntr,(unsigned int)keysize); if (status < keysize) goto osd_werror; datsize = KEYALL.LOCDAT + 2; cpntr = (char *) KEYALL.KEYWORDS; status = osdwrite(gp,cpntr,(unsigned int)datsize); if (status < datsize) goto osd_werror; status = osdclose(gp); } /* normal end */ return ERR_NORMAL; osd_rerror: (void) printf("MID_MOVKEY - Problems reading keyfile: %s \n\r",work); osdclose(gp); if (KEYALL.ORIGIN > 9) ospexit(ERR_KEYBAD); else return ERR_KEYBAD; osd_werror: status = ERR_KEYBAD; /* here we can use MID_ERROR... */ MID_ERROR("MIDAS","MID_MOVKEY",status,0); osdclose(gp); return status; } /* */ #else int MID_MOVKEY(direc,option) /*++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE initialize the system keywords from binary file FORGRxy.KEY or write keywords to that file .ALGORITHM either use par. 'option' as keyfile name or build name .RETURNS status: I*4 return status --------------------------------------------------*/ char *direc /* IN: [0] = direction of moving, I or O \ [1] = M(onitor) or X(tension) or A(pplication) */; char *option /* IN: if not blank, it's already the name of the keyfile */; { int whoami, keysize, datsize; int ggp, status, n, mm; static int initflg = -1; static int gp; static int szkeytotal, szkeyall, szkeynam, szkeydat; char action1, action2, buf[4], work[200], *cpntr, *tmpntr; static char *mapbuf; double *keywords; struct stat statbuf; szkeyall = sizeof(struct KEY_ALL); action1 = *direc++; /* already move to direc[1] */ /* --------------------------------*/ /* move keywords in */ /* --------------------------------*/ if (action1 == 'I') { action2 = *direc; initflg ++; ggp = -1; /* if Midas from Unix command line => DAZUNIT is not defined */ if (action2 == 'A') { whoami = 0; /* MIDAS application */ OSY_GETSYMB("DAZUNIT",buf,4); if ((buf[0] == 'D') && (buf[1] == 'A') && (buf[2] == 'Z')) { (void) strcpy(work,"FORGRdrs.KEY"); ggp = 0; whoami += 10; } else { (void) OSY_TRNLOG("MID_WORK",work,168,&mm); if (work[mm-1] != FSY_DIREND) work[mm++] = FSY_DIREND; (void) memcpy(&work[mm],"FORGR .KEY",(size_t)12); work[mm+5] = buf[0]; work[mm+6] = buf[1]; } } else /* action2 now: M or X */ { whoami = 1; /* MIDAS monitor */ if (*option == ' ') /* use default keyword file */ { (void) OSY_TRNLOG("MID_WORK",work,168,&mm); if (work[mm-1] != FSY_DIREND) work[mm++] = FSY_DIREND; (void) memcpy(&work[mm],"FORGR .KEY",(size_t)12); OSY_GETSYMB("DAZUNIT",buf,4); work[mm+5] = buf[0]; work[mm+6] = buf[1]; } else if (*option == '*') /* use fixed (for Unix) keyword file */ { (void) strcpy(work,"FORGRdrs.KEY"); ggp = 0; whoami += 10; } else (void) strcpy(work,option); } /* whoami = 0/10 (applic) or 1/11 (monitor) */ map_open: keywords = KEYALL.KEYWORDS; /* save pointer in case of need */ gp = open(work,O_RDWR); /* open file for read/write */ if (gp == -1) /* open failed ... */ { if (ggp == 0) { /* get FORGRdrs.KEY from MID_MONIT */ (void) OSY_TRNLOG("MID_MONIT",work,156,&mm); if (work[mm-1] != FSY_DIREND) work[mm++] = FSY_DIREND; (void) strcpy(&work[mm],"FORGRdrs.KEY"); ggp = open(work,O_RDWR); if (ggp == -1) { /* we can't use MID_ERROR yet... */ (void) printf("Could not open keyfile %s \n",work); return ERR_KEYBAD; } gp = ggp; } else { (void) printf("Could not open keyfile %s \n",work); return ERR_KEYBAD; } } else ggp = -1; /* avoid using ggp */ status = fstat(gp,&statbuf); /* get all info about file */ if (status != 0) { (void) printf("Could not fstat keyfile %s \n",work); return ERR_KEYBAD; } szkeytotal = statbuf.st_size; /* total file size in bytes */ mapbuf = (char *) mmap(0,(size_t)szkeytotal,PROT_READ | PROT_WRITE, MAP_SHARED,gp,(off_t)0); if (mapbuf == (char *) (-1)) { close (gp); (void) printf("Could not mmap keyfile %s \n",work); return ERR_KEYBAD; } cpntr = (char *) &KEYALL; (void) memcpy(cpntr,mapbuf,(size_t)szkeyall); keysize = sizeof(struct KEY_STRUCT)*(KEYALL.LOCENT+1); datsize = KEYALL.LOCDAT + 2; /* synchronize with midasgo.c!! */ KEYALL.ORIGIN = whoami; /* do not use the one just copied */ /* from mapbuf ... */ /* now also check, if we extend the keyword area */ if (action2 == 'X') /* here only, if we are the Monitor ... */ { int ksz, dsz; n = KIWORDS[OFF_MONPAR+2]; /* new no. of global keys */ mm = KIWORDS[OFF_MONPAR+3]; /* new no. of local keys */ munmap(mapbuf,szkeytotal); /* unmap + close keyfile */ close(gp); /* we just opened */ tmpntr = (char *) KEYALL.KEYWORDS; free(tmpntr); /* now open keyfile as binary file + read "old" KEYALL structure */ gp = osdopen(work,READ_WRITE); if (gp == -1) { (void) printf("MID_MOVKEY + osdopen => we should NOT come here!!!\n"); ospexit(1); } status = osdread(gp,(char *) &KEYALL,(unsigned int)szkeyall); if (status < szkeyall) goto osd_rerror; KEYALL.GLOBENT = n; /* update KEYALL structure */ KEYALL.GLOBDAT = KEYALL.GLOBENT * KEY_FACT; KEYALL.LOCENT = n + mm; KEYALL.LOCDAT = KEYALL.LOCENT * KEY_FACT; KEYALL.LOCNO = KEYALL.GLOBENT - 1; /* reset local keywords */ KEYALL.LOCEND = KEYALL.GLOBDAT - 1; ksz = sizeof(struct KEY_STRUCT)*(KEYALL.LOCENT+1); dsz = KEYALL.LOCDAT + 2; /* new sizes */ cpntr = malloc((unsigned int)ksz); /* aligned to char */ if (cpntr == NULL) { (void) printf("could not allocate %d bytes for key_names\n",ksz); ospexit(0); } tmpntr = malloc((unsigned int)dsz); /* will be aligned to double */ if (tmpntr == NULL) { (void) printf("could not allocate %d bytes for key_data\n",dsz); ospexit(0); } KEYALL.KEYWORDS = (double *) tmpntr; /* now read KEYNAMES + KEYWORDS into new larger buffers */ status = osdread(gp,cpntr,(unsigned int)keysize); if (status < keysize) goto osd_rerror; status = osdread(gp,(char *) KEYALL.KEYWORDS,(unsigned int)datsize); if (status < datsize) goto osd_rerror; /* and write the larger buffers out - thus increasing the file size */ status = osdseek(gp,0L,FILE_START); /* rewind file */ status = osdwrite(gp,(char *) &KEYALL,(unsigned int)szkeyall); if (status < szkeyall) goto osd_werror; status = osdwrite(gp,cpntr,(unsigned int)ksz); if (status < ksz) goto osd_werror; status = osdwrite(gp,(char *) KEYALL.KEYWORDS,(unsigned int)dsz); if (status < dsz) goto osd_werror; status = osdclose(gp); free(cpntr); /* we don't need KEYNAMES buffer anymore */ /* now we use the new, larger keyfile and do again the mapping */ action2 = 'M'; goto map_open; } if (initflg == 0) /* here also as an application ... */ { tmpntr = malloc((unsigned int)datsize); /* will be aligned to double */ if (tmpntr == NULL) { (void) printf("could not allocate %d bytes for key_data\n",datsize); ospexit(0); } KEYALL.KEYWORDS = (double *) tmpntr; } else if ((KEYALL.ORIGIN == 1) || (KEYALL.ORIGIN == 11)) { /* for monitor reuse old pointers */ KEYALL.KEYWORDS = keywords; } KEYALL.KEYNAMES = (struct KEY_STRUCT *) (mapbuf + szkeyall); szkeynam = keysize; szkeydat = datsize; cpntr = (char *) KEYALL.KEYWORDS; (void) memcpy(cpntr,mapbuf+szkeyall+szkeynam,datsize); KDWORDS = KEYALL.KEYWORDS; /* initialize the data pointers */ KIWORDS = (int *) KEYALL.KEYWORDS; KRWORDS = (float *) KEYALL.KEYWORDS; KCWORDS = (char *) KEYALL.KEYWORDS; } /* --------------------------------*/ /* move keywords out */ /* --------------------------------*/ else { cpntr = (char *) &KEYALL; (void) memcpy(mapbuf,cpntr,(size_t)szkeyall); cpntr = (char *) KEYALL.KEYWORDS; (void) memcpy(mapbuf+szkeyall+szkeynam,cpntr,(size_t)szkeydat); status = munmap(mapbuf,(size_t)szkeytotal); if (status != 0) { (void) printf("munmap failed...\n"); } close(gp); } /* normal end */ return ERR_NORMAL; osd_rerror: (void) printf("MID_MOVKEY - Problems reading keyfile: %s \n",work); goto closing; osd_werror: (void) printf("MID_MOVKEY - Problems writing keyfile: %s \n",work); closing: osdclose(gp); if (KEYALL.ORIGIN > 9) ospexit(ERR_KEYBAD); else return ERR_KEYBAD; } #endif /* */ void MID_TYPCHK(intype,outtype,bytelm) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE check given data type + return cleaned type and no. of bytes per element .ALGORITHM straight forward .RETURNS nothing. ---------------------------------------------------------------------------*/ char *intype /* IN : type of keyword/descr */; char *outtype /* OUT: type of keyword/descr currently I,R,C,D; \ set to ' ', if invalid INTYPE given */; int *bytelm /* OUT: no. of bytes per element of keyword/descr data */; { int actval, mm, lbytlm; register char cdif, test; *outtype = ' '; /* default to no_success ... */ cdif = 'A' - 'a'; test = *intype; if ((test >= 'a') && (test <= 'z')) /* convert to upper case */ test += cdif; /* first look for type CHAR*len */ if (test == 'C') { mm = CGN_INDEXC(intype,'*'); /* search for '*' */ if (mm < 0 ) { *bytelm = 1; /* that is o.k. */ *outtype = 'C'; } else { /* point to char. following '*' */ /* actval = CGN_CNVT(intype+mm+1,1,1,&lbytlm,&rwa,&dwa); *bytelm = lbytlm; */ lbytlm = -1; lbytlm = atoi(intype+mm+1); if ( lbytlm > 0) { *bytelm = lbytlm; *outtype = 'C'; /* only o.k., if valid number */ } } } /* then for integer, real + double precision */ else if (test == 'I') { *bytelm = II_SIZE; *outtype = 'I'; } else if (test == 'R') { /* distinguish between R*4 and R*8 */ if ( CGN_INDEXS(intype,"*8") > 0) { *bytelm = DD_SIZE; *outtype = 'D'; } else { *bytelm = RR_SIZE; *outtype = 'R'; } } else if (test == 'D') { *bytelm = DD_SIZE; *outtype = 'D'; } } /* */ void MID_GETLOCAL(inoutno,keyid,byti,noi) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE loop through local keys + return type and no. of bytes per element .ALGORITHM straight forward .RETURNS nothing. ---------------------------------------------------------------------------*/ int *inoutno; /* IN/OUT: = 0 to start search, > 0 to continue (IN), n on return for nth local key (n > 0), -1 on return if no more local keyw. */ char *keyid; /* OUT: keyname in [0] - [14] type in [15] level in [16] */ int *byti; /* OUT: no. of bytes per elem */ int *noi; /* OUT: no. of elements of key */ { register int nr; int proglevel; static int localcount; static struct KEY_STRUCT *lkeypntr; static char kbloclevel; if (*inoutno == 0) /* start of search for local keys */ { proglevel = KIWORDS[OFF_MODE+6] - 1; /* get procedure level */ if (proglevel >= 0) { /* loop through LOCNAMES from KEYALL.LOCENT till KEYALL.LOCNO and get all local keynames */ kbloclevel = level[proglevel]; lkeypntr = KEYALL.KEYNAMES + KEYALL.LOCNO; localcount = 0; for (nr=KEYALL.LOCNO; nr>=KEYALL.GLOBENT; nr--) { if (lkeypntr->IDENT[16] >= kbloclevel) goto found; lkeypntr --; } } } else { if (lkeypntr >= KEYALL.KEYNAMES + KEYALL.GLOBENT) { lkeypntr --; if (lkeypntr->IDENT[16] >= kbloclevel) goto found; } } *inoutno = -1; return; found: localcount ++; *inoutno = localcount; (void) strncpy(keyid,lkeypntr->IDENT,17); *byti = lkeypntr->BYTELEM; *noi = lkeypntr->NOELEM; }