]> andersk Git - splint.git/blame - src/flags.c
Fixed -help <mode> bug.
[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
5b99bfd6 708cstring
709describeMode (cstring mode)
710{
711 cstringSList sflags = sortedFlags ();
712 cstring res = message ("Predefined mode %s sets: ", mode);
713
714 llassert (flags_isModeName (mode));
715
716 context_setMode (mode);
717
718 cstringSList_elements (sflags, flagname)
719 {
720 flagcode code = flags_identifyFlag (flagname);
721 fflag currentflag = flags[code];
722
723 if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
724 {
725 if (context_getFlag (code))
726 {
727 res = message ("%q\n +%s", res, cstring_fromChars (currentflag.flag));
728 }
729 else
730 {
731 res = message ("%q\n -%s", res, cstring_fromChars (currentflag.flag));
732 }
733 }
734 } end_cstringSList_elements;
735
736 cstringSList_free (sflags);
737
738 res = cstring_appendChar (res, '\n');
739 return (res);
740}
741
616915dd 742cstring
743describeFlagCode (flagcode flag)
744{
745 cstring ret = cstring_undefined;
746 fflag f;
4f43223c 747
616915dd 748 if (flagcode_isInvalid (flag))
749 {
750 return (cstring_makeLiteral ("<invalid>"));
751 }
752
5b99bfd6 753 if (flagcode_isModeName (flag))
754 {
755 return (cstring_makeLiteral ("<mode flag>"));
756 }
757
616915dd 758 context_resetAllFlags ();
759
760 f = flags[flag];
761 ret = cstring_copy (cstring_fromChars (f.desc));
616915dd 762
763 if (f.sub != FK_NONE)
764 {
765 ret = message ("%q\nCategories: %s, %s",
766 ret,
767 categoryName (f.main),
768 categoryName (f.sub));
769 }
770 else
771 {
772 if (f.main != FK_NONE)
773 {
774 cstring cname = categoryName (f.main);
775
776 if (cstring_isDefined (cname))
777 {
778 ret = message ("%q\nCategory: %s",
779 ret, cname);
780 }
781 }
782 }
4f43223c 783
616915dd 784 if (f.isModeFlag)
785 {
4f43223c 786 ret = message ("%q\nMode Settings: %q",
787 ret, getFlagModeSettings (flag));
616915dd 788 }
789 else
790 {
791 ret = message ("%q\nDefault Setting: %s",
792 ret,
4f43223c 793 cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
616915dd 794 }
4f43223c 795
616915dd 796 if (f.isGlobal)
797 {
798 ret = message("%q\nSet globally only", ret);
799 }
800 else
801 {
802 ret = message("%q\nSet locally", ret);
803 }
4f43223c 804
616915dd 805 switch (f.argtype)
806 {
807 case ARG_NONE:
808 case ARG_SPECIAL:
809 break;
4f43223c 810 case ARG_NUMBER:
811 ret = message("%q\nNumeric Argument. Default: %d",
812 ret,
813 context_getValue (flag));
814 break;
815 case ARG_CHAR:
816 ret = message("%q\nCharacter Argument. Default: %h",
817 ret, (char) context_getValue (flag));
616915dd 818 break;
819 case ARG_STRING:
4f43223c 820 case ARG_FILE:
821 case ARG_PATH:
822 case ARG_DIRECTORY:
823 {
616915dd 824 if (cstring_isDefined (context_getString (flag)))
825 {
4f43223c 826 ret = message("%q\n%q argument. Default: %s",
616915dd 827 ret,
4f43223c 828 cstring_capitalize (argcode_unparse (f.argtype)),
616915dd 829 context_getString (flag));
830 }
831 else
832 {
4f43223c 833 ret = message("%q\n%s argument. No default.",
834 ret,
835 cstring_capitalize (argcode_unparse (f.argtype)));
616915dd 836 }
837 break;
4f43223c 838 }
616915dd 839 }
4f43223c 840
616915dd 841 if (mstring_isDefined (f.hint))
842 {
843 ret = message("%q\n\3%s", ret, cstring_fromChars (f.hint));
844 }
4f43223c 845
616915dd 846 return ret;
847}
4f43223c 848
849static cstring getFlagModeSettings (flagcode flag)
850{
851 cstring res = cstring_undefined;
852
853 allModes (mname)
854 {
982cc10b 855 context_setModeNoWarn (cstring_fromChars (mname));
4f43223c 856
857 res = message ("%q%s", res, cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
858 } end_allModes;
859
860 return res;
861}
616915dd 862
863cstring
864describeFlag (cstring flagname)
865{
866 cstring oflagname = cstring_copy (flagname);
a956d444 867 flagcode f = flags_identifyFlag (flagname);
616915dd 868
869 if (flagcode_isSkip (f))
870 {
871 cstring_free (oflagname);
872 return cstring_undefined;
873 }
874 else if (flagcode_isValid (f))
875 {
876 if (cstring_equal (flagname, oflagname))
877 {
878 cstring_free (oflagname);
879 return (message ("%s\n\3%q", flagname, describeFlagCode (f)));
880 }
881 else
882 {
883 return (message ("%q (standardized name: %s)\n\3%q",
884 oflagname, flagname, describeFlagCode (f)));
885 }
886 }
887 else
888 {
aa9c1601 889 if (flags_isModeName (flagname))
616915dd 890 {
891 cstring_free (oflagname);
5b99bfd6 892 return describeMode (flagname);
616915dd 893 }
894 else
895 {
896 return (message ("%q: <invalid flag>", oflagname));
897 }
898 }
899}
900
901static cstringSList
902sortedFlags (void)
903{
904 cstringSList s = cstringSList_new ();
905
906 allFlags (f)
907 {
908 if (f.desc != NULL)
909 {
910 s = cstringSList_add (s, cstring_fromChars (f.flag));
911 }
912 } end_allFlags;
913
914 cstringSList_alphabetize (s);
915
916 return s;
917}
918
919void printAlphaFlags ()
920{
921 cstringSList fl = sortedFlags ();
922
923 cstringSList_printSpaced (fl, 3, 1, context_getLineLen () - 25);
924 cstringSList_free (fl);
925}
28bf4b0b 926
616915dd 927/*@observer@*/ cstring
28bf4b0b 928flagcode_unparse (flagcode code)
616915dd 929{
7272a1c1 930 if (code == INVALID_FLAG)
931 {
932 return cstring_makeLiteralTemp ("<invalid flag>");
933 }
934
616915dd 935 return cstring_fromChars (flags[code].flag);
936}
937
938/*
939** Transforms a flag into its cannonical form.
940**
941** The following transformations are made:
942**
943** function -> fcn
944** variable -> var
945** constant -> const
946** iterator -> iter
947** parameter -> param
948** unrecognized -> unrecog
949** qualifier -> qual
950** declaration -> decl
951** globalias -> (no change)
952** global -> glob
953** modifies -> mods
954** modify -> mod
955** pointer -> ptr
956** implies -> imp
957** implicit -> imp
958** implied -> imp
959** unconstrained -> unspec
960** unconst -> unspec
961** memory -> mem
962** length -> len
963*/
964
92b2ba2c 965static /*@only@*/ cstring
616915dd 966canonicalizeFlag (cstring s)
967{
968 int i = 0;
92b2ba2c 969 cstring res = cstring_copy (s);
616915dd 970 static bn_mstring transform[] =
971 {
972 "function", "fcn",
973 "variable", "var",
974 "constant", "const",
975 "iterator", "iter",
976 "parameter", "param",
977 "unrecognized", "unrecog",
978 "qualifier", "qual",
979 "declaration", "decl",
980 "globals", "globs",
981 "modifies", "mods",
982 "modify", "mod",
983 "pointer", "ptr",
984 "implies", "imp",
985 "implicit", "imp",
986 "implied", "imp",
987 "unconstrained", "uncon",
988 "unconst", "uncon",
989 "memory", "mem",
990 "length", "len",
991 "return", "ret",
992 "system", "sys",
993 NULL
994 } ;
995 char *current;
86d93ed3 996
616915dd 997 while ((current = transform[i]) != NULL)
998 {
92b2ba2c 999 if (cstring_containsLit (res, current))
616915dd 1000 {
92b2ba2c 1001 cstring_replaceLit (res, current, transform[i+1]);
616915dd 1002 }
1003 i += 2;
1004 }
1005
1006 /* remove whitespace, -'s, and _'s */
92b2ba2c 1007 cstring_stripChars (res, " -_");
1008 return res;
616915dd 1009}
1010
1011flagcode
a956d444 1012flags_identifyFlag (cstring s)
1013{
1014 return flags_identifyFlagAux (s, FALSE);
1015}
1016
1017flagcode
1018flags_identifyFlagQuiet (cstring s)
1019{
1020 return flags_identifyFlagAux (s, TRUE);
1021}
1022
1023static flagcode
1024flags_identifyFlagAux (cstring s, bool quiet)
616915dd 1025{
92b2ba2c 1026 cstring cflag;
1027 flagcode res;
1028
616915dd 1029 if (cstring_length (s) == 0) {
1030 /* evs 2000-06-25: A malformed flag. */
1031 return INVALID_FLAG;
1032 }
1033
1034 if (cstring_firstChar (s) == 'I')
1035 {
aa9c1601 1036 return FLG_INCLUDEPATH; /* no space required after -I */
616915dd 1037 }
1038
1039 if (cstring_firstChar (s) == 'S')
1040 {
aa9c1601 1041 return FLG_SPECPATH; /* no space required after -S */
616915dd 1042 }
1043
1044 if (cstring_firstChar (s) == 'D')
1045 {
aa9c1601 1046 return FLG_DEFINE; /* no space required after -D */
616915dd 1047 }
1048
1049 if (cstring_firstChar (s) == 'U')
1050 {
aa9c1601 1051 return FLG_UNDEFINE; /* no space required after -D */
616915dd 1052 }
1053
92b2ba2c 1054 cflag = canonicalizeFlag (s);
1055 res = INVALID_FLAG;
616915dd 1056
1057 allFlags (f)
1058 {
92b2ba2c 1059 if (cstring_equal (cstring_fromChars (f.flag), cflag))
616915dd 1060 {
92b2ba2c 1061 res = f.code;
1062 break;
616915dd 1063 }
1064 } end_allFlags;
616915dd 1065
92b2ba2c 1066 if (res == INVALID_FLAG)
616915dd 1067 {
92b2ba2c 1068 /*
1069 ** Synonyms
1070 */
1071
1072 if (cstring_equalLit (cflag, "pred"))
a956d444 1073 {
92b2ba2c 1074 res = FLG_PREDBOOL;
1075 }
1076 else if (cstring_equalLit (cflag, "modobserverstrict"))
1077 {
1078 res = FLG_MODOBSERVERUNCON;
1079 }
1080 else if (cstring_equalLit (cflag, "czechnames"))
1081 {
1082 res = FLG_CZECH;
a956d444 1083 }
92b2ba2c 1084 else if (cstring_equalLit (cflag, "slovaknames"))
1085 {
1086 res = FLG_SLOVAK;
1087 }
1088 else if (cstring_equalLit (cflag, "czechoslovaknames"))
1089 {
1090 res = FLG_CZECHOSLOVAK;
1091 }
1092 else if (cstring_equalLit (cflag, "globunspec")
1093 || cstring_equalLit (cflag, "globuncon"))
1094 {
1095 res = FLG_GLOBUNSPEC;
1096 }
1097 else if (cstring_equalLit (cflag, "modglobsunspec")
1098 || cstring_equalLit (cflag, "modglobsuncon")
1099 || cstring_equalLit (cflag, "modglobsnomods"))
1100 {
1101 res = FLG_MODGLOBSUNSPEC;
1102 }
1103 else if (cstring_equalLit (cflag, "export"))
1104 {
1105 res = FLG_EXPORTANY;
1106 }
1107 else if (cstring_equalLit (cflag, "macrospec"))
1108 {
1109 res = FLG_MACRODECL;
1110 }
1111 else if (cstring_equalLit (cflag, "ansireservedlocal"))
1112 {
abd7f895 1113 res = FLG_ISORESERVEDLOCAL;
92b2ba2c 1114 }
1115 else if (cstring_equalLit (cflag, "warnposix"))
1116 {
1117 res = FLG_WARNPOSIX;
1118 }
1119 else if (cstring_equalLit (cflag, "defuse"))
1120 {
1121 res = FLG_USEDEF;
1122 }
1123 else if (cstring_equalLit (cflag, "macroundef"))
1124 {
1125 res = FLG_MACROUNDEF;
1126 }
1127 else if (cstring_equalLit (cflag, "showcol"))
1128 {
1129 res = FLG_SHOWCOL;
1130 }
1131 else if (cstring_equalLit (cflag, "intbool"))
1132 {
1133 res = FLG_BOOLINT;
1134 }
1135 else if (cstring_equalLit (cflag, "intchar"))
1136 {
1137 res = FLG_CHARINT;
1138 }
1139 else if (cstring_equalLit (cflag, "intenum"))
1140 {
1141 res = FLG_ENUMINT;
1142 }
81fc136a 1143 else if (cstring_equalLit (cflag, "intlong"))
1144 {
1145 res = FLG_LONGINT;
1146 }
1147 else if (cstring_equalLit (cflag, "intshort"))
1148 {
1149 res = FLG_SHORTINT;
1150 }
92b2ba2c 1151 /*
1152 ** Backwards compatibility for our American friends...
1153 */
616915dd 1154
92b2ba2c 1155 else if (cstring_equalLit (cflag, "ansilib"))
1156 {
1157 res = FLG_ANSILIB;
1158 }
1159 else if (cstring_equalLit (cflag, "ansistrictlib"))
1160 {
1161 res = FLG_STRICTLIB;
1162 }
1163 else if (cstring_equalLit (cflag, "skipansiheaders"))
1164 {
abd7f895 1165 res = FLG_SKIPISOHEADERS;
92b2ba2c 1166 }
1167 else if (cstring_equalLit (cflag, "ansireserved"))
1168 {
abd7f895 1169 res = FLG_ISORESERVED;
92b2ba2c 1170 }
1171 else if (cstring_equalLit (cflag, "ansireservedinternal"))
1172 {
abd7f895 1173 res = FLG_ISORESERVEDLOCAL;
92b2ba2c 1174 }
1175
1176 /*
1177 ** Obsolete Flags
1178 */
1179
1180 else if (cstring_equalLit (cflag, "accessunspec"))
1181 {
1182 if (!quiet)
1183 {
1184 llerror_flagWarning
1185 (cstring_makeLiteral
1186 ("accessunspec flag is no longer supported. It has been replaced by accessmodule, accessfile and "
1187 "accessfunction to provide more precise control of accessibility "
1188 "of representations. For more information, "
1189 "see splint -help accessmodule"));
1190 }
1191
1192 res = SKIP_FLAG;
1193 }
1194 else if (cstring_equalLit (cflag, "ansilimits"))
1195 {
27c9e640 1196 llerror_flagWarning
1197 (cstring_makeLiteral
1198 ("ansilimits flag is no longer supported. It has been replaced by ansi89limits and "
1199 "iso99limits to select either the lower translation limits imposed by the ANSI89 "
1200 "standard or the typically higher limits prescribed by ISO C99."));
92b2ba2c 1201
1202 res = SKIP_FLAG;
1203 }
1204 else if (cstring_equalLit (cflag, "staticmods"))
a956d444 1205 {
92b2ba2c 1206 if (!quiet)
1207 {
1208 llerror_flagWarning
1209 (cstring_makeLiteral
1210 ("staticmods flag is obsolete. You probably "
1211 "want impcheckmodstatics. For more information, "
1212 "see splint -help impcheckmodstatics"));
1213 }
1214
1215 res = SKIP_FLAG;
a956d444 1216 }
92b2ba2c 1217 else if (cstring_equalLit (cflag, "bool"))
a956d444 1218 {
92b2ba2c 1219 if (!quiet)
1220 {
1221 llerror_flagWarning
1222 (cstring_makeLiteral ("bool flag is obsolete. It never really "
1223 "made sense in the first place."));
1224 }
1225
1226 res = SKIP_FLAG;
a956d444 1227 }
92b2ba2c 1228 else if (cstring_equalLit (cflag, "shiftsigned"))
a956d444 1229 {
92b2ba2c 1230 if (!quiet)
1231 {
1232 llerror_flagWarning
1233 (cstring_makeLiteral ("shiftsigned flag is obsolete. You probably "
06418c9b 1234 "want bitwisesigned, shiftnegative or shiftimplementation."));
92b2ba2c 1235 }
1236
1237 res = SKIP_FLAG;
a956d444 1238 }
92b2ba2c 1239 else if (cstring_equalLit (cflag, "ansi"))
a956d444 1240 {
92b2ba2c 1241 if (!quiet)
1242 {
1243 llerror_flagWarning
1244 (cstring_makeLiteral ("ansi flag is obsolete. You probably "
1245 "want noparams and/or oldstyle."));
1246 }
1247
1248 res = SKIP_FLAG;
a956d444 1249 }
80489f0a 1250 else if (cstring_equalLit (cflag, "usestderr"))
1251 {
1252 if (!quiet)
1253 {
1254 llerror_flagWarning
1255 (cstring_makeLiteral
1256 ("usestderr flag is obsolete. This has been replaced "
1257 "by more precise flags for controlling the warning, "
1258 "status message and fatal error streams independently: message-stream-stdout, "
1259 "message-stream-stderr, message-stream <file>, "
1260 "warning-stream-stdout, warning-stream-stderr, warning-stream <file>, "
1261 "error-stream-stdout, error-stream-stderr, error-stream <file>."));
1262 }
1263
1264 res = SKIP_FLAG;
1265 }
1266
92b2ba2c 1267 else if (cstring_equalLit (cflag, "stdio"))
a956d444 1268 {
92b2ba2c 1269 if (!quiet)
1270 {
1271 llerror_flagWarning
1272 (cstring_makeLiteral
1273 ("stdio flag is obsolete. You may "
1274 "want strictlib or one of the gloabls "
1275 "checking flags. For more information, "
1276 "see splint -help strictlib or splint -help flags globals"));
1277 }
1278
1279 res = SKIP_FLAG;
1280 }
aa9c1601 1281 else if (flags_isModeName (cflag))
1282 {
1283 res = MODENAME_FLAG;
140c27a8 1284 }
92b2ba2c 1285 else
1286 {
1287 res = INVALID_FLAG;
a956d444 1288 }
a956d444 1289 }
92b2ba2c 1290
1291 cstring_free (cflag);
1292 return res;
616915dd 1293}
1294
16c024b5 1295void flags_setValueFlag (flagcode opt, cstring arg)
616915dd 1296{
1297 switch (opt)
1298 {
1299 case FLG_EXPECT:
1300 case FLG_LCLEXPECT:
1301 case FLG_LIMIT:
1302 case FLG_LINELEN:
28bf4b0b 1303 case FLG_INDENTSPACES:
16c024b5 1304 case FLG_LOCINDENTSPACES:
28bf4b0b 1305 case FLG_BUGSLIMIT:
616915dd 1306 case FLG_EXTERNALNAMELEN:
1307 case FLG_INTERNALNAMELEN:
1308 case FLG_CONTROLNESTDEPTH:
1309 case FLG_STRINGLITERALLEN:
1310 case FLG_NUMSTRUCTFIELDS:
1311 case FLG_NUMENUMMEMBERS:
1312 case FLG_INCLUDENEST:
1313 {
1314 int val = cstring_toPosInt (arg);
1315
1316 if (val < 0)
1317 {
1318 llerror
1319 (FLG_BADFLAG,
1320 message
1321 ("Flag %s must be followed by a positive number number. "
1322 "Followed by %s",
1323 flagcode_unparse (opt), arg));
1324 }
1325 else
1326 {
28bf4b0b 1327 context_setValueAndFlag (opt, val);
616915dd 1328 }
1329 }
1330 break;
1331 case FLG_COMMENTCHAR:
1332 {
1333 if (cstring_length (arg) != 1)
1334 {
1335 llfatalerrorLoc
1336 (message
1337 ("Flag %s should be followed by a single character. Followed by %s",
1338 flagcode_unparse (opt), arg));
1339 }
1340 else
1341 {
1342 context_setCommentMarkerChar (cstring_firstChar (arg));
1343 }
1344 }
1345 break;
16c024b5 1346 BADDEFAULT;
616915dd 1347 }
1348}
1349
16c024b5 1350void flags_setStringFlag (flagcode opt, /*@only@*/ cstring arg)
616915dd 1351{
1352 switch (opt)
1353 {
1354 case FLG_TMPDIR:
1355 {
1356 if (cstring_lastChar (arg) == CONNECTCHAR)
1357 {
1358 context_setString (opt, arg);
1359 }
1360 else
1361 {
1362 context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1363 }
1364 break;
1365 }
1366 default:
1367 {
1368 context_setString (opt, arg);
1369 break;
1370 }
1371 }
1372}
1373
1374cstring
1375describeModes ()
1376{
1377 cstring s = cstring_makeLiteral ("Flag ");
1378 cstringSList sflags = sortedFlags ();
1379
1380 allModes (modename)
1381 {
1382 s = message ("%q%9s", s, cstring_fromChars (modename));
1383 } end_allModes;
1384
1385 s = message ("%q\n", s);
1386
1387 cstringSList_elements (sflags, flagname)
1388 {
a956d444 1389 flagcode code = flags_identifyFlag (flagname);
616915dd 1390 fflag currentflag = flags[code];
1391
1392 if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1393 {
1394 s = message ("%q\n%27s", s,
1395 cstring_fromChars (currentflag.flag));
1396
1397 allModes (modename)
1398 {
1399 context_setMode (cstring_fromChars (modename));
1400
1401 if (context_getFlag (code))
1402 {
1403 s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1404 }
1405 else
1406 {
1407 s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1408 }
1409
1410 context_resetModeFlags ();
1411 } end_allModes;
1412 }
1413 } end_cstringSList_elements;
1414
1415 cstringSList_free (sflags);
1416
1417 s = cstring_appendChar (s, '\n');
1418
1419 return (s);
1420}
1421
8250fa4a 1422# if 0
ee229125 1423static /*@unused@*/ cstring
616915dd 1424listModes (void)
1425{
1426 cstring s = cstring_makeLiteral ("\t");
1427 int i = 0;
1428
1429 allModes (modename)
1430 {
1431 if (i != 0 && (i % 4 == 0))
1432 {
1433 s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1434 }
1435 else
1436 {
1437 s = message ("%q%15s", s, cstring_fromChars (modename));
1438 }
1439 i++;
1440 } end_allModes;
1441
1442 return s;
1443}
8250fa4a 1444# endif
616915dd 1445
1446bool
aa9c1601 1447flags_isModeName (cstring s)
616915dd 1448{
1449 allModes (modename)
1450 {
1451 if (mstring_isDefined (modename))
1452 {
1453 if (cstring_equalLit (s, modename))
1454 {
1455 return TRUE;
1456 }
1457 }
1458 } end_allModes;
1459
1460 return FALSE;
1461}
1462
1463extern bool flagcode_hasArgument (flagcode f)
1464{
1465 return (flags[f].argtype != ARG_NONE);
1466}
1467
4f43223c 1468extern bool flagcode_hasNumber (flagcode f)
1469{
1470 return (flags[f].argtype == ARG_NUMBER);
1471}
1472
1473extern bool flagcode_hasChar (flagcode f)
616915dd 1474{
4f43223c 1475 return (flags[f].argtype == ARG_CHAR);
616915dd 1476}
1477
1478extern bool flagcode_hasString (flagcode f)
1479{
4f43223c 1480 return (flags[f].argtype == ARG_STRING
1481 || flags[f].argtype == ARG_FILE
1482 || flags[f].argtype == ARG_DIRECTORY
1483 || flags[f].argtype == ARG_PATH);
616915dd 1484}
1485
1486extern int flagcode_valueIndex (flagcode f)
1487{
1488 /*@unchecked@*/ static bool initialized = FALSE;
1489 int i;
1490 /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
616915dd 1491
1492 if (!initialized)
1493 {
1494 int nv = 0;
1495
1496 allFlagCodes (code)
1497 {
4f43223c 1498 if (flagcode_hasNumber (code) || flagcode_hasChar (code))
616915dd 1499 {
1500 llassert (nv < NUMVALUEFLAGS);
28bf4b0b 1501 DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
616915dd 1502 valueFlags[nv] = code;
28bf4b0b 1503 nv++;
616915dd 1504 }
1505 } end_allFlagCodes;
1506
1507 llassertprint (nv == NUMVALUEFLAGS,
28bf4b0b 1508 ("Number of value flags: %d (expected %d)",
1509 nv, (int) NUMVALUEFLAGS));
616915dd 1510 initialized = TRUE;
1511 }
1512
1513 for (i = 0; i < NUMVALUEFLAGS; i++)
1514 {
1515 /* static valueFlags must be defined */
86d93ed3 1516 /*@-usedef@*/
86d93ed3 1517 if (f == valueFlags[i]) /*@=usedef@*/
616915dd 1518 {
1519 return i;
1520 }
1521 }
1522
28bf4b0b 1523 fprintf (stderr, "Cannot find value flag: %d", (int) f);
1524 exit (EXIT_FAILURE);
1525 /* Cannot do this...might call recursively...
1526 llfatalbug (message ("Cannot fine value flag: %d", (int) f));
616915dd 1527 BADEXIT;
28bf4b0b 1528 */
616915dd 1529}
1530
1531extern int flagcode_stringIndex (flagcode f)
1532{
1533 /*@unchecked@*/ static bool initialized = FALSE;
1534 /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1535 int i;
1536
1537
1538 if (!initialized)
1539 {
1540 int nv = 0;
1541
1542 allFlagCodes (code)
1543 {
1544 if (flagcode_hasString (code))
1545 {
1546 llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1547 stringFlags[nv] = code;
1548 nv++;
1549 }
1550 } end_allFlagCodes;
1551
1552 llassertprint (nv == NUMSTRINGFLAGS,
1553 ("number of string flags: %d (expected %d)",
1554 nv, NUMSTRINGFLAGS));
1555 initialized = TRUE;
1556 }
1557
1558 for (i = 0; i < NUMSTRINGFLAGS; i++)
1559 {
1560 /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1561 {
1562 return i;
1563 }
1564 }
1565
1566 llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1567 BADEXIT;
1568}
1569
1570bool flagcode_isNamePrefixFlag (flagcode f)
1571{
1572 switch (f)
1573 {
1574 case FLG_MACROVARPREFIX:
1575 case FLG_TAGPREFIX:
1576 case FLG_ENUMPREFIX:
1577 case FLG_FILESTATICPREFIX:
1578 case FLG_GLOBPREFIX:
1579 case FLG_TYPEPREFIX:
1580 case FLG_EXTERNALPREFIX:
1581 case FLG_LOCALPREFIX:
1582 case FLG_UNCHECKEDMACROPREFIX:
1583 case FLG_CONSTPREFIX:
1584 case FLG_ITERPREFIX:
1585 case FLG_DECLPARAMPREFIX:
1586 return TRUE;
1587 default:
1588 return FALSE;
1589 }
1590}
140c27a8 1591
1592static cstring findLarchPathFile (/*@temp@*/ cstring s)
aa9c1601 1593{
140c27a8 1594 cstring pathName;
1595 filestatus status;
1596
1597 status = osd_getPath (context_getLarchPath (), s, &pathName);
1598
1599 if (status == OSD_FILEFOUND)
1600 {
1601 return pathName;
1602 }
1603 else if (status == OSD_FILENOTFOUND)
1604 {
1605 showHerald ();
1606 lldiagmsg (message ("Cannot find file on LARCH_PATH: %s", s));
1607 }
1608 else if (status == OSD_PATHTOOLONG)
1609 {
1610 /* Directory and filename are too long. Report error. */
1611 llbuglit ("soure_getPath: Filename plus directory from search path too long");
1612 }
1613 else
1614 {
1615 BADBRANCH;
1616 }
1617
1618 return cstring_undefined;
1619}
1620
1621static void addLarchPathFile (fileIdList files, /*@temp@*/ cstring s)
1622{
1623 cstring pathName = findLarchPathFile (s);
1624
1625 if (cstring_isDefined (pathName))
1626 {
1627 if (fileTable_exists (context_fileTable (), pathName))
1628 {
1629 showHerald ();
1630 lldiagmsg (message ("File listed multiple times: %s", pathName));
1631 cstring_free (pathName);
1632 }
1633 else
1634 {
1635 fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), pathName));
1636 }
1637 }
1638}
1639
1640
1641static void addFile (fileIdList files, /*@only@*/ cstring s)
1642{
1643 if (fileTable_exists (context_fileTable (), s))
1644 {
1645 showHerald ();
1646 lldiagmsg (message ("File listed multiple times: %s", s));
1647 cstring_free (s);
1648 }
1649 else
1650 {
1651 fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), s));
1652 }
1653}
1654
1655static void addXHFile (fileIdList files, /*@temp@*/ cstring s)
1656{
1657 cstring pathName = findLarchPathFile (s);
1658
1659 if (cstring_isDefined (pathName))
1660 {
1661 if (fileTable_exists (context_fileTable (), pathName))
1662 {
1663 showHerald ();
1664 lldiagmsg (message ("File listed multiple times: %s", s));
1665 }
1666 else
1667 {
1668 fileIdList_add (files, fileTable_addXHFile (context_fileTable (), pathName));
1669 }
1670 }
aa9c1601 1671
140c27a8 1672 cstring_free (pathName);
1673}
1674
1675void
1676flags_processFlags (bool inCommandLine,
1677 fileIdList xfiles,
1678 fileIdList cfiles,
1679 fileIdList lclfiles,
1680 fileIdList mtfiles,
6fcd0b1e 1681 cstringList *passThroughArgs,
140c27a8 1682 int argc, char **argv)
1683{
1684 int i;
1685 cstringSList fl = cstringSList_undefined;
1686
aa9c1601 1687 for (i = 0; i < argc; i++)
1688 {
140c27a8 1689 char *thisarg;
1690
1691 llassert (argv != NULL);
1692 thisarg = argv[i];
ce7034f0 1693
1694 DPRINTF (("process thisarg [%d]: %s", i, thisarg));
140c27a8 1695
aa9c1601 1696 if (*thisarg == '-' || *thisarg == '+')
1697 {
1698 bool set = (*thisarg == '+');
368f75ae 1699 cstring flagname;
1700 flagcode opt;
aa9c1601 1701
368f75ae 1702 if (*(thisarg + 1) == '-') { /* allow -- before flags */
1703 flagname = cstring_fromChars (thisarg + 2);
1704 } else {
1705 flagname = cstring_fromChars (thisarg + 1);
1706 }
1707
1708 opt = flags_identifyFlag (flagname);
53306cab 1709 DPRINTF (("Flag [%s]: %s", flagname, flagcode_unparse (opt)));
aa9c1601 1710
1711 if (flagcode_isInvalid (opt))
1712 {
1713 DPRINTF (("Error!"));
1714 voptgenerror (FLG_BADFLAG,
1715 message ("Unrecognized option: %s",
1716 cstring_fromChars (thisarg)),
1717 g_currentloc);
1718 }
1719 else if (flagcode_isHelpFlag (opt))
1720 {
1721 if (inCommandLine)
1722 {
1723 voptgenerror (FLG_BADFLAG,
1724 message ("Help flag must be first on the command line: %s",
1725 cstring_fromChars (thisarg)),
1726 g_currentloc);
1727 }
1728 else
1729 {
1730 voptgenerror (FLG_BADFLAG,
1731 message ("Help flags can only be used on the command line: %s",
1732 cstring_fromChars (thisarg)),
1733 g_currentloc);
1734 }
1735 }
140c27a8 1736 else if (flagcode_isPassThrough (opt)) /* preprocessor flag: -D or -U */
1737 {
1738 /*
1739 ** Following space is optional, don't include the -
1740 */
1741
6fcd0b1e 1742 *passThroughArgs = cstringList_add (*passThroughArgs,
1743 cstring_fromCharsNew (thisarg + 1));
140c27a8 1744 }
1745 else if (opt == FLG_INCLUDEPATH || opt == FLG_SPECPATH)
1746 {
c3be2604 1747 if (mstring_length (thisarg) < 2) {
1748 BADBRANCH;
1749 } else {
1750 if (mstring_equal (thisarg, "-I-")) {
1751 cppAddIncludeDir (cstring_fromChars (thisarg)); /* Need to handle this specially. */
1752 } else {
1753 cstring dir = cstring_suffix (cstring_fromChars (thisarg), 2); /* skip over -I */
1754
1755 DPRINTF (("Length of thisarg [%s] %d", thisarg, cstring_length (thisarg)));
1756
1757 if (cstring_length (dir) == 0) {
1758 DPRINTF (("space after directory: "));
1759 if (++i < argc) {
1760 dir = cstring_fromChars (argv[i]);
1761 } else {
1762 voptgenerror
1763 (FLG_BADFLAG,
1764 message
1765 ("Flag %s must be followed by a directory name",
1766 flagcode_unparse (opt)),
1767 g_currentloc);
1768 }
1769 }
1770
1771 DPRINTF (("Got directory: [%s]", dir));
1772
1773 switch (opt)
1774 {
1775 case FLG_INCLUDEPATH:
1776 cppAddIncludeDir (dir);
1777 /*@switchbreak@*/ break;
1778 case FLG_SPECPATH:
1779 /*@-mustfree@*/
1780 g_localSpecPath = cstring_toCharsSafe
1781 (message ("%s%h%s",
1782 cstring_fromChars (g_localSpecPath),
1783 PATH_SEPARATOR,
1784 dir));
1785 /*@=mustfree@*/
1786 /*@switchbreak@*/ break;
1787 BADDEFAULT;
1788 }
140c27a8 1789 }
c3be2604 1790 }
140c27a8 1791 }
1792 else if (flagcode_isModeName (opt))
aa9c1601 1793 {
1794 context_setMode (flagname);
1795 }
ce7034f0 1796 else if (inCommandLine && flagcode_isMessageControlFlag (opt))
aa9c1601 1797 {
1798 /*
1799 ** Processed on first pass
1800 */
1801
1802 if (flagcode_hasArgument (opt))
1803 {
1804 ++i;
1805 }
1806 }
1807 else
1808 {
1809 /*
1810 ** A normal control flag
1811 */
1812
1813 context_userSetFlag (opt, set);
1814
1815 if (flagcode_hasArgument (opt))
1816 {
140c27a8 1817 if (flagcode_hasNumber (opt))
1818 {
1819 if (++i < argc)
aa9c1601 1820 {
16c024b5 1821 flags_setValueFlag (opt, cstring_fromCharsNew (argv[i]));
140c27a8 1822 }
1823 else
aa9c1601 1824 {
140c27a8 1825 voptgenerror
1826 (FLG_BADFLAG,
1827 message
1828 ("Flag %s must be followed by a number",
1829 flagcode_unparse (opt)),
1830 g_currentloc);
1831 }
1832 }
1833 else if (flagcode_hasChar (opt))
1834 {
1835 if (++i < argc)
aa9c1601 1836 {
16c024b5 1837 flags_setValueFlag (opt, cstring_fromCharsNew (argv[i]));
140c27a8 1838 }
1839 else
1840 {
1841 voptgenerror
1842 (FLG_BADFLAG,
1843 message
1844 ("Flag %s must be followed by a character",
1845 flagcode_unparse (opt)),
1846 g_currentloc);
aa9c1601 1847 }
140c27a8 1848 }
1849 else if (flagcode_hasString (opt)
1850 || opt == FLG_INIT || opt == FLG_OPTF)
1851 {
1852 if (++i < argc)
aa9c1601 1853 {
35e063d8 1854 /*drl 10/21/2002
1855 Changed this because arg can be freed when it's passed to
1856 lslinit_setInitFile and freeing argv[i] causes a seg fault
1857 */
1858 cstring arg = cstring_fromCharsNew (argv[i]);
140c27a8 1859
1860 if (opt == FLG_OPTF)
aa9c1601 1861 {
140c27a8 1862 if (inCommandLine)
aa9c1601 1863 {
1864 ; /* -f already processed */
1865 }
140c27a8 1866 else
aa9c1601 1867 {
140c27a8 1868 (void) rcfiles_read (arg, passThroughArgs, TRUE);
1869 }
1870 }
1871 else if (opt == FLG_INIT)
1872 {
140c27a8 1873 lslinit_setInitFile (inputStream_create
1874 (arg,
1875 cstring_makeLiteralTemp (LCLINIT_SUFFIX),
1876 FALSE));
140c27a8 1877 break;
1878 }
1879 else
1880 {
1881 DPRINTF (("String flag: %s / %s",
1882 flagcode_unparse (opt), arg));
1883 if (opt == FLG_MTSFILE)
1884 {
1885 /*
1886 ** arg identifies mts files
1887 */
1888 cstring tmp = message ("%s%s", arg, MTS_EXTENSION);
1889 addLarchPathFile (mtfiles, tmp);
1890 cstring_free (tmp);
1891 tmp = message ("%s%s", arg, XH_EXTENSION);
1892 addXHFile (xfiles, tmp);
1893 cstring_free (tmp);
aa9c1601 1894 }
1895 else
1896 {
16c024b5 1897 flags_setStringFlag (opt, cstring_copy (arg));
aa9c1601 1898 }
1899 }
aa9c1601 1900 }
1901 else
1902 {
140c27a8 1903 voptgenerror
1904 (FLG_BADFLAG,
1905 message
1906 ("Flag %s must be followed by a string",
1907 flagcode_unparse (opt)),
1908 g_currentloc);
aa9c1601 1909 }
1910 }
140c27a8 1911 else
1912 {
1913 /* no argument */
1914 }
aa9c1601 1915 }
1916 }
140c27a8 1917 }
1918 else /* its a filename */
1919 {
1920 DPRINTF (("Adding filename: %s", thisarg));
1921 fl = cstringSList_add (fl, cstring_fromChars (thisarg));
aa9c1601 1922 }
1923 }
aa9c1601 1924
140c27a8 1925 /*
1926 ** create lists of C and LCL files
1927 */
1928
1929 if (inCommandLine)
1930 {
1931 cstringSList_elements (fl, current)
aa9c1601 1932 {
140c27a8 1933 cstring ext = fileLib_getExtension (current);
aa9c1601 1934
140c27a8 1935 if (cstring_isUndefined (ext))
aa9c1601 1936 {
140c27a8 1937 /* no extension --- both C and LCL with default extensions */
1938
1939 addFile (cfiles, message ("%s%s", current, C_EXTENSION));
1940 addFile (lclfiles, message ("%s%s", current, LCL_EXTENSION));
aa9c1601 1941 }
140c27a8 1942 else if (cstring_equal (ext, XH_EXTENSION))
aa9c1601 1943 {
140c27a8 1944 addXHFile (xfiles, current);
aa9c1601 1945 }
140c27a8 1946 else if (cstring_equal (ext, PP_EXTENSION))
aa9c1601 1947 {
140c27a8 1948 if (!context_getFlag (FLG_NOPP))
1949 {
1950 voptgenerror
1951 (FLG_FILEEXTENSIONS,
1952 message ("File extension %s used without +nopp flag (will be processed as C source code): %s",
1953 ext, current),
1954 g_currentloc);
1955 }
1956
1957 addFile (cfiles, cstring_copy (current));
aa9c1601 1958 }
140c27a8 1959 else if (cstring_equal (ext, LCL_EXTENSION))
aa9c1601 1960 {
140c27a8 1961 addFile (lclfiles, cstring_copy (current));
aa9c1601 1962 }
140c27a8 1963 else if (fileLib_isCExtension (ext))
aa9c1601 1964 {
140c27a8 1965 addFile (cfiles, cstring_copy (current));
aa9c1601 1966 }
140c27a8 1967 else if (cstring_equal (ext, MTS_EXTENSION))
aa9c1601 1968 {
140c27a8 1969 addLarchPathFile (mtfiles, current);
aa9c1601 1970 }
140c27a8 1971 else
aa9c1601 1972 {
140c27a8 1973 voptgenerror
1974 (FLG_FILEEXTENSIONS,
1975 message ("Unrecognized file extension: %s (assuming %s is C source code)",
1976 current, ext),
1977 g_currentloc);
aa9c1601 1978
140c27a8 1979 addFile (cfiles, cstring_copy (current));
aa9c1601 1980 }
140c27a8 1981 } end_cstringSList_elements;
1982 }
1983 else
1984 {
1985 if (cstringSList_size (fl) != 0)
aa9c1601 1986 {
140c27a8 1987 /* Cannot list files in .splintrc files */
1988 voptgenerror (FLG_BADFLAG,
1989 message ("Cannot list files in .splintrc files: %s (probable missing + or -)",
1990 cstringSList_unparse (fl)),
1991 g_currentloc);
1992 }
1993 }
6fcd0b1e 1994
1995 cstringSList_free (fl); /* evans 2002-07-12: why wasn't this reported!?? */
140c27a8 1996}
53306cab 1997
1998int flagcode_priority (/*@unused@*/ flagcode code)
1999{
2000 /*
2001 ** For now, we do a really simple prioritization: all are 1
2002 */
2003
2004 return 1;
2005}
This page took 0.426055 seconds and 5 git commands to generate.