]> andersk Git - splint.git/blame - src/flags.c
Updated README version number. (Testing sourceforge)
[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) /*@*/ ;
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
616915dd 899 ("accessunspec flag is not supported by LCLint version 2.0 or "
900 "later. It has been replaced by accessmodule, accessfile and "
901 "accessfunction to provide more precise control of accessibility "
902 "of representations. For more information, "
903 "see lclint -help accessmodule"));
904
905 return SKIP_FLAG;
906 }
907
908 if (cstring_equalLit (s, "staticmods"))
909 {
abb1cb43 910 llerror_flagWarning
911 (cstring_makeLiteral
616915dd 912 ("staticmods flag is obsolete. You probably "
913 "want impcheckmodstatics. For more information, "
914 "see lclint -help impcheckmodstatics"));
915
916 return SKIP_FLAG;
917 }
918
919 if (cstring_equalLit (s, "bool"))
920 {
abb1cb43 921 llerror_flagWarning
922 (cstring_makeLiteral ("bool flag is obsolete. It never really "
923 "made sense in the first place."));
616915dd 924
925 return SKIP_FLAG;
926 }
927
928 if (cstring_equalLit (s, "ansi"))
929 {
abb1cb43 930 llerror_flagWarning
931 (cstring_makeLiteral ("ansi flag is obsolete. You probably "
932 "want noparams and/or oldstyle."));
616915dd 933
934 return SKIP_FLAG;
935 }
936
937 if (cstring_equalLit (s, "stdio"))
938 {
abb1cb43 939 llerror_flagWarning
940 (cstring_makeLiteral
616915dd 941 ("stdio flag is obsolete. You may "
942 "want strictlib or one of the gloabls "
943 "checking flags. For more information, "
944 "see lclint -help strictlib or lclint -help flags globals"));
945
946 return SKIP_FLAG;
947 }
948
949 return INVALID_FLAG;
950}
951
952void setValueFlag (flagcode opt, cstring arg)
953{
954 switch (opt)
955 {
956 case FLG_EXPECT:
957 case FLG_LCLEXPECT:
958 case FLG_LIMIT:
959 case FLG_LINELEN:
28bf4b0b 960 case FLG_INDENTSPACES:
961 case FLG_BUGSLIMIT:
616915dd 962 case FLG_EXTERNALNAMELEN:
963 case FLG_INTERNALNAMELEN:
964 case FLG_CONTROLNESTDEPTH:
965 case FLG_STRINGLITERALLEN:
966 case FLG_NUMSTRUCTFIELDS:
967 case FLG_NUMENUMMEMBERS:
968 case FLG_INCLUDENEST:
969 {
970 int val = cstring_toPosInt (arg);
971
972 if (val < 0)
973 {
974 llerror
975 (FLG_BADFLAG,
976 message
977 ("Flag %s must be followed by a positive number number. "
978 "Followed by %s",
979 flagcode_unparse (opt), arg));
980 }
981 else
982 {
28bf4b0b 983 context_setValueAndFlag (opt, val);
616915dd 984 }
985 }
986 break;
987 case FLG_COMMENTCHAR:
988 {
989 if (cstring_length (arg) != 1)
990 {
991 llfatalerrorLoc
992 (message
993 ("Flag %s should be followed by a single character. Followed by %s",
994 flagcode_unparse (opt), arg));
995 }
996 else
997 {
998 context_setCommentMarkerChar (cstring_firstChar (arg));
999 }
1000 }
1001 break;
1002 BADDEFAULT;
1003 }
1004}
1005
1006void setStringFlag (flagcode opt, /*@only@*/ cstring arg)
1007{
1008 switch (opt)
1009 {
1010 case FLG_TMPDIR:
1011 {
1012 if (cstring_lastChar (arg) == CONNECTCHAR)
1013 {
1014 context_setString (opt, arg);
1015 }
1016 else
1017 {
1018 context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1019 }
1020 break;
1021 }
1022 default:
1023 {
1024 context_setString (opt, arg);
1025 break;
1026 }
1027 }
1028}
1029
1030cstring
1031describeModes ()
1032{
1033 cstring s = cstring_makeLiteral ("Flag ");
1034 cstringSList sflags = sortedFlags ();
1035
1036 allModes (modename)
1037 {
1038 s = message ("%q%9s", s, cstring_fromChars (modename));
1039 } end_allModes;
1040
1041 s = message ("%q\n", s);
1042
1043 cstringSList_elements (sflags, flagname)
1044 {
1045 flagcode code = identifyFlag (flagname);
1046 fflag currentflag = flags[code];
1047
1048 if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1049 {
1050 s = message ("%q\n%27s", s,
1051 cstring_fromChars (currentflag.flag));
1052
1053 allModes (modename)
1054 {
1055 context_setMode (cstring_fromChars (modename));
1056
1057 if (context_getFlag (code))
1058 {
1059 s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1060 }
1061 else
1062 {
1063 s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1064 }
1065
1066 context_resetModeFlags ();
1067 } end_allModes;
1068 }
1069 } end_cstringSList_elements;
1070
1071 cstringSList_free (sflags);
1072
1073 s = cstring_appendChar (s, '\n');
1074
1075 return (s);
1076}
1077
8250fa4a 1078# if 0
ee229125 1079static /*@unused@*/ cstring
616915dd 1080listModes (void)
1081{
1082 cstring s = cstring_makeLiteral ("\t");
1083 int i = 0;
1084
1085 allModes (modename)
1086 {
1087 if (i != 0 && (i % 4 == 0))
1088 {
1089 s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1090 }
1091 else
1092 {
1093 s = message ("%q%15s", s, cstring_fromChars (modename));
1094 }
1095 i++;
1096 } end_allModes;
1097
1098 return s;
1099}
8250fa4a 1100# endif
616915dd 1101
1102bool
1103isMode (cstring s)
1104{
1105 allModes (modename)
1106 {
1107 if (mstring_isDefined (modename))
1108 {
1109 if (cstring_equalLit (s, modename))
1110 {
1111 return TRUE;
1112 }
1113 }
1114 } end_allModes;
1115
1116 return FALSE;
1117}
1118
1119extern bool flagcode_hasArgument (flagcode f)
1120{
1121 return (flags[f].argtype != ARG_NONE);
1122}
1123
1124extern bool flagcode_hasValue (flagcode f)
1125{
1126 return (flags[f].argtype == ARG_VALUE);
1127}
1128
1129extern bool flagcode_hasString (flagcode f)
1130{
1131 return (flags[f].argtype == ARG_STRING);
1132}
1133
1134extern int flagcode_valueIndex (flagcode f)
1135{
1136 /*@unchecked@*/ static bool initialized = FALSE;
1137 int i;
1138 /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
616915dd 1139
1140 if (!initialized)
1141 {
1142 int nv = 0;
1143
1144 allFlagCodes (code)
1145 {
1146 if (flagcode_hasValue (code))
1147 {
1148 llassert (nv < NUMVALUEFLAGS);
28bf4b0b 1149 DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
616915dd 1150 valueFlags[nv] = code;
28bf4b0b 1151 nv++;
616915dd 1152 }
1153 } end_allFlagCodes;
1154
1155 llassertprint (nv == NUMVALUEFLAGS,
28bf4b0b 1156 ("Number of value flags: %d (expected %d)",
1157 nv, (int) NUMVALUEFLAGS));
616915dd 1158 initialized = TRUE;
1159 }
1160
1161 for (i = 0; i < NUMVALUEFLAGS; i++)
1162 {
1163 /* static valueFlags must be defined */
1164 /*@-usedef@*/ if (f == valueFlags[i]) /*@=usedef@*/
1165 {
1166 return i;
1167 }
1168 }
1169
28bf4b0b 1170 fprintf (stderr, "Cannot find value flag: %d", (int) f);
1171 exit (EXIT_FAILURE);
1172 /* Cannot do this...might call recursively...
1173 llfatalbug (message ("Cannot fine value flag: %d", (int) f));
616915dd 1174 BADEXIT;
28bf4b0b 1175 */
616915dd 1176}
1177
1178extern int flagcode_stringIndex (flagcode f)
1179{
1180 /*@unchecked@*/ static bool initialized = FALSE;
1181 /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1182 int i;
1183
1184
1185 if (!initialized)
1186 {
1187 int nv = 0;
1188
1189 allFlagCodes (code)
1190 {
1191 if (flagcode_hasString (code))
1192 {
1193 llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1194 stringFlags[nv] = code;
1195 nv++;
1196 }
1197 } end_allFlagCodes;
1198
1199 llassertprint (nv == NUMSTRINGFLAGS,
1200 ("number of string flags: %d (expected %d)",
1201 nv, NUMSTRINGFLAGS));
1202 initialized = TRUE;
1203 }
1204
1205 for (i = 0; i < NUMSTRINGFLAGS; i++)
1206 {
1207 /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1208 {
1209 return i;
1210 }
1211 }
1212
1213 llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1214 BADEXIT;
1215}
1216
1217bool flagcode_isNamePrefixFlag (flagcode f)
1218{
1219 switch (f)
1220 {
1221 case FLG_MACROVARPREFIX:
1222 case FLG_TAGPREFIX:
1223 case FLG_ENUMPREFIX:
1224 case FLG_FILESTATICPREFIX:
1225 case FLG_GLOBPREFIX:
1226 case FLG_TYPEPREFIX:
1227 case FLG_EXTERNALPREFIX:
1228 case FLG_LOCALPREFIX:
1229 case FLG_UNCHECKEDMACROPREFIX:
1230 case FLG_CONSTPREFIX:
1231 case FLG_ITERPREFIX:
1232 case FLG_DECLPARAMPREFIX:
1233 return TRUE;
1234 default:
1235 return FALSE;
1236 }
1237}
1238
This page took 0.978933 seconds and 5 git commands to generate.