OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [argtable2/] [argtable2.c] - Blame information for rev 144

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 19 jeremybenn
/*********************************************************************
2
This file is part of the argtable2 library.
3
Copyright (C) 1998-2001,2003-2008 Stewart Heitmann
4
sheitmann@users.sourceforge.net
5
 
6
The argtable2 library is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Library General Public License as
8
published by the Free Software Foundation; either version 2 of the
9
License, or (at your option) any later version.
10
 
11
This software is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
Library General Public License for more details.
15
 
16
You should have received a copy of the GNU Library General Public
17
License along with this library; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19
USA.
20
**********************************************************************/
21
 
22
/* config.h must be included before anything else */
23
#ifdef HAVE_CONFIG_H
24
#include "config.h"
25
#endif
26
 
27
#include <stdlib.h>
28
#include <string.h>
29
#include <stdlib.h>
30
#include <ctype.h>
31
 
32
#ifdef HAVE_STRINGS_H
33
#include <strings.h>
34
#endif
35
 
36
#ifdef HAVE_GETOPT_H
37
#include <getopt.h>
38
#else
39
#include "./getopt.h"
40
#endif
41
 
42
#ifdef HAVE_UNISTD_H
43
#include <unistd.h>
44
#endif
45
 
46
#include "argtable2.h"
47
#include "./getopt.h"
48
 
49
static
50
void arg_register_error(struct arg_end *end, void *parent, int error, const char *argval)
51
    {
52
    /* printf("arg_register_error(%p,%p,%d,%s)\n",end,parent,error,argval); */
53
    if (end->count < end->hdr.maxcount)
54
        {
55
        end->error[end->count] = error;
56
        end->parent[end->count] = parent;
57
        end->argval[end->count] = argval;
58
        end->count++;
59
        }
60
    else
61
        {
62
        end->error[end->hdr.maxcount-1]  = ARG_ELIMIT;
63
        end->parent[end->hdr.maxcount-1] = end;
64
        end->argval[end->hdr.maxcount-1] = NULL;
65
        }
66
    }
67
 
68
 
69
/*
70
 * Return index of first table entry with a matching short option
71
 * or -1 if no match was found.
72
 */
73
static
74
int find_shortoption(struct arg_hdr **table, char shortopt)
75
    {
76
    int tabindex;
77
    for(tabindex=0; !(table[tabindex]->flag&ARG_TERMINATOR); tabindex++)
78
        {
79
        if (table[tabindex]->shortopts && strchr(table[tabindex]->shortopts,shortopt))
80
            return tabindex;
81
        }
82
    return -1;
83
    }
84
 
85
 
86
struct longoptions
87
    {
88
    int getoptval;
89
    int noptions;
90
    struct option *options;
91
    };
92
 
93
#ifndef NDEBUG
94
/* Commented out by JPB for GCC compliance
95
static
96
void dump_longoptions(struct longoptions* longoptions)
97
    {
98
    int i;
99
    printf("getoptval = %d\n", longoptions->getoptval);
100
    printf("noptions  = %d\n", longoptions->noptions);
101
    for (i=0; i<longoptions->noptions; i++)
102
        {
103
        printf("options[%d].name    = \"%s\"\n", i, longoptions->options[i].name);
104
        printf("options[%d].has_arg = %d\n", i, longoptions->options[i].has_arg);
105
        printf("options[%d].flag    = %p\n", i, longoptions->options[i].flag);
106
        printf("options[%d].val     = %d\n", i, longoptions->options[i].val);
107
        }
108
    }
109
*/
110
#endif
111
 
112
static
113
struct longoptions* alloc_longoptions(struct arg_hdr **table)
114
    {
115
    struct longoptions *result;
116
    size_t nbytes;
117
    int noptions = 1;
118
    size_t longoptlen = 0;
119
    int tabindex;
120
 
121
    /*
122
     * Determine the total number of option structs required
123
     * by counting the number of comma separated long options
124
     * in all table entries and return the count in noptions.
125
     * note: noptions starts at 1 not 0 because we getoptlong
126
     * requires a NULL option entry to terminate the option array.
127
     * While we are at it, count the number of chars required
128
     * to store private copies of all the longoption strings
129
     * and return that count in logoptlen.
130
     */
131
     tabindex=0;
132
     do
133
        {
134
        const char *longopts = table[tabindex]->longopts;
135
        longoptlen += (longopts?strlen(longopts):0) + 1;
136
        while (longopts)
137
            {
138
            noptions++;
139
            longopts = strchr(longopts+1,',');
140
            }
141
        }while(!(table[tabindex++]->flag&ARG_TERMINATOR));
142
    /*printf("%d long options consuming %d chars in total\n",noptions,longoptlen);*/
143
 
144
 
145
    /* allocate storage for return data structure as: */
146
    /* (struct longoptions) + (struct options)[noptions] + char[longoptlen] */
147
    nbytes = sizeof(struct longoptions)
148
           + sizeof(struct option)*noptions
149
           + longoptlen;
150
    result = (struct longoptions*)malloc(nbytes);
151
    if (result)
152
        {
153
        int option_index=0;
154
        char *store;
155
 
156
        result->getoptval=0;
157
        result->noptions = noptions;
158
        result->options = (struct option*)(result + 1);
159
        store = (char*)(result->options + noptions);
160
 
161
        for(tabindex=0; !(table[tabindex]->flag&ARG_TERMINATOR); tabindex++)
162
            {
163
            const char *longopts = table[tabindex]->longopts;
164
 
165
            while(longopts && *longopts)
166
                {
167
                char *storestart = store;
168
 
169
                /* copy progressive longopt strings into the store */
170
                while (*longopts!=0 && *longopts!=',')
171
                    *store++ = *longopts++;
172
                *store++ = 0;
173
                if (*longopts==',')
174
                    longopts++;
175
                /*fprintf(stderr,"storestart=\"%s\"\n",storestart);*/
176
 
177
                result->options[option_index].name    = storestart;
178
                result->options[option_index].flag    = &(result->getoptval);
179
                result->options[option_index].val     = tabindex;
180
                if (table[tabindex]->flag & ARG_HASOPTVALUE)
181
                    result->options[option_index].has_arg = 2;
182
                else if (table[tabindex]->flag & ARG_HASVALUE)
183
                    result->options[option_index].has_arg = 1;
184
                else
185
                    result->options[option_index].has_arg = 0;
186
 
187
                option_index++;
188
                }
189
            }
190
        /* terminate the options array with a zero-filled entry */
191
        result->options[option_index].name    = 0;
192
        result->options[option_index].has_arg = 0;
193
        result->options[option_index].flag    = 0;
194
        result->options[option_index].val     = 0;
195
        }
196
 
197
    /*dump_longoptions(result);*/
198
    return result;
199
    }
200
 
201
static
202
char* alloc_shortoptions(struct arg_hdr **table)
203
   {
204
   char *result;
205
   size_t len = 2;
206
   int tabindex;
207
 
208
   /* determine the total number of option chars required */
209
   for(tabindex=0; !(table[tabindex]->flag&ARG_TERMINATOR); tabindex++)
210
       {
211
       struct arg_hdr *hdr = table[tabindex];
212
       len += 3 * (hdr->shortopts?strlen(hdr->shortopts):0);
213
       }
214
 
215
   result = malloc(len);
216
   if (result)
217
        {
218
        char *res = result;
219
 
220
        /* add a leading ':' so getopt return codes distinguish    */
221
        /* unrecognised option and options missing argument values */
222
        *res++=':';
223
 
224
        for(tabindex=0; !(table[tabindex]->flag&ARG_TERMINATOR); tabindex++)
225
            {
226
            struct arg_hdr *hdr = table[tabindex];
227
            const char *shortopts = hdr->shortopts;
228
            while(shortopts && *shortopts)
229
                {
230
                *res++ = *shortopts++;
231
                if (hdr->flag & ARG_HASVALUE)
232
                    *res++=':';
233
                if (hdr->flag & ARG_HASOPTVALUE)
234
                    *res++=':';
235
                }
236
            }
237
        /* null terminate the string */
238
        *res=0;
239
        }
240
 
241
   /*printf("alloc_shortoptions() returns \"%s\"\n",(result?result:"NULL"));*/
242
   return result;
243
   }
244
 
245
 
246
/* return index of the table terminator entry */
247
static
248
int arg_endindex(struct arg_hdr **table)
249
    {
250
    int tabindex=0;
251
    while (!(table[tabindex]->flag&ARG_TERMINATOR))
252
        tabindex++;
253
    return tabindex;
254
    }
255
 
256
 
257
static
258
void arg_parse_tagged(int argc, char **argv, struct arg_hdr **table, struct arg_end *endtable)
259
    {
260
    struct longoptions *longoptions;
261
    char *shortoptions;
262
    int copt;
263
 
264
    /*printf("arg_parse_tagged(%d,%p,%p,%p)\n",argc,argv,table,endtable);*/
265
 
266
    /* allocate short and long option arrays for the given opttable[].   */
267
    /* if the allocs fail then put an error msg in the last table entry. */
268
    longoptions  = alloc_longoptions(table);
269
    shortoptions = alloc_shortoptions(table);
270
    if (!longoptions || !shortoptions)
271
        {
272
        /* one or both memory allocs failed */
273
        arg_register_error(endtable,endtable,ARG_EMALLOC,NULL);
274
        /* free anything that was allocated (this is null safe) */
275
        free(shortoptions);
276
        free(longoptions);
277
        return;
278
        }
279
 
280
    /*dump_longoptions(longoptions);*/
281
 
282
    /* reset getopts internal option-index to zero, and disable error reporting */
283
    optind = 0;
284
    opterr = 0;
285
 
286
    /* fetch and process args using getopt_long */
287
    while( (copt=getopt_long(argc,argv,shortoptions,longoptions->options,NULL)) != -1)
288
        {
289
        /*
290
        printf("optarg='%s'\n",optarg);
291
        printf("optind=%d\n",optind);
292
        printf("copt=%c\n",(char)copt);
293
        printf("optopt=%c (%d)\n",optopt, (int)(optopt));
294
        */
295
        switch(copt)
296
            {
297
            case 0:
298
                {
299
                int tabindex = longoptions->getoptval;
300
                void *parent  = table[tabindex]->parent;
301
                /*printf("long option detected from argtable[%d]\n", tabindex);*/
302
                if (optarg && optarg[0]==0 && (table[tabindex]->flag & ARG_HASVALUE))
303
                    {
304
                    /* printf(": long option %s requires an argument\n",argv[optind-1]); */
305
                    arg_register_error(endtable,endtable,ARG_EMISSARG,argv[optind-1]);
306
                    /* continue to scan the (empty) argument value to enforce argument count checking */
307
                    }
308
                if (table[tabindex]->scanfn)
309
                    {
310
                    int errorcode = table[tabindex]->scanfn(parent,optarg);
311
                    if (errorcode!=0)
312
                        arg_register_error(endtable,parent,errorcode,optarg);
313
                    }
314
                }
315
                break;
316
 
317
            case '?':
318
                /*
319
                * getopt_long() found an unrecognised short option.
320
                * if it was a short option its value is in optopt
321
                * if it was a long option then optopt=0
322
                */
323
                switch (optopt)
324
                    {
325
                    case 0:
326
                        /*printf("?0 unrecognised long option %s\n",argv[optind-1]);*/
327
                        arg_register_error(endtable,endtable,ARG_ELONGOPT,argv[optind-1]);
328
                        break;
329
                    default:
330
                        /*printf("?* unrecognised short option '%c'\n",optopt);*/
331
                        arg_register_error(endtable,endtable,optopt,NULL);
332
                        break;
333
                    }
334
                break;
335
 
336
            case':':
337
                /*
338
                * getopt_long() found an option with its argument missing.
339
                */
340
                /*printf(": option %s requires an argument\n",argv[optind-1]); */
341
                arg_register_error(endtable,endtable,ARG_EMISSARG,argv[optind-1]);
342
                break;
343
 
344
            default:
345
                {
346
                /* getopt_long() found a valid short option */
347
                int tabindex = find_shortoption(table,(char)copt);
348
                /*printf("short option detected from argtable[%d]\n", tabindex);*/
349
                if (tabindex==-1)
350
                    {
351
                    /* should never get here - but handle it just in case */
352
                    /*printf("unrecognised short option %d\n",copt);*/
353
                    arg_register_error(endtable,endtable,copt,NULL);
354
                    }
355
                else
356
                    {
357
                    if (table[tabindex]->scanfn)
358
                        {
359
                        void *parent  = table[tabindex]->parent;
360
                        int errorcode = table[tabindex]->scanfn(parent,optarg);
361
                        if (errorcode!=0)
362
                            arg_register_error(endtable,parent,errorcode,optarg);
363
                        }
364
                    }
365
                break;
366
                }
367
            }
368
        }
369
 
370
    free(shortoptions);
371
    free(longoptions);
372
    }
373
 
374
 
375
static
376
void arg_parse_untagged(int argc, char **argv, struct arg_hdr **table, struct arg_end *endtable)
377
    {
378
    int tabindex=0;
379
    int errorlast=0;
380
    const char *optarglast = NULL;
381
    void *parentlast = NULL;
382
 
383
    /*printf("arg_parse_untagged(%d,%p,%p,%p)\n",argc,argv,table,endtable);*/
384
    while (!(table[tabindex]->flag&ARG_TERMINATOR))
385
        {
386
        void *parent;
387
        int errorcode;
388
 
389
        /* if we have exhausted our argv[optind] entries then we have finished */
390
        if (optind>=argc)
391
            {
392
            /*printf("arg_parse_untagged(): argv[] exhausted\n");*/
393
            return;
394
            }
395
 
396
        /* skip table entries with non-null long or short options (they are not untagged entries) */
397
        if (table[tabindex]->longopts || table[tabindex]->shortopts)
398
            {
399
            /*printf("arg_parse_untagged(): skipping argtable[%d] (tagged argument)\n",tabindex);*/
400
            tabindex++;
401
            continue;
402
            }
403
 
404
        /* skip table entries with NULL scanfn */
405
        if (!(table[tabindex]->scanfn))
406
            {
407
            /*printf("arg_parse_untagged(): skipping argtable[%d] (NULL scanfn)\n",tabindex);*/
408
            tabindex++;
409
            continue;
410
            }
411
 
412
        /* attempt to scan the current argv[optind] with the current     */
413
        /* table[tabindex] entry. If it succeeds then keep it, otherwise */
414
        /* try again with the next table[] entry.                        */
415
        parent = table[tabindex]->parent;
416
        errorcode = table[tabindex]->scanfn(parent,argv[optind]);
417
        if (errorcode==0)
418
            {
419
            /* success, move onto next argv[optind] but stay with same table[tabindex] */
420
            /*printf("arg_parse_untagged(): argtable[%d] successfully matched\n",tabindex);*/
421
            optind++;
422
 
423
            /* clear the last tentative error */
424
            errorlast = 0;
425
            }
426
        else
427
            {
428
            /* failure, try same argv[optind] with next table[tabindex] entry */
429
            /*printf("arg_parse_untagged(): argtable[%d] failed match\n",tabindex);*/
430
            tabindex++;
431
 
432
            /* remember this as a tentative error we may wish to reinstate later */
433
            errorlast = errorcode;
434
            optarglast = argv[optind];
435
            parentlast = parent;
436
            }
437
 
438
        }
439
 
440
    /* if a tenative error still remains at this point then register it as a proper error */
441
    if (errorlast)
442
        {
443
        arg_register_error(endtable,parentlast,errorlast,optarglast);
444
        optind++;
445
        }
446
 
447
    /* only get here when not all argv[] entries were consumed */
448
    /* register an error for each unused argv[] entry */
449
    while (optind<argc)
450
        {
451
        /*printf("arg_parse_untagged(): argv[%d]=\"%s\" not consumed\n",optind,argv[optind]);*/
452
        arg_register_error(endtable,endtable,ARG_ENOMATCH,argv[optind++]);
453
        }
454
 
455
    return;
456
    }
457
 
458
 
459
static
460
void arg_parse_check(struct arg_hdr **table, struct arg_end *endtable)
461
    {
462
    int tabindex=0;
463
    /* printf("arg_parse_check()\n"); */
464
    do
465
        {
466
        if (table[tabindex]->checkfn)
467
            {
468
            void *parent  = table[tabindex]->parent;
469
            int errorcode = table[tabindex]->checkfn(parent);
470
            if (errorcode!=0)
471
                arg_register_error(endtable,parent,errorcode,NULL);
472
            }
473
        }while(!(table[tabindex++]->flag&ARG_TERMINATOR));
474
    }
475
 
476
 
477
static
478
void arg_reset(void **argtable)
479
    {
480
    struct arg_hdr **table=(struct arg_hdr**)argtable;
481
    int tabindex=0;
482
    /*printf("arg_reset(%p)\n",argtable);*/
483
    do
484
        {
485
        if (table[tabindex]->resetfn)
486
            table[tabindex]->resetfn(table[tabindex]->parent);
487
        } while(!(table[tabindex++]->flag&ARG_TERMINATOR));
488
    }
489
 
490
 
491
int arg_parse(int argc, char **argv, void **argtable)
492
    {
493
    struct arg_hdr **table = (struct arg_hdr **)argtable;
494
    struct arg_end *endtable;
495
    int endindex;
496
    char **argvcopy = NULL;
497
 
498
    /*printf("arg_parse(%d,%p,%p)\n",argc,argv,argtable);*/
499
 
500
    /* reset any argtable data from previous invocations */
501
    arg_reset(argtable);
502
 
503
    /* locate the first end-of-table marker within the array */
504
    endindex = arg_endindex(table);
505
    endtable = (struct arg_end*)table[endindex];
506
 
507
    /* Special case of argc==0.  This can occur on Texas Instruments DSP. */
508
    /* Failure to trap this case results in an unwanted NULL result from  */
509
    /* the malloc for argvcopy (next code block).                         */
510
    if (argc==0)
511
        {
512
        /* We must still perform post-parse checks despite the absence of command line arguments */
513
        arg_parse_check(table,endtable);
514
 
515
        /* Now we are finished */
516
        return endtable->count;
517
        }
518
 
519
    argvcopy = malloc(sizeof(char *) * argc);
520
    if (argvcopy)
521
        {
522
        int i;
523
 
524
        /*
525
        Fill in the local copy of argv[]. We need a local copy
526
        because getopt rearranges argv[] which adversely affects
527
        susbsequent parsing attempts.
528
        */
529
        for (i=0; i<argc; i++)
530
            argvcopy[i] = argv[i];
531
 
532
        /* parse the command line (local copy) for tagged options */
533
        arg_parse_tagged(argc,argvcopy,table,endtable);
534
 
535
        /* parse the command line (local copy) for untagged options */
536
        arg_parse_untagged(argc,argvcopy,table,endtable);
537
 
538
        /* if no errors so far then perform post-parse checks otherwise dont bother */
539
        if (endtable->count==0)
540
            arg_parse_check(table,endtable);
541
 
542
        /* release the local copt of argv[] */
543
        free(argvcopy);
544
        }
545
    else
546
        {
547
        /* memory alloc failed */
548
        arg_register_error(endtable,endtable,ARG_EMALLOC,NULL);
549
        }
550
 
551
    return endtable->count;
552
    }
553
 
554
 
555
/*
556
 * Concatenate contents of src[] string onto *pdest[] string.
557
 * The *pdest pointer is altered to point to the end of the
558
 * target string and *pndest is decremented by the same number
559
 * of chars.
560
 * Does not append more than *pndest chars into *pdest[]
561
 * so as to prevent buffer overruns.
562
 * Its something like strncat() but more efficient for repeated
563
 * calls on the same destination string.
564
 * Example of use:
565
 *   char dest[30] = "good"
566
 *   size_t ndest = sizeof(dest);
567
 *   char *pdest = dest;
568
 *   arg_char(&pdest,"bye ",&ndest);
569
 *   arg_char(&pdest,"cruel ",&ndest);
570
 *   arg_char(&pdest,"world!",&ndest);
571
 * Results in:
572
 *   dest[] == "goodbye cruel world!"
573
 *   ndest  == 10
574
 */
575
static
576
void arg_cat(char **pdest, const char *src, size_t *pndest)
577
    {
578
    char *dest = *pdest;
579
    char *end  = dest + *pndest;
580
 
581
    /*locate null terminator of dest string */
582
    while(dest<end && *dest!=0)
583
        dest++;
584
 
585
    /* concat src string to dest string */
586
    while(dest<end && *src!=0)
587
        *dest++ = *src++;
588
 
589
    /* null terminate dest string */
590
    *dest=0;
591
 
592
    /* update *pdest and *pndest */
593
    *pndest = end - dest;
594
    *pdest  = dest;
595
    }
596
 
597
 
598
static
599
void arg_cat_option(char *dest, size_t ndest, const char *shortopts, const char *longopts, const char *datatype, int optvalue)
600
    {
601
    if (shortopts)
602
        {
603
        char option[3];
604
 
605
        /* note: option array[] is initialiazed dynamically here to satisfy   */
606
        /* a deficiency in the watcom compiler wrt static array initializers. */
607
        option[0] = '-';
608
        option[1] = shortopts[0];
609
        option[2] = 0;
610
 
611
        arg_cat(&dest,option,&ndest);
612
        if (datatype)
613
            {
614
            arg_cat(&dest," ",&ndest);
615
            if (optvalue)
616
                {
617
                arg_cat(&dest,"[",&ndest);
618
                arg_cat(&dest,datatype,&ndest);
619
                arg_cat(&dest,"]",&ndest);
620
                }
621
            else
622
                arg_cat(&dest,datatype,&ndest);
623
            }
624
        }
625
    else if (longopts)
626
        {
627
        size_t ncspn;
628
 
629
        /* add "--" tag prefix */
630
        arg_cat(&dest,"--",&ndest);
631
 
632
        /* add comma separated option tag */
633
        ncspn = strcspn(longopts,",");
634
        strncat(dest,longopts,(ncspn<ndest)?ncspn:ndest);
635
 
636
        if (datatype)
637
            {
638
            arg_cat(&dest,"=",&ndest);
639
            if (optvalue)
640
                {
641
                arg_cat(&dest,"[",&ndest);
642
                arg_cat(&dest,datatype,&ndest);
643
                arg_cat(&dest,"]",&ndest);
644
                }
645
            else
646
                arg_cat(&dest,datatype,&ndest);
647
            }
648
        }
649
    else if (datatype)
650
        {
651
        if (optvalue)
652
            {
653
            arg_cat(&dest,"[",&ndest);
654
            arg_cat(&dest,datatype,&ndest);
655
            arg_cat(&dest,"]",&ndest);
656
            }
657
        else
658
            arg_cat(&dest,datatype,&ndest);
659
        }
660
    }
661
 
662
static
663
void arg_cat_optionv(char *dest, size_t ndest, const char *shortopts, const char *longopts, const char *datatype,  int optvalue, const char *separator)
664
    {
665
    separator = separator ? separator : "";
666
 
667
    if (shortopts)
668
        {
669
        const char *c = shortopts;
670
        while(*c)
671
            {
672
            /* "-a|-b|-c" */
673
            char shortopt[3];
674
 
675
            /* note: shortopt array[] is initialiazed dynamically here to satisfy */
676
            /* a deficiency in the watcom compiler wrt static array initializers. */
677
            shortopt[0]='-';
678
            shortopt[1]=*c;
679
            shortopt[2]=0;
680
 
681
            arg_cat(&dest,shortopt,&ndest);
682
            if (*++c)
683
                arg_cat(&dest,separator,&ndest);
684
            }
685
        }
686
 
687
    /* put separator between long opts and short opts */
688
    if (shortopts && longopts)
689
        arg_cat(&dest,separator,&ndest);
690
 
691
    if (longopts)
692
        {
693
        const char *c = longopts;
694
        while(*c)
695
            {
696
            size_t ncspn;
697
 
698
            /* add "--" tag prefix */
699
            arg_cat(&dest,"--",&ndest);
700
 
701
            /* add comma separated option tag */
702
            ncspn = strcspn(c,",");
703
            strncat(dest,c,(ncspn<ndest)?ncspn:ndest);
704
            c+=ncspn;
705
 
706
            /* add given separator in place of comma */
707
            if (*c==',')
708
                 {
709
                 arg_cat(&dest,separator,&ndest);
710
                 c++;
711
                 }
712
            }
713
        }
714
 
715
    if (datatype)
716
        {
717
        if (longopts)
718
            arg_cat(&dest,"=",&ndest);
719
        else if (shortopts)
720
            arg_cat(&dest," ",&ndest);
721
 
722
        if (optvalue)
723
            {
724
            arg_cat(&dest,"[",&ndest);
725
            arg_cat(&dest,datatype,&ndest);
726
            arg_cat(&dest,"]",&ndest);
727
            }
728
        else
729
            arg_cat(&dest,datatype,&ndest);
730
        }
731
    }
732
 
733
 
734
/* this function should be deprecated because it doesnt consider optional argument values (ARG_HASOPTVALUE) */
735
void arg_print_option(FILE *fp, const char *shortopts, const char *longopts, const char *datatype, const char *suffix)
736
    {
737
    char syntax[200]="";
738
    suffix = suffix ? suffix : "";
739
 
740
    /* there is no way of passing the proper optvalue for optional argument values here, so we must ignore it */
741
    arg_cat_optionv(syntax,sizeof(syntax),shortopts,longopts,datatype,0,"|");
742
 
743
    fputs(syntax,fp);
744
    fputs(suffix,fp);
745
    }
746
 
747
 
748
/*
749
 * Print a GNU style [OPTION] string in which all short options that
750
 * do not take argument values are presented in abbreviated form, as
751
 * in: -xvfsd, or -xvf[sd], or [-xvsfd]
752
 */
753
static
754
void arg_print_gnuswitch(FILE *fp, struct arg_hdr **table)
755
    {
756
    int tabindex;
757
    char *format1=" -%c";
758
    char *format2=" [-%c";
759 82 jeremybenn
    int   need_suffix=0; /* JPB mod */
760 19 jeremybenn
 
761
    /* print all mandatory switches that are without argument values */
762
    for(tabindex=0; table[tabindex] && !(table[tabindex]->flag&ARG_TERMINATOR); tabindex++)
763
        {
764
        /* skip optional options */
765
        if (table[tabindex]->mincount<1)
766
            continue;
767
 
768
        /* skip non-short options */
769
        if (table[tabindex]->shortopts==NULL)
770
            continue;
771
 
772
        /* skip options that take argument values */
773
        if (table[tabindex]->flag&ARG_HASVALUE)
774
            continue;
775
 
776
        /* print the short option (only the first short option char, ignore multiple choices)*/
777
        fprintf(fp,format1,table[tabindex]->shortopts[0]);
778
        format1="%c";
779
        format2="[%c";
780
        }
781
 
782
    /* print all optional switches that are without argument values */
783
    for(tabindex=0; table[tabindex] && !(table[tabindex]->flag&ARG_TERMINATOR); tabindex++)
784
        {
785
        /* skip mandatory args */
786
        if (table[tabindex]->mincount>0)
787
            continue;
788
 
789
        /* skip args without short options */
790
        if (table[tabindex]->shortopts==NULL)
791
            continue;
792
 
793
        /* skip args with values */
794
        if (table[tabindex]->flag&ARG_HASVALUE)
795
            continue;
796
 
797
        /* print first short option */
798
        fprintf(fp,format2,table[tabindex]->shortopts[0]);
799
        format2="%c";
800 82 jeremybenn
        need_suffix=1;
801 19 jeremybenn
        }
802
 
803 82 jeremybenn
    fprintf(fp,need_suffix ? "]" : "");
804 19 jeremybenn
    }
805
 
806
 
807
void arg_print_syntax(FILE *fp, void **argtable, const char *suffix)
808
    {
809
    struct arg_hdr **table = (struct arg_hdr**)argtable;
810
    int i,tabindex;
811
 
812
    /* print GNU style [OPTION] string */
813
    arg_print_gnuswitch(fp, table);
814
 
815
    /* print remaining options in abbreviated style */
816
    for(tabindex=0; table[tabindex] && !(table[tabindex]->flag&ARG_TERMINATOR); tabindex++)
817
        {
818
        char syntax[200]="";
819
        const char *shortopts, *longopts, *datatype;
820
 
821
        /* skip short options without arg values (they were printed by arg_print_gnu_switch) */
822
        if (table[tabindex]->shortopts && !(table[tabindex]->flag&ARG_HASVALUE))
823
            continue;
824
 
825
        shortopts = table[tabindex]->shortopts;
826
        longopts  = table[tabindex]->longopts;
827
        datatype  = table[tabindex]->datatype;
828
        arg_cat_option(syntax,sizeof(syntax),shortopts,longopts,datatype, table[tabindex]->flag&ARG_HASOPTVALUE);
829
 
830
        if (strlen(syntax)>0)
831
            {
832
            /* print mandatory instances of this option */
833
            for (i=0; i<table[tabindex]->mincount; i++)
834
                fprintf(fp, " %s",syntax);
835
 
836
            /* print optional instances enclosed in "[..]" */
837
            switch ( table[tabindex]->maxcount - table[tabindex]->mincount )
838
                {
839
                case 0:
840
                    break;
841
                case 1:
842
                    fprintf(fp, " [%s]",syntax);
843
                    break;
844
                case 2:
845
                    fprintf(fp, " [%s] [%s]",syntax,syntax);
846
                    break;
847
                default:
848
                    fprintf(fp, " [%s]...",syntax);
849
                    break;
850
                }
851
            }
852
        }
853
 
854
    if (suffix)
855
        fprintf(fp, "%s",suffix);
856
    }
857
 
858
 
859
void arg_print_syntaxv(FILE *fp, void **argtable, const char *suffix)
860
    {
861
    struct arg_hdr **table = (struct arg_hdr**)argtable;
862
    int i,tabindex;
863
 
864
    /* print remaining options in abbreviated style */
865
    for(tabindex=0; table[tabindex] && !(table[tabindex]->flag&ARG_TERMINATOR); tabindex++)
866
        {
867
        char syntax[200]="";
868
        const char *shortopts, *longopts, *datatype;
869
 
870
        shortopts = table[tabindex]->shortopts;
871
        longopts  = table[tabindex]->longopts;
872
        datatype  = table[tabindex]->datatype;
873
        arg_cat_optionv(syntax,sizeof(syntax),shortopts,longopts,datatype,table[tabindex]->flag&ARG_HASOPTVALUE, "|");
874
 
875
        /* print mandatory options */
876
        for (i=0; i<table[tabindex]->mincount; i++)
877
            fprintf(fp," %s",syntax);
878
 
879
        /* print optional args enclosed in "[..]" */
880
        switch ( table[tabindex]->maxcount - table[tabindex]->mincount )
881
            {
882
            case 0:
883
                break;
884
            case 1:
885
                fprintf(fp, " [%s]",syntax);
886
                break;
887
            case 2:
888
                fprintf(fp, " [%s] [%s]",syntax,syntax);
889
                break;
890
            default:
891
                fprintf(fp, " [%s]...",syntax);
892
                break;
893
            }
894
        }
895
 
896
    if (suffix)
897
        fprintf(fp,"%s",suffix);
898
    }
899
 
900
 
901
void arg_print_glossary(FILE *fp, void **argtable, const char *format)
902
    {
903
    struct arg_hdr **table = (struct arg_hdr**)argtable;
904
    int tabindex;
905
 
906
    format = format ? format : "  %-20s %s\n";
907
    for(tabindex=0; !(table[tabindex]->flag&ARG_TERMINATOR); tabindex++)
908
        {
909
        if (table[tabindex]->glossary)
910
            {
911
            char syntax[200]="";
912
            const char *shortopts = table[tabindex]->shortopts;
913
            const char *longopts  = table[tabindex]->longopts;
914
            const char *datatype  = table[tabindex]->datatype;
915
            const char *glossary  = table[tabindex]->glossary;
916
            arg_cat_optionv(syntax,sizeof(syntax),shortopts,longopts,datatype,table[tabindex]->flag&ARG_HASOPTVALUE,", ");
917
            fprintf(fp,format,syntax,glossary);
918
            }
919
        }
920
    }
921
 
922
 
923
/**
924
 * Print a piece of text formatted, which means in a column with a
925
 * left and a right margin. The lines are wrapped at whitspaces next
926
 * to right margin. The function does not indent the first line, but
927
 * only the following ones.
928
 *
929
 * Example:
930
 * arg_print_formatted( fp, 0, 5, "Some text that doesn't fit." )
931
 * will result in the following output:
932
 *
933
 * Some
934
 * text
935
 * that
936
 * doesn'
937
 * t fit.
938
 *
939
 * Too long lines will be wrapped in the middle of a word.
940
 *
941
 * arg_print_formatted( fp, 2, 7, "Some text that doesn't fit." )
942
 * will result in the following output:
943
 *
944
 * Some
945
 *   text
946
 *   that
947
 *   doesn'
948
 *   t fit.
949
 *
950
 * As you see, the first line is not indented. This enables output of
951
 * lines, which start in a line where output already happened.
952
 *
953
 * Author: Uli Fouquet
954
 */
955
static
956
void arg_print_formatted( FILE *fp, const unsigned lmargin, const unsigned rmargin, const char *text )
957
    {
958
    const unsigned textlen = strlen( text );
959
    unsigned line_start = 0;
960
    unsigned line_end = textlen + 1;
961
    const unsigned colwidth = (rmargin - lmargin) + 1;
962
 
963
    /* Someone doesn't like us... */
964
    if ( line_end < line_start )
965
        { fprintf( fp, "%s\n", text ); }
966
 
967
    while (line_end-1 > line_start )
968
        {
969
        /* Eat leading whitespaces. This is essential because while
970
           wrapping lines, there will often be a whitespace at beginning
971
           of line  */
972 143 jeremybenn
        /* JPB patch to cast argument */
973
          while (isspace ((int) (*(text+line_start))) )
974 19 jeremybenn
            { line_start++; }
975
 
976
        if ((line_end - line_start) > colwidth )
977
            { line_end = line_start + colwidth; }
978
 
979
        /* Find last whitespace, that fits into line */
980 144 jeremybenn
        /* JPB patch to cast argument */
981 19 jeremybenn
        while ( ( line_end > line_start )
982
                && ( line_end - line_start > colwidth )
983 143 jeremybenn
                && !isspace ((int) (*(text+line_end))))
984 19 jeremybenn
            { line_end--; }
985
 
986
        /* Do not print trailing whitespace. If this text
987
           has got only one line, line_end now points to the
988
           last char due to initialization. */
989
        line_end--;
990
 
991
        /* Output line of text */
992
        while ( line_start < line_end )
993
            {
994
            fputc(*(text+line_start), fp );
995
            line_start++;
996
            }
997
        fputc( '\n', fp );
998
 
999
        /* Initialize another line */
1000
        if ( line_end+1 < textlen )
1001
            {
1002
            unsigned i;
1003
 
1004
            for (i=0; i < lmargin; i++ )
1005
                { fputc( ' ', fp ); }
1006
 
1007
            line_end = textlen;
1008
            }
1009
 
1010
        /* If we have to print another line, get also the last char. */
1011
        line_end++;
1012
 
1013
        } /* lines of text */
1014
    }
1015
 
1016
/**
1017
 * Prints the glossary in strict GNU format.
1018
 * Differences to arg_print_glossary() are:
1019
 *  - wraps lines after 80 chars
1020
 *  - indents lines without shortops
1021
 *  - does not accept formatstrings
1022
 *
1023
 * Contributed by Uli Fouquet
1024
 */
1025
void arg_print_glossary_gnu(FILE *fp, void **argtable )
1026
    {
1027
    struct arg_hdr **table = (struct arg_hdr**)argtable;
1028
    int tabindex;
1029
 
1030
    for(tabindex=0; !(table[tabindex]->flag&ARG_TERMINATOR); tabindex++)
1031
        {
1032
        if (table[tabindex]->glossary)
1033
            {
1034
            char syntax[200]="";
1035
            const char *shortopts = table[tabindex]->shortopts;
1036
            const char *longopts  = table[tabindex]->longopts;
1037
            const char *datatype  = table[tabindex]->datatype;
1038
            const char *glossary  = table[tabindex]->glossary;
1039
 
1040
            if ( !shortopts && longopts )
1041
                {
1042
                /* Indent trailing line by 4 spaces... */
1043
                memset( syntax, ' ', 4 );
1044
                *(syntax+4) = '\0';
1045
                }
1046
 
1047
            arg_cat_optionv(syntax,sizeof(syntax),shortopts,longopts,datatype,table[tabindex]->flag&ARG_HASOPTVALUE,", ");
1048
 
1049
            /* If syntax fits not into column, print glossary in new line... */
1050
            if ( strlen(syntax) > 25 )
1051
                {
1052
                fprintf( fp, "  %-25s %s\n", syntax, "" );
1053
                *syntax = '\0';
1054
                }
1055
 
1056
            fprintf( fp, "  %-25s ", syntax );
1057
            arg_print_formatted( fp, 28, 79, glossary );
1058
            }
1059
        } /* for each table entry */
1060
 
1061
    fputc( '\n', fp );
1062
    }
1063
 
1064
 
1065
/**
1066
 * Checks the argtable[] array for NULL entries and returns 1
1067
 * if any are found, zero otherwise.
1068
 */
1069
int arg_nullcheck(void **argtable)
1070
    {
1071
    struct arg_hdr **table = (struct arg_hdr **)argtable;
1072
    int tabindex;
1073
    /*printf("arg_nullcheck(%p)\n",argtable);*/
1074
 
1075
    if (!table)
1076
        return 1;
1077
 
1078
    tabindex=0;
1079
    do
1080
        {
1081
        /*printf("argtable[%d]=%p\n",tabindex,argtable[tabindex]);*/
1082
        if (!table[tabindex])
1083
            return 1;
1084
        } while(!(table[tabindex++]->flag&ARG_TERMINATOR));
1085
 
1086
    return 0;
1087
    }
1088
 
1089
 
1090
/*
1091
 * arg_free() is deprecated in favour of arg_freetable() due to a flaw in its design.
1092
 * The flaw results in memory leak in the (very rare) case that an intermediate
1093
 * entry in the argtable array failed its memory allocation while others following
1094
 * that entry were still allocated ok. Those subsequent allocations will not be
1095
 * deallocated by arg_free().
1096
 * Despite the unlikeliness of the problem occurring, and the even unlikelier event
1097
 * that it has any deliterious effect, it is fixed regardless by replacing arg_free()
1098
 * with the newer arg_freetable() function.
1099
 * We still keep arg_free() for backwards compatibility.
1100
 */
1101
void arg_free(void **argtable)
1102
    {
1103
    struct arg_hdr **table=(struct arg_hdr**)argtable;
1104
    int tabindex=0;
1105
    int flag;
1106
    /*printf("arg_free(%p)\n",argtable);*/
1107
    do
1108
        {
1109
        /*
1110
        if we encounter a NULL entry then somewhat incorrectly we presume
1111
        we have come to the end of the array. It isnt strictly true because
1112
        an intermediate entry could be NULL with other non-NULL entries to follow.
1113
        The subsequent argtable entries would then not be freed as they should.
1114
        */
1115
        if (table[tabindex]==NULL)
1116
            break;
1117
 
1118
        flag = table[tabindex]->flag;
1119
        free(table[tabindex]);
1120
        table[tabindex++]=NULL;
1121
 
1122
        } while(!(flag&ARG_TERMINATOR));
1123
    }
1124
 
1125
/* frees each non-NULL element of argtable[], where n is the size of the number of entries in the array */
1126
void arg_freetable(void **argtable, size_t n)
1127
    {
1128
    struct arg_hdr **table=(struct arg_hdr**)argtable;
1129
    int tabindex=0;
1130
    /*printf("arg_freetable(%p)\n",argtable);*/
1131
    for (tabindex=0; tabindex<n; tabindex++)
1132
        {
1133
        if (table[tabindex]==NULL)
1134
            continue;
1135
 
1136
        free(table[tabindex]);
1137
        table[tabindex]=NULL;
1138
        };
1139
    }
1140
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.