00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 # include "lclintMacros.nf"
00029 # include "basic.h"
00030 # include "portab.h"
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 typedef struct {
00044 flagkind kind;
00045 char *name;
00046 char *describe;
00047 } flagcatinfo;
00048
00049 static flagcatinfo categories[] =
00050 {
00051 { FK_ABSTRACT, "abstract", "abstraction violations, representation access" } ,
00052 { FK_ALIAS, "aliasing", "unexpected or dangerous aliasing" } ,
00053 { FK_USE, "alluse", "all declarations are used" } ,
00054 { FK_ANSI, "ansi", "violations of constraints imposed by ANSI/ISO standard" } ,
00055 { FK_ARRAY, "arrays", "special checking involving arrays" } ,
00056 { FK_BOOL, "booleans", "checking and naming of boolean types" } ,
00057 { FK_COMMENTS, "comments", "interpretation of stylized comments" } ,
00058 { FK_COMPLETE, "complete", "completely defined, used, or specified system" } ,
00059 { FK_CONTROL, "controlflow", "suspicious control structures" } ,
00060 { FK_DECL, "declarations", "consistency of declarations" } ,
00061 { FK_DEF, "definition", "undefined storage errors" } ,
00062 { FK_DIRECT, "directories", "set directores" } ,
00063 { FK_DISPLAY, "display", "control what is displayed" } ,
00064 { FK_EFFECT, "effect", "statements with no effects" } ,
00065 { FK_ERRORS, "errors", "control expected errors, summary reporting" } ,
00066 { FK_EXPORT, "export", "control what may be exported" } ,
00067 { FK_EXPOSURE, "exposure", "representation exposure" } ,
00068 { FK_FILES, "files", "control system files" } ,
00069 { FK_FORMAT, "format", "control format of warning messages" } ,
00070 { FK_GLOBALS, "globals", "use of global and file static variables" },
00071 { FK_HEADERS, "headers", "control inclusion and generation of header files" },
00072 { FK_HELP, "help", "on-line help" },
00073 { FK_IMPLICIT, "implicit", "control implicit annotations and interpretations" } ,
00074 { FK_INIT, "initializations", "initialization files" } ,
00075 { FK_ITER, "iterators", "checking iterator definitions and uses" } ,
00076 { FK_LEAK, "leaks", "memory leaks" } ,
00077 { FK_LIBS, "libraries", "loading and dumping of user and standard libraries" } ,
00078 { FK_LIMITS, "limits", "violations of set limits" } ,
00079 { FK_MACROS, "macros", "expansion, definition and use of macros" },
00080 { FK_MEMORY, "memory", "memory management" } ,
00081 { FK_MODIFIES, "modification", "modification errors" } ,
00082 { FK_NAMES, "names", "naming conventions and limits" } ,
00083 { FK_NULL, "null", "misuses of null pointers" } ,
00084 { FK_NUMBERS, "numbers", "control type-checking of numeric types" } ,
00085 { FK_OPS, "operations", "checking of primitive operations" } ,
00086 { FK_PARAMS, "parameters", "function and macro parameters" } ,
00087 { FK_SPEED, "performance", "speeding up checking" } ,
00088 { FK_POINTER, "pointers", "pointers" } ,
00089 { FK_PRED, "predicates", "condition test expressions" } ,
00090 { FK_PREFIX, "prefixes", "set naming prefixes and control checking" } ,
00091 { FK_PREPROC, "preproc", "defines and undefines for the preprocessor" } ,
00092 { FK_PROTOS, "prototypes", "function prototypes" } ,
00093 { FK_DEAD, "released", "using storage that has been deallocated" } ,
00094 { FK_IGNORERET, "returnvals", "ignored return values" },
00095 { FK_SPEC, "specifications", "checks involving .lcl specifications" } ,
00096 { FK_SUPPRESS, "suppress", "local and global suppression of messages" } ,
00097 { FK_TYPEEQ, "typeequivalence", "control what types are equivalent" } ,
00098 { FK_BEHAVIOR, "undefined", "code with undefined or implementation-defined behavior" } ,
00099 { FK_UNRECOG, "unrecognized", "unrecognized identifiers" } ,
00100 { FK_UNSPEC, "unconstrained", "checking in the presence of unconstrained functions" } ,
00101 { FK_DEBUG, NULL, NULL } ,
00102 { FK_SYNTAX, NULL, NULL } ,
00103 { FK_TYPE, NULL, NULL } ,
00104 { FK_SECRET, NULL, NULL } ,
00105 { FK_OBSOLETE, NULL, NULL } ,
00106 { FK_NONE, NULL, NULL }
00107 } ;
00108
00109 typedef enum {
00110 ARG_NONE,
00111 ARG_VALUE,
00112 ARG_STRING,
00113 ARG_SPECIAL
00114 } argcode;
00115
00116 typedef struct {
00117 flagkind main;
00118 flagkind sub;
00119 bool isSpecial;
00120 bool isIdem;
00121 bool isGlobal;
00122 bool isModeFlag;
00123 argcode argtype;
00124 char *flag;
00125 flagcode code;
00126 char *desc;
00127 bn_mstring hint;
00128 int nreported;
00129 int nsuppressed;
00130 } fflag;
00131
00132 typedef fflag flaglist[];
00133
00134 # include "flags.def"
00135
00136
00137 # define allFlags(m_f) \
00138 { flagcode m_i; for (m_i = 0; m_i < NUMFLAGS; m_i++) { fflag m_f = flags[m_i];
00139 # define end_allFlags }}
00140
00141 static bn_mstring mode_names[] =
00142 {
00143 "weak", "standard", "checks", "strict", NULL,
00144 };
00145
00146
00147 # define allModes(m_m) \
00148 { int m_ii = 0; while (mstring_isDefined (mode_names[m_ii])) \
00149 { bn_mstring m_m = mode_names[m_ii]; m_ii++;
00150
00151 # define end_allModes }}
00152
00153
00154
00155 static cstring describeFlagCode (flagcode p_flag) ;
00156 static cstringSList sortedFlags (void) ;
00157 static cstring categoryName (flagkind p_kind) ;
00158 static cstring listModes (void) ;
00159
00160 bool flagcode_isSpecialFlag (flagcode f)
00161 {
00162 return (flags[f].isSpecial);
00163 }
00164
00165 bool flagcode_isGlobalFlag (flagcode f)
00166 {
00167 return (flags[f].isGlobal);
00168 }
00169
00170 bool flagcode_isIdemFlag (flagcode f)
00171 {
00172 return (flags[f].isIdem);
00173 }
00174
00175 bool flagcode_isModeFlag (flagcode f)
00176 {
00177 return (flags[f].isModeFlag);
00178 }
00179
00180 bool flagcode_isNameChecksFlag (flagcode f)
00181 {
00182 return (flags[f].main == FK_NAMES);
00183 }
00184
00185
00186
00187
00188
00189 void flags_initMod ()
00190 {
00191 allFlagCodes (code)
00192 {
00193
00194 if (flags[code].code != code)
00195 {
00196 llbug (message ("*** ERROR: inconsistent flag %s / %d / %d",
00197 cstring_fromChars (flags[code].flag),
00198 flags[code].code, code));
00199 }
00200
00201 } end_allFlagCodes;
00202 }
00203
00204 void
00205 summarizeErrors ()
00206 {
00207 bool hadOne = FALSE;
00208 int sumrep = 0;
00209 int sumsup = 0;
00210
00211 char *buf = mstring_create (128);
00212
00213 allFlags (f)
00214 {
00215 if (f.nreported > 0 || f.nsuppressed > 0)
00216 {
00217 int nrep = f.nreported;
00218 int nsup = f.nsuppressed;
00219 cstring fs = cstring_fill (cstring_fromChars (f.flag), 23);
00220
00221 if (!hadOne)
00222 {
00223 llmsgplain (cstring_makeLiteral
00224 ("\nError Type Reported Suppressed\n"
00225 "=================== ======== ========="));
00226 hadOne = TRUE;
00227 }
00228
00229 sprintf (buf, "%s%7d %9d", cstring_toCharsSafe (fs), nrep, nsup);
00230
00231 sumrep += nrep;
00232 sumsup += nsup;
00233
00234 cstring_free (fs);
00235 llmsg (cstring_copy (cstring_fromChars (buf)));
00236 }
00237 } end_allFlags;
00238
00239 if (hadOne)
00240 {
00241 cstring ts = cstring_fill (cstring_makeLiteralTemp ("Total"), 23);
00242
00243 llmsglit (" ======== =========");
00244
00245 sprintf (buf, "%s%7d %9d", cstring_toCharsSafe (ts), sumrep, sumsup);
00246 cstring_free (ts);
00247 llmsgplain (cstring_copy (cstring_fromChars (buf)));
00248 }
00249
00250 sfree (buf);
00251 }
00252
00253
00254
00255 void
00256 flagcode_recordError (flagcode f)
00257 {
00258 if (f != INVALID_FLAG)
00259 {
00260 if (f == FLG_WARNFLAGS)
00261 {
00262 ;
00263 }
00264 else
00265 {
00266 flags[f].nreported = flags[f].nreported + 1;
00267 }
00268 }
00269 else
00270 {
00271 llcontbug (message ("flagcode_recordError: invalid flag: %d", (int) f));
00272 }
00273 }
00274
00275 void
00276 flagcode_recordSuppressed (flagcode f)
00277 {
00278 llassertprint (f != INVALID_FLAG, ("flagcode: %s", flagcode_unparse (f)));
00279
00280 flags[f].nsuppressed = flags[f].nsuppressed + 1;
00281 }
00282
00283 int
00284 flagcode_numReported (flagcode f)
00285 {
00286 llassert (f != INVALID_FLAG);
00287
00288 return (flags[f].nreported);
00289 }
00290
00291 cstring
00292 flagcodeHint (flagcode f)
00293 {
00294 llassert (f != INVALID_FLAG);
00295
00296 if (mstring_isDefined (flags[f].hint))
00297 {
00298 return (cstring_fromChars (flags[f].hint));
00299 }
00300 else
00301 {
00302 return (cstring_fromChars (flags[f].desc));
00303 }
00304 }
00305
00306 static int categorySize (flagkind kind)
00307 {
00308 int n = 0;
00309
00310
00311 allFlags (f)
00312 {
00313 if (f.main == kind || f.sub == kind)
00314 {
00315 n++;
00316 }
00317 } end_allFlags;
00318
00319 return n;
00320 }
00321
00322 flagkind identifyCategory (cstring s)
00323 {
00324 int i;
00325
00326 for (i = 0; categories[i].kind != FK_NONE; i++)
00327 {
00328 if (mstring_isDefined (categories[i].name))
00329 {
00330 if (cstring_equalLit (s, categories[i].name))
00331 {
00332 return categories[i].kind;
00333 }
00334 }
00335 }
00336
00337 return FK_NONE;
00338 }
00339
00340 static cstring categoryName (flagkind kind)
00341 {
00342 int i;
00343
00344 for (i = 0; categories[i].kind != FK_NONE; i++)
00345 {
00346 if (categories[i].kind == kind)
00347 {
00348 return (cstring_fromChars (categories[i].name));
00349 }
00350 }
00351
00352 return (cstring_makeLiteralTemp ("<No Category>"));
00353 }
00354
00355 static int categoryIndex (flagkind kind)
00356 {
00357 int i;
00358
00359 for (i = 0; categories[i].kind != FK_NONE; i++)
00360 {
00361 if (categories[i].kind == kind)
00362 {
00363 return i;
00364 }
00365 }
00366
00367 return -1;
00368 }
00369
00370 void printCategory (flagkind kind)
00371 {
00372 int index = categoryIndex (kind);
00373
00374 llassert (index >= 0);
00375
00376 llmsg (message ("%s (%d flags)\n\3%s\n\n",
00377 cstring_fromChars (categories[index].name),
00378 categorySize (kind),
00379 cstring_fromChars (categories[index].describe)));
00380
00381 allFlags (f)
00382 {
00383 if (f.main == kind || f.sub == kind)
00384 {
00385 llmsg (message (" %s\n\6%q", cstring_fromChars (f.flag),
00386 describeFlagCode (f.code)));
00387 }
00388 } end_allFlags;
00389 }
00390
00391 void
00392 listAllCategories (void)
00393 {
00394 int i;
00395
00396 for (i = 0; categories[i].kind != FK_NONE; i++)
00397 {
00398 flagkind kind = categories[i].kind ;
00399
00400 if (categories[i].describe != NULL)
00401 {
00402 llmsg (message ("%s (%d flags)\n\3%s",
00403 categoryName (kind),
00404 categorySize (kind),
00405 cstring_fromChars (categories[i].describe)));
00406 }
00407 }
00408 }
00409
00410 void
00411 printAllFlags (bool desc, bool full)
00412 {
00413 if (full)
00414 {
00415 cstringSList fl = sortedFlags ();
00416
00417 cstringSList_elements (fl, el)
00418 {
00419 llmsg (message ("%q\n\n", describeFlag (el)));
00420 } end_cstringSList_elements ;
00421
00422 cstringSList_free (fl);
00423 }
00424 else
00425 {
00426 allFlags (f)
00427 {
00428 if (f.code != INVALID_FLAG && f.main != FK_OBSOLETE)
00429 {
00430 if (mstring_isDefined (f.desc))
00431 {
00432 if (desc)
00433 {
00434 llmsg (message ("%s --- %s", cstring_fromChars (f.flag),
00435 cstring_fromChars (f.desc)));
00436 }
00437 }
00438 }
00439 } end_allFlags;
00440 }
00441 }
00442
00443 cstring
00444 describeFlagCode (flagcode flag)
00445 {
00446 cstring ret = cstring_undefined;
00447 fflag f;
00448
00449 if (flagcode_isInvalid (flag))
00450 {
00451 return (cstring_makeLiteral ("<invalid>"));
00452 }
00453
00454 context_resetAllFlags ();
00455
00456 f = flags[flag];
00457 ret = cstring_copy (cstring_fromChars (f.desc));
00458
00459
00460 if (f.sub != FK_NONE)
00461 {
00462 ret = message ("%q\nCategories: %s, %s",
00463 ret,
00464 categoryName (f.main),
00465 categoryName (f.sub));
00466 }
00467 else
00468 {
00469 if (f.main != FK_NONE)
00470 {
00471 cstring cname = categoryName (f.main);
00472
00473 if (cstring_isDefined (cname))
00474 {
00475 ret = message ("%q\nCategory: %s",
00476 ret, cname);
00477 }
00478 }
00479 }
00480
00481 if (f.isModeFlag)
00482 {
00483 bool first = TRUE;
00484
00485 allModes (mname)
00486 {
00487 context_setMode (cstring_fromChars (mname));
00488
00489 if (first)
00490 {
00491 ret = message ("%q\nMode Settings: %s %s",
00492 ret, cstring_fromChars (mname),
00493 cstring_makeLiteralTemp
00494 (context_getFlag (flag) ? "+" : "-"));
00495 first = FALSE;
00496 }
00497 else
00498 {
00499 ret = message ("%q, %s %s",
00500 ret, cstring_fromChars (mname),
00501 cstring_makeLiteralTemp
00502 (context_getFlag (flag) ? "+" : "-"));
00503 }
00504 } end_allModes;
00505 }
00506 else
00507 {
00508 ret = message ("%q\nDefault Setting: %s",
00509 ret,
00510 cstring_makeLiteralTemp
00511 (context_getFlag (flag) ? "+" : "-"));
00512 }
00513
00514 if (f.isGlobal)
00515 {
00516 ret = message("%q\nSet globally only", ret);
00517 }
00518 else
00519 {
00520 ret = message("%q\nSet locally", ret);
00521 }
00522
00523 switch (f.argtype)
00524 {
00525 case ARG_NONE:
00526 case ARG_SPECIAL:
00527 break;
00528 case ARG_VALUE:
00529 if (flag == FLG_COMMENTCHAR)
00530 {
00531 ret = message("%q\nCharacter Argument. Default: %h",
00532 ret, (char) context_getValue (flag));
00533 }
00534 else
00535 {
00536 ret = message("%q\nNumeric Argument. Default: %d",
00537 ret,
00538 context_getValue (flag));
00539 }
00540 break;
00541 case ARG_STRING:
00542 if (cstring_isDefined (context_getString (flag)))
00543 {
00544 ret = message("%q\nString Argument. Default: %s",
00545 ret,
00546 context_getString (flag));
00547 }
00548 else
00549 {
00550 ret = message("%q\nString Argument. No default.", ret);
00551 }
00552 break;
00553 }
00554
00555 if (mstring_isDefined (f.hint))
00556 {
00557 ret = message("%q\n\3%s", ret, cstring_fromChars (f.hint));
00558 }
00559
00560 return ret;
00561 }
00562
00563 cstring
00564 describeFlag (cstring flagname)
00565 {
00566 cstring oflagname = cstring_copy (flagname);
00567 flagcode f = identifyFlag (flagname);
00568
00569 if (flagcode_isSkip (f))
00570 {
00571 cstring_free (oflagname);
00572 return cstring_undefined;
00573 }
00574 else if (flagcode_isValid (f))
00575 {
00576 if (cstring_equal (flagname, oflagname))
00577 {
00578 cstring_free (oflagname);
00579 return (message ("%s\n\3%q", flagname, describeFlagCode (f)));
00580 }
00581 else
00582 {
00583 return (message ("%q (standardized name: %s)\n\3%q",
00584 oflagname, flagname, describeFlagCode (f)));
00585 }
00586 }
00587 else
00588 {
00589 if (isMode (flagname))
00590 {
00591 cstring_free (oflagname);
00592
00593 return
00594 (message ("%s: predefined mode (see User's Guide for information)",
00595 flagname));
00596 }
00597 else
00598 {
00599 return (message ("%q: <invalid flag>", oflagname));
00600 }
00601 }
00602 }
00603
00604 static cstringSList
00605 sortedFlags (void)
00606 {
00607 cstringSList s = cstringSList_new ();
00608
00609 allFlags (f)
00610 {
00611 if (f.desc != NULL)
00612 {
00613 s = cstringSList_add (s, cstring_fromChars (f.flag));
00614 }
00615 } end_allFlags;
00616
00617 cstringSList_alphabetize (s);
00618
00619 return s;
00620 }
00621
00622 void printAlphaFlags ()
00623 {
00624 cstringSList fl = sortedFlags ();
00625
00626 cstringSList_printSpaced (fl, 3, 1, context_getLineLen () - 25);
00627 cstringSList_free (fl);
00628 }
00629 cstring
00630 flagcode_name (flagcode code)
00631 {
00632 return cstring_fromChars (flags[code].flag);
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662 static void
00663 canonicalizeFlag (cstring s)
00664 {
00665 int i = 0;
00666 static bn_mstring transform[] =
00667 {
00668 "function", "fcn",
00669 "variable", "var",
00670 "constant", "const",
00671 "iterator", "iter",
00672 "parameter", "param",
00673 "unrecognized", "unrecog",
00674 "qualifier", "qual",
00675 "declaration", "decl",
00676 "globals", "globs",
00677 "modifies", "mods",
00678 "modify", "mod",
00679 "pointer", "ptr",
00680 "implies", "imp",
00681 "implicit", "imp",
00682 "implied", "imp",
00683 "unconstrained", "uncon",
00684 "unconst", "uncon",
00685 "memory", "mem",
00686 "length", "len",
00687 "return", "ret",
00688 "system", "sys",
00689 NULL
00690 } ;
00691 char *current;
00692
00693 while ((current = transform[i]) != NULL)
00694 {
00695 if (cstring_containsLit (s, current))
00696 {
00697 cstring_replaceLit (s, current, transform[i+1]);
00698 }
00699 i += 2;
00700 }
00701
00702
00703 cstring_stripChars (s, " -_");
00704 }
00705
00706 flagcode
00707 identifyFlag (cstring s)
00708 {
00709 if (cstring_length (s) == 0) {
00710
00711 return INVALID_FLAG;
00712 }
00713
00714 if (cstring_firstChar (s) == 'I')
00715 {
00716 return FLG_INCLUDEPATH;
00717 }
00718
00719 if (cstring_firstChar (s) == 'S')
00720 {
00721 return FLG_SPECPATH;
00722 }
00723
00724 if (cstring_firstChar (s) == 'D')
00725 {
00726 return FLG_DEFINE;
00727 }
00728
00729 if (cstring_firstChar (s) == 'U')
00730 {
00731 return FLG_UNDEFINE;
00732 }
00733
00734 canonicalizeFlag (s);
00735
00736 allFlags (f)
00737 {
00738 if (cstring_equal (cstring_fromChars (f.flag), s))
00739 {
00740 return (f.code);
00741 }
00742 } end_allFlags;
00743
00744
00745
00746
00747
00748 if (cstring_equalLit (s, "pred"))
00749 {
00750 return FLG_PREDBOOL;
00751 }
00752
00753 if (cstring_equalLit (s, "modobserverstrict"))
00754 {
00755 return FLG_MODOBSERVERUNCON;
00756 }
00757
00758 if (cstring_equalLit (s, "czechnames"))
00759 {
00760 return FLG_CZECH;
00761 }
00762
00763 if (cstring_equalLit (s, "slovaknames"))
00764 {
00765 return FLG_SLOVAK;
00766 }
00767
00768 if (cstring_equalLit (s, "czechoslovaknames"))
00769 {
00770 return FLG_CZECHOSLOVAK;
00771 }
00772
00773 if (cstring_equalLit (s, "globunspec")
00774 || cstring_equalLit (s, "globuncon"))
00775 {
00776 return FLG_GLOBUNSPEC;
00777 }
00778
00779 if (cstring_equalLit (s, "modglobsunspec")
00780 || cstring_equalLit (s, "modglobsuncon")
00781 || cstring_equalLit (s, "modglobsnomods"))
00782 {
00783 return FLG_MODGLOBSUNSPEC;
00784 }
00785
00786 if (cstring_equalLit (s, "export"))
00787 {
00788 return FLG_EXPORTANY;
00789 }
00790
00791 if (cstring_equalLit (s, "macrospec"))
00792 {
00793 return FLG_MACRODECL;
00794 }
00795
00796 if (cstring_equalLit (s, "ansireservedlocal"))
00797 {
00798 return FLG_ANSIRESERVEDLOCAL;
00799 }
00800
00801 if (cstring_equalLit (s, "warnposix"))
00802 {
00803 return FLG_WARNPOSIX;
00804 }
00805
00806 if (cstring_equalLit (s, "defuse"))
00807 {
00808 return FLG_USEDEF;
00809 }
00810
00811 if (cstring_equalLit (s, "macroundef"))
00812 {
00813 return FLG_MACROUNDEF;
00814 }
00815
00816 if (cstring_equalLit (s, "showcol"))
00817 {
00818 return FLG_SHOWCOL;
00819 }
00820
00821 if (cstring_equalLit (s, "intbool"))
00822 {
00823 return FLG_BOOLINT;
00824 }
00825
00826 if (cstring_equalLit (s, "intchar"))
00827 {
00828 return FLG_CHARINT;
00829 }
00830
00831 if (cstring_equalLit (s, "intenum"))
00832 {
00833 return FLG_ENUMINT;
00834 }
00835
00836
00837
00838
00839
00840 if (cstring_equalLit (s, "isolib"))
00841 {
00842 return FLG_ANSILIB;
00843 }
00844
00845 if (cstring_equalLit (s, "isostrictlib"))
00846 {
00847 return FLG_STRICTLIB;
00848 }
00849
00850 if (cstring_equalLit (s, "ansistrictlib"))
00851 {
00852 return FLG_STRICTLIB;
00853 }
00854
00855 if (cstring_equalLit (s, "skipisoheaders"))
00856 {
00857 return FLG_SKIPANSIHEADERS;
00858 }
00859
00860 if (cstring_equalLit (s, "isoreserved"))
00861 {
00862 return FLG_ANSIRESERVED;
00863 }
00864
00865 if (cstring_equalLit (s, "isoreservedinternal"))
00866 {
00867 return FLG_ANSIRESERVEDLOCAL;
00868 }
00869
00870 if (cstring_equalLit (s, "isolimits"))
00871 {
00872 return FLG_ANSILIMITS;
00873 }
00874
00875
00876
00877
00878
00879 if (cstring_equalLit (s, "accessunspec"))
00880 {
00881 flagWarning
00882 (cstring_makeLiteralTemp
00883 ("accessunspec flag is not supported by LCLint version 2.0 or "
00884 "later. It has been replaced by accessmodule, accessfile and "
00885 "accessfunction to provide more precise control of accessibility "
00886 "of representations. For more information, "
00887 "see lclint -help accessmodule"));
00888
00889 return SKIP_FLAG;
00890 }
00891
00892 if (cstring_equalLit (s, "staticmods"))
00893 {
00894 flagWarning
00895 (cstring_makeLiteralTemp
00896 ("staticmods flag is obsolete. You probably "
00897 "want impcheckmodstatics. For more information, "
00898 "see lclint -help impcheckmodstatics"));
00899
00900 return SKIP_FLAG;
00901 }
00902
00903 if (cstring_equalLit (s, "bool"))
00904 {
00905 flagWarning
00906 (cstring_makeLiteralTemp ("bool flag is obsolete. It never really "
00907 "made sense in the first place."));
00908
00909 return SKIP_FLAG;
00910 }
00911
00912 if (cstring_equalLit (s, "ansi"))
00913 {
00914 flagWarning
00915 (cstring_makeLiteralTemp ("ansi flag is obsolete. You probably "
00916 "want noparams and/or oldstyle."));
00917
00918 return SKIP_FLAG;
00919 }
00920
00921 if (cstring_equalLit (s, "stdio"))
00922 {
00923 flagWarning
00924 (cstring_makeLiteralTemp
00925 ("stdio flag is obsolete. You may "
00926 "want strictlib or one of the gloabls "
00927 "checking flags. For more information, "
00928 "see lclint -help strictlib or lclint -help flags globals"));
00929
00930 return SKIP_FLAG;
00931 }
00932
00933 return INVALID_FLAG;
00934 }
00935
00936 void setValueFlag (flagcode opt, cstring arg)
00937 {
00938 switch (opt)
00939 {
00940 case FLG_EXPECT:
00941 case FLG_LCLEXPECT:
00942 case FLG_LIMIT:
00943 case FLG_LINELEN:
00944 case FLG_EXTERNALNAMELEN:
00945 case FLG_INTERNALNAMELEN:
00946 case FLG_CONTROLNESTDEPTH:
00947 case FLG_STRINGLITERALLEN:
00948 case FLG_NUMSTRUCTFIELDS:
00949 case FLG_NUMENUMMEMBERS:
00950 case FLG_INCLUDENEST:
00951 {
00952 int val = cstring_toPosInt (arg);
00953
00954 if (val < 0)
00955 {
00956 llerror
00957 (FLG_BADFLAG,
00958 message
00959 ("Flag %s must be followed by a positive number number. "
00960 "Followed by %s",
00961 flagcode_unparse (opt), arg));
00962 }
00963 else
00964 {
00965 context_setValueAndFlag (opt, val);
00966 }
00967 }
00968 break;
00969 case FLG_COMMENTCHAR:
00970 {
00971 if (cstring_length (arg) != 1)
00972 {
00973 llfatalerrorLoc
00974 (message
00975 ("Flag %s should be followed by a single character. Followed by %s",
00976 flagcode_unparse (opt), arg));
00977 }
00978 else
00979 {
00980 context_setCommentMarkerChar (cstring_firstChar (arg));
00981 }
00982 }
00983 break;
00984 BADDEFAULT;
00985 }
00986 }
00987
00988 void setStringFlag (flagcode opt, cstring arg)
00989 {
00990 switch (opt)
00991 {
00992 case FLG_TMPDIR:
00993 {
00994 if (cstring_lastChar (arg) == CONNECTCHAR)
00995 {
00996 context_setString (opt, arg);
00997 }
00998 else
00999 {
01000 context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
01001 }
01002 break;
01003 }
01004 default:
01005 {
01006 context_setString (opt, arg);
01007 break;
01008 }
01009 }
01010 }
01011
01012 cstring
01013 describeModes ()
01014 {
01015 cstring s = cstring_makeLiteral ("Flag ");
01016 cstringSList sflags = sortedFlags ();
01017
01018 allModes (modename)
01019 {
01020 s = message ("%q%9s", s, cstring_fromChars (modename));
01021 } end_allModes;
01022
01023 s = message ("%q\n", s);
01024
01025 cstringSList_elements (sflags, flagname)
01026 {
01027 flagcode code = identifyFlag (flagname);
01028 fflag currentflag = flags[code];
01029
01030 if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
01031 {
01032 s = message ("%q\n%27s", s,
01033 cstring_fromChars (currentflag.flag));
01034
01035 allModes (modename)
01036 {
01037 context_setMode (cstring_fromChars (modename));
01038
01039 if (context_getFlag (code))
01040 {
01041 s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
01042 }
01043 else
01044 {
01045 s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
01046 }
01047
01048 context_resetModeFlags ();
01049 } end_allModes;
01050 }
01051 } end_cstringSList_elements;
01052
01053 cstringSList_free (sflags);
01054
01055 s = cstring_appendChar (s, '\n');
01056
01057 return (s);
01058 }
01059
01060 static cstring
01061 listModes (void)
01062 {
01063 cstring s = cstring_makeLiteral ("\t");
01064 int i = 0;
01065
01066 allModes (modename)
01067 {
01068 if (i != 0 && (i % 4 == 0))
01069 {
01070 s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
01071 }
01072 else
01073 {
01074 s = message ("%q%15s", s, cstring_fromChars (modename));
01075 }
01076 i++;
01077 } end_allModes;
01078
01079 return s;
01080 }
01081
01082 bool
01083 isMode (cstring s)
01084 {
01085 allModes (modename)
01086 {
01087 if (mstring_isDefined (modename))
01088 {
01089 if (cstring_equalLit (s, modename))
01090 {
01091 return TRUE;
01092 }
01093 }
01094 } end_allModes;
01095
01096 return FALSE;
01097 }
01098
01099 extern bool flagcode_hasArgument (flagcode f)
01100 {
01101 return (flags[f].argtype != ARG_NONE);
01102 }
01103
01104 extern bool flagcode_hasValue (flagcode f)
01105 {
01106 return (flags[f].argtype == ARG_VALUE);
01107 }
01108
01109 extern bool flagcode_hasString (flagcode f)
01110 {
01111 return (flags[f].argtype == ARG_STRING);
01112 }
01113
01114 extern int flagcode_valueIndex (flagcode f)
01115 {
01116 static bool initialized = FALSE;
01117 int i;
01118 static flagcode valueFlags[NUMVALUEFLAGS];
01119
01120
01121 if (!initialized)
01122 {
01123 int nv = 0;
01124
01125 allFlagCodes (code)
01126 {
01127 if (flagcode_hasValue (code))
01128 {
01129 llassert (nv < NUMVALUEFLAGS);
01130 valueFlags[nv] = code;
01131 nv++;
01132 }
01133 } end_allFlagCodes;
01134
01135 llassertprint (nv == NUMVALUEFLAGS,
01136 ("number of value flags: %d (expected %d)",
01137 nv, NUMVALUEFLAGS));
01138 initialized = TRUE;
01139 }
01140
01141 for (i = 0; i < NUMVALUEFLAGS; i++)
01142 {
01143
01144 if (f == valueFlags[i])
01145 {
01146 return i;
01147 }
01148 }
01149
01150 BADEXIT;
01151 }
01152
01153 extern int flagcode_stringIndex (flagcode f)
01154 {
01155 static bool initialized = FALSE;
01156 static flagcode stringFlags[NUMSTRINGFLAGS];
01157 int i;
01158
01159
01160 if (!initialized)
01161 {
01162 int nv = 0;
01163
01164 allFlagCodes (code)
01165 {
01166 if (flagcode_hasString (code))
01167 {
01168 llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
01169 stringFlags[nv] = code;
01170 nv++;
01171 }
01172 } end_allFlagCodes;
01173
01174 llassertprint (nv == NUMSTRINGFLAGS,
01175 ("number of string flags: %d (expected %d)",
01176 nv, NUMSTRINGFLAGS));
01177 initialized = TRUE;
01178 }
01179
01180 for (i = 0; i < NUMSTRINGFLAGS; i++)
01181 {
01182 if (f == stringFlags[i])
01183 {
01184 return i;
01185 }
01186 }
01187
01188 llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
01189 BADEXIT;
01190 }
01191
01192 bool flagcode_isNamePrefixFlag (flagcode f)
01193 {
01194 switch (f)
01195 {
01196 case FLG_MACROVARPREFIX:
01197 case FLG_TAGPREFIX:
01198 case FLG_ENUMPREFIX:
01199 case FLG_FILESTATICPREFIX:
01200 case FLG_GLOBPREFIX:
01201 case FLG_TYPEPREFIX:
01202 case FLG_EXTERNALPREFIX:
01203 case FLG_LOCALPREFIX:
01204 case FLG_UNCHECKEDMACROPREFIX:
01205 case FLG_CONSTPREFIX:
01206 case FLG_ITERPREFIX:
01207 case FLG_DECLPARAMPREFIX:
01208 return TRUE;
01209 default:
01210 return FALSE;
01211 }
01212 }
01213