/*
** Splint - annotation-assisted static program checker
** Copyright (C) 1994-2003 University of Virginia,
** Massachusetts Institute of Technology
**
** This program is free software; you can redistribute it and/or modify it
** under the terms of the GNU General Public License as published by the
** Free Software Foundation; either version 2 of the License, or (at your
** option) any later version.
**
** This program is distributed in the hope that it will be useful, but
** WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** General Public License for more details.
**
** The GNU General Public License is available from http://www.gnu.org/ or
** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
** MA 02111-1307, USA.
**
** For information on splint: info@splint.org
** To report a bug: splint-bug@splint.org
** For more information: http://www.splint.org
*/
/*
** nameChecks.c
*/
# include "splintMacros.nf"
# include "basic.h"
# include "nameChecks.h"
static bool checkCzechName (uentry p_ue, flagcode p_czechflag, bool p_report)
/*@modifies p_ue, g_warningstream@*/ ;
static bool checkSlovakName (uentry p_ue, flagcode p_slovakflag, bool p_report)
/*@modifies p_ue, g_warningstream@*/ ;
static cstring czechPrefix (cstring name)
{
return (cstring_beforeChar (name, '_'));
}
static cstring slovakPrefix (cstring name)
{
size_t i = 0;
cstring_chars (name, c)
{
if (isupper ((unsigned char) c))
{
return (cstring_prefix (name, i));
}
i++;
} end_cstring_chars;
return cstring_undefined;
}
static flagcode excludeCodes [] =
{
FLG_MACROVARPREFIXEXCLUDE,
FLG_TAGPREFIXEXCLUDE,
FLG_ENUMPREFIXEXCLUDE,
FLG_FILESTATICPREFIXEXCLUDE,
FLG_GLOBPREFIXEXCLUDE,
FLG_TYPEPREFIXEXCLUDE,
FLG_EXTERNALPREFIXEXCLUDE,
FLG_UNCHECKEDMACROPREFIXEXCLUDE,
FLG_LOCALPREFIXEXCLUDE,
INVALID_FLAG
} ;
/*@iter excludeFlagCodes (yield flagcode code);@*/
# define excludeFlagCodes(m_c) \
{ int m_i = 0; while (flagcode_isValid (excludeCodes[m_i])) \
{ flagcode m_c = excludeCodes[m_i]; m_i++;
# define end_excludeFlagCodes }}
static bool matchPrefixChar (int nc, int pc)
{
if (nc == pc)
{
return TRUE;
}
else
{
switch (pc)
{
case PFX_UPPERCASE:
return isupper (nc);
case PFX_LOWERCASE:
return islower (nc);
case PFX_ANY:
return TRUE;
case PFX_DIGIT:
return isdigit (nc);
case PFX_NOTUPPER:
return !isupper (nc);
case PFX_NOTLOWER:
return !islower (nc);
case PFX_ANYLETTER:
return isalpha (nc);
case PFX_ANYLETTERDIGIT:
return (isdigit (nc) || isalpha (nc));
default: return FALSE;
}
}
BADEXIT;
}
static bool matchPrefix (cstring name, cstring prefix)
{
if (cstring_isUndefined (name)
|| cstring_isUndefined (prefix))
{
return TRUE;
}
else
{
size_t namelen = cstring_length (name);
int last = (int) '\0';
size_t n = 1;
cstring_chars (prefix, pc)
{
int nc;
if (pc == '*')
{
n++;
while (n <= namelen)
{
nc = (int) cstring_getChar (name, n);
if (!matchPrefixChar (nc, last))
{
return FALSE;
}
n++;
}
return TRUE;
}
else
{
if (n > namelen)
{
if (namelen > 1
&& (cstring_length (prefix) >= n + 1)
&& cstring_getChar (prefix, n + 1) == '*')
{
return TRUE;
}
else
{
return FALSE;
}
}
nc = (int) cstring_getChar (name, n);
if (!matchPrefixChar (nc, (int) pc))
{
return FALSE;
}
}
last = (int) pc;
n++;
} end_cstring_chars;
return TRUE;
}
}
static flagcode
namespaceExcluded (flagcode code) /*@*/
{
switch (code)
{
case FLG_MACROVARPREFIXEXCLUDE:
return (FLG_MACROVARPREFIX);
case FLG_TAGPREFIXEXCLUDE:
return (FLG_TAGPREFIX);
case FLG_ENUMPREFIXEXCLUDE:
return (FLG_ENUMPREFIX);
case FLG_FILESTATICPREFIXEXCLUDE:
return (FLG_FILESTATICPREFIX);
case FLG_GLOBPREFIXEXCLUDE:
return (FLG_GLOBPREFIX);
case FLG_TYPEPREFIXEXCLUDE:
return (FLG_TYPEPREFIX);
case FLG_EXTERNALPREFIXEXCLUDE:
return (FLG_EXTERNALPREFIX);
case FLG_UNCHECKEDMACROPREFIXEXCLUDE:
return (FLG_UNCHECKEDMACROPREFIX);
case FLG_LOCALPREFIXEXCLUDE:
return (FLG_LOCALPREFIX);
case FLG_ITERPREFIXEXCLUDE:
return (FLG_ITERPREFIX);
case FLG_CONSTPREFIXEXCLUDE:
return (FLG_CONSTPREFIX);
BADDEFAULT;
}
}
static /*@observer@*/ cstring
namespaceName (flagcode flag) /*@*/
{
switch (flag)
{
case FLG_MACROVARPREFIX:
return cstring_makeLiteralTemp ("macro variable");
case FLG_TAGPREFIX:
return cstring_makeLiteralTemp ("tag");
case FLG_ENUMPREFIX:
return cstring_makeLiteralTemp ("enum member");
case FLG_TYPEPREFIX:
return cstring_makeLiteralTemp ("user-defined type");
case FLG_FILESTATICPREFIX:
return cstring_makeLiteralTemp ("file static");
case FLG_GLOBPREFIX:
return cstring_makeLiteralTemp ("global variable");
case FLG_EXTERNALPREFIX:
return cstring_makeLiteralTemp ("external");
case FLG_LOCALPREFIX:
return cstring_makeLiteralTemp ("local variable");
case FLG_CONSTPREFIX:
return cstring_makeLiteralTemp ("constant");
case FLG_ITERPREFIX:
return cstring_makeLiteralTemp ("iter");
case FLG_UNCHECKEDMACROPREFIX:
return cstring_makeLiteralTemp ("unchecked macro");
BADDEFAULT;
}
}
void
checkPrefix (uentry ue)
{
cstring name = cstring_undefined;
flagcode flag;
if (uentry_isExpandedMacro (ue))
{
flag = FLG_UNCHECKEDMACROPREFIX;
}
else if (uentry_isAnyTag (ue))
{
flag = FLG_TAGPREFIX;
}
else if (uentry_isEnumConstant (ue))
{
flag = FLG_ENUMPREFIX;
}
else if (uentry_isDatatype (ue))
{
flag = FLG_TYPEPREFIX;
}
else if (uentry_isFileStatic (ue))
{
flag = FLG_FILESTATICPREFIX;
}
else if (uentry_isGlobalVariable (ue))
{
flag = FLG_GLOBPREFIX;
}
else if (uentry_isVariable (ue))
{
if (uentry_isRefParam (ue))
{
return; /* already checked param */
}
if (context_inMacro ())
{
if (uentry_isAnyParam (ue))
{
if (uentry_isYield (ue))
{
flag = FLG_MACROVARPREFIX;
}
else
{
flag = FLG_LOCALPREFIX;
}
}
else
{
flag = FLG_MACROVARPREFIX;
}
}
else
{
flag = FLG_LOCALPREFIX;
}
}
else if (uentry_isConstant (ue))
{
flag = FLG_CONSTPREFIX;
}
else if (uentry_isIter (ue))
{
flag = FLG_ITERPREFIX;
}
else if (uentry_isExported (ue))
{
flag = FLG_EXTERNALPREFIX;
}
else
{
llcontbug (message ("What is it: %q", uentry_unparseFull (ue)));
return;
}
if (flag == FLG_TYPEPREFIX || flag == FLG_GLOBPREFIX
|| flag == FLG_ENUMPREFIX || flag == FLG_CONSTPREFIX)
{
if (flag == FLG_ENUMPREFIX)
{
if (!context_getFlag (flag))
{
flag = FLG_CONSTPREFIX;
}
}
if (!context_getFlag (flag))
{
flag = FLG_EXTERNALPREFIX;
}
}
if (context_getFlag (flag))
{
name = uentry_observeRealName (ue);
if (!matchPrefix (name, context_getString (flag)))
{
llassert (flag != FLG_NAMECHECKS);
if (optgenerror2
(flag, FLG_NAMECHECKS,
message ("%s %s name is not consistent with %s "
"namespace prefix \"%s\"",
uentry_ekindName (ue),
name,
namespaceName (flag),
context_getString (flag)),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
}
}
excludeFlagCodes (code)
{
bool check = FALSE;
if (context_getFlag (code))
{
/*@-loopswitchbreak@*/
switch (code)
{
case FLG_MACROVARPREFIXEXCLUDE:
check = (flag != FLG_MACROVARPREFIX);
break;
case FLG_TAGPREFIXEXCLUDE:
check = (flag != FLG_TAGPREFIX);
break;
case FLG_ENUMPREFIXEXCLUDE:
check = (flag != FLG_ENUMPREFIX);
break;
case FLG_FILESTATICPREFIXEXCLUDE:
check = (flag != FLG_FILESTATICPREFIX);
break;
case FLG_GLOBPREFIXEXCLUDE:
check = (flag != FLG_GLOBPREFIX);
break;
case FLG_TYPEPREFIXEXCLUDE:
check = (flag != FLG_TYPEPREFIX);
break;
case FLG_EXTERNALPREFIXEXCLUDE:
check = (flag != FLG_EXTERNALPREFIX
&& flag != FLG_GLOBPREFIX
&& flag != FLG_TYPEPREFIX
&& flag != FLG_UNCHECKEDMACROPREFIX);
break;
case FLG_UNCHECKEDMACROPREFIXEXCLUDE:
check = (flag != FLG_UNCHECKEDMACROPREFIX);
break;
case FLG_LOCALPREFIXEXCLUDE:
check = (flag != FLG_LOCALPREFIX);
break;
case FLG_CONSTPREFIXEXCLUDE:
check = (flag != FLG_CONSTPREFIX);
break;
case FLG_ITERPREFIXEXCLUDE:
check = (flag != FLG_ITERPREFIX);
break;
BADDEFAULT;
}
/*@=loopswitchbreak@*/
if (check)
{
flagcode rcode = namespaceExcluded (code);
cstring pstring = context_getString (rcode);
if (cstring_isDefined (pstring))
{
if (cstring_isUndefined (name))
{
name = uentry_observeRealName (ue);
}
if (matchPrefix (name, context_getString (rcode)))
{
if (optgenerror2
(code, FLG_NAMECHECKS,
message
("%s %s name is not a %s (it is a %s), "
"but matches the %s "
"namespace prefix \"%s\"",
uentry_ekindName (ue),
name,
namespaceName (rcode),
namespaceName (flag),
namespaceName (rcode),
context_getString (rcode)),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
}
}
}
}
} end_excludeFlagCodes ;
}
static void
checkNationalName (uentry ue)
{
flagcode czechflag;
flagcode slovakflag;
flagcode czechoslovakflag;
bool gcf, gsf, gcsf;
if (uentry_isFunction (ue)
|| uentry_isIter (ue)
|| uentry_isEndIter (ue))
{
czechflag = FLG_CZECHFUNCTIONS;
slovakflag = FLG_SLOVAKFUNCTIONS;
czechoslovakflag = FLG_CZECHOSLOVAKFUNCTIONS;
}
else if (uentry_isExpandedMacro (ue))
{
czechflag = FLG_CZECHMACROS;
slovakflag = FLG_SLOVAKMACROS;
czechoslovakflag = FLG_CZECHOSLOVAKMACROS;
}
else if (uentry_isVariable (ue))
{
if (uentry_isGlobalVariable (ue) && context_getFlag (FLG_GLOBPREFIX))
{
/* prefix checks supercede national naming checks */
return;
}
czechflag = FLG_CZECHVARS;
slovakflag = FLG_SLOVAKVARS;
czechoslovakflag = FLG_CZECHOSLOVAKVARS;
}
else if (uentry_isConstant (ue))
{
if (uentry_isGlobalVariable (ue) && context_getFlag (FLG_CONSTPREFIX))
{
/* prefix checks supercede national naming checks */
return;
}
czechflag = FLG_CZECHCONSTANTS;
slovakflag = FLG_SLOVAKCONSTANTS;
czechoslovakflag = FLG_CZECHOSLOVAKCONSTANTS;
}
else
{
if (uentry_isAnyTag (ue) || uentry_isEnumConstant (ue))
{
return; /* no errors for tags */
}
llassert (uentry_isDatatype (ue));
czechflag = FLG_CZECHTYPES;
slovakflag = FLG_SLOVAKTYPES;
czechoslovakflag = FLG_CZECHOSLOVAKTYPES;
}
gcf = context_getFlag (czechflag);
gsf = context_getFlag (slovakflag);
gcsf = context_getFlag (czechoslovakflag);
if (gcf || (uentry_isFunction (ue)
&& context_getFlag (FLG_ACCESSCZECH)))
{
(void) checkCzechName (ue, czechflag, gcf);
}
if (gsf || (uentry_isFunction (ue)
&& context_getFlag (FLG_ACCESSSLOVAK)))
{
(void) checkSlovakName (ue, slovakflag, gsf);
}
if (gcsf)
{
if (uentry_isDatatype (ue))
{
/* May not have either _'s or uppercase letter */
cstring name = uentry_rawName (ue);
int charno = 1;
cstring_chars (name, c)
{
if (isupper ((unsigned char) c))
{
if (optgenerror2
(FLG_CZECHOSLOVAKTYPES, FLG_NAMECHECKS,
message
("%s %q name violates Czechoslovak naming convention. "
"Czechoslovak datatype names should not use uppercase "
"letters.",
uentry_ekindName (ue),
uentry_getName (ue)),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
break;
}
if (c == '_' && charno != 2 && charno != 3)
{
if (optgenerror2
(FLG_CZECHOSLOVAKTYPES, FLG_NAMECHECKS,
message ("%s %q name violates Czechoslovak naming "
"convention. Czechoslovak datatype names "
"should not use the _ charater.",
uentry_ekindName (ue),
uentry_getName (ue)),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
break;
}
charno++;
} end_cstring_chars;
}
else
{
bool okay = checkCzechName (ue, czechflag, FALSE);
/* still need to call, to set access */
okay |= checkSlovakName (ue, slovakflag, FALSE);
if (!okay)
{
if (optgenerror2
(czechoslovakflag, FLG_NAMECHECKS,
message ("%s %q name is not consistent with Czechoslovak "
"naming convention.",
uentry_ekindName (ue),
uentry_getName (ue)),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
}
}
}
}
static bool checkCzechName (uentry ue, flagcode czechflag, bool report)
{
if (uentry_isDatatype (ue))
{
/*
** Czech datatypes may not have _'s, except if there are 1 or 2 characters
** before the only _.
*/
cstring name = uentry_rawName (ue);
int charno = 1;
cstring_chars (name, c)
{
if (c == '_' && charno != 2 && charno != 3)
{
if (report)
{
if (optgenerror2
(FLG_CZECHTYPES, FLG_NAMECHECKS,
message
("%s %q name violates Czech naming convention. "
"Czech datatype names should not use the _ charater.",
uentry_ekindName (ue),
uentry_getName (ue)),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
}
return FALSE;
}
charno++;
} end_cstring_chars;
}
else
{
typeIdSet acc = context_fileAccessTypes ();
cstring pfx = czechPrefix (uentry_rawName (ue));
if (cstring_isEmpty (pfx))
{
if (uentry_isVariable (ue) || uentry_isConstant (ue))
{
ctype ct = uentry_getType (ue);
if (ctype_isAbstract (ct)
&& context_hasAccess (ctype_typeId (ct)))
{
if (report)
{
if (optgenerror2
(czechflag, FLG_NAMECHECKS,
message ("%s %q name is not consistent with Czech "
"naming convention. The name should "
"begin with %s_",
uentry_ekindName (ue),
uentry_getName (ue),
ctype_unparse (ct)),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
}
cstring_free (pfx);
return FALSE;
}
}
else if (uentry_isFunction (ue) || uentry_isIter (ue))
{
if (typeIdSet_isEmpty (acc))
{
; /* okay - should not be czech name */
}
else
{
if (report)
{
if (optgenerror2
(czechflag, FLG_NAMECHECKS,
message ("%s %q name is not consistent with Czech "
"naming convention. Accessible types: %q",
uentry_ekindName (ue),
uentry_getName (ue),
typeIdSet_unparse (acc)),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
}
cstring_free (pfx);
return FALSE;
}
}
else
{
;
}
}
else
{
if (usymtab_existsTypeEither (pfx))
{
ctype ct = usymtab_lookupAbstractType (pfx);
typeId tid;
if (ctype_isUA (ct))
{
tid = ctype_typeId (ct);
if (ctype_isUser (ct) || context_hasAccess (tid))
{
;
}
else
{
if (context_getFlag (FLG_ACCESSCZECH)
|| context_getFlag (FLG_ACCESSCZECHOSLOVAK))
{
if (!uentry_isVar (ue))
{
uentry_addAccessType (ue, tid);
}
}
else
{
if (report)
{
if (llgenhinterror
(czechflag,
message
("%s %q name violates Czech naming "
"convention. Czech prefix %s names "
"an abstract type that is "
"not accessible.",
uentry_ekindName (ue),
uentry_getName (ue),
pfx),
cstring_makeLiteral
("Use +accessczech to allow access to "
"type <t> in functions "
"named <t>_<name>."),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
}
cstring_free (pfx);
return FALSE;
}
}
}
else if (ctype_isManifestBool (ct))
{
if (context_canAccessBool ())
{
;
}
else
{
if (context_getFlag (FLG_ACCESSCZECH)
|| context_getFlag (FLG_ACCESSCZECHOSLOVAK))
{
if (!uentry_isVar (ue))
{
tid = usymtab_getTypeId (context_getBoolName ());
uentry_addAccessType (ue, tid);
}
}
else
{
if (report)
{
if (llgenhinterror
(czechflag,
message
("%s %q name violates Czech naming "
"convention. Type bool is not accessible.",
uentry_ekindName (ue),
uentry_getName (ue)),
cstring_makeLiteral
("Use +accessczech to allow access to "
"type <t> in functions named <t>_<name>."),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
}
cstring_free (pfx);
return FALSE;
}
}
}
else
{
;
}
}
else
{
if (cstring_equalLit (pfx, "int")
|| cstring_equalLit (pfx, "char")
|| cstring_equalLit (pfx, "short")
|| cstring_equalLit (pfx, "long")
|| cstring_equalLit (pfx, "unsigned")
|| cstring_equalLit (pfx, "signed")
|| cstring_equalLit (pfx, "float")
|| cstring_equalLit (pfx, "double"))
{
; /* built-in types */
}
else
{
/* no accessible types, could match module name */
if (cstring_equal (pfx, context_moduleName ()))
{
;
}
else
{
if (report)
{
if (optgenerror2
(czechflag, FLG_NAMECHECKS,
message
("%s %q name violates Czech naming convention. "
"Czech prefix %s is not the name of a type.",
uentry_ekindName (ue),
uentry_getName (ue),
pfx),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
}
cstring_free (pfx);
return FALSE;
}
}
}
}
cstring_free (pfx);
}
return TRUE;
}
static bool checkSlovakName (uentry ue, flagcode slovakflag, bool report)
{
if (uentry_isDatatype (ue))
{
/*
** Slovak datatypes may not have uppercase letters.
*/
if (context_getFlag (FLG_SLOVAK))
{
cstring name = uentry_rawName (ue);
cstring_chars (name, c)
{
if (isupper ((unsigned char) c))
{
if (report)
{
if (optgenerror2
(FLG_SLOVAKTYPES, FLG_NAMECHECKS,
message
("%s %q name violates Slovak naming convention. "
"Slovak datatype names should not use uppercase "
"letters.",
uentry_ekindName (ue),
uentry_getName (ue)),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
}
return FALSE;
}
} end_cstring_chars;
}
}
else
{
typeIdSet acc = context_fileAccessTypes ();
cstring pfx = slovakPrefix (uentry_rawName (ue));
if (cstring_isEmpty (pfx))
{
if (typeIdSet_isEmpty (acc))
{
; /* okay - should not be slovak name */
}
else
{
if (uentry_isFunction (ue))
{
if (report)
{
if (optgenerror2
(slovakflag, FLG_NAMECHECKS,
message ("%s %q name is not consistent with Slovak "
"naming convention. Accessible types: %q",
uentry_ekindName (ue),
uentry_getName (ue),
typeIdSet_unparse (acc)),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
}
cstring_free (pfx);
return FALSE;
}
else
{
ctype ct = uentry_getType (ue);
if (ctype_isUA (ct))
{
if (report)
{
if (optgenerror2
(slovakflag, FLG_NAMECHECKS,
message ("%s %q name is not consistent with "
"Slovak naming convention. The "
"name should begin with %s followed "
"by an uppercase letter.",
uentry_ekindName (ue),
uentry_getName (ue),
ctype_unparse (ct)),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
}
cstring_free (pfx);
return FALSE;
}
}
}
}
else
{
if (usymtab_existsTypeEither (pfx))
{
ctype ct = usymtab_lookupAbstractType (pfx);
typeId tid;
if (ctype_isUA (ct))
{
tid = ctype_typeId (ct);
if (ctype_isUser (ct) || context_hasAccess (tid))
{
;
}
else
{
if (context_getFlag (FLG_ACCESSSLOVAK)
|| context_getFlag (FLG_ACCESSCZECHOSLOVAK))
{
if (!uentry_isVar (ue))
{
uentry_addAccessType (ue, tid);
}
}
else
{
if (report)
{
if (llgenhinterror
(slovakflag,
message
("%s %q name violates Slovak naming "
"convention. Slovak prefix %s names "
"an abstract type that is not accessible.",
uentry_ekindName (ue),
uentry_getName (ue),
pfx),
cstring_makeLiteral
("Use +accessslovak to allow access to "
"type <t> in functions named <t>_<name>."),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
}
cstring_free (pfx);
return FALSE;
}
}
}
else if (ctype_isManifestBool (ct))
{
if (context_canAccessBool ())
{
;
}
else
{
if (context_getFlag (FLG_ACCESSSLOVAK)
|| context_getFlag (FLG_ACCESSCZECHOSLOVAK))
{
if (!uentry_isVar (ue))
{
tid = usymtab_getTypeId (context_getBoolName ());
uentry_addAccessType (ue, tid);
}
}
else
{
if (report)
{
if (llgenhinterror
(slovakflag,
message
("%s %q name violates Slovak naming convention. "
"Type bool is not accessible.",
uentry_ekindName (ue),
uentry_getName (ue)),
cstring_makeLiteral
("Use +accessslovak to allow access to "
"type <t> in functions named <t>_<name>."),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
}
cstring_free (pfx);
return FALSE;
}
}
}
else
{
;
}
}
else
{
if (cstring_equalLit (pfx, "int")
|| cstring_equalLit (pfx, "char")
|| cstring_equalLit (pfx, "short")
|| cstring_equalLit (pfx, "long")
|| cstring_equalLit (pfx, "unsigned")
|| cstring_equalLit (pfx, "signed")
|| cstring_equalLit (pfx, "float")
|| cstring_equalLit (pfx, "double"))
{
; /* built-in types */
}
else
{
/* no accessible types, could match module name */
if (cstring_equal (pfx, context_moduleName ()))
{
;
}
else
{
if (report)
{
if (optgenerror2
(slovakflag, FLG_NAMECHECKS,
message
("%s %q name violates Slovak naming convention. "
"Slovak prefix %s is not the name of a type.",
uentry_ekindName (ue),
uentry_getName (ue),
pfx),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
}
cstring_free (pfx);
return FALSE;
}
}
}
}
cstring_free (pfx);
}
return TRUE;
}
void
checkExternalName (uentry ue)
{
if (!uentry_isStatic (ue) && uentry_hasName (ue))
{
checkNationalName (ue);
}
else
{
;
}
}
void
checkLocalName (/*@unused@*/ uentry ue)
{
/*
** No local checks (yet)
*/
return;
}
void
checkFileScopeName (/*@unused@*/ uentry ue)
{
/*
** No file scope checks (yet)
*/
/* add a file scope naming convention policy? */
return;
}
/*
** Checks a name used by user source is not reserved by ANSI
** (or for future library functions).
**
** The restrictions are described in X3.159-1989: 4.13
*/
/*@constant int NRESERVEDNAMES; @*/
# define NRESERVEDNAMES 201
/*@constant int NCPPNAMES@*/
# define NCPPNAMES 39
void
checkCppName (uentry ue)
{
cstring name = uentry_observeRealName (ue);
static ob_mstring cppNames[NCPPNAMES] =
{
"and", "and_eq", "asm",
"bitand", "bitor", "bool", /* gasp: "bool", is special for splint */
"catch", "class", "compl", "const_class",
"delete", "dynamic_cast", "false", "friend",
"inline", "mutable", "namespace", "new",
"not", "not_eq",
"operator", "or", "or_eq", "overload",
"private", "protected", "public",
"reinterpret_cast", "static_cast",
"template", "this", "throw", "true", "try",
"typeid", "using", "virtual", "xor", "xor_eq"
} ;
if (cstring_isDefined (cstring_bsearch (name, &cppNames[0],
NCPPNAMES)))
{
if (optgenerror2
(FLG_CPPNAMES, FLG_NAMECHECKS,
message ("Name %s is a keyword or reserved word in C++",
name),
uentry_whereLast (ue)))
{
uentry_setHasNameError (ue);
}
}
}
void
checkAnsiName (uentry ue)
{
bool hasError = FALSE;
cstring name = uentry_observeRealName (ue);
size_t length = cstring_length (name);
char fchar = (length >= 1) ? cstring_firstChar (name) : '\0';
char schar = (length >= 2) ? cstring_secondChar (name) : '\0';
char tchar = (length >= 3) ? cstring_getChar (name, 3) : '\0';
char rchar = (length >= 4) ? cstring_getChar (name, 4) : '\0';
/*
** reservedNames
** taken from Linden, "Expert C Programming", p. 126-8.
** invariant: must be sorted (case-insensitive, lexicographically)
** must end with NULL
*/
static ob_mstring reservedNames[NRESERVEDNAMES] =
{
# include "reservedNames.nf"
} ;
# if 0
/*
** This code is for checking reservedNames.nf
*/
{
int i = 0;
char *lastname = NULL;
char *name;
while ((name = reservedNames[i]) != NULL)
{
llassertprint (lastname == NULL
|| strcmp (name, lastname) > 0,
("%s / %s", lastname, name));
lastname = name;
i++;
}
nreservedNames = i - 1;
}
# endif
if (fileloc_isSystemFile (uentry_whereLast (ue)) || fileloc_isBuiltin (uentry_whereLast (ue)))
{
return; /* no errors for system files */
}
if (cstring_isDefined (cstring_bsearch (name, &reservedNames[0],
NRESERVEDNAMES)))
{
hasError |= optgenerror2
(FLG_ISORESERVED, FLG_NAMECHECKS,
message ("Name %s is reserved for the standard library",
name),
uentry_whereLast (ue));
}
if (uentry_isFileStatic (ue) || uentry_isVisibleExternally (ue) || uentry_isAnyTag (ue)
|| context_getFlag (FLG_ISORESERVEDLOCAL))
{
if (fchar == '_')
{
hasError |= optgenerror2
(FLG_ISORESERVED, FLG_NAMECHECKS,
message
("Name %s is in the implementation name space (any identifier "
"beginning with underscore)",
name),
uentry_whereLast (ue));
}
}
else
{
/*
** ISO 7.1.3:
** - All identifiers that begin with an underscore and either an uppercase
** letter or another underscore are always reserved for any use.
*/
if (fchar == '_'
&& (schar == '_' || isupper ((int) schar)))
{
hasError |= optgenerror2
(FLG_ISORESERVED, FLG_NAMECHECKS,
message
("Name %s is in the implementation name space (any identifier "
"beginning with underscore and either an uppercase letter or "
"another underscore is always reserved for any use)",
name),
uentry_whereLast (ue));
}
}
/*
** 4.13.1 Errors <errno.h>
**
** Macros that begin with E and a digit or E and an uppercase letter ...
*/
if (fchar == 'E' && (isdigit ((int) schar)
|| isupper ((int) schar)))
{
hasError |= optgenerror2
(FLG_ISORESERVED, FLG_NAMECHECKS,
message
("Name %s is reserved for future library extensions. "
"Macros beginning with E and a digit or uppercase letter "
"may be added to <errno.h>. (ISO99:7.26.3)",
name),
uentry_whereLast (ue));
}
/*
** 4.13.3 Localization <locale.h>
**
** Macros that begin with LC_ and an uppercase letter ...
*/
if (length >= 4
&& ((fchar == 'L')
&& (schar == 'C')
&& (tchar == '_'))
&& (isupper ((int) rchar)))
{
hasError |= optgenerror2
(FLG_ISORESERVED, FLG_NAMECHECKS,
message
("Name %s is reserved for future library extensions. "
"Macros beginning with \"LC_\" and an uppercase letter may "
"be added to <locale.h>. (ISO99:7.26.5)",
name),
uentry_whereLast (ue));
}
/*
** 4.13.5 Signal Handling <signal.h>
**
** Macros that begin with either SIG or SIG_ and an uppercase letter or...
*/
if (fchar == 'S' && schar == 'I' && tchar == 'G'
&& ((rchar == '_' && ((length >= 5
&& isupper ((int) cstring_getChar (name, 5)))))
|| (isupper ((int) rchar))))
{
hasError |= optgenerror2
(FLG_ISORESERVED, FLG_NAMECHECKS,
message
("Name %s is reserved for future library extensions. "
"Macros that begin with SIG and an uppercase letter or SIG_ "
"and an uppercase letter may be added to "
"<signal.h>. (ISO99:7.14)",
name),
uentry_whereLast (ue));
}
/*
** evans - 2002-12-16: added this check (even though it is not required by ISO)
*/
if (fchar == 'S' && schar == 'A' && tchar == '_')
{
hasError |= optgenerror2
(FLG_ISORESERVED, FLG_NAMECHECKS,
message
("Name %s may be defined as a macro by Linux library. "
"It is not research by the ISO specification, but may produce conflicts on some systems.",
name),
uentry_whereLast (ue));
}
if ((uentry_isVisibleExternally (ue) && !uentry_isAnyTag (ue))
|| context_getFlag (FLG_ISORESERVEDLOCAL))
{
flagcode flg;
DPRINTF (("Okay...: %s", uentry_unparse (ue)));
if (uentry_isVisibleExternally (ue) && !uentry_isAnyTag (ue))
{
flg = FLG_ISORESERVED;
}
else
{
flg = FLG_ISORESERVEDLOCAL;
}
DPRINTF (("ue: %s", uentry_unparseFull (ue)));
/*
** These restrictions only apply to identifiers with global linkage.
*/
/*
** 4.13.2 Character Handling <ctype.h>
**
** Function names that begin with either "is" or "to" and a lowercase letter ...
*/
if (((fchar == 'i' && schar == 's')
|| (fchar == 't' && schar == 'o'))
&& (islower ((int) tchar)))
{
hasError |= optgenerror2
(flg, FLG_NAMECHECKS,
message
("Name %s is reserved for future library extensions. "
"Functions beginning with \"is\" or \"to\" and a lowercase "
"letter may be added to <ctype.h>. (ISO99:7.26.2)",
name),
uentry_whereLast (ue));
DPRINTF (("Externally visible: %s / %s",
uentry_unparseFull (ue),
bool_unparse (uentry_isVisibleExternally (ue))));
}
/*
** 4.13.4 Mathematics <math.h>
**
** The names of all existing functions declared in the <math.h> header,
** suffixed with f or l...
*/
DPRINTF (("Check name: %s", name));
if ((cstring_lastChar (name) == 'f' || cstring_lastChar (name) == 'l')
&&
(((length == 4)
&& ((cstring_equalPrefixLit (name, "cos") ||
cstring_equalPrefixLit (name, "sin") ||
cstring_equalPrefixLit (name, "tan") ||
cstring_equalPrefixLit (name, "exp") ||
cstring_equalPrefixLit (name, "log") ||
cstring_equalPrefixLit (name, "pow"))))
|| ((length == 5)
&& ((cstring_equalPrefixLit (name, "acos") ||
cstring_equalPrefixLit (name, "asin") ||
cstring_equalPrefixLit (name, "atan") ||
cstring_equalPrefixLit (name, "cosh") ||
cstring_equalPrefixLit (name, "sinh") ||
cstring_equalPrefixLit (name, "sqrt") ||
cstring_equalPrefixLit (name, "ceil") ||
cstring_equalPrefixLit (name, "fabs") ||
cstring_equalPrefixLit (name, "fmod") ||
cstring_equalPrefixLit (name, "tanh") ||
cstring_equalPrefixLit (name, "modf"))))
|| ((length == 6)
&& ((cstring_equalPrefixLit (name, "atan2") ||
cstring_equalPrefixLit (name, "floor") ||
cstring_equalPrefixLit (name, "frexp") ||
cstring_equalPrefixLit (name, "ldexp") ||
cstring_equalPrefixLit (name, "log10"))))))
{
hasError |= optgenerror2
(flg, FLG_NAMECHECKS,
message
("Name %s is reserved for future library extensions. "
"The names of all existing functions in <math.h> suffixed "
"with 'f' or 'l' may be added to <math.h>. (ISO:7.26.1)",
name),
uentry_whereLast (ue));
}
/*
** 4.13.6 Input/Output <stdio.h>
**
** (nothing to check)
*/
/*
** 4.13.7 General Utilities <stdlib.h>
**
** Functions names that begin with str and a lowercase letter may be added to <stdlib.h>.
*/
if (fchar == 's' && schar == 't' && tchar == 'r'
&& (islower ((int) rchar)))
{
hasError |= optgenerror2
(flg, FLG_NAMECHECKS,
message
("Name %s is reserved for future library extensions. "
"Functions that begin with \"str\" and a lowercase letter "
"may be added to <stdlib.h> or <string.h>. (ISO99:7.26.9)",
name),
uentry_whereLast (ue));
}
/*
** 4.13.8 String Handling <string.h>
**
** Function names that begin with str, mem, or wcs and a lowercase letter ...
**
** (Note: already checked "str" above.)
*/
if (((fchar == 'm' && schar == 'e' && tchar == 'm')
|| (fchar == 'w' && schar == 'c' && tchar == 's'))
&& (islower ((int) rchar)))
{
hasError |= optgenerror2
(flg, FLG_NAMECHECKS,
message
("Name %s is reserved for future library extensions. "
"Functions that begin with \"mem\" or \"wcs\" and a "
"lowercase letter may be added to <string.h>. (ISO:7.26.11)",
name),
uentry_whereLast (ue));
}
}
else
{
DPRINTF (("Not checked: [%s] %s", bool_unparse (uentry_isVisibleExternally (ue)),
uentry_unparseFull (ue)));
}
if (hasError)
{
uentry_setHasNameError (ue);
}
}
void checkParamNames (uentry ue)
{
cstring fpfx = context_getString (FLG_DECLPARAMPREFIX);
bool noformal = context_getFlag (FLG_DECLPARAMNAME);
llassert (uentry_isFunction (ue));
if (cstring_isDefined (fpfx) || noformal)
{
uentryList params = uentry_getParams (ue);
uentryList_elements (params, p)
{
if (uentry_hasName (p))
{
if (noformal && !cstring_isDefined (fpfx))
{
if (optgenerror2
(FLG_DECLPARAMNAME, FLG_NAMECHECKS,
message ("Declaration parameter has name: %q",
uentry_getName (p)),
uentry_whereLast (p)))
{
uentry_setHasNameError (p);
}
}
else
{
cstring pname = uentry_observeRealName (p);
if (!cstring_equalPrefix (pname, fpfx))
{
if (context_getFlag (FLG_NAMECHECKS))
{
if (optgenerror2
(FLG_DECLPARAMPREFIX, FLG_NAMECHECKS,
message ("Declaration parameter name %s does not begin "
"with protoparamprefix (%s)",
pname, fpfx),
uentry_whereLast (p)))
{
uentry_setHasNameError (p);
}
}
}
}
}
} end_uentryList_elements ;
}
}
/* not yet checked: POSIX p. 527 - applications should not declare any symbols that end _MAX */
syntax highlighted by Code2HTML, v. 0.9.1