]> andersk Git - splint.git/blame_incremental - src/flags.c
Fixed -help <mode> bug.
[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
709describeMode (cstring mode)
710{
711 cstringSList sflags = sortedFlags ();
712 cstring res = message ("Predefined mode %s sets: ", mode);
713
714 llassert (flags_isModeName (mode));
715
716 context_setMode (mode);
717
718 cstringSList_elements (sflags, flagname)
719 {
720 flagcode code = flags_identifyFlag (flagname);
721 fflag currentflag = flags[code];
722
723 if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
724 {
725 if (context_getFlag (code))
726 {
727 res = message ("%q\n +%s", res, cstring_fromChars (currentflag.flag));
728 }
729 else
730 {
731 res = message ("%q\n -%s", res, cstring_fromChars (currentflag.flag));
732 }
733 }
734 } end_cstringSList_elements;
735
736 cstringSList_free (sflags);
737
738 res = cstring_appendChar (res, '\n');
739 return (res);
740}
741
742cstring
743describeFlagCode (flagcode flag)
744{
745 cstring ret = cstring_undefined;
746 fflag f;
747
748 if (flagcode_isInvalid (flag))
749 {
750 return (cstring_makeLiteral ("<invalid>"));
751 }
752
753 if (flagcode_isModeName (flag))
754 {
755 return (cstring_makeLiteral ("<mode flag>"));
756 }
757
758 context_resetAllFlags ();
759
760 f = flags[flag];
761 ret = cstring_copy (cstring_fromChars (f.desc));
762
763 if (f.sub != FK_NONE)
764 {
765 ret = message ("%q\nCategories: %s, %s",
766 ret,
767 categoryName (f.main),
768 categoryName (f.sub));
769 }
770 else
771 {
772 if (f.main != FK_NONE)
773 {
774 cstring cname = categoryName (f.main);
775
776 if (cstring_isDefined (cname))
777 {
778 ret = message ("%q\nCategory: %s",
779 ret, cname);
780 }
781 }
782 }
783
784 if (f.isModeFlag)
785 {
786 ret = message ("%q\nMode Settings: %q",
787 ret, getFlagModeSettings (flag));
788 }
789 else
790 {
791 ret = message ("%q\nDefault Setting: %s",
792 ret,
793 cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
794 }
795
796 if (f.isGlobal)
797 {
798 ret = message("%q\nSet globally only", ret);
799 }
800 else
801 {
802 ret = message("%q\nSet locally", ret);
803 }
804
805 switch (f.argtype)
806 {
807 case ARG_NONE:
808 case ARG_SPECIAL:
809 break;
810 case ARG_NUMBER:
811 ret = message("%q\nNumeric Argument. Default: %d",
812 ret,
813 context_getValue (flag));
814 break;
815 case ARG_CHAR:
816 ret = message("%q\nCharacter Argument. Default: %h",
817 ret, (char) context_getValue (flag));
818 break;
819 case ARG_STRING:
820 case ARG_FILE:
821 case ARG_PATH:
822 case ARG_DIRECTORY:
823 {
824 if (cstring_isDefined (context_getString (flag)))
825 {
826 ret = message("%q\n%q argument. Default: %s",
827 ret,
828 cstring_capitalize (argcode_unparse (f.argtype)),
829 context_getString (flag));
830 }
831 else
832 {
833 ret = message("%q\n%s argument. No default.",
834 ret,
835 cstring_capitalize (argcode_unparse (f.argtype)));
836 }
837 break;
838 }
839 }
840
841 if (mstring_isDefined (f.hint))
842 {
843 ret = message("%q\n\3%s", ret, cstring_fromChars (f.hint));
844 }
845
846 return ret;
847}
848
849static cstring getFlagModeSettings (flagcode flag)
850{
851 cstring res = cstring_undefined;
852
853 allModes (mname)
854 {
855 context_setModeNoWarn (cstring_fromChars (mname));
856
857 res = message ("%q%s", res, cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
858 } end_allModes;
859
860 return res;
861}
862
863cstring
864describeFlag (cstring flagname)
865{
866 cstring oflagname = cstring_copy (flagname);
867 flagcode f = flags_identifyFlag (flagname);
868
869 if (flagcode_isSkip (f))
870 {
871 cstring_free (oflagname);
872 return cstring_undefined;
873 }
874 else if (flagcode_isValid (f))
875 {
876 if (cstring_equal (flagname, oflagname))
877 {
878 cstring_free (oflagname);
879 return (message ("%s\n\3%q", flagname, describeFlagCode (f)));
880 }
881 else
882 {
883 return (message ("%q (standardized name: %s)\n\3%q",
884 oflagname, flagname, describeFlagCode (f)));
885 }
886 }
887 else
888 {
889 if (flags_isModeName (flagname))
890 {
891 cstring_free (oflagname);
892 return describeMode (flagname);
893 }
894 else
895 {
896 return (message ("%q: <invalid flag>", oflagname));
897 }
898 }
899}
900
901static cstringSList
902sortedFlags (void)
903{
904 cstringSList s = cstringSList_new ();
905
906 allFlags (f)
907 {
908 if (f.desc != NULL)
909 {
910 s = cstringSList_add (s, cstring_fromChars (f.flag));
911 }
912 } end_allFlags;
913
914 cstringSList_alphabetize (s);
915
916 return s;
917}
918
919void printAlphaFlags ()
920{
921 cstringSList fl = sortedFlags ();
922
923 cstringSList_printSpaced (fl, 3, 1, context_getLineLen () - 25);
924 cstringSList_free (fl);
925}
926
927/*@observer@*/ cstring
928flagcode_unparse (flagcode code)
929{
930 if (code == INVALID_FLAG)
931 {
932 return cstring_makeLiteralTemp ("<invalid flag>");
933 }
934
935 return cstring_fromChars (flags[code].flag);
936}
937
938/*
939** Transforms a flag into its cannonical form.
940**
941** The following transformations are made:
942**
943** function -> fcn
944** variable -> var
945** constant -> const
946** iterator -> iter
947** parameter -> param
948** unrecognized -> unrecog
949** qualifier -> qual
950** declaration -> decl
951** globalias -> (no change)
952** global -> glob
953** modifies -> mods
954** modify -> mod
955** pointer -> ptr
956** implies -> imp
957** implicit -> imp
958** implied -> imp
959** unconstrained -> unspec
960** unconst -> unspec
961** memory -> mem
962** length -> len
963*/
964
965static /*@only@*/ cstring
966canonicalizeFlag (cstring s)
967{
968 int i = 0;
969 cstring res = cstring_copy (s);
970 static bn_mstring transform[] =
971 {
972 "function", "fcn",
973 "variable", "var",
974 "constant", "const",
975 "iterator", "iter",
976 "parameter", "param",
977 "unrecognized", "unrecog",
978 "qualifier", "qual",
979 "declaration", "decl",
980 "globals", "globs",
981 "modifies", "mods",
982 "modify", "mod",
983 "pointer", "ptr",
984 "implies", "imp",
985 "implicit", "imp",
986 "implied", "imp",
987 "unconstrained", "uncon",
988 "unconst", "uncon",
989 "memory", "mem",
990 "length", "len",
991 "return", "ret",
992 "system", "sys",
993 NULL
994 } ;
995 char *current;
996
997 while ((current = transform[i]) != NULL)
998 {
999 if (cstring_containsLit (res, current))
1000 {
1001 cstring_replaceLit (res, current, transform[i+1]);
1002 }
1003 i += 2;
1004 }
1005
1006 /* remove whitespace, -'s, and _'s */
1007 cstring_stripChars (res, " -_");
1008 return res;
1009}
1010
1011flagcode
1012flags_identifyFlag (cstring s)
1013{
1014 return flags_identifyFlagAux (s, FALSE);
1015}
1016
1017flagcode
1018flags_identifyFlagQuiet (cstring s)
1019{
1020 return flags_identifyFlagAux (s, TRUE);
1021}
1022
1023static flagcode
1024flags_identifyFlagAux (cstring s, bool quiet)
1025{
1026 cstring cflag;
1027 flagcode res;
1028
1029 if (cstring_length (s) == 0) {
1030 /* evs 2000-06-25: A malformed flag. */
1031 return INVALID_FLAG;
1032 }
1033
1034 if (cstring_firstChar (s) == 'I')
1035 {
1036 return FLG_INCLUDEPATH; /* no space required after -I */
1037 }
1038
1039 if (cstring_firstChar (s) == 'S')
1040 {
1041 return FLG_SPECPATH; /* no space required after -S */
1042 }
1043
1044 if (cstring_firstChar (s) == 'D')
1045 {
1046 return FLG_DEFINE; /* no space required after -D */
1047 }
1048
1049 if (cstring_firstChar (s) == 'U')
1050 {
1051 return FLG_UNDEFINE; /* no space required after -D */
1052 }
1053
1054 cflag = canonicalizeFlag (s);
1055 res = INVALID_FLAG;
1056
1057 allFlags (f)
1058 {
1059 if (cstring_equal (cstring_fromChars (f.flag), cflag))
1060 {
1061 res = f.code;
1062 break;
1063 }
1064 } end_allFlags;
1065
1066 if (res == INVALID_FLAG)
1067 {
1068 /*
1069 ** Synonyms
1070 */
1071
1072 if (cstring_equalLit (cflag, "pred"))
1073 {
1074 res = FLG_PREDBOOL;
1075 }
1076 else if (cstring_equalLit (cflag, "modobserverstrict"))
1077 {
1078 res = FLG_MODOBSERVERUNCON;
1079 }
1080 else if (cstring_equalLit (cflag, "czechnames"))
1081 {
1082 res = FLG_CZECH;
1083 }
1084 else if (cstring_equalLit (cflag, "slovaknames"))
1085 {
1086 res = FLG_SLOVAK;
1087 }
1088 else if (cstring_equalLit (cflag, "czechoslovaknames"))
1089 {
1090 res = FLG_CZECHOSLOVAK;
1091 }
1092 else if (cstring_equalLit (cflag, "globunspec")
1093 || cstring_equalLit (cflag, "globuncon"))
1094 {
1095 res = FLG_GLOBUNSPEC;
1096 }
1097 else if (cstring_equalLit (cflag, "modglobsunspec")
1098 || cstring_equalLit (cflag, "modglobsuncon")
1099 || cstring_equalLit (cflag, "modglobsnomods"))
1100 {
1101 res = FLG_MODGLOBSUNSPEC;
1102 }
1103 else if (cstring_equalLit (cflag, "export"))
1104 {
1105 res = FLG_EXPORTANY;
1106 }
1107 else if (cstring_equalLit (cflag, "macrospec"))
1108 {
1109 res = FLG_MACRODECL;
1110 }
1111 else if (cstring_equalLit (cflag, "ansireservedlocal"))
1112 {
1113 res = FLG_ISORESERVEDLOCAL;
1114 }
1115 else if (cstring_equalLit (cflag, "warnposix"))
1116 {
1117 res = FLG_WARNPOSIX;
1118 }
1119 else if (cstring_equalLit (cflag, "defuse"))
1120 {
1121 res = FLG_USEDEF;
1122 }
1123 else if (cstring_equalLit (cflag, "macroundef"))
1124 {
1125 res = FLG_MACROUNDEF;
1126 }
1127 else if (cstring_equalLit (cflag, "showcol"))
1128 {
1129 res = FLG_SHOWCOL;
1130 }
1131 else if (cstring_equalLit (cflag, "intbool"))
1132 {
1133 res = FLG_BOOLINT;
1134 }
1135 else if (cstring_equalLit (cflag, "intchar"))
1136 {
1137 res = FLG_CHARINT;
1138 }
1139 else if (cstring_equalLit (cflag, "intenum"))
1140 {
1141 res = FLG_ENUMINT;
1142 }
1143 else if (cstring_equalLit (cflag, "intlong"))
1144 {
1145 res = FLG_LONGINT;
1146 }
1147 else if (cstring_equalLit (cflag, "intshort"))
1148 {
1149 res = FLG_SHORTINT;
1150 }
1151 /*
1152 ** Backwards compatibility for our American friends...
1153 */
1154
1155 else if (cstring_equalLit (cflag, "ansilib"))
1156 {
1157 res = FLG_ANSILIB;
1158 }
1159 else if (cstring_equalLit (cflag, "ansistrictlib"))
1160 {
1161 res = FLG_STRICTLIB;
1162 }
1163 else if (cstring_equalLit (cflag, "skipansiheaders"))
1164 {
1165 res = FLG_SKIPISOHEADERS;
1166 }
1167 else if (cstring_equalLit (cflag, "ansireserved"))
1168 {
1169 res = FLG_ISORESERVED;
1170 }
1171 else if (cstring_equalLit (cflag, "ansireservedinternal"))
1172 {
1173 res = FLG_ISORESERVEDLOCAL;
1174 }
1175
1176 /*
1177 ** Obsolete Flags
1178 */
1179
1180 else if (cstring_equalLit (cflag, "accessunspec"))
1181 {
1182 if (!quiet)
1183 {
1184 llerror_flagWarning
1185 (cstring_makeLiteral
1186 ("accessunspec flag is no longer supported. It has been replaced by accessmodule, accessfile and "
1187 "accessfunction to provide more precise control of accessibility "
1188 "of representations. For more information, "
1189 "see splint -help accessmodule"));
1190 }
1191
1192 res = SKIP_FLAG;
1193 }
1194 else if (cstring_equalLit (cflag, "ansilimits"))
1195 {
1196 llerror_flagWarning
1197 (cstring_makeLiteral
1198 ("ansilimits flag is no longer supported. It has been replaced by ansi89limits and "
1199 "iso99limits to select either the lower translation limits imposed by the ANSI89 "
1200 "standard or the typically higher limits prescribed by ISO C99."));
1201
1202 res = SKIP_FLAG;
1203 }
1204 else if (cstring_equalLit (cflag, "staticmods"))
1205 {
1206 if (!quiet)
1207 {
1208 llerror_flagWarning
1209 (cstring_makeLiteral
1210 ("staticmods flag is obsolete. You probably "
1211 "want impcheckmodstatics. For more information, "
1212 "see splint -help impcheckmodstatics"));
1213 }
1214
1215 res = SKIP_FLAG;
1216 }
1217 else if (cstring_equalLit (cflag, "bool"))
1218 {
1219 if (!quiet)
1220 {
1221 llerror_flagWarning
1222 (cstring_makeLiteral ("bool flag is obsolete. It never really "
1223 "made sense in the first place."));
1224 }
1225
1226 res = SKIP_FLAG;
1227 }
1228 else if (cstring_equalLit (cflag, "shiftsigned"))
1229 {
1230 if (!quiet)
1231 {
1232 llerror_flagWarning
1233 (cstring_makeLiteral ("shiftsigned flag is obsolete. You probably "
1234 "want bitwisesigned, shiftnegative or shiftimplementation."));
1235 }
1236
1237 res = SKIP_FLAG;
1238 }
1239 else if (cstring_equalLit (cflag, "ansi"))
1240 {
1241 if (!quiet)
1242 {
1243 llerror_flagWarning
1244 (cstring_makeLiteral ("ansi flag is obsolete. You probably "
1245 "want noparams and/or oldstyle."));
1246 }
1247
1248 res = SKIP_FLAG;
1249 }
1250 else if (cstring_equalLit (cflag, "usestderr"))
1251 {
1252 if (!quiet)
1253 {
1254 llerror_flagWarning
1255 (cstring_makeLiteral
1256 ("usestderr flag is obsolete. This has been replaced "
1257 "by more precise flags for controlling the warning, "
1258 "status message and fatal error streams independently: message-stream-stdout, "
1259 "message-stream-stderr, message-stream <file>, "
1260 "warning-stream-stdout, warning-stream-stderr, warning-stream <file>, "
1261 "error-stream-stdout, error-stream-stderr, error-stream <file>."));
1262 }
1263
1264 res = SKIP_FLAG;
1265 }
1266
1267 else if (cstring_equalLit (cflag, "stdio"))
1268 {
1269 if (!quiet)
1270 {
1271 llerror_flagWarning
1272 (cstring_makeLiteral
1273 ("stdio flag is obsolete. You may "
1274 "want strictlib or one of the gloabls "
1275 "checking flags. For more information, "
1276 "see splint -help strictlib or splint -help flags globals"));
1277 }
1278
1279 res = SKIP_FLAG;
1280 }
1281 else if (flags_isModeName (cflag))
1282 {
1283 res = MODENAME_FLAG;
1284 }
1285 else
1286 {
1287 res = INVALID_FLAG;
1288 }
1289 }
1290
1291 cstring_free (cflag);
1292 return res;
1293}
1294
1295void flags_setValueFlag (flagcode opt, cstring arg)
1296{
1297 switch (opt)
1298 {
1299 case FLG_EXPECT:
1300 case FLG_LCLEXPECT:
1301 case FLG_LIMIT:
1302 case FLG_LINELEN:
1303 case FLG_INDENTSPACES:
1304 case FLG_LOCINDENTSPACES:
1305 case FLG_BUGSLIMIT:
1306 case FLG_EXTERNALNAMELEN:
1307 case FLG_INTERNALNAMELEN:
1308 case FLG_CONTROLNESTDEPTH:
1309 case FLG_STRINGLITERALLEN:
1310 case FLG_NUMSTRUCTFIELDS:
1311 case FLG_NUMENUMMEMBERS:
1312 case FLG_INCLUDENEST:
1313 {
1314 int val = cstring_toPosInt (arg);
1315
1316 if (val < 0)
1317 {
1318 llerror
1319 (FLG_BADFLAG,
1320 message
1321 ("Flag %s must be followed by a positive number number. "
1322 "Followed by %s",
1323 flagcode_unparse (opt), arg));
1324 }
1325 else
1326 {
1327 context_setValueAndFlag (opt, val);
1328 }
1329 }
1330 break;
1331 case FLG_COMMENTCHAR:
1332 {
1333 if (cstring_length (arg) != 1)
1334 {
1335 llfatalerrorLoc
1336 (message
1337 ("Flag %s should be followed by a single character. Followed by %s",
1338 flagcode_unparse (opt), arg));
1339 }
1340 else
1341 {
1342 context_setCommentMarkerChar (cstring_firstChar (arg));
1343 }
1344 }
1345 break;
1346 BADDEFAULT;
1347 }
1348}
1349
1350void flags_setStringFlag (flagcode opt, /*@only@*/ cstring arg)
1351{
1352 switch (opt)
1353 {
1354 case FLG_TMPDIR:
1355 {
1356 if (cstring_lastChar (arg) == CONNECTCHAR)
1357 {
1358 context_setString (opt, arg);
1359 }
1360 else
1361 {
1362 context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1363 }
1364 break;
1365 }
1366 default:
1367 {
1368 context_setString (opt, arg);
1369 break;
1370 }
1371 }
1372}
1373
1374cstring
1375describeModes ()
1376{
1377 cstring s = cstring_makeLiteral ("Flag ");
1378 cstringSList sflags = sortedFlags ();
1379
1380 allModes (modename)
1381 {
1382 s = message ("%q%9s", s, cstring_fromChars (modename));
1383 } end_allModes;
1384
1385 s = message ("%q\n", s);
1386
1387 cstringSList_elements (sflags, flagname)
1388 {
1389 flagcode code = flags_identifyFlag (flagname);
1390 fflag currentflag = flags[code];
1391
1392 if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1393 {
1394 s = message ("%q\n%27s", s,
1395 cstring_fromChars (currentflag.flag));
1396
1397 allModes (modename)
1398 {
1399 context_setMode (cstring_fromChars (modename));
1400
1401 if (context_getFlag (code))
1402 {
1403 s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1404 }
1405 else
1406 {
1407 s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1408 }
1409
1410 context_resetModeFlags ();
1411 } end_allModes;
1412 }
1413 } end_cstringSList_elements;
1414
1415 cstringSList_free (sflags);
1416
1417 s = cstring_appendChar (s, '\n');
1418
1419 return (s);
1420}
1421
1422# if 0
1423static /*@unused@*/ cstring
1424listModes (void)
1425{
1426 cstring s = cstring_makeLiteral ("\t");
1427 int i = 0;
1428
1429 allModes (modename)
1430 {
1431 if (i != 0 && (i % 4 == 0))
1432 {
1433 s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1434 }
1435 else
1436 {
1437 s = message ("%q%15s", s, cstring_fromChars (modename));
1438 }
1439 i++;
1440 } end_allModes;
1441
1442 return s;
1443}
1444# endif
1445
1446bool
1447flags_isModeName (cstring s)
1448{
1449 allModes (modename)
1450 {
1451 if (mstring_isDefined (modename))
1452 {
1453 if (cstring_equalLit (s, modename))
1454 {
1455 return TRUE;
1456 }
1457 }
1458 } end_allModes;
1459
1460 return FALSE;
1461}
1462
1463extern bool flagcode_hasArgument (flagcode f)
1464{
1465 return (flags[f].argtype != ARG_NONE);
1466}
1467
1468extern bool flagcode_hasNumber (flagcode f)
1469{
1470 return (flags[f].argtype == ARG_NUMBER);
1471}
1472
1473extern bool flagcode_hasChar (flagcode f)
1474{
1475 return (flags[f].argtype == ARG_CHAR);
1476}
1477
1478extern bool flagcode_hasString (flagcode f)
1479{
1480 return (flags[f].argtype == ARG_STRING
1481 || flags[f].argtype == ARG_FILE
1482 || flags[f].argtype == ARG_DIRECTORY
1483 || flags[f].argtype == ARG_PATH);
1484}
1485
1486extern int flagcode_valueIndex (flagcode f)
1487{
1488 /*@unchecked@*/ static bool initialized = FALSE;
1489 int i;
1490 /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
1491
1492 if (!initialized)
1493 {
1494 int nv = 0;
1495
1496 allFlagCodes (code)
1497 {
1498 if (flagcode_hasNumber (code) || flagcode_hasChar (code))
1499 {
1500 llassert (nv < NUMVALUEFLAGS);
1501 DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
1502 valueFlags[nv] = code;
1503 nv++;
1504 }
1505 } end_allFlagCodes;
1506
1507 llassertprint (nv == NUMVALUEFLAGS,
1508 ("Number of value flags: %d (expected %d)",
1509 nv, (int) NUMVALUEFLAGS));
1510 initialized = TRUE;
1511 }
1512
1513 for (i = 0; i < NUMVALUEFLAGS; i++)
1514 {
1515 /* static valueFlags must be defined */
1516 /*@-usedef@*/
1517 if (f == valueFlags[i]) /*@=usedef@*/
1518 {
1519 return i;
1520 }
1521 }
1522
1523 fprintf (stderr, "Cannot find value flag: %d", (int) f);
1524 exit (EXIT_FAILURE);
1525 /* Cannot do this...might call recursively...
1526 llfatalbug (message ("Cannot fine value flag: %d", (int) f));
1527 BADEXIT;
1528 */
1529}
1530
1531extern int flagcode_stringIndex (flagcode f)
1532{
1533 /*@unchecked@*/ static bool initialized = FALSE;
1534 /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1535 int i;
1536
1537
1538 if (!initialized)
1539 {
1540 int nv = 0;
1541
1542 allFlagCodes (code)
1543 {
1544 if (flagcode_hasString (code))
1545 {
1546 llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1547 stringFlags[nv] = code;
1548 nv++;
1549 }
1550 } end_allFlagCodes;
1551
1552 llassertprint (nv == NUMSTRINGFLAGS,
1553 ("number of string flags: %d (expected %d)",
1554 nv, NUMSTRINGFLAGS));
1555 initialized = TRUE;
1556 }
1557
1558 for (i = 0; i < NUMSTRINGFLAGS; i++)
1559 {
1560 /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1561 {
1562 return i;
1563 }
1564 }
1565
1566 llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1567 BADEXIT;
1568}
1569
1570bool flagcode_isNamePrefixFlag (flagcode f)
1571{
1572 switch (f)
1573 {
1574 case FLG_MACROVARPREFIX:
1575 case FLG_TAGPREFIX:
1576 case FLG_ENUMPREFIX:
1577 case FLG_FILESTATICPREFIX:
1578 case FLG_GLOBPREFIX:
1579 case FLG_TYPEPREFIX:
1580 case FLG_EXTERNALPREFIX:
1581 case FLG_LOCALPREFIX:
1582 case FLG_UNCHECKEDMACROPREFIX:
1583 case FLG_CONSTPREFIX:
1584 case FLG_ITERPREFIX:
1585 case FLG_DECLPARAMPREFIX:
1586 return TRUE;
1587 default:
1588 return FALSE;
1589 }
1590}
1591
1592static cstring findLarchPathFile (/*@temp@*/ cstring s)
1593{
1594 cstring pathName;
1595 filestatus status;
1596
1597 status = osd_getPath (context_getLarchPath (), s, &pathName);
1598
1599 if (status == OSD_FILEFOUND)
1600 {
1601 return pathName;
1602 }
1603 else if (status == OSD_FILENOTFOUND)
1604 {
1605 showHerald ();
1606 lldiagmsg (message ("Cannot find file on LARCH_PATH: %s", s));
1607 }
1608 else if (status == OSD_PATHTOOLONG)
1609 {
1610 /* Directory and filename are too long. Report error. */
1611 llbuglit ("soure_getPath: Filename plus directory from search path too long");
1612 }
1613 else
1614 {
1615 BADBRANCH;
1616 }
1617
1618 return cstring_undefined;
1619}
1620
1621static void addLarchPathFile (fileIdList files, /*@temp@*/ cstring s)
1622{
1623 cstring pathName = findLarchPathFile (s);
1624
1625 if (cstring_isDefined (pathName))
1626 {
1627 if (fileTable_exists (context_fileTable (), pathName))
1628 {
1629 showHerald ();
1630 lldiagmsg (message ("File listed multiple times: %s", pathName));
1631 cstring_free (pathName);
1632 }
1633 else
1634 {
1635 fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), pathName));
1636 }
1637 }
1638}
1639
1640
1641static void addFile (fileIdList files, /*@only@*/ cstring s)
1642{
1643 if (fileTable_exists (context_fileTable (), s))
1644 {
1645 showHerald ();
1646 lldiagmsg (message ("File listed multiple times: %s", s));
1647 cstring_free (s);
1648 }
1649 else
1650 {
1651 fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), s));
1652 }
1653}
1654
1655static void addXHFile (fileIdList files, /*@temp@*/ cstring s)
1656{
1657 cstring pathName = findLarchPathFile (s);
1658
1659 if (cstring_isDefined (pathName))
1660 {
1661 if (fileTable_exists (context_fileTable (), pathName))
1662 {
1663 showHerald ();
1664 lldiagmsg (message ("File listed multiple times: %s", s));
1665 }
1666 else
1667 {
1668 fileIdList_add (files, fileTable_addXHFile (context_fileTable (), pathName));
1669 }
1670 }
1671
1672 cstring_free (pathName);
1673}
1674
1675void
1676flags_processFlags (bool inCommandLine,
1677 fileIdList xfiles,
1678 fileIdList cfiles,
1679 fileIdList lclfiles,
1680 fileIdList mtfiles,
1681 cstringList *passThroughArgs,
1682 int argc, char **argv)
1683{
1684 int i;
1685 cstringSList fl = cstringSList_undefined;
1686
1687 for (i = 0; i < argc; i++)
1688 {
1689 char *thisarg;
1690
1691 llassert (argv != NULL);
1692 thisarg = argv[i];
1693
1694 DPRINTF (("process thisarg [%d]: %s", i, thisarg));
1695
1696 if (*thisarg == '-' || *thisarg == '+')
1697 {
1698 bool set = (*thisarg == '+');
1699 cstring flagname;
1700 flagcode opt;
1701
1702 if (*(thisarg + 1) == '-') { /* allow -- before flags */
1703 flagname = cstring_fromChars (thisarg + 2);
1704 } else {
1705 flagname = cstring_fromChars (thisarg + 1);
1706 }
1707
1708 opt = flags_identifyFlag (flagname);
1709 DPRINTF (("Flag [%s]: %s", flagname, flagcode_unparse (opt)));
1710
1711 if (flagcode_isInvalid (opt))
1712 {
1713 DPRINTF (("Error!"));
1714 voptgenerror (FLG_BADFLAG,
1715 message ("Unrecognized option: %s",
1716 cstring_fromChars (thisarg)),
1717 g_currentloc);
1718 }
1719 else if (flagcode_isHelpFlag (opt))
1720 {
1721 if (inCommandLine)
1722 {
1723 voptgenerror (FLG_BADFLAG,
1724 message ("Help flag must be first on the command line: %s",
1725 cstring_fromChars (thisarg)),
1726 g_currentloc);
1727 }
1728 else
1729 {
1730 voptgenerror (FLG_BADFLAG,
1731 message ("Help flags can only be used on the command line: %s",
1732 cstring_fromChars (thisarg)),
1733 g_currentloc);
1734 }
1735 }
1736 else if (flagcode_isPassThrough (opt)) /* preprocessor flag: -D or -U */
1737 {
1738 /*
1739 ** Following space is optional, don't include the -
1740 */
1741
1742 *passThroughArgs = cstringList_add (*passThroughArgs,
1743 cstring_fromCharsNew (thisarg + 1));
1744 }
1745 else if (opt == FLG_INCLUDEPATH || opt == FLG_SPECPATH)
1746 {
1747 if (mstring_length (thisarg) < 2) {
1748 BADBRANCH;
1749 } else {
1750 if (mstring_equal (thisarg, "-I-")) {
1751 cppAddIncludeDir (cstring_fromChars (thisarg)); /* Need to handle this specially. */
1752 } else {
1753 cstring dir = cstring_suffix (cstring_fromChars (thisarg), 2); /* skip over -I */
1754
1755 DPRINTF (("Length of thisarg [%s] %d", thisarg, cstring_length (thisarg)));
1756
1757 if (cstring_length (dir) == 0) {
1758 DPRINTF (("space after directory: "));
1759 if (++i < argc) {
1760 dir = cstring_fromChars (argv[i]);
1761 } else {
1762 voptgenerror
1763 (FLG_BADFLAG,
1764 message
1765 ("Flag %s must be followed by a directory name",
1766 flagcode_unparse (opt)),
1767 g_currentloc);
1768 }
1769 }
1770
1771 DPRINTF (("Got directory: [%s]", dir));
1772
1773 switch (opt)
1774 {
1775 case FLG_INCLUDEPATH:
1776 cppAddIncludeDir (dir);
1777 /*@switchbreak@*/ break;
1778 case FLG_SPECPATH:
1779 /*@-mustfree@*/
1780 g_localSpecPath = cstring_toCharsSafe
1781 (message ("%s%h%s",
1782 cstring_fromChars (g_localSpecPath),
1783 PATH_SEPARATOR,
1784 dir));
1785 /*@=mustfree@*/
1786 /*@switchbreak@*/ break;
1787 BADDEFAULT;
1788 }
1789 }
1790 }
1791 }
1792 else if (flagcode_isModeName (opt))
1793 {
1794 context_setMode (flagname);
1795 }
1796 else if (inCommandLine && flagcode_isMessageControlFlag (opt))
1797 {
1798 /*
1799 ** Processed on first pass
1800 */
1801
1802 if (flagcode_hasArgument (opt))
1803 {
1804 ++i;
1805 }
1806 }
1807 else
1808 {
1809 /*
1810 ** A normal control flag
1811 */
1812
1813 context_userSetFlag (opt, set);
1814
1815 if (flagcode_hasArgument (opt))
1816 {
1817 if (flagcode_hasNumber (opt))
1818 {
1819 if (++i < argc)
1820 {
1821 flags_setValueFlag (opt, cstring_fromCharsNew (argv[i]));
1822 }
1823 else
1824 {
1825 voptgenerror
1826 (FLG_BADFLAG,
1827 message
1828 ("Flag %s must be followed by a number",
1829 flagcode_unparse (opt)),
1830 g_currentloc);
1831 }
1832 }
1833 else if (flagcode_hasChar (opt))
1834 {
1835 if (++i < argc)
1836 {
1837 flags_setValueFlag (opt, cstring_fromCharsNew (argv[i]));
1838 }
1839 else
1840 {
1841 voptgenerror
1842 (FLG_BADFLAG,
1843 message
1844 ("Flag %s must be followed by a character",
1845 flagcode_unparse (opt)),
1846 g_currentloc);
1847 }
1848 }
1849 else if (flagcode_hasString (opt)
1850 || opt == FLG_INIT || opt == FLG_OPTF)
1851 {
1852 if (++i < argc)
1853 {
1854 /*drl 10/21/2002
1855 Changed this because arg can be freed when it's passed to
1856 lslinit_setInitFile and freeing argv[i] causes a seg fault
1857 */
1858 cstring arg = cstring_fromCharsNew (argv[i]);
1859
1860 if (opt == FLG_OPTF)
1861 {
1862 if (inCommandLine)
1863 {
1864 ; /* -f already processed */
1865 }
1866 else
1867 {
1868 (void) rcfiles_read (arg, passThroughArgs, TRUE);
1869 }
1870 }
1871 else if (opt == FLG_INIT)
1872 {
1873 lslinit_setInitFile (inputStream_create
1874 (arg,
1875 cstring_makeLiteralTemp (LCLINIT_SUFFIX),
1876 FALSE));
1877 break;
1878 }
1879 else
1880 {
1881 DPRINTF (("String flag: %s / %s",
1882 flagcode_unparse (opt), arg));
1883 if (opt == FLG_MTSFILE)
1884 {
1885 /*
1886 ** arg identifies mts files
1887 */
1888 cstring tmp = message ("%s%s", arg, MTS_EXTENSION);
1889 addLarchPathFile (mtfiles, tmp);
1890 cstring_free (tmp);
1891 tmp = message ("%s%s", arg, XH_EXTENSION);
1892 addXHFile (xfiles, tmp);
1893 cstring_free (tmp);
1894 }
1895 else
1896 {
1897 flags_setStringFlag (opt, cstring_copy (arg));
1898 }
1899 }
1900 }
1901 else
1902 {
1903 voptgenerror
1904 (FLG_BADFLAG,
1905 message
1906 ("Flag %s must be followed by a string",
1907 flagcode_unparse (opt)),
1908 g_currentloc);
1909 }
1910 }
1911 else
1912 {
1913 /* no argument */
1914 }
1915 }
1916 }
1917 }
1918 else /* its a filename */
1919 {
1920 DPRINTF (("Adding filename: %s", thisarg));
1921 fl = cstringSList_add (fl, cstring_fromChars (thisarg));
1922 }
1923 }
1924
1925 /*
1926 ** create lists of C and LCL files
1927 */
1928
1929 if (inCommandLine)
1930 {
1931 cstringSList_elements (fl, current)
1932 {
1933 cstring ext = fileLib_getExtension (current);
1934
1935 if (cstring_isUndefined (ext))
1936 {
1937 /* no extension --- both C and LCL with default extensions */
1938
1939 addFile (cfiles, message ("%s%s", current, C_EXTENSION));
1940 addFile (lclfiles, message ("%s%s", current, LCL_EXTENSION));
1941 }
1942 else if (cstring_equal (ext, XH_EXTENSION))
1943 {
1944 addXHFile (xfiles, current);
1945 }
1946 else if (cstring_equal (ext, PP_EXTENSION))
1947 {
1948 if (!context_getFlag (FLG_NOPP))
1949 {
1950 voptgenerror
1951 (FLG_FILEEXTENSIONS,
1952 message ("File extension %s used without +nopp flag (will be processed as C source code): %s",
1953 ext, current),
1954 g_currentloc);
1955 }
1956
1957 addFile (cfiles, cstring_copy (current));
1958 }
1959 else if (cstring_equal (ext, LCL_EXTENSION))
1960 {
1961 addFile (lclfiles, cstring_copy (current));
1962 }
1963 else if (fileLib_isCExtension (ext))
1964 {
1965 addFile (cfiles, cstring_copy (current));
1966 }
1967 else if (cstring_equal (ext, MTS_EXTENSION))
1968 {
1969 addLarchPathFile (mtfiles, current);
1970 }
1971 else
1972 {
1973 voptgenerror
1974 (FLG_FILEEXTENSIONS,
1975 message ("Unrecognized file extension: %s (assuming %s is C source code)",
1976 current, ext),
1977 g_currentloc);
1978
1979 addFile (cfiles, cstring_copy (current));
1980 }
1981 } end_cstringSList_elements;
1982 }
1983 else
1984 {
1985 if (cstringSList_size (fl) != 0)
1986 {
1987 /* Cannot list files in .splintrc files */
1988 voptgenerror (FLG_BADFLAG,
1989 message ("Cannot list files in .splintrc files: %s (probable missing + or -)",
1990 cstringSList_unparse (fl)),
1991 g_currentloc);
1992 }
1993 }
1994
1995 cstringSList_free (fl); /* evans 2002-07-12: why wasn't this reported!?? */
1996}
1997
1998int flagcode_priority (/*@unused@*/ flagcode code)
1999{
2000 /*
2001 ** For now, we do a really simple prioritization: all are 1
2002 */
2003
2004 return 1;
2005}
This page took 0.079304 seconds and 5 git commands to generate.