]> andersk Git - splint.git/blame - src/flags.c
Fixed pre-processing bug reported by Adam Clarke. Moved marking point
[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
303 sprintf (buf, "%s%7d %9d", cstring_toCharsSafe (fs), nrep, nsup);
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
319 sprintf (buf, "%s%7d %9d", cstring_toCharsSafe (ts), sumrep, sumsup);
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 }
1114 /*
1115 ** Backwards compatibility for our American friends...
1116 */
616915dd 1117
92b2ba2c 1118 else if (cstring_equalLit (cflag, "ansilib"))
1119 {
1120 res = FLG_ANSILIB;
1121 }
1122 else if (cstring_equalLit (cflag, "ansistrictlib"))
1123 {
1124 res = FLG_STRICTLIB;
1125 }
1126 else if (cstring_equalLit (cflag, "skipansiheaders"))
1127 {
abd7f895 1128 res = FLG_SKIPISOHEADERS;
92b2ba2c 1129 }
1130 else if (cstring_equalLit (cflag, "ansireserved"))
1131 {
abd7f895 1132 res = FLG_ISORESERVED;
92b2ba2c 1133 }
1134 else if (cstring_equalLit (cflag, "ansireservedinternal"))
1135 {
abd7f895 1136 res = FLG_ISORESERVEDLOCAL;
92b2ba2c 1137 }
1138
1139 /*
1140 ** Obsolete Flags
1141 */
1142
1143 else if (cstring_equalLit (cflag, "accessunspec"))
1144 {
1145 if (!quiet)
1146 {
1147 llerror_flagWarning
1148 (cstring_makeLiteral
1149 ("accessunspec flag is no longer supported. It has been replaced by accessmodule, accessfile and "
1150 "accessfunction to provide more precise control of accessibility "
1151 "of representations. For more information, "
1152 "see splint -help accessmodule"));
1153 }
1154
1155 res = SKIP_FLAG;
1156 }
1157 else if (cstring_equalLit (cflag, "ansilimits"))
1158 {
27c9e640 1159 llerror_flagWarning
1160 (cstring_makeLiteral
1161 ("ansilimits flag is no longer supported. It has been replaced by ansi89limits and "
1162 "iso99limits to select either the lower translation limits imposed by the ANSI89 "
1163 "standard or the typically higher limits prescribed by ISO C99."));
92b2ba2c 1164
1165 res = SKIP_FLAG;
1166 }
1167 else if (cstring_equalLit (cflag, "staticmods"))
a956d444 1168 {
92b2ba2c 1169 if (!quiet)
1170 {
1171 llerror_flagWarning
1172 (cstring_makeLiteral
1173 ("staticmods flag is obsolete. You probably "
1174 "want impcheckmodstatics. For more information, "
1175 "see splint -help impcheckmodstatics"));
1176 }
1177
1178 res = SKIP_FLAG;
a956d444 1179 }
92b2ba2c 1180 else if (cstring_equalLit (cflag, "bool"))
a956d444 1181 {
92b2ba2c 1182 if (!quiet)
1183 {
1184 llerror_flagWarning
1185 (cstring_makeLiteral ("bool flag is obsolete. It never really "
1186 "made sense in the first place."));
1187 }
1188
1189 res = SKIP_FLAG;
a956d444 1190 }
92b2ba2c 1191 else if (cstring_equalLit (cflag, "shiftsigned"))
a956d444 1192 {
92b2ba2c 1193 if (!quiet)
1194 {
1195 llerror_flagWarning
1196 (cstring_makeLiteral ("shiftsigned flag is obsolete. You probably "
06418c9b 1197 "want bitwisesigned, shiftnegative or shiftimplementation."));
92b2ba2c 1198 }
1199
1200 res = SKIP_FLAG;
a956d444 1201 }
92b2ba2c 1202 else if (cstring_equalLit (cflag, "ansi"))
a956d444 1203 {
92b2ba2c 1204 if (!quiet)
1205 {
1206 llerror_flagWarning
1207 (cstring_makeLiteral ("ansi flag is obsolete. You probably "
1208 "want noparams and/or oldstyle."));
1209 }
1210
1211 res = SKIP_FLAG;
a956d444 1212 }
80489f0a 1213 else if (cstring_equalLit (cflag, "usestderr"))
1214 {
1215 if (!quiet)
1216 {
1217 llerror_flagWarning
1218 (cstring_makeLiteral
1219 ("usestderr flag is obsolete. This has been replaced "
1220 "by more precise flags for controlling the warning, "
1221 "status message and fatal error streams independently: message-stream-stdout, "
1222 "message-stream-stderr, message-stream <file>, "
1223 "warning-stream-stdout, warning-stream-stderr, warning-stream <file>, "
1224 "error-stream-stdout, error-stream-stderr, error-stream <file>."));
1225 }
1226
1227 res = SKIP_FLAG;
1228 }
1229
92b2ba2c 1230 else if (cstring_equalLit (cflag, "stdio"))
a956d444 1231 {
92b2ba2c 1232 if (!quiet)
1233 {
1234 llerror_flagWarning
1235 (cstring_makeLiteral
1236 ("stdio flag is obsolete. You may "
1237 "want strictlib or one of the gloabls "
1238 "checking flags. For more information, "
1239 "see splint -help strictlib or splint -help flags globals"));
1240 }
1241
1242 res = SKIP_FLAG;
1243 }
aa9c1601 1244 else if (flags_isModeName (cflag))
1245 {
1246 res = MODENAME_FLAG;
140c27a8 1247 }
92b2ba2c 1248 else
1249 {
1250 res = INVALID_FLAG;
a956d444 1251 }
a956d444 1252 }
92b2ba2c 1253
1254 cstring_free (cflag);
1255 return res;
616915dd 1256}
1257
1258void setValueFlag (flagcode opt, cstring arg)
1259{
1260 switch (opt)
1261 {
1262 case FLG_EXPECT:
1263 case FLG_LCLEXPECT:
1264 case FLG_LIMIT:
1265 case FLG_LINELEN:
28bf4b0b 1266 case FLG_INDENTSPACES:
1267 case FLG_BUGSLIMIT:
616915dd 1268 case FLG_EXTERNALNAMELEN:
1269 case FLG_INTERNALNAMELEN:
1270 case FLG_CONTROLNESTDEPTH:
1271 case FLG_STRINGLITERALLEN:
1272 case FLG_NUMSTRUCTFIELDS:
1273 case FLG_NUMENUMMEMBERS:
1274 case FLG_INCLUDENEST:
1275 {
1276 int val = cstring_toPosInt (arg);
1277
1278 if (val < 0)
1279 {
1280 llerror
1281 (FLG_BADFLAG,
1282 message
1283 ("Flag %s must be followed by a positive number number. "
1284 "Followed by %s",
1285 flagcode_unparse (opt), arg));
1286 }
1287 else
1288 {
28bf4b0b 1289 context_setValueAndFlag (opt, val);
616915dd 1290 }
1291 }
1292 break;
1293 case FLG_COMMENTCHAR:
1294 {
1295 if (cstring_length (arg) != 1)
1296 {
1297 llfatalerrorLoc
1298 (message
1299 ("Flag %s should be followed by a single character. Followed by %s",
1300 flagcode_unparse (opt), arg));
1301 }
1302 else
1303 {
1304 context_setCommentMarkerChar (cstring_firstChar (arg));
1305 }
1306 }
1307 break;
1308 BADDEFAULT;
1309 }
1310}
1311
1312void setStringFlag (flagcode opt, /*@only@*/ cstring arg)
1313{
1314 switch (opt)
1315 {
1316 case FLG_TMPDIR:
1317 {
1318 if (cstring_lastChar (arg) == CONNECTCHAR)
1319 {
1320 context_setString (opt, arg);
1321 }
1322 else
1323 {
1324 context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1325 }
1326 break;
1327 }
1328 default:
1329 {
1330 context_setString (opt, arg);
1331 break;
1332 }
1333 }
1334}
1335
1336cstring
1337describeModes ()
1338{
1339 cstring s = cstring_makeLiteral ("Flag ");
1340 cstringSList sflags = sortedFlags ();
1341
1342 allModes (modename)
1343 {
1344 s = message ("%q%9s", s, cstring_fromChars (modename));
1345 } end_allModes;
1346
1347 s = message ("%q\n", s);
1348
1349 cstringSList_elements (sflags, flagname)
1350 {
a956d444 1351 flagcode code = flags_identifyFlag (flagname);
616915dd 1352 fflag currentflag = flags[code];
1353
1354 if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1355 {
1356 s = message ("%q\n%27s", s,
1357 cstring_fromChars (currentflag.flag));
1358
1359 allModes (modename)
1360 {
1361 context_setMode (cstring_fromChars (modename));
1362
1363 if (context_getFlag (code))
1364 {
1365 s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1366 }
1367 else
1368 {
1369 s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1370 }
1371
1372 context_resetModeFlags ();
1373 } end_allModes;
1374 }
1375 } end_cstringSList_elements;
1376
1377 cstringSList_free (sflags);
1378
1379 s = cstring_appendChar (s, '\n');
1380
1381 return (s);
1382}
1383
8250fa4a 1384# if 0
ee229125 1385static /*@unused@*/ cstring
616915dd 1386listModes (void)
1387{
1388 cstring s = cstring_makeLiteral ("\t");
1389 int i = 0;
1390
1391 allModes (modename)
1392 {
1393 if (i != 0 && (i % 4 == 0))
1394 {
1395 s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1396 }
1397 else
1398 {
1399 s = message ("%q%15s", s, cstring_fromChars (modename));
1400 }
1401 i++;
1402 } end_allModes;
1403
1404 return s;
1405}
8250fa4a 1406# endif
616915dd 1407
1408bool
aa9c1601 1409flags_isModeName (cstring s)
616915dd 1410{
1411 allModes (modename)
1412 {
1413 if (mstring_isDefined (modename))
1414 {
1415 if (cstring_equalLit (s, modename))
1416 {
1417 return TRUE;
1418 }
1419 }
1420 } end_allModes;
1421
1422 return FALSE;
1423}
1424
1425extern bool flagcode_hasArgument (flagcode f)
1426{
1427 return (flags[f].argtype != ARG_NONE);
1428}
1429
4f43223c 1430extern bool flagcode_hasNumber (flagcode f)
1431{
1432 return (flags[f].argtype == ARG_NUMBER);
1433}
1434
1435extern bool flagcode_hasChar (flagcode f)
616915dd 1436{
4f43223c 1437 return (flags[f].argtype == ARG_CHAR);
616915dd 1438}
1439
1440extern bool flagcode_hasString (flagcode f)
1441{
4f43223c 1442 return (flags[f].argtype == ARG_STRING
1443 || flags[f].argtype == ARG_FILE
1444 || flags[f].argtype == ARG_DIRECTORY
1445 || flags[f].argtype == ARG_PATH);
616915dd 1446}
1447
1448extern int flagcode_valueIndex (flagcode f)
1449{
1450 /*@unchecked@*/ static bool initialized = FALSE;
1451 int i;
1452 /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
616915dd 1453
1454 if (!initialized)
1455 {
1456 int nv = 0;
1457
1458 allFlagCodes (code)
1459 {
4f43223c 1460 if (flagcode_hasNumber (code) || flagcode_hasChar (code))
616915dd 1461 {
1462 llassert (nv < NUMVALUEFLAGS);
28bf4b0b 1463 DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
616915dd 1464 valueFlags[nv] = code;
28bf4b0b 1465 nv++;
616915dd 1466 }
1467 } end_allFlagCodes;
1468
1469 llassertprint (nv == NUMVALUEFLAGS,
28bf4b0b 1470 ("Number of value flags: %d (expected %d)",
1471 nv, (int) NUMVALUEFLAGS));
616915dd 1472 initialized = TRUE;
1473 }
1474
1475 for (i = 0; i < NUMVALUEFLAGS; i++)
1476 {
1477 /* static valueFlags must be defined */
86d93ed3 1478 /*@-usedef@*/
1479 /*drl bee: sta*/
1480 if (f == valueFlags[i]) /*@=usedef@*/
616915dd 1481 {
1482 return i;
1483 }
1484 }
1485
28bf4b0b 1486 fprintf (stderr, "Cannot find value flag: %d", (int) f);
1487 exit (EXIT_FAILURE);
1488 /* Cannot do this...might call recursively...
1489 llfatalbug (message ("Cannot fine value flag: %d", (int) f));
616915dd 1490 BADEXIT;
28bf4b0b 1491 */
616915dd 1492}
1493
1494extern int flagcode_stringIndex (flagcode f)
1495{
1496 /*@unchecked@*/ static bool initialized = FALSE;
1497 /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1498 int i;
1499
1500
1501 if (!initialized)
1502 {
1503 int nv = 0;
1504
1505 allFlagCodes (code)
1506 {
1507 if (flagcode_hasString (code))
1508 {
1509 llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1510 stringFlags[nv] = code;
1511 nv++;
1512 }
1513 } end_allFlagCodes;
1514
1515 llassertprint (nv == NUMSTRINGFLAGS,
1516 ("number of string flags: %d (expected %d)",
1517 nv, NUMSTRINGFLAGS));
1518 initialized = TRUE;
1519 }
1520
1521 for (i = 0; i < NUMSTRINGFLAGS; i++)
1522 {
86d93ed3 1523 /*drl bee: sta*/
616915dd 1524 /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1525 {
1526 return i;
1527 }
1528 }
1529
1530 llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1531 BADEXIT;
1532}
1533
1534bool flagcode_isNamePrefixFlag (flagcode f)
1535{
1536 switch (f)
1537 {
1538 case FLG_MACROVARPREFIX:
1539 case FLG_TAGPREFIX:
1540 case FLG_ENUMPREFIX:
1541 case FLG_FILESTATICPREFIX:
1542 case FLG_GLOBPREFIX:
1543 case FLG_TYPEPREFIX:
1544 case FLG_EXTERNALPREFIX:
1545 case FLG_LOCALPREFIX:
1546 case FLG_UNCHECKEDMACROPREFIX:
1547 case FLG_CONSTPREFIX:
1548 case FLG_ITERPREFIX:
1549 case FLG_DECLPARAMPREFIX:
1550 return TRUE;
1551 default:
1552 return FALSE;
1553 }
1554}
140c27a8 1555
1556static cstring findLarchPathFile (/*@temp@*/ cstring s)
aa9c1601 1557{
140c27a8 1558 cstring pathName;
1559 filestatus status;
1560
1561 status = osd_getPath (context_getLarchPath (), s, &pathName);
1562
1563 if (status == OSD_FILEFOUND)
1564 {
1565 return pathName;
1566 }
1567 else if (status == OSD_FILENOTFOUND)
1568 {
1569 showHerald ();
1570 lldiagmsg (message ("Cannot find file on LARCH_PATH: %s", s));
1571 }
1572 else if (status == OSD_PATHTOOLONG)
1573 {
1574 /* Directory and filename are too long. Report error. */
1575 llbuglit ("soure_getPath: Filename plus directory from search path too long");
1576 }
1577 else
1578 {
1579 BADBRANCH;
1580 }
1581
1582 return cstring_undefined;
1583}
1584
1585static void addLarchPathFile (fileIdList files, /*@temp@*/ cstring s)
1586{
1587 cstring pathName = findLarchPathFile (s);
1588
1589 if (cstring_isDefined (pathName))
1590 {
1591 if (fileTable_exists (context_fileTable (), pathName))
1592 {
1593 showHerald ();
1594 lldiagmsg (message ("File listed multiple times: %s", pathName));
1595 cstring_free (pathName);
1596 }
1597 else
1598 {
1599 fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), pathName));
1600 }
1601 }
1602}
1603
1604
1605static void addFile (fileIdList files, /*@only@*/ cstring s)
1606{
1607 if (fileTable_exists (context_fileTable (), s))
1608 {
1609 showHerald ();
1610 lldiagmsg (message ("File listed multiple times: %s", s));
1611 cstring_free (s);
1612 }
1613 else
1614 {
1615 fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), s));
1616 }
1617}
1618
1619static void addXHFile (fileIdList files, /*@temp@*/ cstring s)
1620{
1621 cstring pathName = findLarchPathFile (s);
1622
1623 if (cstring_isDefined (pathName))
1624 {
1625 if (fileTable_exists (context_fileTable (), pathName))
1626 {
1627 showHerald ();
1628 lldiagmsg (message ("File listed multiple times: %s", s));
1629 }
1630 else
1631 {
1632 fileIdList_add (files, fileTable_addXHFile (context_fileTable (), pathName));
1633 }
1634 }
aa9c1601 1635
140c27a8 1636 cstring_free (pathName);
1637}
1638
1639void
1640flags_processFlags (bool inCommandLine,
1641 fileIdList xfiles,
1642 fileIdList cfiles,
1643 fileIdList lclfiles,
1644 fileIdList mtfiles,
1645 cstringSList *passThroughArgs,
1646 int argc, char **argv)
1647{
1648 int i;
1649 cstringSList fl = cstringSList_undefined;
1650
aa9c1601 1651 for (i = 0; i < argc; i++)
1652 {
140c27a8 1653 char *thisarg;
1654
1655 llassert (argv != NULL);
1656 thisarg = argv[i];
ce7034f0 1657
1658 DPRINTF (("process thisarg [%d]: %s", i, thisarg));
140c27a8 1659
aa9c1601 1660 if (*thisarg == '-' || *thisarg == '+')
1661 {
1662 bool set = (*thisarg == '+');
1663 cstring flagname = cstring_fromChars (thisarg + 1); /* skip '-' or '+' */
1664 flagcode opt = flags_identifyFlag (flagname);
1665
1666 DPRINTF (("Flag: %s", flagcode_unparse (opt)));
1667
1668 if (flagcode_isInvalid (opt))
1669 {
1670 DPRINTF (("Error!"));
1671 voptgenerror (FLG_BADFLAG,
1672 message ("Unrecognized option: %s",
1673 cstring_fromChars (thisarg)),
1674 g_currentloc);
1675 }
1676 else if (flagcode_isHelpFlag (opt))
1677 {
1678 if (inCommandLine)
1679 {
1680 voptgenerror (FLG_BADFLAG,
1681 message ("Help flag must be first on the command line: %s",
1682 cstring_fromChars (thisarg)),
1683 g_currentloc);
1684 }
1685 else
1686 {
1687 voptgenerror (FLG_BADFLAG,
1688 message ("Help flags can only be used on the command line: %s",
1689 cstring_fromChars (thisarg)),
1690 g_currentloc);
1691 }
1692 }
140c27a8 1693 else if (flagcode_isPassThrough (opt)) /* preprocessor flag: -D or -U */
1694 {
1695 /*
1696 ** Following space is optional, don't include the -
1697 */
1698
1699 *passThroughArgs = cstringSList_add (*passThroughArgs,
1700 cstring_fromChars (thisarg + 1));
1701 }
1702 else if (opt == FLG_INCLUDEPATH || opt == FLG_SPECPATH)
1703 {
1704 cstring dir = cstring_suffix (cstring_fromChars (thisarg), 1); /* skip over I */
1705
1706 DPRINTF (("Directory: %s", dir));
1707
1708 switch (opt)
1709 {
1710 case FLG_INCLUDEPATH:
1711 cppAddIncludeDir (dir);
1712 /*@switchbreak@*/ break;
1713 case FLG_SPECPATH:
1714 /*@-mustfree@*/
1715 g_localSpecPath = cstring_toCharsSafe
1716 (message ("%s%h%s",
1717 cstring_fromChars (g_localSpecPath),
1718 PATH_SEPARATOR,
1719 dir));
1720 /*@=mustfree@*/
1721 /*@switchbreak@*/ break;
1722 BADDEFAULT;
1723 }
1724 }
1725 else if (flagcode_isModeName (opt))
aa9c1601 1726 {
1727 context_setMode (flagname);
1728 }
ce7034f0 1729 else if (inCommandLine && flagcode_isMessageControlFlag (opt))
aa9c1601 1730 {
1731 /*
1732 ** Processed on first pass
1733 */
1734
1735 if (flagcode_hasArgument (opt))
1736 {
1737 ++i;
1738 }
1739 }
1740 else
1741 {
1742 /*
1743 ** A normal control flag
1744 */
1745
1746 context_userSetFlag (opt, set);
1747
1748 if (flagcode_hasArgument (opt))
1749 {
140c27a8 1750 if (flagcode_hasNumber (opt))
1751 {
1752 if (++i < argc)
aa9c1601 1753 {
140c27a8 1754 setValueFlag (opt, cstring_fromChars (argv[i]));
1755 }
1756 else
aa9c1601 1757 {
140c27a8 1758 voptgenerror
1759 (FLG_BADFLAG,
1760 message
1761 ("Flag %s must be followed by a number",
1762 flagcode_unparse (opt)),
1763 g_currentloc);
1764 }
1765 }
1766 else if (flagcode_hasChar (opt))
1767 {
1768 if (++i < argc)
aa9c1601 1769 {
140c27a8 1770 setValueFlag (opt, cstring_fromChars (argv[i]));
1771 }
1772 else
1773 {
1774 voptgenerror
1775 (FLG_BADFLAG,
1776 message
1777 ("Flag %s must be followed by a character",
1778 flagcode_unparse (opt)),
1779 g_currentloc);
aa9c1601 1780 }
140c27a8 1781 }
1782 else if (flagcode_hasString (opt)
1783 || opt == FLG_INIT || opt == FLG_OPTF)
1784 {
1785 if (++i < argc)
aa9c1601 1786 {
140c27a8 1787 cstring arg = cstring_fromChars (argv[i]);
1788
1789 if (opt == FLG_OPTF)
aa9c1601 1790 {
140c27a8 1791 if (inCommandLine)
aa9c1601 1792 {
1793 ; /* -f already processed */
1794 }
140c27a8 1795 else
aa9c1601 1796 {
140c27a8 1797 (void) rcfiles_read (arg, passThroughArgs, TRUE);
1798 }
1799 }
1800 else if (opt == FLG_INIT)
1801 {
aa9c1601 1802# ifndef NOLCL
140c27a8 1803 lslinit_setInitFile (inputStream_create
1804 (arg,
1805 cstring_makeLiteralTemp (LCLINIT_SUFFIX),
1806 FALSE));
aa9c1601 1807# endif
140c27a8 1808 break;
1809 }
1810 else
1811 {
1812 DPRINTF (("String flag: %s / %s",
1813 flagcode_unparse (opt), arg));
1814 if (opt == FLG_MTSFILE)
1815 {
1816 /*
1817 ** arg identifies mts files
1818 */
1819 cstring tmp = message ("%s%s", arg, MTS_EXTENSION);
1820 addLarchPathFile (mtfiles, tmp);
1821 cstring_free (tmp);
1822 tmp = message ("%s%s", arg, XH_EXTENSION);
1823 addXHFile (xfiles, tmp);
1824 cstring_free (tmp);
aa9c1601 1825 }
1826 else
1827 {
140c27a8 1828 setStringFlag (opt, cstring_copy (arg));
aa9c1601 1829 }
1830 }
aa9c1601 1831 }
1832 else
1833 {
140c27a8 1834 voptgenerror
1835 (FLG_BADFLAG,
1836 message
1837 ("Flag %s must be followed by a string",
1838 flagcode_unparse (opt)),
1839 g_currentloc);
aa9c1601 1840 }
1841 }
140c27a8 1842 else
1843 {
1844 /* no argument */
1845 }
aa9c1601 1846 }
1847 }
140c27a8 1848 }
1849 else /* its a filename */
1850 {
1851 DPRINTF (("Adding filename: %s", thisarg));
1852 fl = cstringSList_add (fl, cstring_fromChars (thisarg));
aa9c1601 1853 }
1854 }
aa9c1601 1855
140c27a8 1856 /*
1857 ** create lists of C and LCL files
1858 */
1859
1860 if (inCommandLine)
1861 {
1862 cstringSList_elements (fl, current)
aa9c1601 1863 {
140c27a8 1864 cstring ext = fileLib_getExtension (current);
aa9c1601 1865
140c27a8 1866 if (cstring_isUndefined (ext))
aa9c1601 1867 {
140c27a8 1868 /* no extension --- both C and LCL with default extensions */
1869
1870 addFile (cfiles, message ("%s%s", current, C_EXTENSION));
1871 addFile (lclfiles, message ("%s%s", current, LCL_EXTENSION));
aa9c1601 1872 }
140c27a8 1873 else if (cstring_equal (ext, XH_EXTENSION))
aa9c1601 1874 {
140c27a8 1875 addXHFile (xfiles, current);
aa9c1601 1876 }
140c27a8 1877 else if (cstring_equal (ext, PP_EXTENSION))
aa9c1601 1878 {
140c27a8 1879 if (!context_getFlag (FLG_NOPP))
1880 {
1881 voptgenerror
1882 (FLG_FILEEXTENSIONS,
1883 message ("File extension %s used without +nopp flag (will be processed as C source code): %s",
1884 ext, current),
1885 g_currentloc);
1886 }
1887
1888 addFile (cfiles, cstring_copy (current));
aa9c1601 1889 }
140c27a8 1890 else if (cstring_equal (ext, LCL_EXTENSION))
aa9c1601 1891 {
140c27a8 1892 addFile (lclfiles, cstring_copy (current));
aa9c1601 1893 }
140c27a8 1894 else if (fileLib_isCExtension (ext))
aa9c1601 1895 {
140c27a8 1896 addFile (cfiles, cstring_copy (current));
aa9c1601 1897 }
140c27a8 1898 else if (cstring_equal (ext, MTS_EXTENSION))
aa9c1601 1899 {
140c27a8 1900 addLarchPathFile (mtfiles, current);
aa9c1601 1901 }
140c27a8 1902 else
aa9c1601 1903 {
140c27a8 1904 voptgenerror
1905 (FLG_FILEEXTENSIONS,
1906 message ("Unrecognized file extension: %s (assuming %s is C source code)",
1907 current, ext),
1908 g_currentloc);
aa9c1601 1909
140c27a8 1910 addFile (cfiles, cstring_copy (current));
aa9c1601 1911 }
140c27a8 1912 } end_cstringSList_elements;
1913 }
1914 else
1915 {
1916 if (cstringSList_size (fl) != 0)
aa9c1601 1917 {
140c27a8 1918 /* Cannot list files in .splintrc files */
1919 voptgenerror (FLG_BADFLAG,
1920 message ("Cannot list files in .splintrc files: %s (probable missing + or -)",
1921 cstringSList_unparse (fl)),
1922 g_currentloc);
1923 }
1924 }
1925}
This page took 0.342849 seconds and 5 git commands to generate.