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