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