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