miriad 4.1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/hio.h ADDED
@@ -0,0 +1,48 @@
1
+ #if !defined(MIR_HIO_H)
2
+ #define MIR_HIO_H
3
+
4
+ #include "sysdep.h"
5
+
6
+ /*
7
+ * magic numbers at the start of an item, these are like BITPIX in fits,
8
+ * so don't change them or your MIRIAD files won't be exchangeable between
9
+ * other MIRIAD implementations
10
+ * MAXTYPES is pretty arbitrary, just make sure it's at least the last H_<type>+1
11
+ *
12
+ */
13
+
14
+ #define H_BYTE 1
15
+ #define H_INT 2
16
+ #define H_INT2 3
17
+ #define H_REAL 4
18
+ #define H_DBLE 5
19
+ #define H_TXT 6
20
+ #define H_CMPLX 7
21
+ #define H_INT8 8
22
+
23
+ #define MAXTYPES 10
24
+
25
+ #define H_BYTE_SIZE 1
26
+ #define H_INT_SIZE 4
27
+ #define H_INT2_SIZE 2
28
+ #define H_INT8_SIZE 8
29
+ #define H_REAL_SIZE 4
30
+ #define H_DBLE_SIZE 8
31
+ #define H_TXT_SIZE 1
32
+ #define H_CMPLX_SIZE 8
33
+
34
+ #define MAXPATH 256
35
+ #define MAXOPEN 26
36
+
37
+
38
+ /* prototypes are now in miriad.h (mostly) and sysdep.h (pack routines) */
39
+
40
+ /* Other handy definitions. */
41
+
42
+ #define TRUE 1
43
+ #define FALSE 0
44
+ #define max(a,b) ((a)>(b)?(a):(b))
45
+ #define min(a,b) ((a)<(b)?(a):(b))
46
+ #define mroundup(a,b) ((b)*(((a)+(b)-1)/(b)))
47
+
48
+ #endif /* MIR_HIO_H */
data/ext/interface.c ADDED
@@ -0,0 +1,74 @@
1
+ /************************************************************************/
2
+ /* */
3
+ /* Subroutines to aid interfacing between C and FORTRAN. */
4
+ /* */
5
+ /* History: */
6
+ /* rjs ??????? Original version. */
7
+ /* rjs 23dec92 Broke out into separate file. */
8
+ /* rjs 05dec95 Comment out a dirty trick in zterm that was screwing */
9
+ /* up with some compilers!! */
10
+ /* pjt 17jun02 MIR4 prototypes */
11
+ /************************************************************************/
12
+
13
+ #include <string.h>
14
+
15
+ void pad(char *string,int length)
16
+ /*
17
+ This takes a zero-terminated string, and pads it with blanks up a certain
18
+ length.
19
+
20
+ Input:
21
+ length Length to pad to.
22
+ Input/Output:
23
+ string Output is the blank padded version of the input.
24
+ ------------------------------------------------------------------------*/
25
+ {
26
+ int len0,i;
27
+ char *s;
28
+
29
+ len0 = strlen(string);
30
+ s = string + len0;
31
+ for(i=len0; i < length; i++) *s++ = ' ';
32
+ }
33
+ /************************************************************************/
34
+ char *zterm(char *string,int length)
35
+ /*
36
+ This returns a pointer to a nul terminated string. This is usually
37
+ called to convert strings from a FORTRAN to C manner. Its algorithm
38
+ consists of firstly checking if the string is already null-terminated
39
+ (without trailing blanks). If so return the string address. Otherwise
40
+ trim back trailing blanks and copy the string (null terminating) to
41
+ a buffer. The buffer is a circular one, with no checks for "overflows".
42
+ Overflows are unlikely because the FORTRAN to C boundary is only
43
+ spanned at most once at any given moment.
44
+
45
+ Input:
46
+ string Points to the string of interest.
47
+ length The FORTRAN length of the string (may include blank padding).
48
+
49
+ Output:
50
+ zterm Pointer to null terminated string.
51
+ ------------------------------------------------------------------------*/
52
+ {
53
+ #define CIRBUFSIZE 2048
54
+ static char buffer[CIRBUFSIZE];
55
+ static int offset=0;
56
+
57
+ char *s;
58
+
59
+ /* Trim back over blanks, and check if its already null terminated. */
60
+ /* If its already null terminated, there is nothing to do. */
61
+
62
+ s = string + length;
63
+ while(*--s == ' ' && length)length--;
64
+ /* if(*(string+length) == 0)return(string); */
65
+
66
+ /* We have to put it in our circular buffer. Determine where to put it. */
67
+
68
+ if(offset + length + 1 > CIRBUFSIZE) offset = 0;
69
+ s = buffer + offset;
70
+ memcpy(s,string,length);
71
+ *(s+length) = 0;
72
+ offset += length + 1;
73
+ return(s);
74
+ }
data/ext/io.h ADDED
@@ -0,0 +1,56 @@
1
+ /************************************************************************/
2
+ /* */
3
+ /* A general header file for the various file and i/o handling */
4
+ /* routines. */
5
+ /* */
6
+ /* History: */
7
+ /* rjs Dark-ages Original version. */
8
+ /* rjs 20aug92 Correct "roundup" macro when rounding 0. */
9
+ /* rjs 15may96 Moved roundup macro elsewhere. */
10
+ /* pjt 28may02 Added H_INT8 */
11
+ /* pjt 17jun02 different MIR4 structures? */
12
+ /************************************************************************/
13
+
14
+ /* Binary items start with a sequence to allow routines to blindly determine
15
+ how to read them. The "binary_item" is a catch all with only indicates
16
+ that the data is binary valued, but does not hint at the format. */
17
+
18
+ #if !defined(MIR_IO_H)
19
+ #define MIR_IO_H
20
+
21
+ #include "hio.h"
22
+ #include <unistd.h>
23
+
24
+ #define ITEM_HDR_SIZE 4
25
+
26
+ #if 1
27
+
28
+ /* MIRIAD3 and below data structures */
29
+
30
+
31
+ static char binary_item[ITEM_HDR_SIZE] = {0,0,0,0},
32
+ real_item[ITEM_HDR_SIZE] = {0,0,0,H_REAL},
33
+ int_item[ITEM_HDR_SIZE] = {0,0,0,H_INT},
34
+ int2_item[ITEM_HDR_SIZE] = {0,0,0,H_INT2},
35
+ int8_item[ITEM_HDR_SIZE] = {0,0,0,H_INT8},
36
+ char_item[ITEM_HDR_SIZE] = {0,0,0,H_BYTE},
37
+ dble_item[ITEM_HDR_SIZE] = {0,0,0,H_DBLE},
38
+ cmplx_item[ITEM_HDR_SIZE] = {0,0,0,H_CMPLX};
39
+
40
+ #else
41
+
42
+ /* MIRIAD4 data structures - not finalized on this though */
43
+
44
+ static char binary_item[ITEM_HDR_SIZE] = {1,0,0,0},
45
+ real_item[ITEM_HDR_SIZE] = {1,0,0,H_REAL},
46
+ int_item[ITEM_HDR_SIZE] = {1,0,0,H_INT},
47
+ int2_item[ITEM_HDR_SIZE] = {1,0,0,H_INT2},
48
+ int8_item[ITEM_HDR_SIZE] = {1,0,0,H_INT8},
49
+ char_item[ITEM_HDR_SIZE] = {1,0,0,H_BYTE},
50
+ dble_item[ITEM_HDR_SIZE] = {1,0,0,H_DBLE},
51
+ cmplx_item[ITEM_HDR_SIZE] = {1,0,0,H_CMPLX};
52
+
53
+
54
+ #endif
55
+
56
+ #endif /* MIR_IO_H */
data/ext/key.c ADDED
@@ -0,0 +1,934 @@
1
+ /***********************************************************************
2
+ *
3
+ * Key routines provide keyword-oriented access to the command line.
4
+ *
5
+ * History:
6
+ * rjs 24apr91 Original version.
7
+ * jm 28jun94 Wrote the ANSI-C version.
8
+ * jm 01nov94 Added expand and local traits and added keyl().
9
+ * jm 17nov94 Rewrote #if definitions for ANSI prototypes. Sun
10
+ * machines define __STDC__ even when it is 0! This
11
+ * involved creating and using PROTOTYPE in sysdep.h.
12
+ * jm 24oct96 Increased MAXSTRING from 256 to 512 and fixed a
13
+ * few lint complaints.
14
+ * jm 01aug97 Changed getKeyValue to properly handle single and
15
+ * double quotes around a value.
16
+ * pjt 03sep98 fixed malloc(size+1) bug with interesting side-effects
17
+ * on linux and HP-UX
18
+ * pjt 5aug99 increased MAXSTRING to 1024 (also do keyf.f !!!)
19
+ * pjt 6mar01 increased MAXSTRING to 2048
20
+ * mchw 15mar02 increased MAXSTRING to 4096
21
+ * pjt 22jun02 MIR4 prototypes, also added a few more Const
22
+ * jwr 22jul04 changed a few vars from size_t to ssize_t, since signed
23
+ * arithmetic is required. Also made failure of wildcard
24
+ * expansion fatal (it would crash later if only a warning
25
+ * is given)
26
+ * pjt 13jul07 make unique messages in different pieces of code
27
+ ***********************************************************************
28
+ */
29
+
30
+ #include <stdio.h>
31
+ #include <stdlib.h>
32
+ #include <string.h>
33
+ #include <ctype.h>
34
+ #include <math.h>
35
+ #include "miriad.h"
36
+
37
+ #ifndef Null
38
+ #define Null '\0'
39
+ #endif
40
+
41
+ /* if you change MAXSTRING, also do keyf.for */
42
+ #define KEYTRUE 1
43
+ #define KEYFALSE 0
44
+ #define MAXSTRING 4096
45
+
46
+ typedef struct ckeys {
47
+ char *key; /* Pointer to a malloc'd string holding the key name. */
48
+ char *Pvalue; /* Pointer to a malloc'd string holding the value. */
49
+ char *value; /* Pointer to current spot in Pvalue. */
50
+ int isexpanded; /* False if not yet expanded; true otherwise. */
51
+ int islocal; /* True if defined locally; false if globally. */
52
+ struct ckeys *fwd; /* Pointer to next ckey structure. */
53
+ } KEYS;
54
+
55
+ static KEYS *KeyHead = (KEYS *)NULL;
56
+
57
+ /* This will be set to KEYTRUE only when keyini[_c]() is called. */
58
+ static int iniCalled = KEYFALSE;
59
+
60
+ /***********************************************************************/
61
+ static char *skipLeading(Const char *string)
62
+ {
63
+ char *ptr;
64
+
65
+ if (string == (Const char *)NULL)
66
+ return((char *)NULL);
67
+
68
+ for (ptr = (char *)string; ((*ptr != Null) && isspace(*ptr)); ptr++)
69
+ /* NULL */ ;
70
+
71
+ return(ptr);
72
+ }
73
+
74
+ /***********************************************************************/
75
+ static KEYS *getKey(Const char *key)
76
+ {
77
+ char *ptr;
78
+ KEYS *t;
79
+
80
+ /* First, check that the key routines have been initialized. */
81
+ if (iniCalled == KEYFALSE) {
82
+ (void)bug_c('f', "The Key initialization routine must be called first.");
83
+ }
84
+ /*
85
+ * Search for a key by name. If the key name is not found,
86
+ * return a NULL pointer. Otherwise, return a pointer to the
87
+ * private structure of the key.
88
+ */
89
+ if ((ptr = skipLeading(key)) == (char *)NULL)
90
+ return((KEYS *)NULL);
91
+
92
+ for (t = KeyHead; t != (KEYS *)NULL; t = t->fwd)
93
+ if (strcmp(ptr, t->key) == 0)
94
+ break;
95
+
96
+ return(t);
97
+ }
98
+
99
+ /***********************************************************************/
100
+ static char *getKeyValue(Const char *key, int doexpand)
101
+ {
102
+ char *r, *s;
103
+ char quoted;
104
+ char string[MAXSTRING];
105
+ int more;
106
+ ssize_t size, depth;
107
+ KEYS *t;
108
+ FILE *fp;
109
+
110
+ if ((t = getKey(key)) == (KEYS *)NULL)
111
+ return((char *)NULL);
112
+ if ((t->value == (char *)NULL) || (*(t->value) == Null))
113
+ return((char *)NULL);
114
+ /*
115
+ * At this point, there is a value to return. Scan through to
116
+ * the end of the parameter value.
117
+ */
118
+ r = s = skipLeading(t->value);
119
+ depth = 0;
120
+ more = KEYTRUE;
121
+ quoted = Null; /* Initially, not in a quoted string. */
122
+ while ((*s != Null) && (more == KEYTRUE)) {
123
+ if (quoted == Null) { /* Not currently within a quote. */
124
+ if ((*s == '"') || (*s == '\'')) {
125
+ quoted = *s; /* Set this to the char that ends the quote. */
126
+ } else {
127
+ if (*s == '(') depth++;
128
+ else if (*s == ')') depth--;
129
+ else if (isspace(*s) || (*s == ','))
130
+ more = (depth == 0) ? KEYFALSE : KEYTRUE;
131
+ }
132
+ } else if (*s == quoted) { /* Inside a quote; read till matched. */
133
+ quoted = Null; /* Reset this to mean not in a quote. */
134
+ }
135
+ if (more == KEYTRUE) s++;
136
+ }
137
+ t->value = (*s == Null) ? s : s + 1;
138
+ *s-- = Null; /* Subtract 1 from index for following test. */
139
+
140
+ /* Remove leading and trailing quotes. */
141
+ if ((*r != Null) && (s > r)) {
142
+ if (((*r == '"') && (*s == '"')) || ((*r == '\'') && (*s == '\''))) {
143
+ *s = Null;
144
+ r++;
145
+ }
146
+ }
147
+ /*
148
+ * If the value starts with a '@' character, then open the
149
+ * given file name and store each line as a comma separated list.
150
+ * Next, if there is anything left in the keyword value list,
151
+ * add it to the end of the newly generated list. Finally, re-call
152
+ * this routine to read the first parameter off the new list.
153
+ */
154
+ if (*r == '@') {
155
+ r++;
156
+ if ((fp = fopen(r, "r")) == (FILE *)NULL) {
157
+ (void)sprintf(string, "Error opening @ file [%s].", r);
158
+ (void)bug_c('f', string);
159
+ }
160
+
161
+ more = KEYTRUE;
162
+ while (fgets(string, MAXSTRING, fp) != (char *)NULL) {
163
+ if (((size = strlen(string)) > (size_t)0) && (string[size-1] == '\n'))
164
+ string[size-1] = Null;
165
+
166
+ r = skipLeading(string);
167
+ if ((r == (char *)NULL) || (*r == Null) || (*r == '#'))
168
+ continue;
169
+
170
+ if (more == KEYTRUE) {
171
+ depth = strlen(r) + 1;
172
+ if ((s = (char *)malloc(depth)) == (char *)NULL)
173
+ (void)bug_c('f', "Could not allocate memory in the key routines.");
174
+ (void)strcpy(s, r);
175
+ more = KEYFALSE;
176
+ } else {
177
+ depth += strlen(r) + 2;
178
+ if ((s = (char *)realloc(s, depth)) == (char *)NULL)
179
+ (void)bug_c('f', "Could not allocate memory in the key routines.");
180
+ (void)strcat(s, ",");
181
+ (void)strcat(s, r);
182
+ }
183
+ }
184
+
185
+ (void)fclose(fp);
186
+
187
+ if (depth == 0)
188
+ (void)bug_c('f', "Trouble processing the @ directive.");
189
+
190
+ if (*(t->value) != Null) {
191
+ depth += strlen(t->value) + 2;
192
+ if ((s = (char *)realloc(s, depth)) == (char *)NULL)
193
+ (void)bug_c('f', "Could not allocate memory in the key routines.");
194
+ (void)strcat(s, ",");
195
+ (void)strcat(s, t->value);
196
+ }
197
+
198
+ (void)free((Void *)t->Pvalue);
199
+ t->value = t->Pvalue = s;
200
+ t->isexpanded = KEYTRUE;
201
+ r = getKeyValue(key, doexpand);
202
+ } else if ((doexpand == KEYTRUE) && (t->isexpanded == KEYFALSE)) {
203
+ /*
204
+ * Otherwise, if expansion is desired and the keyword has not
205
+ * yet been expanded, call the dio.c routine dexpand_c() to
206
+ * return the result of the system call to "echo r".
207
+ */
208
+ size = dexpand_c(r, string, MAXSTRING);
209
+ if (size < 1) {
210
+ (void)sprintf(string, "Error doing wildcard expansion of [%s].", r);
211
+ (void)bug_c('f', string);
212
+ } else {
213
+ if (*(t->value) != Null)
214
+ size += strlen(t->value) + 2;
215
+ if ((s = (char *)malloc(size+1)) == (char *)NULL)
216
+ (void)bug_c('f', "Could not allocate memory in the key routines.");
217
+ (void)strcpy(s, string);
218
+ if (*(t->value) != Null) {
219
+ (void)strcat(s, ",");
220
+ (void)strcat(s, t->value);
221
+ }
222
+ (void)free((Void *)t->Pvalue);
223
+ t->value = t->Pvalue = s;
224
+ t->isexpanded = KEYTRUE;
225
+ }
226
+ r = getKeyValue(key, doexpand);
227
+ }
228
+
229
+ return((*r == Null) ? (char *)NULL : r);
230
+ }
231
+
232
+ /***********************************************************************/
233
+ void keyinit_c(Const char *task)
234
+ {
235
+ buglabel_c(task); /* Let the bug routines know the task name. */
236
+ iniCalled = KEYTRUE; /* Is True only when keyini[_c]() is called. */
237
+ }
238
+
239
+ /***********************************************************************/
240
+ void keyput_c(Const char *task, char *string)
241
+ /** KeyPut -- Store a keyword for later retrieval. */
242
+ /*& pjt */
243
+ /*: user-input,command-line */
244
+ /*+ FORTRAN call sequence:
245
+
246
+ subroutine keyput(task,value)
247
+ character task*(*),value*(*)
248
+
249
+ This task stores the keyword=value pair for later retrieval by the
250
+ other key routines. If the keyword has previously been saved prior
251
+ to calling this routine, then this version will only be saved if
252
+ (1) the previous was not defined locally (ie. task/keyword) or
253
+ (2) this reference is also a local reference.
254
+
255
+ If the keyword is locally defined (ie. task/keyword) but the task
256
+ name does not match the value of the input string task, then the
257
+ keyword is not (ever) saved.
258
+
259
+ NOTE: This is an internal routine that is only called by KeyIni.
260
+
261
+ Input:
262
+ task The name of the current task.
263
+ value The keyword=value pair.
264
+
265
+ Output:
266
+ (none)
267
+ */
268
+ /*--*/
269
+ /*---------------------------------------------------------------------*/
270
+ {
271
+ char *s, *key;
272
+ char *pequal, *pslash;
273
+ char errmsg[MAXSTRING];
274
+ int localkey;
275
+ KEYS *t;
276
+
277
+ if (iniCalled == KEYFALSE) {
278
+ (void)bug_c('f',
279
+ "The Key initialization routine must be called before calling KEYPUT.");
280
+ }
281
+
282
+ if (((s = skipLeading(string)) == (char *)NULL) || (*s == Null)) {
283
+ (void)sprintf(errmsg, "Badly formed parameter-1: [%s].", string);
284
+ (void)bug_c('w', errmsg);
285
+ return;
286
+ } else if (*s == '#') { /* Quietly return on comment lines. */
287
+ return;
288
+ }
289
+
290
+ key = s; /* Get the key name. */
291
+ while ((*s != Null) && (isalnum(*s) || (*s == '$')))
292
+ s++;
293
+ if (*s == Null) {
294
+ (void)sprintf(errmsg, "Badly formed parameter-2: [%s].", string);
295
+ (void)bug_c('w', errmsg);
296
+ return;
297
+ }
298
+ /*
299
+ * Search for the local keyword character (/). If it exists,
300
+ * it must appear before the equal sign with text that precedes
301
+ * and follows it. If the key is local, the key and value will
302
+ * be saved only if the task name matches the text before the
303
+ * local flag character.
304
+ */
305
+ localkey = KEYFALSE;
306
+ if (((pslash = strchr(s, '/')) != (char *)NULL) &&
307
+ ((pequal = strchr(s, '=')) != (char *)NULL) &&
308
+ (pslash < pequal)) {
309
+ *s = Null; /* Terminate the task name. */
310
+ if (strcmp(task, key) != 0) /* This keyword doesn't match task. */
311
+ return;
312
+ s = skipLeading(pslash+1); /* Skip blanks after the local char. */
313
+
314
+ localkey = KEYTRUE;
315
+ key = s; /* Now, get the real [local] key name. */
316
+ while ((*s != Null) && (isalnum(*s) || (*s == '$'))) s++;
317
+ if (*s == Null) {
318
+ (void)sprintf(errmsg, "Badly formed parameter-3: [%s].", string);
319
+ (void)bug_c('w', errmsg);
320
+ return;
321
+ }
322
+ }
323
+ *s++ = Null; /* Properly terminate the keyword. */
324
+
325
+ /* Now move to the value part of this keyword. */
326
+ while ((*s != Null) && (isspace(*s) || (*s == '=')))
327
+ s++;
328
+ if ((*s == Null) || (strlen(s) < (size_t)1)) {
329
+ (void)sprintf(errmsg, "Badly formed parameter-4: [%s=%s].", key, string);
330
+ (void)bug_c('w', errmsg);
331
+ return;
332
+ }
333
+ /*
334
+ * See if this keyword already exists. If not, then create it.
335
+ * If it exists and was not previously declared local, then
336
+ * this version will override the previous reference of the key.
337
+ * If this reference was previously defined locally then only
338
+ * another local reference will override it.
339
+ */
340
+ for (t = KeyHead; t != (KEYS *)NULL; t = t->fwd) {
341
+ if (strcmp(key, t->key) == 0)
342
+ break;
343
+ }
344
+
345
+ if (t == (KEYS *)NULL) {
346
+ if ((t = (KEYS *)malloc(sizeof(KEYS))) == (KEYS *)NULL)
347
+ (void)bug_c('f', "Could not allocate memory in the key routines.");
348
+ if ((t->key = (char *)malloc(strlen(key) + 1)) == (char *)NULL)
349
+ (void)bug_c('f', "Could not allocate memory in the key routines.");
350
+ (void)strcpy(t->key, key);
351
+ t->fwd = KeyHead;
352
+ KeyHead = t;
353
+ } else if ((localkey == KEYTRUE) || (t->islocal != KEYTRUE)) {
354
+ if (t->Pvalue != (char *)NULL)
355
+ (void)free((Void *)t->Pvalue);
356
+ } else {
357
+ return;
358
+ }
359
+
360
+ if ((t->Pvalue = (char *)malloc(strlen(s) + 1)) == (char *)NULL)
361
+ (void)bug_c('f', "Could not allocate memory in the key routines.");
362
+ (void)strcpy(t->Pvalue, s);
363
+ t->value = t->Pvalue;
364
+ t->isexpanded = KEYFALSE;
365
+ t->islocal = localkey;
366
+
367
+ return;
368
+ }
369
+
370
+ /***********************************************************************/
371
+ void keyini_c(int argc, char *argv[])
372
+ /** KeyIni_c -- Initialise the `key' routines (C version). */
373
+ /*& pjt */
374
+ /*: user-input, command-line */
375
+ /*+
376
+
377
+ void keyini_c(int argc, char *argv[])
378
+
379
+ Keyini_c performs some initial parsing of the command line breaking
380
+ it up into its keyword=value pairs. It also stores the name of
381
+ the program (which is currently only used by the bug routines).
382
+
383
+ NOTE: This has a different calling sequence than the Fortran
384
+ version.
385
+ */
386
+ /*--*/
387
+ /*---------------------------------------------------------------------*/
388
+ {
389
+ char *task;
390
+ char string[MAXSTRING];
391
+ register int i;
392
+ size_t size;
393
+ FILE *fp;
394
+ /*
395
+ * Get the program name, and tell the bug routines what it
396
+ * really is. Then strip off any leading path characters
397
+ * so only the task name remains.
398
+ */
399
+ keyinit_c(argv[0]);
400
+ task = argv[0] + strlen(argv[0]) - 1;
401
+ while ((task > argv[0]) && (strchr("]/", task[-1]) == (char *)NULL))
402
+ task--;
403
+
404
+ for (i = 1; i < argc; i++) {
405
+ if (strcmp("-f", argv[i]) == 0) { /* Read args from a file. */
406
+ if (++i >= argc)
407
+ (void)bug_c('f', "KeyIni: No parameter file given for -f option.");
408
+
409
+ if ((fp = fopen(argv[i], "r")) == (FILE *)NULL) {
410
+ (void)sprintf(string,
411
+ "KeyIni: Failed to open the parameter file [%s].", argv[i]);
412
+ (void)bug_c('f', string);
413
+ }
414
+
415
+ while (fgets(string, MAXSTRING, fp) != (char *)NULL) {
416
+ if (((size = strlen(string)) > (size_t)0) && (string[size-1] == '\n'))
417
+ string[size-1] = Null;
418
+ keyput_c(task, string);
419
+ }
420
+
421
+ (void)fclose(fp);
422
+ } else if (strcmp("-?", argv[i]) == 0) { /* Give help. */
423
+ (void)sprintf(string, "mirhelp %s", task);
424
+ (void)system(string);
425
+ (void)exit(0);
426
+ } else if (strcmp("-k", argv[i]) == 0) { /* List the keywords. */
427
+ (void)sprintf(string, "doc %s", task);
428
+ (void)system(string);
429
+ (void)exit(0);
430
+ } else if (argv[i][0] == '-') { /* Others not understood yet. */
431
+ (void)sprintf(string, "KeyIni: Flag [%s] not understood.", argv[i]);
432
+ (void)bug_c('w', string);
433
+ } else { /* Otherwise, the argument is a parameter. */
434
+ keyput_c(task, argv[i]);
435
+ }
436
+ }
437
+ return;
438
+ }
439
+
440
+ /***********************************************************************/
441
+ void keyfin_c(void)
442
+ /** KeyFin -- Finish access to the 'key' routines. */
443
+ /*& pjt */
444
+ /*: user-input,command-line */
445
+ /*+ FORTRAN call sequence:
446
+
447
+ subroutine keyfin
448
+
449
+ A call to KeyFin indicates that all of the parameters that the
450
+ program wants have been retrieved from the command line. KeyFin
451
+ makes sure all command line parameters have been read.
452
+ */
453
+ /*--*/
454
+ /*---------------------------------------------------------------------*/
455
+ {
456
+ char errmsg[MAXSTRING];
457
+ KEYS *t, *next;
458
+
459
+ if (iniCalled == KEYFALSE) {
460
+ (void)bug_c('f',
461
+ "The Key initialization routine must be called before calling KEYFIN.");
462
+ }
463
+
464
+ next = (KEYS *)NULL;
465
+ for (t = KeyHead; t != (KEYS *)NULL; t = next) {
466
+ next = t->fwd;
467
+ if ((t->value != (char *)NULL) && (*(t->value) != Null)) {
468
+ (void)sprintf(errmsg, "Keyword [%s] not used or not exhausted.",
469
+ t->key);
470
+ (void)bug_c('w', errmsg);
471
+ }
472
+
473
+ if (t->Pvalue != (char *)NULL)
474
+ (void)free((Void *)t->Pvalue);
475
+ if (t->key != (char *)NULL)
476
+ (void)free((Void *)t->key);
477
+ (void)free((Void *)t);
478
+ }
479
+
480
+ KeyHead = (KEYS *)NULL;
481
+ iniCalled = KEYFALSE;
482
+ return;
483
+ }
484
+
485
+ /***********************************************************************/
486
+ /* Returns FORT_TRUE if keyword is present; FORT_FALSE otherwise. */
487
+ int keyprsnt_c(Const char *keyword)
488
+ /** KeyPrsnt -- Determine if a keyword is present on the command line. */
489
+ /*& pjt */
490
+ /*: user-input,command-line */
491
+ /*+ FORTRAN call sequence:
492
+
493
+ logical function keyprsnt(key)
494
+ character key*(*)
495
+
496
+ Determine if a parameter is still present.
497
+
498
+ Input:
499
+ key The keyword to check.
500
+
501
+ Output:
502
+ keyprsnt Is .TRUE. if the keyword is present; .FALSE. otherwise.
503
+ */
504
+ /*--*/
505
+ /*---------------------------------------------------------------------*/
506
+ {
507
+ int isPresent;
508
+ KEYS *t;
509
+
510
+ t = getKey(keyword);
511
+ isPresent = ((t != (KEYS *)NULL) &&
512
+ (t->value != (char *)NULL) &&
513
+ (*(t->value) != Null)) ? FORT_TRUE : FORT_FALSE;
514
+
515
+ return(isPresent);
516
+ }
517
+
518
+ /***********************************************************************/
519
+ void keya_c(Const char *keyword, char *value, Const char *keydef)
520
+ /** Keya -- Retrieve a character string from the command line. */
521
+ /*& pjt */
522
+ /*: user-input,command-line */
523
+ /*+ FORTRAN call sequence:
524
+
525
+ subroutine keya(key,value,default)
526
+ character key*(*)
527
+ character value*(*),default*(*)
528
+
529
+ Retrieve a character string from the command line. If the keyword
530
+ is not found, the default is returned.
531
+
532
+ Input:
533
+ key The name of the keyword to return.
534
+ default The default value to return if the keyword is not
535
+ present on the command line.
536
+ Output:
537
+ value The returned value.
538
+ */
539
+ /*--*/
540
+ /*---------------------------------------------------------------------*/
541
+ {
542
+ char *s;
543
+
544
+ s = getKeyValue(keyword, KEYFALSE);
545
+ (void)strcpy(value, ((s == (char *)NULL) ? keydef : s));
546
+ return;
547
+ }
548
+
549
+ /***********************************************************************/
550
+ void keyf_c(Const char *keyword, char *value, Const char *keydef)
551
+ /** Keyf -- Retrieve a file name (with wildcards) from the command line. */
552
+ /*& pjt */
553
+ /*: user-input,command-line */
554
+ /*+ FORTRAN call sequence:
555
+
556
+ subroutine keyf(key,value,default)
557
+ character key*(*)
558
+ character value*(*),default*(*)
559
+
560
+ Retrieve a character string from the command line. If the keyword
561
+ is not found, the default is returned.
562
+
563
+ Input:
564
+ key The name of the keyword to return.
565
+ default The default value to return if the keyword is not
566
+ present on the command line.
567
+ Output:
568
+ value The returned value.
569
+ */
570
+ /*--*/
571
+ /*---------------------------------------------------------------------*/
572
+ {
573
+ char *s;
574
+
575
+ /* Expand any wildcards and match them with files. */
576
+ s = getKeyValue(keyword, KEYTRUE);
577
+ (void)strcpy(value, ((s == (char *)NULL) ? keydef : s));
578
+ return;
579
+ }
580
+
581
+ /***********************************************************************/
582
+ void keyd_c(Const char *keyword, double *value, Const double keydef)
583
+ /** Keyd -- Retrieve a double precision from the command line. */
584
+ /*& pjt */
585
+ /*: user-input,command-line */
586
+ /*+ FORTRAN call sequence:
587
+
588
+ subroutine keyd(key,value,default)
589
+ character key*(*)
590
+ double precision value,default
591
+
592
+ Retrieve a double precision value from the command line. If the
593
+ keyword is not found, the default is returned.
594
+
595
+ Input:
596
+ key The name of the keyword to return.
597
+ default The default value to return, if the keyword is not
598
+ present on the command line.
599
+ Output:
600
+ value The returned value.
601
+ */
602
+ /*--*/
603
+ /*---------------------------------------------------------------------*/
604
+ {
605
+ char *s, *ptr;
606
+ char errmsg[MAXSTRING];
607
+
608
+ *value = keydef;
609
+ if ((s = getKeyValue(keyword, KEYFALSE)) == (char *)NULL)
610
+ return;
611
+
612
+ ptr = (char *)NULL;
613
+ *value = strtod(s, &ptr);
614
+ if (s == ptr) {
615
+ (void)sprintf(errmsg,
616
+ "KeyD: Conversion error decoding parameter [%s=%s].", keyword, s);
617
+ (void)bug_c('f', errmsg);
618
+ }
619
+
620
+ return;
621
+ }
622
+
623
+ /***********************************************************************/
624
+ void keyr_c(Const char *keyword, float *value, Const float keydef)
625
+ /** Keyr -- Retrieve a real value from the command line. */
626
+ /*& pjt */
627
+ /*: user-input,command-line */
628
+ /*+ FORTRAN call sequence:
629
+
630
+ subroutine keyr(key,value,default)
631
+ character key*(*)
632
+ real value,default
633
+
634
+ Retrieve a real value from the command line. If the keyword is
635
+ not found, the default is returned.
636
+
637
+ Input:
638
+ key The name of the keyword to return.
639
+ default The default value to return, if the keyword is not
640
+ present on the command line.
641
+ Output:
642
+ value The returned value.
643
+ */
644
+ /*--*/
645
+ /*---------------------------------------------------------------------*/
646
+ {
647
+ double retval, defval;
648
+
649
+ defval = keydef;
650
+ keyd_c(keyword, &retval, defval);
651
+ *value = retval;
652
+ return;
653
+ }
654
+
655
+ /***********************************************************************/
656
+ void keyi_c(Const char *keyword, int *value, Const int keydef)
657
+ /** Keyi -- Retrieve an integer from the command line. */
658
+ /*& pjt */
659
+ /*: user-input,command-line */
660
+ /*+ FORTRAN call sequence:
661
+
662
+ subroutine keyi(key,value,default)
663
+ character key*(*)
664
+ integer value,default
665
+
666
+ Retrieve an integer from the command line. If the keyword is
667
+ not found, the default is returned. The integer can be input
668
+ as a hexadecimal, octal or decimal number using a prefix 0x, %x
669
+ or h for hex; o or %o for octal; and +, - or nothing for decimal.
670
+
671
+ Input:
672
+ key The name of the keyword to return.
673
+ default The default value to return, if the keyword is not
674
+ present on the command line.
675
+ Output:
676
+ value The returned value.
677
+ */
678
+ /*--*/
679
+ /*---------------------------------------------------------------------*/
680
+ {
681
+ char *s, *ptr;
682
+ char temp[MAXSTRING];
683
+ int iarg, dummy;
684
+ double dval;
685
+
686
+ *value = keydef;
687
+ if ((s = getKeyValue(keyword, KEYFALSE)) == (char *)NULL)
688
+ return;
689
+ /*
690
+ * This business is done instead of a call to strtol because
691
+ * hexadecimal and octal are also acceptable integer inputs.
692
+ */
693
+ (void)sprintf(temp, "%s~~1", s);
694
+ if ((sscanf(temp, "%i~~%d", &iarg, &dummy) == 2) && (dummy == 1)) {
695
+ *value = iarg; /* Token was just a simple integer. */
696
+ return;
697
+ }
698
+
699
+ /* Number is floating point; find it and then take nint(). */
700
+ ptr = (char *)NULL;
701
+ dval = strtod(s, &ptr);
702
+ if (s == ptr) {
703
+ (void)sprintf(temp,
704
+ "KeyI: Conversion error decoding parameter [%s=%s].", keyword, s);
705
+ (void)bug_c('f', temp);
706
+ }
707
+ *value = (dval >= 0) ? floor(dval + 0.5) : ceil(dval - 0.5);
708
+
709
+ return;
710
+ }
711
+
712
+ /***********************************************************************/
713
+ void keyl_c(Const char *keyword, int *value, Const int keydef)
714
+ /** keyl -- Retrieve a logical value from the command line. */
715
+ /*& pjt */
716
+ /*: user-input,command-line */
717
+ /*+ FORTRAN call sequence:
718
+
719
+ subroutine keyl(key,value,default)
720
+ character key*(*)
721
+ logical value,default
722
+
723
+ Retrieve a logical value from the command line. If the keyword is
724
+ not found, the default is returned. It associates (case
725
+ insensitive) words starting with 'y', 't' and '1' as .TRUE. and
726
+ words starting with 'n', 'f' and '0' as .FALSE. Values of .TRUE.
727
+ and .FALSE. are also detected... both with minimum match.
728
+
729
+ Input:
730
+ key The name of the keyword to return.
731
+ default The default value to return, if the keyword is not
732
+ present on the command line.
733
+ Output:
734
+ value The returned value.
735
+ */
736
+ /*--*/
737
+ /*---------------------------------------------------------------------*/
738
+ {
739
+ char string[MAXSTRING];
740
+ char errmsg[MAXSTRING];
741
+ int state;
742
+
743
+ if (keydef == FORT_FALSE) {
744
+ keya_c(keyword, string, "f");
745
+ state = KEYFALSE;
746
+ } else {
747
+ keya_c(keyword, string, "t");
748
+ state = KEYTRUE;
749
+ }
750
+
751
+ (void)sprintf(errmsg, "KeyL: invalid value for a logical: [%s].", string);
752
+ switch ((int)string[0]) {
753
+ case 'f': case 'F': case 'n': case 'N': case '0':
754
+ state = KEYFALSE;
755
+ break;
756
+ case 't': case 'T': case 'y': case 'Y': case '1':
757
+ state = KEYTRUE;
758
+ break;
759
+ case '.':
760
+ switch ((int)string[1]) {
761
+ case 'f': case 'F':
762
+ state = KEYFALSE;
763
+ break;
764
+ case 't': case 'T':
765
+ state = KEYTRUE;
766
+ break;
767
+ default:
768
+ (void)bug_c('w', errmsg);
769
+ break;
770
+ }
771
+ break;
772
+ default:
773
+ (void)bug_c('w', errmsg);
774
+ break;
775
+ }
776
+
777
+ *value = (state == KEYTRUE) ? FORT_TRUE : FORT_FALSE;
778
+ return;
779
+ }
780
+
781
+ /***********************************************************************/
782
+ /*
783
+ * The following macro is used by all of the subsequent multi-get
784
+ * routines. It assumes that:
785
+ *
786
+ * Const char *keyword is the name of the key to retrieve;
787
+ * T value[] is the array to receive each returned value;
788
+ * int nmax is the maximum number of items to get; and
789
+ * int *n is the number of items returned;
790
+ *
791
+ * where T is the type of the variable (char *, double, float, or int).
792
+ *
793
+ * In the macro below,
794
+ * task is the name of the individual item retrieval task;
795
+ * defval is the default value to be used if the keyword is missing; and
796
+ * name is a string representing the task name (to be used in
797
+ * an error message.
798
+ *
799
+ * The do {} while (1==0) construct is done so that the macro may
800
+ * be called like a regular subroutine.
801
+ */
802
+ #define MULTIGET(task,defval,name) \
803
+ do { \
804
+ char errmsg[MAXSTRING]; \
805
+ register int count = 0; \
806
+ \
807
+ while ((count < nmax) && (keyprsnt_c(keyword) == FORT_TRUE)) \
808
+ task(keyword, &value[count++], defval); \
809
+ \
810
+ if (keyprsnt_c(keyword) == FORT_TRUE) { \
811
+ (void)sprintf(errmsg, "%s: Buffer overflow for keyword [%s].", \
812
+ name, keyword); \
813
+ (void)bug_c('f', errmsg); \
814
+ } \
815
+ \
816
+ *n = count; \
817
+ } while (1==0)
818
+
819
+ /***********************************************************************/
820
+ void mkeyd_c(Const char *keyword, double value[], Const int nmax, int *n)
821
+ /** MKeyd -- Retrieve multiple double values from the command line. */
822
+ /*& pjt */
823
+ /*: user-input,command-line */
824
+ /*+ FORTRAN call sequence:
825
+
826
+ subroutine mkeyd(key,value,nmax,n)
827
+ integer nmax, n
828
+ character key*(*)
829
+ double precision value(nmax)
830
+
831
+ Retrieve multiple double precision values from the command line.
832
+ If the keyword is not found, then zero values are returned.
833
+
834
+ Input:
835
+ key The name of the keyword to return.
836
+ nmax The maximum number of values to return
837
+
838
+ Output:
839
+ n The number of values returned.
840
+ value The returned values
841
+ */
842
+ /*--*/
843
+ /*---------------------------------------------------------------------*/
844
+ {
845
+ MULTIGET(keyd_c, 0.0, "MKeyD");
846
+ return;
847
+ }
848
+
849
+ /***********************************************************************/
850
+ void mkeyr_c(Const char *keyword, float value[], Const int nmax, int *n)
851
+ /** MKeyr -- Retrieve multiple real values from the command line. */
852
+ /*& pjt */
853
+ /*: user-input,command-line */
854
+ /*+ FORTRAN call sequence:
855
+
856
+ subroutine mkeyr(key,value,nmax,n)
857
+ integer nmax, n
858
+ character key*(*)
859
+ real value(nmax)
860
+
861
+ Retrieve multiple real values from the command line. If the keyword
862
+ is not found, then zero values are returned.
863
+
864
+ Input:
865
+ key The name of the keyword to return.
866
+ nmax The maximum number of values to return
867
+
868
+ Output:
869
+ n The number of values returned.
870
+ value The returned values
871
+ */
872
+ /*--*/
873
+ /*---------------------------------------------------------------------*/
874
+ {
875
+ MULTIGET(keyr_c, 0.0, "MKeyR");
876
+ return;
877
+ }
878
+
879
+ /***********************************************************************/
880
+ void mkeyi_c(Const char *keyword, int value[], Const int nmax, int *n)
881
+ /** MKeyi -- Retrieve multiple integer values from the command line. */
882
+ /*& pjt */
883
+ /*: user-input,command-line */
884
+ /*+ FORTRAN call sequence:
885
+
886
+ subroutine mkeyi(key,value,nmax,n)
887
+ integer nmax, n
888
+ character key*(*)
889
+ integer value(nmax)
890
+
891
+ Retrieve multiple integer values from the command line. If the
892
+ keyword is not found, then zero values are returned.
893
+
894
+ Input:
895
+ key The name of the keyword to return.
896
+ nmax The maximum number of values to return
897
+
898
+ Output:
899
+ n The number of values returned.
900
+ value The returned values
901
+ */
902
+ /*--*/
903
+ /*---------------------------------------------------------------------*/
904
+ {
905
+ MULTIGET(keyi_c, 0, "MKeyI");
906
+ return;
907
+ }
908
+
909
+ #ifdef TESTBED
910
+ /***********************************************************************/
911
+ int main(int argc, char *argv[])
912
+ {
913
+ char aval[100];
914
+ register int i;
915
+ int ival;
916
+ float fval;
917
+ double cnt[5];
918
+
919
+ keyini_c(argc, argv);
920
+ mkeyd_c("cnt", cnt, 5, &ival);
921
+ for (i = 0; i < ival; i++)
922
+ (void)printf("cnt[%d] = %g\n", i+1, cnt[i]);
923
+ for (i = 0; i < 5; i++) {
924
+ keyi_c("alpha", &ival, 100);
925
+ (void)printf("Alpha[100] = %d ", ival);
926
+ keya_c("beta", aval, "def-val");
927
+ (void)printf("Beta[def-val] = %s ", aval);
928
+ keyr_c("gamma", &fval, 10.0);
929
+ (void)printf("Gamma[10.0] = %g\n", fval);
930
+ }
931
+ keyfin_c();
932
+ (void)exit(0);
933
+ }
934
+ #endif