]> andersk Git - splint.git/blame_incremental - src/flags.c
Added support for omitted if clauses in conditionals, patch provided by peteran.
[splint.git] / src / flags.c
... / ...
CommitLineData
1/*
2** Splint - annotation-assisted static program checker
3** Copyright (C) 1994-2003 University of Virginia,
4** Massachusetts Institute of Technology
5**
6** This program is free software; you can redistribute it and/or modify it
7** under the terms of the GNU General Public License as published by the
8** Free Software Foundation; either version 2 of the License, or (at your
9** option) any later version.
10**
11** This program is distributed in the hope that it will be useful, but
12** WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14** General Public License for more details.
15**
16** The GNU General Public License is available from http://www.gnu.org/ or
17** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18** MA 02111-1307, USA.
19**
20** For information on splint: info@splint.org
21** To report a bug: splint-bug@splint.org
22** For more information: http://www.splint.org
23*/
24/*
25** flags.c
26*/
27
28# include "splintMacros.nf"
29# include "basic.h"
30# include "osd.h"
31# include "rcfiles.h"
32# include "lslinit.h"
33# include "llmain.h"
34
35/*
36** from the CC man page:
37**
38** -Idir Search for #include files whose names do not begin with a
39** slash (/) in the following order: (1) in the directory of
40** the dir argument, (2) in the directories specified by -I
41** options, (3) in the standard directory (/usr/include).
42*/
43
44/* needed for string literals literals */
45
46typedef struct {
47 flagkind kind;
48 /*@null@*/ /*@observer@*/ char *name;
49 /*@null@*/ /*@observer@*/ char *describe;
50} flagcatinfo;
51
52static flagcatinfo categories[] =
53{
54 { FK_ABSTRACT, "abstract", "abstraction violations, representation access" } ,
55 { FK_ALIAS, "aliasing", "unexpected or dangerous aliasing" } ,
56 { FK_USE, "alluse", "all declarations are used" } ,
57 { FK_ANSI, "ansi", "violations of constraints imposed by ANSI/ISO standard" } ,
58 { FK_ARRAY, "arrays", "special checking involving arrays" } ,
59 { FK_BOOL, "booleans", "checking and naming of boolean types" } ,
60 { FK_COMMENTS, "comments", "warnings about (normal) comments" } ,
61 { FK_SYNCOMMENTS, "syncomments", "interpretation of annotation comments" } ,
62 { FK_COMPLETE, "complete", "completely defined, used, or specified system" } ,
63 { FK_CONTROL, "controlflow", "suspicious control structures" } ,
64 { FK_DEBUG, "debug", "flags for debugging splint" } ,
65 { FK_DECL, "declarations", "consistency of declarations" } ,
66 { FK_DEF, "definition", "undefined storage errors" } ,
67 { FK_DIRECT, "directories", "set directores" } ,
68 { FK_DISPLAY, "display", "control what is displayed" } ,
69 { FK_EFFECT, "effect", "statements with no effects" } ,
70 { FK_ERRORS, "errors", "control expected errors, summary reporting" } ,
71 { FK_EXPORT, "export", "control what may be exported" } ,
72 { FK_EXPOSURE, "exposure", "representation exposure" } ,
73 { FK_EXTENSIBLE, "extensible", "user-defined checks and annotations" },
74 { FK_FILES, "files", "control system files" } ,
75 { FK_FORMAT, "format", "control format of warning messages" } ,
76 { FK_GLOBALS, "globals", "use of global and file static variables" },
77 { FK_HEADERS, "headers", "control inclusion and generation of header files" },
78 { FK_HELP, "help", "on-line help" },
79 { FK_BOUNDS, "memorybounds", "out-of-bounds memory accesses" },
80 { FK_HINTS, "hints", "control display of warning hints" },
81 { FK_SYSTEMFUNCTIONS, "systemfunctions", "special properties of exit and main" },
82 { FK_IMPLICIT, "implicit", "control implicit annotations and interpretations" } ,
83 { FK_INIT, "initializations", "initialization files" } ,
84 { FK_ITER, "iterators", "checking iterator definitions and uses" } ,
85 { FK_LEAK, "leaks", "memory leaks" } ,
86 { FK_LIBS, "libraries", "loading and dumping of user and standard libraries" } ,
87 { FK_LIMITS, "limits", "violations of set limits" } ,
88 { FK_MACROS, "macros", "expansion, definition and use of macros" },
89 { FK_MEMORY, "memory", "memory management" } ,
90 { FK_MODIFIES, "modification", "modification errors" } ,
91 { FK_NAMES, "names", "naming conventions and limits" } ,
92 { FK_NULL, "null", "misuses of null pointers" } ,
93 { FK_NUMBERS, "numbers", "control type-checking of numeric types" } ,
94 { FK_OPS, "operations", "checking of primitive operations" } ,
95 { FK_PARAMS, "parameters", "function and macro parameters" } ,
96 { FK_SPEED, "performance", "speeding up checking" } ,
97 { FK_POINTER, "pointers", "pointers" } ,
98 { FK_PRED, "predicates", "condition test expressions" } ,
99 { FK_PREFIX, "prefixes", "set naming prefixes and control checking" } ,
100 { FK_PREPROC, "preproc", "defines and undefines for the preprocessor" } ,
101 { FK_PROTOS, "prototypes", "function prototypes" } ,
102 { FK_DEAD, "released", "using storage that has been deallocated" } ,
103 { FK_IGNORERET, "returnvals", "ignored return values" },
104 { FK_SECURITY, "security", "possible security vulnerability" },
105 { FK_SPEC, "specifications", "checks involving .lcl specifications" } ,
106 { FK_SUPPRESS, "suppress", "local and global suppression of messages" } ,
107 { FK_TYPEEQ, "typeequivalence", "control what types are equivalent" } ,
108 { FK_BEHAVIOR, "undefined", "code with undefined or implementation-defined behavior" } ,
109 { FK_UNRECOG, "unrecognized", "unrecognized identifiers" } ,
110 { FK_UNSPEC, "unconstrained", "checking in the presence of unconstrained functions" } ,
111 { FK_WARNUSE, "warnuse", "use of possibly problematic function" } ,
112 { FK_ITS4, "its4", "its4 compatibility flags (report warnings for uses of possibly insecure functions)" } ,
113 { FK_SYNTAX, NULL, NULL } ,
114 { FK_TYPE, NULL, NULL } ,
115 { FK_SECRET, NULL, NULL } ,
116 { FK_OBSOLETE, NULL, NULL } ,
117 { FK_NONE, NULL, NULL } /* must be last */
118} ;
119
120typedef enum {
121 ARG_NONE,
122 ARG_NUMBER, /* number */
123 ARG_CHAR, /* char */
124 ARG_STRING, /* string */
125 ARG_FILE, /* filename (also a string) */
126 ARG_DIRECTORY, /* directory (also a string) */
127 ARG_PATH, /* path */
128 ARG_SPECIAL /* ? */
129} argcode;
130
131# ifdef WIN32
132/* Make Microsoft VC++ happy */
133# pragma warning (disable:4715)
134# endif
135
136static /*@observer@*/ cstring argcode_unparse (argcode arg)
137{
138 switch (arg)
139 {
140 case ARG_STRING: return cstring_makeLiteralTemp ("string");
141 case ARG_FILE: return cstring_makeLiteralTemp ("filename");
142 case ARG_DIRECTORY: return cstring_makeLiteralTemp ("directory");
143 case ARG_PATH: return cstring_makeLiteralTemp ("path");
144 case ARG_NUMBER: return cstring_makeLiteralTemp ("number");
145 case ARG_CHAR: return cstring_makeLiteralTemp ("character");
146 case ARG_NONE:
147 BADBRANCH;
148 case ARG_SPECIAL:
149 BADBRANCH;
150 }
151}
152
153# ifdef WIN32
154# pragma warning (default : 4715)
155# endif
156
157typedef struct {
158 flagkind main;
159 flagkind sub;
160 bool isSpecial; /* setting this flag may set other flags (or values) */
161 bool isIdem; /* idempotent - always sets to TRUE */
162 bool isGlobal; /* cannot be set locally (using control comments) */
163 bool isModeFlag; /* set by modes */
164 argcode argtype;
165 /*@observer@*/ char *flag;
166 flagcode code;
167 /*@observer@*/ /*@null@*/ char *desc;
168 bn_mstring hint;
169 int nreported;
170 int nsuppressed;
171} fflag;
172
173typedef fflag flaglist[];
174
175# include "flags.def"
176
177/*@iter allFlags (yield observer fflag f); @*/
178# define allFlags(m_f) \
179 { /*@+enumint@*/ flagcode m_i; for (m_i = 0; m_i < NUMFLAGS; m_i++) { fflag m_f = flags[m_i]; /*@=enumint@*/
180# define end_allFlags }}
181
182static bn_mstring mode_names[] =
183{
184 "weak", "standard", "checks", "strict", NULL,
185};
186
187/*@iter allModes (yield bn_mstring modename)@*/
188# define allModes(m_m) \
189 { int m_ii = 0; while (mstring_isDefined (mode_names[m_ii])) \
190 { bn_mstring m_m = mode_names[m_ii]; m_ii++;
191
192# define end_allModes }}
193
194/*@+enumint@*/
195
196static cstring getFlagModeSettings (flagcode p_flag) /*@modifies internalState@*/ ;
197static cstring describeFlagCode (flagcode p_flag) /*@*/ ;
198static cstringSList sortedFlags (void) /*@*/ ;
199static /*@observer@*/ cstring categoryName (flagkind p_kind) /*@*/ ;
200
201static flagcode flags_identifyFlagAux (cstring p_s, bool p_quiet) /*@modifies g_warningstream@*/ ;
202
203# if 0
204static /*@unused@*/ cstring listModes (void) /*@*/ ;
205# endif
206
207bool flagcode_isSpecialFlag (flagcode f)
208{
209 return (flags[f].isSpecial);
210}
211
212bool flagcode_isGlobalFlag (flagcode f)
213{
214 return (flags[f].isGlobal);
215}
216
217bool flagcode_isIdemFlag (flagcode f)
218{
219 return (flags[f].isIdem);
220}
221
222bool flagcode_isModeFlag (flagcode f)
223{
224 return (flags[f].isModeFlag);
225}
226
227bool flagcode_isNameChecksFlag (flagcode f)
228{
229 return (flags[f].main == FK_NAMES);
230}
231
232bool flagcode_isHelpFlag (flagcode f)
233{
234 return f == FLG_HELP;
235}
236
237bool flagcode_isMessageControlFlag (flagcode f)
238{
239 /*
240 ** True if opt controls the display of messages.
241 ** These flags must be processed first.
242 */
243
244 return (f == FLG_SHOWSCAN
245 || f == FLG_WARNRC
246 || f == FLG_PARENFILEFORMAT
247 || f == FLG_MESSAGESTREAMSTDERR
248 || f == FLG_MESSAGESTREAMSTDOUT
249 || f == FLG_WARNINGSTREAMSTDERR
250 || f == FLG_WARNINGSTREAMSTDOUT
251 || f == FLG_ERRORSTREAMSTDERR
252 || f == FLG_ERRORSTREAMSTDOUT
253 || f == FLG_MESSAGESTREAM
254 || f == FLG_WARNINGSTREAM
255 || f == FLG_ERRORSTREAM
256 || f == FLG_STREAMOVERWRITE);
257}
258
259/*
260** Internal consistency check on the flags.
261*/
262
263void flags_initMod ()
264{
265 allFlagCodes (code)
266 {
267 /*@+enumint@*/
268 if (flags[code].code != code)
269 {
270 fprintf (stderr,
271 "*** ERROR: inconsistent flag %s / %d / %d",
272 flags[code].flag,
273 flags[code].code, code);
274
275 llbug (message ("*** ERROR: inconsistent flag %s / %d / %d",
276 cstring_fromChars (flags[code].flag),
277 flags[code].code, code));
278 }
279 /*@=enumint@*/
280 } end_allFlagCodes;
281}
282
283void
284summarizeErrors ()
285{
286 bool hadOne = FALSE;
287 int sumrep = 0;
288 int sumsup = 0;
289
290 char *buf = mstring_create (128);
291
292 allFlags (f)
293 {
294 if (f.nreported > 0 || f.nsuppressed > 0)
295 {
296 int nrep = f.nreported;
297 int nsup = f.nsuppressed;
298 cstring fs = cstring_fill (cstring_fromChars (f.flag), 23);
299
300 if (!hadOne)
301 {
302 llmsgplain (cstring_makeLiteral
303 ("\nError Type Reported Suppressed\n"
304 "=================== ======== ========="));
305 hadOne = TRUE;
306 }
307
308 (void) snprintf (buf, 128, "%s%7d %9d", cstring_toCharsSafe (fs), nrep, nsup);
309
310 sumrep += nrep;
311 sumsup += nsup;
312
313 cstring_free (fs);
314 llmsg (cstring_copy (cstring_fromChars (buf)));
315 }
316 } end_allFlags;
317
318 if (hadOne)
319 {
320 cstring ts = cstring_fill (cstring_makeLiteralTemp ("Total"), 23);
321
322 llmsglit (" ======== =========");
323
324 (void) snprintf (buf, 128, "%s%7d %9d", cstring_toCharsSafe (ts), sumrep, sumsup);
325 cstring_free (ts);
326 llmsgplain (cstring_copy (cstring_fromChars (buf)));
327 }
328
329 sfree (buf);
330}
331
332/*@+enumindex@*/
333
334void
335flagcode_recordError (flagcode f)
336{
337 if (f != INVALID_FLAG)
338 {
339 if (f == FLG_WARNFLAGS)
340 {
341 ; /* don't count these */
342 }
343 else
344 {
345 flags[f].nreported = flags[f].nreported + 1;
346 }
347 }
348 else
349 {
350 llcontbug (message ("flagcode_recordError: invalid flag: %d", (int) f));
351 }
352}
353
354void
355flagcode_recordSuppressed (flagcode f)
356{
357 llassertprint (f != INVALID_FLAG, ("flagcode: %s", flagcode_unparse (f)));
358
359 flags[f].nsuppressed = flags[f].nsuppressed + 1;
360}
361
362int
363flagcode_numReported (flagcode f)
364{
365 llassert (f != INVALID_FLAG);
366
367 return (flags[f].nreported);
368}
369
370/*@observer@*/ cstring
371flagcodeHint (flagcode f)
372{
373 llassert (f != INVALID_FLAG);
374
375 if (mstring_isDefined (flags[f].hint))
376 {
377 return (cstring_fromChars (flags[f].hint));
378 }
379 else
380 {
381 return (cstring_fromChars (flags[f].desc));
382 }
383}
384
385static int categorySize (flagkind kind) /*@*/
386{
387 int n = 0;
388
389
390 allFlags (f)
391 {
392 if (f.main == kind || f.sub == kind)
393 {
394 n++;
395 }
396 } end_allFlags;
397
398 return n;
399}
400
401flagkind identifyCategory (cstring s)
402{
403 int i;
404
405 for (i = 0; categories[i].kind != FK_NONE; i++)
406 {
407 if (mstring_isDefined (categories[i].name))
408 {
409 if (cstring_equalLit (s, categories[i].name))
410 {
411 return categories[i].kind;
412 }
413 }
414 }
415
416 return FK_NONE;
417}
418
419static /*@observer@*/ cstring categoryName (flagkind kind)
420{
421 int i;
422
423 for (i = 0; categories[i].kind != FK_NONE; i++)
424 {
425 if (categories[i].kind == kind)
426 {
427 return (cstring_fromChars (categories[i].name));
428 }
429 }
430
431 return (cstring_makeLiteralTemp ("<No Category>"));
432}
433
434static int categoryIndex (flagkind kind)
435{
436 int i;
437
438 for (i = 0; categories[i].kind != FK_NONE; i++)
439 {
440 if (categories[i].kind == kind)
441 {
442 return i;
443 }
444 }
445
446 return -1;
447}
448
449void printCategory (flagkind kind)
450{
451 int index = categoryIndex (kind);
452
453 llassert (index >= 0);
454 llmsg (message ("%s (%d flags)\n\3%s\n\n",
455 cstring_fromChars (categories[index].name),
456 categorySize (kind),
457 cstring_fromChars (categories[index].describe)));
458
459 allFlags (f)
460 {
461 if (f.main == kind || f.sub == kind)
462 {
463 llmsg (message (" %s\n\6%q", cstring_fromChars (f.flag),
464 describeFlagCode (f.code)));
465 }
466 } end_allFlags;
467}
468
469void
470listAllCategories (void)
471{
472 int i;
473
474 for (i = 0; categories[i].kind != FK_NONE; i++)
475 {
476 flagkind kind = categories[i].kind ;
477
478 if (categories[i].describe != NULL)
479 {
480 llmsg (message ("%s (%d flags)\n\3%s",
481 categoryName (kind),
482 categorySize (kind),
483 cstring_fromChars (categories[i].describe)));
484 }
485 }
486}
487
488void
489printAllFlags (bool desc, bool full)
490{
491 if (full)
492 {
493 cstringSList fl = sortedFlags ();
494
495 cstringSList_elements (fl, el)
496 {
497 cstring tmp;
498 tmp = cstring_copy(el);
499 llmsg (message ("%q\n\n", describeFlag (tmp)));
500 cstring_free(tmp);
501 } end_cstringSList_elements ;
502
503 cstringSList_free (fl);
504 }
505 else
506 {
507 allFlags (f)
508 {
509 if (f.code != INVALID_FLAG && f.main != FK_OBSOLETE)
510 {
511 if (mstring_isDefined (f.desc))
512 {
513 if (desc)
514 {
515 llmsg (message ("%s --- %s", cstring_fromChars (f.flag),
516 cstring_fromChars (f.desc)));
517 }
518 }
519 }
520 } end_allFlags;
521 }
522}
523
524void
525printFlagManual (bool html)
526{
527 /*
528 ** Prints all flags by category, in order they appear in flags.def
529 */
530
531 flagkind lastCategory = FK_NONE;
532
533 allFlags (f) {
534 cstring flagname;
535 cstring flagtype = cstring_undefined;
536
537 if (f.main != lastCategory)
538 {
539 if (html)
540 {
541 llmsg (message ("\n<h4>%s</h4>\n", categoryName (f.main)));
542 }
543 else
544 {
545 llmsg (message ("\n%s\n%s\n",
546 categoryName (f.main),
547 cstring_makeLiteralTemp ("===================================")));
548 }
549
550 lastCategory = f.main;
551 }
552
553 if (f.argtype == ARG_NONE || f.argtype == ARG_SPECIAL)
554 {
555 if (html)
556 {
557 flagname = message ("<tt>%s</tt>", cstring_fromChars (f.flag));
558 }
559 else
560 {
561 flagname = cstring_fromCharsNew (f.flag);
562 }
563 }
564 else
565 {
566 if (flagcode_hasString (f.code))
567 {
568 if (html)
569 {
570 flagname = message ("<tt>%s <em>&lt;%s&gt;</em></tt>",
571 cstring_fromChars (f.flag), argcode_unparse (f.argtype));
572 }
573 else
574 {
575 flagname = message ("%s <%s>", cstring_fromChars (f.flag), argcode_unparse (f.argtype));
576 }
577
578 if (cstring_isDefined (context_getString (f.code)))
579 {
580 if (html)
581 {
582 flagname = message ("%q <font color=\"blue\">[%s]</font>", flagname,
583 context_getString (f.code));
584 }
585 else
586 {
587 flagname = message ("%q [%s]", flagname,
588 context_getString (f.code));
589 }
590 }
591 }
592 else if (f.argtype == ARG_CHAR)
593 {
594 if (html)
595 {
596 flagname = message ("<tt>%s <em>&lt;%s&gt;</em></tt> <font color=\"blue\">[%c]</font>",
597 cstring_fromChars (f.flag), argcode_unparse (f.argtype),
598 (char) context_getValue (f.code));
599 }
600 else
601 {
602 flagname = message ("%s <%s> [%c]", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
603 (char) context_getValue (f.code));
604 }
605 }
606 else
607 {
608 llassert (f.argtype == ARG_NUMBER);
609
610 if (html)
611 {
612 flagname = message ("<tt>%s <em>&lt;%s&gt;</em> <font color=\"blue\">[%d]</font>",
613 cstring_fromChars (f.flag), argcode_unparse (f.argtype),
614 context_getValue (f.code));
615 }
616 else
617 {
618 flagname = message ("%s <%s> [%d]", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
619 context_getValue (f.code));
620 }
621 }
622 }
623
624 if (f.isIdem)
625 {
626 if (html)
627 {
628 flagtype = message("%q<font color=\"green\">-</font>", flagtype);
629 }
630 else
631 {
632 flagtype = message("%q<->", flagtype);
633 }
634 }
635
636 if (f.isGlobal)
637 {
638 if (html)
639 {
640 flagtype = message ("%q<font color=\"green\"><em>global</em></font>", flagtype);
641 }
642 else
643 {
644 flagtype = message ("%q<G>", flagtype);
645 }
646 }
647
648 if (f.isSpecial)
649 {
650 if (html)
651 {
652 flagtype = message ("%q<font color=\"orange\"><em>shortcut</em></font>", flagtype);
653 }
654 else
655 {
656 flagtype = message("%q<S>", flagtype);
657 }
658 }
659
660 if (f.isModeFlag)
661 {
662 if (html)
663 {
664 flagtype = message ("%q mode:<tt>%q</tt>>", flagtype, getFlagModeSettings (f.code));
665 }
666 else
667 {
668 flagtype = message ("%q<M:%q>", flagtype, getFlagModeSettings (f.code));
669 }
670 }
671 else /* its a plain flag */
672 {
673 if (html)
674 {
675 flagtype = message ("%q plain:<tt>%s</tt>", flagtype,
676 cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-"));
677 }
678 else
679 {
680 flagtype = message ("%q<P:%s>", flagtype,
681 cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-"));
682 }
683 }
684
685 llmsg (message ("%s: %s", flagname, flagtype));
686
687 if (html)
688 {
689 llgenindentmsgnoloc (cstring_makeLiteral ("<blockquote>"));
690 }
691
692 if (mstring_isDefined (f.hint))
693 {
694 llgenindentmsgnoloc (cstring_fromCharsNew (f.hint));
695 }
696 else
697 {
698 llgenindentmsgnoloc (message ("%q.", cstring_capitalize (cstring_fromChars (f.desc))));
699 }
700
701 if (html)
702 {
703 llgenindentmsgnoloc (cstring_makeLiteral ("</blockquote>"));
704 }
705 } end_allFlags ;
706}
707
708cstring
709describeFlagCode (flagcode flag)
710{
711 cstring ret = cstring_undefined;
712 fflag f;
713
714 if (flagcode_isInvalid (flag))
715 {
716 return (cstring_makeLiteral ("<invalid>"));
717 }
718
719 context_resetAllFlags ();
720
721 f = flags[flag];
722 ret = cstring_copy (cstring_fromChars (f.desc));
723
724 if (f.sub != FK_NONE)
725 {
726 ret = message ("%q\nCategories: %s, %s",
727 ret,
728 categoryName (f.main),
729 categoryName (f.sub));
730 }
731 else
732 {
733 if (f.main != FK_NONE)
734 {
735 cstring cname = categoryName (f.main);
736
737 if (cstring_isDefined (cname))
738 {
739 ret = message ("%q\nCategory: %s",
740 ret, cname);
741 }
742 }
743 }
744
745 if (f.isModeFlag)
746 {
747 ret = message ("%q\nMode Settings: %q",
748 ret, getFlagModeSettings (flag));
749 }
750 else
751 {
752 ret = message ("%q\nDefault Setting: %s",
753 ret,
754 cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
755 }
756
757 if (f.isGlobal)
758 {
759 ret = message("%q\nSet globally only", ret);
760 }
761 else
762 {
763 ret = message("%q\nSet locally", ret);
764 }
765
766 switch (f.argtype)
767 {
768 case ARG_NONE:
769 case ARG_SPECIAL:
770 break;
771 case ARG_NUMBER:
772 ret = message("%q\nNumeric Argument. Default: %d",
773 ret,
774 context_getValue (flag));
775 break;
776 case ARG_CHAR:
777 ret = message("%q\nCharacter Argument. Default: %h",
778 ret, (char) context_getValue (flag));
779 break;
780 case ARG_STRING:
781 case ARG_FILE:
782 case ARG_PATH:
783 case ARG_DIRECTORY:
784 {
785 if (cstring_isDefined (context_getString (flag)))
786 {
787 ret = message("%q\n%q argument. Default: %s",
788 ret,
789 cstring_capitalize (argcode_unparse (f.argtype)),
790 context_getString (flag));
791 }
792 else
793 {
794 ret = message("%q\n%s argument. No default.",
795 ret,
796 cstring_capitalize (argcode_unparse (f.argtype)));
797 }
798 break;
799 }
800 }
801
802 if (mstring_isDefined (f.hint))
803 {
804 ret = message("%q\n\3%s", ret, cstring_fromChars (f.hint));
805 }
806
807 return ret;
808}
809
810static cstring getFlagModeSettings (flagcode flag)
811{
812 cstring res = cstring_undefined;
813
814 allModes (mname)
815 {
816 context_setModeNoWarn (cstring_fromChars (mname));
817
818 res = message ("%q%s", res, cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
819 } end_allModes;
820
821 return res;
822}
823
824cstring
825describeFlag (cstring flagname)
826{
827 cstring oflagname = cstring_copy (flagname);
828 flagcode f = flags_identifyFlag (flagname);
829
830 if (flagcode_isSkip (f))
831 {
832 cstring_free (oflagname);
833 return cstring_undefined;
834 }
835 else if (flagcode_isValid (f))
836 {
837 if (cstring_equal (flagname, oflagname))
838 {
839 cstring_free (oflagname);
840 return (message ("%s\n\3%q", flagname, describeFlagCode (f)));
841 }
842 else
843 {
844 return (message ("%q (standardized name: %s)\n\3%q",
845 oflagname, flagname, describeFlagCode (f)));
846 }
847 }
848 else
849 {
850 if (flags_isModeName (flagname))
851 {
852 cstring_free (oflagname);
853
854 return
855 (message ("%s: predefined mode (see Manual for information)",
856 flagname));
857 }
858 else
859 {
860 return (message ("%q: <invalid flag>", oflagname));
861 }
862 }
863}
864
865static cstringSList
866sortedFlags (void)
867{
868 cstringSList s = cstringSList_new ();
869
870 allFlags (f)
871 {
872 if (f.desc != NULL)
873 {
874 s = cstringSList_add (s, cstring_fromChars (f.flag));
875 }
876 } end_allFlags;
877
878 cstringSList_alphabetize (s);
879
880 return s;
881}
882
883void printAlphaFlags ()
884{
885 cstringSList fl = sortedFlags ();
886
887 cstringSList_printSpaced (fl, 3, 1, context_getLineLen () - 25);
888 cstringSList_free (fl);
889}
890
891/*@observer@*/ cstring
892flagcode_unparse (flagcode code)
893{
894 if (code == INVALID_FLAG)
895 {
896 return cstring_makeLiteralTemp ("<invalid flag>");
897 }
898
899 return cstring_fromChars (flags[code].flag);
900}
901
902/*
903** Transforms a flag into its cannonical form.
904**
905** The following transformations are made:
906**
907** function -> fcn
908** variable -> var
909** constant -> const
910** iterator -> iter
911** parameter -> param
912** unrecognized -> unrecog
913** qualifier -> qual
914** declaration -> decl
915** globalias -> (no change)
916** global -> glob
917** modifies -> mods
918** modify -> mod
919** pointer -> ptr
920** implies -> imp
921** implicit -> imp
922** implied -> imp
923** unconstrained -> unspec
924** unconst -> unspec
925** memory -> mem
926** length -> len
927*/
928
929static /*@only@*/ cstring
930canonicalizeFlag (cstring s)
931{
932 int i = 0;
933 cstring res = cstring_copy (s);
934 static bn_mstring transform[] =
935 {
936 "function", "fcn",
937 "variable", "var",
938 "constant", "const",
939 "iterator", "iter",
940 "parameter", "param",
941 "unrecognized", "unrecog",
942 "qualifier", "qual",
943 "declaration", "decl",
944 "globals", "globs",
945 "modifies", "mods",
946 "modify", "mod",
947 "pointer", "ptr",
948 "implies", "imp",
949 "implicit", "imp",
950 "implied", "imp",
951 "unconstrained", "uncon",
952 "unconst", "uncon",
953 "memory", "mem",
954 "length", "len",
955 "return", "ret",
956 "system", "sys",
957 NULL
958 } ;
959 char *current;
960
961 while ((current = transform[i]) != NULL)
962 {
963 if (cstring_containsLit (res, current))
964 {
965 cstring_replaceLit (res, current, transform[i+1]);
966 }
967 i += 2;
968 }
969
970 /* remove whitespace, -'s, and _'s */
971 cstring_stripChars (res, " -_");
972 return res;
973}
974
975flagcode
976flags_identifyFlag (cstring s)
977{
978 return flags_identifyFlagAux (s, FALSE);
979}
980
981flagcode
982flags_identifyFlagQuiet (cstring s)
983{
984 return flags_identifyFlagAux (s, TRUE);
985}
986
987static flagcode
988flags_identifyFlagAux (cstring s, bool quiet)
989{
990 cstring cflag;
991 flagcode res;
992
993 if (cstring_length (s) == 0) {
994 /* evs 2000-06-25: A malformed flag. */
995 return INVALID_FLAG;
996 }
997
998 if (cstring_firstChar (s) == 'I')
999 {
1000 return FLG_INCLUDEPATH; /* no space required after -I */
1001 }
1002
1003 if (cstring_firstChar (s) == 'S')
1004 {
1005 return FLG_SPECPATH; /* no space required after -S */
1006 }
1007
1008 if (cstring_firstChar (s) == 'D')
1009 {
1010 return FLG_DEFINE; /* no space required after -D */
1011 }
1012
1013 if (cstring_firstChar (s) == 'U')
1014 {
1015 return FLG_UNDEFINE; /* no space required after -D */
1016 }
1017
1018 cflag = canonicalizeFlag (s);
1019 res = INVALID_FLAG;
1020
1021 allFlags (f)
1022 {
1023 if (cstring_equal (cstring_fromChars (f.flag), cflag))
1024 {
1025 res = f.code;
1026 break;
1027 }
1028 } end_allFlags;
1029
1030 if (res == INVALID_FLAG)
1031 {
1032 /*
1033 ** Synonyms
1034 */
1035
1036 if (cstring_equalLit (cflag, "pred"))
1037 {
1038 res = FLG_PREDBOOL;
1039 }
1040 else if (cstring_equalLit (cflag, "modobserverstrict"))
1041 {
1042 res = FLG_MODOBSERVERUNCON;
1043 }
1044 else if (cstring_equalLit (cflag, "czechnames"))
1045 {
1046 res = FLG_CZECH;
1047 }
1048 else if (cstring_equalLit (cflag, "slovaknames"))
1049 {
1050 res = FLG_SLOVAK;
1051 }
1052 else if (cstring_equalLit (cflag, "czechoslovaknames"))
1053 {
1054 res = FLG_CZECHOSLOVAK;
1055 }
1056 else if (cstring_equalLit (cflag, "globunspec")
1057 || cstring_equalLit (cflag, "globuncon"))
1058 {
1059 res = FLG_GLOBUNSPEC;
1060 }
1061 else if (cstring_equalLit (cflag, "modglobsunspec")
1062 || cstring_equalLit (cflag, "modglobsuncon")
1063 || cstring_equalLit (cflag, "modglobsnomods"))
1064 {
1065 res = FLG_MODGLOBSUNSPEC;
1066 }
1067 else if (cstring_equalLit (cflag, "export"))
1068 {
1069 res = FLG_EXPORTANY;
1070 }
1071 else if (cstring_equalLit (cflag, "macrospec"))
1072 {
1073 res = FLG_MACRODECL;
1074 }
1075 else if (cstring_equalLit (cflag, "ansireservedlocal"))
1076 {
1077 res = FLG_ISORESERVEDLOCAL;
1078 }
1079 else if (cstring_equalLit (cflag, "warnposix"))
1080 {
1081 res = FLG_WARNPOSIX;
1082 }
1083 else if (cstring_equalLit (cflag, "defuse"))
1084 {
1085 res = FLG_USEDEF;
1086 }
1087 else if (cstring_equalLit (cflag, "macroundef"))
1088 {
1089 res = FLG_MACROUNDEF;
1090 }
1091 else if (cstring_equalLit (cflag, "showcol"))
1092 {
1093 res = FLG_SHOWCOL;
1094 }
1095 else if (cstring_equalLit (cflag, "intbool"))
1096 {
1097 res = FLG_BOOLINT;
1098 }
1099 else if (cstring_equalLit (cflag, "intchar"))
1100 {
1101 res = FLG_CHARINT;
1102 }
1103 else if (cstring_equalLit (cflag, "intenum"))
1104 {
1105 res = FLG_ENUMINT;
1106 }
1107 else if (cstring_equalLit (cflag, "intlong"))
1108 {
1109 res = FLG_LONGINT;
1110 }
1111 else if (cstring_equalLit (cflag, "intshort"))
1112 {
1113 res = FLG_SHORTINT;
1114 }
1115 /*
1116 ** Backwards compatibility for our American friends...
1117 */
1118
1119 else if (cstring_equalLit (cflag, "ansilib"))
1120 {
1121 res = FLG_ANSILIB;
1122 }
1123 else if (cstring_equalLit (cflag, "ansistrictlib"))
1124 {
1125 res = FLG_STRICTLIB;
1126 }
1127 else if (cstring_equalLit (cflag, "skipansiheaders"))
1128 {
1129 res = FLG_SKIPISOHEADERS;
1130 }
1131 else if (cstring_equalLit (cflag, "ansireserved"))
1132 {
1133 res = FLG_ISORESERVED;
1134 }
1135 else if (cstring_equalLit (cflag, "ansireservedinternal"))
1136 {
1137 res = FLG_ISORESERVEDLOCAL;
1138 }
1139
1140 /*
1141 ** Obsolete Flags
1142 */
1143
1144 else if (cstring_equalLit (cflag, "accessunspec"))
1145 {
1146 if (!quiet)
1147 {
1148 llerror_flagWarning
1149 (cstring_makeLiteral
1150 ("accessunspec flag is no longer supported. It has been replaced by accessmodule, accessfile and "
1151 "accessfunction to provide more precise control of accessibility "
1152 "of representations. For more information, "
1153 "see splint -help accessmodule"));
1154 }
1155
1156 res = SKIP_FLAG;
1157 }
1158 else if (cstring_equalLit (cflag, "ansilimits"))
1159 {
1160 llerror_flagWarning
1161 (cstring_makeLiteral
1162 ("ansilimits flag is no longer supported. It has been replaced by ansi89limits and "
1163 "iso99limits to select either the lower translation limits imposed by the ANSI89 "
1164 "standard or the typically higher limits prescribed by ISO C99."));
1165
1166 res = SKIP_FLAG;
1167 }
1168 else if (cstring_equalLit (cflag, "staticmods"))
1169 {
1170 if (!quiet)
1171 {
1172 llerror_flagWarning
1173 (cstring_makeLiteral
1174 ("staticmods flag is obsolete. You probably "
1175 "want impcheckmodstatics. For more information, "
1176 "see splint -help impcheckmodstatics"));
1177 }
1178
1179 res = SKIP_FLAG;
1180 }
1181 else if (cstring_equalLit (cflag, "bool"))
1182 {
1183 if (!quiet)
1184 {
1185 llerror_flagWarning
1186 (cstring_makeLiteral ("bool flag is obsolete. It never really "
1187 "made sense in the first place."));
1188 }
1189
1190 res = SKIP_FLAG;
1191 }
1192 else if (cstring_equalLit (cflag, "shiftsigned"))
1193 {
1194 if (!quiet)
1195 {
1196 llerror_flagWarning
1197 (cstring_makeLiteral ("shiftsigned flag is obsolete. You probably "
1198 "want bitwisesigned, shiftnegative or shiftimplementation."));
1199 }
1200
1201 res = SKIP_FLAG;
1202 }
1203 else if (cstring_equalLit (cflag, "ansi"))
1204 {
1205 if (!quiet)
1206 {
1207 llerror_flagWarning
1208 (cstring_makeLiteral ("ansi flag is obsolete. You probably "
1209 "want noparams and/or oldstyle."));
1210 }
1211
1212 res = SKIP_FLAG;
1213 }
1214 else if (cstring_equalLit (cflag, "usestderr"))
1215 {
1216 if (!quiet)
1217 {
1218 llerror_flagWarning
1219 (cstring_makeLiteral
1220 ("usestderr flag is obsolete. This has been replaced "
1221 "by more precise flags for controlling the warning, "
1222 "status message and fatal error streams independently: message-stream-stdout, "
1223 "message-stream-stderr, message-stream <file>, "
1224 "warning-stream-stdout, warning-stream-stderr, warning-stream <file>, "
1225 "error-stream-stdout, error-stream-stderr, error-stream <file>."));
1226 }
1227
1228 res = SKIP_FLAG;
1229 }
1230
1231 else if (cstring_equalLit (cflag, "stdio"))
1232 {
1233 if (!quiet)
1234 {
1235 llerror_flagWarning
1236 (cstring_makeLiteral
1237 ("stdio flag is obsolete. You may "
1238 "want strictlib or one of the gloabls "
1239 "checking flags. For more information, "
1240 "see splint -help strictlib or splint -help flags globals"));
1241 }
1242
1243 res = SKIP_FLAG;
1244 }
1245 else if (flags_isModeName (cflag))
1246 {
1247 res = MODENAME_FLAG;
1248 }
1249 else
1250 {
1251 res = INVALID_FLAG;
1252 }
1253 }
1254
1255 cstring_free (cflag);
1256 return res;
1257}
1258
1259void flags_setValueFlag (flagcode opt, cstring arg)
1260{
1261 switch (opt)
1262 {
1263 case FLG_EXPECT:
1264 case FLG_LCLEXPECT:
1265 case FLG_LIMIT:
1266 case FLG_LINELEN:
1267 case FLG_INDENTSPACES:
1268 case FLG_LOCINDENTSPACES:
1269 case FLG_BUGSLIMIT:
1270 case FLG_EXTERNALNAMELEN:
1271 case FLG_INTERNALNAMELEN:
1272 case FLG_CONTROLNESTDEPTH:
1273 case FLG_STRINGLITERALLEN:
1274 case FLG_NUMSTRUCTFIELDS:
1275 case FLG_NUMENUMMEMBERS:
1276 case FLG_INCLUDENEST:
1277 {
1278 int val = cstring_toPosInt (arg);
1279
1280 if (val < 0)
1281 {
1282 llerror
1283 (FLG_BADFLAG,
1284 message
1285 ("Flag %s must be followed by a positive number number. "
1286 "Followed by %s",
1287 flagcode_unparse (opt), arg));
1288 }
1289 else
1290 {
1291 context_setValueAndFlag (opt, val);
1292 }
1293 }
1294 break;
1295 case FLG_COMMENTCHAR:
1296 {
1297 if (cstring_length (arg) != 1)
1298 {
1299 llfatalerrorLoc
1300 (message
1301 ("Flag %s should be followed by a single character. Followed by %s",
1302 flagcode_unparse (opt), arg));
1303 }
1304 else
1305 {
1306 context_setCommentMarkerChar (cstring_firstChar (arg));
1307 }
1308 }
1309 break;
1310 BADDEFAULT;
1311 }
1312}
1313
1314void flags_setStringFlag (flagcode opt, /*@only@*/ cstring arg)
1315{
1316 switch (opt)
1317 {
1318 case FLG_TMPDIR:
1319 {
1320 if (cstring_lastChar (arg) == CONNECTCHAR)
1321 {
1322 context_setString (opt, arg);
1323 }
1324 else
1325 {
1326 context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1327 }
1328 break;
1329 }
1330 default:
1331 {
1332 context_setString (opt, arg);
1333 break;
1334 }
1335 }
1336}
1337
1338cstring
1339describeModes ()
1340{
1341 cstring s = cstring_makeLiteral ("Flag ");
1342 cstringSList sflags = sortedFlags ();
1343
1344 allModes (modename)
1345 {
1346 s = message ("%q%9s", s, cstring_fromChars (modename));
1347 } end_allModes;
1348
1349 s = message ("%q\n", s);
1350
1351 cstringSList_elements (sflags, flagname)
1352 {
1353 flagcode code = flags_identifyFlag (flagname);
1354 fflag currentflag = flags[code];
1355
1356 if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1357 {
1358 s = message ("%q\n%27s", s,
1359 cstring_fromChars (currentflag.flag));
1360
1361 allModes (modename)
1362 {
1363 context_setMode (cstring_fromChars (modename));
1364
1365 if (context_getFlag (code))
1366 {
1367 s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1368 }
1369 else
1370 {
1371 s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1372 }
1373
1374 context_resetModeFlags ();
1375 } end_allModes;
1376 }
1377 } end_cstringSList_elements;
1378
1379 cstringSList_free (sflags);
1380
1381 s = cstring_appendChar (s, '\n');
1382
1383 return (s);
1384}
1385
1386# if 0
1387static /*@unused@*/ cstring
1388listModes (void)
1389{
1390 cstring s = cstring_makeLiteral ("\t");
1391 int i = 0;
1392
1393 allModes (modename)
1394 {
1395 if (i != 0 && (i % 4 == 0))
1396 {
1397 s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1398 }
1399 else
1400 {
1401 s = message ("%q%15s", s, cstring_fromChars (modename));
1402 }
1403 i++;
1404 } end_allModes;
1405
1406 return s;
1407}
1408# endif
1409
1410bool
1411flags_isModeName (cstring s)
1412{
1413 allModes (modename)
1414 {
1415 if (mstring_isDefined (modename))
1416 {
1417 if (cstring_equalLit (s, modename))
1418 {
1419 return TRUE;
1420 }
1421 }
1422 } end_allModes;
1423
1424 return FALSE;
1425}
1426
1427extern bool flagcode_hasArgument (flagcode f)
1428{
1429 return (flags[f].argtype != ARG_NONE);
1430}
1431
1432extern bool flagcode_hasNumber (flagcode f)
1433{
1434 return (flags[f].argtype == ARG_NUMBER);
1435}
1436
1437extern bool flagcode_hasChar (flagcode f)
1438{
1439 return (flags[f].argtype == ARG_CHAR);
1440}
1441
1442extern bool flagcode_hasString (flagcode f)
1443{
1444 return (flags[f].argtype == ARG_STRING
1445 || flags[f].argtype == ARG_FILE
1446 || flags[f].argtype == ARG_DIRECTORY
1447 || flags[f].argtype == ARG_PATH);
1448}
1449
1450extern int flagcode_valueIndex (flagcode f)
1451{
1452 /*@unchecked@*/ static bool initialized = FALSE;
1453 int i;
1454 /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
1455
1456 if (!initialized)
1457 {
1458 int nv = 0;
1459
1460 allFlagCodes (code)
1461 {
1462 if (flagcode_hasNumber (code) || flagcode_hasChar (code))
1463 {
1464 llassert (nv < NUMVALUEFLAGS);
1465 DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
1466 valueFlags[nv] = code;
1467 nv++;
1468 }
1469 } end_allFlagCodes;
1470
1471 llassertprint (nv == NUMVALUEFLAGS,
1472 ("Number of value flags: %d (expected %d)",
1473 nv, (int) NUMVALUEFLAGS));
1474 initialized = TRUE;
1475 }
1476
1477 for (i = 0; i < NUMVALUEFLAGS; i++)
1478 {
1479 /* static valueFlags must be defined */
1480 /*@-usedef@*/
1481 if (f == valueFlags[i]) /*@=usedef@*/
1482 {
1483 return i;
1484 }
1485 }
1486
1487 fprintf (stderr, "Cannot find value flag: %d", (int) f);
1488 exit (EXIT_FAILURE);
1489 /* Cannot do this...might call recursively...
1490 llfatalbug (message ("Cannot fine value flag: %d", (int) f));
1491 BADEXIT;
1492 */
1493}
1494
1495extern int flagcode_stringIndex (flagcode f)
1496{
1497 /*@unchecked@*/ static bool initialized = FALSE;
1498 /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1499 int i;
1500
1501
1502 if (!initialized)
1503 {
1504 int nv = 0;
1505
1506 allFlagCodes (code)
1507 {
1508 if (flagcode_hasString (code))
1509 {
1510 llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1511 stringFlags[nv] = code;
1512 nv++;
1513 }
1514 } end_allFlagCodes;
1515
1516 llassertprint (nv == NUMSTRINGFLAGS,
1517 ("number of string flags: %d (expected %d)",
1518 nv, NUMSTRINGFLAGS));
1519 initialized = TRUE;
1520 }
1521
1522 for (i = 0; i < NUMSTRINGFLAGS; i++)
1523 {
1524 /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1525 {
1526 return i;
1527 }
1528 }
1529
1530 llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1531 BADEXIT;
1532}
1533
1534bool flagcode_isNamePrefixFlag (flagcode f)
1535{
1536 switch (f)
1537 {
1538 case FLG_MACROVARPREFIX:
1539 case FLG_TAGPREFIX:
1540 case FLG_ENUMPREFIX:
1541 case FLG_FILESTATICPREFIX:
1542 case FLG_GLOBPREFIX:
1543 case FLG_TYPEPREFIX:
1544 case FLG_EXTERNALPREFIX:
1545 case FLG_LOCALPREFIX:
1546 case FLG_UNCHECKEDMACROPREFIX:
1547 case FLG_CONSTPREFIX:
1548 case FLG_ITERPREFIX:
1549 case FLG_DECLPARAMPREFIX:
1550 return TRUE;
1551 default:
1552 return FALSE;
1553 }
1554}
1555
1556static cstring findLarchPathFile (/*@temp@*/ cstring s)
1557{
1558 cstring pathName;
1559 filestatus status;
1560
1561 status = osd_getPath (context_getLarchPath (), s, &pathName);
1562
1563 if (status == OSD_FILEFOUND)
1564 {
1565 return pathName;
1566 }
1567 else if (status == OSD_FILENOTFOUND)
1568 {
1569 showHerald ();
1570 lldiagmsg (message ("Cannot find file on LARCH_PATH: %s", s));
1571 }
1572 else if (status == OSD_PATHTOOLONG)
1573 {
1574 /* Directory and filename are too long. Report error. */
1575 llbuglit ("soure_getPath: Filename plus directory from search path too long");
1576 }
1577 else
1578 {
1579 BADBRANCH;
1580 }
1581
1582 return cstring_undefined;
1583}
1584
1585static void addLarchPathFile (fileIdList files, /*@temp@*/ cstring s)
1586{
1587 cstring pathName = findLarchPathFile (s);
1588
1589 if (cstring_isDefined (pathName))
1590 {
1591 if (fileTable_exists (context_fileTable (), pathName))
1592 {
1593 showHerald ();
1594 lldiagmsg (message ("File listed multiple times: %s", pathName));
1595 cstring_free (pathName);
1596 }
1597 else
1598 {
1599 fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), pathName));
1600 }
1601 }
1602}
1603
1604
1605static void addFile (fileIdList files, /*@only@*/ cstring s)
1606{
1607 if (fileTable_exists (context_fileTable (), s))
1608 {
1609 showHerald ();
1610 lldiagmsg (message ("File listed multiple times: %s", s));
1611 cstring_free (s);
1612 }
1613 else
1614 {
1615 fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), s));
1616 }
1617}
1618
1619static void addXHFile (fileIdList files, /*@temp@*/ cstring s)
1620{
1621 cstring pathName = findLarchPathFile (s);
1622
1623 if (cstring_isDefined (pathName))
1624 {
1625 if (fileTable_exists (context_fileTable (), pathName))
1626 {
1627 showHerald ();
1628 lldiagmsg (message ("File listed multiple times: %s", s));
1629 }
1630 else
1631 {
1632 fileIdList_add (files, fileTable_addXHFile (context_fileTable (), pathName));
1633 }
1634 }
1635
1636 cstring_free (pathName);
1637}
1638
1639void
1640flags_processFlags (bool inCommandLine,
1641 fileIdList xfiles,
1642 fileIdList cfiles,
1643 fileIdList lclfiles,
1644 fileIdList mtfiles,
1645 cstringList *passThroughArgs,
1646 int argc, char **argv)
1647{
1648 int i;
1649 cstringSList fl = cstringSList_undefined;
1650
1651 for (i = 0; i < argc; i++)
1652 {
1653 char *thisarg;
1654
1655 llassert (argv != NULL);
1656 thisarg = argv[i];
1657
1658 DPRINTF (("process thisarg [%d]: %s", i, thisarg));
1659
1660 if (*thisarg == '-' || *thisarg == '+')
1661 {
1662 bool set = (*thisarg == '+');
1663 cstring flagname;
1664 flagcode opt;
1665
1666 if (*(thisarg + 1) == '-') { /* allow -- before flags */
1667 flagname = cstring_fromChars (thisarg + 2);
1668 } else {
1669 flagname = cstring_fromChars (thisarg + 1);
1670 }
1671
1672 opt = flags_identifyFlag (flagname);
1673 DPRINTF (("Flag [%s]: %s", flagname, flagcode_unparse (opt)));
1674
1675 if (flagcode_isInvalid (opt))
1676 {
1677 DPRINTF (("Error!"));
1678 voptgenerror (FLG_BADFLAG,
1679 message ("Unrecognized option: %s",
1680 cstring_fromChars (thisarg)),
1681 g_currentloc);
1682 }
1683 else if (flagcode_isHelpFlag (opt))
1684 {
1685 if (inCommandLine)
1686 {
1687 voptgenerror (FLG_BADFLAG,
1688 message ("Help flag must be first on the command line: %s",
1689 cstring_fromChars (thisarg)),
1690 g_currentloc);
1691 }
1692 else
1693 {
1694 voptgenerror (FLG_BADFLAG,
1695 message ("Help flags can only be used on the command line: %s",
1696 cstring_fromChars (thisarg)),
1697 g_currentloc);
1698 }
1699 }
1700 else if (flagcode_isPassThrough (opt)) /* preprocessor flag: -D or -U */
1701 {
1702 /*
1703 ** Following space is optional, don't include the -
1704 */
1705
1706 *passThroughArgs = cstringList_add (*passThroughArgs,
1707 cstring_fromCharsNew (thisarg + 1));
1708 }
1709 else if (opt == FLG_INCLUDEPATH || opt == FLG_SPECPATH)
1710 {
1711 if (mstring_length (thisarg) < 2) {
1712 BADBRANCH;
1713 } else {
1714 if (mstring_equal (thisarg, "-I-")) {
1715 cppAddIncludeDir (cstring_fromChars (thisarg)); /* Need to handle this specially. */
1716 } else {
1717 cstring dir = cstring_suffix (cstring_fromChars (thisarg), 2); /* skip over -I */
1718
1719 DPRINTF (("Length of thisarg [%s] %d", thisarg, cstring_length (thisarg)));
1720
1721 if (cstring_length (dir) == 0) {
1722 DPRINTF (("space after directory: "));
1723 if (++i < argc) {
1724 dir = cstring_fromChars (argv[i]);
1725 } else {
1726 voptgenerror
1727 (FLG_BADFLAG,
1728 message
1729 ("Flag %s must be followed by a directory name",
1730 flagcode_unparse (opt)),
1731 g_currentloc);
1732 }
1733 }
1734
1735 DPRINTF (("Got directory: [%s]", dir));
1736
1737 switch (opt)
1738 {
1739 case FLG_INCLUDEPATH:
1740 cppAddIncludeDir (dir);
1741 /*@switchbreak@*/ break;
1742 case FLG_SPECPATH:
1743 /*@-mustfree@*/
1744 g_localSpecPath = cstring_toCharsSafe
1745 (message ("%s%h%s",
1746 cstring_fromChars (g_localSpecPath),
1747 PATH_SEPARATOR,
1748 dir));
1749 /*@=mustfree@*/
1750 /*@switchbreak@*/ break;
1751 BADDEFAULT;
1752 }
1753 }
1754 }
1755 }
1756 else if (flagcode_isModeName (opt))
1757 {
1758 context_setMode (flagname);
1759 }
1760 else if (inCommandLine && flagcode_isMessageControlFlag (opt))
1761 {
1762 /*
1763 ** Processed on first pass
1764 */
1765
1766 if (flagcode_hasArgument (opt))
1767 {
1768 ++i;
1769 }
1770 }
1771 else
1772 {
1773 /*
1774 ** A normal control flag
1775 */
1776
1777 context_userSetFlag (opt, set);
1778
1779 if (flagcode_hasArgument (opt))
1780 {
1781 if (flagcode_hasNumber (opt))
1782 {
1783 if (++i < argc)
1784 {
1785 flags_setValueFlag (opt, cstring_fromCharsNew (argv[i]));
1786 }
1787 else
1788 {
1789 voptgenerror
1790 (FLG_BADFLAG,
1791 message
1792 ("Flag %s must be followed by a number",
1793 flagcode_unparse (opt)),
1794 g_currentloc);
1795 }
1796 }
1797 else if (flagcode_hasChar (opt))
1798 {
1799 if (++i < argc)
1800 {
1801 flags_setValueFlag (opt, cstring_fromCharsNew (argv[i]));
1802 }
1803 else
1804 {
1805 voptgenerror
1806 (FLG_BADFLAG,
1807 message
1808 ("Flag %s must be followed by a character",
1809 flagcode_unparse (opt)),
1810 g_currentloc);
1811 }
1812 }
1813 else if (flagcode_hasString (opt)
1814 || opt == FLG_INIT || opt == FLG_OPTF)
1815 {
1816 if (++i < argc)
1817 {
1818 /*drl 10/21/2002
1819 Changed this because arg can be freed when it's passed to
1820 lslinit_setInitFile and freeing argv[i] causes a seg fault
1821 */
1822 cstring arg = cstring_fromCharsNew (argv[i]);
1823
1824 if (opt == FLG_OPTF)
1825 {
1826 if (inCommandLine)
1827 {
1828 ; /* -f already processed */
1829 }
1830 else
1831 {
1832 (void) rcfiles_read (arg, passThroughArgs, TRUE);
1833 }
1834 }
1835 else if (opt == FLG_INIT)
1836 {
1837 lslinit_setInitFile (inputStream_create
1838 (arg,
1839 cstring_makeLiteralTemp (LCLINIT_SUFFIX),
1840 FALSE));
1841 break;
1842 }
1843 else
1844 {
1845 DPRINTF (("String flag: %s / %s",
1846 flagcode_unparse (opt), arg));
1847 if (opt == FLG_MTSFILE)
1848 {
1849 /*
1850 ** arg identifies mts files
1851 */
1852 cstring tmp = message ("%s%s", arg, MTS_EXTENSION);
1853 addLarchPathFile (mtfiles, tmp);
1854 cstring_free (tmp);
1855 tmp = message ("%s%s", arg, XH_EXTENSION);
1856 addXHFile (xfiles, tmp);
1857 cstring_free (tmp);
1858 }
1859 else
1860 {
1861 flags_setStringFlag (opt, cstring_copy (arg));
1862 }
1863 }
1864 }
1865 else
1866 {
1867 voptgenerror
1868 (FLG_BADFLAG,
1869 message
1870 ("Flag %s must be followed by a string",
1871 flagcode_unparse (opt)),
1872 g_currentloc);
1873 }
1874 }
1875 else
1876 {
1877 /* no argument */
1878 }
1879 }
1880 }
1881 }
1882 else /* its a filename */
1883 {
1884 DPRINTF (("Adding filename: %s", thisarg));
1885 fl = cstringSList_add (fl, cstring_fromChars (thisarg));
1886 }
1887 }
1888
1889 /*
1890 ** create lists of C and LCL files
1891 */
1892
1893 if (inCommandLine)
1894 {
1895 cstringSList_elements (fl, current)
1896 {
1897 cstring ext = fileLib_getExtension (current);
1898
1899 if (cstring_isUndefined (ext))
1900 {
1901 /* no extension --- both C and LCL with default extensions */
1902
1903 addFile (cfiles, message ("%s%s", current, C_EXTENSION));
1904 addFile (lclfiles, message ("%s%s", current, LCL_EXTENSION));
1905 }
1906 else if (cstring_equal (ext, XH_EXTENSION))
1907 {
1908 addXHFile (xfiles, current);
1909 }
1910 else if (cstring_equal (ext, PP_EXTENSION))
1911 {
1912 if (!context_getFlag (FLG_NOPP))
1913 {
1914 voptgenerror
1915 (FLG_FILEEXTENSIONS,
1916 message ("File extension %s used without +nopp flag (will be processed as C source code): %s",
1917 ext, current),
1918 g_currentloc);
1919 }
1920
1921 addFile (cfiles, cstring_copy (current));
1922 }
1923 else if (cstring_equal (ext, LCL_EXTENSION))
1924 {
1925 addFile (lclfiles, cstring_copy (current));
1926 }
1927 else if (fileLib_isCExtension (ext))
1928 {
1929 addFile (cfiles, cstring_copy (current));
1930 }
1931 else if (cstring_equal (ext, MTS_EXTENSION))
1932 {
1933 addLarchPathFile (mtfiles, current);
1934 }
1935 else
1936 {
1937 voptgenerror
1938 (FLG_FILEEXTENSIONS,
1939 message ("Unrecognized file extension: %s (assuming %s is C source code)",
1940 current, ext),
1941 g_currentloc);
1942
1943 addFile (cfiles, cstring_copy (current));
1944 }
1945 } end_cstringSList_elements;
1946 }
1947 else
1948 {
1949 if (cstringSList_size (fl) != 0)
1950 {
1951 /* Cannot list files in .splintrc files */
1952 voptgenerror (FLG_BADFLAG,
1953 message ("Cannot list files in .splintrc files: %s (probable missing + or -)",
1954 cstringSList_unparse (fl)),
1955 g_currentloc);
1956 }
1957 }
1958
1959 cstringSList_free (fl); /* evans 2002-07-12: why wasn't this reported!?? */
1960}
1961
1962int flagcode_priority (/*@unused@*/ flagcode code)
1963{
1964 /*
1965 ** For now, we do a really simple prioritization: all are 1
1966 */
1967
1968 return 1;
1969}
This page took 0.088861 seconds and 5 git commands to generate.