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