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