source: proiecte/NBody/Tree codes/getparam.c @ 170

Last change on this file since 170 was 170, checked in by (none), 14 years ago
File size: 11.9 KB
Line 
1/****************************************************************************/
2/* GETPARAM.C: command-line processing functions.                           */
3/* Copyright (c) 2001 by Joshua E. Barnes, Honolulu, Hawai`i.               */
4/****************************************************************************/
5
6#include "stdinc.h"
7#include "getparam.h"
8#include <string.h>
9
10/*
11 * PARAM: structure encoding parameter name and value.
12 */
13
14typedef struct {
15    string name;                                /* name of parameter        */
16    string value;                               /* value of parameter       */
17    string comment;                             /* documentation string     */
18    int flags;                                  /* for various options      */
19} param;
20
21/*
22 * Local routines and definitions.
23 */
24
25local int countdefaults(string *);              /* number of defaults       */
26local void setprogram(param *, string);         /* set 0th parameter        */
27local void copydefaults(param *, string *);     /* set default parameters   */
28local void checkhelp(param *, string);          /* help processing          */
29local void printitem(string, string);           /* print param and comment  */
30local void setarguments(param *, string *);     /* set command parameters   */
31local void reqarguments(param *);               /* check manditory args     */
32local param *findparam(string, param *);        /* look up parameter value  */
33local string parname(string);                   /* extract param name       */
34local string parvalue(string);                  /* extract param value      */
35
36local param *paramvec = NULL;                   /* vector of parameters     */
37
38local string progname = NULL;                   /* program name, for errors */
39
40/*
41 * INITPARAM: initalize parameter lists and handle special requests.
42 */
43
44void initparam(string *argv, string *defv)
45{
46    int nparam;
47    param *pvec;
48
49    progname = argv[0];                         /* initialize program name  */
50    nparam = 1 + countdefaults(defv);           /* include argv0 in count   */
51    pvec = (param *) allocate(sizeof(param) * (nparam + 1));
52    setprogram(pvec, argv[0]);                  /* install 0th argument     */
53    copydefaults(pvec, defv);                   /* set up default values    */
54    checkhelp(pvec, argv[1]);                   /* give help if requested   */
55    setarguments(pvec, argv);                   /* args override defaults   */
56    reqarguments(pvec);                         /* complain if args missing */
57    paramvec = pvec;                            /* install parameter vector */
58}
59
60/*
61 * COUNTDEFAULTS: count number of default parameters.
62 */
63
64local int countdefaults(string *defv)
65{
66    int ndefault;
67    string *dp;
68
69    ndefault = 0;
70    for (dp = defv; *dp != NULL; dp++)          /* loop over all defaults   */
71        if (**dp != ';')                        /* if not a comment         */
72            ndefault++;                         /* then count one more      */
73    return (ndefault);
74}
75
76/*
77 * SETPROGRAM: initialize the program name as parameter "argv0".
78 */
79
80local void setprogram(param *pvec, string argv0)
81{
82    pvec->name = "argv0";                       /* install 0th parameter    */
83    pvec->value = argv0;                        /* set name from argv[0]    */
84    pvec->comment = NULL;                       /* no comment for now       */
85    pvec->flags = ARGPARAM;                     /* so user can't reset it   */
86}
87
88/*
89 * COPYDEFAULTS: install default parameters and comments.
90 */
91
92local void copydefaults(param *pvec, string *defv)
93{
94    param *pp;
95    string *dp, name, value;
96
97    pp = pvec;                                  /* start with 0th param     */
98    for (dp = defv; *dp != NULL; dp++)          /* loop over the defaults   */
99        if (**dp == ';') {                      /* is this is a comment?    */
100            if (pp->comment != NULL)            /* already have a comment?  */
101                error("copydefaults: cant append comments\n");
102            pp->comment = strdup(*dp + 1);      /* store comment in field   */
103        } else {                                /* else its not a comment   */
104            pp++;                               /* so move onto new param   */
105            name = parname(*dp);                /* extract parameter name   */
106            value = parvalue(*dp);              /* and parameter value      */
107            if (name == NULL || value == NULL)  /* is either one missing?   */
108                error("copydefaults: bad parameter %s\n", *dp);
109            pp->name = strdup(name);            /* assign parameter name    */
110            pp->value = strdup(value);          /* and parameter value      */
111            pp->comment = NULL;                 /* clear comment field      */
112            pp->flags = DEFPARAM;               /* set source to default    */
113            if (streq(pp->value, "???"))        /* is this param required?  */
114                pp->flags |= REQPARAM;          /* set the required flag    */
115            if (**dp == '<')                    /* an input parameter?      */
116                pp->flags |= INPARAM;           /* set the input flag       */
117            else if (**dp == '>')               /* or an output parameter?  */
118                pp->flags |= OUTPARAM;          /* set the output flag      */
119            if (name[0] == '.')                 /* a hidden parameter?      */
120                pp->flags |= HIDPARAM;          /* set the hidden flag      */
121        }
122    pp++;                                       /* past last real param     */
123    pp->name = NULL;                            /* end list of parameters   */
124}
125
126/*
127 * CHECKHELP: if requested, print out help mesaages and exit.
128 */
129
130local void checkhelp(param *pvec, string argv1)
131{
132    param *pp;
133    char buf[128];
134
135    if (argv1 != NULL && streq(argv1, "-clue")) {
136                                                /* print brief help message */
137        printf("%s", pvec->value);
138        for (pp = pvec+1; pp->name != NULL; pp++)
139            printf(" %s=%s", pp->name, pp->value);
140        printf("\n");
141        exit(0);
142    }
143    if (argv1 != NULL && streq(argv1, "-help")) {
144                                                /* print full help message  */
145       printitem(pvec->value, pvec->comment);
146        for (pp = pvec+1; pp->name != NULL; pp++) {
147            sprintf(buf, "  %s=%s", pp->name, pp->value);
148            printitem(buf, pp->comment);
149        }
150        exit(0);
151    }
152}
153
154local void printitem(string item, string comment)
155{
156    if (comment == NULL)
157        printf("%s\n", item);
158    else
159        if (strlen(item) < 32)
160            printf("%-32s  %s\n", item, comment);
161        else
162            printf("%s\n\t\t\t\t  %s\n", item, comment);
163}
164
165/*
166 * SETARGUMENTS: override defaults with commandline arguments.
167 */
168
169local void setarguments(param *pvec, string *argv)
170{
171    bool scanpos;
172    param *pp;
173    string *ap, name;
174
175    scanpos = TRUE;                             /* start scan by position   */
176    pp = pvec;                                  /* start at 0th param       */
177    for (ap = argv + 1; *ap != NULL; ap++) {    /* loop over command args   */
178        name = parname(*ap);                    /* get param name, if any   */
179        scanpos = scanpos && (name == NULL);    /* see how to match args    */
180        if (scanpos) {                          /* matching by position?    */
181            pp++;                               /* then move to next param  */
182            if (pp->name == NULL)               /* make sure it exists      */
183                error("%s: too many arguments\n", progname);
184            pp->value = strdup(*ap);            /* OK, set new param value  */
185        } else {                                /* else matching by name?   */
186            if (name == NULL)                   /* make sure name was given */
187                error("%s: nameless arg %s\n", progname, *ap);
188            pp = findparam(name, pvec);         /* look for named param     */
189            if (pp == NULL)                     /* make sure param exists   */
190                error("%s: parameter %s unknown\n", progname, name);
191            if (pp->flags & ARGPARAM)           /* must not already be set  */
192                error("%s: parameter %s duplicated\n", progname, name);
193            pp->value = strdup(parvalue(*ap));  /* OK, set new param value  */
194        }
195        pp->flags = (pp->flags & ~DEFPARAM) | ARGPARAM;
196                                                /* switch source flag       */
197    }
198}
199
200/*
201 * REQARGUMENTS: print out short message on use.
202 */
203
204local void reqarguments(param *pvec)
205{
206    bool needarg;
207    param *pp;
208
209    needarg = FALSE;                            /* see if any args left out */
210    for (pp = pvec+1; pp->name != NULL; pp++)   /* scan list of parameters  */
211        if ((pp->flags & REQPARAM) &&           /* a required parameter?    */
212              (pp->flags & DEFPARAM))           /* and still defaulted?     */
213            needarg = TRUE;                     /* note missing args exist  */
214    if (needarg) {                              /* list required arguments  */
215        eprintf("Usage: %s", progname);
216        for (pp = pvec+1; pp->name != NULL; pp++)
217            if ((pp->flags & REQPARAM))
218                eprintf(" %s=???", pp->name);
219        error("%s: required arguments missing\n", progname);
220    }
221}
222
223/*
224 * GETPARAM: return value of parameter.  As a special case, requests for
225 * "argv0" can be handled before paramvec has been set, to allow error
226 * handling during the initialization process.
227 */
228
229string getparam(string name)
230{
231    param *par;
232
233    if (paramvec == NULL)
234        if (streq(name, "argv0") && progname != NULL)
235            return (progname);
236        else
237            error("getparam: called before initparam\n");
238    par = findparam(name, paramvec);
239    if (par == NULL)
240        error("getparam in %s: parameter %s unknown\n", progname, name);
241    return (par->value);
242}
243
244/*
245 * GETPARAMSTAT: return parameter flags, or zero if no such parameter
246 * (note that all defined parameters have at least one bit set).
247 */
248
249int getparamstat(string name)
250{
251    param *par;
252
253    par = findparam(name, paramvec);
254    return (par != NULL ? par->flags : 0);
255}
256
257/*
258 * GETIPARAM, GETDPARAM, GETBPARAM: get int, double, or bool parameter.
259 */
260
261int getiparam(string name)
262{
263    int val;
264    string end;
265
266    val = strtol(getparam(name), &end, 0);
267    if (*end == 'k' || *end == 'K')
268        return (1024 * val);
269    if (*end == 'm' || *end == 'M')
270        return (1024 * 1024 * val);
271    return (val);
272}
273
274double getdparam(string name)
275{
276    return (atof(getparam(name)));              /* convert value to double  */
277}
278
279bool getbparam(string name)
280{
281    char *val;
282
283    val = getparam(name);                       /* obtain value of param    */
284    if (strchr("tTyY1", *val) != NULL)          /* is value true?           */
285        return (TRUE);
286    if (strchr("fFnN0", *val) != NULL)          /* is value false?          */
287        return (FALSE);
288    error("getbparam: %s=%s not bool\n", name, val);
289    return (FALSE);                             /* keep compiler happy...   */
290}
291
292/*
293 * FINDPARAM: look for named parameter in list of parameters.
294 */
295
296local param *findparam(string name, param *pvec)
297{
298    param *pp;
299
300    for (pp = pvec; pp->name != NULL; pp++)
301        if (streq(name, pp->name))
302            return (pp);
303    return (NULL);
304}
305
306/*
307 * PARNAME: extract name from name=value string.
308 * W A R N I N G :  returns ptr to static storage.
309 */
310
311local string parname(string arg)
312{
313    char *ap, *ep;
314    static char namebuf[64];
315
316    ap = (char *) arg;
317    if (*ap == '<' || *ap == '>')
318        ap++;
319    strncpy(namebuf, ap, 63);
320    namebuf[63] = NULL;
321    ep = strchr(namebuf, '=');
322    if (ep == NULL)                             /* not of form name=value?  */
323        return (NULL);
324    *ep = NULL;
325    return (namebuf);
326}
327
328/*
329 * PARVALUE: extract value from name=value string.
330 */
331
332local string parvalue(string arg)
333{
334    char *ep;
335
336    ep = strchr(arg, '=');
337    if (ep == NULL)
338        return (NULL);
339    return (ep + 1);
340}
Note: See TracBrowser for help on using the repository browser.