]> andersk Git - splint.git/blame - src/flags.c
*** empty log message ***
[splint.git] / src / flags.c
CommitLineData
616915dd 1/*
2** LCLint - annotation-assisted static program checker
28bf4b0b 3** Copyright (C) 1994-2001 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
22** For more information: http://lclint.cs.virginia.edu
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,
113 ARG_VALUE,
114 ARG_STRING,
115 ARG_SPECIAL
116} argcode;
117
118typedef struct {
119 flagkind main;
120 flagkind sub;
121 bool isSpecial; /* setting this flag may set other flags (or values) */
122 bool isIdem; /* idempotent - always sets to TRUE */
123 bool isGlobal; /* cannot be set locally (using control comments) */
124 bool isModeFlag; /* set by modes */
125 argcode argtype;
126 /*@observer@*/ char *flag;
127 flagcode code;
128 /*@observer@*/ /*@null@*/ char *desc;
129 bn_mstring hint;
130 int nreported;
131 int nsuppressed;
132} fflag;
133
134typedef fflag flaglist[];
135
136# include "flags.def"
137
138/*@iter allFlags (yield observer fflag f); @*/
139# define allFlags(m_f) \
140 { /*@+enumint@*/ flagcode m_i; for (m_i = 0; m_i < NUMFLAGS; m_i++) { fflag m_f = flags[m_i]; /*@=enumint@*/
141# define end_allFlags }}
142
143static bn_mstring mode_names[] =
144{
145 "weak", "standard", "checks", "strict", NULL,
146};
147
148/*@iter allModes (yield bn_mstring modename)@*/
149# define allModes(m_m) \
150 { int m_ii = 0; while (mstring_isDefined (mode_names[m_ii])) \
151 { bn_mstring m_m = mode_names[m_ii]; m_ii++;
152
153# define end_allModes }}
154
155/*@+enumint@*/
156
157static cstring describeFlagCode (flagcode p_flag) /*@*/ ;
158static cstringSList sortedFlags (void) /*@*/ ;
159static /*@observer@*/ cstring categoryName (flagkind p_kind) /*@*/ ;
160static /*@unused@*/ cstring listModes (void) /*@*/ ;
161
162bool flagcode_isSpecialFlag (flagcode f)
163{
164 return (flags[f].isSpecial);
165}
166
167bool flagcode_isGlobalFlag (flagcode f)
168{
169 return (flags[f].isGlobal);
170}
171
172bool flagcode_isIdemFlag (flagcode f)
173{
174 return (flags[f].isIdem);
175}
176
177bool flagcode_isModeFlag (flagcode f)
178{
179 return (flags[f].isModeFlag);
180}
181
182bool flagcode_isNameChecksFlag (flagcode f)
183{
184 return (flags[f].main == FK_NAMES);
185}
186
187/*
188** Internal consistency check on the flags.
189*/
190
191void flags_initMod ()
192{
193 allFlagCodes (code)
194 {
195 /*@+enumint@*/
196 if (flags[code].code != code)
197 {
28bf4b0b 198 fprintf (stderr,
199 "*** ERROR: inconsistent flag %s / %d / %d",
200 flags[code].flag,
201 flags[code].code, code);
202
616915dd 203 llbug (message ("*** ERROR: inconsistent flag %s / %d / %d",
204 cstring_fromChars (flags[code].flag),
205 flags[code].code, code));
206 }
207 /*@=enumint@*/
208 } end_allFlagCodes;
209}
210
211void
212summarizeErrors ()
213{
214 bool hadOne = FALSE;
215 int sumrep = 0;
216 int sumsup = 0;
217
218 char *buf = mstring_create (128);
219
220 allFlags (f)
221 {
222 if (f.nreported > 0 || f.nsuppressed > 0)
223 {
224 int nrep = f.nreported;
225 int nsup = f.nsuppressed;
226 cstring fs = cstring_fill (cstring_fromChars (f.flag), 23);
227
228 if (!hadOne)
229 {
230 llmsgplain (cstring_makeLiteral
231 ("\nError Type Reported Suppressed\n"
232 "=================== ======== ========="));
233 hadOne = TRUE;
234 }
235
236 sprintf (buf, "%s%7d %9d", cstring_toCharsSafe (fs), nrep, nsup);
237
238 sumrep += nrep;
239 sumsup += nsup;
240
241 cstring_free (fs);
242 llmsg (cstring_copy (cstring_fromChars (buf)));
243 }
244 } end_allFlags;
245
246 if (hadOne)
247 {
248 cstring ts = cstring_fill (cstring_makeLiteralTemp ("Total"), 23);
249
250 llmsglit (" ======== =========");
251
252 sprintf (buf, "%s%7d %9d", cstring_toCharsSafe (ts), sumrep, sumsup);
253 cstring_free (ts);
254 llmsgplain (cstring_copy (cstring_fromChars (buf)));
255 }
256
257 sfree (buf);
258}
259
260/*@+enumindex@*/
261
262void
263flagcode_recordError (flagcode f)
264{
265 if (f != INVALID_FLAG)
266 {
267 if (f == FLG_WARNFLAGS)
268 {
269 ; /* don't count these */
270 }
271 else
272 {
273 flags[f].nreported = flags[f].nreported + 1;
274 }
275 }
276 else
277 {
278 llcontbug (message ("flagcode_recordError: invalid flag: %d", (int) f));
279 }
280}
281
282void
283flagcode_recordSuppressed (flagcode f)
284{
285 llassertprint (f != INVALID_FLAG, ("flagcode: %s", flagcode_unparse (f)));
286
287 flags[f].nsuppressed = flags[f].nsuppressed + 1;
288}
289
290int
291flagcode_numReported (flagcode f)
292{
293 llassert (f != INVALID_FLAG);
294
295 return (flags[f].nreported);
296}
297
298/*@observer@*/ cstring
299flagcodeHint (flagcode f)
300{
301 llassert (f != INVALID_FLAG);
302
303 if (mstring_isDefined (flags[f].hint))
304 {
305 return (cstring_fromChars (flags[f].hint));
306 }
307 else
308 {
309 return (cstring_fromChars (flags[f].desc));
310 }
311}
312
313static int categorySize (flagkind kind) /*@*/
314{
315 int n = 0;
316
317
318 allFlags (f)
319 {
320 if (f.main == kind || f.sub == kind)
321 {
322 n++;
323 }
324 } end_allFlags;
325
326 return n;
327}
328
329flagkind identifyCategory (cstring s)
330{
331 int i;
332
333 for (i = 0; categories[i].kind != FK_NONE; i++)
334 {
335 if (mstring_isDefined (categories[i].name))
336 {
337 if (cstring_equalLit (s, categories[i].name))
338 {
339 return categories[i].kind;
340 }
341 }
342 }
343
344 return FK_NONE;
345}
346
347static /*@observer@*/ cstring categoryName (flagkind kind)
348{
349 int i;
350
351 for (i = 0; categories[i].kind != FK_NONE; i++)
352 {
353 if (categories[i].kind == kind)
354 {
355 return (cstring_fromChars (categories[i].name));
356 }
357 }
358
359 return (cstring_makeLiteralTemp ("<No Category>"));
360}
361
362static int categoryIndex (flagkind kind)
363{
364 int i;
365
366 for (i = 0; categories[i].kind != FK_NONE; i++)
367 {
368 if (categories[i].kind == kind)
369 {
370 return i;
371 }
372 }
373
374 return -1;
375}
376
377void printCategory (flagkind kind)
378{
379 int index = categoryIndex (kind);
380
381 llassert (index >= 0);
382
383 llmsg (message ("%s (%d flags)\n\3%s\n\n",
384 cstring_fromChars (categories[index].name),
385 categorySize (kind),
386 cstring_fromChars (categories[index].describe)));
387
388 allFlags (f)
389 {
390 if (f.main == kind || f.sub == kind)
391 {
392 llmsg (message (" %s\n\6%q", cstring_fromChars (f.flag),
393 describeFlagCode (f.code)));
394 }
395 } end_allFlags;
396}
397
398void
399listAllCategories (void)
400{
401 int i;
402
403 for (i = 0; categories[i].kind != FK_NONE; i++)
404 {
405 flagkind kind = categories[i].kind ;
406
407 if (categories[i].describe != NULL)
408 {
409 llmsg (message ("%s (%d flags)\n\3%s",
410 categoryName (kind),
411 categorySize (kind),
412 cstring_fromChars (categories[i].describe)));
413 }
414 }
415}
416
417void
418printAllFlags (bool desc, bool full)
419{
420 if (full)
421 {
422 cstringSList fl = sortedFlags ();
423
424 cstringSList_elements (fl, el)
425 {
426 llmsg (message ("%q\n\n", describeFlag (el)));
427 } end_cstringSList_elements ;
428
429 cstringSList_free (fl);
430 }
431 else
432 {
433 allFlags (f)
434 {
435 if (f.code != INVALID_FLAG && f.main != FK_OBSOLETE)
436 {
437 if (mstring_isDefined (f.desc))
438 {
439 if (desc)
440 {
441 llmsg (message ("%s --- %s", cstring_fromChars (f.flag),
442 cstring_fromChars (f.desc)));
443 }
444 }
445 }
446 } end_allFlags;
447 }
448}
449
450cstring
451describeFlagCode (flagcode flag)
452{
453 cstring ret = cstring_undefined;
454 fflag f;
455
456 if (flagcode_isInvalid (flag))
457 {
458 return (cstring_makeLiteral ("<invalid>"));
459 }
460
461 context_resetAllFlags ();
462
463 f = flags[flag];
464 ret = cstring_copy (cstring_fromChars (f.desc));
465
466
467 if (f.sub != FK_NONE)
468 {
469 ret = message ("%q\nCategories: %s, %s",
470 ret,
471 categoryName (f.main),
472 categoryName (f.sub));
473 }
474 else
475 {
476 if (f.main != FK_NONE)
477 {
478 cstring cname = categoryName (f.main);
479
480 if (cstring_isDefined (cname))
481 {
482 ret = message ("%q\nCategory: %s",
483 ret, cname);
484 }
485 }
486 }
487
488 if (f.isModeFlag)
489 {
490 bool first = TRUE;
491
492 allModes (mname)
493 {
494 context_setMode (cstring_fromChars (mname));
495
496 if (first)
497 {
498 ret = message ("%q\nMode Settings: %s %s",
499 ret, cstring_fromChars (mname),
500 cstring_makeLiteralTemp
501 (context_getFlag (flag) ? "+" : "-"));
502 first = FALSE;
503 }
504 else
505 {
506 ret = message ("%q, %s %s",
507 ret, cstring_fromChars (mname),
508 cstring_makeLiteralTemp
509 (context_getFlag (flag) ? "+" : "-"));
510 }
511 } end_allModes;
512 }
513 else
514 {
515 ret = message ("%q\nDefault Setting: %s",
516 ret,
517 cstring_makeLiteralTemp
518 (context_getFlag (flag) ? "+" : "-"));
519 }
520
521 if (f.isGlobal)
522 {
523 ret = message("%q\nSet globally only", ret);
524 }
525 else
526 {
527 ret = message("%q\nSet locally", ret);
528 }
529
530 switch (f.argtype)
531 {
532 case ARG_NONE:
533 case ARG_SPECIAL:
534 break;
535 case ARG_VALUE:
536 if (flag == FLG_COMMENTCHAR)
537 {
538 ret = message("%q\nCharacter Argument. Default: %h",
539 ret, (char) context_getValue (flag));
540 }
541 else
542 {
543 ret = message("%q\nNumeric Argument. Default: %d",
544 ret,
545 context_getValue (flag));
546 }
547 break;
548 case ARG_STRING:
549 if (cstring_isDefined (context_getString (flag)))
550 {
551 ret = message("%q\nString Argument. Default: %s",
552 ret,
553 context_getString (flag));
554 }
555 else
556 {
557 ret = message("%q\nString Argument. No default.", ret);
558 }
559 break;
560 }
561
562 if (mstring_isDefined (f.hint))
563 {
564 ret = message("%q\n\3%s", ret, cstring_fromChars (f.hint));
565 }
566
567 return ret;
568}
569
570cstring
571describeFlag (cstring flagname)
572{
573 cstring oflagname = cstring_copy (flagname);
574 flagcode f = identifyFlag (flagname);
575
576 if (flagcode_isSkip (f))
577 {
578 cstring_free (oflagname);
579 return cstring_undefined;
580 }
581 else if (flagcode_isValid (f))
582 {
583 if (cstring_equal (flagname, oflagname))
584 {
585 cstring_free (oflagname);
586 return (message ("%s\n\3%q", flagname, describeFlagCode (f)));
587 }
588 else
589 {
590 return (message ("%q (standardized name: %s)\n\3%q",
591 oflagname, flagname, describeFlagCode (f)));
592 }
593 }
594 else
595 {
596 if (isMode (flagname))
597 {
598 cstring_free (oflagname);
599
600 return
601 (message ("%s: predefined mode (see User's Guide for information)",
602 flagname));
603 }
604 else
605 {
606 return (message ("%q: <invalid flag>", oflagname));
607 }
608 }
609}
610
611static cstringSList
612sortedFlags (void)
613{
614 cstringSList s = cstringSList_new ();
615
616 allFlags (f)
617 {
618 if (f.desc != NULL)
619 {
620 s = cstringSList_add (s, cstring_fromChars (f.flag));
621 }
622 } end_allFlags;
623
624 cstringSList_alphabetize (s);
625
626 return s;
627}
628
629void printAlphaFlags ()
630{
631 cstringSList fl = sortedFlags ();
632
633 cstringSList_printSpaced (fl, 3, 1, context_getLineLen () - 25);
634 cstringSList_free (fl);
635}
28bf4b0b 636
616915dd 637/*@observer@*/ cstring
28bf4b0b 638flagcode_unparse (flagcode code)
616915dd 639{
640 return cstring_fromChars (flags[code].flag);
641}
642
643/*
644** Transforms a flag into its cannonical form.
645**
646** The following transformations are made:
647**
648** function -> fcn
649** variable -> var
650** constant -> const
651** iterator -> iter
652** parameter -> param
653** unrecognized -> unrecog
654** qualifier -> qual
655** declaration -> decl
656** globalias -> (no change)
657** global -> glob
658** modifies -> mods
659** modify -> mod
660** pointer -> ptr
661** implies -> imp
662** implicit -> imp
663** implied -> imp
664** unconstrained -> unspec
665** unconst -> unspec
666** memory -> mem
667** length -> len
668*/
669
670static void
671canonicalizeFlag (cstring s)
672{
673 int i = 0;
674 static bn_mstring transform[] =
675 {
676 "function", "fcn",
677 "variable", "var",
678 "constant", "const",
679 "iterator", "iter",
680 "parameter", "param",
681 "unrecognized", "unrecog",
682 "qualifier", "qual",
683 "declaration", "decl",
684 "globals", "globs",
685 "modifies", "mods",
686 "modify", "mod",
687 "pointer", "ptr",
688 "implies", "imp",
689 "implicit", "imp",
690 "implied", "imp",
691 "unconstrained", "uncon",
692 "unconst", "uncon",
693 "memory", "mem",
694 "length", "len",
695 "return", "ret",
696 "system", "sys",
697 NULL
698 } ;
699 char *current;
700
701 while ((current = transform[i]) != NULL)
702 {
703 if (cstring_containsLit (s, current))
704 {
705 cstring_replaceLit (s, current, transform[i+1]);
706 }
707 i += 2;
708 }
709
710 /* remove whitespace, -'s, and _'s */
711 cstring_stripChars (s, " -_");
712}
713
714flagcode
715identifyFlag (cstring s)
716{
717 if (cstring_length (s) == 0) {
718 /* evs 2000-06-25: A malformed flag. */
719 return INVALID_FLAG;
720 }
721
722 if (cstring_firstChar (s) == 'I')
723 {
724 return FLG_INCLUDEPATH; /* no space after -I */
725 }
726
727 if (cstring_firstChar (s) == 'S')
728 {
729 return FLG_SPECPATH; /* no space after -S */
730 }
731
732 if (cstring_firstChar (s) == 'D')
733 {
734 return FLG_DEFINE; /* no space after -D */
735 }
736
737 if (cstring_firstChar (s) == 'U')
738 {
739 return FLG_UNDEFINE; /* no space after -D */
740 }
741
742 canonicalizeFlag (s);
743
744 allFlags (f)
745 {
746 if (cstring_equal (cstring_fromChars (f.flag), s))
747 {
748 return (f.code);
749 }
750 } end_allFlags;
751
752 /*
753 ** Synonyms
754 */
755
756 if (cstring_equalLit (s, "pred"))
757 {
758 return FLG_PREDBOOL;
759 }
760
761 if (cstring_equalLit (s, "modobserverstrict"))
762 {
763 return FLG_MODOBSERVERUNCON;
764 }
765
766 if (cstring_equalLit (s, "czechnames"))
767 {
768 return FLG_CZECH;
769 }
770
771 if (cstring_equalLit (s, "slovaknames"))
772 {
773 return FLG_SLOVAK;
774 }
775
776 if (cstring_equalLit (s, "czechoslovaknames"))
777 {
778 return FLG_CZECHOSLOVAK;
779 }
780
781 if (cstring_equalLit (s, "globunspec")
782 || cstring_equalLit (s, "globuncon"))
783 {
784 return FLG_GLOBUNSPEC;
785 }
786
787 if (cstring_equalLit (s, "modglobsunspec")
788 || cstring_equalLit (s, "modglobsuncon")
789 || cstring_equalLit (s, "modglobsnomods"))
790 {
791 return FLG_MODGLOBSUNSPEC;
792 }
793
794 if (cstring_equalLit (s, "export"))
795 {
796 return FLG_EXPORTANY;
797 }
798
799 if (cstring_equalLit (s, "macrospec"))
800 {
801 return FLG_MACRODECL;
802 }
803
804 if (cstring_equalLit (s, "ansireservedlocal"))
805 {
806 return FLG_ANSIRESERVEDLOCAL;
807 }
808
809 if (cstring_equalLit (s, "warnposix"))
810 {
811 return FLG_WARNPOSIX;
812 }
813
814 if (cstring_equalLit (s, "defuse"))
815 {
816 return FLG_USEDEF;
817 }
818
819 if (cstring_equalLit (s, "macroundef"))
820 {
821 return FLG_MACROUNDEF;
822 }
823
824 if (cstring_equalLit (s, "showcol"))
825 {
826 return FLG_SHOWCOL;
827 }
828
829 if (cstring_equalLit (s, "intbool"))
830 {
831 return FLG_BOOLINT;
832 }
833
834 if (cstring_equalLit (s, "intchar"))
835 {
836 return FLG_CHARINT;
837 }
838
839 if (cstring_equalLit (s, "intenum"))
840 {
841 return FLG_ENUMINT;
842 }
843
844 /*
845 ** For our European friends...
846 */
847
848 if (cstring_equalLit (s, "isolib"))
849 {
850 return FLG_ANSILIB;
851 }
852
853 if (cstring_equalLit (s, "isostrictlib"))
854 {
855 return FLG_STRICTLIB;
856 }
857
858 if (cstring_equalLit (s, "ansistrictlib"))
859 {
860 return FLG_STRICTLIB;
861 }
862
863 if (cstring_equalLit (s, "skipisoheaders"))
864 {
865 return FLG_SKIPANSIHEADERS;
866 }
867
868 if (cstring_equalLit (s, "isoreserved"))
869 {
870 return FLG_ANSIRESERVED;
871 }
872
873 if (cstring_equalLit (s, "isoreservedinternal"))
874 {
875 return FLG_ANSIRESERVEDLOCAL;
876 }
877
878 if (cstring_equalLit (s, "isolimits"))
879 {
880 return FLG_ANSILIMITS;
881 }
882
883 /*
884 ** Obsolete Flags
885 */
886
887 if (cstring_equalLit (s, "accessunspec"))
888 {
abb1cb43 889 llerror_flagWarning
890 (cstring_makeLiteral
616915dd 891 ("accessunspec flag is not supported by LCLint version 2.0 or "
892 "later. It has been replaced by accessmodule, accessfile and "
893 "accessfunction to provide more precise control of accessibility "
894 "of representations. For more information, "
895 "see lclint -help accessmodule"));
896
897 return SKIP_FLAG;
898 }
899
900 if (cstring_equalLit (s, "staticmods"))
901 {
abb1cb43 902 llerror_flagWarning
903 (cstring_makeLiteral
616915dd 904 ("staticmods flag is obsolete. You probably "
905 "want impcheckmodstatics. For more information, "
906 "see lclint -help impcheckmodstatics"));
907
908 return SKIP_FLAG;
909 }
910
911 if (cstring_equalLit (s, "bool"))
912 {
abb1cb43 913 llerror_flagWarning
914 (cstring_makeLiteral ("bool flag is obsolete. It never really "
915 "made sense in the first place."));
616915dd 916
917 return SKIP_FLAG;
918 }
919
920 if (cstring_equalLit (s, "ansi"))
921 {
abb1cb43 922 llerror_flagWarning
923 (cstring_makeLiteral ("ansi flag is obsolete. You probably "
924 "want noparams and/or oldstyle."));
616915dd 925
926 return SKIP_FLAG;
927 }
928
929 if (cstring_equalLit (s, "stdio"))
930 {
abb1cb43 931 llerror_flagWarning
932 (cstring_makeLiteral
616915dd 933 ("stdio flag is obsolete. You may "
934 "want strictlib or one of the gloabls "
935 "checking flags. For more information, "
936 "see lclint -help strictlib or lclint -help flags globals"));
937
938 return SKIP_FLAG;
939 }
940
941 return INVALID_FLAG;
942}
943
944void setValueFlag (flagcode opt, cstring arg)
945{
946 switch (opt)
947 {
948 case FLG_EXPECT:
949 case FLG_LCLEXPECT:
950 case FLG_LIMIT:
951 case FLG_LINELEN:
28bf4b0b 952 case FLG_INDENTSPACES:
953 case FLG_BUGSLIMIT:
616915dd 954 case FLG_EXTERNALNAMELEN:
955 case FLG_INTERNALNAMELEN:
956 case FLG_CONTROLNESTDEPTH:
957 case FLG_STRINGLITERALLEN:
958 case FLG_NUMSTRUCTFIELDS:
959 case FLG_NUMENUMMEMBERS:
960 case FLG_INCLUDENEST:
961 {
962 int val = cstring_toPosInt (arg);
963
964 if (val < 0)
965 {
966 llerror
967 (FLG_BADFLAG,
968 message
969 ("Flag %s must be followed by a positive number number. "
970 "Followed by %s",
971 flagcode_unparse (opt), arg));
972 }
973 else
974 {
28bf4b0b 975 context_setValueAndFlag (opt, val);
616915dd 976 }
977 }
978 break;
979 case FLG_COMMENTCHAR:
980 {
981 if (cstring_length (arg) != 1)
982 {
983 llfatalerrorLoc
984 (message
985 ("Flag %s should be followed by a single character. Followed by %s",
986 flagcode_unparse (opt), arg));
987 }
988 else
989 {
990 context_setCommentMarkerChar (cstring_firstChar (arg));
991 }
992 }
993 break;
994 BADDEFAULT;
995 }
996}
997
998void setStringFlag (flagcode opt, /*@only@*/ cstring arg)
999{
1000 switch (opt)
1001 {
1002 case FLG_TMPDIR:
1003 {
1004 if (cstring_lastChar (arg) == CONNECTCHAR)
1005 {
1006 context_setString (opt, arg);
1007 }
1008 else
1009 {
1010 context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1011 }
1012 break;
1013 }
1014 default:
1015 {
1016 context_setString (opt, arg);
1017 break;
1018 }
1019 }
1020}
1021
1022cstring
1023describeModes ()
1024{
1025 cstring s = cstring_makeLiteral ("Flag ");
1026 cstringSList sflags = sortedFlags ();
1027
1028 allModes (modename)
1029 {
1030 s = message ("%q%9s", s, cstring_fromChars (modename));
1031 } end_allModes;
1032
1033 s = message ("%q\n", s);
1034
1035 cstringSList_elements (sflags, flagname)
1036 {
1037 flagcode code = identifyFlag (flagname);
1038 fflag currentflag = flags[code];
1039
1040 if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1041 {
1042 s = message ("%q\n%27s", s,
1043 cstring_fromChars (currentflag.flag));
1044
1045 allModes (modename)
1046 {
1047 context_setMode (cstring_fromChars (modename));
1048
1049 if (context_getFlag (code))
1050 {
1051 s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1052 }
1053 else
1054 {
1055 s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1056 }
1057
1058 context_resetModeFlags ();
1059 } end_allModes;
1060 }
1061 } end_cstringSList_elements;
1062
1063 cstringSList_free (sflags);
1064
1065 s = cstring_appendChar (s, '\n');
1066
1067 return (s);
1068}
1069
1070static cstring
1071listModes (void)
1072{
1073 cstring s = cstring_makeLiteral ("\t");
1074 int i = 0;
1075
1076 allModes (modename)
1077 {
1078 if (i != 0 && (i % 4 == 0))
1079 {
1080 s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1081 }
1082 else
1083 {
1084 s = message ("%q%15s", s, cstring_fromChars (modename));
1085 }
1086 i++;
1087 } end_allModes;
1088
1089 return s;
1090}
1091
1092bool
1093isMode (cstring s)
1094{
1095 allModes (modename)
1096 {
1097 if (mstring_isDefined (modename))
1098 {
1099 if (cstring_equalLit (s, modename))
1100 {
1101 return TRUE;
1102 }
1103 }
1104 } end_allModes;
1105
1106 return FALSE;
1107}
1108
1109extern bool flagcode_hasArgument (flagcode f)
1110{
1111 return (flags[f].argtype != ARG_NONE);
1112}
1113
1114extern bool flagcode_hasValue (flagcode f)
1115{
1116 return (flags[f].argtype == ARG_VALUE);
1117}
1118
1119extern bool flagcode_hasString (flagcode f)
1120{
1121 return (flags[f].argtype == ARG_STRING);
1122}
1123
1124extern int flagcode_valueIndex (flagcode f)
1125{
1126 /*@unchecked@*/ static bool initialized = FALSE;
1127 int i;
1128 /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
616915dd 1129
1130 if (!initialized)
1131 {
1132 int nv = 0;
1133
1134 allFlagCodes (code)
1135 {
1136 if (flagcode_hasValue (code))
1137 {
1138 llassert (nv < NUMVALUEFLAGS);
28bf4b0b 1139 DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
616915dd 1140 valueFlags[nv] = code;
28bf4b0b 1141 nv++;
616915dd 1142 }
1143 } end_allFlagCodes;
1144
1145 llassertprint (nv == NUMVALUEFLAGS,
28bf4b0b 1146 ("Number of value flags: %d (expected %d)",
1147 nv, (int) NUMVALUEFLAGS));
616915dd 1148 initialized = TRUE;
1149 }
1150
1151 for (i = 0; i < NUMVALUEFLAGS; i++)
1152 {
1153 /* static valueFlags must be defined */
1154 /*@-usedef@*/ if (f == valueFlags[i]) /*@=usedef@*/
1155 {
1156 return i;
1157 }
1158 }
1159
28bf4b0b 1160 fprintf (stderr, "Cannot find value flag: %d", (int) f);
1161 exit (EXIT_FAILURE);
1162 /* Cannot do this...might call recursively...
1163 llfatalbug (message ("Cannot fine value flag: %d", (int) f));
616915dd 1164 BADEXIT;
28bf4b0b 1165 */
616915dd 1166}
1167
1168extern int flagcode_stringIndex (flagcode f)
1169{
1170 /*@unchecked@*/ static bool initialized = FALSE;
1171 /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1172 int i;
1173
1174
1175 if (!initialized)
1176 {
1177 int nv = 0;
1178
1179 allFlagCodes (code)
1180 {
1181 if (flagcode_hasString (code))
1182 {
1183 llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1184 stringFlags[nv] = code;
1185 nv++;
1186 }
1187 } end_allFlagCodes;
1188
1189 llassertprint (nv == NUMSTRINGFLAGS,
1190 ("number of string flags: %d (expected %d)",
1191 nv, NUMSTRINGFLAGS));
1192 initialized = TRUE;
1193 }
1194
1195 for (i = 0; i < NUMSTRINGFLAGS; i++)
1196 {
1197 /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1198 {
1199 return i;
1200 }
1201 }
1202
1203 llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1204 BADEXIT;
1205}
1206
1207bool flagcode_isNamePrefixFlag (flagcode f)
1208{
1209 switch (f)
1210 {
1211 case FLG_MACROVARPREFIX:
1212 case FLG_TAGPREFIX:
1213 case FLG_ENUMPREFIX:
1214 case FLG_FILESTATICPREFIX:
1215 case FLG_GLOBPREFIX:
1216 case FLG_TYPEPREFIX:
1217 case FLG_EXTERNALPREFIX:
1218 case FLG_LOCALPREFIX:
1219 case FLG_UNCHECKEDMACROPREFIX:
1220 case FLG_CONSTPREFIX:
1221 case FLG_ITERPREFIX:
1222 case FLG_DECLPARAMPREFIX:
1223 return TRUE;
1224 default:
1225 return FALSE;
1226 }
1227}
1228
This page took 0.587752 seconds and 5 git commands to generate.