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