Added "clig" for command line parsing, and man page.
[mx3r.git] / cmdline.c
blob2367dd6b1a375560b4f385010d0cae4f552a6a74
1 /*****
2 command line parser -- generated by clig
3 (http://wsd.iitb.fhg.de/~kir/clighome/)
5 The command line parser `clig':
6 (C) 1995-2004 Harald Kirsch (clig@geggus.net)
7 *****/
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include <errno.h>
14 #include <limits.h>
15 #include <float.h>
16 #include <math.h>
18 #include "cmdline.h"
20 char *Program;
22 /*@-null*/
24 static Cmdline cmd = {
25 /***** -blr: Try a full (base->local to remote) merge */
26 /* mergeP = */ 0,
27 /* merge = */ (char**)0,
28 /* mergeC = */ 0,
29 /***** -help: show usage information */
30 /* show_helpP = */ 0,
31 /***** -version: show program version */
32 /* show_versionP = */ 0,
33 /***** uninterpreted rest of command line */
34 /* argc = */ 0,
35 /* argv = */ (char**)0,
36 /***** the original command line concatenated */
37 /* tool = */ NULL
40 /*@=null*/
42 /***** let LCLint run more smoothly */
43 /*@-predboolothers*/
44 /*@-boolops*/
47 /******************************************************************/
48 /*****
49 This is a bit tricky. We want to make a difference between overflow
50 and underflow and we want to allow v==Inf or v==-Inf but not
51 v>FLT_MAX.
53 We don't use fabs to avoid linkage with -lm.
54 *****/
55 static void
56 checkFloatConversion(double v, char *option, char *arg)
58 char *err = NULL;
60 if( (errno==ERANGE && v!=0.0) /* even double overflowed */
61 || (v<HUGE_VAL && v>-HUGE_VAL && (v<0.0?-v:v)>(double)FLT_MAX) ) {
62 err = "large";
63 } else if( (errno==ERANGE && v==0.0)
64 || (v!=0.0 && (v<0.0?-v:v)<(double)FLT_MIN) ) {
65 err = "small";
67 if( err ) {
68 fprintf(stderr,
69 "%s: parameter `%s' of option `%s' to %s to represent\n",
70 Program, arg, option, err);
71 exit(EXIT_FAILURE);
75 int
76 getIntOpt(int argc, char **argv, int i, int *value, int force)
78 char *end;
79 long v;
81 if( ++i>=argc ) goto nothingFound;
83 errno = 0;
84 v = strtol(argv[i], &end, 0);
86 /***** check for conversion error */
87 if( end==argv[i] ) goto nothingFound;
89 /***** check for surplus non-whitespace */
90 while( isspace((int) *end) ) end+=1;
91 if( *end ) goto nothingFound;
93 /***** check if it fits into an int */
94 if( errno==ERANGE || v>(long)INT_MAX || v<(long)INT_MIN ) {
95 fprintf(stderr,
96 "%s: parameter `%s' of option `%s' to large to represent\n",
97 Program, argv[i], argv[i-1]);
98 exit(EXIT_FAILURE);
100 *value = (int)v;
102 return i;
104 nothingFound:
105 if( !force ) return i-1;
107 fprintf(stderr,
108 "%s: missing or malformed integer value after option `%s'\n",
109 Program, argv[i-1]);
110 exit(EXIT_FAILURE);
112 /**********************************************************************/
115 getIntOpts(int argc, char **argv, int i,
116 int **values,
117 int cmin, int cmax)
118 /*****
119 We want to find at least cmin values and at most cmax values.
120 cmax==-1 then means infinitely many are allowed.
121 *****/
123 int alloced, used;
124 char *end;
125 long v;
126 if( i+cmin >= argc ) {
127 fprintf(stderr,
128 "%s: option `%s' wants at least %d parameters\n",
129 Program, argv[i], cmin);
130 exit(EXIT_FAILURE);
133 /*****
134 alloc a bit more than cmin values. It does not hurt to have room
135 for a bit more values than cmax.
136 *****/
137 alloced = cmin + 4;
138 *values = (int*)calloc((size_t)alloced, sizeof(int));
139 if( ! *values ) {
140 outMem:
141 fprintf(stderr,
142 "%s: out of memory while parsing option `%s'\n",
143 Program, argv[i]);
144 exit(EXIT_FAILURE);
147 for(used=0; (cmax==-1 || used<cmax) && used+i+1<argc; used++) {
148 if( used==alloced ) {
149 alloced += 8;
150 *values = (int *) realloc(*values, alloced*sizeof(int));
151 if( !*values ) goto outMem;
154 errno = 0;
155 v = strtol(argv[used+i+1], &end, 0);
157 /***** check for conversion error */
158 if( end==argv[used+i+1] ) break;
160 /***** check for surplus non-whitespace */
161 while( isspace((int) *end) ) end+=1;
162 if( *end ) break;
164 /***** check for overflow */
165 if( errno==ERANGE || v>(long)INT_MAX || v<(long)INT_MIN ) {
166 fprintf(stderr,
167 "%s: parameter `%s' of option `%s' to large to represent\n",
168 Program, argv[i+used+1], argv[i]);
169 exit(EXIT_FAILURE);
172 (*values)[used] = (int)v;
176 if( used<cmin ) {
177 fprintf(stderr,
178 "%s: parameter `%s' of `%s' should be an "
179 "integer value\n",
180 Program, argv[i+used+1], argv[i]);
181 exit(EXIT_FAILURE);
184 return i+used;
186 /**********************************************************************/
189 getLongOpt(int argc, char **argv, int i, long *value, int force)
191 char *end;
193 if( ++i>=argc ) goto nothingFound;
195 errno = 0;
196 *value = strtol(argv[i], &end, 0);
198 /***** check for conversion error */
199 if( end==argv[i] ) goto nothingFound;
201 /***** check for surplus non-whitespace */
202 while( isspace((int) *end) ) end+=1;
203 if( *end ) goto nothingFound;
205 /***** check for overflow */
206 if( errno==ERANGE ) {
207 fprintf(stderr,
208 "%s: parameter `%s' of option `%s' to large to represent\n",
209 Program, argv[i], argv[i-1]);
210 exit(EXIT_FAILURE);
212 return i;
214 nothingFound:
215 /***** !force means: this parameter may be missing.*/
216 if( !force ) return i-1;
218 fprintf(stderr,
219 "%s: missing or malformed value after option `%s'\n",
220 Program, argv[i-1]);
221 exit(EXIT_FAILURE);
223 /**********************************************************************/
226 getLongOpts(int argc, char **argv, int i,
227 long **values,
228 int cmin, int cmax)
229 /*****
230 We want to find at least cmin values and at most cmax values.
231 cmax==-1 then means infinitely many are allowed.
232 *****/
234 int alloced, used;
235 char *end;
237 if( i+cmin >= argc ) {
238 fprintf(stderr,
239 "%s: option `%s' wants at least %d parameters\n",
240 Program, argv[i], cmin);
241 exit(EXIT_FAILURE);
244 /*****
245 alloc a bit more than cmin values. It does not hurt to have room
246 for a bit more values than cmax.
247 *****/
248 alloced = cmin + 4;
249 *values = (long int *)calloc((size_t)alloced, sizeof(long));
250 if( ! *values ) {
251 outMem:
252 fprintf(stderr,
253 "%s: out of memory while parsing option `%s'\n",
254 Program, argv[i]);
255 exit(EXIT_FAILURE);
258 for(used=0; (cmax==-1 || used<cmax) && used+i+1<argc; used++) {
259 if( used==alloced ) {
260 alloced += 8;
261 *values = (long int*) realloc(*values, alloced*sizeof(long));
262 if( !*values ) goto outMem;
265 errno = 0;
266 (*values)[used] = strtol(argv[used+i+1], &end, 0);
268 /***** check for conversion error */
269 if( end==argv[used+i+1] ) break;
271 /***** check for surplus non-whitespace */
272 while( isspace((int) *end) ) end+=1;
273 if( *end ) break;
275 /***** check for overflow */
276 if( errno==ERANGE ) {
277 fprintf(stderr,
278 "%s: parameter `%s' of option `%s' to large to represent\n",
279 Program, argv[i+used+1], argv[i]);
280 exit(EXIT_FAILURE);
285 if( used<cmin ) {
286 fprintf(stderr,
287 "%s: parameter `%s' of `%s' should be an "
288 "integer value\n",
289 Program, argv[i+used+1], argv[i]);
290 exit(EXIT_FAILURE);
293 return i+used;
295 /**********************************************************************/
298 getFloatOpt(int argc, char **argv, int i, float *value, int force)
300 char *end;
301 double v;
303 if( ++i>=argc ) goto nothingFound;
305 errno = 0;
306 v = strtod(argv[i], &end);
308 /***** check for conversion error */
309 if( end==argv[i] ) goto nothingFound;
311 /***** check for surplus non-whitespace */
312 while( isspace((int) *end) ) end+=1;
313 if( *end ) goto nothingFound;
315 /***** check for overflow */
316 checkFloatConversion(v, argv[i-1], argv[i]);
318 *value = (float)v;
320 return i;
322 nothingFound:
323 if( !force ) return i-1;
325 fprintf(stderr,
326 "%s: missing or malformed float value after option `%s'\n",
327 Program, argv[i-1]);
328 exit(EXIT_FAILURE);
331 /**********************************************************************/
334 getFloatOpts(int argc, char **argv, int i,
335 float **values,
336 int cmin, int cmax)
337 /*****
338 We want to find at least cmin values and at most cmax values.
339 cmax==-1 then means infinitely many are allowed.
340 *****/
342 int alloced, used;
343 char *end;
344 double v;
346 if( i+cmin >= argc ) {
347 fprintf(stderr,
348 "%s: option `%s' wants at least %d parameters\n",
349 Program, argv[i], cmin);
350 exit(EXIT_FAILURE);
353 /*****
354 alloc a bit more than cmin values.
355 *****/
356 alloced = cmin + 4;
357 *values = (float*)calloc((size_t)alloced, sizeof(float));
358 if( ! *values ) {
359 outMem:
360 fprintf(stderr,
361 "%s: out of memory while parsing option `%s'\n",
362 Program, argv[i]);
363 exit(EXIT_FAILURE);
366 for(used=0; (cmax==-1 || used<cmax) && used+i+1<argc; used++) {
367 if( used==alloced ) {
368 alloced += 8;
369 *values = (float *) realloc(*values, alloced*sizeof(float));
370 if( !*values ) goto outMem;
373 errno = 0;
374 v = strtod(argv[used+i+1], &end);
376 /***** check for conversion error */
377 if( end==argv[used+i+1] ) break;
379 /***** check for surplus non-whitespace */
380 while( isspace((int) *end) ) end+=1;
381 if( *end ) break;
383 /***** check for overflow */
384 checkFloatConversion(v, argv[i], argv[i+used+1]);
386 (*values)[used] = (float)v;
389 if( used<cmin ) {
390 fprintf(stderr,
391 "%s: parameter `%s' of `%s' should be a "
392 "floating-point value\n",
393 Program, argv[i+used+1], argv[i]);
394 exit(EXIT_FAILURE);
397 return i+used;
399 /**********************************************************************/
402 getDoubleOpt(int argc, char **argv, int i, double *value, int force)
404 char *end;
406 if( ++i>=argc ) goto nothingFound;
408 errno = 0;
409 *value = strtod(argv[i], &end);
411 /***** check for conversion error */
412 if( end==argv[i] ) goto nothingFound;
414 /***** check for surplus non-whitespace */
415 while( isspace((int) *end) ) end+=1;
416 if( *end ) goto nothingFound;
418 /***** check for overflow */
419 if( errno==ERANGE ) {
420 fprintf(stderr,
421 "%s: parameter `%s' of option `%s' to %s to represent\n",
422 Program, argv[i], argv[i-1],
423 (*value==0.0 ? "small" : "large"));
424 exit(EXIT_FAILURE);
427 return i;
429 nothingFound:
430 if( !force ) return i-1;
432 fprintf(stderr,
433 "%s: missing or malformed value after option `%s'\n",
434 Program, argv[i-1]);
435 exit(EXIT_FAILURE);
438 /**********************************************************************/
441 getDoubleOpts(int argc, char **argv, int i,
442 double **values,
443 int cmin, int cmax)
444 /*****
445 We want to find at least cmin values and at most cmax values.
446 cmax==-1 then means infinitely many are allowed.
447 *****/
449 int alloced, used;
450 char *end;
452 if( i+cmin >= argc ) {
453 fprintf(stderr,
454 "%s: option `%s' wants at least %d parameters\n",
455 Program, argv[i], cmin);
456 exit(EXIT_FAILURE);
459 /*****
460 alloc a bit more than cmin values.
461 *****/
462 alloced = cmin + 4;
463 *values = (double*)calloc((size_t)alloced, sizeof(double));
464 if( ! *values ) {
465 outMem:
466 fprintf(stderr,
467 "%s: out of memory while parsing option `%s'\n",
468 Program, argv[i]);
469 exit(EXIT_FAILURE);
472 for(used=0; (cmax==-1 || used<cmax) && used+i+1<argc; used++) {
473 if( used==alloced ) {
474 alloced += 8;
475 *values = (double *) realloc(*values, alloced*sizeof(double));
476 if( !*values ) goto outMem;
479 errno = 0;
480 (*values)[used] = strtod(argv[used+i+1], &end);
482 /***** check for conversion error */
483 if( end==argv[used+i+1] ) break;
485 /***** check for surplus non-whitespace */
486 while( isspace((int) *end) ) end+=1;
487 if( *end ) break;
489 /***** check for overflow */
490 if( errno==ERANGE ) {
491 fprintf(stderr,
492 "%s: parameter `%s' of option `%s' to %s to represent\n",
493 Program, argv[i+used+1], argv[i],
494 ((*values)[used]==0.0 ? "small" : "large"));
495 exit(EXIT_FAILURE);
500 if( used<cmin ) {
501 fprintf(stderr,
502 "%s: parameter `%s' of `%s' should be a "
503 "double value\n",
504 Program, argv[i+used+1], argv[i]);
505 exit(EXIT_FAILURE);
508 return i+used;
510 /**********************************************************************/
513 force will be set if we need at least one argument for the option.
514 *****/
516 getStringOpt(int argc, char **argv, int i, char **value, int force)
518 i += 1;
519 if( i>=argc ) {
520 if( force ) {
521 fprintf(stderr, "%s: missing string after option `%s'\n",
522 Program, argv[i-1]);
523 exit(EXIT_FAILURE);
525 return i-1;
528 if( !force && argv[i][0] == '-' ) return i-1;
529 *value = argv[i];
530 return i;
532 /**********************************************************************/
535 getStringOpts(int argc, char **argv, int i,
536 char* **values,
537 int cmin, int cmax)
538 /*****
539 We want to find at least cmin values and at most cmax values.
540 cmax==-1 then means infinitely many are allowed.
541 *****/
543 int alloced, used;
545 if( i+cmin >= argc ) {
546 fprintf(stderr,
547 "%s: option `%s' wants at least %d parameters\n",
548 Program, argv[i], cmin);
549 exit(EXIT_FAILURE);
552 alloced = cmin + 4;
554 *values = (char**)calloc((size_t)alloced, sizeof(char*));
555 if( ! *values ) {
556 outMem:
557 fprintf(stderr,
558 "%s: out of memory during parsing of option `%s'\n",
559 Program, argv[i]);
560 exit(EXIT_FAILURE);
563 for(used=0; (cmax==-1 || used<cmax) && used+i+1<argc; used++) {
564 if( used==alloced ) {
565 alloced += 8;
566 *values = (char **)realloc(*values, alloced*sizeof(char*));
567 if( !*values ) goto outMem;
570 if( used>=cmin && argv[used+i+1][0]=='-' ) break;
571 (*values)[used] = argv[used+i+1];
574 if( used<cmin ) {
575 fprintf(stderr,
576 "%s: less than %d parameters for option `%s', only %d found\n",
577 Program, cmin, argv[i], used);
578 exit(EXIT_FAILURE);
581 return i+used;
583 /**********************************************************************/
585 void
586 checkIntLower(char *opt, int *values, int count, int max)
588 int i;
590 for(i=0; i<count; i++) {
591 if( values[i]<=max ) continue;
592 fprintf(stderr,
593 "%s: parameter %d of option `%s' greater than max=%d\n",
594 Program, i+1, opt, max);
595 exit(EXIT_FAILURE);
598 /**********************************************************************/
600 void
601 checkIntHigher(char *opt, int *values, int count, int min)
603 int i;
605 for(i=0; i<count; i++) {
606 if( values[i]>=min ) continue;
607 fprintf(stderr,
608 "%s: parameter %d of option `%s' smaller than min=%d\n",
609 Program, i+1, opt, min);
610 exit(EXIT_FAILURE);
613 /**********************************************************************/
615 void
616 checkLongLower(char *opt, long *values, int count, long max)
618 int i;
620 for(i=0; i<count; i++) {
621 if( values[i]<=max ) continue;
622 fprintf(stderr,
623 "%s: parameter %d of option `%s' greater than max=%ld\n",
624 Program, i+1, opt, max);
625 exit(EXIT_FAILURE);
628 /**********************************************************************/
630 void
631 checkLongHigher(char *opt, long *values, int count, long min)
633 int i;
635 for(i=0; i<count; i++) {
636 if( values[i]>=min ) continue;
637 fprintf(stderr,
638 "%s: parameter %d of option `%s' smaller than min=%ld\n",
639 Program, i+1, opt, min);
640 exit(EXIT_FAILURE);
643 /**********************************************************************/
645 void
646 checkFloatLower(char *opt, float *values, int count, float max)
648 int i;
650 for(i=0; i<count; i++) {
651 if( values[i]<=max ) continue;
652 fprintf(stderr,
653 "%s: parameter %d of option `%s' greater than max=%f\n",
654 Program, i+1, opt, max);
655 exit(EXIT_FAILURE);
658 /**********************************************************************/
660 void
661 checkFloatHigher(char *opt, float *values, int count, float min)
663 int i;
665 for(i=0; i<count; i++) {
666 if( values[i]>=min ) continue;
667 fprintf(stderr,
668 "%s: parameter %d of option `%s' smaller than min=%f\n",
669 Program, i+1, opt, min);
670 exit(EXIT_FAILURE);
673 /**********************************************************************/
675 void
676 checkDoubleLower(char *opt, double *values, int count, double max)
678 int i;
680 for(i=0; i<count; i++) {
681 if( values[i]<=max ) continue;
682 fprintf(stderr,
683 "%s: parameter %d of option `%s' greater than max=%f\n",
684 Program, i+1, opt, max);
685 exit(EXIT_FAILURE);
688 /**********************************************************************/
690 void
691 checkDoubleHigher(char *opt, double *values, int count, double min)
693 int i;
695 for(i=0; i<count; i++) {
696 if( values[i]>=min ) continue;
697 fprintf(stderr,
698 "%s: parameter %d of option `%s' smaller than min=%f\n",
699 Program, i+1, opt, min);
700 exit(EXIT_FAILURE);
703 /**********************************************************************/
705 static char *
706 catArgv(int argc, char **argv)
708 int i;
709 size_t l;
710 char *s, *t;
712 for(i=0, l=0; i<argc; i++) l += (1+strlen(argv[i]));
713 s = (char *)malloc(l);
714 if( !s ) {
715 fprintf(stderr, "%s: out of memory\n", Program);
716 exit(EXIT_FAILURE);
718 strcpy(s, argv[0]);
719 t = s;
720 for(i=1; i<argc; i++) {
721 t = t+strlen(t);
722 *t++ = ' ';
723 strcpy(t, argv[i]);
725 return s;
727 /**********************************************************************/
729 void
730 usage(void)
732 fprintf(stderr,"%s"," [-blr merge] [-help] [-version]\n");
733 fprintf(stderr,"%s"," merges files looking for similar patterns, and allows several plugins\n");
734 fprintf(stderr,"%s"," for understanding the syntax of several files \n");
735 fprintf(stderr,"%s"," -blr: Try a full (base->local to remote) merge\n");
736 fprintf(stderr,"%s"," 3 char* values\n");
737 fprintf(stderr,"%s"," -help: show usage information\n");
738 fprintf(stderr,"%s"," -version: show program version\n");
739 fprintf(stderr,"%s"," version: 0.1.0\n");
740 fprintf(stderr,"%s"," ");
741 exit(EXIT_FAILURE);
743 /**********************************************************************/
744 Cmdline *
745 parseCmdline(int argc, char **argv)
747 int i;
749 Program = argv[0];
750 cmd.tool = catArgv(argc, argv);
751 for(i=1, cmd.argc=1; i<argc; i++) {
752 if( 0==strcmp("-blr", argv[i]) ) {
753 int keep = i;
754 cmd.mergeP = 1;
755 i = getStringOpts(argc, argv, i, &cmd.merge, 3, 3);
756 cmd.mergeC = i-keep;
757 continue;
760 if( 0==strcmp("-help", argv[i]) ) {
761 cmd.show_helpP = 1;
762 continue;
765 if( 0==strcmp("-version", argv[i]) ) {
766 cmd.show_versionP = 1;
767 continue;
770 if( argv[i][0]=='-' ) {
771 fprintf(stderr, "\n%s: unknown option `%s'\n\n",
772 Program, argv[i]);
773 usage();
775 argv[cmd.argc++] = argv[i];
776 }/* for i */
779 /*@-mustfree*/
780 cmd.argv = argv+1;
781 /*@=mustfree*/
782 cmd.argc -= 1;
784 if( cmd.argc>0 ) {
785 fprintf(stderr, "%s: There are %d arguments not associated with any option\n",
786 Program, cmd.argc);
787 exit(EXIT_FAILURE);
789 /*@-compmempass*/ return &cmd;