Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

flags.c

Go to the documentation of this file.
00001 /*
00002 ** LCLint - annotation-assisted static program checker
00003 ** Copyright (C) 1994-2000 University of Virginia,
00004 **         Massachusetts Institute of Technology
00005 **
00006 ** This program is free software; you can redistribute it and/or modify it
00007 ** under the terms of the GNU General Public License as published by the
00008 ** Free Software Foundation; either version 2 of the License, or (at your
00009 ** option) any later version.
00010 ** 
00011 ** This program is distributed in the hope that it will be useful, but
00012 ** WITHOUT ANY WARRANTY; without even the implied warranty of
00013 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 ** General Public License for more details.
00015 ** 
00016 ** The GNU General Public License is available from http://www.gnu.org/ or
00017 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00018 ** MA 02111-1307, USA.
00019 **
00020 ** For information on lclint: lclint-request@cs.virginia.edu
00021 ** To report a bug: lclint-bug@cs.virginia.edu
00022 ** For more information: http://lclint.cs.virginia.edu
00023 */
00024 /*
00025 ** flags.c
00026 */
00027 
00028 # include "lclintMacros.nf"
00029 # include "basic.h"
00030 # include "portab.h"
00031 
00032 /*
00033 ** from the CC man page:
00034 **
00035 **  -Idir          Search for #include files whose names do not begin with a
00036 **                    slash (/) in the following order: (1) in the directory of
00037 **                    the dir argument, (2) in the directories specified by -I
00038 **                    options, (3) in the standard directory (/usr/include).
00039 */
00040 
00041 /* needed for string literals literals */
00042 
00043 typedef struct { 
00044   flagkind kind;
00045   /*@null@*/ /*@observer@*/ char *name;
00046   /*@null@*/ /*@observer@*/ 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 }  /* must be last */
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;  /* setting this flag may set other flags (or values) */
00120   bool isIdem;     /* idempotent - always sets to TRUE */
00121   bool isGlobal;   /* cannot be set locally (using control comments) */
00122   bool isModeFlag; /* set by modes */
00123   argcode argtype;
00124   /*@observer@*/ char *flag;
00125   flagcode code; 
00126   /*@observer@*/ /*@null@*/ 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 /*@iter allFlags (yield observer fflag f); @*/
00137 # define allFlags(m_f) \
00138   { /*@+enumint@*/ flagcode m_i; for (m_i = 0; m_i < NUMFLAGS; m_i++) { fflag m_f = flags[m_i]; /*@=enumint@*/
00139 # define end_allFlags }}
00140 
00141 static bn_mstring mode_names[] =
00142 { 
00143   "weak", "standard", "checks", "strict", NULL, 
00144 };
00145 
00146 /*@iter allModes (yield bn_mstring modename)@*/
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 /*@+enumint@*/
00154 
00155 static cstring describeFlagCode (flagcode p_flag) /*@*/ ;
00156 static cstringSList sortedFlags (void) /*@*/ ;
00157 static /*@observer@*/ cstring categoryName (flagkind p_kind) /*@*/ ;
00158 static /*@unused@*/ 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 ** Internal consistency check on the flags.
00187 */
00188 
00189 void flags_initMod ()
00190 {
00191   allFlagCodes (code)
00192     {
00193       /*@+enumint@*/
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       /*@=enumint@*/
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 /*@+enumindex@*/
00254 
00255 void
00256 flagcode_recordError (flagcode f)
00257 {
00258   if (f != INVALID_FLAG)
00259     {
00260       if (f == FLG_WARNFLAGS)
00261         {
00262           ; /* don't count these */
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 /*@observer@*/ 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 /*@observer@*/ 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 /*@observer@*/ cstring
00630 flagcode_name (flagcode code)
00631 {
00632   return cstring_fromChars (flags[code].flag);
00633 }
00634 
00635 /*
00636 ** Transforms a flag into its cannonical form.
00637 **
00638 ** The following transformations are made:
00639 **
00640 **    function      -> fcn
00641 **    variable      -> var
00642 **    constant      -> const
00643 **    iterator      -> iter
00644 **    parameter     -> param
00645 **    unrecognized  -> unrecog
00646 **    qualifier     -> qual         
00647 **    declaration   -> decl
00648 **    globalias     -> (no change)
00649 **    global        -> glob
00650 **    modifies      -> mods
00651 **    modify        -> mod
00652 **    pointer       -> ptr
00653 **    implies       -> imp
00654 **    implicit      -> imp
00655 **    implied       -> imp
00656 **    unconstrained -> unspec       
00657 **    unconst       -> unspec
00658 **    memory        -> mem
00659 **    length        -> len
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   /* remove whitespace, -'s, and _'s */
00703   cstring_stripChars (s, " -_");
00704 }
00705 
00706 flagcode
00707 identifyFlag (cstring s)
00708 {
00709   if (cstring_length (s) == 0) {
00710     /* evs 2000-06-25: A malformed flag. */
00711     return INVALID_FLAG;
00712   }
00713 
00714   if (cstring_firstChar (s) == 'I')
00715     {
00716       return FLG_INCLUDEPATH; /* no space after -I */
00717     }
00718 
00719   if (cstring_firstChar (s) == 'S') 
00720     {
00721       return FLG_SPECPATH;    /* no space after -S */
00722     }
00723 
00724   if (cstring_firstChar (s) == 'D') 
00725     {
00726       return FLG_DEFINE;      /* no space after -D */
00727     }
00728 
00729   if (cstring_firstChar (s) == 'U') 
00730     {
00731       return FLG_UNDEFINE;    /* no space after -D */
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   ** Synonyms
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   ** For our European friends...
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   ** Obsolete Flags
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, /*@only@*/ 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   /*@unchecked@*/ static bool initialized = FALSE;
01117   int i;
01118   /*@unchecked@*/ 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       /* static valueFlags must be defined */
01144       /*@-usedef@*/ if (f == valueFlags[i]) /*@=usedef@*/
01145         {
01146           return i;
01147         }
01148     }
01149 
01150   BADEXIT;
01151 }
01152 
01153 extern int flagcode_stringIndex (flagcode f)
01154 {
01155   /*@unchecked@*/ static bool initialized = FALSE;
01156   /*@unchecked@*/ 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       /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
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         

Generated at Fri Nov 3 18:57:41 2000 for LCLint by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000