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