Added -Wall to CFLAGS
[mx3r.git] / cmdline.c
blob7c6bc9dc3510ff60e3284d930588d92f65e5bc36
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: <base-filename> <local-filename> <remote-filename>
26 Try a full (base->local to remote) merge */
27 /* do_blrmergeP = */ 0,
28 /* do_blrmerge = */ (char**)0,
29 /* do_blrmergeC = */ 0,
30 /***** --hashcmp: <line1> <line2> ... <lineN>
31 Do a hash compare between 4 or more lines. */
32 /* do_hashcmpP = */ 0,
33 /* do_hashcmp = */ (char**)0,
34 /* do_hashcmpC = */ 0,
35 /***** --test-plugin: try to load the split-lines plugin */
36 /* test_pluginP = */ 0,
37 /***** --help: show usage information */
38 /* show_helpP = */ 0,
39 /***** uninterpreted rest of command line */
40 /* argc = */ 0,
41 /* argv = */ (char**)0,
42 /***** the original command line concatenated */
43 /* tool = */ NULL
46 /*@=null*/
48 /***** let LCLint run more smoothly */
49 /*@-predboolothers*/
50 /*@-boolops*/
53 /******************************************************************/
54 /*****
55 This is a bit tricky. We want to make a difference between overflow
56 and underflow and we want to allow v==Inf or v==-Inf but not
57 v>FLT_MAX.
59 We don't use fabs to avoid linkage with -lm.
60 *****/
61 static void
62 checkFloatConversion(double v, char *option, char *arg)
64 char *err = NULL;
66 if( (errno==ERANGE && v!=0.0) /* even double overflowed */
67 || (v<HUGE_VAL && v>-HUGE_VAL && (v<0.0?-v:v)>(double)FLT_MAX) ) {
68 err = "large";
69 } else if( (errno==ERANGE && v==0.0)
70 || (v!=0.0 && (v<0.0?-v:v)<(double)FLT_MIN) ) {
71 err = "small";
73 if( err ) {
74 fprintf(stderr,
75 "%s: parameter `%s' of option `%s' to %s to represent\n",
76 Program, arg, option, err);
77 exit(EXIT_FAILURE);
81 int
82 getIntOpt(int argc, char **argv, int i, int *value, int force)
84 char *end;
85 long v;
87 if( ++i>=argc ) goto nothingFound;
89 errno = 0;
90 v = strtol(argv[i], &end, 0);
92 /***** check for conversion error */
93 if( end==argv[i] ) goto nothingFound;
95 /***** check for surplus non-whitespace */
96 while( isspace((int) *end) ) end+=1;
97 if( *end ) goto nothingFound;
99 /***** check if it fits into an int */
100 if( errno==ERANGE || v>(long)INT_MAX || v<(long)INT_MIN ) {
101 fprintf(stderr,
102 "%s: parameter `%s' of option `%s' to large to represent\n",
103 Program, argv[i], argv[i-1]);
104 exit(EXIT_FAILURE);
106 *value = (int)v;
108 return i;
110 nothingFound:
111 if( !force ) return i-1;
113 fprintf(stderr,
114 "%s: missing or malformed integer value after option `%s'\n",
115 Program, argv[i-1]);
116 exit(EXIT_FAILURE);
118 /**********************************************************************/
121 getIntOpts(int argc, char **argv, int i,
122 int **values,
123 int cmin, int cmax)
124 /*****
125 We want to find at least cmin values and at most cmax values.
126 cmax==-1 then means infinitely many are allowed.
127 *****/
129 int alloced, used;
130 char *end;
131 long v;
132 if( i+cmin >= argc ) {
133 fprintf(stderr,
134 "%s: option `%s' wants at least %d parameters\n",
135 Program, argv[i], cmin);
136 exit(EXIT_FAILURE);
139 /*****
140 alloc a bit more than cmin values. It does not hurt to have room
141 for a bit more values than cmax.
142 *****/
143 alloced = cmin + 4;
144 *values = (int*)calloc((size_t)alloced, sizeof(int));
145 if( ! *values ) {
146 outMem:
147 fprintf(stderr,
148 "%s: out of memory while parsing option `%s'\n",
149 Program, argv[i]);
150 exit(EXIT_FAILURE);
153 for(used=0; (cmax==-1 || used<cmax) && used+i+1<argc; used++) {
154 if( used==alloced ) {
155 alloced += 8;
156 *values = (int *) realloc(*values, alloced*sizeof(int));
157 if( !*values ) goto outMem;
160 errno = 0;
161 v = strtol(argv[used+i+1], &end, 0);
163 /***** check for conversion error */
164 if( end==argv[used+i+1] ) break;
166 /***** check for surplus non-whitespace */
167 while( isspace((int) *end) ) end+=1;
168 if( *end ) break;
170 /***** check for overflow */
171 if( errno==ERANGE || v>(long)INT_MAX || v<(long)INT_MIN ) {
172 fprintf(stderr,
173 "%s: parameter `%s' of option `%s' to large to represent\n",
174 Program, argv[i+used+1], argv[i]);
175 exit(EXIT_FAILURE);
178 (*values)[used] = (int)v;
182 if( used<cmin ) {
183 fprintf(stderr,
184 "%s: parameter `%s' of `%s' should be an "
185 "integer value\n",
186 Program, argv[i+used+1], argv[i]);
187 exit(EXIT_FAILURE);
190 return i+used;
192 /**********************************************************************/
195 getLongOpt(int argc, char **argv, int i, long *value, int force)
197 char *end;
199 if( ++i>=argc ) goto nothingFound;
201 errno = 0;
202 *value = strtol(argv[i], &end, 0);
204 /***** check for conversion error */
205 if( end==argv[i] ) goto nothingFound;
207 /***** check for surplus non-whitespace */
208 while( isspace((int) *end) ) end+=1;
209 if( *end ) goto nothingFound;
211 /***** check for overflow */
212 if( errno==ERANGE ) {
213 fprintf(stderr,
214 "%s: parameter `%s' of option `%s' to large to represent\n",
215 Program, argv[i], argv[i-1]);
216 exit(EXIT_FAILURE);
218 return i;
220 nothingFound:
221 /***** !force means: this parameter may be missing.*/
222 if( !force ) return i-1;
224 fprintf(stderr,
225 "%s: missing or malformed value after option `%s'\n",
226 Program, argv[i-1]);
227 exit(EXIT_FAILURE);
229 /**********************************************************************/
232 getLongOpts(int argc, char **argv, int i,
233 long **values,
234 int cmin, int cmax)
235 /*****
236 We want to find at least cmin values and at most cmax values.
237 cmax==-1 then means infinitely many are allowed.
238 *****/
240 int alloced, used;
241 char *end;
243 if( i+cmin >= argc ) {
244 fprintf(stderr,
245 "%s: option `%s' wants at least %d parameters\n",
246 Program, argv[i], cmin);
247 exit(EXIT_FAILURE);
250 /*****
251 alloc a bit more than cmin values. It does not hurt to have room
252 for a bit more values than cmax.
253 *****/
254 alloced = cmin + 4;
255 *values = (long int *)calloc((size_t)alloced, sizeof(long));
256 if( ! *values ) {
257 outMem:
258 fprintf(stderr,
259 "%s: out of memory while parsing option `%s'\n",
260 Program, argv[i]);
261 exit(EXIT_FAILURE);
264 for(used=0; (cmax==-1 || used<cmax) && used+i+1<argc; used++) {
265 if( used==alloced ) {
266 alloced += 8;
267 *values = (long int*) realloc(*values, alloced*sizeof(long));
268 if( !*values ) goto outMem;
271 errno = 0;
272 (*values)[used] = strtol(argv[used+i+1], &end, 0);
274 /***** check for conversion error */
275 if( end==argv[used+i+1] ) break;
277 /***** check for surplus non-whitespace */
278 while( isspace((int) *end) ) end+=1;
279 if( *end ) break;
281 /***** check for overflow */
282 if( errno==ERANGE ) {
283 fprintf(stderr,
284 "%s: parameter `%s' of option `%s' to large to represent\n",
285 Program, argv[i+used+1], argv[i]);
286 exit(EXIT_FAILURE);
291 if( used<cmin ) {
292 fprintf(stderr,
293 "%s: parameter `%s' of `%s' should be an "
294 "integer value\n",
295 Program, argv[i+used+1], argv[i]);
296 exit(EXIT_FAILURE);
299 return i+used;
301 /**********************************************************************/
304 getFloatOpt(int argc, char **argv, int i, float *value, int force)
306 char *end;
307 double v;
309 if( ++i>=argc ) goto nothingFound;
311 errno = 0;
312 v = strtod(argv[i], &end);
314 /***** check for conversion error */
315 if( end==argv[i] ) goto nothingFound;
317 /***** check for surplus non-whitespace */
318 while( isspace((int) *end) ) end+=1;
319 if( *end ) goto nothingFound;
321 /***** check for overflow */
322 checkFloatConversion(v, argv[i-1], argv[i]);
324 *value = (float)v;
326 return i;
328 nothingFound:
329 if( !force ) return i-1;
331 fprintf(stderr,
332 "%s: missing or malformed float value after option `%s'\n",
333 Program, argv[i-1]);
334 exit(EXIT_FAILURE);
337 /**********************************************************************/
340 getFloatOpts(int argc, char **argv, int i,
341 float **values,
342 int cmin, int cmax)
343 /*****
344 We want to find at least cmin values and at most cmax values.
345 cmax==-1 then means infinitely many are allowed.
346 *****/
348 int alloced, used;
349 char *end;
350 double v;
352 if( i+cmin >= argc ) {
353 fprintf(stderr,
354 "%s: option `%s' wants at least %d parameters\n",
355 Program, argv[i], cmin);
356 exit(EXIT_FAILURE);
359 /*****
360 alloc a bit more than cmin values.
361 *****/
362 alloced = cmin + 4;
363 *values = (float*)calloc((size_t)alloced, sizeof(float));
364 if( ! *values ) {
365 outMem:
366 fprintf(stderr,
367 "%s: out of memory while parsing option `%s'\n",
368 Program, argv[i]);
369 exit(EXIT_FAILURE);
372 for(used=0; (cmax==-1 || used<cmax) && used+i+1<argc; used++) {
373 if( used==alloced ) {
374 alloced += 8;
375 *values = (float *) realloc(*values, alloced*sizeof(float));
376 if( !*values ) goto outMem;
379 errno = 0;
380 v = strtod(argv[used+i+1], &end);
382 /***** check for conversion error */
383 if( end==argv[used+i+1] ) break;
385 /***** check for surplus non-whitespace */
386 while( isspace((int) *end) ) end+=1;
387 if( *end ) break;
389 /***** check for overflow */
390 checkFloatConversion(v, argv[i], argv[i+used+1]);
392 (*values)[used] = (float)v;
395 if( used<cmin ) {
396 fprintf(stderr,
397 "%s: parameter `%s' of `%s' should be a "
398 "floating-point value\n",
399 Program, argv[i+used+1], argv[i]);
400 exit(EXIT_FAILURE);
403 return i+used;
405 /**********************************************************************/
408 getDoubleOpt(int argc, char **argv, int i, double *value, int force)
410 char *end;
412 if( ++i>=argc ) goto nothingFound;
414 errno = 0;
415 *value = strtod(argv[i], &end);
417 /***** check for conversion error */
418 if( end==argv[i] ) goto nothingFound;
420 /***** check for surplus non-whitespace */
421 while( isspace((int) *end) ) end+=1;
422 if( *end ) goto nothingFound;
424 /***** check for overflow */
425 if( errno==ERANGE ) {
426 fprintf(stderr,
427 "%s: parameter `%s' of option `%s' to %s to represent\n",
428 Program, argv[i], argv[i-1],
429 (*value==0.0 ? "small" : "large"));
430 exit(EXIT_FAILURE);
433 return i;
435 nothingFound:
436 if( !force ) return i-1;
438 fprintf(stderr,
439 "%s: missing or malformed value after option `%s'\n",
440 Program, argv[i-1]);
441 exit(EXIT_FAILURE);
444 /**********************************************************************/
447 getDoubleOpts(int argc, char **argv, int i,
448 double **values,
449 int cmin, int cmax)
450 /*****
451 We want to find at least cmin values and at most cmax values.
452 cmax==-1 then means infinitely many are allowed.
453 *****/
455 int alloced, used;
456 char *end;
458 if( i+cmin >= argc ) {
459 fprintf(stderr,
460 "%s: option `%s' wants at least %d parameters\n",
461 Program, argv[i], cmin);
462 exit(EXIT_FAILURE);
465 /*****
466 alloc a bit more than cmin values.
467 *****/
468 alloced = cmin + 4;
469 *values = (double*)calloc((size_t)alloced, sizeof(double));
470 if( ! *values ) {
471 outMem:
472 fprintf(stderr,
473 "%s: out of memory while parsing option `%s'\n",
474 Program, argv[i]);
475 exit(EXIT_FAILURE);
478 for(used=0; (cmax==-1 || used<cmax) && used+i+1<argc; used++) {
479 if( used==alloced ) {
480 alloced += 8;
481 *values = (double *) realloc(*values, alloced*sizeof(double));
482 if( !*values ) goto outMem;
485 errno = 0;
486 (*values)[used] = strtod(argv[used+i+1], &end);
488 /***** check for conversion error */
489 if( end==argv[used+i+1] ) break;
491 /***** check for surplus non-whitespace */
492 while( isspace((int) *end) ) end+=1;
493 if( *end ) break;
495 /***** check for overflow */
496 if( errno==ERANGE ) {
497 fprintf(stderr,
498 "%s: parameter `%s' of option `%s' to %s to represent\n",
499 Program, argv[i+used+1], argv[i],
500 ((*values)[used]==0.0 ? "small" : "large"));
501 exit(EXIT_FAILURE);
506 if( used<cmin ) {
507 fprintf(stderr,
508 "%s: parameter `%s' of `%s' should be a "
509 "double value\n",
510 Program, argv[i+used+1], argv[i]);
511 exit(EXIT_FAILURE);
514 return i+used;
516 /**********************************************************************/
519 force will be set if we need at least one argument for the option.
520 *****/
522 getStringOpt(int argc, char **argv, int i, char **value, int force)
524 i += 1;
525 if( i>=argc ) {
526 if( force ) {
527 fprintf(stderr, "%s: missing string after option `%s'\n",
528 Program, argv[i-1]);
529 exit(EXIT_FAILURE);
531 return i-1;
534 if( !force && argv[i][0] == '-' ) return i-1;
535 *value = argv[i];
536 return i;
538 /**********************************************************************/
541 getStringOpts(int argc, char **argv, int i,
542 char* **values,
543 int cmin, int cmax)
544 /*****
545 We want to find at least cmin values and at most cmax values.
546 cmax==-1 then means infinitely many are allowed.
547 *****/
549 int alloced, used;
551 if( i+cmin >= argc ) {
552 fprintf(stderr,
553 "%s: option `%s' wants at least %d parameters\n",
554 Program, argv[i], cmin);
555 exit(EXIT_FAILURE);
558 alloced = cmin + 4;
560 *values = (char**)calloc((size_t)alloced, sizeof(char*));
561 if( ! *values ) {
562 outMem:
563 fprintf(stderr,
564 "%s: out of memory during parsing of option `%s'\n",
565 Program, argv[i]);
566 exit(EXIT_FAILURE);
569 for(used=0; (cmax==-1 || used<cmax) && used+i+1<argc; used++) {
570 if( used==alloced ) {
571 alloced += 8;
572 *values = (char **)realloc(*values, alloced*sizeof(char*));
573 if( !*values ) goto outMem;
576 if( used>=cmin && argv[used+i+1][0]=='-' ) break;
577 (*values)[used] = argv[used+i+1];
580 if( used<cmin ) {
581 fprintf(stderr,
582 "%s: less than %d parameters for option `%s', only %d found\n",
583 Program, cmin, argv[i], used);
584 exit(EXIT_FAILURE);
587 return i+used;
589 /**********************************************************************/
591 void
592 checkIntLower(char *opt, int *values, int count, int max)
594 int i;
596 for(i=0; i<count; i++) {
597 if( values[i]<=max ) continue;
598 fprintf(stderr,
599 "%s: parameter %d of option `%s' greater than max=%d\n",
600 Program, i+1, opt, max);
601 exit(EXIT_FAILURE);
604 /**********************************************************************/
606 void
607 checkIntHigher(char *opt, int *values, int count, int min)
609 int i;
611 for(i=0; i<count; i++) {
612 if( values[i]>=min ) continue;
613 fprintf(stderr,
614 "%s: parameter %d of option `%s' smaller than min=%d\n",
615 Program, i+1, opt, min);
616 exit(EXIT_FAILURE);
619 /**********************************************************************/
621 void
622 checkLongLower(char *opt, long *values, int count, long max)
624 int i;
626 for(i=0; i<count; i++) {
627 if( values[i]<=max ) continue;
628 fprintf(stderr,
629 "%s: parameter %d of option `%s' greater than max=%ld\n",
630 Program, i+1, opt, max);
631 exit(EXIT_FAILURE);
634 /**********************************************************************/
636 void
637 checkLongHigher(char *opt, long *values, int count, long min)
639 int i;
641 for(i=0; i<count; i++) {
642 if( values[i]>=min ) continue;
643 fprintf(stderr,
644 "%s: parameter %d of option `%s' smaller than min=%ld\n",
645 Program, i+1, opt, min);
646 exit(EXIT_FAILURE);
649 /**********************************************************************/
651 void
652 checkFloatLower(char *opt, float *values, int count, float max)
654 int i;
656 for(i=0; i<count; i++) {
657 if( values[i]<=max ) continue;
658 fprintf(stderr,
659 "%s: parameter %d of option `%s' greater than max=%f\n",
660 Program, i+1, opt, max);
661 exit(EXIT_FAILURE);
664 /**********************************************************************/
666 void
667 checkFloatHigher(char *opt, float *values, int count, float min)
669 int i;
671 for(i=0; i<count; i++) {
672 if( values[i]>=min ) continue;
673 fprintf(stderr,
674 "%s: parameter %d of option `%s' smaller than min=%f\n",
675 Program, i+1, opt, min);
676 exit(EXIT_FAILURE);
679 /**********************************************************************/
681 void
682 checkDoubleLower(char *opt, double *values, int count, double max)
684 int i;
686 for(i=0; i<count; i++) {
687 if( values[i]<=max ) continue;
688 fprintf(stderr,
689 "%s: parameter %d of option `%s' greater than max=%f\n",
690 Program, i+1, opt, max);
691 exit(EXIT_FAILURE);
694 /**********************************************************************/
696 void
697 checkDoubleHigher(char *opt, double *values, int count, double min)
699 int i;
701 for(i=0; i<count; i++) {
702 if( values[i]>=min ) continue;
703 fprintf(stderr,
704 "%s: parameter %d of option `%s' smaller than min=%f\n",
705 Program, i+1, opt, min);
706 exit(EXIT_FAILURE);
709 /**********************************************************************/
711 static char *
712 catArgv(int argc, char **argv)
714 int i;
715 size_t l;
716 char *s, *t;
718 for(i=0, l=0; i<argc; i++) l += (1+strlen(argv[i]));
719 s = (char *)malloc(l);
720 if( !s ) {
721 fprintf(stderr, "%s: out of memory\n", Program);
722 exit(EXIT_FAILURE);
724 strcpy(s, argv[0]);
725 t = s;
726 for(i=1; i<argc; i++) {
727 t = t+strlen(t);
728 *t++ = ' ';
729 strcpy(t, argv[i]);
731 return s;
733 /**********************************************************************/
735 void
736 usage(void)
738 fprintf(stderr,"%s"," [--blr do_blrmerge] [--hashcmp do_hashcmp] [--test-plugin] [--help]\n");
739 fprintf(stderr,"%s"," merges files looking for similar patterns, and allows several plugins\n");
740 fprintf(stderr,"%s"," for understanding the syntax of several files \n");
741 fprintf(stderr,"%s"," --blr: <base-filename> <local-filename> <remote-filename>\n");
742 fprintf(stderr,"%s"," Try a full (base->local to remote) merge\n");
743 fprintf(stderr,"%s"," 3 char* values\n");
744 fprintf(stderr,"%s"," --hashcmp: <line1> <line2> ... <lineN>\n");
745 fprintf(stderr,"%s"," Do a hash compare between 4 or more lines.\n");
746 fprintf(stderr,"%s"," 4 or more char* values\n");
747 fprintf(stderr,"%s"," --test-plugin: try to load the split-lines plugin\n");
748 fprintf(stderr,"%s"," --help: show usage information\n");
749 fprintf(stderr,"%s"," version: 0.1.1\n");
750 fprintf(stderr,"%s"," ");
751 exit(EXIT_FAILURE);
753 /**********************************************************************/
754 Cmdline *
755 parseCmdline(int argc, char **argv)
757 int i;
759 Program = argv[0];
760 cmd.tool = catArgv(argc, argv);
761 for(i=1, cmd.argc=1; i<argc; i++) {
762 if( 0==strcmp("--blr", argv[i]) ) {
763 int keep = i;
764 cmd.do_blrmergeP = 1;
765 i = getStringOpts(argc, argv, i, &cmd.do_blrmerge, 3, 3);
766 cmd.do_blrmergeC = i-keep;
767 continue;
770 if( 0==strcmp("--hashcmp", argv[i]) ) {
771 int keep = i;
772 cmd.do_hashcmpP = 1;
773 i = getStringOpts(argc, argv, i, &cmd.do_hashcmp, 4, -1);
774 cmd.do_hashcmpC = i-keep;
775 continue;
778 if( 0==strcmp("--test-plugin", argv[i]) ) {
779 cmd.test_pluginP = 1;
780 continue;
783 if( 0==strcmp("--help", argv[i]) ) {
784 cmd.show_helpP = 1;
785 continue;
788 if( argv[i][0]=='-' ) {
789 fprintf(stderr, "\n%s: unknown option `%s'\n\n",
790 Program, argv[i]);
791 usage();
793 argv[cmd.argc++] = argv[i];
794 }/* for i */
797 /*@-mustfree*/
798 cmd.argv = argv+1;
799 /*@=mustfree*/
800 cmd.argc -= 1;
802 if( cmd.argc>0 ) {
803 fprintf(stderr, "%s: There are %d arguments not associated with any option\n",
804 Program, cmd.argc);
805 exit(EXIT_FAILURE);
807 /*@-compmempass*/ return &cmd;