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