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