]> andersk Git - splint.git/blame - src/flags.c
Removed /bin/csh from tainted/Makefile
[splint.git] / src / flags.c
CommitLineData
616915dd 1/*
11db3170 2** Splint - annotation-assisted static program checker
77d37419 3** Copyright (C) 1994-2002 University of Virginia,
616915dd 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**
1b8ae690 20** For information on splint: splint@cs.virginia.edu
21** To report a bug: splint-bug@cs.virginia.edu
11db3170 22** For more information: http://www.splint.org
616915dd 23*/
24/*
25** flags.c
26*/
27
1b8ae690 28# include "splintMacros.nf"
616915dd 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" } ,
bb7c2085 57 { FK_COMMENTS, "comments", "warnings about (normal) comments" } ,
58 { FK_SYNCOMMENTS, "syncomments", "interpretation of annotation comments" } ,
616915dd 59 { FK_COMPLETE, "complete", "completely defined, used, or specified system" } ,
60 { FK_CONTROL, "controlflow", "suspicious control structures" } ,
1b8ae690 61 { FK_DEBUG, "debug", "flags for debugging splint" } ,
616915dd 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" } ,
bb7c2085 70 { FK_EXTENSIBLE, "extensible", "user-defined checks and annotations" },
616915dd 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" },
bb7c2085 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" },
616915dd 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" },
28bf4b0b 101 { FK_SECURITY, "security", "possible security vulnerability" },
616915dd 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" } ,
28bf4b0b 108 { FK_WARNUSE, "warnuse", "use of possibly problematic function" } ,
bb7c2085 109 { FK_ITS4, "its4", "its4 compatibility flags (report warnings for uses of possibly insecure functions)" } ,
616915dd 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,
4f43223c 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 /* ? */
616915dd 126} argcode;
127
4f43223c 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 }
4dd72714 143# ifdef WIN32
144/* Make Microsoft VC++ happy */
145# pragma warning (disable:4715)
146# endif
4f43223c 147}
148
616915dd 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
4f43223c 188static cstring getFlagModeSettings (flagcode p_flag) /*@modifies internalState@*/ ;
616915dd 189static cstring describeFlagCode (flagcode p_flag) /*@*/ ;
190static cstringSList sortedFlags (void) /*@*/ ;
191static /*@observer@*/ cstring categoryName (flagkind p_kind) /*@*/ ;
8250fa4a 192
a956d444 193static flagcode flags_identifyFlagAux (cstring p_s, bool p_quiet) /*@modifies g_msgstream@*/ ;
194
8250fa4a 195# if 0
616915dd 196static /*@unused@*/ cstring listModes (void) /*@*/ ;
8250fa4a 197# endif
616915dd 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
224/*
225** Internal consistency check on the flags.
226*/
227
228void flags_initMod ()
229{
230 allFlagCodes (code)
231 {
232 /*@+enumint@*/
233 if (flags[code].code != code)
234 {
28bf4b0b 235 fprintf (stderr,
236 "*** ERROR: inconsistent flag %s / %d / %d",
237 flags[code].flag,
238 flags[code].code, code);
239
616915dd 240 llbug (message ("*** ERROR: inconsistent flag %s / %d / %d",
241 cstring_fromChars (flags[code].flag),
242 flags[code].code, code));
243 }
244 /*@=enumint@*/
245 } end_allFlagCodes;
246}
247
248void
249summarizeErrors ()
250{
251 bool hadOne = FALSE;
252 int sumrep = 0;
253 int sumsup = 0;
254
255 char *buf = mstring_create (128);
256
257 allFlags (f)
258 {
259 if (f.nreported > 0 || f.nsuppressed > 0)
260 {
261 int nrep = f.nreported;
262 int nsup = f.nsuppressed;
263 cstring fs = cstring_fill (cstring_fromChars (f.flag), 23);
264
265 if (!hadOne)
266 {
267 llmsgplain (cstring_makeLiteral
268 ("\nError Type Reported Suppressed\n"
269 "=================== ======== ========="));
270 hadOne = TRUE;
271 }
272
273 sprintf (buf, "%s%7d %9d", cstring_toCharsSafe (fs), nrep, nsup);
274
275 sumrep += nrep;
276 sumsup += nsup;
277
278 cstring_free (fs);
279 llmsg (cstring_copy (cstring_fromChars (buf)));
280 }
281 } end_allFlags;
282
283 if (hadOne)
284 {
285 cstring ts = cstring_fill (cstring_makeLiteralTemp ("Total"), 23);
286
287 llmsglit (" ======== =========");
288
289 sprintf (buf, "%s%7d %9d", cstring_toCharsSafe (ts), sumrep, sumsup);
290 cstring_free (ts);
291 llmsgplain (cstring_copy (cstring_fromChars (buf)));
292 }
293
294 sfree (buf);
295}
296
297/*@+enumindex@*/
298
299void
300flagcode_recordError (flagcode f)
301{
302 if (f != INVALID_FLAG)
303 {
304 if (f == FLG_WARNFLAGS)
305 {
306 ; /* don't count these */
307 }
308 else
309 {
86d93ed3 310 /*drl bee: ec*/
311 /*drl bee: ec*/
616915dd 312 flags[f].nreported = flags[f].nreported + 1;
313 }
314 }
315 else
316 {
317 llcontbug (message ("flagcode_recordError: invalid flag: %d", (int) f));
318 }
319}
320
321void
322flagcode_recordSuppressed (flagcode f)
323{
324 llassertprint (f != INVALID_FLAG, ("flagcode: %s", flagcode_unparse (f)));
325
86d93ed3 326 /*drl bee: ec*/
327 /*drl bee: ec*/ flags[f].nsuppressed = flags[f].nsuppressed + 1;
616915dd 328}
329
330int
331flagcode_numReported (flagcode f)
332{
333 llassert (f != INVALID_FLAG);
334
335 return (flags[f].nreported);
336}
337
338/*@observer@*/ cstring
339flagcodeHint (flagcode f)
340{
341 llassert (f != INVALID_FLAG);
342
86d93ed3 343 /*drl bee: ec*/
616915dd 344 if (mstring_isDefined (flags[f].hint))
345 {
346 return (cstring_fromChars (flags[f].hint));
347 }
348 else
349 {
350 return (cstring_fromChars (flags[f].desc));
351 }
352}
353
354static int categorySize (flagkind kind) /*@*/
355{
356 int n = 0;
357
358
359 allFlags (f)
360 {
361 if (f.main == kind || f.sub == kind)
362 {
363 n++;
364 }
365 } end_allFlags;
366
367 return n;
368}
369
370flagkind identifyCategory (cstring s)
371{
372 int i;
373
374 for (i = 0; categories[i].kind != FK_NONE; i++)
375 {
86d93ed3 376 /*drl bee: mRug*/
616915dd 377 if (mstring_isDefined (categories[i].name))
378 {
379 if (cstring_equalLit (s, categories[i].name))
380 {
381 return categories[i].kind;
382 }
383 }
384 }
385
386 return FK_NONE;
387}
388
389static /*@observer@*/ cstring categoryName (flagkind kind)
390{
391 int i;
392
393 for (i = 0; categories[i].kind != FK_NONE; i++)
394 {
86d93ed3 395 /*drl bee: mrUg*/
616915dd 396 if (categories[i].kind == kind)
397 {
398 return (cstring_fromChars (categories[i].name));
399 }
400 }
401
402 return (cstring_makeLiteralTemp ("<No Category>"));
403}
404
405static int categoryIndex (flagkind kind)
406{
407 int i;
408
409 for (i = 0; categories[i].kind != FK_NONE; i++)
410 {
86d93ed3 411 /*drl bee: mRug*/
616915dd 412 if (categories[i].kind == kind)
413 {
414 return i;
415 }
416 }
417
418 return -1;
419}
420
421void printCategory (flagkind kind)
422{
423 int index = categoryIndex (kind);
424
425 llassert (index >= 0);
86d93ed3 426 /*drl bee: mRug*/
616915dd 427 llmsg (message ("%s (%d flags)\n\3%s\n\n",
428 cstring_fromChars (categories[index].name),
429 categorySize (kind),
430 cstring_fromChars (categories[index].describe)));
431
432 allFlags (f)
433 {
434 if (f.main == kind || f.sub == kind)
435 {
436 llmsg (message (" %s\n\6%q", cstring_fromChars (f.flag),
437 describeFlagCode (f.code)));
438 }
439 } end_allFlags;
440}
441
442void
443listAllCategories (void)
444{
445 int i;
446
447 for (i = 0; categories[i].kind != FK_NONE; i++)
448 {
86d93ed3 449 /*drl bee: mRug*/
616915dd 450 flagkind kind = categories[i].kind ;
451
452 if (categories[i].describe != NULL)
453 {
454 llmsg (message ("%s (%d flags)\n\3%s",
455 categoryName (kind),
456 categorySize (kind),
457 cstring_fromChars (categories[i].describe)));
458 }
459 }
460}
461
462void
463printAllFlags (bool desc, bool full)
464{
465 if (full)
466 {
467 cstringSList fl = sortedFlags ();
468
469 cstringSList_elements (fl, el)
470 {
471 llmsg (message ("%q\n\n", describeFlag (el)));
472 } end_cstringSList_elements ;
473
474 cstringSList_free (fl);
475 }
476 else
477 {
478 allFlags (f)
479 {
480 if (f.code != INVALID_FLAG && f.main != FK_OBSOLETE)
481 {
482 if (mstring_isDefined (f.desc))
483 {
484 if (desc)
485 {
486 llmsg (message ("%s --- %s", cstring_fromChars (f.flag),
487 cstring_fromChars (f.desc)));
488 }
489 }
490 }
491 } end_allFlags;
492 }
493}
494
4f43223c 495void
45569d72 496printFlagManual (bool html)
4f43223c 497{
498 /*
499 ** Prints all flags by category, in order they appear in flags.def
500 */
501
502 flagkind lastCategory = FK_NONE;
503
504 allFlags (f) {
505 cstring flagname;
506 cstring flagtype = cstring_undefined;
507
508 if (f.main != lastCategory)
509 {
45569d72 510 if (html)
511 {
512 llmsg (message ("\n<h4>%s</h4>\n", categoryName (f.main)));
513 }
514 else
515 {
516 llmsg (message ("\n%s\n%s\n",
517 categoryName (f.main),
518 cstring_makeLiteralTemp ("===================================")));
519 }
4f43223c 520
521 lastCategory = f.main;
522 }
523
524 if (f.argtype == ARG_NONE || f.argtype == ARG_SPECIAL)
525 {
45569d72 526 if (html)
527 {
528 flagname = message ("<tt>%s</tt>", cstring_fromChars (f.flag));
529 }
530 else
531 {
532 flagname = cstring_fromCharsNew (f.flag);
533 }
4f43223c 534 }
535 else
536 {
537 if (flagcode_hasString (f.code))
538 {
45569d72 539 if (html)
540 {
541 flagname = message ("<tt>%s <em>&lt;%s&gt;</em></tt>",
542 cstring_fromChars (f.flag), argcode_unparse (f.argtype));
543 }
544 else
545 {
546 flagname = message ("%s <%s>", cstring_fromChars (f.flag), argcode_unparse (f.argtype));
547 }
548
982cc10b 549 if (cstring_isDefined (context_getString (f.code)))
550 {
45569d72 551 if (html)
552 {
553 flagname = message ("%q <font color=\"blue\">[%s]</font>", flagname,
554 context_getString (f.code));
555 }
556 else
557 {
558 flagname = message ("%q [%s]", flagname,
559 context_getString (f.code));
560 }
982cc10b 561 }
4f43223c 562 }
563 else if (f.argtype == ARG_CHAR)
564 {
45569d72 565 if (html)
566 {
567 flagname = message ("<tt>%s <em>&lt;%s&gt;</em></tt> <font color=\"blue\">[%c]</font>",
568 cstring_fromChars (f.flag), argcode_unparse (f.argtype),
569 (char) context_getValue (f.code));
570 }
571 else
572 {
573 flagname = message ("%s <%s> [%c]", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
574 (char) context_getValue (f.code));
575 }
4f43223c 576 }
577 else
578 {
579 llassert (f.argtype == ARG_NUMBER);
45569d72 580
581 if (html)
582 {
583 flagname = message ("<tt>%s <em>&lt;%s&gt;</em> <font color=\"blue\">[%d]</font>",
584 cstring_fromChars (f.flag), argcode_unparse (f.argtype),
585 context_getValue (f.code));
586 }
587 else
588 {
589 flagname = message ("%s <%s> [%d]", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
590 context_getValue (f.code));
591 }
4f43223c 592 }
593 }
594
595 if (f.isIdem)
596 {
45569d72 597 if (html)
598 {
599 flagtype = message("%q<font color=\"green\">-</font>", flagtype);
600 }
601 else
602 {
603 flagtype = message("%q<->", flagtype);
604 }
4f43223c 605 }
4f43223c 606
607 if (f.isGlobal)
608 {
45569d72 609 if (html)
610 {
611 flagtype = message ("%q<font color=\"green\"><em>global</em></font>", flagtype);
612 }
613 else
614 {
615 flagtype = message ("%q<G>", flagtype);
616 }
4f43223c 617 }
618
619 if (f.isSpecial)
620 {
45569d72 621 if (html)
622 {
623 flagtype = message ("%q<font color=\"orange\"><em>shortcut</em></font>", flagtype);
624 }
625 else
626 {
627 flagtype = message("%q<S>", flagtype);
628 }
4f43223c 629 }
630
631 if (f.isModeFlag)
632 {
45569d72 633 if (html)
634 {
635 flagtype = message ("%q mode:<tt>%q</tt>>", flagtype, getFlagModeSettings (f.code));
636 }
637 else
638 {
639 flagtype = message ("%q<M:%q>", flagtype, getFlagModeSettings (f.code));
640 }
4f43223c 641 }
642 else /* its a plain flag */
643 {
45569d72 644 if (html)
645 {
646 flagtype = message ("%q plain:<tt>%s</tt>", flagtype,
647 cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-"));
648 }
649 else
650 {
651 flagtype = message ("%q<P:%s>", flagtype,
652 cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-"));
653 }
4f43223c 654 }
bb7c2085 655
4f43223c 656 llmsg (message ("%s: %s", flagname, flagtype));
bb7c2085 657
45569d72 658 if (html)
659 {
660 llgenindentmsgnoloc (cstring_makeLiteral ("<blockquote>"));
661 }
662
bb7c2085 663 if (mstring_isDefined (f.hint))
664 {
665 llgenindentmsgnoloc (cstring_fromCharsNew (f.hint));
666 }
667 else
668 {
669 llgenindentmsgnoloc (message ("%q.", cstring_capitalize (cstring_fromChars (f.desc))));
670 }
45569d72 671
672 if (html)
673 {
674 llgenindentmsgnoloc (cstring_makeLiteral ("</blockquote>"));
675 }
4f43223c 676 } end_allFlags ;
677}
678
616915dd 679cstring
680describeFlagCode (flagcode flag)
681{
682 cstring ret = cstring_undefined;
683 fflag f;
4f43223c 684
616915dd 685 if (flagcode_isInvalid (flag))
686 {
687 return (cstring_makeLiteral ("<invalid>"));
688 }
689
690 context_resetAllFlags ();
691
86d93ed3 692 /*drl bee: mRug*/
616915dd 693 f = flags[flag];
694 ret = cstring_copy (cstring_fromChars (f.desc));
616915dd 695
696 if (f.sub != FK_NONE)
697 {
698 ret = message ("%q\nCategories: %s, %s",
699 ret,
700 categoryName (f.main),
701 categoryName (f.sub));
702 }
703 else
704 {
705 if (f.main != FK_NONE)
706 {
707 cstring cname = categoryName (f.main);
708
709 if (cstring_isDefined (cname))
710 {
711 ret = message ("%q\nCategory: %s",
712 ret, cname);
713 }
714 }
715 }
4f43223c 716
616915dd 717 if (f.isModeFlag)
718 {
4f43223c 719 ret = message ("%q\nMode Settings: %q",
720 ret, getFlagModeSettings (flag));
616915dd 721 }
722 else
723 {
724 ret = message ("%q\nDefault Setting: %s",
725 ret,
4f43223c 726 cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
616915dd 727 }
4f43223c 728
616915dd 729 if (f.isGlobal)
730 {
731 ret = message("%q\nSet globally only", ret);
732 }
733 else
734 {
735 ret = message("%q\nSet locally", ret);
736 }
4f43223c 737
616915dd 738 switch (f.argtype)
739 {
740 case ARG_NONE:
741 case ARG_SPECIAL:
742 break;
4f43223c 743 case ARG_NUMBER:
744 ret = message("%q\nNumeric Argument. Default: %d",
745 ret,
746 context_getValue (flag));
747 break;
748 case ARG_CHAR:
749 ret = message("%q\nCharacter Argument. Default: %h",
750 ret, (char) context_getValue (flag));
616915dd 751 break;
752 case ARG_STRING:
4f43223c 753 case ARG_FILE:
754 case ARG_PATH:
755 case ARG_DIRECTORY:
756 {
616915dd 757 if (cstring_isDefined (context_getString (flag)))
758 {
4f43223c 759 ret = message("%q\n%q argument. Default: %s",
616915dd 760 ret,
4f43223c 761 cstring_capitalize (argcode_unparse (f.argtype)),
616915dd 762 context_getString (flag));
763 }
764 else
765 {
4f43223c 766 ret = message("%q\n%s argument. No default.",
767 ret,
768 cstring_capitalize (argcode_unparse (f.argtype)));
616915dd 769 }
770 break;
4f43223c 771 }
616915dd 772 }
4f43223c 773
616915dd 774 if (mstring_isDefined (f.hint))
775 {
776 ret = message("%q\n\3%s", ret, cstring_fromChars (f.hint));
777 }
4f43223c 778
616915dd 779 return ret;
780}
4f43223c 781
782static cstring getFlagModeSettings (flagcode flag)
783{
784 cstring res = cstring_undefined;
785
786 allModes (mname)
787 {
982cc10b 788 context_setModeNoWarn (cstring_fromChars (mname));
4f43223c 789
790 res = message ("%q%s", res, cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
791 } end_allModes;
792
793 return res;
794}
616915dd 795
796cstring
797describeFlag (cstring flagname)
798{
799 cstring oflagname = cstring_copy (flagname);
a956d444 800 flagcode f = flags_identifyFlag (flagname);
616915dd 801
802 if (flagcode_isSkip (f))
803 {
804 cstring_free (oflagname);
805 return cstring_undefined;
806 }
807 else if (flagcode_isValid (f))
808 {
809 if (cstring_equal (flagname, oflagname))
810 {
811 cstring_free (oflagname);
812 return (message ("%s\n\3%q", flagname, describeFlagCode (f)));
813 }
814 else
815 {
816 return (message ("%q (standardized name: %s)\n\3%q",
817 oflagname, flagname, describeFlagCode (f)));
818 }
819 }
820 else
821 {
822 if (isMode (flagname))
823 {
824 cstring_free (oflagname);
825
826 return
4f43223c 827 (message ("%s: predefined mode (see Manual for information)",
616915dd 828 flagname));
829 }
830 else
831 {
832 return (message ("%q: <invalid flag>", oflagname));
833 }
834 }
835}
836
837static cstringSList
838sortedFlags (void)
839{
840 cstringSList s = cstringSList_new ();
841
842 allFlags (f)
843 {
844 if (f.desc != NULL)
845 {
846 s = cstringSList_add (s, cstring_fromChars (f.flag));
847 }
848 } end_allFlags;
849
850 cstringSList_alphabetize (s);
851
852 return s;
853}
854
855void printAlphaFlags ()
856{
857 cstringSList fl = sortedFlags ();
858
859 cstringSList_printSpaced (fl, 3, 1, context_getLineLen () - 25);
860 cstringSList_free (fl);
861}
28bf4b0b 862
616915dd 863/*@observer@*/ cstring
28bf4b0b 864flagcode_unparse (flagcode code)
616915dd 865{
7272a1c1 866 if (code == INVALID_FLAG)
867 {
868 return cstring_makeLiteralTemp ("<invalid flag>");
869 }
870
616915dd 871 return cstring_fromChars (flags[code].flag);
872}
873
874/*
875** Transforms a flag into its cannonical form.
876**
877** The following transformations are made:
878**
879** function -> fcn
880** variable -> var
881** constant -> const
882** iterator -> iter
883** parameter -> param
884** unrecognized -> unrecog
885** qualifier -> qual
886** declaration -> decl
887** globalias -> (no change)
888** global -> glob
889** modifies -> mods
890** modify -> mod
891** pointer -> ptr
892** implies -> imp
893** implicit -> imp
894** implied -> imp
895** unconstrained -> unspec
896** unconst -> unspec
897** memory -> mem
898** length -> len
899*/
900
901static void
902canonicalizeFlag (cstring s)
903{
904 int i = 0;
905 static bn_mstring transform[] =
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 "globals", "globs",
916 "modifies", "mods",
917 "modify", "mod",
918 "pointer", "ptr",
919 "implies", "imp",
920 "implicit", "imp",
921 "implied", "imp",
922 "unconstrained", "uncon",
923 "unconst", "uncon",
924 "memory", "mem",
925 "length", "len",
926 "return", "ret",
927 "system", "sys",
928 NULL
929 } ;
930 char *current;
86d93ed3 931
932 /*drl bee: ia*/
616915dd 933 while ((current = transform[i]) != NULL)
934 {
935 if (cstring_containsLit (s, current))
936 {
937 cstring_replaceLit (s, current, transform[i+1]);
938 }
939 i += 2;
940 }
941
942 /* remove whitespace, -'s, and _'s */
943 cstring_stripChars (s, " -_");
944}
945
946flagcode
a956d444 947flags_identifyFlag (cstring s)
948{
949 return flags_identifyFlagAux (s, FALSE);
950}
951
952flagcode
953flags_identifyFlagQuiet (cstring s)
954{
955 return flags_identifyFlagAux (s, TRUE);
956}
957
958static flagcode
959flags_identifyFlagAux (cstring s, bool quiet)
616915dd 960{
961 if (cstring_length (s) == 0) {
962 /* evs 2000-06-25: A malformed flag. */
963 return INVALID_FLAG;
964 }
965
966 if (cstring_firstChar (s) == 'I')
967 {
968 return FLG_INCLUDEPATH; /* no space after -I */
969 }
970
971 if (cstring_firstChar (s) == 'S')
972 {
973 return FLG_SPECPATH; /* no space after -S */
974 }
975
976 if (cstring_firstChar (s) == 'D')
977 {
978 return FLG_DEFINE; /* no space after -D */
979 }
980
981 if (cstring_firstChar (s) == 'U')
982 {
983 return FLG_UNDEFINE; /* no space after -D */
984 }
985
986 canonicalizeFlag (s);
987
988 allFlags (f)
989 {
990 if (cstring_equal (cstring_fromChars (f.flag), s))
991 {
992 return (f.code);
993 }
994 } end_allFlags;
995
996 /*
997 ** Synonyms
998 */
999
1000 if (cstring_equalLit (s, "pred"))
1001 {
1002 return FLG_PREDBOOL;
1003 }
1004
1005 if (cstring_equalLit (s, "modobserverstrict"))
1006 {
1007 return FLG_MODOBSERVERUNCON;
1008 }
1009
1010 if (cstring_equalLit (s, "czechnames"))
1011 {
1012 return FLG_CZECH;
1013 }
1014
1015 if (cstring_equalLit (s, "slovaknames"))
1016 {
1017 return FLG_SLOVAK;
1018 }
1019
1020 if (cstring_equalLit (s, "czechoslovaknames"))
1021 {
1022 return FLG_CZECHOSLOVAK;
1023 }
1024
1025 if (cstring_equalLit (s, "globunspec")
1026 || cstring_equalLit (s, "globuncon"))
1027 {
1028 return FLG_GLOBUNSPEC;
1029 }
1030
1031 if (cstring_equalLit (s, "modglobsunspec")
1032 || cstring_equalLit (s, "modglobsuncon")
1033 || cstring_equalLit (s, "modglobsnomods"))
1034 {
1035 return FLG_MODGLOBSUNSPEC;
1036 }
1037
1038 if (cstring_equalLit (s, "export"))
1039 {
1040 return FLG_EXPORTANY;
1041 }
1042
1043 if (cstring_equalLit (s, "macrospec"))
1044 {
1045 return FLG_MACRODECL;
1046 }
1047
1048 if (cstring_equalLit (s, "ansireservedlocal"))
1049 {
1050 return FLG_ANSIRESERVEDLOCAL;
1051 }
1052
1053 if (cstring_equalLit (s, "warnposix"))
1054 {
1055 return FLG_WARNPOSIX;
1056 }
1057
1058 if (cstring_equalLit (s, "defuse"))
1059 {
1060 return FLG_USEDEF;
1061 }
1062
1063 if (cstring_equalLit (s, "macroundef"))
1064 {
1065 return FLG_MACROUNDEF;
1066 }
1067
1068 if (cstring_equalLit (s, "showcol"))
1069 {
1070 return FLG_SHOWCOL;
1071 }
1072
1073 if (cstring_equalLit (s, "intbool"))
1074 {
1075 return FLG_BOOLINT;
1076 }
1077
1078 if (cstring_equalLit (s, "intchar"))
1079 {
1080 return FLG_CHARINT;
1081 }
1082
1083 if (cstring_equalLit (s, "intenum"))
1084 {
1085 return FLG_ENUMINT;
1086 }
1087
1088 /*
27c9e640 1089 ** Backwards compatibility for our American friends...
616915dd 1090 */
1091
27c9e640 1092 if (cstring_equalLit (s, "ansilib"))
616915dd 1093 {
1094 return FLG_ANSILIB;
1095 }
1096
616915dd 1097 if (cstring_equalLit (s, "ansistrictlib"))
1098 {
1099 return FLG_STRICTLIB;
1100 }
1101
27c9e640 1102 if (cstring_equalLit (s, "skipansiheaders"))
616915dd 1103 {
1104 return FLG_SKIPANSIHEADERS;
1105 }
1106
27c9e640 1107 if (cstring_equalLit (s, "ansireserved"))
616915dd 1108 {
1109 return FLG_ANSIRESERVED;
1110 }
1111
27c9e640 1112 if (cstring_equalLit (s, "ansireservedinternal"))
616915dd 1113 {
1114 return FLG_ANSIRESERVEDLOCAL;
1115 }
1116
616915dd 1117 /*
1118 ** Obsolete Flags
1119 */
1120
1121 if (cstring_equalLit (s, "accessunspec"))
1122 {
a956d444 1123 if (!quiet)
1124 {
1125 llerror_flagWarning
1126 (cstring_makeLiteral
1127 ("accessunspec flag is no longer supported. It has been replaced by accessmodule, accessfile and "
1128 "accessfunction to provide more precise control of accessibility "
1129 "of representations. For more information, "
1b8ae690 1130 "see splint -help accessmodule"));
a956d444 1131 }
616915dd 1132
27c9e640 1133 return SKIP_FLAG;
1134 }
1135 else if (cstring_equalLit (s, "ansilimits"))
1136 {
1137 llerror_flagWarning
1138 (cstring_makeLiteral
1139 ("ansilimits flag is no longer supported. It has been replaced by ansi89limits and "
1140 "iso99limits to select either the lower translation limits imposed by the ANSI89 "
1141 "standard or the typically higher limits prescribed by ISO C99."));
1142
616915dd 1143 return SKIP_FLAG;
1144 }
a956d444 1145 else if (cstring_equalLit (s, "staticmods"))
1146 {
1147 if (!quiet)
1148 {
1149 llerror_flagWarning
1150 (cstring_makeLiteral
1151 ("staticmods flag is obsolete. You probably "
1152 "want impcheckmodstatics. For more information, "
1b8ae690 1153 "see splint -help impcheckmodstatics"));
a956d444 1154 }
616915dd 1155
a956d444 1156 return SKIP_FLAG;
1157 }
1158 else if (cstring_equalLit (s, "bool"))
616915dd 1159 {
a956d444 1160 if (!quiet)
1161 {
1162 llerror_flagWarning
1163 (cstring_makeLiteral ("bool flag is obsolete. It never really "
1164 "made sense in the first place."));
1165 }
616915dd 1166
1167 return SKIP_FLAG;
1168 }
a956d444 1169 else if (cstring_equalLit (s, "shiftsigned"))
616915dd 1170 {
a956d444 1171 if (!quiet)
1172 {
1173 llerror_flagWarning
1174 (cstring_makeLiteral ("shiftsigned flag is obsolete. You probably "
1175 "want bitwisesigned, shiftnegative or shiftsize."));
1176 }
616915dd 1177
1178 return SKIP_FLAG;
1179 }
a956d444 1180 else if (cstring_equalLit (s, "ansi"))
616915dd 1181 {
a956d444 1182 if (!quiet)
1183 {
1184 llerror_flagWarning
1185 (cstring_makeLiteral ("ansi flag is obsolete. You probably "
1186 "want noparams and/or oldstyle."));
1187 }
616915dd 1188
1189 return SKIP_FLAG;
1190 }
a956d444 1191 else if (cstring_equalLit (s, "stdio"))
1192 {
1193 if (!quiet)
1194 {
1195 llerror_flagWarning
1196 (cstring_makeLiteral
1197 ("stdio flag is obsolete. You may "
1198 "want strictlib or one of the gloabls "
1199 "checking flags. For more information, "
1b8ae690 1200 "see splint -help strictlib or splint -help flags globals"));
a956d444 1201 }
616915dd 1202
1203 return SKIP_FLAG;
1204 }
a956d444 1205 else
1206 {
1207 return INVALID_FLAG;
1208 }
616915dd 1209}
1210
1211void setValueFlag (flagcode opt, cstring arg)
1212{
1213 switch (opt)
1214 {
1215 case FLG_EXPECT:
1216 case FLG_LCLEXPECT:
1217 case FLG_LIMIT:
1218 case FLG_LINELEN:
28bf4b0b 1219 case FLG_INDENTSPACES:
1220 case FLG_BUGSLIMIT:
616915dd 1221 case FLG_EXTERNALNAMELEN:
1222 case FLG_INTERNALNAMELEN:
1223 case FLG_CONTROLNESTDEPTH:
1224 case FLG_STRINGLITERALLEN:
1225 case FLG_NUMSTRUCTFIELDS:
1226 case FLG_NUMENUMMEMBERS:
1227 case FLG_INCLUDENEST:
1228 {
1229 int val = cstring_toPosInt (arg);
1230
1231 if (val < 0)
1232 {
1233 llerror
1234 (FLG_BADFLAG,
1235 message
1236 ("Flag %s must be followed by a positive number number. "
1237 "Followed by %s",
1238 flagcode_unparse (opt), arg));
1239 }
1240 else
1241 {
28bf4b0b 1242 context_setValueAndFlag (opt, val);
616915dd 1243 }
1244 }
1245 break;
1246 case FLG_COMMENTCHAR:
1247 {
1248 if (cstring_length (arg) != 1)
1249 {
1250 llfatalerrorLoc
1251 (message
1252 ("Flag %s should be followed by a single character. Followed by %s",
1253 flagcode_unparse (opt), arg));
1254 }
1255 else
1256 {
1257 context_setCommentMarkerChar (cstring_firstChar (arg));
1258 }
1259 }
1260 break;
1261 BADDEFAULT;
1262 }
1263}
1264
1265void setStringFlag (flagcode opt, /*@only@*/ cstring arg)
1266{
1267 switch (opt)
1268 {
1269 case FLG_TMPDIR:
1270 {
1271 if (cstring_lastChar (arg) == CONNECTCHAR)
1272 {
1273 context_setString (opt, arg);
1274 }
1275 else
1276 {
1277 context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1278 }
1279 break;
1280 }
1281 default:
1282 {
1283 context_setString (opt, arg);
1284 break;
1285 }
1286 }
1287}
1288
1289cstring
1290describeModes ()
1291{
1292 cstring s = cstring_makeLiteral ("Flag ");
1293 cstringSList sflags = sortedFlags ();
1294
1295 allModes (modename)
1296 {
1297 s = message ("%q%9s", s, cstring_fromChars (modename));
1298 } end_allModes;
1299
1300 s = message ("%q\n", s);
1301
1302 cstringSList_elements (sflags, flagname)
1303 {
a956d444 1304 flagcode code = flags_identifyFlag (flagname);
616915dd 1305 fflag currentflag = flags[code];
1306
1307 if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1308 {
1309 s = message ("%q\n%27s", s,
1310 cstring_fromChars (currentflag.flag));
1311
1312 allModes (modename)
1313 {
1314 context_setMode (cstring_fromChars (modename));
1315
1316 if (context_getFlag (code))
1317 {
1318 s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1319 }
1320 else
1321 {
1322 s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1323 }
1324
1325 context_resetModeFlags ();
1326 } end_allModes;
1327 }
1328 } end_cstringSList_elements;
1329
1330 cstringSList_free (sflags);
1331
1332 s = cstring_appendChar (s, '\n');
1333
1334 return (s);
1335}
1336
8250fa4a 1337# if 0
ee229125 1338static /*@unused@*/ cstring
616915dd 1339listModes (void)
1340{
1341 cstring s = cstring_makeLiteral ("\t");
1342 int i = 0;
1343
1344 allModes (modename)
1345 {
1346 if (i != 0 && (i % 4 == 0))
1347 {
1348 s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1349 }
1350 else
1351 {
1352 s = message ("%q%15s", s, cstring_fromChars (modename));
1353 }
1354 i++;
1355 } end_allModes;
1356
1357 return s;
1358}
8250fa4a 1359# endif
616915dd 1360
1361bool
1362isMode (cstring s)
1363{
1364 allModes (modename)
1365 {
1366 if (mstring_isDefined (modename))
1367 {
1368 if (cstring_equalLit (s, modename))
1369 {
1370 return TRUE;
1371 }
1372 }
1373 } end_allModes;
1374
1375 return FALSE;
1376}
1377
1378extern bool flagcode_hasArgument (flagcode f)
1379{
1380 return (flags[f].argtype != ARG_NONE);
1381}
1382
4f43223c 1383extern bool flagcode_hasNumber (flagcode f)
1384{
1385 return (flags[f].argtype == ARG_NUMBER);
1386}
1387
1388extern bool flagcode_hasChar (flagcode f)
616915dd 1389{
4f43223c 1390 return (flags[f].argtype == ARG_CHAR);
616915dd 1391}
1392
1393extern bool flagcode_hasString (flagcode f)
1394{
4f43223c 1395 return (flags[f].argtype == ARG_STRING
1396 || flags[f].argtype == ARG_FILE
1397 || flags[f].argtype == ARG_DIRECTORY
1398 || flags[f].argtype == ARG_PATH);
616915dd 1399}
1400
1401extern int flagcode_valueIndex (flagcode f)
1402{
1403 /*@unchecked@*/ static bool initialized = FALSE;
1404 int i;
1405 /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
616915dd 1406
1407 if (!initialized)
1408 {
1409 int nv = 0;
1410
1411 allFlagCodes (code)
1412 {
4f43223c 1413 if (flagcode_hasNumber (code) || flagcode_hasChar (code))
616915dd 1414 {
1415 llassert (nv < NUMVALUEFLAGS);
28bf4b0b 1416 DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
616915dd 1417 valueFlags[nv] = code;
28bf4b0b 1418 nv++;
616915dd 1419 }
1420 } end_allFlagCodes;
1421
1422 llassertprint (nv == NUMVALUEFLAGS,
28bf4b0b 1423 ("Number of value flags: %d (expected %d)",
1424 nv, (int) NUMVALUEFLAGS));
616915dd 1425 initialized = TRUE;
1426 }
1427
1428 for (i = 0; i < NUMVALUEFLAGS; i++)
1429 {
1430 /* static valueFlags must be defined */
86d93ed3 1431 /*@-usedef@*/
1432 /*drl bee: sta*/
1433 if (f == valueFlags[i]) /*@=usedef@*/
616915dd 1434 {
1435 return i;
1436 }
1437 }
1438
28bf4b0b 1439 fprintf (stderr, "Cannot find value flag: %d", (int) f);
1440 exit (EXIT_FAILURE);
1441 /* Cannot do this...might call recursively...
1442 llfatalbug (message ("Cannot fine value flag: %d", (int) f));
616915dd 1443 BADEXIT;
28bf4b0b 1444 */
616915dd 1445}
1446
1447extern int flagcode_stringIndex (flagcode f)
1448{
1449 /*@unchecked@*/ static bool initialized = FALSE;
1450 /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1451 int i;
1452
1453
1454 if (!initialized)
1455 {
1456 int nv = 0;
1457
1458 allFlagCodes (code)
1459 {
1460 if (flagcode_hasString (code))
1461 {
1462 llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1463 stringFlags[nv] = code;
1464 nv++;
1465 }
1466 } end_allFlagCodes;
1467
1468 llassertprint (nv == NUMSTRINGFLAGS,
1469 ("number of string flags: %d (expected %d)",
1470 nv, NUMSTRINGFLAGS));
1471 initialized = TRUE;
1472 }
1473
1474 for (i = 0; i < NUMSTRINGFLAGS; i++)
1475 {
86d93ed3 1476 /*drl bee: sta*/
616915dd 1477 /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1478 {
1479 return i;
1480 }
1481 }
1482
1483 llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1484 BADEXIT;
1485}
1486
1487bool flagcode_isNamePrefixFlag (flagcode f)
1488{
1489 switch (f)
1490 {
1491 case FLG_MACROVARPREFIX:
1492 case FLG_TAGPREFIX:
1493 case FLG_ENUMPREFIX:
1494 case FLG_FILESTATICPREFIX:
1495 case FLG_GLOBPREFIX:
1496 case FLG_TYPEPREFIX:
1497 case FLG_EXTERNALPREFIX:
1498 case FLG_LOCALPREFIX:
1499 case FLG_UNCHECKEDMACROPREFIX:
1500 case FLG_CONSTPREFIX:
1501 case FLG_ITERPREFIX:
1502 case FLG_DECLPARAMPREFIX:
1503 return TRUE;
1504 default:
1505 return FALSE;
1506 }
1507}
1508
This page took 0.290527 seconds and 5 git commands to generate.