diff options
Diffstat (limited to 'Ganlib/src/xsm_c.c')
| -rw-r--r-- | Ganlib/src/xsm_c.c | 1235 |
1 files changed, 1235 insertions, 0 deletions
diff --git a/Ganlib/src/xsm_c.c b/Ganlib/src/xsm_c.c new file mode 100644 index 0000000..7abbf1f --- /dev/null +++ b/Ganlib/src/xsm_c.c @@ -0,0 +1,1235 @@ + +/**********************************/ +/* C API for xsm file support */ +/* author: A. Hebert (30/04/2002) */ +/**********************************/ + +/* + Copyright (C) 2002 Ecole Polytechnique de Montreal + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + */ + +#include <stdlib.h> +#include <string.h> +#include "xsm.h" + +#define iprim 3 +#define iwrd 3 +#define klong 5+iwrd+(3+iwrd)*iofmax +#if !defined(min) +#define min(A,B) ((A) < (B) ? (A) : (B)) +#endif +#define TRUE 1 /* valeur boolenne TRUE */ +#define FALSE 0 /* valeur boolenne FALSE */ + +static char AbortString[132]; + +/* Table of constant values */ + +static int_32 c__0 = 0; +static int_32 c__1 = 1; +static int_32 c__2 = 2; +static int_32 c__8 = 8; +static char *bl12=" "; + +void xsmkep(db1 *ipkeep, int_32 imode, xsm **iplist) +/* + *----------------------------------------------------------------------- + * + * keep the addresses of the open active directories. + * + * input parameters: + * ipkeep : address of the database handle (always the same). + * imode : =1: add to the database; =2: remove from the database. + * iplist : address of an active directory. + * + * output parameter: + * iplist : last active directory in the database. =0 if the + * database is empty. + * + * database handle structure: + * 0 : number of addresses in the database. + * 1 : maximum slots in the database. + * 2 : address of the database. + * + *----------------------------------------------------------------------- + */ +{ + char *nomsub="xsmkep"; + int_32 n = ipkeep->nad; + if (imode == 1) { + int_32 i; + xsm **my_parray; + if ((*iplist)->header != 200) { + sprintf(AbortString,"%s: WRONG HEADER(1).",nomsub); + xabort_c(AbortString); + } else if (ipkeep->nad + 1 > ipkeep->maxad) { + ipkeep->maxad += maxit; + my_parray = (xsm **) malloc((ipkeep->maxad)*sizeof(*my_parray)); + for (i = 0; i < n; ++i) my_parray[i]=ipkeep->idir[i]; + if (n > 0) free(ipkeep->idir); + ipkeep->idir=my_parray; + } + ++ipkeep->nad; + ipkeep->idir[n] = *iplist; + } else if (imode == 2) { + int_32 i, i0=0; + for (i = n; i >= 1; --i) { + if (ipkeep->idir[i-1] == *iplist) { + i0 = i; + goto L30; + } + } + sprintf(AbortString,"%s: UNABLE TO FIND AN ADDRESS.",nomsub); + xabort_c(AbortString); +L30: + for (i = i0; i <= n-1; ++i) + ipkeep->idir[i-1]=ipkeep->idir[i]; + --ipkeep->nad; + if (ipkeep->nad == 0) { + *iplist = NULL; + free(ipkeep->idir); + ipkeep->maxad=0; + ipkeep->idir=NULL; + } else { + *iplist = ipkeep->idir[n-1]; + if ((*iplist)->header != 200) { + sprintf(AbortString,"%s: WRONG HEADER(2).",nomsub); + xabort_c(AbortString); + } + } + } else { + sprintf(AbortString,"%s: INVALID VALUE OF IMODE.",nomsub); + xabort_c(AbortString); + } + return; +} + +void xsmdir(int_32 *ind, block2 *my_block2) +/* + *----------------------------------------------------------------------- + * + * import or export a directory using the kdi utility. + * + * input parameters: + * ind : =1 for import ; =2 for export. + * my_block2 : address of memory-resident xsm structure (block 2). + * + *----------------------------------------------------------------------- + */ +{ + char *nomsub="xsmdir"; + int_32 i,j,irc,ibuf[9],ipos,iofma2,iivec[6*iofmax]; + ipos = my_block2->idir; + if (*ind == 1) { + irc = kdiget_c(my_block2->ifile, ibuf, ipos, c__8); + if (irc != 0) goto L40; + if (strncmp((char*)ibuf,"$$$$",4) != 0) goto L30; + iofma2 = ibuf[1]; + if (iofma2 > iofmax) goto L30; + my_block2->nmt = ibuf[2]; + my_block2->link = ibuf[3]; + my_block2->iroot = ibuf[4]; + strncpy(my_block2->mynam,(char*)&ibuf[5],12); + my_block2->mynam[12]='\0'; + for(i=11; i>0; i--) { + if(my_block2->mynam[i] != ' ') break; + my_block2->mynam[i]='\0'; + } + if (my_block2->nmt == 0) return; + ipos += c__8; + irc = kdiget_c(my_block2->ifile, iivec, ipos, 6*iofma2); + if (irc != 0) goto L40; + for(i=0; i<my_block2->nmt; i++) { + my_block2->iofs[i] = iivec[i]; + my_block2->jlon[i] = iivec[iofma2+i]; + my_block2->jtyp[i] = iivec[2*iofma2+i]; + strncpy(my_block2->cmt[i],(char*)&iivec[3*(iofma2+i)],12); + my_block2->cmt[i][12]='\0'; + for(j=11; j>0; j--) { + if(my_block2->cmt[i][j] != ' ') break; + my_block2->cmt[i][j]='\0'; + } + } + } else if (*ind == 2) { + my_block2->modif = 0; + const char *src = "$$$$"; + memcpy((char*)ibuf,src,strlen(src)); + ibuf[1] = iofmax; + ibuf[2] = my_block2->nmt; + ibuf[3] = my_block2->link; + ibuf[4] = my_block2->iroot; + memcpy((char*)&ibuf[5],bl12,12); + strncpy((char*)&ibuf[5],my_block2->mynam,min(12,strlen(my_block2->mynam))); + irc = kdiput_c(my_block2->ifile, ibuf, ipos, c__8); + if (irc != 0) goto L50; + ipos += c__8; + memset(iivec, 0, 6*iofmax*sizeof(iivec[0])); + for(i=0; i<my_block2->nmt; i++) { + iivec[i] = my_block2->iofs[i]; + iivec[iofmax+i] = my_block2->jlon[i]; + iivec[2*iofmax+i] = my_block2->jtyp[i]; + memcpy((char*)&iivec[3*(iofmax+i)],bl12,12); + strncpy((char*)&iivec[3*(iofmax+i)],my_block2->cmt[i],min(12,strlen(my_block2->cmt[i]))); + } + irc = kdiput_c(my_block2->ifile, iivec, ipos, 6*iofmax); + if (irc != 0) goto L50; + } + return; +/* ABORT ON FATAL ERRORS */ +L30: + sprintf(AbortString,"%s: UNABLE TO RECOVER DIRECTORY.",nomsub); + xabort_c(AbortString); +L40: + sprintf(AbortString,"%s: kdiget_c ERROR NB. %d.",nomsub,(int)irc); + xabort_c(AbortString); +L50: + sprintf(AbortString,"%s: kdiput_c ERROR NB. %d.",nomsub,(int)irc); + xabort_c(AbortString); +} + +void xsmop_c(xsm **iplist, char *namp, int_32 imp, int_32 impx) +/* + *----------------------------------------------------------------------- + * + * open an existing or create a new xsm file. + * + * The xsm database results from the juxtaposition of a hierarchical + * logical structure into a direct access file. The direct access file + * is ANSI-C or Fortran-77 compatible and is managed by kdiget/put/cl. + * xsmop/put/get/len/vec/nxt/cl entries provide a set of methods to + * access a xsm file. + * + * The logical structure of a xsm file is made of a root directory fol- + * lowed by variable-length blocks containing the useful information. + * Each time a directory is full, an extent is automatically created at + * the end of the file, so that the total number of blocks in a direc- + * tory is only limited by the maximum size of the direct access file. + * Any block can contain a sub-directory in order to create a hierar- + * chical structure. + * + * input parameters: + * namp : character name (null terminated) of the xsm file. + * imp : type of access. =0: new file mode; + * =1: modification mode; + * =2: read only mode. + * impx : if impx=0, we suppress printing on xsmop. + * + * output parameters: + * iplist : address of the handle to the xsm file. + * namp : character*12 name of the xsm file if imp=1 or imp=2. + * + * The active directory is made of two blocks linked together. A block 1 + * is allocated for each scalar directory or vector directory component. + * Block 2 is unique for a given xsm file; every block 1 is pointing to + * the same block 2. + * + *----------------------------------------------------------------------- + */ +{ + char *nomsub="xsmop_c"; + int_32 irc,ibuf; + char hbuf[5]; + block2 *my_block2; + db1 *my_db1; + db2 *my_db2; + kdi_file *my_file; + if (imp < 0 || imp > 2) { + sprintf(AbortString,"%s: INVALID ACTION ( %d ) ON XSM FILE '%s'.",nomsub,(int)imp,namp); + xabort_c(AbortString); + } else if (strlen(namp) > 72) { + sprintf(AbortString,"%s: FINENAME '%s' EXCEEDING 72 CHARACTERS.",nomsub,namp); + xabort_c(AbortString); + } + *iplist = (xsm *) malloc(sizeof(**iplist)); + my_block2 = (block2 *) malloc(sizeof(*my_block2)); + + my_db1 = (db1 *) malloc(sizeof(*my_db1)); + my_db1->nad = 0; + my_db1->maxad = 0; + my_db1->idir = NULL; + (*iplist)->icang = my_db1; + + my_db2 = (db2 *) malloc(sizeof(*my_db2)); + my_db2->nad = 0; + my_db2->maxad = 0; + my_db2->iref = NULL; + my_db2->iofset = NULL; + my_db2->lg = NULL; + (*iplist)->icang2 = my_db2; + + (*iplist)->header = 200; + (*iplist)->listlen = -1; + (*iplist)->impf = imp; + (*iplist)->ibloc = my_block2; + (*iplist)->father = NULL; + strcpy((*iplist)->hname,namp); + my_file = (kdi_file *) kdiop_c(namp,imp); + if (my_file == NULL) { + sprintf(AbortString,"%s: UNABLE TO OPEN XSM FILE '%s'.",nomsub,namp); + xabort_c(AbortString); + } + my_block2->ifile = my_file; + if (impx > 1) + printf("%s: KDI FILE OPEN = %ld NAME = '%s' ACTION = %d.\n",nomsub,(long)my_file->fd,namp,(int)imp); + if (imp >= 1) { +/* RECOVER THE ROOT DIRECTORY IF THE XSM FILE ALREADY EXISTS. */ + irc=kdiget_c(my_block2->ifile, &ibuf, c__0, c__1); + if (irc != 0) goto L140; + strncpy(hbuf,(char*)&ibuf,4); + hbuf[4]='\0'; + if (strcmp(hbuf,"$XSM") != 0) { + sprintf(AbortString,"%s: WRONG HEADER ON XSM FILE '%s'.",nomsub,namp); + xabort_c(AbortString); + } + irc=kdiget_c(my_block2->ifile, &(my_block2->ioft), c__1, c__1); + if (irc != 0) goto L140; + irc=kdiget_c(my_block2->ifile, &(my_block2->idir), c__2, c__1); + if (irc != 0) goto L140; + (*iplist)->idir = my_block2->idir; + xsmdir(&c__1,my_block2); + my_block2->modif = 0; + if (impx > 0) { + printf("%s: XSM FILE RECOVERY. FILE = '%s'.\n",nomsub,namp); + printf("%6s HIGHEST ATTAINABLE ADDRESS = %d\n"," ",(int)my_block2->ioft); + printf("%6s ACTIVE DIRECTORY = %s\n"," ",my_block2->mynam); + } + } else { +/* NEW-FILE MODE. */ + (*iplist)->impf = 1; + (*iplist)->idir = iprim; + my_block2->ioft = iprim+klong; + my_block2->idir = iprim; + my_block2->iroot = -1; + my_block2->nmt = 0; + my_block2->link = iprim; + sprintf(my_block2->mynam,"/"); + memcpy((char*)&ibuf,"$XSM",sizeof(ibuf)); + irc=kdiput_c(my_block2->ifile, &ibuf, c__0, c__1); + if (irc != 0) goto L150; + irc=kdiput_c(my_block2->ifile, &(my_block2->ioft), c__1, c__1); + if (irc != 0) goto L150; + irc=kdiput_c(my_block2->ifile, &(my_block2->idir), c__2, c__1); + if (irc != 0) goto L150; + xsmdir(&c__2,my_block2); + my_block2->modif = 1; + } + return; +L140: + sprintf(AbortString,"%s: kdiget_c ERROR NB. %d ON XSM FILE '%s'.",nomsub,(int)irc,namp); + xabort_c(AbortString); +L150: + sprintf(AbortString,"%s: kdiput_c ERROR NB. %d ON XSM FILE '%s'.",nomsub,(int)irc,namp); + xabort_c(AbortString); +} + +void xsmrep(const char *namt, int_32 *ind, int_32 *idir, block2 *my_block2, int_32 *iii) +/* + *----------------------------------------------------------------------- + * + * find a block (record or directory) position in the active directory + * and related extents. + * + * input parameters: + * namt : character*12 name of the required block. + * ind : =1 search namt ; =2 search and positionning in an empty + * slot of the active directory if namt does not exists. + * idir : offset of active directory on xsm file. + * my_block2 : address of memory-resident xsm structure (block 2). + * + * output parameter: + * iii : return code. =0 if the block named namt does not exists; + * =position in the active directory extent if namt extsts. + * =0 or 1 if namt=' '. + * + *----------------------------------------------------------------------- + */ +{ + char *nomsub="xsmrep"; + int_32 i, ipos, ipos2, irc, irc2, istart; + char namp[13],nomC[25]; + + if (my_block2->idir != *idir) { +/* SWITCH TO THE CORRECT ACTIVE DIRECTORY (BLOCK 2). */ + if (my_block2->modif == 1) xsmdir(&c__2, my_block2); + my_block2->idir = *idir; + xsmdir(&c__1, my_block2); + } + if (strcmp(namt,"***HANDLE***") == 0) { + sprintf(AbortString,"%s: ***HANDLE*** IS A RESERVED KEYWORD.",nomsub); + xabort_c(AbortString); + } + strcpy(namp,namt); + if (strcmp(namp," ") == 0) strcpy(namp,"***HANDLE***"); + ipos = -1; + if (my_block2->nmt < iofmax) ipos = my_block2->idir; + if (my_block2->nmt == 0) goto L50; + for (i = 1; i <= my_block2->nmt; ++i) { + if (strcmp(namp,my_block2->cmt[i-1]) == 0) { +/* THE BLOCK ALREADY EXISTS. */ + *iii = i; + return; + } + } +/* THE BLOCK NAMP DOES NOT EXISTS IN THE ACTIVE DIRECTORY EXTENT. WE + SEARCH IN OTHER EXTENTS THAT BELONG TO THE ACTIVE DIRECTORY. */ + if (my_block2->idir != my_block2->link) { +/* RECOVER A NEW DIRECTORY EXTENT. */ + istart = my_block2->link; + if (my_block2->modif == 1) xsmdir(&c__2, my_block2); + my_block2->idir = istart; +L30: + xsmdir(&c__1, my_block2); + if (my_block2->nmt < iofmax) ipos = my_block2->idir; + for (i = 1; i <= my_block2->nmt; ++i) { + if (strcmp(namp,my_block2->cmt[i-1]) == 0) { +/* THE BLOCK NAMP WAS FOUND IN THE ACTIVE DIRECTORY EXTENT. */ + *iii = i; + return; + } + } + if (my_block2->link == istart) goto L50; + my_block2->idir = my_block2->link; + goto L30; + } +L50: + *iii = 0; + if (*ind == 1) return; + if (ipos >= 0 && ipos != my_block2->idir) { +/* AN EXTENT WITH AN EMPTY SLOT WAS FOUND. */ + if (my_block2->modif == 1) xsmdir(&c__2, my_block2); + my_block2->idir = ipos; + xsmdir(&c__1, my_block2); + } else if (ipos == -1) { +/* THE ACTIVE DIRECTORY IS FULL. CREATE AN EXTENT. */ + ipos = my_block2->link; + my_block2->link = my_block2->ioft; + if (my_block2->modif == 1) { + xsmdir(&c__2, my_block2); + } else { + ipos2 = my_block2->idir + 3; + irc=kdiput_c(my_block2->ifile, &(my_block2->link), ipos2, c__1); + if (irc != 0) goto L150; + } + my_block2->idir = my_block2->link; + my_block2->link = ipos; + my_block2->ioft += klong; + my_block2->nmt = 0; + } + ++my_block2->nmt; + *iii = my_block2->nmt; + my_block2->modif = 1; + my_block2->jlon[*iii - 1] = 0; + my_block2->jtyp[*iii - 1] = 99; + strcpy(my_block2->cmt[*iii - 1],namp); + return; + +L150: + irc2=kdicl_c(my_block2->ifile, c__1); + strcpy(nomC,(my_block2->ifile)->nom); + if (irc2 != 0) printf("%s: kdicl_c ERROR NB. %d ON XSM FILE '%s'.\n",nomsub,(int)irc2,nomC); + sprintf(AbortString,"%s: kdiput_c ERROR NB. %d ON XSM FILE '%s'.",nomsub,(int)irc,nomC); + xabort_c(AbortString); +} + +void xsmput_c(xsm **iplist, const char *namp, int_32 ilong, int_32 itype, int_32 *data1) +/* + *----------------------------------------------------------------------- + * + * copy a block from memory into the xsm file. + * + * input parameter: + * iplist : address of the handle to the xsm file. + * namp : character*12 name of the current block. + * ilong : number of information elements stored in the current block. + * itype : type of information elements stored in the current block. + * 0: directory 1: integer + * 2: single precision 3: character*4 + * 4: double precision 5: logical + * 6: complex + * data1 : information elements. dimension data1(ilong) + * + *----------------------------------------------------------------------- + */ +{ + char *nomsub="xsmput_c"; + char nomC[13]; + block2 *my_block2; + int_32 iii,irc; + if ((*iplist)->impf == 2) { + sprintf(AbortString,"%s: THE XSM FILE '%.60s' IS OPEN IN READ-ONLY MODE(1).", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } else if (ilong <= 0) { + sprintf(AbortString,"%s: INVALID LENGTH (%d) FOR NODE '%s' IN THE XSM FILE '%.60s'.", + nomsub,(int)ilong,namp,(*iplist)->hname); + xabort_c(AbortString); + } else if (itype <= 0 || itype >= 8) { + sprintf(AbortString,"%s: INVALID TYPE NUMBER (%d) FOR NODE '%s' IN THE XSM FILE '%.60s'.", + nomsub,(int)itype,namp,(*iplist)->hname); + xabort_c(AbortString); + } else if ((*iplist)->header != 200) { + sprintf(AbortString,"%s: THE XSM FILE '%.60s' HAVE THE WRONG HEADER.", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } + my_block2=(*iplist)->ibloc; + xsmrep(namp, &c__2, &(*iplist)->idir, my_block2, &iii); + my_block2->modif = 1; + int_32 jlong = ilong; + if (itype == 4 || itype == 6) jlong = 2*ilong; + if (jlong > my_block2->jlon[iii-1]) { + my_block2->iofs[iii-1] = my_block2->ioft; + my_block2->ioft += jlong; + } + my_block2->jlon[iii-1] = jlong; + my_block2->jtyp[iii-1] = itype; + irc=kdiput_c(my_block2->ifile, data1, my_block2->iofs[iii-1], jlong); + if (irc != 0) { + strcpy(nomC,(my_block2->ifile)->nom); + sprintf(AbortString,"%s: kdiput_c ERROR NB. %d ON XSM FILE '%s'.",nomsub,(int)irc,nomC); + xabort_c(AbortString); + } + return; +} +void xsmget_c(xsm **iplist, const char *namp, int_32 *data2) +/* + *----------------------------------------------------------------------- + * + * copy a block from the xsm file into memory. + * + * input parameters: + * iplist : address of the handle to the xsm file. + * namp : character*12 name of the current block. + * + * output parameter: + * data2 : information elements. dimension data2(ilong) + * + *----------------------------------------------------------------------- + */ +{ + char *nomsub="xsmget_c"; + char nomC[13]; + block2 *my_block2; + int_32 iii,irc; + if ((*iplist)->header != 200) { + sprintf(AbortString,"%s: THE XSM FILE '%.60s' HAVE THE WRONG HEADER.", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } + my_block2=(*iplist)->ibloc; + xsmrep(namp, &c__1, &(*iplist)->idir, my_block2, &iii); + if (iii > 0) { + irc=kdiget_c(my_block2->ifile, data2, my_block2->iofs[iii-1], my_block2->jlon[iii-1]); + if (irc != 0) { + strcpy(nomC,(my_block2->ifile)->nom); + sprintf(AbortString,"%s: kdiget_c ERROR NB. %d ON XSM FILE '%s'.",nomsub,(int)irc,nomC); + xabort_c(AbortString); + } + } else { + sprintf(AbortString,"%s: UNABLE TO FIND BLOCK '%s' INTO DIRECTORY '%s' IN THE XSM FILE '%.45s'.", + nomsub,namp,my_block2->mynam,(*iplist)->hname); + xabort_c(AbortString); + } + return; +} + +void xsmcl_c(xsm **iplist, int_32 istatu) +/* + *----------------------------------------------------------------------- + * + * close the xsm file. + * + * input parameters: + * iplist : address of the handle to the xsm file. + * istatu : =1 to keep the file at close ; =2 to destroy it. + * + *----------------------------------------------------------------------- + */ +{ + char *nomsub="xsmcl_c"; + block2 *my_block2; + int_32 i, irc, iii; + db1 *ipkeep; + db2 *ipkep2; + if ((*iplist)->impf == 2 && istatu == 2) { + sprintf(AbortString,"%s: CANNOT ERASE THE XSM FILE '%.60s' OPEN IN READ-ONLY MODE.", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } else if (istatu < 1 || istatu > 2) { + sprintf(AbortString,"%s: INVALID ACTION ( %d ) ON XSM FILE '%s'.", + nomsub,(int)istatu,(*iplist)->hname); + xabort_c(AbortString); + } else if ((*iplist)->header != 200) { + sprintf(AbortString,"%s: THE XSM FILE '%.60s' HAVE THE WRONG HEADER.", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } + ipkeep = (*iplist)->icang; + if (ipkeep->nad > 0) { + for (i = 1; i <= ipkeep->nad; ++i) free(ipkeep->idir[i-1]); + free(ipkeep->idir); + } + ipkep2 = (*iplist)->icang2; + if (ipkep2->nad > 0) { + for (i = 1; i <= ipkep2->nad; ++i) free(ipkep2->iofset[i-1]); /* rlsara_c() */ + free(ipkep2->iref); + free(ipkep2->iofset); + free(ipkep2->lg); + } + my_block2 = (*iplist)->ibloc; + + if (my_block2->modif == 1) { + if ((*iplist)->impf == 2) { + sprintf(AbortString,"%s: THE XSM FILE '%.60s' IS OPEN IN READ-ONLY MODE(2).", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } + xsmdir(&c__2, my_block2); + } + + if (my_block2->idir != (*iplist)->idir) { +/* SWITCH TO THE CORRECT ACTIVE DIRECTORY (BLOCK 2). */ + my_block2->idir = (*iplist)->idir; + xsmdir(&c__1, my_block2); + } + if (my_block2->iroot != -1) { + sprintf(AbortString,"%s: THE XSM FILE '%.60s' IS NOT ON ROOT DIRECTORY.", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } + if (my_block2->idir != iprim) { +/* SWITCH TO THE CORRECT ACTIVE DIRECTORY (BLOCK 2). */ + my_block2->idir = iprim; + xsmdir(&c__1, my_block2); + } + + irc = kdiget_c(my_block2->ifile, &iii, c__1, c__1); + if (irc != 0) goto L140; + if (my_block2->ioft > iii) { + if ((*iplist)->impf == 2) { + sprintf(AbortString,"%s: THE XSM FILE '%.60s' IS OPEN IN READ-ONLY MODE(3).", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } + irc = kdiput_c(my_block2->ifile, &(my_block2->ioft), c__1, c__1); + if (irc != 0) goto L150; + } + irc = kdicl_c(my_block2->ifile, istatu); + if (irc != 0) goto L160; + +/* RELEASE THE XSM FILE HANDLE. */ + free((*iplist)->icang); + free((*iplist)->icang2); + my_block2->ifile = NULL; + free(my_block2); + (*iplist)->header = 0; + free(*iplist); + *iplist = NULL; + return; + +L140: + sprintf(AbortString,"%s: kdiget_c ERROR NB. %d ON XSM FILE '%s'.",nomsub,(int)irc,(*iplist)->hname); + xabort_c(AbortString); +L150: + sprintf(AbortString,"%s: kdiput_c ERROR NB. %d ON XSM FILE '%s'.",nomsub,(int)irc,(*iplist)->hname); + xabort_c(AbortString); +L160: + sprintf(AbortString,"%s: kdicl_cS ERROR NB. %d ON XSM FILE '%s'.",nomsub,(int)irc,(*iplist)->hname); + xabort_c(AbortString); +} + +void xsmnxt_c(xsm **iplist, char *namp) +/* + *----------------------------------------------------------------------- + * + * find the name of the next block stored in the active directory. + * + * input parameters: + * iplist : address of the handle to the xsm file. + * namp : character*12 name of a block. if namp=' ' at input, find + * any name for any block stored in this directory. + * + * output parameters: + * namp : character*12 name of the next block. namp=' ' for an empty + * directory. + * + *----------------------------------------------------------------------- + */ +{ + char *nomsub="xsmnxt_c"; + block2 *my_block2; + int_32 iii; + + if ((*iplist)->header != 200) { + sprintf(AbortString,"%s: THE XSM FILE '%.60s' HAVE THE WRONG HEADER.", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } + my_block2 = (*iplist)->ibloc; + if (strcmp(namp," ") == 0) { + if (my_block2->idir != (*iplist)->idir) { +/* SWITCH TO THE CORRECT ACTIVE DIRECTORY (BLOCK 2). */ + if (my_block2->modif == 1) xsmdir(&c__2, my_block2); + my_block2->idir = (*iplist)->idir; + xsmdir(&c__1, my_block2); + } + iii = min(my_block2->nmt,1); + } else { + xsmrep(namp, &c__1, &(*iplist)->idir, my_block2, &iii); + } + if (iii == 0 && strcmp(namp, " ") == 0) { +/* EMPTY DIRECTORY */ + sprintf(AbortString,"%s: THE ACTIVE DIRECTORY '%s' OF THE XSM FILE '%.45s' IS EMPTY.", + nomsub,my_block2->mynam,(*iplist)->hname); + xabort_c(AbortString); + } else if (iii == 0) { + sprintf(AbortString,"%s: UNABLE TO FIND BLOCK '%s' INTO DIRECTORY '%s' IN THE XSM FILE '%.45s'.", + nomsub,namp,my_block2->mynam,(*iplist)->hname); + xabort_c(AbortString); + } else if (iii + 1 <= my_block2->nmt) { + strcpy(namp,my_block2->cmt[iii]); + return; + } +/* SWITCH TO THE NEXT DIRECTORY. */ + if (my_block2->idir != my_block2->link) { + if (my_block2->modif == 1) xsmdir(&c__2, my_block2); + my_block2->idir = my_block2->link; +/* RECOVER THE NEXT DIRECTORY. */ + xsmdir(&c__1, my_block2); + } + strcpy(namp,my_block2->cmt[0]); + if (strcmp(namp,"***HANDLE***") == 0) strcpy(namp," "); + return; +} + +void xsmlen_c(xsm **iplist, const char *namp, int_32 *ilong, int_32 *itype) +/* + *----------------------------------------------------------------------- + * + * return the length and type of a block. Return 0 if the block does not + * exists. + * + * input parameters: + * iplist : address of the handle to the xsm file. + * namp : character*12 name of the current block. + * ilong : number of information elements stored in the current block. + * ilong=-1 is returned for a scalar directory. + * ilong=0 if the block does not exists. + * itype : type of information elements stored in the current block. + * 0: directory 1: integer + * 2: single precision 3: character*4 + * 4: double precision 5: logical + * 6: complex 99: undefined + * + *----------------------------------------------------------------------- + */ +{ + char *nomsub="xsmlen_c"; + block2 *my_block2; + int_32 iii; + if ((*iplist)->header != 200) { + sprintf(AbortString,"%s: THE XSM FILE '%.60s' HAVE THE WRONG HEADER.", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } + my_block2=(*iplist)->ibloc; + xsmrep(namp, &c__1, &(*iplist)->idir, my_block2, &iii); + if (iii > 0) { + *ilong = my_block2->jlon[iii-1]; + *itype = my_block2->jtyp[iii-1]; + if (*itype == 4 || *itype == 6) *ilong=*ilong/2; + } else { + *ilong = 0; + *itype = 99; + } + return; +} +void xsminf_c(xsm **iplist, char *namxsm, char *nammy, int_32 *empty, int_32 *ilong, int_32 *access) +/* + *----------------------------------------------------------------------- + * + * recover global informations related to an xsm file. + * + * input parameters: + * iplist : address of the handle to the xsm file. + * + * output parameters: + * namxsm : character*12 name of the xsm file. + * nammy : charecter*12 name of the active directory. + * empty : =.true. if the active directory is empty. + * ilong : =-1: for a table; >0: number of list items. + * access : type of access. =1: object open for modification; + * =2: object in read-only mode. + * + *----------------------------------------------------------------------- + */ +{ + char *nomsub="xsminf_c"; + block2 *my_block2; + if ((*iplist)->header != 200) { + sprintf(AbortString,"%s: THE XSM FILE '%.60s' HAVE THE WRONG HEADER.", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } + my_block2=(*iplist)->ibloc; + if (my_block2->idir != (*iplist)->idir) { +/* SWITCH TO THE CORRECT ACTIVE DIRECTORY (BLOCK 2). */ + if (my_block2->modif == 1) xsmdir(&c__2, my_block2); + my_block2->idir = (*iplist)->idir; + xsmdir(&c__1, my_block2); + } + strcpy(namxsm,(*iplist)->hname); + strcpy(nammy,my_block2->mynam); + + *empty = (my_block2->nmt == 0); + *ilong = (*iplist)->listlen; + *access = (*iplist)->impf; + return; +} + +void xsmsix_c(xsm **iplist, const char *namp, int_32 iact) +/* + *----------------------------------------------------------------------- + * + * move in the scalar hierarchical structure of a xsm file. + * + * input parameters: + * iplist : address of the father/son table. + * namp : character*12 name of the son table if iact=1. + * not used if iact=0 or iact=2. + * iact : type of movement in the hierarchical structure. + * 0: move back to the root directory; + * 1: move to a son vectorial directory; + * 2: move back to the parent directory. + * + *----------------------------------------------------------------------- + */ +{ + char *nomsub="xsmsix_c"; + block2 *my_block2; + int_32 iii, lenold, idir=0, ityold; + xsm *iofset, *iofpre; + char nomC[13]; + + if (iact < 0 || iact > 2) { + sprintf(AbortString,"%s: INVALID ACTION (%d) ON THE XSM FILE '%.60s'.", + nomsub,(int)iact,(*iplist)->hname); + xabort_c(AbortString); + } else if ((*iplist)->header != 200) { + sprintf(AbortString,"%s: THE XSM FILE '%.60s' HAVE THE WRONG HEADER.", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } + if (iact == 1) { +/* MOVE TO A SON DIRECTORY. */ + my_block2=(*iplist)->ibloc; + xsmrep(namp, &c__2, &(*iplist)->idir, my_block2, &iii); + lenold = my_block2->jlon[iii-1]; + if (lenold == -1) lenold = 1; + ityold = my_block2->jtyp[iii-1]; + if (lenold == 0) { +/* CREATE A NEW SCALAR DIRECTORY EXTENT ON THE XSM FILE. */ + if ((*iplist)->impf == 2) { + printf("new directory name=%s\n",namp); + sprintf(AbortString,"%s: THE XSM FILE '%.60s' IS OPEN IN READ-ONLY MODE(4).", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } + my_block2->jlon[iii-1] = -1; + my_block2->jtyp[iii-1] = 0; + my_block2->iofs[iii-1] = my_block2->ioft; + idir = my_block2->iofs[iii-1]; + my_block2->ioft += klong; + xsmdir(&c__2, my_block2); + my_block2->iroot = my_block2->idir; + strcpy(my_block2->mynam,namp); + my_block2->idir = my_block2->iofs[iii-1]; + my_block2->nmt = 0; + my_block2->link = my_block2->idir; + my_block2->modif = 1; + } else if (lenold == 1 && ityold == 0) { + idir = my_block2->iofs[iii-1]; + } else if (ityold != 0) { + sprintf(AbortString,"%s: BLOCK '%s' IS NOT A DIRECTORY OF THE XSM FILE '%.60s'.", + nomsub,namp,(*iplist)->hname); + xabort_c(AbortString); + } + iofset = (xsm *) malloc(sizeof(*iofset)); + +/* COPY BLOCK1 */ + iofset->header = (*iplist)->header; + strcpy(iofset->hname,(*iplist)->hname); + iofset->listlen = -1; + iofset->impf = (*iplist)->impf; + iofset->idir = (*iplist)->idir; + iofset->ibloc = (*iplist)->ibloc; + iofset->icang = (*iplist)->icang; + iofset->icang2 = (*iplist)->icang2; + iofset->father = (*iplist)->father; + + xsmkep(iofset->icang, c__1, &iofset); + iofset->idir = idir; + iofset->father = *iplist; + *iplist = iofset; + } else if (iact == 0 || iact == 2) { +/* MOVE BACK TO THE ROOT OR PARENT DIRECTORY. */ +L50: + my_block2 = (*iplist)->ibloc; + if (my_block2->modif == 1) xsmdir(&c__2, my_block2); + if (my_block2->idir != (*iplist)->idir) { +/* SWITCH TO THE CORRECT ACTIVE DIRECTORY (BLOCK 2). */ + my_block2->idir = (*iplist)->idir; + xsmdir(&c__1, my_block2); + } + if (my_block2->iroot == -1) { + if (iact == 0) { + if ((*iplist)->header != 200) { + sprintf(AbortString,"%s: WRONG HEADER(1).",nomsub); + xabort_c(AbortString); + } + return; + } + sprintf(AbortString,"%s: THE XSM FILE '%.60s' IS ALREADY ON ROOT DIRECTORY.", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } + strcpy(nomC,my_block2->mynam); + iofset = *iplist; + *iplist = (*iplist)->father; + xsmrep(nomC, &c__1, &(*iplist)->idir, my_block2, &iii); + if (iii == 0) { + sprintf(AbortString,"%s: UNABLE TO STEP DOWN ON FATHER RECORD '%s' FOR XSM FILE '%.60s'.", + nomsub,namp,(*iplist)->hname); + xabort_c(AbortString); + } + iofpre = iofset; + xsmkep((*iplist)->icang, c__2, &iofpre); + free(iofset); + if (iact == 0 && (*iplist)->idir != iprim) { + goto L50; + } else if ((*iplist)->header != 200) { + sprintf(AbortString,"%s: WRONG HEADER(2).",nomsub); + xabort_c(AbortString); + } + } + return; +} + +void xsmdid_c(xsm **iplist, const char *namp, xsm **jplist) +/* + *----------------------------------------------------------------------- + * + * create/access a daughter associative table in a father table. + * + * input parameters: + * iplist : address of the father table. + * namp : character*12 name of the daughter associative table. + * + * output parameter: + * jplist : address of the daughter associative table. + * + *----------------------------------------------------------------------- + */ +{ + char *nomsub="xsmdid_c"; + block2 *my_block2; + int_32 iii, lenold, idir=0, ityold; + xsm *iofset; + + if ((*iplist)->header != 200) { + sprintf(AbortString,"%s: THE XSM FILE '%.60s' HAVE THE WRONG HEADER.", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } + my_block2=(*iplist)->ibloc; + xsmrep(namp, &c__2, &(*iplist)->idir, my_block2, &iii); + lenold = my_block2->jlon[iii-1]; + ityold = my_block2->jtyp[iii-1]; + if (lenold == 0) { +/* CREATE A NEW SCALAR DIRECTORY EXTENT ON THE XSM FILE. */ + if ((*iplist)->impf == 2) { + sprintf(AbortString,"%s: THE XSM FILE '%.60s' IS OPEN IN READ-ONLY MODE(5).", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } + my_block2->jlon[iii-1] = -1; + my_block2->jtyp[iii-1] = 0; + my_block2->iofs[iii-1] = my_block2->ioft; + idir = my_block2->iofs[iii-1]; + my_block2->ioft += klong; + xsmdir(&c__2, my_block2); + my_block2->iroot = my_block2->idir; + strcpy(my_block2->mynam,namp); + my_block2->idir = my_block2->iofs[iii-1]; + my_block2->nmt = 0; + my_block2->link = my_block2->idir; + my_block2->modif = 1; + } else if (lenold == -1 && ityold == 0) { + idir = my_block2->iofs[iii-1]; + } else { + sprintf(AbortString,"%s: BLOCK '%s' IS NOT AN ASSOCIATIVE TABLE OF THE XSM FILE '%.60s'.", + nomsub,namp,(*iplist)->hname); + xabort_c(AbortString); + } + iofset = (xsm *) malloc(sizeof(*iofset)); + *jplist = iofset; + +/* COPY BLOCK1 */ + (*jplist)->header = (*iplist)->header; + strcpy((*jplist)->hname,(*iplist)->hname); + (*jplist)->listlen = -1; + (*jplist)->impf = (*iplist)->impf; + (*jplist)->idir = idir; + (*jplist)->ibloc = (*iplist)->ibloc; + (*jplist)->icang = (*iplist)->icang; + (*jplist)->icang2 = (*iplist)->icang2; + (*jplist)->father = *iplist; + xsmkep((*iplist)->icang, c__1, &iofset); + return; +} + +void xsmlid_c(xsm **iplist, const char *namp, int_32 ilong, xsm **jplist) +/* + *----------------------------------------------------------------------- + * + * create/access the hierarchical structure of a list in a xsm file. + * + * input parameters: + * iplist : address of the father table. + * namp : character*12 name of the daughter list. + * ilong : dimension of the daughter list. + * + * output parameter: + * jplist : address of the daughter list. + * + *----------------------------------------------------------------------- + */ +{ + char *nomsub="xsmlid_c"; + char nomC[13]; + block2 *my_block2; + int_32 iii, irc, irc2, lenold, idir=0, i, idiold, ityold, iroold, *iivec; + xsm *iofset; + + if ((*iplist)->header != 200) { + sprintf(AbortString,"%s: THE XSM FILE '%.60s' HAVE THE WRONG HEADER.", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } else if (ilong <= 0) { + sprintf(AbortString,"%s: INVALID LENGTH (%d) FOR NODE '%s' IN THE XSM FILE '%.60s'.", + nomsub,(int)ilong,namp,(*iplist)->hname); + xabort_c(AbortString); + } + my_block2=(*iplist)->ibloc; + xsmrep(namp, &c__2, &(*iplist)->idir, my_block2, &iii); + lenold = my_block2->jlon[iii-1]; + ityold = my_block2->jtyp[iii-1]; + if ((ilong > lenold && ityold == 10) || lenold == 0) { +/* CREATE ILONG-LENOLD NEW LIST EXTENTS ON THE XSM FILE. */ + if ((*iplist)->impf == 2) { + sprintf(AbortString,"%s: THE XSM FILE '%.60s' IS OPEN IN READ-ONLY MODE(6).", + nomsub,(*iplist)->hname); + xabort_c(AbortString); + } + my_block2->jlon[iii-1] = ilong; + my_block2->jtyp[iii-1] = 10; + idiold = my_block2->iofs[iii-1]; + my_block2->iofs[iii-1] = my_block2->ioft; + idir = my_block2->iofs[iii-1]; + my_block2->ioft += ilong; + iroold = my_block2->idir; + xsmdir(&c__2, my_block2); + iivec = (int_32 *) malloc(ilong * sizeof(*iivec)); + if (lenold > 0) { + irc = kdiget_c(my_block2->ifile, iivec, idiold, lenold); + if (irc != 0) goto L110; + } + for (i = abs(lenold) + 1; i <= ilong; ++i) { + iivec[i-1] = my_block2->ioft; + my_block2->iroot = iroold; + strcpy(my_block2->mynam,namp); + my_block2->nmt = 0; + my_block2->idir = my_block2->ioft; + my_block2->ioft += klong; + my_block2->link = my_block2->idir; + xsmdir(&c__2, my_block2); + } + irc = kdiput_c(my_block2->ifile, iivec, idir, ilong); + if (irc != 0) goto L100; + free(iivec); + } else if (ilong <= lenold && ityold == 10) { + ilong = lenold; + idir = my_block2->iofs[iii-1]; + } else if (ityold != 10) { + sprintf(AbortString,"%s: BLOCK '%s' IS NOT A LIST OF THE XSM FILE '%.60s'.", + nomsub,namp,(*iplist)->hname); + xabort_c(AbortString); + } + iivec = (int_32 *) malloc(ilong * sizeof(*iivec)); + irc = kdiget_c(my_block2->ifile, iivec, idir, ilong); + if (irc != 0) goto L110; + *jplist = (xsm *) malloc(ilong * sizeof(**jplist)); + for (i = 0; i < ilong; ++i) { + iofset = *jplist + i; + +/* COPY BLOCK1 */ + iofset->header = (*iplist)->header; + strcpy(iofset->hname,(*iplist)->hname); + iofset->listlen = 0; + iofset->impf = (*iplist)->impf; + iofset->idir = iivec[i]; + iofset->ibloc = (*iplist)->ibloc; + iofset->icang = (*iplist)->icang; + iofset->icang2 = (*iplist)->icang2; + iofset->father = *iplist; + } + (*jplist)->listlen = ilong; + xsmkep((*iplist)->icang, c__1, jplist); + free(iivec); + return; + +L100: + irc2=kdicl_c(my_block2->ifile, c__1); + strcpy(nomC,(my_block2->ifile)->nom); + if (irc2 != 0) printf("%s: kdicl_c ERROR NB. %d ON XSM FILE '%s'.\n",nomsub,(int)irc2,nomC); + sprintf(AbortString,"%s: kdiput_c ERROR NB. %d ON XSM FILE '%s'.",nomsub,(int)irc,nomC); + xabort_c(AbortString); +L110: + irc2=kdicl_c(my_block2->ifile, c__1); + if (irc2 != 0) printf("%s: kdicl_c ERROR NB. %d ON XSM FILE '%s'.\n",nomsub,(int)irc2,nomC); + strcpy(nomC,(my_block2->ifile)->nom); + sprintf(AbortString,"%s: kdiget_c ERROR NB. %d ON XSM FILE '%s'.",nomsub,(int)irc,nomC); + xabort_c(AbortString); +} + +void xsmgpd_c(xsm **iplist, const char *namp, int_32 **iofdum) +/* + *----------------------------------------------------------------------- + * + * get a malloc pointer for an entry in the xsm file. + * + * input parameters: + * iplist : address of the handle to the xsm file. + * namp : character*12 name of the current block. + * + * output parameter: + * iofdum : malloc pointer to the xsm entry named namp. + * + *----------------------------------------------------------------------- + */ +{ + db2 *ipkep2; + int_32 i, i0, ilong, itylcm, n; + xsmlen_c(iplist,namp,&ilong,&itylcm); + if(itylcm == 4 || itylcm == 6) ilong = 2*ilong; + ipkep2 = (*iplist)->icang2; + n = ipkep2->nad; + for (i = n; i >= 1; --i) { + if (ipkep2->iref[i-1] == iofdum) { + i0 = i; + goto L10; + } + } + goto L20; +L10: + if (ilong == ipkep2->lg[i0-1]) { + *iofdum = ipkep2->iofset[i0-1]; + xsmget_c(iplist,namp,*iofdum); + return; + } + free(ipkep2->iofset[i0-1]); /* rlsara_c() */ + for (i = i0; i <= n-1; ++i) { + ipkep2->iref[i-1]=ipkep2->iref[i]; + ipkep2->iofset[i-1]=ipkep2->iofset[i]; + ipkep2->lg[i-1]=ipkep2->lg[i]; + } + --ipkep2->nad; + n = ipkep2->nad; +L20: + *iofdum = (int_32 *)malloc(ilong*sizeof(int_32)); /* setara_c(ilong) */ + xsmget_c(iplist,namp,*iofdum); + if (n + 1 > ipkep2->maxad) { + int_32 ***my_iref, **my_iofset, *my_lg; + ipkep2->maxad += maxit; + my_iref = (int_32 ***) malloc((ipkep2->maxad)*sizeof(*my_iref)); + my_iofset = (int_32 **) malloc((ipkep2->maxad)*sizeof(*my_iofset)); + my_lg = (int_32 *) malloc((ipkep2->maxad)*sizeof(*my_lg)); + for (i = 0; i < n; ++i) { + my_iref[i]=ipkep2->iref[i]; + my_iofset[i]=ipkep2->iofset[i]; + my_lg[i]=ipkep2->lg[i]; + } + if (n > 0) { + free(ipkep2->iref); + free(ipkep2->iofset); + free(ipkep2->lg); + } + ipkep2->iref=my_iref; + ipkep2->iofset=my_iofset; + ipkep2->lg=my_lg; + } + ipkep2->iref[n] = iofdum; + ipkep2->iofset[n] = *iofdum; + ipkep2->lg[n] = ilong; + ++ipkep2->nad; + return; +} + +void xsmppd_c(xsm **iplist, const char *namp, int_32 ilong, int_32 itype, int_32 *iofdum) +/* + *----------------------------------------------------------------------- + * + * add a new malloc pointer entry in the xsm file. + * + * input parameter: + * iplist : address of the handle to the xsm file. + * namp : character*12 name of the current block. + * ilong : number of information elements stored in the current block. + * itype : type of information elements stored in the current block. + * 0: directory 1: integer + * 2: single precision 3: character*4 + * 4: double precision 5: logical + * 6: complex + * iofdum : malloc pointer of the first information element. + * + *----------------------------------------------------------------------- + */ +{ + db2 *ipkep2; + int_32 i, i0, n; + xsmput_c(iplist,namp,ilong,itype,iofdum); + ipkep2 = (*iplist)->icang2; + n = ipkep2->nad; + for (i = n; i >= 1; --i) { + if (ipkep2->iofset[i-1] == iofdum) { + i0 = i; + goto L10; + } + } + goto L20; +L10: + for (i = i0; i <= n-1; ++i) { + ipkep2->iref[i-1]=ipkep2->iref[i]; + ipkep2->iofset[i-1]=ipkep2->iofset[i]; + ipkep2->lg[i-1]=ipkep2->lg[i]; + } + --ipkep2->nad; + if (ipkep2->nad == 0) { + free(ipkep2->iref); + free(ipkep2->iofset); + free(ipkep2->lg); + ipkep2->maxad = 0; + ipkep2->iref = NULL; + ipkep2->iofset = NULL; + ipkep2->lg = NULL; + } +L20: + free(iofdum); /* rlsara_c(iofdum) */ + iofdum = NULL; + return; +} |
