static char rcsver[] = "$Id: header.c,v 1.5 2000/06/05 17:14:50 asbms Exp $"; /** ** $Source: /tes/cvs/vanilla/header.c,v $ ** ** $Log: header.c,v $ ** Revision 1.5 2000/06/05 17:14:50 asbms ** Removed check for VANILLA keyword ** ** Revision 1.4 2000/05/26 15:04:52 asbms ** Added fixes for smoother return from errors ** ** Revision 1.3 2000/05/25 02:24:26 saadat ** Fixed IRTM temperature generation. ** ** Revision 1.2 1999/11/19 21:19:46 gorelick ** Version 3.1, post PDS delivery of 3.0 ** ** Revision 1.1.1.1 1999/10/15 19:30:35 gorelick ** Version 3.0 ** ** ** Revision 1.4 1998/11/12 22:58:55 gorelick ** first release version ** **/ #include #include "header.h" #include "proto.h" #include "io_lablib3.h" #define GetKey(ob, name) OdlFindKwd(ob, name, NULL, 0, ODL_THIS_OBJECT) FIELD *MakeField(OBJDESC *, LABEL *); int DetermineFieldType(char *type, int size); IFORMAT eformat_to_iformat(EFORMAT e); void MakeBitFields(OBJDESC *col, FIELD *f, LIST *list); FIELD * MakeBitField(OBJDESC *col, FIELD *f); EFORMAT ConvertType(char *type); /** ** LoadLabel() - Read and decode a PDS label, including individual fields. **/ LABEL * LoadLabel(char *fname) { OBJDESC *ob, *tbl, *col; KEYWORD *kw; FIELD *f; LIST *list; LABEL *l; int i; ushort scope; int reclen, nfields; char *name, *alias = NULL; char *Id; ob = OdlParseLabelFile(fname, NULL, ODL_EXPAND_STRUCTURE, 1); if (ob == NULL) { fprintf(stderr, "Unable to read file: %s\n", fname); return (NULL); } /* find the first (and only?) table object */ if ((tbl = OdlFindObjDesc(ob,"TABLE",NULL,NULL, 0, ODL_TO_END)) == NULL) { fprintf(stderr, "Unable to find TABLE object: %s\n", fname); fprintf(stderr, "Is this a vanilla file?\n"); return (NULL); } if ((kw = OdlFindKwd(tbl, "ROW_BYTES", NULL,0, ODL_THIS_OBJECT)) != NULL) { reclen = atoi(OdlGetKwdValue(kw)); } else { fprintf(stderr, "Unable to find keyword: ROW_BYTES: %s\n", fname); fprintf(stderr, "Is this a vanilla file? Is it's ^STRUCTURE file ok?\n"); return (NULL); } if ((kw = OdlFindKwd(tbl, "COLUMNS", NULL, 0, ODL_THIS_OBJECT)) != NULL) { nfields = atoi(OdlGetKwdValue(kw)); } else { fprintf(stderr, "Unable to find keyword: COLUMNS\n"); return (NULL); } if ((kw = OdlFindKwd(tbl, "NAME", NULL, 0, ODL_THIS_OBJECT)) != NULL) { name = OdlGetKwdValue(kw); } l = calloc(1, sizeof(LABEL)); l->reclen = reclen; l->nfields = nfields; l->name = name; /** ** get all the column descriptions **/ list = new_list(); i = 0; scope = ODL_CHILDREN_ONLY; col = tbl ; while ((col = OdlNextObjDesc(col, 0, &scope)) != NULL) { if ((f = MakeField(col, l)) != NULL) { list_add(list, f); i++; /** ** Fake up some additional fields for bit columns. **/ if (f->eformat == MSB_BIT_FIELD) { MakeBitFields(col, f, list); } } } if (i != nfields) { fprintf(stderr, "Wrong number of column definitions. Expected %d, got %d.\n", nfields,i); } l->fields = list; /** ** Get list of key fields **/ if ((kw = GetKey(tbl, "PRIMARY_KEYS")) != NULL || (kw = GetKey(tbl, "PRIMARY_KEY")) != NULL || (kw = GetKey(tbl, "KEYS")) != NULL) { int j; LIST *keylist; FIELD *f; char keyname[256]; char **array; i = OdlGetAllKwdValuesArray(kw, &array); keylist = new_list(); for (j = 0; j < i; j++) { strcpy(keyname, &array[j][1]); keyname[strlen(keyname) - 1] = 0; if ((f = FindFieldInLabel(keyname, l)) == NULL) { fprintf(stderr, "Unable to find key: \"%s\" in label \"%s\"\n", keyname, l->name); return(NULL); } list_add(keylist, f); } l->keys = keylist; } return (l); } /** ** Convert a field description into a FIELD struct **/ FIELD * MakeField(OBJDESC *col, LABEL *l) { FIELD *f; VARDATA *vardata; KEYWORD *kw; int i = 0; char *ptr; do { f = (FIELD *) calloc(1, sizeof(FIELD)); f->label = l; if ((kw = GetKey(col, "NAME")) == NULL) { fprintf(stderr, "Column %d has no name.\n", i); break; } f->name = OdlGetKwdValue(kw); f->alias = NULL; if ((kw = GetKey(col, "ALIAS_NAME")) != NULL) { f->alias = OdlGetKwdValue(kw); } if ((kw = GetKey(col, "START_BYTE")) == NULL) { fprintf(stderr, "Column %s: START_BYTE not specified.\n", f->name); break; } f->start = atoi(OdlGetKwdValue(kw)) - 1; if ((kw = GetKey(col, "BYTES")) == NULL) { fprintf(stderr, "Column %s: BYTES not specified.\n", f->name); break; } f->size = atoi(OdlGetKwdValue(kw)); if ((kw = GetKey(col, "ITEMS")) != NULL) { f->dimension = atoi(OdlGetKwdValue(kw)); /** ** If BYTES was specified, this will overwrite the value ** with the indivdual element size, as we expect. **/ if ((kw = GetKey(col, "ITEM_BYTES")) != NULL) { f->size = atoi(OdlGetKwdValue(kw)); } else { fprintf(stderr, "Column %s: ITEM_BYTES not specified, dividing BYTES by ITEMS.\n", f->name); f->size = f->size / f->dimension; } } if ((kw = GetKey(col, "DATA_TYPE")) == NULL) { fprintf(stderr, "Column %s: DATA_TYPE not specified.\n", f->name); break; } f->type = OdlGetKwdValue(kw); if ((f->eformat = ConvertType(f->type)) == INVALID_EFORMAT) { fprintf(stderr, "Unrecognized type: %s, %s %d bytes\n", f->name, f->type, f->size); break; } f->iformat = eformat_to_iformat(f->eformat); if ((kw = GetKey(col, "SCALING_FACTOR")) != NULL) { f->scale = atof(OdlGetKwdValue(kw)); } if ((kw = GetKey(col, "OFFSET")) != NULL) { f->offset = atof(OdlGetKwdValue(kw)); } if ((kw = GetKey(col, "VAR_RECORD_TYPE")) != NULL) { ptr = OdlGetKwdValue(kw); vardata = f->vardata = calloc(1, sizeof(VARDATA)); if (!strcmp(ptr, "VAX_VARIABLE_LENGTH")) vardata->type = VAX_VAR; else if (!strcmp(ptr, "Q15")) vardata->type = Q15; else { fprintf(stderr, "Unrecognized VAR_DATA_TYPE: %s\n", ptr); } if ((kw = GetKey(col, "VAR_ITEM_BYTES")) != NULL) { vardata->size = atoi(OdlGetKwdValue(kw)); if ((kw = GetKey(col, "VAR_DATA_TYPE")) != NULL) { ptr = OdlGetKwdValue(kw); } else { fprintf(stderr, "VAR_DATA_TYPE not specified for field: %s\n", f->name); exit(1); } if ((vardata->eformat = ConvertType(ptr)) == INVALID_EFORMAT) { fprintf(stderr, "Unrecognized vartype: %s, %s %d bytes\n", f->name, ptr, vardata->size); } vardata->iformat = eformat_to_iformat(vardata->eformat); } else { fprintf(stderr, "VAR_ITEM_BYTES not specified for field: %s\n", f->name); exit(1); } } if (f->eformat == BYTE_OFFSET) { f->eformat = MSB_INTEGER; f->iformat = eformat_to_iformat(f->eformat); vardata = f->vardata = calloc(1, sizeof(VARDATA)); vardata->size = 2; vardata->eformat = MSB_INTEGER; vardata->iformat = INT; vardata->type = Q15; } return(f); } while(0); return(NULL); } void MakeBitFields(OBJDESC *col, FIELD *f, LIST *list) { ushort scope; FIELD *b; scope = ODL_CHILDREN_ONLY; while ((col = OdlNextObjDesc(col, 0, &scope)) != NULL) { if ((b = MakeBitField(col, f)) != NULL) { list_add(list, b); } } } FIELD * MakeBitField(OBJDESC *col, FIELD *f) { FIELD *f2; KEYWORD *kw; BITFIELD *b; char name[256], *ptr; int i = 1; /** ** Do this once, and allow for breaks **/ do { f2 = (FIELD *) calloc(1, sizeof(FIELD)); *f2 = *f; b = (BITFIELD *) calloc(1, sizeof(BITFIELD)); f2->bitfield = b; if ((kw = GetKey(col, "NAME")) == NULL) { fprintf(stderr, "Bitfield %d has no name.\n", i); break; } sprintf(name, "%s:%s", f->name, OdlGetKwdValue(kw)); f2->name = strdup(name); if ((kw = GetKey(col, "ALIAS_NAME")) != NULL) { sprintf(name, "%s:%s", f->name, OdlGetKwdValue(kw)); f2->alias = strdup(name); } if ((kw = GetKey(col, "BIT_DATA_TYPE")) == NULL) { fprintf(stderr, "Bitfield %s has no data type.\n", f2->name); break; } ptr = OdlGetKwdValue(kw); b->type = ConvertType(ptr); /* b->type contains the EFORMAT */ f2->iformat = eformat_to_iformat(b->type); /* Saadat - I think! */ if ((kw = GetKey(col, "START_BIT")) == NULL) { fprintf(stderr, "Bitfield %s has no start bit.\n", f2->name); break; } b->start_bit = atoi(OdlGetKwdValue(kw)); if ((kw = GetKey(col, "BITS")) == NULL) { fprintf(stderr, "Bitfield %s has no BITS value.\n", f2->name); break; } b->bits = atoi(OdlGetKwdValue(kw)); b->shifts = (f->size * 8) - b->start_bit - b->bits + 1; /* b->mask = (1 << b->bits) - 1; -- fails for bits=32 */ b->mask = UINT_MAX; b->mask >>= -(b->bits - 32); return(f2); } while (0); return(NULL); } IFORMAT eformat_to_iformat(EFORMAT e) { switch(e) { case MSB_INTEGER: case ASCII_INTEGER: return(INT); case MSB_BIT_FIELD: case MSB_UNSIGNED_INTEGER: case BYTE_OFFSET: return(UINT); case IEEE_REAL: case ASCII_REAL: return ( REAL ); case CHARACTER: return ( STRING ); default: fprintf(stderr, "Unrecognized etype: %d\n", e); } return INVALID_IFORMAT; } EFORMAT ConvertType(char *type) { if (!strcasecmp(type, "MSB_INTEGER") || !strcasecmp(type, "SUN_INTEGER") || !strcasecmp(type, "MAC_INTEGER") || !strcasecmp(type, "INTEGER")) { return(MSB_INTEGER); } else if (!strcasecmp(type, "MSB_UNSIGNED_INTEGER") || !strcasecmp(type, "SUN_UNSIGNED_INTEGER") || !strcasecmp(type, "MAC_UNSIGNED_INTEGER") || !strcasecmp(type, "UNSIGNED_INTEGER")) { return(MSB_UNSIGNED_INTEGER); } else if (!strcasecmp(type, "IEEE_REAL") || !strcasecmp(type, "SUN_REAL") || !strcasecmp(type, "MAC_REAL") || !strcasecmp(type, "REAL")) { return(IEEE_REAL); } else if (!strcasecmp(type, "CHARACTER")) { return(CHARACTER); } else if (!strcasecmp(type, "ASCII_INTEGER")) { return(ASCII_INTEGER); } else if (!strcasecmp(type, "ASCII_REAL")) { return(ASCII_REAL); } else if (!strcasecmp(type, "BYTE_OFFSET")) { return(BYTE_OFFSET); } else if (!strcasecmp(type, "MSB_BIT_STRING")) { return(MSB_BIT_FIELD); } return(INVALID_EFORMAT); } /** ** Given a field name, locate it in the list of labels. **/ FIELD * FindField(char *name, LIST *tables) { char buf[256]; char *p; char *field_name; char *label_name; int i; TABLE *t; LABEL *l; FIELD *f; strcpy(buf, name); if ((p = strchr(buf, '.')) != NULL) { *p = '\0'; label_name = buf; field_name = p + 1; } else { label_name = NULL; field_name = buf; } /** ** If this field name includes a dimension, get rid of it **/ if ((p = strchr(field_name, '[')) != NULL) { *p = '\0'; } for (i = 0; i < tables->number; i++) { t = (tables->ptr)[i]; l = t->label; /* ** If the user told us what struct the field is in, skip all others */ if (label_name && strcasecmp(label_name, l->name)) continue; if ((f = FindFieldInLabel(field_name, l)) != NULL) { return(f); } } return (NULL); } FIELD * FindFieldInLabel(char *name, LABEL * l) { int i; FIELD **f = (FIELD **) l->fields->ptr; int nfields = l->fields->number; for (i = 0; i < nfields; i++) { if (!strcasecmp(name, f[i]->name)) { return (f[i]); } if (f[i]->alias && !strcasecmp(name, f[i]->alias)) { return (f[i]); } } return (NULL); } /** ** Load the header values specific to an individual file **/ FRAGMENT * LoadFragment(char *fname, TABLE *table) { OBJDESC *ob, *tbl, *col; KEYWORD *kw; LIST *startlist=NULL, *endlist=NULL; FRAGMENT *f; int rows; int offset; struct stat sbuf; if (stat(fname, &sbuf) == -1) { fprintf(stderr, "Unable to find file: %s\n", fname); return(NULL); } ob = OdlParseLabelFile(fname, NULL, ODL_EXPAND_STRUCTURE, 1); if (ob == NULL) { fprintf(stderr, "Unable to read file: %s\n", fname); return (NULL); } if ((kw = OdlFindKwd(ob, "^TABLE", NULL, 0, ODL_THIS_OBJECT)) != NULL) { offset = atoi(OdlGetKwdValue(kw)); } else { fprintf(stderr, "Unable to find table pointer (^TABLE) in: %s\n", fname); return (NULL); } /* find the first (and only?) table object */ if ((tbl = OdlFindObjDesc(ob, "TABLE", NULL, NULL, 0, ODL_TO_END)) == NULL) { fprintf(stderr, "Unable to find TABLE object: %s\n", fname); return (NULL); } if ((kw = OdlFindKwd(tbl, "ROWS", NULL,0, ODL_THIS_OBJECT)) != NULL) { rows = atoi(OdlGetKwdValue(kw)); } else { fprintf(stderr, "Unable to find keyword ROWS: %s\n", fname); return (NULL); } if ((kw = GetKey(tbl, "START_KEYS")) != NULL || (kw = GetKey(tbl, "START_PRIMARY_KEY")) != NULL) { int i,j; char **array; DATA *dataval; FIELD **keys = (FIELD **)table->label->keys->ptr; i = OdlGetAllKwdValuesArray(kw, &array); startlist = new_list(); dataval = calloc(i, sizeof(DATA)); for (j = 0; j < i; j++) { dataval[j] = ConvertASCIItoData(array[j], keys[j]->iformat); list_add(startlist, &dataval[j]); } } else if ((kw = GetKey(tbl, "START_KEY")) != NULL) { DATA *dataval; FIELD **keys = (FIELD **)table->label->keys->ptr; startlist = new_list(); dataval = calloc(1, sizeof(DATA)); dataval[0] = ConvertASCIItoData(OdlGetKwdValue(kw), keys[0]->iformat); list_add(startlist, &dataval[0]); } if ((kw = GetKey(tbl, "END_KEYS")) != NULL || (kw = GetKey(tbl, "STOP_PRIMARY_KEY")) != NULL) { int i,j; char **array; DATA *dataval; FIELD **keys = (FIELD **)table->label->keys->ptr; i = OdlGetAllKwdValuesArray(kw, &array); endlist = new_list(); dataval = calloc(i, sizeof(DATA)); for (j = 0; j < i; j++) { dataval[j] = ConvertASCIItoData(array[j], keys[j]->iformat); list_add(endlist, &dataval[j]); } } else if ((kw = GetKey(tbl, "STOP_KEY")) != NULL) { DATA *dataval; FIELD **keys = (FIELD **)table->label->keys->ptr; endlist = new_list(); dataval = calloc(1, sizeof(DATA)); dataval[0] = ConvertASCIItoData(OdlGetKwdValue(kw), keys[0]->iformat); list_add(endlist, &dataval[0]); } f = calloc(1, sizeof(FRAGMENT)); /** ** This is the all important ^PTR conversion **/ f->offset = (offset - 1) * table->label->reclen; f->nrows = rows; f->start_keys = startlist; f->end_keys = endlist; f->sbuf = sbuf; if (sbuf.st_size != f->offset + f->nrows * table->label->reclen) { fprintf(stderr, "File is an odd size: %s\n", fname); } return(f); } void FreeFragment(FRAGMENT *f) { list_free(f->start_keys); list_free(f->end_keys); free(f); }