]> andersk Git - splint.git/blame - src/flags.c
Fixed line numbering when multi-line macro parameters are used.
[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**
155af98d 20** For information on splint: info@splint.org
21** To report a bug: splint-bug@splint.org
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 {
6b654b9a 471 /*@i22@*/ /*find out why this is necessary*/
472 cstring tmp;
473 tmp = cstring_copy(el);
474 llmsg (message ("%q\n\n", describeFlag (tmp)));
475 cstring_free(tmp);
616915dd 476 } end_cstringSList_elements ;
477
478 cstringSList_free (fl);
479 }
480 else
481 {
482 allFlags (f)
483 {
484 if (f.code != INVALID_FLAG && f.main != FK_OBSOLETE)
485 {
486 if (mstring_isDefined (f.desc))
487 {
488 if (desc)
489 {
490 llmsg (message ("%s --- %s", cstring_fromChars (f.flag),
491 cstring_fromChars (f.desc)));
492 }
493 }
494 }
495 } end_allFlags;
496 }
497}
498
4f43223c 499void
45569d72 500printFlagManual (bool html)
4f43223c 501{
502 /*
503 ** Prints all flags by category, in order they appear in flags.def
504 */
505
506 flagkind lastCategory = FK_NONE;
507
508 allFlags (f) {
509 cstring flagname;
510 cstring flagtype = cstring_undefined;
511
512 if (f.main != lastCategory)
513 {
45569d72 514 if (html)
515 {
516 llmsg (message ("\n<h4>%s</h4>\n", categoryName (f.main)));
517 }
518 else
519 {
520 llmsg (message ("\n%s\n%s\n",
521 categoryName (f.main),
522 cstring_makeLiteralTemp ("===================================")));
523 }
4f43223c 524
525 lastCategory = f.main;
526 }
527
528 if (f.argtype == ARG_NONE || f.argtype == ARG_SPECIAL)
529 {
45569d72 530 if (html)
531 {
532 flagname = message ("<tt>%s</tt>", cstring_fromChars (f.flag));
533 }
534 else
535 {
536 flagname = cstring_fromCharsNew (f.flag);
537 }
4f43223c 538 }
539 else
540 {
541 if (flagcode_hasString (f.code))
542 {
45569d72 543 if (html)
544 {
545 flagname = message ("<tt>%s <em>&lt;%s&gt;</em></tt>",
546 cstring_fromChars (f.flag), argcode_unparse (f.argtype));
547 }
548 else
549 {
550 flagname = message ("%s <%s>", cstring_fromChars (f.flag), argcode_unparse (f.argtype));
551 }
552
982cc10b 553 if (cstring_isDefined (context_getString (f.code)))
554 {
45569d72 555 if (html)
556 {
557 flagname = message ("%q <font color=\"blue\">[%s]</font>", flagname,
558 context_getString (f.code));
559 }
560 else
561 {
562 flagname = message ("%q [%s]", flagname,
563 context_getString (f.code));
564 }
982cc10b 565 }
4f43223c 566 }
567 else if (f.argtype == ARG_CHAR)
568 {
45569d72 569 if (html)
570 {
571 flagname = message ("<tt>%s <em>&lt;%s&gt;</em></tt> <font color=\"blue\">[%c]</font>",
572 cstring_fromChars (f.flag), argcode_unparse (f.argtype),
573 (char) context_getValue (f.code));
574 }
575 else
576 {
577 flagname = message ("%s <%s> [%c]", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
578 (char) context_getValue (f.code));
579 }
4f43223c 580 }
581 else
582 {
583 llassert (f.argtype == ARG_NUMBER);
45569d72 584
585 if (html)
586 {
587 flagname = message ("<tt>%s <em>&lt;%s&gt;</em> <font color=\"blue\">[%d]</font>",
588 cstring_fromChars (f.flag), argcode_unparse (f.argtype),
589 context_getValue (f.code));
590 }
591 else
592 {
593 flagname = message ("%s <%s> [%d]", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
594 context_getValue (f.code));
595 }
4f43223c 596 }
597 }
598
599 if (f.isIdem)
600 {
45569d72 601 if (html)
602 {
603 flagtype = message("%q<font color=\"green\">-</font>", flagtype);
604 }
605 else
606 {
607 flagtype = message("%q<->", flagtype);
608 }
4f43223c 609 }
4f43223c 610
611 if (f.isGlobal)
612 {
45569d72 613 if (html)
614 {
615 flagtype = message ("%q<font color=\"green\"><em>global</em></font>", flagtype);
616 }
617 else
618 {
619 flagtype = message ("%q<G>", flagtype);
620 }
4f43223c 621 }
622
623 if (f.isSpecial)
624 {
45569d72 625 if (html)
626 {
627 flagtype = message ("%q<font color=\"orange\"><em>shortcut</em></font>", flagtype);
628 }
629 else
630 {
631 flagtype = message("%q<S>", flagtype);
632 }
4f43223c 633 }
634
635 if (f.isModeFlag)
636 {
45569d72 637 if (html)
638 {
639 flagtype = message ("%q mode:<tt>%q</tt>>", flagtype, getFlagModeSettings (f.code));
640 }
641 else
642 {
643 flagtype = message ("%q<M:%q>", flagtype, getFlagModeSettings (f.code));
644 }
4f43223c 645 }
646 else /* its a plain flag */
647 {
45569d72 648 if (html)
649 {
650 flagtype = message ("%q plain:<tt>%s</tt>", flagtype,
651 cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-"));
652 }
653 else
654 {
655 flagtype = message ("%q<P:%s>", flagtype,
656 cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-"));
657 }
4f43223c 658 }
bb7c2085 659
4f43223c 660 llmsg (message ("%s: %s", flagname, flagtype));
bb7c2085 661
45569d72 662 if (html)
663 {
664 llgenindentmsgnoloc (cstring_makeLiteral ("<blockquote>"));
665 }
666
bb7c2085 667 if (mstring_isDefined (f.hint))
668 {
669 llgenindentmsgnoloc (cstring_fromCharsNew (f.hint));
670 }
671 else
672 {
673 llgenindentmsgnoloc (message ("%q.", cstring_capitalize (cstring_fromChars (f.desc))));
674 }
45569d72 675
676 if (html)
677 {
678 llgenindentmsgnoloc (cstring_makeLiteral ("</blockquote>"));
679 }
4f43223c 680 } end_allFlags ;
681}
682
616915dd 683cstring
684describeFlagCode (flagcode flag)
685{
686 cstring ret = cstring_undefined;
687 fflag f;
4f43223c 688
616915dd 689 if (flagcode_isInvalid (flag))
690 {
691 return (cstring_makeLiteral ("<invalid>"));
692 }
693
694 context_resetAllFlags ();
695
86d93ed3 696 /*drl bee: mRug*/
616915dd 697 f = flags[flag];
698 ret = cstring_copy (cstring_fromChars (f.desc));
616915dd 699
700 if (f.sub != FK_NONE)
701 {
702 ret = message ("%q\nCategories: %s, %s",
703 ret,
704 categoryName (f.main),
705 categoryName (f.sub));
706 }
707 else
708 {
709 if (f.main != FK_NONE)
710 {
711 cstring cname = categoryName (f.main);
712
713 if (cstring_isDefined (cname))
714 {
715 ret = message ("%q\nCategory: %s",
716 ret, cname);
717 }
718 }
719 }
4f43223c 720
616915dd 721 if (f.isModeFlag)
722 {
4f43223c 723 ret = message ("%q\nMode Settings: %q",
724 ret, getFlagModeSettings (flag));
616915dd 725 }
726 else
727 {
728 ret = message ("%q\nDefault Setting: %s",
729 ret,
4f43223c 730 cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
616915dd 731 }
4f43223c 732
616915dd 733 if (f.isGlobal)
734 {
735 ret = message("%q\nSet globally only", ret);
736 }
737 else
738 {
739 ret = message("%q\nSet locally", ret);
740 }
4f43223c 741
616915dd 742 switch (f.argtype)
743 {
744 case ARG_NONE:
745 case ARG_SPECIAL:
746 break;
4f43223c 747 case ARG_NUMBER:
748 ret = message("%q\nNumeric Argument. Default: %d",
749 ret,
750 context_getValue (flag));
751 break;
752 case ARG_CHAR:
753 ret = message("%q\nCharacter Argument. Default: %h",
754 ret, (char) context_getValue (flag));
616915dd 755 break;
756 case ARG_STRING:
4f43223c 757 case ARG_FILE:
758 case ARG_PATH:
759 case ARG_DIRECTORY:
760 {
616915dd 761 if (cstring_isDefined (context_getString (flag)))
762 {
4f43223c 763 ret = message("%q\n%q argument. Default: %s",
616915dd 764 ret,
4f43223c 765 cstring_capitalize (argcode_unparse (f.argtype)),
616915dd 766 context_getString (flag));
767 }
768 else
769 {
4f43223c 770 ret = message("%q\n%s argument. No default.",
771 ret,
772 cstring_capitalize (argcode_unparse (f.argtype)));
616915dd 773 }
774 break;
4f43223c 775 }
616915dd 776 }
4f43223c 777
616915dd 778 if (mstring_isDefined (f.hint))
779 {
780 ret = message("%q\n\3%s", ret, cstring_fromChars (f.hint));
781 }
4f43223c 782
616915dd 783 return ret;
784}
4f43223c 785
786static cstring getFlagModeSettings (flagcode flag)
787{
788 cstring res = cstring_undefined;
789
790 allModes (mname)
791 {
982cc10b 792 context_setModeNoWarn (cstring_fromChars (mname));
4f43223c 793
794 res = message ("%q%s", res, cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
795 } end_allModes;
796
797 return res;
798}
616915dd 799
800cstring
801describeFlag (cstring flagname)
802{
803 cstring oflagname = cstring_copy (flagname);
a956d444 804 flagcode f = flags_identifyFlag (flagname);
616915dd 805
806 if (flagcode_isSkip (f))
807 {
808 cstring_free (oflagname);
809 return cstring_undefined;
810 }
811 else if (flagcode_isValid (f))
812 {
813 if (cstring_equal (flagname, oflagname))
814 {
815 cstring_free (oflagname);
816 return (message ("%s\n\3%q", flagname, describeFlagCode (f)));
817 }
818 else
819 {
820 return (message ("%q (standardized name: %s)\n\3%q",
821 oflagname, flagname, describeFlagCode (f)));
822 }
823 }
824 else
825 {
826 if (isMode (flagname))
827 {
828 cstring_free (oflagname);
829
830 return
4f43223c 831 (message ("%s: predefined mode (see Manual for information)",
616915dd 832 flagname));
833 }
834 else
835 {
836 return (message ("%q: <invalid flag>", oflagname));
837 }
838 }
839}
840
841static cstringSList
842sortedFlags (void)
843{
844 cstringSList s = cstringSList_new ();
845
846 allFlags (f)
847 {
848 if (f.desc != NULL)
849 {
850 s = cstringSList_add (s, cstring_fromChars (f.flag));
851 }
852 } end_allFlags;
853
854 cstringSList_alphabetize (s);
855
856 return s;
857}
858
859void printAlphaFlags ()
860{
861 cstringSList fl = sortedFlags ();
862
863 cstringSList_printSpaced (fl, 3, 1, context_getLineLen () - 25);
864 cstringSList_free (fl);
865}
28bf4b0b 866
616915dd 867/*@observer@*/ cstring
28bf4b0b 868flagcode_unparse (flagcode code)
616915dd 869{
7272a1c1 870 if (code == INVALID_FLAG)
871 {
872 return cstring_makeLiteralTemp ("<invalid flag>");
873 }
874
616915dd 875 return cstring_fromChars (flags[code].flag);
876}
877
878/*
879** Transforms a flag into its cannonical form.
880**
881** The following transformations are made:
882**
883** function -> fcn
884** variable -> var
885** constant -> const
886** iterator -> iter
887** parameter -> param
888** unrecognized -> unrecog
889** qualifier -> qual
890** declaration -> decl
891** globalias -> (no change)
892** global -> glob
893** modifies -> mods
894** modify -> mod
895** pointer -> ptr
896** implies -> imp
897** implicit -> imp
898** implied -> imp
899** unconstrained -> unspec
900** unconst -> unspec
901** memory -> mem
902** length -> len
903*/
904
92b2ba2c 905static /*@only@*/ cstring
616915dd 906canonicalizeFlag (cstring s)
907{
908 int i = 0;
92b2ba2c 909 cstring res = cstring_copy (s);
616915dd 910 static bn_mstring transform[] =
911 {
912 "function", "fcn",
913 "variable", "var",
914 "constant", "const",
915 "iterator", "iter",
916 "parameter", "param",
917 "unrecognized", "unrecog",
918 "qualifier", "qual",
919 "declaration", "decl",
920 "globals", "globs",
921 "modifies", "mods",
922 "modify", "mod",
923 "pointer", "ptr",
924 "implies", "imp",
925 "implicit", "imp",
926 "implied", "imp",
927 "unconstrained", "uncon",
928 "unconst", "uncon",
929 "memory", "mem",
930 "length", "len",
931 "return", "ret",
932 "system", "sys",
933 NULL
934 } ;
935 char *current;
86d93ed3 936
937 /*drl bee: ia*/
616915dd 938 while ((current = transform[i]) != NULL)
939 {
92b2ba2c 940 if (cstring_containsLit (res, current))
616915dd 941 {
92b2ba2c 942 cstring_replaceLit (res, current, transform[i+1]);
616915dd 943 }
944 i += 2;
945 }
946
947 /* remove whitespace, -'s, and _'s */
92b2ba2c 948 cstring_stripChars (res, " -_");
949 return res;
616915dd 950}
951
952flagcode
a956d444 953flags_identifyFlag (cstring s)
954{
955 return flags_identifyFlagAux (s, FALSE);
956}
957
958flagcode
959flags_identifyFlagQuiet (cstring s)
960{
961 return flags_identifyFlagAux (s, TRUE);
962}
963
964static flagcode
965flags_identifyFlagAux (cstring s, bool quiet)
616915dd 966{
92b2ba2c 967 cstring cflag;
968 flagcode res;
969
616915dd 970 if (cstring_length (s) == 0) {
971 /* evs 2000-06-25: A malformed flag. */
972 return INVALID_FLAG;
973 }
974
975 if (cstring_firstChar (s) == 'I')
976 {
977 return FLG_INCLUDEPATH; /* no space after -I */
978 }
979
980 if (cstring_firstChar (s) == 'S')
981 {
982 return FLG_SPECPATH; /* no space after -S */
983 }
984
985 if (cstring_firstChar (s) == 'D')
986 {
987 return FLG_DEFINE; /* no space after -D */
988 }
989
990 if (cstring_firstChar (s) == 'U')
991 {
992 return FLG_UNDEFINE; /* no space after -D */
993 }
994
92b2ba2c 995 cflag = canonicalizeFlag (s);
996 res = INVALID_FLAG;
616915dd 997
998 allFlags (f)
999 {
92b2ba2c 1000 if (cstring_equal (cstring_fromChars (f.flag), cflag))
616915dd 1001 {
92b2ba2c 1002 res = f.code;
1003 break;
616915dd 1004 }
1005 } end_allFlags;
616915dd 1006
92b2ba2c 1007 if (res == INVALID_FLAG)
616915dd 1008 {
92b2ba2c 1009 /*
1010 ** Synonyms
1011 */
1012
1013 if (cstring_equalLit (cflag, "pred"))
a956d444 1014 {
92b2ba2c 1015 res = FLG_PREDBOOL;
1016 }
1017 else if (cstring_equalLit (cflag, "modobserverstrict"))
1018 {
1019 res = FLG_MODOBSERVERUNCON;
1020 }
1021 else if (cstring_equalLit (cflag, "czechnames"))
1022 {
1023 res = FLG_CZECH;
a956d444 1024 }
92b2ba2c 1025 else if (cstring_equalLit (cflag, "slovaknames"))
1026 {
1027 res = FLG_SLOVAK;
1028 }
1029 else if (cstring_equalLit (cflag, "czechoslovaknames"))
1030 {
1031 res = FLG_CZECHOSLOVAK;
1032 }
1033 else if (cstring_equalLit (cflag, "globunspec")
1034 || cstring_equalLit (cflag, "globuncon"))
1035 {
1036 res = FLG_GLOBUNSPEC;
1037 }
1038 else if (cstring_equalLit (cflag, "modglobsunspec")
1039 || cstring_equalLit (cflag, "modglobsuncon")
1040 || cstring_equalLit (cflag, "modglobsnomods"))
1041 {
1042 res = FLG_MODGLOBSUNSPEC;
1043 }
1044 else if (cstring_equalLit (cflag, "export"))
1045 {
1046 res = FLG_EXPORTANY;
1047 }
1048 else if (cstring_equalLit (cflag, "macrospec"))
1049 {
1050 res = FLG_MACRODECL;
1051 }
1052 else if (cstring_equalLit (cflag, "ansireservedlocal"))
1053 {
abd7f895 1054 res = FLG_ISORESERVEDLOCAL;
92b2ba2c 1055 }
1056 else if (cstring_equalLit (cflag, "warnposix"))
1057 {
1058 res = FLG_WARNPOSIX;
1059 }
1060 else if (cstring_equalLit (cflag, "defuse"))
1061 {
1062 res = FLG_USEDEF;
1063 }
1064 else if (cstring_equalLit (cflag, "macroundef"))
1065 {
1066 res = FLG_MACROUNDEF;
1067 }
1068 else if (cstring_equalLit (cflag, "showcol"))
1069 {
1070 res = FLG_SHOWCOL;
1071 }
1072 else if (cstring_equalLit (cflag, "intbool"))
1073 {
1074 res = FLG_BOOLINT;
1075 }
1076 else if (cstring_equalLit (cflag, "intchar"))
1077 {
1078 res = FLG_CHARINT;
1079 }
1080 else if (cstring_equalLit (cflag, "intenum"))
1081 {
1082 res = FLG_ENUMINT;
1083 }
1084 /*
1085 ** Backwards compatibility for our American friends...
1086 */
616915dd 1087
92b2ba2c 1088 else if (cstring_equalLit (cflag, "ansilib"))
1089 {
1090 res = FLG_ANSILIB;
1091 }
1092 else if (cstring_equalLit (cflag, "ansistrictlib"))
1093 {
1094 res = FLG_STRICTLIB;
1095 }
1096 else if (cstring_equalLit (cflag, "skipansiheaders"))
1097 {
abd7f895 1098 res = FLG_SKIPISOHEADERS;
92b2ba2c 1099 }
1100 else if (cstring_equalLit (cflag, "ansireserved"))
1101 {
abd7f895 1102 res = FLG_ISORESERVED;
92b2ba2c 1103 }
1104 else if (cstring_equalLit (cflag, "ansireservedinternal"))
1105 {
abd7f895 1106 res = FLG_ISORESERVEDLOCAL;
92b2ba2c 1107 }
1108
1109 /*
1110 ** Obsolete Flags
1111 */
1112
1113 else if (cstring_equalLit (cflag, "accessunspec"))
1114 {
1115 if (!quiet)
1116 {
1117 llerror_flagWarning
1118 (cstring_makeLiteral
1119 ("accessunspec flag is no longer supported. It has been replaced by accessmodule, accessfile and "
1120 "accessfunction to provide more precise control of accessibility "
1121 "of representations. For more information, "
1122 "see splint -help accessmodule"));
1123 }
1124
1125 res = SKIP_FLAG;
1126 }
1127 else if (cstring_equalLit (cflag, "ansilimits"))
1128 {
27c9e640 1129 llerror_flagWarning
1130 (cstring_makeLiteral
1131 ("ansilimits flag is no longer supported. It has been replaced by ansi89limits and "
1132 "iso99limits to select either the lower translation limits imposed by the ANSI89 "
1133 "standard or the typically higher limits prescribed by ISO C99."));
92b2ba2c 1134
1135 res = SKIP_FLAG;
1136 }
1137 else if (cstring_equalLit (cflag, "staticmods"))
a956d444 1138 {
92b2ba2c 1139 if (!quiet)
1140 {
1141 llerror_flagWarning
1142 (cstring_makeLiteral
1143 ("staticmods flag is obsolete. You probably "
1144 "want impcheckmodstatics. For more information, "
1145 "see splint -help impcheckmodstatics"));
1146 }
1147
1148 res = SKIP_FLAG;
a956d444 1149 }
92b2ba2c 1150 else if (cstring_equalLit (cflag, "bool"))
a956d444 1151 {
92b2ba2c 1152 if (!quiet)
1153 {
1154 llerror_flagWarning
1155 (cstring_makeLiteral ("bool flag is obsolete. It never really "
1156 "made sense in the first place."));
1157 }
1158
1159 res = SKIP_FLAG;
a956d444 1160 }
92b2ba2c 1161 else if (cstring_equalLit (cflag, "shiftsigned"))
a956d444 1162 {
92b2ba2c 1163 if (!quiet)
1164 {
1165 llerror_flagWarning
1166 (cstring_makeLiteral ("shiftsigned flag is obsolete. You probably "
06418c9b 1167 "want bitwisesigned, shiftnegative or shiftimplementation."));
92b2ba2c 1168 }
1169
1170 res = SKIP_FLAG;
a956d444 1171 }
92b2ba2c 1172 else if (cstring_equalLit (cflag, "ansi"))
a956d444 1173 {
92b2ba2c 1174 if (!quiet)
1175 {
1176 llerror_flagWarning
1177 (cstring_makeLiteral ("ansi flag is obsolete. You probably "
1178 "want noparams and/or oldstyle."));
1179 }
1180
1181 res = SKIP_FLAG;
a956d444 1182 }
92b2ba2c 1183 else if (cstring_equalLit (cflag, "stdio"))
a956d444 1184 {
92b2ba2c 1185 if (!quiet)
1186 {
1187 llerror_flagWarning
1188 (cstring_makeLiteral
1189 ("stdio flag is obsolete. You may "
1190 "want strictlib or one of the gloabls "
1191 "checking flags. For more information, "
1192 "see splint -help strictlib or splint -help flags globals"));
1193 }
1194
1195 res = SKIP_FLAG;
1196 }
1197 else
1198 {
1199 res = INVALID_FLAG;
a956d444 1200 }
a956d444 1201 }
92b2ba2c 1202
1203 cstring_free (cflag);
1204 return res;
616915dd 1205}
1206
1207void setValueFlag (flagcode opt, cstring arg)
1208{
1209 switch (opt)
1210 {
1211 case FLG_EXPECT:
1212 case FLG_LCLEXPECT:
1213 case FLG_LIMIT:
1214 case FLG_LINELEN:
28bf4b0b 1215 case FLG_INDENTSPACES:
1216 case FLG_BUGSLIMIT:
616915dd 1217 case FLG_EXTERNALNAMELEN:
1218 case FLG_INTERNALNAMELEN:
1219 case FLG_CONTROLNESTDEPTH:
1220 case FLG_STRINGLITERALLEN:
1221 case FLG_NUMSTRUCTFIELDS:
1222 case FLG_NUMENUMMEMBERS:
1223 case FLG_INCLUDENEST:
1224 {
1225 int val = cstring_toPosInt (arg);
1226
1227 if (val < 0)
1228 {
1229 llerror
1230 (FLG_BADFLAG,
1231 message
1232 ("Flag %s must be followed by a positive number number. "
1233 "Followed by %s",
1234 flagcode_unparse (opt), arg));
1235 }
1236 else
1237 {
28bf4b0b 1238 context_setValueAndFlag (opt, val);
616915dd 1239 }
1240 }
1241 break;
1242 case FLG_COMMENTCHAR:
1243 {
1244 if (cstring_length (arg) != 1)
1245 {
1246 llfatalerrorLoc
1247 (message
1248 ("Flag %s should be followed by a single character. Followed by %s",
1249 flagcode_unparse (opt), arg));
1250 }
1251 else
1252 {
1253 context_setCommentMarkerChar (cstring_firstChar (arg));
1254 }
1255 }
1256 break;
1257 BADDEFAULT;
1258 }
1259}
1260
1261void setStringFlag (flagcode opt, /*@only@*/ cstring arg)
1262{
1263 switch (opt)
1264 {
1265 case FLG_TMPDIR:
1266 {
1267 if (cstring_lastChar (arg) == CONNECTCHAR)
1268 {
1269 context_setString (opt, arg);
1270 }
1271 else
1272 {
1273 context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1274 }
1275 break;
1276 }
1277 default:
1278 {
1279 context_setString (opt, arg);
1280 break;
1281 }
1282 }
1283}
1284
1285cstring
1286describeModes ()
1287{
1288 cstring s = cstring_makeLiteral ("Flag ");
1289 cstringSList sflags = sortedFlags ();
1290
1291 allModes (modename)
1292 {
1293 s = message ("%q%9s", s, cstring_fromChars (modename));
1294 } end_allModes;
1295
1296 s = message ("%q\n", s);
1297
1298 cstringSList_elements (sflags, flagname)
1299 {
a956d444 1300 flagcode code = flags_identifyFlag (flagname);
616915dd 1301 fflag currentflag = flags[code];
1302
1303 if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1304 {
1305 s = message ("%q\n%27s", s,
1306 cstring_fromChars (currentflag.flag));
1307
1308 allModes (modename)
1309 {
1310 context_setMode (cstring_fromChars (modename));
1311
1312 if (context_getFlag (code))
1313 {
1314 s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1315 }
1316 else
1317 {
1318 s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1319 }
1320
1321 context_resetModeFlags ();
1322 } end_allModes;
1323 }
1324 } end_cstringSList_elements;
1325
1326 cstringSList_free (sflags);
1327
1328 s = cstring_appendChar (s, '\n');
1329
1330 return (s);
1331}
1332
8250fa4a 1333# if 0
ee229125 1334static /*@unused@*/ cstring
616915dd 1335listModes (void)
1336{
1337 cstring s = cstring_makeLiteral ("\t");
1338 int i = 0;
1339
1340 allModes (modename)
1341 {
1342 if (i != 0 && (i % 4 == 0))
1343 {
1344 s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1345 }
1346 else
1347 {
1348 s = message ("%q%15s", s, cstring_fromChars (modename));
1349 }
1350 i++;
1351 } end_allModes;
1352
1353 return s;
1354}
8250fa4a 1355# endif
616915dd 1356
1357bool
1358isMode (cstring s)
1359{
1360 allModes (modename)
1361 {
1362 if (mstring_isDefined (modename))
1363 {
1364 if (cstring_equalLit (s, modename))
1365 {
1366 return TRUE;
1367 }
1368 }
1369 } end_allModes;
1370
1371 return FALSE;
1372}
1373
1374extern bool flagcode_hasArgument (flagcode f)
1375{
1376 return (flags[f].argtype != ARG_NONE);
1377}
1378
4f43223c 1379extern bool flagcode_hasNumber (flagcode f)
1380{
1381 return (flags[f].argtype == ARG_NUMBER);
1382}
1383
1384extern bool flagcode_hasChar (flagcode f)
616915dd 1385{
4f43223c 1386 return (flags[f].argtype == ARG_CHAR);
616915dd 1387}
1388
1389extern bool flagcode_hasString (flagcode f)
1390{
4f43223c 1391 return (flags[f].argtype == ARG_STRING
1392 || flags[f].argtype == ARG_FILE
1393 || flags[f].argtype == ARG_DIRECTORY
1394 || flags[f].argtype == ARG_PATH);
616915dd 1395}
1396
1397extern int flagcode_valueIndex (flagcode f)
1398{
1399 /*@unchecked@*/ static bool initialized = FALSE;
1400 int i;
1401 /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
616915dd 1402
1403 if (!initialized)
1404 {
1405 int nv = 0;
1406
1407 allFlagCodes (code)
1408 {
4f43223c 1409 if (flagcode_hasNumber (code) || flagcode_hasChar (code))
616915dd 1410 {
1411 llassert (nv < NUMVALUEFLAGS);
28bf4b0b 1412 DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
616915dd 1413 valueFlags[nv] = code;
28bf4b0b 1414 nv++;
616915dd 1415 }
1416 } end_allFlagCodes;
1417
1418 llassertprint (nv == NUMVALUEFLAGS,
28bf4b0b 1419 ("Number of value flags: %d (expected %d)",
1420 nv, (int) NUMVALUEFLAGS));
616915dd 1421 initialized = TRUE;
1422 }
1423
1424 for (i = 0; i < NUMVALUEFLAGS; i++)
1425 {
1426 /* static valueFlags must be defined */
86d93ed3 1427 /*@-usedef@*/
1428 /*drl bee: sta*/
1429 if (f == valueFlags[i]) /*@=usedef@*/
616915dd 1430 {
1431 return i;
1432 }
1433 }
1434
28bf4b0b 1435 fprintf (stderr, "Cannot find value flag: %d", (int) f);
1436 exit (EXIT_FAILURE);
1437 /* Cannot do this...might call recursively...
1438 llfatalbug (message ("Cannot fine value flag: %d", (int) f));
616915dd 1439 BADEXIT;
28bf4b0b 1440 */
616915dd 1441}
1442
1443extern int flagcode_stringIndex (flagcode f)
1444{
1445 /*@unchecked@*/ static bool initialized = FALSE;
1446 /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1447 int i;
1448
1449
1450 if (!initialized)
1451 {
1452 int nv = 0;
1453
1454 allFlagCodes (code)
1455 {
1456 if (flagcode_hasString (code))
1457 {
1458 llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1459 stringFlags[nv] = code;
1460 nv++;
1461 }
1462 } end_allFlagCodes;
1463
1464 llassertprint (nv == NUMSTRINGFLAGS,
1465 ("number of string flags: %d (expected %d)",
1466 nv, NUMSTRINGFLAGS));
1467 initialized = TRUE;
1468 }
1469
1470 for (i = 0; i < NUMSTRINGFLAGS; i++)
1471 {
86d93ed3 1472 /*drl bee: sta*/
616915dd 1473 /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1474 {
1475 return i;
1476 }
1477 }
1478
1479 llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1480 BADEXIT;
1481}
1482
1483bool flagcode_isNamePrefixFlag (flagcode f)
1484{
1485 switch (f)
1486 {
1487 case FLG_MACROVARPREFIX:
1488 case FLG_TAGPREFIX:
1489 case FLG_ENUMPREFIX:
1490 case FLG_FILESTATICPREFIX:
1491 case FLG_GLOBPREFIX:
1492 case FLG_TYPEPREFIX:
1493 case FLG_EXTERNALPREFIX:
1494 case FLG_LOCALPREFIX:
1495 case FLG_UNCHECKEDMACROPREFIX:
1496 case FLG_CONSTPREFIX:
1497 case FLG_ITERPREFIX:
1498 case FLG_DECLPARAMPREFIX:
1499 return TRUE;
1500 default:
1501 return FALSE;
1502 }
1503}
1504
This page took 1.063562 seconds and 5 git commands to generate.