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