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

nameChecks.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 ** nameChecks.c
00026 */
00027 
00028 # include "lclintMacros.nf"
00029 # include "basic.h"
00030 # include "nameChecks.h"
00031 
00032 static bool checkCzechName (uentry p_ue, flagcode p_czechflag, bool p_report)
00033   /*@modifies p_ue, g_msgstream@*/ ;
00034 
00035 static bool checkSlovakName (uentry p_ue, flagcode p_slovakflag, bool p_report)
00036   /*@modifies p_ue, g_msgstream@*/ ;
00037 
00038 static cstring czechPrefix (cstring name)
00039 {
00040   return (cstring_beforeChar (name, '_'));
00041 }
00042 
00043 static cstring slovakPrefix (cstring name)
00044 {
00045   int i = 0;
00046 
00047   cstring_chars (name, c)
00048     {
00049       if (isupper ((unsigned char) c))
00050         {
00051           return (cstring_prefix (name, i));
00052         }
00053       i++;
00054     } end_cstring_chars;
00055 
00056   return cstring_undefined;
00057 }
00058 
00059 static flagcode excludeCodes [] = 
00060  {
00061    FLG_MACROVARPREFIXEXCLUDE,
00062    FLG_TAGPREFIXEXCLUDE,
00063    FLG_ENUMPREFIXEXCLUDE,
00064    FLG_FILESTATICPREFIXEXCLUDE,
00065    FLG_GLOBPREFIXEXCLUDE,
00066    FLG_TYPEPREFIXEXCLUDE,
00067    FLG_EXTERNALPREFIXEXCLUDE,
00068    FLG_UNCHECKEDMACROPREFIXEXCLUDE,
00069    FLG_LOCALPREFIXEXCLUDE,
00070    INVALID_FLAG
00071    } ;
00072 
00073 /*@iter excludeFlagCodes (yield flagcode code);@*/
00074 # define excludeFlagCodes(m_c) \
00075   { int m_i = 0; while (flagcode_isValid (excludeCodes[m_i])) \
00076       { flagcode m_c = excludeCodes[m_i]; m_i++; 
00077 
00078 # define end_excludeFlagCodes }}
00079 
00080 static bool matchPrefixChar (int nc, int pc)
00081 {
00082   if (nc == pc)
00083     {
00084       return TRUE;
00085     }
00086   else
00087     {
00088       switch (pc)
00089         {
00090         case PFX_UPPERCASE: 
00091           return isupper (nc);
00092         case PFX_LOWERCASE:
00093           return islower (nc);
00094         case PFX_ANY:
00095           return TRUE;
00096         case PFX_DIGIT:
00097           return isdigit (nc);
00098         case PFX_NOTUPPER:
00099           return !isupper (nc);
00100         case PFX_NOTLOWER:
00101           return !islower (nc);
00102         case PFX_ANYLETTER:
00103           return isalpha (nc);
00104         case PFX_ANYLETTERDIGIT: 
00105           return (isdigit (nc) || isalpha (nc));
00106         default: return FALSE;
00107         }
00108     }
00109 
00110   BADEXIT;
00111 }
00112 
00113 static bool matchPrefix (cstring name, cstring prefix)
00114 {
00115   if (cstring_isUndefined (name)
00116       || cstring_isUndefined (prefix))
00117     {
00118       return TRUE;
00119     }
00120   else
00121     {
00122       int namelen = cstring_length (name);
00123       int last = (int) '\0';
00124       int n = 1;
00125 
00126       cstring_chars (prefix, pc)
00127         {
00128           int nc;
00129 
00130           if (pc == '*')
00131             {
00132               n++;
00133 
00134               
00135               while (n <= namelen)
00136                 {
00137                   nc = (int) cstring_getChar (name, n);
00138 
00139                   if (!matchPrefixChar (nc, last))
00140                     {
00141                       return FALSE;
00142                     }
00143                   n++;
00144                 }
00145 
00146               return TRUE;
00147             }
00148           else
00149             {
00150               if (n > namelen)
00151                 {
00152                   if ((cstring_length (prefix) >= n + 1)
00153                       && cstring_getChar (prefix, n + 1) == '*')
00154                     {
00155                       return TRUE;
00156                     }
00157                   else
00158                     {
00159                       return FALSE;
00160                     }
00161                 }
00162               
00163               nc = (int) cstring_getChar (name, n);
00164               
00165               if (!matchPrefixChar (nc, (int) pc))
00166                 {
00167                   return FALSE;
00168                 }
00169             }
00170         
00171           last = (int) pc;
00172           n++;
00173         } end_cstring_chars;
00174 
00175       return TRUE;
00176     }
00177 }
00178 
00179 static flagcode
00180 namespaceExcluded (flagcode code) /*@*/ 
00181 {
00182   switch (code)
00183     {
00184     case FLG_MACROVARPREFIXEXCLUDE:
00185       return (FLG_MACROVARPREFIX);
00186     case FLG_TAGPREFIXEXCLUDE:
00187       return (FLG_TAGPREFIX);
00188     case FLG_ENUMPREFIXEXCLUDE:
00189       return (FLG_ENUMPREFIX);
00190     case FLG_FILESTATICPREFIXEXCLUDE:
00191       return (FLG_FILESTATICPREFIX);
00192     case FLG_GLOBPREFIXEXCLUDE:
00193       return (FLG_GLOBPREFIX);
00194     case FLG_TYPEPREFIXEXCLUDE:
00195       return (FLG_TYPEPREFIX);
00196     case FLG_EXTERNALPREFIXEXCLUDE:
00197       return (FLG_EXTERNALPREFIX);
00198     case FLG_UNCHECKEDMACROPREFIXEXCLUDE:
00199       return (FLG_UNCHECKEDMACROPREFIX);
00200     case FLG_LOCALPREFIXEXCLUDE:
00201       return (FLG_LOCALPREFIX);
00202     case FLG_ITERPREFIXEXCLUDE:
00203       return (FLG_ITERPREFIX);
00204     case FLG_CONSTPREFIXEXCLUDE:
00205       return (FLG_CONSTPREFIX);
00206     BADDEFAULT;
00207     }
00208 }
00209 
00210 static /*@observer@*/ cstring
00211 namespaceName (flagcode flag) /*@*/
00212 {
00213   switch (flag)
00214     {
00215     case FLG_MACROVARPREFIX: 
00216       return cstring_makeLiteralTemp ("macro variable");
00217     case FLG_TAGPREFIX:  
00218       return cstring_makeLiteralTemp ("tag");
00219     case FLG_ENUMPREFIX:  
00220       return cstring_makeLiteralTemp ("enum member");
00221     case FLG_TYPEPREFIX:     
00222       return cstring_makeLiteralTemp ("user-defined type");
00223     case FLG_FILESTATICPREFIX:
00224       return cstring_makeLiteralTemp ("file static");
00225     case FLG_GLOBPREFIX: 
00226       return cstring_makeLiteralTemp ("global variable");
00227     case FLG_EXTERNALPREFIX: 
00228       return cstring_makeLiteralTemp ("external");
00229     case FLG_LOCALPREFIX: 
00230       return cstring_makeLiteralTemp ("local variable");
00231     case FLG_CONSTPREFIX: 
00232       return cstring_makeLiteralTemp ("constant");
00233     case FLG_ITERPREFIX: 
00234       return cstring_makeLiteralTemp ("iter");
00235     case FLG_UNCHECKEDMACROPREFIX: 
00236       return cstring_makeLiteralTemp ("unchecked macro");
00237     BADDEFAULT;
00238     }
00239 }
00240 
00241 void 
00242 checkPrefix (uentry ue)
00243 {
00244   cstring name = cstring_undefined;
00245   flagcode flag;
00246 
00247   if (uentry_isExpandedMacro (ue))
00248     {
00249       flag = FLG_UNCHECKEDMACROPREFIX;
00250     }
00251   else if (uentry_isAnyTag (ue))
00252     {
00253       flag = FLG_TAGPREFIX;
00254     }
00255   else if (uentry_isEnumConstant (ue))
00256     {
00257       flag = FLG_ENUMPREFIX;
00258     }
00259   else if (uentry_isDatatype (ue))
00260     {
00261       flag = FLG_TYPEPREFIX;
00262     }
00263   else if (uentry_isFileStatic (ue))
00264     {
00265       flag = FLG_FILESTATICPREFIX;
00266     }
00267   else if (uentry_isGlobal (ue))
00268     {
00269       flag = FLG_GLOBPREFIX;
00270     }
00271   else if (uentry_isVariable (ue))
00272     {
00273       if (uentry_isRefParam (ue))
00274         {
00275           return; /* already checked param */
00276         }
00277 
00278       if (context_inMacro ())
00279         {
00280           if (uentry_isAnyParam (ue))
00281             {
00282               if (uentry_isYield (ue))
00283                 {
00284                   flag = FLG_MACROVARPREFIX;
00285                 }
00286               else
00287                 {
00288                   flag = FLG_LOCALPREFIX;
00289                 }
00290             }
00291           else
00292             {
00293               flag = FLG_MACROVARPREFIX;
00294             }
00295         }
00296       else
00297         {
00298           flag = FLG_LOCALPREFIX;
00299         }
00300     }
00301   else if (uentry_isConstant (ue))
00302     {
00303       flag = FLG_CONSTPREFIX;
00304     }
00305   else if (uentry_isIter (ue))
00306     {
00307       flag = FLG_ITERPREFIX;
00308     }
00309   else if (uentry_isExported (ue))
00310     {
00311       flag = FLG_EXTERNALPREFIX;
00312     }
00313   else
00314     {
00315       llcontbug (message ("What is it: %q", uentry_unparseFull (ue)));
00316       return;
00317     }
00318 
00319   if (flag == FLG_TYPEPREFIX || flag == FLG_GLOBPREFIX
00320       || flag == FLG_ENUMPREFIX || flag == FLG_CONSTPREFIX)
00321     {
00322       if (flag == FLG_ENUMPREFIX)
00323         {
00324           if (!context_getFlag (flag))
00325             {
00326               flag = FLG_CONSTPREFIX;
00327             }
00328         }
00329 
00330       if (!context_getFlag (flag))
00331         {
00332           flag = FLG_EXTERNALPREFIX;
00333         }
00334     }
00335 
00336   if (context_getFlag (flag))
00337     {
00338       name = uentry_getName (ue);
00339       
00340       
00341       if (!matchPrefix (name, context_getString (flag)))
00342         {
00343           if (optgenerror
00344               (flag,
00345                message ("%s %s name is not consistent with %s "
00346                         "namespace prefix \"%s\"",
00347                         uentry_ekindName (ue),
00348                         name,
00349                         namespaceName (flag),
00350                         context_getString (flag)),
00351                uentry_whereLast (ue)))
00352             {
00353               uentry_setHasNameError (ue);
00354             }
00355         }
00356     }  
00357 
00358   excludeFlagCodes (code)
00359     {
00360       bool check = FALSE;
00361 
00362       if (context_getFlag (code))
00363         {
00364           /*@-loopswitchbreak@*/
00365           switch (code)
00366             {
00367             case FLG_MACROVARPREFIXEXCLUDE:
00368               check = (flag != FLG_MACROVARPREFIX);
00369               break;
00370             case FLG_TAGPREFIXEXCLUDE:
00371               check = (flag != FLG_TAGPREFIX);
00372               break;
00373             case FLG_ENUMPREFIXEXCLUDE:
00374               check = (flag != FLG_ENUMPREFIX);
00375               break;
00376             case FLG_FILESTATICPREFIXEXCLUDE:
00377               check = (flag != FLG_FILESTATICPREFIX);
00378               break;
00379             case FLG_GLOBPREFIXEXCLUDE:
00380               check = (flag != FLG_GLOBPREFIX);
00381               break;
00382             case FLG_TYPEPREFIXEXCLUDE:
00383               check = (flag != FLG_TYPEPREFIX);
00384               break;
00385             case FLG_EXTERNALPREFIXEXCLUDE:
00386               check = (flag != FLG_EXTERNALPREFIX
00387                        && flag != FLG_GLOBPREFIX
00388                        && flag != FLG_TYPEPREFIX
00389                        && flag != FLG_UNCHECKEDMACROPREFIX);
00390               break;
00391             case FLG_UNCHECKEDMACROPREFIXEXCLUDE:
00392               check = (flag != FLG_UNCHECKEDMACROPREFIX);
00393               break;
00394             case FLG_LOCALPREFIXEXCLUDE:
00395               check = (flag != FLG_LOCALPREFIX);
00396               break;
00397             case FLG_CONSTPREFIXEXCLUDE:
00398               check = (flag != FLG_CONSTPREFIX);
00399               break;
00400             case FLG_ITERPREFIXEXCLUDE:
00401               check = (flag != FLG_ITERPREFIX);
00402               break;
00403             BADDEFAULT;
00404             }
00405           /*@=loopswitchbreak@*/
00406 
00407           if (check)
00408             {
00409               flagcode rcode = namespaceExcluded (code);
00410               cstring pstring = context_getString (rcode);
00411 
00412               if (cstring_isDefined (pstring))
00413                 {
00414                   if (cstring_isUndefined (name))
00415                     {
00416                       name = uentry_getName (ue);
00417                     }
00418                   
00419                   if (matchPrefix (name, context_getString (rcode)))
00420                     {
00421                       if (optgenerror
00422                           (code,
00423                            message
00424                            ("%s %s name is not a %s (it is a %s), "
00425                             "but matches the %s "
00426                             "namespace prefix \"%s\"",
00427                             uentry_ekindName (ue),
00428                             name,
00429                             namespaceName (rcode),
00430                             namespaceName (flag),
00431                             namespaceName (rcode),
00432                             context_getString (rcode)),
00433                            uentry_whereLast (ue)))
00434                         {
00435                           uentry_setHasNameError (ue);
00436                         }
00437                     }
00438                 }
00439             }
00440         } 
00441     } end_excludeFlagCodes ;
00442 
00443   cstring_free (name);
00444 }
00445 
00446 static void
00447 checkNationalName (uentry ue)
00448 {
00449   flagcode czechflag;
00450   flagcode slovakflag;
00451   flagcode czechoslovakflag;
00452   bool gcf, gsf, gcsf;
00453 
00454   
00455   if (uentry_isFunction (ue)
00456       || uentry_isIter (ue)
00457       || uentry_isEndIter (ue))
00458     {
00459       czechflag = FLG_CZECHFUNCTIONS;
00460       slovakflag = FLG_SLOVAKFUNCTIONS;
00461       czechoslovakflag = FLG_CZECHOSLOVAKFUNCTIONS;
00462     }
00463   else if (uentry_isExpandedMacro (ue))
00464     {
00465       czechflag = FLG_CZECHMACROS;
00466       slovakflag = FLG_SLOVAKMACROS;
00467       czechoslovakflag = FLG_CZECHOSLOVAKMACROS;
00468     }
00469   else if (uentry_isVariable (ue))
00470     {
00471       if (uentry_isGlobal (ue) && context_getFlag (FLG_GLOBPREFIX))
00472         {
00473           /* prefix checks supercede national naming checks */
00474           return;
00475         }
00476 
00477       czechflag = FLG_CZECHVARS;
00478       slovakflag = FLG_SLOVAKVARS;
00479       czechoslovakflag = FLG_CZECHOSLOVAKVARS;
00480     }
00481   else if (uentry_isConstant (ue))
00482     {
00483       if (uentry_isGlobal (ue) && context_getFlag (FLG_CONSTPREFIX))
00484         {
00485           /* prefix checks supercede national naming checks */
00486           return;
00487         }
00488 
00489       czechflag = FLG_CZECHCONSTANTS;
00490       slovakflag = FLG_SLOVAKCONSTANTS;
00491       czechoslovakflag = FLG_CZECHOSLOVAKCONSTANTS;
00492     }
00493   else
00494     {
00495       if (uentry_isAnyTag (ue) || uentry_isEnumConstant (ue))
00496         {
00497           return; /* no errors for tags */
00498         }
00499       
00500       llassert (uentry_isDatatype (ue));
00501 
00502       czechflag = FLG_CZECHTYPES;
00503       slovakflag = FLG_SLOVAKTYPES;
00504       czechoslovakflag = FLG_CZECHOSLOVAKTYPES;
00505     }
00506 
00507   gcf = context_getFlag (czechflag);
00508   gsf = context_getFlag (slovakflag);
00509   gcsf = context_getFlag (czechoslovakflag);
00510 
00511   if (gcf || (uentry_isFunction (ue) 
00512               && context_getFlag (FLG_ACCESSCZECH)))
00513     {
00514             (void) checkCzechName (ue, czechflag, gcf);
00515     }
00516 
00517   if (gsf || (uentry_isFunction (ue) 
00518               && context_getFlag (FLG_ACCESSSLOVAK)))
00519     {
00520       (void) checkSlovakName (ue, slovakflag, gsf);
00521     }
00522 
00523   if (gcsf)
00524     {
00525       if (uentry_isDatatype (ue))
00526         {
00527           /* May not have either _'s or uppercase letter */
00528           cstring name = uentry_rawName (ue);
00529           int charno = 1;
00530 
00531           cstring_chars (name, c)
00532             {
00533               if (isupper ((unsigned char) c))
00534                 {
00535                   if (optgenerror
00536                       (FLG_CZECHOSLOVAKTYPES,
00537                        message
00538                        ("%s %q name violates Czechoslovak naming convention.  "
00539                         "Czechoslovak datatype names should not use uppercase "
00540                         "letters.",
00541                         uentry_ekindName (ue),
00542                         uentry_getName (ue)),
00543                        uentry_whereLast (ue)))
00544                     {
00545                       uentry_setHasNameError (ue);
00546                     }
00547                   break;
00548                 }
00549 
00550               if (c == '_' && charno != 2 && charno != 3)
00551                 {
00552                   if (optgenerror
00553                       (FLG_CZECHOSLOVAKTYPES,
00554                        message ("%s %q name violates Czechoslovak naming "
00555                                 "convention.  Czechoslovak datatype names "
00556                                 "should not use the _ charater.",
00557                                 uentry_ekindName (ue),
00558                                 uentry_getName (ue)),
00559                        uentry_whereLast (ue)))
00560                     {
00561                       uentry_setHasNameError (ue);
00562                     }
00563                   break;
00564                 }
00565               
00566               charno++;
00567             } end_cstring_chars;
00568         }
00569       else
00570         {
00571           bool okay = checkCzechName (ue, czechflag, FALSE);
00572           
00573           /* still need to call, to set access */
00574           okay |= checkSlovakName (ue, slovakflag, FALSE);
00575           
00576           if (!okay)
00577             {
00578               if (optgenerror
00579                   (czechoslovakflag,
00580                    message ("%s %q name is not consistent with Czechoslovak "
00581                             "naming convention.",
00582                             uentry_ekindName (ue),
00583                             uentry_getName (ue)),
00584                    uentry_whereLast (ue)))
00585                 {
00586                   uentry_setHasNameError (ue);
00587                 }
00588             }
00589         }
00590     }
00591 }
00592 
00593 static bool checkCzechName (uentry ue, flagcode czechflag, bool report)
00594 {
00595   if (uentry_isDatatype (ue))
00596     {
00597       /*
00598       ** Czech datatypes may not have _'s, except if there are 1 or 2 characters
00599       ** before the only _.
00600       */
00601 
00602       cstring name = uentry_rawName (ue);
00603       int charno = 1;
00604       
00605       cstring_chars (name, c)
00606         {
00607           if (c == '_' && charno != 2 && charno != 3)
00608             {
00609               if (report)
00610                 {
00611                   if (optgenerror
00612                       (FLG_CZECHTYPES,
00613                        message 
00614                        ("%s %q name violates Czech naming convention.  "
00615                         "Czech datatype names should not use the _ charater.",
00616                         uentry_ekindName (ue),
00617                         uentry_getName (ue)),
00618                        uentry_whereLast (ue)))
00619                     {
00620                       uentry_setHasNameError (ue);
00621                     }
00622                 }
00623 
00624               return FALSE;
00625             }
00626           
00627           charno++;
00628         } end_cstring_chars;
00629     }
00630   else
00631     {
00632       typeIdSet acc = context_fileAccessTypes ();
00633       cstring pfx = czechPrefix (uentry_rawName (ue));
00634 
00635       if (cstring_isEmpty (pfx))
00636         {
00637           if (uentry_isVariable (ue) || uentry_isConstant (ue))
00638             {
00639               ctype ct = uentry_getType (ue);
00640               
00641               if (ctype_isAbstract (ct)
00642                   && context_hasAccess (ctype_typeId (ct)))
00643                 {
00644                   if (report)
00645                     {
00646                       if (optgenerror
00647                           (czechflag,
00648                            message ("%s %q name is not consistent with Czech "
00649                                     "naming convention.  The name should "
00650                                     "begin with %s_",
00651                                     uentry_ekindName (ue),
00652                                     uentry_getName (ue),
00653                                     ctype_unparse (ct)),
00654                            uentry_whereLast (ue)))
00655                         {
00656                           uentry_setHasNameError (ue);
00657                         }
00658                     }
00659 
00660                   cstring_free (pfx);
00661                   return FALSE;
00662                 }
00663             }
00664           else if (uentry_isFunction (ue) || uentry_isIter (ue))
00665             {
00666               if (typeIdSet_isEmpty (acc))
00667                 {
00668                   ; /* okay - should not be czech name */
00669                 }
00670               else
00671                 {
00672                   if (report)
00673                     {
00674                       if (optgenerror
00675                           (czechflag,
00676                            message ("%s %q name is not consistent with Czech "
00677                                     "naming convention.  Accessible types: %q",
00678                                     uentry_ekindName (ue),
00679                                     uentry_getName (ue),
00680                                     typeIdSet_unparse (acc)),
00681                            uentry_whereLast (ue)))
00682                         {
00683                           uentry_setHasNameError (ue);
00684                         }
00685                     }
00686 
00687                   cstring_free (pfx);
00688                   return FALSE;
00689                 }
00690             }
00691           else
00692             {
00693               ;
00694             }
00695         }
00696       else
00697         {
00698           if (usymtab_existsTypeEither (pfx))
00699             {
00700               ctype ct = usymtab_lookupAbstractType (pfx);
00701               typeId tid;
00702               
00703               if (ctype_isUA (ct))
00704                 {
00705                   tid = ctype_typeId (ct);
00706                   
00707                   if (ctype_isUser (ct) || context_hasAccess (tid))
00708                     {
00709                       ;
00710                     }
00711                   else
00712                     {
00713                       if (context_getFlag (FLG_ACCESSCZECH)
00714                           || context_getFlag (FLG_ACCESSCZECHOSLOVAK))
00715                         {
00716                           if (!uentry_isVar (ue))
00717                             {
00718                               uentry_addAccessType (ue, tid);
00719                             }
00720                         }
00721                       else
00722                         {
00723                           if (report)
00724                             {
00725                               if (llgenhinterror
00726                                   (czechflag,
00727                                    message 
00728                                    ("%s %q name violates Czech naming "
00729                                     "convention. Czech prefix %s names "
00730                                     "an abstract type that is "
00731                                     "not accessible.",
00732                                     uentry_ekindName (ue),
00733                                     uentry_getName (ue),
00734                                     pfx),
00735                                    cstring_makeLiteral 
00736                                    ("Use +accessczech to allow access to "
00737                                     "type <t> in functions "
00738                                     "named <t>_<name>."), 
00739                                    uentry_whereLast (ue)))
00740                                 {
00741                                   uentry_setHasNameError (ue);
00742                                 }
00743                             }
00744                           
00745                           cstring_free (pfx);
00746                           return FALSE;
00747                         }
00748                     }
00749                 }
00750               else if (ctype_isManifestBool (ct))
00751                 {
00752                   if (context_canAccessBool ())
00753                     {
00754                       ;
00755                     }
00756                   else
00757                     {
00758                       if (context_getFlag (FLG_ACCESSCZECH)
00759                           || context_getFlag (FLG_ACCESSCZECHOSLOVAK))
00760                         {
00761                           if (!uentry_isVar (ue))
00762                             {
00763                               tid = usymtab_getTypeId (context_getBoolName ());
00764                               uentry_addAccessType (ue, tid);
00765                             }
00766                         }
00767                       else
00768                         {
00769                           if (report)
00770                             {
00771                               if (llgenhinterror
00772                                   (czechflag,
00773                                    message
00774                                    ("%s %q name violates Czech naming "
00775                                     "convention. Type bool is not accessible.",
00776                                     uentry_ekindName (ue),
00777                                     uentry_getName (ue)),
00778                                    cstring_makeLiteral 
00779                                    ("Use +accessczech to allow access to "
00780                                     "type <t> in functions named <t>_<name>."), 
00781                                    uentry_whereLast (ue)))
00782                                 {
00783                                   uentry_setHasNameError (ue);
00784                                 }
00785                             }
00786                           
00787                           cstring_free (pfx);
00788                           return FALSE;
00789                         }
00790                     }
00791                 }
00792               else
00793                 {
00794                   ;
00795                 }
00796             }
00797           else
00798             {
00799               if (cstring_equalLit (pfx, "int")
00800                   || cstring_equalLit (pfx, "char")
00801                   || cstring_equalLit (pfx, "short")
00802                   || cstring_equalLit (pfx, "long")
00803                   || cstring_equalLit (pfx, "unsigned")
00804                   || cstring_equalLit (pfx, "signed")
00805                   || cstring_equalLit (pfx, "float")
00806                   || cstring_equalLit (pfx, "double"))
00807                 {
00808                   ; /* built-in types */
00809                 }
00810               else
00811                 {
00812                   /* no accessible types, could match module name */
00813                   
00814                   if (cstring_equal (pfx, context_moduleName ()))
00815                     {
00816                       ;
00817                     }
00818                   else
00819                     {
00820                       if (report)
00821                         {
00822                           if (optgenerror
00823                               (czechflag,
00824                                message 
00825                                ("%s %q name violates Czech naming convention.  "
00826                                 "Czech prefix %s is not the name of a type.",
00827                                 uentry_ekindName (ue),
00828                                 uentry_getName (ue),
00829                                 pfx),
00830                                uentry_whereLast (ue)))
00831                             {
00832                               uentry_setHasNameError (ue);
00833                             }
00834                         }
00835 
00836                       cstring_free (pfx);                     
00837                       return FALSE;
00838                     }
00839                 }
00840             }
00841         }
00842       cstring_free (pfx);
00843     }
00844 
00845   return TRUE;
00846 }
00847 
00848 static bool checkSlovakName (uentry ue, flagcode slovakflag, bool report)
00849 {
00850   if (uentry_isDatatype (ue))
00851     {
00852       /*
00853       ** Slovak datatypes may not have uppercase letters.
00854       */
00855 
00856       if (context_getFlag (FLG_SLOVAK))
00857         {
00858           cstring name = uentry_rawName (ue);
00859 
00860           cstring_chars (name, c)
00861             {
00862               if (isupper ((unsigned char) c))
00863                 {
00864                   if (report)
00865                     {
00866                       if (optgenerror
00867                           (FLG_SLOVAKTYPES,
00868                            message 
00869                            ("%s %q name violates Slovak naming convention.  "
00870                             "Slovak datatype names should not use uppercase "
00871                             "letters.",
00872                             uentry_ekindName (ue),
00873                             uentry_getName (ue)),
00874                            uentry_whereLast (ue)))
00875                         {
00876                           uentry_setHasNameError (ue);
00877                         }
00878                     }
00879                   return FALSE;
00880                 }
00881             } end_cstring_chars;
00882         }
00883     }
00884   else
00885     {
00886       typeIdSet acc = context_fileAccessTypes ();
00887       cstring pfx = slovakPrefix (uentry_rawName (ue));
00888       
00889       if (cstring_isEmpty (pfx))
00890         {
00891           if (typeIdSet_isEmpty (acc))
00892             {
00893               ; /* okay - should not be slovak name */
00894             }
00895           else
00896             {
00897               if (uentry_isFunction (ue))
00898                 {
00899                   if (report)
00900                     {
00901                       if (optgenerror
00902                           (slovakflag,
00903                            message ("%s %q name is not consistent with Slovak "
00904                                     "naming convention.  Accessible types: %q",
00905                                     uentry_ekindName (ue),
00906                                     uentry_getName (ue),
00907                                     typeIdSet_unparse (acc)),
00908                            uentry_whereLast (ue)))
00909                         {
00910                           uentry_setHasNameError (ue);
00911                         }
00912                     }
00913                   
00914                   cstring_free (pfx);
00915                   return FALSE;
00916                 }
00917               else
00918                 {
00919                   ctype ct = uentry_getType (ue);
00920                   
00921                   if (ctype_isUA (ct))
00922                     {
00923                       if (report)
00924                         {
00925                           if (optgenerror
00926                               (slovakflag,
00927                                message ("%s %q name is not consistent with "
00928                                         "Slovak naming convention.  The "
00929                                         "name should begin with %s followed "
00930                                         "by an uppercase letter.",
00931                                         uentry_ekindName (ue),
00932                                         uentry_getName (ue),
00933                                         ctype_unparse (ct)),
00934                                uentry_whereLast (ue)))
00935                             {
00936                               uentry_setHasNameError (ue);
00937                             }   
00938                         }
00939                       
00940                       cstring_free (pfx);
00941                       return FALSE;
00942                     }
00943                 }
00944             }
00945         }
00946       else
00947         {
00948           if (usymtab_existsTypeEither (pfx))
00949             {
00950               ctype ct = usymtab_lookupAbstractType (pfx);
00951               typeId tid;
00952               
00953               if (ctype_isUA (ct))
00954                 {
00955                   tid = ctype_typeId (ct);
00956                   
00957                   if (ctype_isUser (ct) || context_hasAccess (tid))
00958                     {
00959                       ;
00960                     }
00961                   else
00962                     {
00963                       if (context_getFlag (FLG_ACCESSSLOVAK)
00964                           || context_getFlag (FLG_ACCESSCZECHOSLOVAK))
00965                         {
00966                           if (!uentry_isVar (ue))
00967                             {
00968                               uentry_addAccessType (ue, tid);
00969                             }
00970                         }
00971                       else
00972                         {
00973                           if (report)
00974                             {
00975                               if (llgenhinterror
00976                                   (slovakflag,
00977                                    message 
00978                                    ("%s %q name violates Slovak naming "
00979                                     "convention. Slovak prefix %s names "
00980                                     "an abstract type that is not accessible.",
00981                                     uentry_ekindName (ue),
00982                                     uentry_getName (ue),
00983                                     pfx),
00984                                    cstring_makeLiteral 
00985                                    ("Use +accessslovak to allow access to "
00986                                     "type <t> in functions named <t>_<name>."), 
00987                                    uentry_whereLast (ue)))
00988                                 {
00989                                   uentry_setHasNameError (ue);
00990                                 }
00991                             }
00992                           
00993                           cstring_free (pfx);
00994                           return FALSE;
00995                         }
00996                     }
00997                 }
00998               else if (ctype_isManifestBool (ct))
00999                 {
01000                   if (context_canAccessBool ())
01001                     {
01002                       ;
01003                     }
01004                   else
01005                     {
01006                       if (context_getFlag (FLG_ACCESSSLOVAK)
01007                           || context_getFlag (FLG_ACCESSCZECHOSLOVAK))
01008                         {
01009                           if (!uentry_isVar (ue))
01010                             {
01011                               tid = usymtab_getTypeId (context_getBoolName ());
01012                               uentry_addAccessType (ue, tid);
01013                             }
01014                         }
01015                       else
01016                         {
01017                           if (report)
01018                             {
01019                               if (llgenhinterror
01020                                   (slovakflag,
01021                                    message
01022                                    ("%s %q name violates Slovak naming convention.  "
01023                                     "Type bool is not accessible.",
01024                                     uentry_ekindName (ue),
01025                                     uentry_getName (ue)),
01026                                    cstring_makeLiteral
01027                                    ("Use +accessslovak to allow access to "
01028                                     "type <t> in functions named <t>_<name>."),
01029                                    uentry_whereLast (ue)))
01030                                 {
01031                                   uentry_setHasNameError (ue);
01032                                 }
01033                             }
01034                           
01035                           cstring_free (pfx);
01036                           return FALSE;
01037                         }
01038                     }
01039                 }
01040               else
01041                 {
01042                   ;
01043                 }
01044             }
01045           else
01046             {
01047               if (cstring_equalLit (pfx, "int")
01048                   || cstring_equalLit (pfx, "char")
01049                   || cstring_equalLit (pfx, "short")
01050                   || cstring_equalLit (pfx, "long")
01051                   || cstring_equalLit (pfx, "unsigned")
01052                   || cstring_equalLit (pfx, "signed")
01053                   || cstring_equalLit (pfx, "float")
01054                   || cstring_equalLit (pfx, "double"))
01055                 {
01056                   ; /* built-in types */
01057                 }
01058               else
01059                 {
01060                   /* no accessible types, could match module name */
01061                   
01062                   if (cstring_equal (pfx, context_moduleName ()))
01063                     {
01064                       ;
01065                     }
01066                   else
01067                     {
01068                       if (report)
01069                         {
01070                           if (optgenerror
01071                               (slovakflag,
01072                                message 
01073                                ("%s %q name violates Slovak naming convention.  "
01074                                 "Slovak prefix %s is not the name of a type.",
01075                                 uentry_ekindName (ue),
01076                                 uentry_getName (ue),
01077                                 pfx),
01078                                uentry_whereLast (ue)))
01079                             {
01080                               uentry_setHasNameError (ue);
01081                             }
01082                         }
01083 
01084                       cstring_free (pfx);
01085                       return FALSE;
01086                     }
01087                 }
01088             }
01089         }
01090 
01091       cstring_free (pfx);
01092     }
01093 
01094   return TRUE;
01095 }
01096 
01097 void
01098 checkGlobalName (uentry ue)
01099 {
01100   if (!uentry_isStatic (ue) && uentry_hasName (ue))
01101     {
01102       checkNationalName (ue);
01103     }
01104   else
01105     {
01106       ;
01107     }
01108 }
01109 
01110 void
01111 checkLocalName (/*@unused@*/ uentry ue)
01112 {
01113   ;
01114 }
01115 
01116 /*
01117 ** Checks a name used by user source is not reserved by ANSI 
01118 ** (or for future library functions).
01119 **
01120 ** The restrictions are described in X3.159-1989: 4.13
01121 */
01122 
01123 /*@constant int NRESERVEDNAMES; @*/
01124 # define NRESERVEDNAMES 201
01125 
01126 /*@constant int NCPPNAMES@*/
01127 # define NCPPNAMES 39
01128 
01129 bool checkCppName (cstring name, fileloc loc)
01130 {
01131   static ob_mstring cppNames[NCPPNAMES] =
01132     {
01133       "and", "and_eq", "asm", 
01134       "bitand", "bitor", "bool", /* gasp: "bool", is special for lclint */
01135       "catch", "class", "compl", "const_class",
01136       "delete", "dynamic_cast", "false", "friend",
01137       "inline", "mutable", "namespace", "new",
01138       "not", "not_eq",
01139       "operator", "or", "or_eq", "overload",
01140       "private", "protected", "public",
01141       "reinterpret_cast", "static_cast",
01142       "template", "this", "throw", "true", "try",
01143       "typeid", "using", "virtual", "xor", "xor_eq"
01144       } ;
01145   
01146   if (cstring_isDefined (cstring_bsearch (name, &cppNames[0],
01147                                           NCPPNAMES)))
01148     {
01149       return (optgenerror
01150               (FLG_CPPNAMES,
01151                message ("Name %s is a keyword or reserved word in C++",
01152                         name),
01153                loc));
01154     }
01155 
01156   return FALSE;
01157 }
01158 
01159 bool
01160 checkAnsiName (cstring name, fileloc loc)
01161 {
01162   bool hasError = FALSE;
01163   int length = cstring_length (name);
01164   char fchar = (length >= 1) ? cstring_firstChar (name) : '\0';
01165   char schar = (length >= 2) ? cstring_secondChar (name) : '\0';
01166   char tchar = (length >= 3) ? cstring_getChar (name, 3) : '\0';
01167   char rchar = (length >= 4) ? cstring_getChar (name, 4) : '\0';
01168 
01169   /* 
01170   ** reservedNames
01171   **   taken from Linden, "Expert C Programming", p. 126-8. 
01172   **   invariant:  must be sorted (case-insensitive, lexicographically)
01173   **               must end with NULL
01174   */
01175 
01176   static ob_mstring reservedNames[NRESERVEDNAMES] =
01177     { 
01178 # include "reservedNames.nf"
01179     } ;
01180 
01181   if (fileloc_isSystemFile (loc) || fileloc_isBuiltin (loc))
01182     {
01183       return FALSE;  /* no errors for system files */
01184     }
01185 
01186 # if 0
01187   {
01188     int i = 0;
01189     char *lastname = NULL;
01190     char *name;
01191     
01192     while ((name = reservedNames[i]) != NULL)
01193       {
01194         llassertprint (lastname == NULL
01195                        || strcmp (name, lastname) > 0,
01196                        ("%s / %s", lastname, name));
01197         lastname = name;
01198         i++;
01199       }
01200     
01201     nreservedNames = i - 1;
01202   }
01203 # endif
01204   
01205   if (cstring_isDefined (cstring_bsearch (name, &reservedNames[0],
01206                                           NRESERVEDNAMES)))
01207     {
01208       return (optgenerror
01209               (FLG_ANSIRESERVED,
01210                message ("Name %s is reserved for the standard library",
01211                         name),
01212                loc));
01213     }
01214 
01215   if (fchar == '_')
01216     {
01217       hasError = optgenerror
01218         (FLG_ANSIRESERVED,
01219          message 
01220          ("Name %s is in the implementation name space (any identifier "
01221           "beginning with underscore)", 
01222           name),
01223          loc);
01224     }
01225 
01226   /*
01227   ** 4.13.1 Errors <errno.h>
01228   **
01229   ** Macros that begin with E and a digit or E and an uppercase letter ...
01230   */
01231 
01232   else if (fchar == 'E' && (isdigit ((int) schar) 
01233                             || isupper ((int) schar)))
01234     {
01235       hasError = optgenerror
01236         (FLG_ANSIRESERVED,
01237          message 
01238          ("Name %s is reserved for future ANSI library extensions. "
01239           "Macros beginning with E and a digit or uppercase letter "
01240           "may be added to <errno.h>. (See ANSI, Section 4.13.1)",
01241           name),
01242          loc);
01243     }
01244   
01245   /*
01246   ** 4.13.2 Character Handling <ctype.h>
01247   **
01248   ** Function names that begin with either "is" or "to" and a lowercase letter ...
01249   */
01250 
01251   else if (((fchar == 'i' && schar == 's') 
01252             || (fchar == 't' && schar == 'o'))
01253            && (islower ((int) tchar)))
01254     {
01255       hasError = optgenerror
01256         (FLG_ANSIRESERVED,
01257          message
01258          ("Name %s is reserved for future ANSI library extensions.  "
01259           "Functions beginning with \"is\" or \"to\" and a lowercase "
01260           "letter may be added to <ctype.h>. (See ANSI, Section 4.13.2)",
01261           name),
01262          loc);
01263     }
01264   
01265   /*
01266   ** 4.13.3 Localization <locale.h>
01267   **
01268   ** Macros that begin with LC_ and an uppercase letter ...
01269   */
01270 
01271   else if (length >= 4 
01272            && ((fchar == 'L')
01273                && (schar == 'C')
01274                && (tchar == '_'))
01275            && (isupper ((int) rchar)))
01276     {
01277       hasError = optgenerror
01278         (FLG_ANSIRESERVED,
01279          message
01280          ("Name %s is reserved for future ANSI library extensions.  "
01281           "Macros beginning with \"LC_\" and an uppercase letter may "
01282           "be added to <locale.h>. (See ANSI, Section 4.13.3)",
01283           name),
01284          loc);
01285     }
01286   
01287   /*
01288   ** 4.13.4 Mathematics <math.h>
01289   **
01290   ** The names of all existing functions declared in the <math.h> header, 
01291   ** suffixed with f or l...
01292   */
01293 
01294   else if ((cstring_lastChar (name) == 'f' || cstring_lastChar (name) == 'l')
01295            && 
01296            (((length == 4)
01297              && ((cstring_equalPrefix (name, "cos") ||
01298                   cstring_equalPrefix (name, "sin") ||
01299                   cstring_equalPrefix (name, "tan") ||
01300                   cstring_equalPrefix (name, "exp") ||
01301                   cstring_equalPrefix (name, "log") ||
01302                   cstring_equalPrefix (name, "pow"))))
01303             || ((length == 5)
01304                 && ((cstring_equalPrefix (name, "acos") ||
01305                      cstring_equalPrefix (name, "asin") ||
01306                      cstring_equalPrefix (name, "atan") ||
01307                      cstring_equalPrefix (name, "cosh") ||
01308                      cstring_equalPrefix (name, "sinh") ||
01309                      cstring_equalPrefix (name, "sqrt") ||
01310                      cstring_equalPrefix (name, "ceil") ||
01311                      cstring_equalPrefix (name, "fabs") ||
01312                      cstring_equalPrefix (name, "fmod") ||
01313                      cstring_equalPrefix (name, "tanh") ||
01314                      cstring_equalPrefix (name, "modf"))))
01315             || ((length == 6)
01316                 && ((cstring_equalPrefix (name, "atan2") ||
01317                      cstring_equalPrefix (name, "floor") ||
01318                      cstring_equalPrefix (name, "frexp") ||
01319                      cstring_equalPrefix (name, "ldexp") ||
01320                      cstring_equalPrefix (name, "log10"))))))
01321     {
01322       hasError = optgenerror
01323         (FLG_ANSIRESERVED,
01324          message
01325          ("Name %s is reserved for future ANSI library extensions.  "
01326           "The names of all existing functions in <math.h> suffixed "
01327           "with 'f' or 'l' may be added to <math.h>. (See ANSI, Section 4.13.4)",
01328           name),
01329          loc);
01330     }
01331   
01332   /*
01333   ** 4.13.5 Signal Handling <signal.h>
01334   **
01335   ** Macros that begin with either SIG or SIG_ and an uppercase letter or...
01336   */
01337 
01338   else if (fchar == 'S' && schar == 'I' && tchar == 'G'
01339            && ((rchar == '_' && ((length >= 5 
01340                                   && isupper ((int) cstring_getChar (name, 5)))))
01341                || (isupper ((int) rchar))))
01342     {
01343       hasError = optgenerror
01344         (FLG_ANSIRESERVED,
01345          message
01346          ("Name %s is reserved for future ANSI library extensions.  "
01347           "Macros that begin with SIG and an uppercase letter or SIG_ "
01348           "and an uppercase letter may be added to "
01349           "<signal.h>. (See ANSI, Section 4.13.5)",
01350           name),
01351          loc);
01352     }
01353   
01354   /*
01355   ** 4.13.6 Input/Output <stdio.h>
01356   **
01357   ** (nothing to check)
01358   */
01359 
01360   /*
01361   ** 4.13.7 General Utilities <stdlib.h>
01362   **
01363   ** Functions names that begin with str and a lowercase letter may be added to <stdlib.h>.
01364   */
01365 
01366   else if (fchar == 's' && schar == 't' && tchar == 'r' 
01367            && (islower ((int) rchar)))
01368     {
01369       hasError = optgenerror
01370         (FLG_ANSIRESERVED,
01371          message
01372          ("Name %s is reserved for future ANSI library extensions.  "
01373           "Functions that begin with \"str\" and a lowercase letter "
01374           "may be added to <stdlib.h> or <string.h>. (See ANSI, Section 4.13.7)",
01375           name),
01376          loc);
01377     }
01378   
01379   /*
01380   ** 4.13.8 String Handling <string.h>
01381   **
01382   ** Function names that begin with str, mem, or wcs and a lowercase letter ...
01383   **
01384   ** (Note: already checked "str" above.)
01385   */
01386 
01387   else if (((fchar == 'm' && schar == 'e' && tchar == 'm')
01388             || (fchar == 'w' && schar == 'c' && tchar == 's'))
01389            && (islower ((int) rchar)))
01390     {
01391       hasError = optgenerror
01392         (FLG_ANSIRESERVED,
01393          message
01394          ("Name %s is reserved for future ANSI library extensions.  "
01395           "Functions that begin with \"mem\" or \"wcs\" and a "
01396           "lowercase letter letter may be added to <string.h>. (See ANSI, Section 4.13.8)",
01397           name),
01398          loc);
01399     }
01400   else
01401     {
01402       ;
01403     }
01404 
01405   return hasError;
01406 }
01407 
01408 void checkParamNames (uentry ue)
01409 {
01410   cstring fpfx = context_getString (FLG_DECLPARAMPREFIX);
01411   bool noformal = context_getFlag (FLG_DECLPARAMNAME);
01412 
01413   llassert (uentry_isFunction (ue));
01414   
01415   if (cstring_isDefined (fpfx) || noformal)
01416     {
01417       uentryList params = uentry_getParams (ue);
01418       
01419       uentryList_elements (params, p)
01420         {
01421           if (uentry_hasName (p))
01422             {
01423               if (noformal && !cstring_isDefined (fpfx))
01424                 {
01425                   if (optgenerror
01426                       (FLG_DECLPARAMNAME, 
01427                        message ("Declaration parameter has name: %q",
01428                                 uentry_getName (p)),
01429                        uentry_whereLast (p)))
01430                     {
01431                       uentry_setHasNameError (p);
01432                     }
01433                 }
01434               else
01435                 {
01436                   cstring pname = uentry_getName (p);
01437                   
01438                   if (!cstring_equalPrefix (pname, cstring_toCharsSafe (fpfx)))
01439                     {
01440                       if (context_getFlag (FLG_NAMECHECKS))
01441                         {
01442                           if (optgenerror
01443                               (FLG_DECLPARAMPREFIX, 
01444                                message ("Declaration parameter name %s does not begin "
01445                                         "with protoparamprefix (%s)",
01446                                         pname, fpfx),
01447                                uentry_whereLast (p)))
01448                             {
01449                               uentry_setHasNameError (p);
01450                             }
01451                         }
01452                     }
01453                   cstring_free (pname);
01454                 }
01455             }
01456         } end_uentryList_elements ;
01457     }
01458 }
01459 
01460 
01461 
01462 

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