]> andersk Git - splint.git/blame - src/flags.c
Fixed data on readme.
[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**
155af98d 20** For information on splint: info@splint.org
21** To report a bug: splint-bug@splint.org
11db3170 22** For more information: http://www.splint.org
616915dd 23*/
24/*
25** flags.c
26*/
27
1b8ae690 28# include "splintMacros.nf"
616915dd 29# include "basic.h"
140c27a8 30# include "osd.h"
616915dd 31# include "portab.h"
140c27a8 32# include "rcfiles.h"
33# include "lslinit.h"
616915dd 34
35/*
36** from the CC man page:
37**
38** -Idir Search for #include files whose names do not begin with a
39** slash (/) in the following order: (1) in the directory of
40** the dir argument, (2) in the directories specified by -I
41** options, (3) in the standard directory (/usr/include).
42*/
43
44/* needed for string literals literals */
45
46typedef struct {
47 flagkind kind;
48 /*@null@*/ /*@observer@*/ char *name;
49 /*@null@*/ /*@observer@*/ char *describe;
50} flagcatinfo;
51
52static flagcatinfo categories[] =
53{
54 { FK_ABSTRACT, "abstract", "abstraction violations, representation access" } ,
55 { FK_ALIAS, "aliasing", "unexpected or dangerous aliasing" } ,
56 { FK_USE, "alluse", "all declarations are used" } ,
57 { FK_ANSI, "ansi", "violations of constraints imposed by ANSI/ISO standard" } ,
58 { FK_ARRAY, "arrays", "special checking involving arrays" } ,
59 { FK_BOOL, "booleans", "checking and naming of boolean types" } ,
bb7c2085 60 { FK_COMMENTS, "comments", "warnings about (normal) comments" } ,
61 { FK_SYNCOMMENTS, "syncomments", "interpretation of annotation comments" } ,
616915dd 62 { FK_COMPLETE, "complete", "completely defined, used, or specified system" } ,
63 { FK_CONTROL, "controlflow", "suspicious control structures" } ,
1b8ae690 64 { FK_DEBUG, "debug", "flags for debugging splint" } ,
616915dd 65 { FK_DECL, "declarations", "consistency of declarations" } ,
66 { FK_DEF, "definition", "undefined storage errors" } ,
67 { FK_DIRECT, "directories", "set directores" } ,
68 { FK_DISPLAY, "display", "control what is displayed" } ,
69 { FK_EFFECT, "effect", "statements with no effects" } ,
70 { FK_ERRORS, "errors", "control expected errors, summary reporting" } ,
71 { FK_EXPORT, "export", "control what may be exported" } ,
72 { FK_EXPOSURE, "exposure", "representation exposure" } ,
bb7c2085 73 { FK_EXTENSIBLE, "extensible", "user-defined checks and annotations" },
616915dd 74 { FK_FILES, "files", "control system files" } ,
75 { FK_FORMAT, "format", "control format of warning messages" } ,
76 { FK_GLOBALS, "globals", "use of global and file static variables" },
77 { FK_HEADERS, "headers", "control inclusion and generation of header files" },
78 { FK_HELP, "help", "on-line help" },
bb7c2085 79 { FK_BOUNDS, "memorybounds", "out-of-bounds memory accesses" },
80 { FK_HINTS, "hints", "control display of warning hints" },
81 { FK_SYSTEMFUNCTIONS, "systemfunctions", "special properties of exit and main" },
616915dd 82 { FK_IMPLICIT, "implicit", "control implicit annotations and interpretations" } ,
83 { FK_INIT, "initializations", "initialization files" } ,
84 { FK_ITER, "iterators", "checking iterator definitions and uses" } ,
85 { FK_LEAK, "leaks", "memory leaks" } ,
86 { FK_LIBS, "libraries", "loading and dumping of user and standard libraries" } ,
87 { FK_LIMITS, "limits", "violations of set limits" } ,
88 { FK_MACROS, "macros", "expansion, definition and use of macros" },
89 { FK_MEMORY, "memory", "memory management" } ,
90 { FK_MODIFIES, "modification", "modification errors" } ,
91 { FK_NAMES, "names", "naming conventions and limits" } ,
92 { FK_NULL, "null", "misuses of null pointers" } ,
93 { FK_NUMBERS, "numbers", "control type-checking of numeric types" } ,
94 { FK_OPS, "operations", "checking of primitive operations" } ,
95 { FK_PARAMS, "parameters", "function and macro parameters" } ,
96 { FK_SPEED, "performance", "speeding up checking" } ,
97 { FK_POINTER, "pointers", "pointers" } ,
98 { FK_PRED, "predicates", "condition test expressions" } ,
99 { FK_PREFIX, "prefixes", "set naming prefixes and control checking" } ,
100 { FK_PREPROC, "preproc", "defines and undefines for the preprocessor" } ,
101 { FK_PROTOS, "prototypes", "function prototypes" } ,
102 { FK_DEAD, "released", "using storage that has been deallocated" } ,
103 { FK_IGNORERET, "returnvals", "ignored return values" },
28bf4b0b 104 { FK_SECURITY, "security", "possible security vulnerability" },
616915dd 105 { FK_SPEC, "specifications", "checks involving .lcl specifications" } ,
106 { FK_SUPPRESS, "suppress", "local and global suppression of messages" } ,
107 { FK_TYPEEQ, "typeequivalence", "control what types are equivalent" } ,
108 { FK_BEHAVIOR, "undefined", "code with undefined or implementation-defined behavior" } ,
109 { FK_UNRECOG, "unrecognized", "unrecognized identifiers" } ,
110 { FK_UNSPEC, "unconstrained", "checking in the presence of unconstrained functions" } ,
28bf4b0b 111 { FK_WARNUSE, "warnuse", "use of possibly problematic function" } ,
bb7c2085 112 { FK_ITS4, "its4", "its4 compatibility flags (report warnings for uses of possibly insecure functions)" } ,
616915dd 113 { FK_SYNTAX, NULL, NULL } ,
114 { FK_TYPE, NULL, NULL } ,
115 { FK_SECRET, NULL, NULL } ,
116 { FK_OBSOLETE, NULL, NULL } ,
117 { FK_NONE, NULL, NULL } /* must be last */
118} ;
119
120typedef enum {
121 ARG_NONE,
4f43223c 122 ARG_NUMBER, /* number */
123 ARG_CHAR, /* char */
124 ARG_STRING, /* string */
125 ARG_FILE, /* filename (also a string) */
126 ARG_DIRECTORY, /* directory (also a string) */
127 ARG_PATH, /* path */
128 ARG_SPECIAL /* ? */
616915dd 129} argcode;
130
4f43223c 131static /*@observer@*/ cstring argcode_unparse (argcode arg)
132{
133 switch (arg)
134 {
135 case ARG_STRING: return cstring_makeLiteralTemp ("string");
136 case ARG_FILE: return cstring_makeLiteralTemp ("filename");
137 case ARG_DIRECTORY: return cstring_makeLiteralTemp ("directory");
138 case ARG_PATH: return cstring_makeLiteralTemp ("path");
139 case ARG_NUMBER: return cstring_makeLiteralTemp ("number");
140 case ARG_CHAR: return cstring_makeLiteralTemp ("character");
141 case ARG_NONE:
142 BADBRANCH;
143 case ARG_SPECIAL:
144 BADBRANCH;
145 }
4dd72714 146# ifdef WIN32
147/* Make Microsoft VC++ happy */
148# pragma warning (disable:4715)
149# endif
4f43223c 150}
151
e5081f8c 152# ifdef WIN32
153# pragma warning (enable:4715)
154# endif
155
616915dd 156typedef struct {
157 flagkind main;
158 flagkind sub;
159 bool isSpecial; /* setting this flag may set other flags (or values) */
160 bool isIdem; /* idempotent - always sets to TRUE */
161 bool isGlobal; /* cannot be set locally (using control comments) */
162 bool isModeFlag; /* set by modes */
163 argcode argtype;
164 /*@observer@*/ char *flag;
165 flagcode code;
166 /*@observer@*/ /*@null@*/ char *desc;
167 bn_mstring hint;
168 int nreported;
169 int nsuppressed;
170} fflag;
171
172typedef fflag flaglist[];
173
174# include "flags.def"
175
176/*@iter allFlags (yield observer fflag f); @*/
177# define allFlags(m_f) \
178 { /*@+enumint@*/ flagcode m_i; for (m_i = 0; m_i < NUMFLAGS; m_i++) { fflag m_f = flags[m_i]; /*@=enumint@*/
179# define end_allFlags }}
180
181static bn_mstring mode_names[] =
182{
183 "weak", "standard", "checks", "strict", NULL,
184};
185
186/*@iter allModes (yield bn_mstring modename)@*/
187# define allModes(m_m) \
188 { int m_ii = 0; while (mstring_isDefined (mode_names[m_ii])) \
189 { bn_mstring m_m = mode_names[m_ii]; m_ii++;
190
191# define end_allModes }}
192
193/*@+enumint@*/
194
4f43223c 195static cstring getFlagModeSettings (flagcode p_flag) /*@modifies internalState@*/ ;
616915dd 196static cstring describeFlagCode (flagcode p_flag) /*@*/ ;
197static cstringSList sortedFlags (void) /*@*/ ;
198static /*@observer@*/ cstring categoryName (flagkind p_kind) /*@*/ ;
8250fa4a 199
80489f0a 200static flagcode flags_identifyFlagAux (cstring p_s, bool p_quiet) /*@modifies g_warningstream@*/ ;
a956d444 201
8250fa4a 202# if 0
616915dd 203static /*@unused@*/ cstring listModes (void) /*@*/ ;
8250fa4a 204# endif
616915dd 205
206bool flagcode_isSpecialFlag (flagcode f)
207{
208 return (flags[f].isSpecial);
209}
210
211bool flagcode_isGlobalFlag (flagcode f)
212{
213 return (flags[f].isGlobal);
214}
215
216bool flagcode_isIdemFlag (flagcode f)
217{
218 return (flags[f].isIdem);
219}
220
221bool flagcode_isModeFlag (flagcode f)
222{
223 return (flags[f].isModeFlag);
224}
225
226bool flagcode_isNameChecksFlag (flagcode f)
227{
228 return (flags[f].main == FK_NAMES);
229}
230
aa9c1601 231bool flagcode_isHelpFlag (flagcode f)
232{
233 return f == FLG_HELP;
234}
235
80489f0a 236bool flagcode_isMessageControlFlag (flagcode f)
237{
238 /*
239 ** True if opt controls the display of messages.
240 ** These flags must be processed first.
241 */
242
243 return (f == FLG_SHOWSCAN
244 || f == FLG_WARNRC
245 || f == FLG_PARENFILEFORMAT
246 || f == FLG_MESSAGESTREAMSTDERR
247 || f == FLG_MESSAGESTREAMSTDOUT
248 || f == FLG_WARNINGSTREAMSTDERR
249 || f == FLG_WARNINGSTREAMSTDOUT
250 || f == FLG_ERRORSTREAMSTDERR
251 || f == FLG_ERRORSTREAMSTDOUT
252 || f == FLG_MESSAGESTREAM
253 || f == FLG_WARNINGSTREAM
254 || f == FLG_ERRORSTREAM
255 || f == FLG_STREAMOVERWRITE);
256}
257
616915dd 258/*
259** Internal consistency check on the flags.
260*/
261
262void flags_initMod ()
263{
264 allFlagCodes (code)
265 {
266 /*@+enumint@*/
267 if (flags[code].code != code)
268 {
28bf4b0b 269 fprintf (stderr,
270 "*** ERROR: inconsistent flag %s / %d / %d",
271 flags[code].flag,
272 flags[code].code, code);
273
616915dd 274 llbug (message ("*** ERROR: inconsistent flag %s / %d / %d",
275 cstring_fromChars (flags[code].flag),
276 flags[code].code, code));
277 }
278 /*@=enumint@*/
279 } end_allFlagCodes;
280}
281
282void
283summarizeErrors ()
284{
285 bool hadOne = FALSE;
286 int sumrep = 0;
287 int sumsup = 0;
288
289 char *buf = mstring_create (128);
290
291 allFlags (f)
292 {
293 if (f.nreported > 0 || f.nsuppressed > 0)
294 {
295 int nrep = f.nreported;
296 int nsup = f.nsuppressed;
297 cstring fs = cstring_fill (cstring_fromChars (f.flag), 23);
298
299 if (!hadOne)
300 {
301 llmsgplain (cstring_makeLiteral
302 ("\nError Type Reported Suppressed\n"
303 "=================== ======== ========="));
304 hadOne = TRUE;
305 }
306
f9264521 307 (void) snprintf (buf, 128, "%s%7d %9d", cstring_toCharsSafe (fs), nrep, nsup);
616915dd 308
309 sumrep += nrep;
310 sumsup += nsup;
311
312 cstring_free (fs);
313 llmsg (cstring_copy (cstring_fromChars (buf)));
314 }
315 } end_allFlags;
316
317 if (hadOne)
318 {
319 cstring ts = cstring_fill (cstring_makeLiteralTemp ("Total"), 23);
320
321 llmsglit (" ======== =========");
322
f9264521 323 (void) snprintf (buf, 128, "%s%7d %9d", cstring_toCharsSafe (ts), sumrep, sumsup);
616915dd 324 cstring_free (ts);
325 llmsgplain (cstring_copy (cstring_fromChars (buf)));
326 }
327
328 sfree (buf);
329}
330
331/*@+enumindex@*/
332
333void
334flagcode_recordError (flagcode f)
335{
336 if (f != INVALID_FLAG)
337 {
338 if (f == FLG_WARNFLAGS)
339 {
340 ; /* don't count these */
341 }
342 else
343 {
86d93ed3 344 /*drl bee: ec*/
345 /*drl bee: ec*/
616915dd 346 flags[f].nreported = flags[f].nreported + 1;
347 }
348 }
349 else
350 {
351 llcontbug (message ("flagcode_recordError: invalid flag: %d", (int) f));
352 }
353}
354
355void
356flagcode_recordSuppressed (flagcode f)
357{
358 llassertprint (f != INVALID_FLAG, ("flagcode: %s", flagcode_unparse (f)));
359
86d93ed3 360 /*drl bee: ec*/
361 /*drl bee: ec*/ flags[f].nsuppressed = flags[f].nsuppressed + 1;
616915dd 362}
363
364int
365flagcode_numReported (flagcode f)
366{
367 llassert (f != INVALID_FLAG);
368
369 return (flags[f].nreported);
370}
371
372/*@observer@*/ cstring
373flagcodeHint (flagcode f)
374{
375 llassert (f != INVALID_FLAG);
376
86d93ed3 377 /*drl bee: ec*/
616915dd 378 if (mstring_isDefined (flags[f].hint))
379 {
380 return (cstring_fromChars (flags[f].hint));
381 }
382 else
383 {
384 return (cstring_fromChars (flags[f].desc));
385 }
386}
387
388static int categorySize (flagkind kind) /*@*/
389{
390 int n = 0;
391
392
393 allFlags (f)
394 {
395 if (f.main == kind || f.sub == kind)
396 {
397 n++;
398 }
399 } end_allFlags;
400
401 return n;
402}
403
404flagkind identifyCategory (cstring s)
405{
406 int i;
407
408 for (i = 0; categories[i].kind != FK_NONE; i++)
409 {
86d93ed3 410 /*drl bee: mRug*/
616915dd 411 if (mstring_isDefined (categories[i].name))
412 {
413 if (cstring_equalLit (s, categories[i].name))
414 {
415 return categories[i].kind;
416 }
417 }
418 }
419
420 return FK_NONE;
421}
422
423static /*@observer@*/ cstring categoryName (flagkind kind)
424{
425 int i;
426
427 for (i = 0; categories[i].kind != FK_NONE; i++)
428 {
86d93ed3 429 /*drl bee: mrUg*/
616915dd 430 if (categories[i].kind == kind)
431 {
432 return (cstring_fromChars (categories[i].name));
433 }
434 }
435
436 return (cstring_makeLiteralTemp ("<No Category>"));
437}
438
439static int categoryIndex (flagkind kind)
440{
441 int i;
442
443 for (i = 0; categories[i].kind != FK_NONE; i++)
444 {
86d93ed3 445 /*drl bee: mRug*/
616915dd 446 if (categories[i].kind == kind)
447 {
448 return i;
449 }
450 }
451
452 return -1;
453}
454
455void printCategory (flagkind kind)
456{
457 int index = categoryIndex (kind);
458
459 llassert (index >= 0);
86d93ed3 460 /*drl bee: mRug*/
616915dd 461 llmsg (message ("%s (%d flags)\n\3%s\n\n",
462 cstring_fromChars (categories[index].name),
463 categorySize (kind),
464 cstring_fromChars (categories[index].describe)));
465
466 allFlags (f)
467 {
468 if (f.main == kind || f.sub == kind)
469 {
470 llmsg (message (" %s\n\6%q", cstring_fromChars (f.flag),
471 describeFlagCode (f.code)));
472 }
473 } end_allFlags;
474}
475
476void
477listAllCategories (void)
478{
479 int i;
480
481 for (i = 0; categories[i].kind != FK_NONE; i++)
482 {
86d93ed3 483 /*drl bee: mRug*/
616915dd 484 flagkind kind = categories[i].kind ;
485
486 if (categories[i].describe != NULL)
487 {
488 llmsg (message ("%s (%d flags)\n\3%s",
489 categoryName (kind),
490 categorySize (kind),
491 cstring_fromChars (categories[i].describe)));
492 }
493 }
494}
495
496void
497printAllFlags (bool desc, bool full)
498{
499 if (full)
500 {
501 cstringSList fl = sortedFlags ();
502
503 cstringSList_elements (fl, el)
504 {
6b654b9a 505 /*@i22@*/ /*find out why this is necessary*/
506 cstring tmp;
507 tmp = cstring_copy(el);
508 llmsg (message ("%q\n\n", describeFlag (tmp)));
509 cstring_free(tmp);
616915dd 510 } end_cstringSList_elements ;
511
512 cstringSList_free (fl);
513 }
514 else
515 {
516 allFlags (f)
517 {
518 if (f.code != INVALID_FLAG && f.main != FK_OBSOLETE)
519 {
520 if (mstring_isDefined (f.desc))
521 {
522 if (desc)
523 {
524 llmsg (message ("%s --- %s", cstring_fromChars (f.flag),
525 cstring_fromChars (f.desc)));
526 }
527 }
528 }
529 } end_allFlags;
530 }
531}
532
4f43223c 533void
45569d72 534printFlagManual (bool html)
4f43223c 535{
536 /*
537 ** Prints all flags by category, in order they appear in flags.def
538 */
539
540 flagkind lastCategory = FK_NONE;
541
542 allFlags (f) {
543 cstring flagname;
544 cstring flagtype = cstring_undefined;
545
546 if (f.main != lastCategory)
547 {
45569d72 548 if (html)
549 {
550 llmsg (message ("\n<h4>%s</h4>\n", categoryName (f.main)));
551 }
552 else
553 {
554 llmsg (message ("\n%s\n%s\n",
555 categoryName (f.main),
556 cstring_makeLiteralTemp ("===================================")));
557 }
4f43223c 558
559 lastCategory = f.main;
560 }
561
562 if (f.argtype == ARG_NONE || f.argtype == ARG_SPECIAL)
563 {
45569d72 564 if (html)
565 {
566 flagname = message ("<tt>%s</tt>", cstring_fromChars (f.flag));
567 }
568 else
569 {
570 flagname = cstring_fromCharsNew (f.flag);
571 }
4f43223c 572 }
573 else
574 {
575 if (flagcode_hasString (f.code))
576 {
45569d72 577 if (html)
578 {
579 flagname = message ("<tt>%s <em>&lt;%s&gt;</em></tt>",
580 cstring_fromChars (f.flag), argcode_unparse (f.argtype));
581 }
582 else
583 {
584 flagname = message ("%s <%s>", cstring_fromChars (f.flag), argcode_unparse (f.argtype));
585 }
586
982cc10b 587 if (cstring_isDefined (context_getString (f.code)))
588 {
45569d72 589 if (html)
590 {
591 flagname = message ("%q <font color=\"blue\">[%s]</font>", flagname,
592 context_getString (f.code));
593 }
594 else
595 {
596 flagname = message ("%q [%s]", flagname,
597 context_getString (f.code));
598 }
982cc10b 599 }
4f43223c 600 }
601 else if (f.argtype == ARG_CHAR)
602 {
45569d72 603 if (html)
604 {
605 flagname = message ("<tt>%s <em>&lt;%s&gt;</em></tt> <font color=\"blue\">[%c]</font>",
606 cstring_fromChars (f.flag), argcode_unparse (f.argtype),
607 (char) context_getValue (f.code));
608 }
609 else
610 {
611 flagname = message ("%s <%s> [%c]", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
612 (char) context_getValue (f.code));
613 }
4f43223c 614 }
615 else
616 {
617 llassert (f.argtype == ARG_NUMBER);
45569d72 618
619 if (html)
620 {
621 flagname = message ("<tt>%s <em>&lt;%s&gt;</em> <font color=\"blue\">[%d]</font>",
622 cstring_fromChars (f.flag), argcode_unparse (f.argtype),
623 context_getValue (f.code));
624 }
625 else
626 {
627 flagname = message ("%s <%s> [%d]", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
628 context_getValue (f.code));
629 }
4f43223c 630 }
631 }
632
633 if (f.isIdem)
634 {
45569d72 635 if (html)
636 {
637 flagtype = message("%q<font color=\"green\">-</font>", flagtype);
638 }
639 else
640 {
641 flagtype = message("%q<->", flagtype);
642 }
4f43223c 643 }
4f43223c 644
645 if (f.isGlobal)
646 {
45569d72 647 if (html)
648 {
649 flagtype = message ("%q<font color=\"green\"><em>global</em></font>", flagtype);
650 }
651 else
652 {
653 flagtype = message ("%q<G>", flagtype);
654 }
4f43223c 655 }
656
657 if (f.isSpecial)
658 {
45569d72 659 if (html)
660 {
661 flagtype = message ("%q<font color=\"orange\"><em>shortcut</em></font>", flagtype);
662 }
663 else
664 {
665 flagtype = message("%q<S>", flagtype);
666 }
4f43223c 667 }
668
669 if (f.isModeFlag)
670 {
45569d72 671 if (html)
672 {
673 flagtype = message ("%q mode:<tt>%q</tt>>", flagtype, getFlagModeSettings (f.code));
674 }
675 else
676 {
677 flagtype = message ("%q<M:%q>", flagtype, getFlagModeSettings (f.code));
678 }
4f43223c 679 }
680 else /* its a plain flag */
681 {
45569d72 682 if (html)
683 {
684 flagtype = message ("%q plain:<tt>%s</tt>", flagtype,
685 cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-"));
686 }
687 else
688 {
689 flagtype = message ("%q<P:%s>", flagtype,
690 cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-"));
691 }
4f43223c 692 }
bb7c2085 693
4f43223c 694 llmsg (message ("%s: %s", flagname, flagtype));
bb7c2085 695
45569d72 696 if (html)
697 {
698 llgenindentmsgnoloc (cstring_makeLiteral ("<blockquote>"));
699 }
700
bb7c2085 701 if (mstring_isDefined (f.hint))
702 {
703 llgenindentmsgnoloc (cstring_fromCharsNew (f.hint));
704 }
705 else
706 {
707 llgenindentmsgnoloc (message ("%q.", cstring_capitalize (cstring_fromChars (f.desc))));
708 }
45569d72 709
710 if (html)
711 {
712 llgenindentmsgnoloc (cstring_makeLiteral ("</blockquote>"));
713 }
4f43223c 714 } end_allFlags ;
715}
716
616915dd 717cstring
718describeFlagCode (flagcode flag)
719{
720 cstring ret = cstring_undefined;
721 fflag f;
4f43223c 722
616915dd 723 if (flagcode_isInvalid (flag))
724 {
725 return (cstring_makeLiteral ("<invalid>"));
726 }
727
728 context_resetAllFlags ();
729
86d93ed3 730 /*drl bee: mRug*/
616915dd 731 f = flags[flag];
732 ret = cstring_copy (cstring_fromChars (f.desc));
616915dd 733
734 if (f.sub != FK_NONE)
735 {
736 ret = message ("%q\nCategories: %s, %s",
737 ret,
738 categoryName (f.main),
739 categoryName (f.sub));
740 }
741 else
742 {
743 if (f.main != FK_NONE)
744 {
745 cstring cname = categoryName (f.main);
746
747 if (cstring_isDefined (cname))
748 {
749 ret = message ("%q\nCategory: %s",
750 ret, cname);
751 }
752 }
753 }
4f43223c 754
616915dd 755 if (f.isModeFlag)
756 {
4f43223c 757 ret = message ("%q\nMode Settings: %q",
758 ret, getFlagModeSettings (flag));
616915dd 759 }
760 else
761 {
762 ret = message ("%q\nDefault Setting: %s",
763 ret,
4f43223c 764 cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
616915dd 765 }
4f43223c 766
616915dd 767 if (f.isGlobal)
768 {
769 ret = message("%q\nSet globally only", ret);
770 }
771 else
772 {
773 ret = message("%q\nSet locally", ret);
774 }
4f43223c 775
616915dd 776 switch (f.argtype)
777 {
778 case ARG_NONE:
779 case ARG_SPECIAL:
780 break;
4f43223c 781 case ARG_NUMBER:
782 ret = message("%q\nNumeric Argument. Default: %d",
783 ret,
784 context_getValue (flag));
785 break;
786 case ARG_CHAR:
787 ret = message("%q\nCharacter Argument. Default: %h",
788 ret, (char) context_getValue (flag));
616915dd 789 break;
790 case ARG_STRING:
4f43223c 791 case ARG_FILE:
792 case ARG_PATH:
793 case ARG_DIRECTORY:
794 {
616915dd 795 if (cstring_isDefined (context_getString (flag)))
796 {
4f43223c 797 ret = message("%q\n%q argument. Default: %s",
616915dd 798 ret,
4f43223c 799 cstring_capitalize (argcode_unparse (f.argtype)),
616915dd 800 context_getString (flag));
801 }
802 else
803 {
4f43223c 804 ret = message("%q\n%s argument. No default.",
805 ret,
806 cstring_capitalize (argcode_unparse (f.argtype)));
616915dd 807 }
808 break;
4f43223c 809 }
616915dd 810 }
4f43223c 811
616915dd 812 if (mstring_isDefined (f.hint))
813 {
814 ret = message("%q\n\3%s", ret, cstring_fromChars (f.hint));
815 }
4f43223c 816
616915dd 817 return ret;
818}
4f43223c 819
820static cstring getFlagModeSettings (flagcode flag)
821{
822 cstring res = cstring_undefined;
823
824 allModes (mname)
825 {
982cc10b 826 context_setModeNoWarn (cstring_fromChars (mname));
4f43223c 827
828 res = message ("%q%s", res, cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
829 } end_allModes;
830
831 return res;
832}
616915dd 833
834cstring
835describeFlag (cstring flagname)
836{
837 cstring oflagname = cstring_copy (flagname);
a956d444 838 flagcode f = flags_identifyFlag (flagname);
616915dd 839
840 if (flagcode_isSkip (f))
841 {
842 cstring_free (oflagname);
843 return cstring_undefined;
844 }
845 else if (flagcode_isValid (f))
846 {
847 if (cstring_equal (flagname, oflagname))
848 {
849 cstring_free (oflagname);
850 return (message ("%s\n\3%q", flagname, describeFlagCode (f)));
851 }
852 else
853 {
854 return (message ("%q (standardized name: %s)\n\3%q",
855 oflagname, flagname, describeFlagCode (f)));
856 }
857 }
858 else
859 {
aa9c1601 860 if (flags_isModeName (flagname))
616915dd 861 {
862 cstring_free (oflagname);
863
864 return
4f43223c 865 (message ("%s: predefined mode (see Manual for information)",
616915dd 866 flagname));
867 }
868 else
869 {
870 return (message ("%q: <invalid flag>", oflagname));
871 }
872 }
873}
874
875static cstringSList
876sortedFlags (void)
877{
878 cstringSList s = cstringSList_new ();
879
880 allFlags (f)
881 {
882 if (f.desc != NULL)
883 {
884 s = cstringSList_add (s, cstring_fromChars (f.flag));
885 }
886 } end_allFlags;
887
888 cstringSList_alphabetize (s);
889
890 return s;
891}
892
893void printAlphaFlags ()
894{
895 cstringSList fl = sortedFlags ();
896
897 cstringSList_printSpaced (fl, 3, 1, context_getLineLen () - 25);
898 cstringSList_free (fl);
899}
28bf4b0b 900
616915dd 901/*@observer@*/ cstring
28bf4b0b 902flagcode_unparse (flagcode code)
616915dd 903{
7272a1c1 904 if (code == INVALID_FLAG)
905 {
906 return cstring_makeLiteralTemp ("<invalid flag>");
907 }
908
616915dd 909 return cstring_fromChars (flags[code].flag);
910}
911
912/*
913** Transforms a flag into its cannonical form.
914**
915** The following transformations are made:
916**
917** function -> fcn
918** variable -> var
919** constant -> const
920** iterator -> iter
921** parameter -> param
922** unrecognized -> unrecog
923** qualifier -> qual
924** declaration -> decl
925** globalias -> (no change)
926** global -> glob
927** modifies -> mods
928** modify -> mod
929** pointer -> ptr
930** implies -> imp
931** implicit -> imp
932** implied -> imp
933** unconstrained -> unspec
934** unconst -> unspec
935** memory -> mem
936** length -> len
937*/
938
92b2ba2c 939static /*@only@*/ cstring
616915dd 940canonicalizeFlag (cstring s)
941{
942 int i = 0;
92b2ba2c 943 cstring res = cstring_copy (s);
616915dd 944 static bn_mstring transform[] =
945 {
946 "function", "fcn",
947 "variable", "var",
948 "constant", "const",
949 "iterator", "iter",
950 "parameter", "param",
951 "unrecognized", "unrecog",
952 "qualifier", "qual",
953 "declaration", "decl",
954 "globals", "globs",
955 "modifies", "mods",
956 "modify", "mod",
957 "pointer", "ptr",
958 "implies", "imp",
959 "implicit", "imp",
960 "implied", "imp",
961 "unconstrained", "uncon",
962 "unconst", "uncon",
963 "memory", "mem",
964 "length", "len",
965 "return", "ret",
966 "system", "sys",
967 NULL
968 } ;
969 char *current;
86d93ed3 970
971 /*drl bee: ia*/
616915dd 972 while ((current = transform[i]) != NULL)
973 {
92b2ba2c 974 if (cstring_containsLit (res, current))
616915dd 975 {
92b2ba2c 976 cstring_replaceLit (res, current, transform[i+1]);
616915dd 977 }
978 i += 2;
979 }
980
981 /* remove whitespace, -'s, and _'s */
92b2ba2c 982 cstring_stripChars (res, " -_");
983 return res;
616915dd 984}
985
986flagcode
a956d444 987flags_identifyFlag (cstring s)
988{
989 return flags_identifyFlagAux (s, FALSE);
990}
991
992flagcode
993flags_identifyFlagQuiet (cstring s)
994{
995 return flags_identifyFlagAux (s, TRUE);
996}
997
998static flagcode
999flags_identifyFlagAux (cstring s, bool quiet)
616915dd 1000{
92b2ba2c 1001 cstring cflag;
1002 flagcode res;
1003
616915dd 1004 if (cstring_length (s) == 0) {
1005 /* evs 2000-06-25: A malformed flag. */
1006 return INVALID_FLAG;
1007 }
1008
1009 if (cstring_firstChar (s) == 'I')
1010 {
aa9c1601 1011 return FLG_INCLUDEPATH; /* no space required after -I */
616915dd 1012 }
1013
1014 if (cstring_firstChar (s) == 'S')
1015 {
aa9c1601 1016 return FLG_SPECPATH; /* no space required after -S */
616915dd 1017 }
1018
1019 if (cstring_firstChar (s) == 'D')
1020 {
aa9c1601 1021 return FLG_DEFINE; /* no space required after -D */
616915dd 1022 }
1023
1024 if (cstring_firstChar (s) == 'U')
1025 {
aa9c1601 1026 return FLG_UNDEFINE; /* no space required after -D */
616915dd 1027 }
1028
92b2ba2c 1029 cflag = canonicalizeFlag (s);
1030 res = INVALID_FLAG;
616915dd 1031
1032 allFlags (f)
1033 {
92b2ba2c 1034 if (cstring_equal (cstring_fromChars (f.flag), cflag))
616915dd 1035 {
92b2ba2c 1036 res = f.code;
1037 break;
616915dd 1038 }
1039 } end_allFlags;
616915dd 1040
92b2ba2c 1041 if (res == INVALID_FLAG)
616915dd 1042 {
92b2ba2c 1043 /*
1044 ** Synonyms
1045 */
1046
1047 if (cstring_equalLit (cflag, "pred"))
a956d444 1048 {
92b2ba2c 1049 res = FLG_PREDBOOL;
1050 }
1051 else if (cstring_equalLit (cflag, "modobserverstrict"))
1052 {
1053 res = FLG_MODOBSERVERUNCON;
1054 }
1055 else if (cstring_equalLit (cflag, "czechnames"))
1056 {
1057 res = FLG_CZECH;
a956d444 1058 }
92b2ba2c 1059 else if (cstring_equalLit (cflag, "slovaknames"))
1060 {
1061 res = FLG_SLOVAK;
1062 }
1063 else if (cstring_equalLit (cflag, "czechoslovaknames"))
1064 {
1065 res = FLG_CZECHOSLOVAK;
1066 }
1067 else if (cstring_equalLit (cflag, "globunspec")
1068 || cstring_equalLit (cflag, "globuncon"))
1069 {
1070 res = FLG_GLOBUNSPEC;
1071 }
1072 else if (cstring_equalLit (cflag, "modglobsunspec")
1073 || cstring_equalLit (cflag, "modglobsuncon")
1074 || cstring_equalLit (cflag, "modglobsnomods"))
1075 {
1076 res = FLG_MODGLOBSUNSPEC;
1077 }
1078 else if (cstring_equalLit (cflag, "export"))
1079 {
1080 res = FLG_EXPORTANY;
1081 }
1082 else if (cstring_equalLit (cflag, "macrospec"))
1083 {
1084 res = FLG_MACRODECL;
1085 }
1086 else if (cstring_equalLit (cflag, "ansireservedlocal"))
1087 {
abd7f895 1088 res = FLG_ISORESERVEDLOCAL;
92b2ba2c 1089 }
1090 else if (cstring_equalLit (cflag, "warnposix"))
1091 {
1092 res = FLG_WARNPOSIX;
1093 }
1094 else if (cstring_equalLit (cflag, "defuse"))
1095 {
1096 res = FLG_USEDEF;
1097 }
1098 else if (cstring_equalLit (cflag, "macroundef"))
1099 {
1100 res = FLG_MACROUNDEF;
1101 }
1102 else if (cstring_equalLit (cflag, "showcol"))
1103 {
1104 res = FLG_SHOWCOL;
1105 }
1106 else if (cstring_equalLit (cflag, "intbool"))
1107 {
1108 res = FLG_BOOLINT;
1109 }
1110 else if (cstring_equalLit (cflag, "intchar"))
1111 {
1112 res = FLG_CHARINT;
1113 }
1114 else if (cstring_equalLit (cflag, "intenum"))
1115 {
1116 res = FLG_ENUMINT;
1117 }
81fc136a 1118 else if (cstring_equalLit (cflag, "intlong"))
1119 {
1120 res = FLG_LONGINT;
1121 }
1122 else if (cstring_equalLit (cflag, "intshort"))
1123 {
1124 res = FLG_SHORTINT;
1125 }
92b2ba2c 1126 /*
1127 ** Backwards compatibility for our American friends...
1128 */
616915dd 1129
92b2ba2c 1130 else if (cstring_equalLit (cflag, "ansilib"))
1131 {
1132 res = FLG_ANSILIB;
1133 }
1134 else if (cstring_equalLit (cflag, "ansistrictlib"))
1135 {
1136 res = FLG_STRICTLIB;
1137 }
1138 else if (cstring_equalLit (cflag, "skipansiheaders"))
1139 {
abd7f895 1140 res = FLG_SKIPISOHEADERS;
92b2ba2c 1141 }
1142 else if (cstring_equalLit (cflag, "ansireserved"))
1143 {
abd7f895 1144 res = FLG_ISORESERVED;
92b2ba2c 1145 }
1146 else if (cstring_equalLit (cflag, "ansireservedinternal"))
1147 {
abd7f895 1148 res = FLG_ISORESERVEDLOCAL;
92b2ba2c 1149 }
1150
1151 /*
1152 ** Obsolete Flags
1153 */
1154
1155 else if (cstring_equalLit (cflag, "accessunspec"))
1156 {
1157 if (!quiet)
1158 {
1159 llerror_flagWarning
1160 (cstring_makeLiteral
1161 ("accessunspec flag is no longer supported. It has been replaced by accessmodule, accessfile and "
1162 "accessfunction to provide more precise control of accessibility "
1163 "of representations. For more information, "
1164 "see splint -help accessmodule"));
1165 }
1166
1167 res = SKIP_FLAG;
1168 }
1169 else if (cstring_equalLit (cflag, "ansilimits"))
1170 {
27c9e640 1171 llerror_flagWarning
1172 (cstring_makeLiteral
1173 ("ansilimits flag is no longer supported. It has been replaced by ansi89limits and "
1174 "iso99limits to select either the lower translation limits imposed by the ANSI89 "
1175 "standard or the typically higher limits prescribed by ISO C99."));
92b2ba2c 1176
1177 res = SKIP_FLAG;
1178 }
1179 else if (cstring_equalLit (cflag, "staticmods"))
a956d444 1180 {
92b2ba2c 1181 if (!quiet)
1182 {
1183 llerror_flagWarning
1184 (cstring_makeLiteral
1185 ("staticmods flag is obsolete. You probably "
1186 "want impcheckmodstatics. For more information, "
1187 "see splint -help impcheckmodstatics"));
1188 }
1189
1190 res = SKIP_FLAG;
a956d444 1191 }
92b2ba2c 1192 else if (cstring_equalLit (cflag, "bool"))
a956d444 1193 {
92b2ba2c 1194 if (!quiet)
1195 {
1196 llerror_flagWarning
1197 (cstring_makeLiteral ("bool flag is obsolete. It never really "
1198 "made sense in the first place."));
1199 }
1200
1201 res = SKIP_FLAG;
a956d444 1202 }
92b2ba2c 1203 else if (cstring_equalLit (cflag, "shiftsigned"))
a956d444 1204 {
92b2ba2c 1205 if (!quiet)
1206 {
1207 llerror_flagWarning
1208 (cstring_makeLiteral ("shiftsigned flag is obsolete. You probably "
06418c9b 1209 "want bitwisesigned, shiftnegative or shiftimplementation."));
92b2ba2c 1210 }
1211
1212 res = SKIP_FLAG;
a956d444 1213 }
92b2ba2c 1214 else if (cstring_equalLit (cflag, "ansi"))
a956d444 1215 {
92b2ba2c 1216 if (!quiet)
1217 {
1218 llerror_flagWarning
1219 (cstring_makeLiteral ("ansi flag is obsolete. You probably "
1220 "want noparams and/or oldstyle."));
1221 }
1222
1223 res = SKIP_FLAG;
a956d444 1224 }
80489f0a 1225 else if (cstring_equalLit (cflag, "usestderr"))
1226 {
1227 if (!quiet)
1228 {
1229 llerror_flagWarning
1230 (cstring_makeLiteral
1231 ("usestderr flag is obsolete. This has been replaced "
1232 "by more precise flags for controlling the warning, "
1233 "status message and fatal error streams independently: message-stream-stdout, "
1234 "message-stream-stderr, message-stream <file>, "
1235 "warning-stream-stdout, warning-stream-stderr, warning-stream <file>, "
1236 "error-stream-stdout, error-stream-stderr, error-stream <file>."));
1237 }
1238
1239 res = SKIP_FLAG;
1240 }
1241
92b2ba2c 1242 else if (cstring_equalLit (cflag, "stdio"))
a956d444 1243 {
92b2ba2c 1244 if (!quiet)
1245 {
1246 llerror_flagWarning
1247 (cstring_makeLiteral
1248 ("stdio flag is obsolete. You may "
1249 "want strictlib or one of the gloabls "
1250 "checking flags. For more information, "
1251 "see splint -help strictlib or splint -help flags globals"));
1252 }
1253
1254 res = SKIP_FLAG;
1255 }
aa9c1601 1256 else if (flags_isModeName (cflag))
1257 {
1258 res = MODENAME_FLAG;
140c27a8 1259 }
92b2ba2c 1260 else
1261 {
1262 res = INVALID_FLAG;
a956d444 1263 }
a956d444 1264 }
92b2ba2c 1265
1266 cstring_free (cflag);
1267 return res;
616915dd 1268}
1269
16c024b5 1270void flags_setValueFlag (flagcode opt, cstring arg)
616915dd 1271{
1272 switch (opt)
1273 {
1274 case FLG_EXPECT:
1275 case FLG_LCLEXPECT:
1276 case FLG_LIMIT:
1277 case FLG_LINELEN:
28bf4b0b 1278 case FLG_INDENTSPACES:
16c024b5 1279 case FLG_LOCINDENTSPACES:
28bf4b0b 1280 case FLG_BUGSLIMIT:
616915dd 1281 case FLG_EXTERNALNAMELEN:
1282 case FLG_INTERNALNAMELEN:
1283 case FLG_CONTROLNESTDEPTH:
1284 case FLG_STRINGLITERALLEN:
1285 case FLG_NUMSTRUCTFIELDS:
1286 case FLG_NUMENUMMEMBERS:
1287 case FLG_INCLUDENEST:
1288 {
1289 int val = cstring_toPosInt (arg);
1290
1291 if (val < 0)
1292 {
1293 llerror
1294 (FLG_BADFLAG,
1295 message
1296 ("Flag %s must be followed by a positive number number. "
1297 "Followed by %s",
1298 flagcode_unparse (opt), arg));
1299 }
1300 else
1301 {
28bf4b0b 1302 context_setValueAndFlag (opt, val);
616915dd 1303 }
1304 }
1305 break;
1306 case FLG_COMMENTCHAR:
1307 {
1308 if (cstring_length (arg) != 1)
1309 {
1310 llfatalerrorLoc
1311 (message
1312 ("Flag %s should be followed by a single character. Followed by %s",
1313 flagcode_unparse (opt), arg));
1314 }
1315 else
1316 {
1317 context_setCommentMarkerChar (cstring_firstChar (arg));
1318 }
1319 }
1320 break;
16c024b5 1321 BADDEFAULT;
616915dd 1322 }
1323}
1324
16c024b5 1325void flags_setStringFlag (flagcode opt, /*@only@*/ cstring arg)
616915dd 1326{
1327 switch (opt)
1328 {
1329 case FLG_TMPDIR:
1330 {
1331 if (cstring_lastChar (arg) == CONNECTCHAR)
1332 {
1333 context_setString (opt, arg);
1334 }
1335 else
1336 {
1337 context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1338 }
1339 break;
1340 }
1341 default:
1342 {
1343 context_setString (opt, arg);
1344 break;
1345 }
1346 }
1347}
1348
1349cstring
1350describeModes ()
1351{
1352 cstring s = cstring_makeLiteral ("Flag ");
1353 cstringSList sflags = sortedFlags ();
1354
1355 allModes (modename)
1356 {
1357 s = message ("%q%9s", s, cstring_fromChars (modename));
1358 } end_allModes;
1359
1360 s = message ("%q\n", s);
1361
1362 cstringSList_elements (sflags, flagname)
1363 {
a956d444 1364 flagcode code = flags_identifyFlag (flagname);
616915dd 1365 fflag currentflag = flags[code];
1366
1367 if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1368 {
1369 s = message ("%q\n%27s", s,
1370 cstring_fromChars (currentflag.flag));
1371
1372 allModes (modename)
1373 {
1374 context_setMode (cstring_fromChars (modename));
1375
1376 if (context_getFlag (code))
1377 {
1378 s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1379 }
1380 else
1381 {
1382 s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1383 }
1384
1385 context_resetModeFlags ();
1386 } end_allModes;
1387 }
1388 } end_cstringSList_elements;
1389
1390 cstringSList_free (sflags);
1391
1392 s = cstring_appendChar (s, '\n');
1393
1394 return (s);
1395}
1396
8250fa4a 1397# if 0
ee229125 1398static /*@unused@*/ cstring
616915dd 1399listModes (void)
1400{
1401 cstring s = cstring_makeLiteral ("\t");
1402 int i = 0;
1403
1404 allModes (modename)
1405 {
1406 if (i != 0 && (i % 4 == 0))
1407 {
1408 s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1409 }
1410 else
1411 {
1412 s = message ("%q%15s", s, cstring_fromChars (modename));
1413 }
1414 i++;
1415 } end_allModes;
1416
1417 return s;
1418}
8250fa4a 1419# endif
616915dd 1420
1421bool
aa9c1601 1422flags_isModeName (cstring s)
616915dd 1423{
1424 allModes (modename)
1425 {
1426 if (mstring_isDefined (modename))
1427 {
1428 if (cstring_equalLit (s, modename))
1429 {
1430 return TRUE;
1431 }
1432 }
1433 } end_allModes;
1434
1435 return FALSE;
1436}
1437
1438extern bool flagcode_hasArgument (flagcode f)
1439{
1440 return (flags[f].argtype != ARG_NONE);
1441}
1442
4f43223c 1443extern bool flagcode_hasNumber (flagcode f)
1444{
1445 return (flags[f].argtype == ARG_NUMBER);
1446}
1447
1448extern bool flagcode_hasChar (flagcode f)
616915dd 1449{
4f43223c 1450 return (flags[f].argtype == ARG_CHAR);
616915dd 1451}
1452
1453extern bool flagcode_hasString (flagcode f)
1454{
4f43223c 1455 return (flags[f].argtype == ARG_STRING
1456 || flags[f].argtype == ARG_FILE
1457 || flags[f].argtype == ARG_DIRECTORY
1458 || flags[f].argtype == ARG_PATH);
616915dd 1459}
1460
1461extern int flagcode_valueIndex (flagcode f)
1462{
1463 /*@unchecked@*/ static bool initialized = FALSE;
1464 int i;
1465 /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
616915dd 1466
1467 if (!initialized)
1468 {
1469 int nv = 0;
1470
1471 allFlagCodes (code)
1472 {
4f43223c 1473 if (flagcode_hasNumber (code) || flagcode_hasChar (code))
616915dd 1474 {
1475 llassert (nv < NUMVALUEFLAGS);
28bf4b0b 1476 DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
616915dd 1477 valueFlags[nv] = code;
28bf4b0b 1478 nv++;
616915dd 1479 }
1480 } end_allFlagCodes;
1481
1482 llassertprint (nv == NUMVALUEFLAGS,
28bf4b0b 1483 ("Number of value flags: %d (expected %d)",
1484 nv, (int) NUMVALUEFLAGS));
616915dd 1485 initialized = TRUE;
1486 }
1487
1488 for (i = 0; i < NUMVALUEFLAGS; i++)
1489 {
1490 /* static valueFlags must be defined */
86d93ed3 1491 /*@-usedef@*/
1492 /*drl bee: sta*/
1493 if (f == valueFlags[i]) /*@=usedef@*/
616915dd 1494 {
1495 return i;
1496 }
1497 }
1498
28bf4b0b 1499 fprintf (stderr, "Cannot find value flag: %d", (int) f);
1500 exit (EXIT_FAILURE);
1501 /* Cannot do this...might call recursively...
1502 llfatalbug (message ("Cannot fine value flag: %d", (int) f));
616915dd 1503 BADEXIT;
28bf4b0b 1504 */
616915dd 1505}
1506
1507extern int flagcode_stringIndex (flagcode f)
1508{
1509 /*@unchecked@*/ static bool initialized = FALSE;
1510 /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1511 int i;
1512
1513
1514 if (!initialized)
1515 {
1516 int nv = 0;
1517
1518 allFlagCodes (code)
1519 {
1520 if (flagcode_hasString (code))
1521 {
1522 llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1523 stringFlags[nv] = code;
1524 nv++;
1525 }
1526 } end_allFlagCodes;
1527
1528 llassertprint (nv == NUMSTRINGFLAGS,
1529 ("number of string flags: %d (expected %d)",
1530 nv, NUMSTRINGFLAGS));
1531 initialized = TRUE;
1532 }
1533
1534 for (i = 0; i < NUMSTRINGFLAGS; i++)
1535 {
86d93ed3 1536 /*drl bee: sta*/
616915dd 1537 /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1538 {
1539 return i;
1540 }
1541 }
1542
1543 llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1544 BADEXIT;
1545}
1546
1547bool flagcode_isNamePrefixFlag (flagcode f)
1548{
1549 switch (f)
1550 {
1551 case FLG_MACROVARPREFIX:
1552 case FLG_TAGPREFIX:
1553 case FLG_ENUMPREFIX:
1554 case FLG_FILESTATICPREFIX:
1555 case FLG_GLOBPREFIX:
1556 case FLG_TYPEPREFIX:
1557 case FLG_EXTERNALPREFIX:
1558 case FLG_LOCALPREFIX:
1559 case FLG_UNCHECKEDMACROPREFIX:
1560 case FLG_CONSTPREFIX:
1561 case FLG_ITERPREFIX:
1562 case FLG_DECLPARAMPREFIX:
1563 return TRUE;
1564 default:
1565 return FALSE;
1566 }
1567}
140c27a8 1568
1569static cstring findLarchPathFile (/*@temp@*/ cstring s)
aa9c1601 1570{
140c27a8 1571 cstring pathName;
1572 filestatus status;
1573
1574 status = osd_getPath (context_getLarchPath (), s, &pathName);
1575
1576 if (status == OSD_FILEFOUND)
1577 {
1578 return pathName;
1579 }
1580 else if (status == OSD_FILENOTFOUND)
1581 {
1582 showHerald ();
1583 lldiagmsg (message ("Cannot find file on LARCH_PATH: %s", s));
1584 }
1585 else if (status == OSD_PATHTOOLONG)
1586 {
1587 /* Directory and filename are too long. Report error. */
1588 llbuglit ("soure_getPath: Filename plus directory from search path too long");
1589 }
1590 else
1591 {
1592 BADBRANCH;
1593 }
1594
1595 return cstring_undefined;
1596}
1597
1598static void addLarchPathFile (fileIdList files, /*@temp@*/ cstring s)
1599{
1600 cstring pathName = findLarchPathFile (s);
1601
1602 if (cstring_isDefined (pathName))
1603 {
1604 if (fileTable_exists (context_fileTable (), pathName))
1605 {
1606 showHerald ();
1607 lldiagmsg (message ("File listed multiple times: %s", pathName));
1608 cstring_free (pathName);
1609 }
1610 else
1611 {
1612 fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), pathName));
1613 }
1614 }
1615}
1616
1617
1618static void addFile (fileIdList files, /*@only@*/ cstring s)
1619{
1620 if (fileTable_exists (context_fileTable (), s))
1621 {
1622 showHerald ();
1623 lldiagmsg (message ("File listed multiple times: %s", s));
1624 cstring_free (s);
1625 }
1626 else
1627 {
1628 fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), s));
1629 }
1630}
1631
1632static void addXHFile (fileIdList files, /*@temp@*/ cstring s)
1633{
1634 cstring pathName = findLarchPathFile (s);
1635
1636 if (cstring_isDefined (pathName))
1637 {
1638 if (fileTable_exists (context_fileTable (), pathName))
1639 {
1640 showHerald ();
1641 lldiagmsg (message ("File listed multiple times: %s", s));
1642 }
1643 else
1644 {
1645 fileIdList_add (files, fileTable_addXHFile (context_fileTable (), pathName));
1646 }
1647 }
aa9c1601 1648
140c27a8 1649 cstring_free (pathName);
1650}
1651
1652void
1653flags_processFlags (bool inCommandLine,
1654 fileIdList xfiles,
1655 fileIdList cfiles,
1656 fileIdList lclfiles,
1657 fileIdList mtfiles,
6fcd0b1e 1658 cstringList *passThroughArgs,
140c27a8 1659 int argc, char **argv)
1660{
1661 int i;
1662 cstringSList fl = cstringSList_undefined;
1663
aa9c1601 1664 for (i = 0; i < argc; i++)
1665 {
140c27a8 1666 char *thisarg;
1667
1668 llassert (argv != NULL);
1669 thisarg = argv[i];
ce7034f0 1670
1671 DPRINTF (("process thisarg [%d]: %s", i, thisarg));
140c27a8 1672
aa9c1601 1673 if (*thisarg == '-' || *thisarg == '+')
1674 {
1675 bool set = (*thisarg == '+');
1676 cstring flagname = cstring_fromChars (thisarg + 1); /* skip '-' or '+' */
1677 flagcode opt = flags_identifyFlag (flagname);
1678
53306cab 1679 DPRINTF (("Flag [%s]: %s", flagname, flagcode_unparse (opt)));
aa9c1601 1680
1681 if (flagcode_isInvalid (opt))
1682 {
1683 DPRINTF (("Error!"));
1684 voptgenerror (FLG_BADFLAG,
1685 message ("Unrecognized option: %s",
1686 cstring_fromChars (thisarg)),
1687 g_currentloc);
1688 }
1689 else if (flagcode_isHelpFlag (opt))
1690 {
1691 if (inCommandLine)
1692 {
1693 voptgenerror (FLG_BADFLAG,
1694 message ("Help flag must be first on the command line: %s",
1695 cstring_fromChars (thisarg)),
1696 g_currentloc);
1697 }
1698 else
1699 {
1700 voptgenerror (FLG_BADFLAG,
1701 message ("Help flags can only be used on the command line: %s",
1702 cstring_fromChars (thisarg)),
1703 g_currentloc);
1704 }
1705 }
140c27a8 1706 else if (flagcode_isPassThrough (opt)) /* preprocessor flag: -D or -U */
1707 {
1708 /*
1709 ** Following space is optional, don't include the -
1710 */
1711
6fcd0b1e 1712 *passThroughArgs = cstringList_add (*passThroughArgs,
1713 cstring_fromCharsNew (thisarg + 1));
140c27a8 1714 }
1715 else if (opt == FLG_INCLUDEPATH || opt == FLG_SPECPATH)
1716 {
c3be2604 1717 if (mstring_length (thisarg) < 2) {
1718 BADBRANCH;
1719 } else {
1720 if (mstring_equal (thisarg, "-I-")) {
1721 cppAddIncludeDir (cstring_fromChars (thisarg)); /* Need to handle this specially. */
1722 } else {
1723 cstring dir = cstring_suffix (cstring_fromChars (thisarg), 2); /* skip over -I */
1724
1725 DPRINTF (("Length of thisarg [%s] %d", thisarg, cstring_length (thisarg)));
1726
1727 if (cstring_length (dir) == 0) {
1728 DPRINTF (("space after directory: "));
1729 if (++i < argc) {
1730 dir = cstring_fromChars (argv[i]);
1731 } else {
1732 voptgenerror
1733 (FLG_BADFLAG,
1734 message
1735 ("Flag %s must be followed by a directory name",
1736 flagcode_unparse (opt)),
1737 g_currentloc);
1738 }
1739 }
1740
1741 DPRINTF (("Got directory: [%s]", dir));
1742
1743 switch (opt)
1744 {
1745 case FLG_INCLUDEPATH:
1746 cppAddIncludeDir (dir);
1747 /*@switchbreak@*/ break;
1748 case FLG_SPECPATH:
1749 /*@-mustfree@*/
1750 g_localSpecPath = cstring_toCharsSafe
1751 (message ("%s%h%s",
1752 cstring_fromChars (g_localSpecPath),
1753 PATH_SEPARATOR,
1754 dir));
1755 /*@=mustfree@*/
1756 /*@switchbreak@*/ break;
1757 BADDEFAULT;
1758 }
140c27a8 1759 }
c3be2604 1760 }
140c27a8 1761 }
1762 else if (flagcode_isModeName (opt))
aa9c1601 1763 {
1764 context_setMode (flagname);
1765 }
ce7034f0 1766 else if (inCommandLine && flagcode_isMessageControlFlag (opt))
aa9c1601 1767 {
1768 /*
1769 ** Processed on first pass
1770 */
1771
1772 if (flagcode_hasArgument (opt))
1773 {
1774 ++i;
1775 }
1776 }
1777 else
1778 {
1779 /*
1780 ** A normal control flag
1781 */
1782
1783 context_userSetFlag (opt, set);
1784
1785 if (flagcode_hasArgument (opt))
1786 {
140c27a8 1787 if (flagcode_hasNumber (opt))
1788 {
1789 if (++i < argc)
aa9c1601 1790 {
16c024b5 1791 flags_setValueFlag (opt, cstring_fromCharsNew (argv[i]));
140c27a8 1792 }
1793 else
aa9c1601 1794 {
140c27a8 1795 voptgenerror
1796 (FLG_BADFLAG,
1797 message
1798 ("Flag %s must be followed by a number",
1799 flagcode_unparse (opt)),
1800 g_currentloc);
1801 }
1802 }
1803 else if (flagcode_hasChar (opt))
1804 {
1805 if (++i < argc)
aa9c1601 1806 {
16c024b5 1807 flags_setValueFlag (opt, cstring_fromCharsNew (argv[i]));
140c27a8 1808 }
1809 else
1810 {
1811 voptgenerror
1812 (FLG_BADFLAG,
1813 message
1814 ("Flag %s must be followed by a character",
1815 flagcode_unparse (opt)),
1816 g_currentloc);
aa9c1601 1817 }
140c27a8 1818 }
1819 else if (flagcode_hasString (opt)
1820 || opt == FLG_INIT || opt == FLG_OPTF)
1821 {
1822 if (++i < argc)
aa9c1601 1823 {
35e063d8 1824 /*drl 10/21/2002
1825 Changed this because arg can be freed when it's passed to
1826 lslinit_setInitFile and freeing argv[i] causes a seg fault
1827 */
1828 cstring arg = cstring_fromCharsNew (argv[i]);
140c27a8 1829
1830 if (opt == FLG_OPTF)
aa9c1601 1831 {
140c27a8 1832 if (inCommandLine)
aa9c1601 1833 {
1834 ; /* -f already processed */
1835 }
140c27a8 1836 else
aa9c1601 1837 {
140c27a8 1838 (void) rcfiles_read (arg, passThroughArgs, TRUE);
1839 }
1840 }
1841 else if (opt == FLG_INIT)
1842 {
140c27a8 1843 lslinit_setInitFile (inputStream_create
1844 (arg,
1845 cstring_makeLiteralTemp (LCLINIT_SUFFIX),
1846 FALSE));
140c27a8 1847 break;
1848 }
1849 else
1850 {
1851 DPRINTF (("String flag: %s / %s",
1852 flagcode_unparse (opt), arg));
1853 if (opt == FLG_MTSFILE)
1854 {
1855 /*
1856 ** arg identifies mts files
1857 */
1858 cstring tmp = message ("%s%s", arg, MTS_EXTENSION);
1859 addLarchPathFile (mtfiles, tmp);
1860 cstring_free (tmp);
1861 tmp = message ("%s%s", arg, XH_EXTENSION);
1862 addXHFile (xfiles, tmp);
1863 cstring_free (tmp);
aa9c1601 1864 }
1865 else
1866 {
16c024b5 1867 flags_setStringFlag (opt, cstring_copy (arg));
aa9c1601 1868 }
1869 }
aa9c1601 1870 }
1871 else
1872 {
140c27a8 1873 voptgenerror
1874 (FLG_BADFLAG,
1875 message
1876 ("Flag %s must be followed by a string",
1877 flagcode_unparse (opt)),
1878 g_currentloc);
aa9c1601 1879 }
1880 }
140c27a8 1881 else
1882 {
1883 /* no argument */
1884 }
aa9c1601 1885 }
1886 }
140c27a8 1887 }
1888 else /* its a filename */
1889 {
1890 DPRINTF (("Adding filename: %s", thisarg));
1891 fl = cstringSList_add (fl, cstring_fromChars (thisarg));
aa9c1601 1892 }
1893 }
aa9c1601 1894
140c27a8 1895 /*
1896 ** create lists of C and LCL files
1897 */
1898
1899 if (inCommandLine)
1900 {
1901 cstringSList_elements (fl, current)
aa9c1601 1902 {
140c27a8 1903 cstring ext = fileLib_getExtension (current);
aa9c1601 1904
140c27a8 1905 if (cstring_isUndefined (ext))
aa9c1601 1906 {
140c27a8 1907 /* no extension --- both C and LCL with default extensions */
1908
1909 addFile (cfiles, message ("%s%s", current, C_EXTENSION));
1910 addFile (lclfiles, message ("%s%s", current, LCL_EXTENSION));
aa9c1601 1911 }
140c27a8 1912 else if (cstring_equal (ext, XH_EXTENSION))
aa9c1601 1913 {
140c27a8 1914 addXHFile (xfiles, current);
aa9c1601 1915 }
140c27a8 1916 else if (cstring_equal (ext, PP_EXTENSION))
aa9c1601 1917 {
140c27a8 1918 if (!context_getFlag (FLG_NOPP))
1919 {
1920 voptgenerror
1921 (FLG_FILEEXTENSIONS,
1922 message ("File extension %s used without +nopp flag (will be processed as C source code): %s",
1923 ext, current),
1924 g_currentloc);
1925 }
1926
1927 addFile (cfiles, cstring_copy (current));
aa9c1601 1928 }
140c27a8 1929 else if (cstring_equal (ext, LCL_EXTENSION))
aa9c1601 1930 {
140c27a8 1931 addFile (lclfiles, cstring_copy (current));
aa9c1601 1932 }
140c27a8 1933 else if (fileLib_isCExtension (ext))
aa9c1601 1934 {
140c27a8 1935 addFile (cfiles, cstring_copy (current));
aa9c1601 1936 }
140c27a8 1937 else if (cstring_equal (ext, MTS_EXTENSION))
aa9c1601 1938 {
140c27a8 1939 addLarchPathFile (mtfiles, current);
aa9c1601 1940 }
140c27a8 1941 else
aa9c1601 1942 {
140c27a8 1943 voptgenerror
1944 (FLG_FILEEXTENSIONS,
1945 message ("Unrecognized file extension: %s (assuming %s is C source code)",
1946 current, ext),
1947 g_currentloc);
aa9c1601 1948
140c27a8 1949 addFile (cfiles, cstring_copy (current));
aa9c1601 1950 }
140c27a8 1951 } end_cstringSList_elements;
1952 }
1953 else
1954 {
1955 if (cstringSList_size (fl) != 0)
aa9c1601 1956 {
140c27a8 1957 /* Cannot list files in .splintrc files */
1958 voptgenerror (FLG_BADFLAG,
1959 message ("Cannot list files in .splintrc files: %s (probable missing + or -)",
1960 cstringSList_unparse (fl)),
1961 g_currentloc);
1962 }
1963 }
6fcd0b1e 1964
1965 cstringSList_free (fl); /* evans 2002-07-12: why wasn't this reported!?? */
140c27a8 1966}
53306cab 1967
1968int flagcode_priority (/*@unused@*/ flagcode code)
1969{
1970 /*
1971 ** For now, we do a really simple prioritization: all are 1
1972 */
1973
1974 return 1;
1975}
This page took 0.442222 seconds and 5 git commands to generate.