]> andersk Git - splint.git/blame - src/flags.c
Added support for omitted if clauses in conditionals, patch provided by peteran.
[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"
140c27a8 31# include "rcfiles.h"
32# include "lslinit.h"
4caf866b 33# include "llmain.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
51bc6ecc 131# ifdef WIN32
132/* Make Microsoft VC++ happy */
133# pragma warning (disable:4715)
134# endif
135
4f43223c 136static /*@observer@*/ cstring argcode_unparse (argcode arg)
137{
138 switch (arg)
139 {
140 case ARG_STRING: return cstring_makeLiteralTemp ("string");
141 case ARG_FILE: return cstring_makeLiteralTemp ("filename");
142 case ARG_DIRECTORY: return cstring_makeLiteralTemp ("directory");
143 case ARG_PATH: return cstring_makeLiteralTemp ("path");
144 case ARG_NUMBER: return cstring_makeLiteralTemp ("number");
145 case ARG_CHAR: return cstring_makeLiteralTemp ("character");
146 case ARG_NONE:
147 BADBRANCH;
148 case ARG_SPECIAL:
149 BADBRANCH;
150 }
151}
152
e5081f8c 153# ifdef WIN32
51bc6ecc 154# pragma warning (default : 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 == '+');
368f75ae 1663 cstring flagname;
1664 flagcode opt;
aa9c1601 1665
368f75ae 1666 if (*(thisarg + 1) == '-') { /* allow -- before flags */
1667 flagname = cstring_fromChars (thisarg + 2);
1668 } else {
1669 flagname = cstring_fromChars (thisarg + 1);
1670 }
1671
1672 opt = flags_identifyFlag (flagname);
53306cab 1673 DPRINTF (("Flag [%s]: %s", flagname, flagcode_unparse (opt)));
aa9c1601 1674
1675 if (flagcode_isInvalid (opt))
1676 {
1677 DPRINTF (("Error!"));
1678 voptgenerror (FLG_BADFLAG,
1679 message ("Unrecognized option: %s",
1680 cstring_fromChars (thisarg)),
1681 g_currentloc);
1682 }
1683 else if (flagcode_isHelpFlag (opt))
1684 {
1685 if (inCommandLine)
1686 {
1687 voptgenerror (FLG_BADFLAG,
1688 message ("Help flag must be first on the command line: %s",
1689 cstring_fromChars (thisarg)),
1690 g_currentloc);
1691 }
1692 else
1693 {
1694 voptgenerror (FLG_BADFLAG,
1695 message ("Help flags can only be used on the command line: %s",
1696 cstring_fromChars (thisarg)),
1697 g_currentloc);
1698 }
1699 }
140c27a8 1700 else if (flagcode_isPassThrough (opt)) /* preprocessor flag: -D or -U */
1701 {
1702 /*
1703 ** Following space is optional, don't include the -
1704 */
1705
6fcd0b1e 1706 *passThroughArgs = cstringList_add (*passThroughArgs,
1707 cstring_fromCharsNew (thisarg + 1));
140c27a8 1708 }
1709 else if (opt == FLG_INCLUDEPATH || opt == FLG_SPECPATH)
1710 {
c3be2604 1711 if (mstring_length (thisarg) < 2) {
1712 BADBRANCH;
1713 } else {
1714 if (mstring_equal (thisarg, "-I-")) {
1715 cppAddIncludeDir (cstring_fromChars (thisarg)); /* Need to handle this specially. */
1716 } else {
1717 cstring dir = cstring_suffix (cstring_fromChars (thisarg), 2); /* skip over -I */
1718
1719 DPRINTF (("Length of thisarg [%s] %d", thisarg, cstring_length (thisarg)));
1720
1721 if (cstring_length (dir) == 0) {
1722 DPRINTF (("space after directory: "));
1723 if (++i < argc) {
1724 dir = cstring_fromChars (argv[i]);
1725 } else {
1726 voptgenerror
1727 (FLG_BADFLAG,
1728 message
1729 ("Flag %s must be followed by a directory name",
1730 flagcode_unparse (opt)),
1731 g_currentloc);
1732 }
1733 }
1734
1735 DPRINTF (("Got directory: [%s]", dir));
1736
1737 switch (opt)
1738 {
1739 case FLG_INCLUDEPATH:
1740 cppAddIncludeDir (dir);
1741 /*@switchbreak@*/ break;
1742 case FLG_SPECPATH:
1743 /*@-mustfree@*/
1744 g_localSpecPath = cstring_toCharsSafe
1745 (message ("%s%h%s",
1746 cstring_fromChars (g_localSpecPath),
1747 PATH_SEPARATOR,
1748 dir));
1749 /*@=mustfree@*/
1750 /*@switchbreak@*/ break;
1751 BADDEFAULT;
1752 }
140c27a8 1753 }
c3be2604 1754 }
140c27a8 1755 }
1756 else if (flagcode_isModeName (opt))
aa9c1601 1757 {
1758 context_setMode (flagname);
1759 }
ce7034f0 1760 else if (inCommandLine && flagcode_isMessageControlFlag (opt))
aa9c1601 1761 {
1762 /*
1763 ** Processed on first pass
1764 */
1765
1766 if (flagcode_hasArgument (opt))
1767 {
1768 ++i;
1769 }
1770 }
1771 else
1772 {
1773 /*
1774 ** A normal control flag
1775 */
1776
1777 context_userSetFlag (opt, set);
1778
1779 if (flagcode_hasArgument (opt))
1780 {
140c27a8 1781 if (flagcode_hasNumber (opt))
1782 {
1783 if (++i < argc)
aa9c1601 1784 {
16c024b5 1785 flags_setValueFlag (opt, cstring_fromCharsNew (argv[i]));
140c27a8 1786 }
1787 else
aa9c1601 1788 {
140c27a8 1789 voptgenerror
1790 (FLG_BADFLAG,
1791 message
1792 ("Flag %s must be followed by a number",
1793 flagcode_unparse (opt)),
1794 g_currentloc);
1795 }
1796 }
1797 else if (flagcode_hasChar (opt))
1798 {
1799 if (++i < argc)
aa9c1601 1800 {
16c024b5 1801 flags_setValueFlag (opt, cstring_fromCharsNew (argv[i]));
140c27a8 1802 }
1803 else
1804 {
1805 voptgenerror
1806 (FLG_BADFLAG,
1807 message
1808 ("Flag %s must be followed by a character",
1809 flagcode_unparse (opt)),
1810 g_currentloc);
aa9c1601 1811 }
140c27a8 1812 }
1813 else if (flagcode_hasString (opt)
1814 || opt == FLG_INIT || opt == FLG_OPTF)
1815 {
1816 if (++i < argc)
aa9c1601 1817 {
35e063d8 1818 /*drl 10/21/2002
1819 Changed this because arg can be freed when it's passed to
1820 lslinit_setInitFile and freeing argv[i] causes a seg fault
1821 */
1822 cstring arg = cstring_fromCharsNew (argv[i]);
140c27a8 1823
1824 if (opt == FLG_OPTF)
aa9c1601 1825 {
140c27a8 1826 if (inCommandLine)
aa9c1601 1827 {
1828 ; /* -f already processed */
1829 }
140c27a8 1830 else
aa9c1601 1831 {
140c27a8 1832 (void) rcfiles_read (arg, passThroughArgs, TRUE);
1833 }
1834 }
1835 else if (opt == FLG_INIT)
1836 {
140c27a8 1837 lslinit_setInitFile (inputStream_create
1838 (arg,
1839 cstring_makeLiteralTemp (LCLINIT_SUFFIX),
1840 FALSE));
140c27a8 1841 break;
1842 }
1843 else
1844 {
1845 DPRINTF (("String flag: %s / %s",
1846 flagcode_unparse (opt), arg));
1847 if (opt == FLG_MTSFILE)
1848 {
1849 /*
1850 ** arg identifies mts files
1851 */
1852 cstring tmp = message ("%s%s", arg, MTS_EXTENSION);
1853 addLarchPathFile (mtfiles, tmp);
1854 cstring_free (tmp);
1855 tmp = message ("%s%s", arg, XH_EXTENSION);
1856 addXHFile (xfiles, tmp);
1857 cstring_free (tmp);
aa9c1601 1858 }
1859 else
1860 {
16c024b5 1861 flags_setStringFlag (opt, cstring_copy (arg));
aa9c1601 1862 }
1863 }
aa9c1601 1864 }
1865 else
1866 {
140c27a8 1867 voptgenerror
1868 (FLG_BADFLAG,
1869 message
1870 ("Flag %s must be followed by a string",
1871 flagcode_unparse (opt)),
1872 g_currentloc);
aa9c1601 1873 }
1874 }
140c27a8 1875 else
1876 {
1877 /* no argument */
1878 }
aa9c1601 1879 }
1880 }
140c27a8 1881 }
1882 else /* its a filename */
1883 {
1884 DPRINTF (("Adding filename: %s", thisarg));
1885 fl = cstringSList_add (fl, cstring_fromChars (thisarg));
aa9c1601 1886 }
1887 }
aa9c1601 1888
140c27a8 1889 /*
1890 ** create lists of C and LCL files
1891 */
1892
1893 if (inCommandLine)
1894 {
1895 cstringSList_elements (fl, current)
aa9c1601 1896 {
140c27a8 1897 cstring ext = fileLib_getExtension (current);
aa9c1601 1898
140c27a8 1899 if (cstring_isUndefined (ext))
aa9c1601 1900 {
140c27a8 1901 /* no extension --- both C and LCL with default extensions */
1902
1903 addFile (cfiles, message ("%s%s", current, C_EXTENSION));
1904 addFile (lclfiles, message ("%s%s", current, LCL_EXTENSION));
aa9c1601 1905 }
140c27a8 1906 else if (cstring_equal (ext, XH_EXTENSION))
aa9c1601 1907 {
140c27a8 1908 addXHFile (xfiles, current);
aa9c1601 1909 }
140c27a8 1910 else if (cstring_equal (ext, PP_EXTENSION))
aa9c1601 1911 {
140c27a8 1912 if (!context_getFlag (FLG_NOPP))
1913 {
1914 voptgenerror
1915 (FLG_FILEEXTENSIONS,
1916 message ("File extension %s used without +nopp flag (will be processed as C source code): %s",
1917 ext, current),
1918 g_currentloc);
1919 }
1920
1921 addFile (cfiles, cstring_copy (current));
aa9c1601 1922 }
140c27a8 1923 else if (cstring_equal (ext, LCL_EXTENSION))
aa9c1601 1924 {
140c27a8 1925 addFile (lclfiles, cstring_copy (current));
aa9c1601 1926 }
140c27a8 1927 else if (fileLib_isCExtension (ext))
aa9c1601 1928 {
140c27a8 1929 addFile (cfiles, cstring_copy (current));
aa9c1601 1930 }
140c27a8 1931 else if (cstring_equal (ext, MTS_EXTENSION))
aa9c1601 1932 {
140c27a8 1933 addLarchPathFile (mtfiles, current);
aa9c1601 1934 }
140c27a8 1935 else
aa9c1601 1936 {
140c27a8 1937 voptgenerror
1938 (FLG_FILEEXTENSIONS,
1939 message ("Unrecognized file extension: %s (assuming %s is C source code)",
1940 current, ext),
1941 g_currentloc);
aa9c1601 1942
140c27a8 1943 addFile (cfiles, cstring_copy (current));
aa9c1601 1944 }
140c27a8 1945 } end_cstringSList_elements;
1946 }
1947 else
1948 {
1949 if (cstringSList_size (fl) != 0)
aa9c1601 1950 {
140c27a8 1951 /* Cannot list files in .splintrc files */
1952 voptgenerror (FLG_BADFLAG,
1953 message ("Cannot list files in .splintrc files: %s (probable missing + or -)",
1954 cstringSList_unparse (fl)),
1955 g_currentloc);
1956 }
1957 }
6fcd0b1e 1958
1959 cstringSList_free (fl); /* evans 2002-07-12: why wasn't this reported!?? */
140c27a8 1960}
53306cab 1961
1962int flagcode_priority (/*@unused@*/ flagcode code)
1963{
1964 /*
1965 ** For now, we do a really simple prioritization: all are 1
1966 */
1967
1968 return 1;
1969}
This page took 0.363702 seconds and 5 git commands to generate.