]> andersk Git - splint.git/blame_incremental - src/flags.c
Fixed manual typo.
[splint.git] / src / flags.c
... / ...
CommitLineData
1/*
2** Splint - annotation-assisted static program checker
3** Copyright (C) 1994-2002 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 "portab.h"
31
32/*
33** from the CC man page:
34**
35** -Idir Search for #include files whose names do not begin with a
36** slash (/) in the following order: (1) in the directory of
37** the dir argument, (2) in the directories specified by -I
38** options, (3) in the standard directory (/usr/include).
39*/
40
41/* needed for string literals literals */
42
43typedef struct {
44 flagkind kind;
45 /*@null@*/ /*@observer@*/ char *name;
46 /*@null@*/ /*@observer@*/ char *describe;
47} flagcatinfo;
48
49static flagcatinfo categories[] =
50{
51 { FK_ABSTRACT, "abstract", "abstraction violations, representation access" } ,
52 { FK_ALIAS, "aliasing", "unexpected or dangerous aliasing" } ,
53 { FK_USE, "alluse", "all declarations are used" } ,
54 { FK_ANSI, "ansi", "violations of constraints imposed by ANSI/ISO standard" } ,
55 { FK_ARRAY, "arrays", "special checking involving arrays" } ,
56 { FK_BOOL, "booleans", "checking and naming of boolean types" } ,
57 { FK_COMMENTS, "comments", "warnings about (normal) comments" } ,
58 { FK_SYNCOMMENTS, "syncomments", "interpretation of annotation comments" } ,
59 { FK_COMPLETE, "complete", "completely defined, used, or specified system" } ,
60 { FK_CONTROL, "controlflow", "suspicious control structures" } ,
61 { FK_DEBUG, "debug", "flags for debugging splint" } ,
62 { FK_DECL, "declarations", "consistency of declarations" } ,
63 { FK_DEF, "definition", "undefined storage errors" } ,
64 { FK_DIRECT, "directories", "set directores" } ,
65 { FK_DISPLAY, "display", "control what is displayed" } ,
66 { FK_EFFECT, "effect", "statements with no effects" } ,
67 { FK_ERRORS, "errors", "control expected errors, summary reporting" } ,
68 { FK_EXPORT, "export", "control what may be exported" } ,
69 { FK_EXPOSURE, "exposure", "representation exposure" } ,
70 { FK_EXTENSIBLE, "extensible", "user-defined checks and annotations" },
71 { FK_FILES, "files", "control system files" } ,
72 { FK_FORMAT, "format", "control format of warning messages" } ,
73 { FK_GLOBALS, "globals", "use of global and file static variables" },
74 { FK_HEADERS, "headers", "control inclusion and generation of header files" },
75 { FK_HELP, "help", "on-line help" },
76 { FK_BOUNDS, "memorybounds", "out-of-bounds memory accesses" },
77 { FK_HINTS, "hints", "control display of warning hints" },
78 { FK_SYSTEMFUNCTIONS, "systemfunctions", "special properties of exit and main" },
79 { FK_IMPLICIT, "implicit", "control implicit annotations and interpretations" } ,
80 { FK_INIT, "initializations", "initialization files" } ,
81 { FK_ITER, "iterators", "checking iterator definitions and uses" } ,
82 { FK_LEAK, "leaks", "memory leaks" } ,
83 { FK_LIBS, "libraries", "loading and dumping of user and standard libraries" } ,
84 { FK_LIMITS, "limits", "violations of set limits" } ,
85 { FK_MACROS, "macros", "expansion, definition and use of macros" },
86 { FK_MEMORY, "memory", "memory management" } ,
87 { FK_MODIFIES, "modification", "modification errors" } ,
88 { FK_NAMES, "names", "naming conventions and limits" } ,
89 { FK_NULL, "null", "misuses of null pointers" } ,
90 { FK_NUMBERS, "numbers", "control type-checking of numeric types" } ,
91 { FK_OPS, "operations", "checking of primitive operations" } ,
92 { FK_PARAMS, "parameters", "function and macro parameters" } ,
93 { FK_SPEED, "performance", "speeding up checking" } ,
94 { FK_POINTER, "pointers", "pointers" } ,
95 { FK_PRED, "predicates", "condition test expressions" } ,
96 { FK_PREFIX, "prefixes", "set naming prefixes and control checking" } ,
97 { FK_PREPROC, "preproc", "defines and undefines for the preprocessor" } ,
98 { FK_PROTOS, "prototypes", "function prototypes" } ,
99 { FK_DEAD, "released", "using storage that has been deallocated" } ,
100 { FK_IGNORERET, "returnvals", "ignored return values" },
101 { FK_SECURITY, "security", "possible security vulnerability" },
102 { FK_SPEC, "specifications", "checks involving .lcl specifications" } ,
103 { FK_SUPPRESS, "suppress", "local and global suppression of messages" } ,
104 { FK_TYPEEQ, "typeequivalence", "control what types are equivalent" } ,
105 { FK_BEHAVIOR, "undefined", "code with undefined or implementation-defined behavior" } ,
106 { FK_UNRECOG, "unrecognized", "unrecognized identifiers" } ,
107 { FK_UNSPEC, "unconstrained", "checking in the presence of unconstrained functions" } ,
108 { FK_WARNUSE, "warnuse", "use of possibly problematic function" } ,
109 { FK_ITS4, "its4", "its4 compatibility flags (report warnings for uses of possibly insecure functions)" } ,
110 { FK_SYNTAX, NULL, NULL } ,
111 { FK_TYPE, NULL, NULL } ,
112 { FK_SECRET, NULL, NULL } ,
113 { FK_OBSOLETE, NULL, NULL } ,
114 { FK_NONE, NULL, NULL } /* must be last */
115} ;
116
117typedef enum {
118 ARG_NONE,
119 ARG_NUMBER, /* number */
120 ARG_CHAR, /* char */
121 ARG_STRING, /* string */
122 ARG_FILE, /* filename (also a string) */
123 ARG_DIRECTORY, /* directory (also a string) */
124 ARG_PATH, /* path */
125 ARG_SPECIAL /* ? */
126} argcode;
127
128static /*@observer@*/ cstring argcode_unparse (argcode arg)
129{
130 switch (arg)
131 {
132 case ARG_STRING: return cstring_makeLiteralTemp ("string");
133 case ARG_FILE: return cstring_makeLiteralTemp ("filename");
134 case ARG_DIRECTORY: return cstring_makeLiteralTemp ("directory");
135 case ARG_PATH: return cstring_makeLiteralTemp ("path");
136 case ARG_NUMBER: return cstring_makeLiteralTemp ("number");
137 case ARG_CHAR: return cstring_makeLiteralTemp ("character");
138 case ARG_NONE:
139 BADBRANCH;
140 case ARG_SPECIAL:
141 BADBRANCH;
142 }
143# ifdef WIN32
144/* Make Microsoft VC++ happy */
145# pragma warning (disable:4715)
146# endif
147}
148
149typedef struct {
150 flagkind main;
151 flagkind sub;
152 bool isSpecial; /* setting this flag may set other flags (or values) */
153 bool isIdem; /* idempotent - always sets to TRUE */
154 bool isGlobal; /* cannot be set locally (using control comments) */
155 bool isModeFlag; /* set by modes */
156 argcode argtype;
157 /*@observer@*/ char *flag;
158 flagcode code;
159 /*@observer@*/ /*@null@*/ char *desc;
160 bn_mstring hint;
161 int nreported;
162 int nsuppressed;
163} fflag;
164
165typedef fflag flaglist[];
166
167# include "flags.def"
168
169/*@iter allFlags (yield observer fflag f); @*/
170# define allFlags(m_f) \
171 { /*@+enumint@*/ flagcode m_i; for (m_i = 0; m_i < NUMFLAGS; m_i++) { fflag m_f = flags[m_i]; /*@=enumint@*/
172# define end_allFlags }}
173
174static bn_mstring mode_names[] =
175{
176 "weak", "standard", "checks", "strict", NULL,
177};
178
179/*@iter allModes (yield bn_mstring modename)@*/
180# define allModes(m_m) \
181 { int m_ii = 0; while (mstring_isDefined (mode_names[m_ii])) \
182 { bn_mstring m_m = mode_names[m_ii]; m_ii++;
183
184# define end_allModes }}
185
186/*@+enumint@*/
187
188static cstring getFlagModeSettings (flagcode p_flag) /*@modifies internalState@*/ ;
189static cstring describeFlagCode (flagcode p_flag) /*@*/ ;
190static cstringSList sortedFlags (void) /*@*/ ;
191static /*@observer@*/ cstring categoryName (flagkind p_kind) /*@*/ ;
192
193static flagcode flags_identifyFlagAux (cstring p_s, bool p_quiet) /*@modifies g_warningstream@*/ ;
194
195# if 0
196static /*@unused@*/ cstring listModes (void) /*@*/ ;
197# endif
198
199bool flagcode_isSpecialFlag (flagcode f)
200{
201 return (flags[f].isSpecial);
202}
203
204bool flagcode_isGlobalFlag (flagcode f)
205{
206 return (flags[f].isGlobal);
207}
208
209bool flagcode_isIdemFlag (flagcode f)
210{
211 return (flags[f].isIdem);
212}
213
214bool flagcode_isModeFlag (flagcode f)
215{
216 return (flags[f].isModeFlag);
217}
218
219bool flagcode_isNameChecksFlag (flagcode f)
220{
221 return (flags[f].main == FK_NAMES);
222}
223
224bool flagcode_isMessageControlFlag (flagcode f)
225{
226 /*
227 ** True if opt controls the display of messages.
228 ** These flags must be processed first.
229 */
230
231 return (f == FLG_SHOWSCAN
232 || f == FLG_WARNRC
233 || f == FLG_PARENFILEFORMAT
234 || f == FLG_MESSAGESTREAMSTDERR
235 || f == FLG_MESSAGESTREAMSTDOUT
236 || f == FLG_WARNINGSTREAMSTDERR
237 || f == FLG_WARNINGSTREAMSTDOUT
238 || f == FLG_ERRORSTREAMSTDERR
239 || f == FLG_ERRORSTREAMSTDOUT
240 || f == FLG_MESSAGESTREAM
241 || f == FLG_WARNINGSTREAM
242 || f == FLG_ERRORSTREAM
243 || f == FLG_STREAMOVERWRITE);
244}
245
246/*
247** Internal consistency check on the flags.
248*/
249
250void flags_initMod ()
251{
252 allFlagCodes (code)
253 {
254 /*@+enumint@*/
255 if (flags[code].code != code)
256 {
257 fprintf (stderr,
258 "*** ERROR: inconsistent flag %s / %d / %d",
259 flags[code].flag,
260 flags[code].code, code);
261
262 llbug (message ("*** ERROR: inconsistent flag %s / %d / %d",
263 cstring_fromChars (flags[code].flag),
264 flags[code].code, code));
265 }
266 /*@=enumint@*/
267 } end_allFlagCodes;
268}
269
270void
271summarizeErrors ()
272{
273 bool hadOne = FALSE;
274 int sumrep = 0;
275 int sumsup = 0;
276
277 char *buf = mstring_create (128);
278
279 allFlags (f)
280 {
281 if (f.nreported > 0 || f.nsuppressed > 0)
282 {
283 int nrep = f.nreported;
284 int nsup = f.nsuppressed;
285 cstring fs = cstring_fill (cstring_fromChars (f.flag), 23);
286
287 if (!hadOne)
288 {
289 llmsgplain (cstring_makeLiteral
290 ("\nError Type Reported Suppressed\n"
291 "=================== ======== ========="));
292 hadOne = TRUE;
293 }
294
295 sprintf (buf, "%s%7d %9d", cstring_toCharsSafe (fs), nrep, nsup);
296
297 sumrep += nrep;
298 sumsup += nsup;
299
300 cstring_free (fs);
301 llmsg (cstring_copy (cstring_fromChars (buf)));
302 }
303 } end_allFlags;
304
305 if (hadOne)
306 {
307 cstring ts = cstring_fill (cstring_makeLiteralTemp ("Total"), 23);
308
309 llmsglit (" ======== =========");
310
311 sprintf (buf, "%s%7d %9d", cstring_toCharsSafe (ts), sumrep, sumsup);
312 cstring_free (ts);
313 llmsgplain (cstring_copy (cstring_fromChars (buf)));
314 }
315
316 sfree (buf);
317}
318
319/*@+enumindex@*/
320
321void
322flagcode_recordError (flagcode f)
323{
324 if (f != INVALID_FLAG)
325 {
326 if (f == FLG_WARNFLAGS)
327 {
328 ; /* don't count these */
329 }
330 else
331 {
332 /*drl bee: ec*/
333 /*drl bee: ec*/
334 flags[f].nreported = flags[f].nreported + 1;
335 }
336 }
337 else
338 {
339 llcontbug (message ("flagcode_recordError: invalid flag: %d", (int) f));
340 }
341}
342
343void
344flagcode_recordSuppressed (flagcode f)
345{
346 llassertprint (f != INVALID_FLAG, ("flagcode: %s", flagcode_unparse (f)));
347
348 /*drl bee: ec*/
349 /*drl bee: ec*/ flags[f].nsuppressed = flags[f].nsuppressed + 1;
350}
351
352int
353flagcode_numReported (flagcode f)
354{
355 llassert (f != INVALID_FLAG);
356
357 return (flags[f].nreported);
358}
359
360/*@observer@*/ cstring
361flagcodeHint (flagcode f)
362{
363 llassert (f != INVALID_FLAG);
364
365 /*drl bee: ec*/
366 if (mstring_isDefined (flags[f].hint))
367 {
368 return (cstring_fromChars (flags[f].hint));
369 }
370 else
371 {
372 return (cstring_fromChars (flags[f].desc));
373 }
374}
375
376static int categorySize (flagkind kind) /*@*/
377{
378 int n = 0;
379
380
381 allFlags (f)
382 {
383 if (f.main == kind || f.sub == kind)
384 {
385 n++;
386 }
387 } end_allFlags;
388
389 return n;
390}
391
392flagkind identifyCategory (cstring s)
393{
394 int i;
395
396 for (i = 0; categories[i].kind != FK_NONE; i++)
397 {
398 /*drl bee: mRug*/
399 if (mstring_isDefined (categories[i].name))
400 {
401 if (cstring_equalLit (s, categories[i].name))
402 {
403 return categories[i].kind;
404 }
405 }
406 }
407
408 return FK_NONE;
409}
410
411static /*@observer@*/ cstring categoryName (flagkind kind)
412{
413 int i;
414
415 for (i = 0; categories[i].kind != FK_NONE; i++)
416 {
417 /*drl bee: mrUg*/
418 if (categories[i].kind == kind)
419 {
420 return (cstring_fromChars (categories[i].name));
421 }
422 }
423
424 return (cstring_makeLiteralTemp ("<No Category>"));
425}
426
427static int categoryIndex (flagkind kind)
428{
429 int i;
430
431 for (i = 0; categories[i].kind != FK_NONE; i++)
432 {
433 /*drl bee: mRug*/
434 if (categories[i].kind == kind)
435 {
436 return i;
437 }
438 }
439
440 return -1;
441}
442
443void printCategory (flagkind kind)
444{
445 int index = categoryIndex (kind);
446
447 llassert (index >= 0);
448 /*drl bee: mRug*/
449 llmsg (message ("%s (%d flags)\n\3%s\n\n",
450 cstring_fromChars (categories[index].name),
451 categorySize (kind),
452 cstring_fromChars (categories[index].describe)));
453
454 allFlags (f)
455 {
456 if (f.main == kind || f.sub == kind)
457 {
458 llmsg (message (" %s\n\6%q", cstring_fromChars (f.flag),
459 describeFlagCode (f.code)));
460 }
461 } end_allFlags;
462}
463
464void
465listAllCategories (void)
466{
467 int i;
468
469 for (i = 0; categories[i].kind != FK_NONE; i++)
470 {
471 /*drl bee: mRug*/
472 flagkind kind = categories[i].kind ;
473
474 if (categories[i].describe != NULL)
475 {
476 llmsg (message ("%s (%d flags)\n\3%s",
477 categoryName (kind),
478 categorySize (kind),
479 cstring_fromChars (categories[i].describe)));
480 }
481 }
482}
483
484void
485printAllFlags (bool desc, bool full)
486{
487 if (full)
488 {
489 cstringSList fl = sortedFlags ();
490
491 cstringSList_elements (fl, el)
492 {
493 /*@i22@*/ /*find out why this is necessary*/
494 cstring tmp;
495 tmp = cstring_copy(el);
496 llmsg (message ("%q\n\n", describeFlag (tmp)));
497 cstring_free(tmp);
498 } end_cstringSList_elements ;
499
500 cstringSList_free (fl);
501 }
502 else
503 {
504 allFlags (f)
505 {
506 if (f.code != INVALID_FLAG && f.main != FK_OBSOLETE)
507 {
508 if (mstring_isDefined (f.desc))
509 {
510 if (desc)
511 {
512 llmsg (message ("%s --- %s", cstring_fromChars (f.flag),
513 cstring_fromChars (f.desc)));
514 }
515 }
516 }
517 } end_allFlags;
518 }
519}
520
521void
522printFlagManual (bool html)
523{
524 /*
525 ** Prints all flags by category, in order they appear in flags.def
526 */
527
528 flagkind lastCategory = FK_NONE;
529
530 allFlags (f) {
531 cstring flagname;
532 cstring flagtype = cstring_undefined;
533
534 if (f.main != lastCategory)
535 {
536 if (html)
537 {
538 llmsg (message ("\n<h4>%s</h4>\n", categoryName (f.main)));
539 }
540 else
541 {
542 llmsg (message ("\n%s\n%s\n",
543 categoryName (f.main),
544 cstring_makeLiteralTemp ("===================================")));
545 }
546
547 lastCategory = f.main;
548 }
549
550 if (f.argtype == ARG_NONE || f.argtype == ARG_SPECIAL)
551 {
552 if (html)
553 {
554 flagname = message ("<tt>%s</tt>", cstring_fromChars (f.flag));
555 }
556 else
557 {
558 flagname = cstring_fromCharsNew (f.flag);
559 }
560 }
561 else
562 {
563 if (flagcode_hasString (f.code))
564 {
565 if (html)
566 {
567 flagname = message ("<tt>%s <em>&lt;%s&gt;</em></tt>",
568 cstring_fromChars (f.flag), argcode_unparse (f.argtype));
569 }
570 else
571 {
572 flagname = message ("%s <%s>", cstring_fromChars (f.flag), argcode_unparse (f.argtype));
573 }
574
575 if (cstring_isDefined (context_getString (f.code)))
576 {
577 if (html)
578 {
579 flagname = message ("%q <font color=\"blue\">[%s]</font>", flagname,
580 context_getString (f.code));
581 }
582 else
583 {
584 flagname = message ("%q [%s]", flagname,
585 context_getString (f.code));
586 }
587 }
588 }
589 else if (f.argtype == ARG_CHAR)
590 {
591 if (html)
592 {
593 flagname = message ("<tt>%s <em>&lt;%s&gt;</em></tt> <font color=\"blue\">[%c]</font>",
594 cstring_fromChars (f.flag), argcode_unparse (f.argtype),
595 (char) context_getValue (f.code));
596 }
597 else
598 {
599 flagname = message ("%s <%s> [%c]", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
600 (char) context_getValue (f.code));
601 }
602 }
603 else
604 {
605 llassert (f.argtype == ARG_NUMBER);
606
607 if (html)
608 {
609 flagname = message ("<tt>%s <em>&lt;%s&gt;</em> <font color=\"blue\">[%d]</font>",
610 cstring_fromChars (f.flag), argcode_unparse (f.argtype),
611 context_getValue (f.code));
612 }
613 else
614 {
615 flagname = message ("%s <%s> [%d]", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
616 context_getValue (f.code));
617 }
618 }
619 }
620
621 if (f.isIdem)
622 {
623 if (html)
624 {
625 flagtype = message("%q<font color=\"green\">-</font>", flagtype);
626 }
627 else
628 {
629 flagtype = message("%q<->", flagtype);
630 }
631 }
632
633 if (f.isGlobal)
634 {
635 if (html)
636 {
637 flagtype = message ("%q<font color=\"green\"><em>global</em></font>", flagtype);
638 }
639 else
640 {
641 flagtype = message ("%q<G>", flagtype);
642 }
643 }
644
645 if (f.isSpecial)
646 {
647 if (html)
648 {
649 flagtype = message ("%q<font color=\"orange\"><em>shortcut</em></font>", flagtype);
650 }
651 else
652 {
653 flagtype = message("%q<S>", flagtype);
654 }
655 }
656
657 if (f.isModeFlag)
658 {
659 if (html)
660 {
661 flagtype = message ("%q mode:<tt>%q</tt>>", flagtype, getFlagModeSettings (f.code));
662 }
663 else
664 {
665 flagtype = message ("%q<M:%q>", flagtype, getFlagModeSettings (f.code));
666 }
667 }
668 else /* its a plain flag */
669 {
670 if (html)
671 {
672 flagtype = message ("%q plain:<tt>%s</tt>", flagtype,
673 cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-"));
674 }
675 else
676 {
677 flagtype = message ("%q<P:%s>", flagtype,
678 cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-"));
679 }
680 }
681
682 llmsg (message ("%s: %s", flagname, flagtype));
683
684 if (html)
685 {
686 llgenindentmsgnoloc (cstring_makeLiteral ("<blockquote>"));
687 }
688
689 if (mstring_isDefined (f.hint))
690 {
691 llgenindentmsgnoloc (cstring_fromCharsNew (f.hint));
692 }
693 else
694 {
695 llgenindentmsgnoloc (message ("%q.", cstring_capitalize (cstring_fromChars (f.desc))));
696 }
697
698 if (html)
699 {
700 llgenindentmsgnoloc (cstring_makeLiteral ("</blockquote>"));
701 }
702 } end_allFlags ;
703}
704
705cstring
706describeFlagCode (flagcode flag)
707{
708 cstring ret = cstring_undefined;
709 fflag f;
710
711 if (flagcode_isInvalid (flag))
712 {
713 return (cstring_makeLiteral ("<invalid>"));
714 }
715
716 context_resetAllFlags ();
717
718 /*drl bee: mRug*/
719 f = flags[flag];
720 ret = cstring_copy (cstring_fromChars (f.desc));
721
722 if (f.sub != FK_NONE)
723 {
724 ret = message ("%q\nCategories: %s, %s",
725 ret,
726 categoryName (f.main),
727 categoryName (f.sub));
728 }
729 else
730 {
731 if (f.main != FK_NONE)
732 {
733 cstring cname = categoryName (f.main);
734
735 if (cstring_isDefined (cname))
736 {
737 ret = message ("%q\nCategory: %s",
738 ret, cname);
739 }
740 }
741 }
742
743 if (f.isModeFlag)
744 {
745 ret = message ("%q\nMode Settings: %q",
746 ret, getFlagModeSettings (flag));
747 }
748 else
749 {
750 ret = message ("%q\nDefault Setting: %s",
751 ret,
752 cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
753 }
754
755 if (f.isGlobal)
756 {
757 ret = message("%q\nSet globally only", ret);
758 }
759 else
760 {
761 ret = message("%q\nSet locally", ret);
762 }
763
764 switch (f.argtype)
765 {
766 case ARG_NONE:
767 case ARG_SPECIAL:
768 break;
769 case ARG_NUMBER:
770 ret = message("%q\nNumeric Argument. Default: %d",
771 ret,
772 context_getValue (flag));
773 break;
774 case ARG_CHAR:
775 ret = message("%q\nCharacter Argument. Default: %h",
776 ret, (char) context_getValue (flag));
777 break;
778 case ARG_STRING:
779 case ARG_FILE:
780 case ARG_PATH:
781 case ARG_DIRECTORY:
782 {
783 if (cstring_isDefined (context_getString (flag)))
784 {
785 ret = message("%q\n%q argument. Default: %s",
786 ret,
787 cstring_capitalize (argcode_unparse (f.argtype)),
788 context_getString (flag));
789 }
790 else
791 {
792 ret = message("%q\n%s argument. No default.",
793 ret,
794 cstring_capitalize (argcode_unparse (f.argtype)));
795 }
796 break;
797 }
798 }
799
800 if (mstring_isDefined (f.hint))
801 {
802 ret = message("%q\n\3%s", ret, cstring_fromChars (f.hint));
803 }
804
805 return ret;
806}
807
808static cstring getFlagModeSettings (flagcode flag)
809{
810 cstring res = cstring_undefined;
811
812 allModes (mname)
813 {
814 context_setModeNoWarn (cstring_fromChars (mname));
815
816 res = message ("%q%s", res, cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
817 } end_allModes;
818
819 return res;
820}
821
822cstring
823describeFlag (cstring flagname)
824{
825 cstring oflagname = cstring_copy (flagname);
826 flagcode f = flags_identifyFlag (flagname);
827
828 if (flagcode_isSkip (f))
829 {
830 cstring_free (oflagname);
831 return cstring_undefined;
832 }
833 else if (flagcode_isValid (f))
834 {
835 if (cstring_equal (flagname, oflagname))
836 {
837 cstring_free (oflagname);
838 return (message ("%s\n\3%q", flagname, describeFlagCode (f)));
839 }
840 else
841 {
842 return (message ("%q (standardized name: %s)\n\3%q",
843 oflagname, flagname, describeFlagCode (f)));
844 }
845 }
846 else
847 {
848 if (isMode (flagname))
849 {
850 cstring_free (oflagname);
851
852 return
853 (message ("%s: predefined mode (see Manual for information)",
854 flagname));
855 }
856 else
857 {
858 return (message ("%q: <invalid flag>", oflagname));
859 }
860 }
861}
862
863static cstringSList
864sortedFlags (void)
865{
866 cstringSList s = cstringSList_new ();
867
868 allFlags (f)
869 {
870 if (f.desc != NULL)
871 {
872 s = cstringSList_add (s, cstring_fromChars (f.flag));
873 }
874 } end_allFlags;
875
876 cstringSList_alphabetize (s);
877
878 return s;
879}
880
881void printAlphaFlags ()
882{
883 cstringSList fl = sortedFlags ();
884
885 cstringSList_printSpaced (fl, 3, 1, context_getLineLen () - 25);
886 cstringSList_free (fl);
887}
888
889/*@observer@*/ cstring
890flagcode_unparse (flagcode code)
891{
892 if (code == INVALID_FLAG)
893 {
894 return cstring_makeLiteralTemp ("<invalid flag>");
895 }
896
897 return cstring_fromChars (flags[code].flag);
898}
899
900/*
901** Transforms a flag into its cannonical form.
902**
903** The following transformations are made:
904**
905** function -> fcn
906** variable -> var
907** constant -> const
908** iterator -> iter
909** parameter -> param
910** unrecognized -> unrecog
911** qualifier -> qual
912** declaration -> decl
913** globalias -> (no change)
914** global -> glob
915** modifies -> mods
916** modify -> mod
917** pointer -> ptr
918** implies -> imp
919** implicit -> imp
920** implied -> imp
921** unconstrained -> unspec
922** unconst -> unspec
923** memory -> mem
924** length -> len
925*/
926
927static /*@only@*/ cstring
928canonicalizeFlag (cstring s)
929{
930 int i = 0;
931 cstring res = cstring_copy (s);
932 static bn_mstring transform[] =
933 {
934 "function", "fcn",
935 "variable", "var",
936 "constant", "const",
937 "iterator", "iter",
938 "parameter", "param",
939 "unrecognized", "unrecog",
940 "qualifier", "qual",
941 "declaration", "decl",
942 "globals", "globs",
943 "modifies", "mods",
944 "modify", "mod",
945 "pointer", "ptr",
946 "implies", "imp",
947 "implicit", "imp",
948 "implied", "imp",
949 "unconstrained", "uncon",
950 "unconst", "uncon",
951 "memory", "mem",
952 "length", "len",
953 "return", "ret",
954 "system", "sys",
955 NULL
956 } ;
957 char *current;
958
959 /*drl bee: ia*/
960 while ((current = transform[i]) != NULL)
961 {
962 if (cstring_containsLit (res, current))
963 {
964 cstring_replaceLit (res, current, transform[i+1]);
965 }
966 i += 2;
967 }
968
969 /* remove whitespace, -'s, and _'s */
970 cstring_stripChars (res, " -_");
971 return res;
972}
973
974flagcode
975flags_identifyFlag (cstring s)
976{
977 return flags_identifyFlagAux (s, FALSE);
978}
979
980flagcode
981flags_identifyFlagQuiet (cstring s)
982{
983 return flags_identifyFlagAux (s, TRUE);
984}
985
986static flagcode
987flags_identifyFlagAux (cstring s, bool quiet)
988{
989 cstring cflag;
990 flagcode res;
991
992 if (cstring_length (s) == 0) {
993 /* evs 2000-06-25: A malformed flag. */
994 return INVALID_FLAG;
995 }
996
997 if (cstring_firstChar (s) == 'I')
998 {
999 return FLG_INCLUDEPATH; /* no space after -I */
1000 }
1001
1002 if (cstring_firstChar (s) == 'S')
1003 {
1004 return FLG_SPECPATH; /* no space after -S */
1005 }
1006
1007 if (cstring_firstChar (s) == 'D')
1008 {
1009 return FLG_DEFINE; /* no space after -D */
1010 }
1011
1012 if (cstring_firstChar (s) == 'U')
1013 {
1014 return FLG_UNDEFINE; /* no space after -D */
1015 }
1016
1017 cflag = canonicalizeFlag (s);
1018 res = INVALID_FLAG;
1019
1020 allFlags (f)
1021 {
1022 if (cstring_equal (cstring_fromChars (f.flag), cflag))
1023 {
1024 res = f.code;
1025 break;
1026 }
1027 } end_allFlags;
1028
1029 if (res == INVALID_FLAG)
1030 {
1031 /*
1032 ** Synonyms
1033 */
1034
1035 if (cstring_equalLit (cflag, "pred"))
1036 {
1037 res = FLG_PREDBOOL;
1038 }
1039 else if (cstring_equalLit (cflag, "modobserverstrict"))
1040 {
1041 res = FLG_MODOBSERVERUNCON;
1042 }
1043 else if (cstring_equalLit (cflag, "czechnames"))
1044 {
1045 res = FLG_CZECH;
1046 }
1047 else if (cstring_equalLit (cflag, "slovaknames"))
1048 {
1049 res = FLG_SLOVAK;
1050 }
1051 else if (cstring_equalLit (cflag, "czechoslovaknames"))
1052 {
1053 res = FLG_CZECHOSLOVAK;
1054 }
1055 else if (cstring_equalLit (cflag, "globunspec")
1056 || cstring_equalLit (cflag, "globuncon"))
1057 {
1058 res = FLG_GLOBUNSPEC;
1059 }
1060 else if (cstring_equalLit (cflag, "modglobsunspec")
1061 || cstring_equalLit (cflag, "modglobsuncon")
1062 || cstring_equalLit (cflag, "modglobsnomods"))
1063 {
1064 res = FLG_MODGLOBSUNSPEC;
1065 }
1066 else if (cstring_equalLit (cflag, "export"))
1067 {
1068 res = FLG_EXPORTANY;
1069 }
1070 else if (cstring_equalLit (cflag, "macrospec"))
1071 {
1072 res = FLG_MACRODECL;
1073 }
1074 else if (cstring_equalLit (cflag, "ansireservedlocal"))
1075 {
1076 res = FLG_ISORESERVEDLOCAL;
1077 }
1078 else if (cstring_equalLit (cflag, "warnposix"))
1079 {
1080 res = FLG_WARNPOSIX;
1081 }
1082 else if (cstring_equalLit (cflag, "defuse"))
1083 {
1084 res = FLG_USEDEF;
1085 }
1086 else if (cstring_equalLit (cflag, "macroundef"))
1087 {
1088 res = FLG_MACROUNDEF;
1089 }
1090 else if (cstring_equalLit (cflag, "showcol"))
1091 {
1092 res = FLG_SHOWCOL;
1093 }
1094 else if (cstring_equalLit (cflag, "intbool"))
1095 {
1096 res = FLG_BOOLINT;
1097 }
1098 else if (cstring_equalLit (cflag, "intchar"))
1099 {
1100 res = FLG_CHARINT;
1101 }
1102 else if (cstring_equalLit (cflag, "intenum"))
1103 {
1104 res = FLG_ENUMINT;
1105 }
1106 /*
1107 ** Backwards compatibility for our American friends...
1108 */
1109
1110 else if (cstring_equalLit (cflag, "ansilib"))
1111 {
1112 res = FLG_ANSILIB;
1113 }
1114 else if (cstring_equalLit (cflag, "ansistrictlib"))
1115 {
1116 res = FLG_STRICTLIB;
1117 }
1118 else if (cstring_equalLit (cflag, "skipansiheaders"))
1119 {
1120 res = FLG_SKIPISOHEADERS;
1121 }
1122 else if (cstring_equalLit (cflag, "ansireserved"))
1123 {
1124 res = FLG_ISORESERVED;
1125 }
1126 else if (cstring_equalLit (cflag, "ansireservedinternal"))
1127 {
1128 res = FLG_ISORESERVEDLOCAL;
1129 }
1130
1131 /*
1132 ** Obsolete Flags
1133 */
1134
1135 else if (cstring_equalLit (cflag, "accessunspec"))
1136 {
1137 if (!quiet)
1138 {
1139 llerror_flagWarning
1140 (cstring_makeLiteral
1141 ("accessunspec flag is no longer supported. It has been replaced by accessmodule, accessfile and "
1142 "accessfunction to provide more precise control of accessibility "
1143 "of representations. For more information, "
1144 "see splint -help accessmodule"));
1145 }
1146
1147 res = SKIP_FLAG;
1148 }
1149 else if (cstring_equalLit (cflag, "ansilimits"))
1150 {
1151 llerror_flagWarning
1152 (cstring_makeLiteral
1153 ("ansilimits flag is no longer supported. It has been replaced by ansi89limits and "
1154 "iso99limits to select either the lower translation limits imposed by the ANSI89 "
1155 "standard or the typically higher limits prescribed by ISO C99."));
1156
1157 res = SKIP_FLAG;
1158 }
1159 else if (cstring_equalLit (cflag, "staticmods"))
1160 {
1161 if (!quiet)
1162 {
1163 llerror_flagWarning
1164 (cstring_makeLiteral
1165 ("staticmods flag is obsolete. You probably "
1166 "want impcheckmodstatics. For more information, "
1167 "see splint -help impcheckmodstatics"));
1168 }
1169
1170 res = SKIP_FLAG;
1171 }
1172 else if (cstring_equalLit (cflag, "bool"))
1173 {
1174 if (!quiet)
1175 {
1176 llerror_flagWarning
1177 (cstring_makeLiteral ("bool flag is obsolete. It never really "
1178 "made sense in the first place."));
1179 }
1180
1181 res = SKIP_FLAG;
1182 }
1183 else if (cstring_equalLit (cflag, "shiftsigned"))
1184 {
1185 if (!quiet)
1186 {
1187 llerror_flagWarning
1188 (cstring_makeLiteral ("shiftsigned flag is obsolete. You probably "
1189 "want bitwisesigned, shiftnegative or shiftimplementation."));
1190 }
1191
1192 res = SKIP_FLAG;
1193 }
1194 else if (cstring_equalLit (cflag, "ansi"))
1195 {
1196 if (!quiet)
1197 {
1198 llerror_flagWarning
1199 (cstring_makeLiteral ("ansi flag is obsolete. You probably "
1200 "want noparams and/or oldstyle."));
1201 }
1202
1203 res = SKIP_FLAG;
1204 }
1205 else if (cstring_equalLit (cflag, "usestderr"))
1206 {
1207 if (!quiet)
1208 {
1209 llerror_flagWarning
1210 (cstring_makeLiteral
1211 ("usestderr flag is obsolete. This has been replaced "
1212 "by more precise flags for controlling the warning, "
1213 "status message and fatal error streams independently: message-stream-stdout, "
1214 "message-stream-stderr, message-stream <file>, "
1215 "warning-stream-stdout, warning-stream-stderr, warning-stream <file>, "
1216 "error-stream-stdout, error-stream-stderr, error-stream <file>."));
1217 }
1218
1219 res = SKIP_FLAG;
1220 }
1221
1222 else if (cstring_equalLit (cflag, "stdio"))
1223 {
1224 if (!quiet)
1225 {
1226 llerror_flagWarning
1227 (cstring_makeLiteral
1228 ("stdio flag is obsolete. You may "
1229 "want strictlib or one of the gloabls "
1230 "checking flags. For more information, "
1231 "see splint -help strictlib or splint -help flags globals"));
1232 }
1233
1234 res = SKIP_FLAG;
1235 }
1236 else
1237 {
1238 res = INVALID_FLAG;
1239 }
1240 }
1241
1242 cstring_free (cflag);
1243 return res;
1244}
1245
1246void setValueFlag (flagcode opt, cstring arg)
1247{
1248 switch (opt)
1249 {
1250 case FLG_EXPECT:
1251 case FLG_LCLEXPECT:
1252 case FLG_LIMIT:
1253 case FLG_LINELEN:
1254 case FLG_INDENTSPACES:
1255 case FLG_BUGSLIMIT:
1256 case FLG_EXTERNALNAMELEN:
1257 case FLG_INTERNALNAMELEN:
1258 case FLG_CONTROLNESTDEPTH:
1259 case FLG_STRINGLITERALLEN:
1260 case FLG_NUMSTRUCTFIELDS:
1261 case FLG_NUMENUMMEMBERS:
1262 case FLG_INCLUDENEST:
1263 {
1264 int val = cstring_toPosInt (arg);
1265
1266 if (val < 0)
1267 {
1268 llerror
1269 (FLG_BADFLAG,
1270 message
1271 ("Flag %s must be followed by a positive number number. "
1272 "Followed by %s",
1273 flagcode_unparse (opt), arg));
1274 }
1275 else
1276 {
1277 context_setValueAndFlag (opt, val);
1278 }
1279 }
1280 break;
1281 case FLG_COMMENTCHAR:
1282 {
1283 if (cstring_length (arg) != 1)
1284 {
1285 llfatalerrorLoc
1286 (message
1287 ("Flag %s should be followed by a single character. Followed by %s",
1288 flagcode_unparse (opt), arg));
1289 }
1290 else
1291 {
1292 context_setCommentMarkerChar (cstring_firstChar (arg));
1293 }
1294 }
1295 break;
1296 BADDEFAULT;
1297 }
1298}
1299
1300void setStringFlag (flagcode opt, /*@only@*/ cstring arg)
1301{
1302 switch (opt)
1303 {
1304 case FLG_TMPDIR:
1305 {
1306 if (cstring_lastChar (arg) == CONNECTCHAR)
1307 {
1308 context_setString (opt, arg);
1309 }
1310 else
1311 {
1312 context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1313 }
1314 break;
1315 }
1316 default:
1317 {
1318 context_setString (opt, arg);
1319 break;
1320 }
1321 }
1322}
1323
1324cstring
1325describeModes ()
1326{
1327 cstring s = cstring_makeLiteral ("Flag ");
1328 cstringSList sflags = sortedFlags ();
1329
1330 allModes (modename)
1331 {
1332 s = message ("%q%9s", s, cstring_fromChars (modename));
1333 } end_allModes;
1334
1335 s = message ("%q\n", s);
1336
1337 cstringSList_elements (sflags, flagname)
1338 {
1339 flagcode code = flags_identifyFlag (flagname);
1340 fflag currentflag = flags[code];
1341
1342 if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1343 {
1344 s = message ("%q\n%27s", s,
1345 cstring_fromChars (currentflag.flag));
1346
1347 allModes (modename)
1348 {
1349 context_setMode (cstring_fromChars (modename));
1350
1351 if (context_getFlag (code))
1352 {
1353 s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1354 }
1355 else
1356 {
1357 s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1358 }
1359
1360 context_resetModeFlags ();
1361 } end_allModes;
1362 }
1363 } end_cstringSList_elements;
1364
1365 cstringSList_free (sflags);
1366
1367 s = cstring_appendChar (s, '\n');
1368
1369 return (s);
1370}
1371
1372# if 0
1373static /*@unused@*/ cstring
1374listModes (void)
1375{
1376 cstring s = cstring_makeLiteral ("\t");
1377 int i = 0;
1378
1379 allModes (modename)
1380 {
1381 if (i != 0 && (i % 4 == 0))
1382 {
1383 s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1384 }
1385 else
1386 {
1387 s = message ("%q%15s", s, cstring_fromChars (modename));
1388 }
1389 i++;
1390 } end_allModes;
1391
1392 return s;
1393}
1394# endif
1395
1396bool
1397isMode (cstring s)
1398{
1399 allModes (modename)
1400 {
1401 if (mstring_isDefined (modename))
1402 {
1403 if (cstring_equalLit (s, modename))
1404 {
1405 return TRUE;
1406 }
1407 }
1408 } end_allModes;
1409
1410 return FALSE;
1411}
1412
1413extern bool flagcode_hasArgument (flagcode f)
1414{
1415 return (flags[f].argtype != ARG_NONE);
1416}
1417
1418extern bool flagcode_hasNumber (flagcode f)
1419{
1420 return (flags[f].argtype == ARG_NUMBER);
1421}
1422
1423extern bool flagcode_hasChar (flagcode f)
1424{
1425 return (flags[f].argtype == ARG_CHAR);
1426}
1427
1428extern bool flagcode_hasString (flagcode f)
1429{
1430 return (flags[f].argtype == ARG_STRING
1431 || flags[f].argtype == ARG_FILE
1432 || flags[f].argtype == ARG_DIRECTORY
1433 || flags[f].argtype == ARG_PATH);
1434}
1435
1436extern int flagcode_valueIndex (flagcode f)
1437{
1438 /*@unchecked@*/ static bool initialized = FALSE;
1439 int i;
1440 /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
1441
1442 if (!initialized)
1443 {
1444 int nv = 0;
1445
1446 allFlagCodes (code)
1447 {
1448 if (flagcode_hasNumber (code) || flagcode_hasChar (code))
1449 {
1450 llassert (nv < NUMVALUEFLAGS);
1451 DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
1452 valueFlags[nv] = code;
1453 nv++;
1454 }
1455 } end_allFlagCodes;
1456
1457 llassertprint (nv == NUMVALUEFLAGS,
1458 ("Number of value flags: %d (expected %d)",
1459 nv, (int) NUMVALUEFLAGS));
1460 initialized = TRUE;
1461 }
1462
1463 for (i = 0; i < NUMVALUEFLAGS; i++)
1464 {
1465 /* static valueFlags must be defined */
1466 /*@-usedef@*/
1467 /*drl bee: sta*/
1468 if (f == valueFlags[i]) /*@=usedef@*/
1469 {
1470 return i;
1471 }
1472 }
1473
1474 fprintf (stderr, "Cannot find value flag: %d", (int) f);
1475 exit (EXIT_FAILURE);
1476 /* Cannot do this...might call recursively...
1477 llfatalbug (message ("Cannot fine value flag: %d", (int) f));
1478 BADEXIT;
1479 */
1480}
1481
1482extern int flagcode_stringIndex (flagcode f)
1483{
1484 /*@unchecked@*/ static bool initialized = FALSE;
1485 /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1486 int i;
1487
1488
1489 if (!initialized)
1490 {
1491 int nv = 0;
1492
1493 allFlagCodes (code)
1494 {
1495 if (flagcode_hasString (code))
1496 {
1497 llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1498 stringFlags[nv] = code;
1499 nv++;
1500 }
1501 } end_allFlagCodes;
1502
1503 llassertprint (nv == NUMSTRINGFLAGS,
1504 ("number of string flags: %d (expected %d)",
1505 nv, NUMSTRINGFLAGS));
1506 initialized = TRUE;
1507 }
1508
1509 for (i = 0; i < NUMSTRINGFLAGS; i++)
1510 {
1511 /*drl bee: sta*/
1512 /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1513 {
1514 return i;
1515 }
1516 }
1517
1518 llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1519 BADEXIT;
1520}
1521
1522bool flagcode_isNamePrefixFlag (flagcode f)
1523{
1524 switch (f)
1525 {
1526 case FLG_MACROVARPREFIX:
1527 case FLG_TAGPREFIX:
1528 case FLG_ENUMPREFIX:
1529 case FLG_FILESTATICPREFIX:
1530 case FLG_GLOBPREFIX:
1531 case FLG_TYPEPREFIX:
1532 case FLG_EXTERNALPREFIX:
1533 case FLG_LOCALPREFIX:
1534 case FLG_UNCHECKEDMACROPREFIX:
1535 case FLG_CONSTPREFIX:
1536 case FLG_ITERPREFIX:
1537 case FLG_DECLPARAMPREFIX:
1538 return TRUE;
1539 default:
1540 return FALSE;
1541 }
1542}
1543
This page took 0.135148 seconds and 5 git commands to generate.