/* Revision logs: 16Jul97 /atn: only clr Encoder section of db tables; chg warning to stdout; */ #include #include #include #include #include #include "grib_lookup.h" /* combined lookup structs */ #include "dprints.h" /* for dprints */ #include "gribfuncs.h" /* prototypes */ extern PARM_DEFN db_parm_tbl[]; /* parm conversion info */ extern LVL_DEFN db_lvl_tbl[]; /* level conversion info */ extern MODEL_DEFN db_mdl_tbl[]; /* model conversion info */ extern GEOM_DEFN db_geom_tbl[]; /* Geom conversion info */ /* **************************************************************************** * A. FUNCTION: ld_enc_lookup * This function reads in the information from an external Lookup * table used by the GRIB Encoder (ie: neons2grib.tab). This info * is used to convert Databse codes to the GRIB Code Numbers. * * INTERFACE: * int ld_enc_lookup (lookup_fn, errmsg) * * ARGUMENTS (I=input, O=output, I&O=input and output): * (I) char *lookup_fn; Name of Lookup file to read from; * (O) char *errmsg REturned filled if error occurred; * * RETURN CODE: * 0> successful, the following pre-defined arrays required for * encoding GRIB messages are filled= * PARM_DEFN db_parm_tbl[NPARM * MAX_PARM_TBLS]; (parameter info) * LVL_DEFN db_lvl_tbl[NLEV]; (level info) * MODEL_DEFN db_mdl_tbl[NMODEL]; (model info) * GEOM_DEFN db_geom_tbl[NGEOM]; (geometry info) * 1> file open error or got error/eof while reading; errmsg filled; **************************************************************************** - only break out of curr Loop if sees next section's header string; */ #if PROTOTYPE_NEEDED int ld_enc_lookup ( char *lookup_fn, char *errmsg) #else int ld_enc_lookup ( lookup_fn, errmsg) char *lookup_fn; char *errmsg; #endif { FILE *infile; char *func="ld_enc_lookup"; /* name of function */ char *ptr, temp[200], TableCode, dummy[100]; int stat=1, num, LineRead, cnt, code=0, indx0= 0; int Indx, indxA=0, indxB=0, indxC=0, indxD=0, indxE= 0; int *indxptr; char *px; char achDBsField[30]; /* DBs Field Name */ char strDSF[50],strGribCode[50], strScale[50], strOffset[50]; char subtbl[20]; /* (0:maintbl) or (a/b/c/d/e:subtabl)*/ int GribCode; /* GRIB Code Number */ float fScale; /* Scale */ float fOffset; /* Offset */ short sDSF; /* DSF */ PARM_DEFN *parmptr; /* ptr to desired cell w/in Parm arr*/ DPRINT2 ("Entering %s\nlookup %s\n", func, lookup_fn); /* * * A.0 CLEAR out all lookup arrays ! Encoder section only */ for (num=0; num < NPARM ; num++) { db_parm_tbl[num].usParm_id= num; db_parm_tbl[num].usParm_sub= 0; /* not used for main tbl */ db_parm_tbl[num].db_name[0] = '\0'; db_parm_tbl[num].fScale = 1.; db_parm_tbl[num].fOffset = 0.; db_parm_tbl[num].sDSF = 0; } for (num=NPARM; num < NPARM * MAX_PARM_TBLS; num++) { /* for sub-tbls */ db_parm_tbl[num].usParm_id= 250 + num / NPARM; db_parm_tbl[num].usParm_sub= num % NPARM; db_parm_tbl[num].db_name[0] = '\0'; db_parm_tbl[num].fScale = 1.; db_parm_tbl[num].fOffset = 0.; db_parm_tbl[num].sDSF = 0; } for (num=0; num < NLEV; num++) { db_lvl_tbl[num].usLevel_id = num; db_lvl_tbl[num].db_name[0] = '\0'; db_lvl_tbl[num].fScale = 1.; db_lvl_tbl[num].fOffset = 0.; } for (num=0; num < NMODEL; num++) { db_mdl_tbl[num].usModel_id = num; db_mdl_tbl[num].db_name[0] = '\0'; } for (num=0; num < NGEOM; num++) { db_geom_tbl[num].usGeom_id = num; db_geom_tbl[num].db_name[0] = '\0'; } /* * * A.1 OPEN Lookup file for reading * RETURN 1 if fails; */ infile = fopen(lookup_fn, "r"); if (infile==NULL) { DPRINT2 ("%s: failed to open %s\n", func, lookup_fn); sprintf (errmsg ,"%s: failed to open %s\n", func, lookup_fn); goto BYE; } /****Database's PARM TABLE -- (0/A/B/C/D/E) *** Sample: NEONS to GRIB Parameter Table NEONS FIELD TABLE CODE GRIB CODE SCALE OFFSET DSF =========== ========== ========= ===== ====== === pres 0 001 1.0 0.0 1 pres 0 002 1.0 0.0 1 * * *** Database's Parameter Defn conversion info *** * A.2 KEEP reading until last of Header/Comment line (see '===') * RETURN error if fails */ LineRead = 0; while (strstr (temp, "===") == NULL) { fgets(temp, sizeof(temp), infile); /* skip Comment/Header lines */ LineRead++; if (feof(infile) || ferror(infile)) { DPRINT1 ("%s: got EOF/ERROR before loading DBs PARM info\n", func); sprintf(errmsg, "%s: got EOF/ERROR before loading DBs PARM info (%s:line %d)\n", func , lookup_fn, LineRead); goto BYE; } } /* * * A.3 FOR (successfully read a line from file) DO * BREAK out of loop if sees Header of next Table * EXTRACT next DBs's Parameter info from line read * IF (fails) SKIP rest of Parm defn ; * !parm_name, tblcode, parmid, scalefctr, offset, Decsclfctr; * DROP line if Parm id is out of range * DROP line if Table Code is not (0/A/B/C/D/E) * DROP defn if Code has already been defined; * STORE in Parm Array cell whose index equals Parmid * ENDFOR */ for (cnt=0; fgets(temp, sizeof(temp), infile)!=NULL; ) { LineRead++; for (ptr=temp; *ptr==' '; ptr++) ; if (*ptr == '#') continue; if (strstr(temp, "to GRIB Level Table") != NULL) break; /* END OF CURR SECT */ if ((num= sscanf (temp,"%s%s%s%s%s%s%s", achDBsField, subtbl, strGribCode, strScale, strOffset, strDSF, dummy)) != 6) { if (num>0) fprintf(stdout,"Warning: unmatched Parm args, drop line %d in %s\n", LineRead, lookup_fn); continue; } for (px=strGribCode; *px; px++) if (!isdigit(*px)) { fprintf(stdout, "Warning: invalid GRIB code, drop line %d in %s\n", LineRead, lookup_fn); continue; } GribCode = atoi(strGribCode); fScale = (float) atof(strScale); fOffset = (float) atof(strOffset); sDSF = (short) atoi(strDSF); if (GribCode < 0 || GribCode >= NPARM) { fprintf(stdout, "Warning: ParmId '%d' out of range, drop line %d in %s\n", GribCode, LineRead, lookup_fn); continue; } if (strlen(subtbl) > 1) { fprintf(stdout, "Warning: Invalid bad TableCode '%s', drop line %d in %s;\n", subtbl, LineRead, lookup_fn); continue; } /* depending on which Table Code it is, entry will be stored in its corresponding Parameter Table; >>> if Tablecode is '0', store at array index PARM_ID; >>> if Tablecode is 'A/B/C/D/E', >>> then store at array index [NPARM*(PARM_ID-249) + PARM_SUB]; >>> UNDEFINED IDS WILL HAVE EMPTY CELLS; */ TableCode = (isalpha(*subtbl) ? tolower(*subtbl) : *subtbl); if (TableCode=='0') { Indx = 0; parmptr = db_parm_tbl + GribCode; parmptr->usParm_id = (unsigned short) GribCode; parmptr->usParm_sub = 0; } else if (TableCode>= 'a' && TableCode <= 'e') { if (GribCode==0) { fprintf(stdout, "Warning: Cannot use Parmid 0 for sub-tbl, drop line %d in %s\n" , LineRead, lookup_fn); continue; } Indx = 256 * (TableCode-'a'+1); /* 'a':256-.. 'b':512-.. */ parmptr = db_parm_tbl + Indx + GribCode; /* actual Index */ parmptr->usParm_id = 250 + (TableCode-'a'); parmptr->usParm_sub = (unsigned short) GribCode; } else { fprintf(stdout, "Warning: Invalid Table '%s' (0,A-E only), drop line %d in %s\n", subtbl, LineRead, lookup_fn); continue; } if (parmptr->db_name[0] != '\0') { /* drop line if Duplicate */ fprintf(stdout, "Warning: duplic Parm %d in Tbl %c (Index=%d), drop line %d in %s\n", parmptr->usParm_id, TableCode, PARMTBL_INDX(parmptr->usParm_id, parmptr->usParm_sub), LineRead, lookup_fn); continue; } strcpy (parmptr->db_name, achDBsField); parmptr->fScale = fScale; parmptr->fOffset = fOffset; parmptr->sDSF = sDSF; ++cnt; /* keep track of #entries loaded */ DPRINT9( "(+)T2-%c cd=%d: Parm=%d sub=%d, INDX=%d, dbnm=%s Scl=%.2f Ofs=%.2f D=%d\n" , TableCode, GribCode, parmptr->usParm_id, parmptr->usParm_sub,Indx+GribCode, parmptr->db_name, parmptr->fScale, parmptr->fOffset, parmptr->sDSF); } /* * DEBUG print */ DPRINT1("Parameter table has %d entries\n", cnt); /******** Database's LEVEL TABLE ******* Sample: NEONS to GRIB Level Table (FNMOC VERSION) NEONS Level Type GRIB CODE SCALE OFFSET ================ ========= ===== ====== surface 001 1.0 0.0 isth_lvl 004 0.0 273.16 trpp_lvl 007 1.0 0.0 * * *** DBs's Level Defn conversion info *** * A.4 KEEP reading until last of Header/Comment line (see '===') * RETURN error if fails */ while (strstr (temp, "====") == NULL) { fgets(temp, sizeof(temp), infile); /* skip Comment/Header lines */ LineRead++; if (feof(infile) || ferror(infile)) { DPRINT1 ("%s: got EOF/ERROR before loading DBs LEVEL info\n",func); sprintf(errmsg, "%s: got EOF/ERROR before loading LEVEL info (line %d in %s)\n", func , LineRead, lookup_fn); goto BYE; } } /* * A.5 FOR (successfully read a line from file) DO * BREAK out of loop if sees Header of next Table * EXTRACT next DBs's Level info into Level Array: * !format= level_type, level_id, scale, offset * DROP line if not enough arguments * DROP line if Duplicate Parm defn * STORE in Level Array cell whose index equals Level id * ENDFOR */ for (cnt=0; fgets(temp, sizeof(temp), infile) != NULL; ) { LineRead++; if (strstr(temp, "to GRIB Model Table") != NULL) break; /* Assume end of section */ for (ptr=temp; *ptr==' '; ptr++) ; if (*ptr == '#') continue; if ((num= sscanf (temp, "%s%s%s%s%s", achDBsField, strGribCode, strScale, strOffset, dummy)) != 4) { if (num>0) fprintf(stdout,"Warning: unmatched Level args, drop line %d in %s\n", LineRead, lookup_fn); continue; } GribCode = atoi(strGribCode); fScale = (float) atof(strScale); fOffset = (float) atof(strOffset); if (GribCode < 0 || GribCode >= NLEV) { fprintf(stdout, "Warning: Level_id '%d' out of range, drop line %d in %s\n" ,GribCode, LineRead, lookup_fn); continue; } if (db_lvl_tbl[GribCode].db_name[0] != '\0') { fprintf(stdout, "Warning: duplic Level %d, drop defn ending on line %d in %s\n", GribCode, LineRead, lookup_fn); continue; } db_lvl_tbl[GribCode].usLevel_id = (unsigned short) GribCode; strncpy (db_lvl_tbl[GribCode].db_name, achDBsField, sizeof(db_lvl_tbl[GribCode].db_name)-1); db_lvl_tbl[GribCode].fScale = fScale; db_lvl_tbl[GribCode].fOffset = fOffset; ++cnt; /* number loaded */ DPRINT4("(+) Level=%d, db_name=%s, Scl=%f, Offs=%f\n", db_lvl_tbl[GribCode].usLevel_id, db_lvl_tbl[GribCode].db_name, db_lvl_tbl[GribCode].fScale, db_lvl_tbl[GribCode].fOffset); } /* * DEBUG print */ DPRINT1("Level table has %d entries\n", cnt); /*** Database's MODEL TABLE*** Sample: NEONS to GRIB Model ID Table (FNMOC VERSION) NEONS Model Name GRIB CODE ================ ========= NORAPS 001 COAMPS 002 * * *** Database 's Model Defn conversion info *** * A.6 KEEP reading until last of Header/Comment line (see '===') * RETURN error if fails */ while (strstr (temp, "====") == NULL) { fgets(temp, sizeof(temp), infile); /* skip Comment/Header lines */ LineRead++; if (feof(infile) || ferror(infile)) { DPRINT1 ("%s: got EOF/ERROR before loading MODEL info\n",func); sprintf(errmsg, "%s: got EOF/ERROR before loading MODEL info (line %d in %s)\n", func , LineRead, lookup_fn); goto BYE; } } /* * A.7 FOR (successfully read a line from file) DO * BREAK out of loop if sees Header of next Table * EXTRACT next DBs's Model info into Model Array; * DROP line if not enough arguments * DROP line if Duplicate model defn * ! format= model_name, model_id; * STORE in Model Array cell whose index equals Model id * ENDFOR */ for (cnt=0; fgets(temp, sizeof(temp), infile)!=NULL; ) { LineRead++; for (ptr=temp; *ptr==' '; ptr++) ; if (*ptr == '#') continue; if (strstr(temp, "to GRIB Geometry Table") != NULL) break; /* Assume end of section */ if ((num= sscanf (temp, "%s%s%s", achDBsField, strGribCode,dummy)) !=2) { if (num>0) fprintf(stdout,"Warning: unmatched Model args, drop line %d in %s\n", LineRead, lookup_fn); continue; } GribCode = atoi(strGribCode); if (GribCode < 0 || GribCode >= NMODEL) { fprintf(stdout, "Warning: Model_id '%d' out of range, drop line %d in %s", GribCode, LineRead, lookup_fn); continue; } if (db_mdl_tbl[GribCode].db_name[0] != '\0') { fprintf(stdout, "Warning: duplic Model %d, drop defn ending on line %d in %s\n", GribCode, LineRead, lookup_fn); continue; } db_mdl_tbl[GribCode].usModel_id = (unsigned short) GribCode; strcpy (db_mdl_tbl[GribCode].db_name, achDBsField); ++cnt; /* number loaded */ DPRINT2("(+) Model=%d, db_name=%s\n", db_mdl_tbl[GribCode].usModel_id, db_mdl_tbl[GribCode].db_name); } /* * DEBUG print */ DPRINT1("Model table has %d entries\n", cnt); /*** Database's GEOMETRY TABLE*** Sample: NEONS to GRIB Geometry Table NEONS Geometry Name GRIB CODE =================== ========= mediterranean_109x82 001 persian_gulf_NORAPS_63x63 002 global_144x288 003 * * *** Database's Geometry Defn conversion info *** * A.8 KEEP reading until last of Header/Comment line (see '===') * RETURN error if fails */ while (strstr (temp, "====") == NULL) { fgets(temp, sizeof(temp), infile); /* skip Comment/Header lines */ LineRead++; if (feof(infile) || ferror(infile)) { DPRINT1 ("%s: got EOF/ERROR before loading DBs GEOM info\n",func); sprintf(errmsg, "%s: got EOF/ERROR before loading GEOM info (line %d in %s)\n", func , LineRead, lookup_fn); goto BYE; } } /* * A.9 FOR (successfully read a line from file) DO * EXTRACT next DBs's Geometry info into Geometry Array; * IF (fails) SKIP rest of Geometry defn ; * !format= parm_name, parm_id, scalefctr, offset, dec scale factor; * STORE in Geom Array cell whose index equals Geom id * ENDFOR */ for (cnt=0; fgets(temp, sizeof(temp), infile)!=NULL; ) { LineRead++; for (ptr=temp; *ptr==' '; ptr++) ; if (*ptr == '#') continue; if ((num= sscanf (temp, "%s%s%s", achDBsField, strGribCode, dummy)) !=2) { if (num>0) fprintf(stdout,"Warning: unmatched Geom args, drop line %d in %s\n", LineRead, lookup_fn); continue; } GribCode = atoi(strGribCode); if (GribCode < 0 || GribCode >= NGEOM) { fprintf(stdout, "Warning: Geom_id '%d' out of range, drop line %d in %s\n", GribCode, LineRead, lookup_fn); continue; } if (db_geom_tbl[GribCode].db_name[0] != '\0') { fprintf(stdout, "Warning: duplic Geom %d, drop defn ending on line %d in %s\n", GribCode, LineRead, lookup_fn); continue; } db_geom_tbl[GribCode].usGeom_id= (unsigned short) GribCode; strcpy (db_geom_tbl[GribCode].db_name, achDBsField); ++cnt; DPRINT2("(+) geom=%d, db_name=%s\n", db_geom_tbl[GribCode].usGeom_id, db_geom_tbl[GribCode].db_name); } /* * DEBUG print */ DPRINT1("Geometry table has %d entries\n", cnt); /* * * A.10 SET status to 0 !success */ stat=0; /* * * A.11 CLOSE Lookup file; */ BYE: if (infile) fclose(infile); DPRINT2 ("Leaving %s(), stat=%d\n", func,stat); /* * * A.12 RETURN with status */ return (stat); /* * END OF FUNCTION * */ }