NCEPLIBS-g2tmpl  1.12.0
process_4dot2.c
Go to the documentation of this file.
1 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <ctype.h>
10 
13 #define MXG2MNEM 16
14 
17 #define MXG2MNEMP4 ( MXG2MNEM + 4)
18 
20 #define NUMALLOC 2500
21 
23 #define MXFNLEN 120
24 
31 #ifdef UNDERSCORE
32 #define open_and_read_4dot2 open_and_read_4dot2_
33 #define sort_and_write_4dot2 sort_and_write_4dot2_
34 #define search_for_4dot2_entry search_for_4dot2_entry_
35 #define close_4dot2 close_4dot2_
36 #endif
37 
47 #ifdef F77_INTSIZE_8
48 typedef long f77int;
49 #else
50 typedef int f77int;
51 #endif
52 
54 struct TableEntry {
55  char mnemonic[MXG2MNEMP4];
56  int discipline;
57  int category;
58  int parameter;
59 };
60 
62 struct TableEntry *pe0 = NULL;
63 
65 size_t nentry = 0;
66 
67 /* Prototypes. */
68 void open_and_read_4dot2(char *, f77int *);
69 void sort_and_write_4dot2(char *, f77int *);
70 /* void search_for_4dot2_entry(char *, f77int *, f77int *, f77int *, f77int *, f77int *); */
71 int compar(const struct TableEntry *, const struct TableEntry *);
72 void close_4dot2(f77int *);
73 
83 int
84 compar(const struct TableEntry *pte1, const struct TableEntry *pte2)
85 {
86  return strcmp(pte1->mnemonic, pte2->mnemonic);
87 }
88 
89 /*
90 ** Define the remaining subprograms which will be called by user applications.
91 */
92 
112 void
113 open_and_read_4dot2(char *filename, f77int *iret)
114 {
115 
116  struct TableEntry *pra;
117 
118  char lfn[MXFNLEN+1], str[81], cflag, cub = '_';
119 
120  size_t i;
121 
122  FILE *pfn;
123 
124 /*
125 ** Copy the input filename into a local variable and check it for validity.
126 ** This is especially important in case the filename was passed in as a
127 ** string literal by the calling program or else doesn't have a trailing
128 ** NULL character.
129 */
130  for (i = 0; (! isspace(filename[i]) && ! iscntrl(filename[i])); i++) {
131  if (i == MXFNLEN) {
132  *iret = (f77int) -1;
133  return;
134  }
135  lfn[i] = filename[i];
136  }
137  lfn[i] = '\0';
138 
139 /*
140 ** Open the file.
141 */
142  if ((pfn = fopen(lfn, "r")) == NULL) {
143  *iret = (f77int) -2;
144  printf("Can't open input file %s\n",lfn);
145  return;
146  }
147 
148 /*
149 ** Read the file contents into an internal memory structure. Memory will be
150 ** allocated as needed for NUMALLOC entries at a time.
151 */
152  while (fgets(str, 80, pfn) != NULL) {
153  if (str[0] != '!') { /* ignore comment lines */
154  if ((nentry % NUMALLOC) == 0) {
155 /*
156 ** Allocate additional memory.
157 */
158  pra = realloc(pe0, (NUMALLOC * sizeof(struct TableEntry)));
159  if (pra == NULL) {
160  *iret = (f77int) -3;
161  return;
162  }
163  pe0 = pra;
164  }
165  sscanf(str, "%d%d%d%*3c%c%*c%s",
166  &pe0[nentry].discipline, &pe0[nentry].category,
167  &pe0[nentry].parameter, &cflag,
168  pe0[nentry].mnemonic);
169  strncat(pe0[nentry].mnemonic, &cub, 1);
170  strncat(pe0[nentry].mnemonic, &cflag, 1);
171  nentry++;
172  }
173  }
174 
175 /*
176 ** Close the file.
177 */
178  fclose (pfn);
179 
180  *iret = (f77int) 0;
181 }
182 
198 void
199 sort_and_write_4dot2(char *filename, f77int *iret)
200 {
201 #define MXFNLEN 120
202 
203  char lfn[MXFNLEN+1], str[MXG2MNEMP4], cflag;
204 
205  size_t i;
206 
207  FILE *pfn;
208 
209 /*
210 ** Copy the filename into a local variable and check it for validity.
211 ** This is especially important in case the filename was passed in as a
212 ** string literal by the calling program or else doesn't have a trailing
213 ** NULL character.
214 */
215  for (i = 0; (! isspace(filename[i]) && ! iscntrl(filename[i])); i++) {
216  if (i == MXFNLEN) {
217  *iret = (f77int) -1;
218  return;
219  }
220  lfn[i] = filename[i];
221  }
222  lfn[i] = '\0';
223 
224 /*
225 ** Open the output file.
226 */
227  if ((pfn = fopen(lfn, "w")) == NULL) {
228  *iret = (f77int) -2;
229  printf("Can't open output file %s\n",lfn);
230  return;
231  }
232 
233 /*
234 ** Sort the entries within the internal memory structure.
235 */
236  qsort(pe0, nentry, sizeof(struct TableEntry),
237  (int (*) (const void *, const void *)) compar);
238 
239 /*
240 ** Write the sorted entries to the output file.
241 */
242  for (i = 0; i < nentry; i++) {
243  strcpy(str, pe0[i].mnemonic);
244  cflag = str[strlen(str)-1];
245  str[strlen(str)-2] = '\0';
246  fprintf(pfn, "%4d%4d%6d %c %s\n",
247  pe0[i].discipline, pe0[i].category,
248  pe0[i].parameter, cflag, str);
249  }
250 /*
251 ** Close the file.
252 */
253  fclose (pfn);
254 
255  *iret = (f77int) 0;
256 }
257 
283 void
285  f77int *disc, f77int *catg, f77int *parm,
286  f77int *iret)
287 {
288  unsigned short n = 0, n2 = 0;
289 
290  long llf;
291 
292  struct TableEntry key, *pbs;
293 
294  size_t ipt;
295 
296 /*
297 ** Make a local copy of nemo. Mnemonics may consist of any combination of
298 ** alphanumeric, underscore and dash characters.
299 */
300  while ( (n < MXG2MNEM) &&
301  ((isalnum((int) nemo[n]) ||
302  (nemo[n] == '_') || (nemo[n] == '-'))) ) {
303  key.mnemonic[n2++] = nemo[n++];
304  }
305 
306 /*
307 ** Append an underscore followed by the locflg in order to generate the
308 ** mnemonic to search for.
309 */
310  key.mnemonic[n2++] = '_';
311  llf = (long) *locflg;
312  if (llf != 1) llf = 0; /* default to using international entry unless
313  local is specified */
314  sprintf(&key.mnemonic[n2], "%ld", llf); /* trailing null will be automatically
315  appended by sprintf */
316 
317 /*
318 ** Search for the mnemonic in the Code Table and return appropriate output values.
319 */
320  pbs = bsearch(&key, pe0, nentry, sizeof(struct TableEntry),
321  (int (*) (const void *, const void *)) compar);
322  if (pbs == NULL) {
323  *iret = (f77int) -1;
324  }
325  else {
326  *iret = (f77int) 0;
327  ipt = pbs - pe0;
328  *disc = (f77int) pe0[ipt].discipline;
329  *catg = (f77int) pe0[ipt].category;
330  *parm = (f77int) pe0[ipt].parameter;
331  }
332 
333 }
334 
341 void
343 {
344  free (pe0);
345  *iret = (f77int) 0;
346 }
struct TableEntry * pe0
Table entry.
Definition: process_4dot2.c:62
void search_for_4dot2_entry(char nemo[MXG2MNEM], f77int *locflg, f77int *disc, f77int *catg, f77int *parm, f77int *iret)
Searches for a specified mnemonic within the previously-opened GRIB2 Code Table 4....
int f77int
On certain operating systems, the FORTRAN compiler appends an underscore to subprogram names in its o...
Definition: process_4dot2.c:50
#define NUMALLOC
Allocate internal memory for table entries in chunks of 25000.
Definition: process_4dot2.c:20
size_t nentry
Number of entries.
Definition: process_4dot2.c:65
#define MXG2MNEM
Define the maximum length of a mnemonic in GRIB2 Code Table 4.2.
Definition: process_4dot2.c:13
int compar(const struct TableEntry *, const struct TableEntry *)
Define the internal comparison function for use with qsort and bsearch.
Definition: process_4dot2.c:84
#define MXFNLEN
Max fn length.
Definition: process_4dot2.c:23
void open_and_read_4dot2(char *, f77int *)
Opens and reads the GRIB2 Code Table 4.2 into an internal memory structure.
void sort_and_write_4dot2(char *, f77int *)
Sorts the contents of GRIB2 Code Table 4.2 within the internal memory structure and writes the output...
#define MXG2MNEMP4
Define the maximum length of a mnemonic in GRIB2 Code Table 4.2.
Definition: process_4dot2.c:17
void close_4dot2(f77int *)
This subroutine should be called one time at the end of the application program in order to free all ...