2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
28 # include "lclintMacros.nf"
30 # include "nameChecks.h"
32 static bool checkCzechName (uentry p_ue, flagcode p_czechflag, bool p_report)
33 /*@modifies p_ue, g_msgstream@*/ ;
35 static bool checkSlovakName (uentry p_ue, flagcode p_slovakflag, bool p_report)
36 /*@modifies p_ue, g_msgstream@*/ ;
38 static cstring czechPrefix (cstring name)
40 return (cstring_beforeChar (name, '_'));
43 static cstring slovakPrefix (cstring name)
47 cstring_chars (name, c)
49 if (isupper ((unsigned char) c))
51 return (cstring_prefix (name, i));
56 return cstring_undefined;
59 static flagcode excludeCodes [] =
61 FLG_MACROVARPREFIXEXCLUDE,
63 FLG_ENUMPREFIXEXCLUDE,
64 FLG_FILESTATICPREFIXEXCLUDE,
65 FLG_GLOBPREFIXEXCLUDE,
66 FLG_TYPEPREFIXEXCLUDE,
67 FLG_EXTERNALPREFIXEXCLUDE,
68 FLG_UNCHECKEDMACROPREFIXEXCLUDE,
69 FLG_LOCALPREFIXEXCLUDE,
73 /*@iter excludeFlagCodes (yield flagcode code);@*/
74 # define excludeFlagCodes(m_c) \
75 { int m_i = 0; while (flagcode_isValid (excludeCodes[m_i])) \
76 { flagcode m_c = excludeCodes[m_i]; m_i++;
78 # define end_excludeFlagCodes }}
80 static bool matchPrefixChar (int nc, int pc)
101 return !islower (nc);
104 case PFX_ANYLETTERDIGIT:
105 return (isdigit (nc) || isalpha (nc));
106 default: return FALSE;
113 static bool matchPrefix (cstring name, cstring prefix)
115 if (cstring_isUndefined (name)
116 || cstring_isUndefined (prefix))
122 int namelen = cstring_length (name);
123 int last = (int) '\0';
126 cstring_chars (prefix, pc)
137 nc = (int) cstring_getChar (name, n);
139 if (!matchPrefixChar (nc, last))
152 if ((cstring_length (prefix) >= n + 1)
153 && cstring_getChar (prefix, n + 1) == '*')
163 nc = (int) cstring_getChar (name, n);
165 if (!matchPrefixChar (nc, (int) pc))
180 namespaceExcluded (flagcode code) /*@*/
184 case FLG_MACROVARPREFIXEXCLUDE:
185 return (FLG_MACROVARPREFIX);
186 case FLG_TAGPREFIXEXCLUDE:
187 return (FLG_TAGPREFIX);
188 case FLG_ENUMPREFIXEXCLUDE:
189 return (FLG_ENUMPREFIX);
190 case FLG_FILESTATICPREFIXEXCLUDE:
191 return (FLG_FILESTATICPREFIX);
192 case FLG_GLOBPREFIXEXCLUDE:
193 return (FLG_GLOBPREFIX);
194 case FLG_TYPEPREFIXEXCLUDE:
195 return (FLG_TYPEPREFIX);
196 case FLG_EXTERNALPREFIXEXCLUDE:
197 return (FLG_EXTERNALPREFIX);
198 case FLG_UNCHECKEDMACROPREFIXEXCLUDE:
199 return (FLG_UNCHECKEDMACROPREFIX);
200 case FLG_LOCALPREFIXEXCLUDE:
201 return (FLG_LOCALPREFIX);
202 case FLG_ITERPREFIXEXCLUDE:
203 return (FLG_ITERPREFIX);
204 case FLG_CONSTPREFIXEXCLUDE:
205 return (FLG_CONSTPREFIX);
210 static /*@observer@*/ cstring
211 namespaceName (flagcode flag) /*@*/
215 case FLG_MACROVARPREFIX:
216 return cstring_makeLiteralTemp ("macro variable");
218 return cstring_makeLiteralTemp ("tag");
220 return cstring_makeLiteralTemp ("enum member");
222 return cstring_makeLiteralTemp ("user-defined type");
223 case FLG_FILESTATICPREFIX:
224 return cstring_makeLiteralTemp ("file static");
226 return cstring_makeLiteralTemp ("global variable");
227 case FLG_EXTERNALPREFIX:
228 return cstring_makeLiteralTemp ("external");
229 case FLG_LOCALPREFIX:
230 return cstring_makeLiteralTemp ("local variable");
231 case FLG_CONSTPREFIX:
232 return cstring_makeLiteralTemp ("constant");
234 return cstring_makeLiteralTemp ("iter");
235 case FLG_UNCHECKEDMACROPREFIX:
236 return cstring_makeLiteralTemp ("unchecked macro");
242 checkPrefix (uentry ue)
244 cstring name = cstring_undefined;
247 if (uentry_isExpandedMacro (ue))
249 flag = FLG_UNCHECKEDMACROPREFIX;
251 else if (uentry_isAnyTag (ue))
253 flag = FLG_TAGPREFIX;
255 else if (uentry_isEnumConstant (ue))
257 flag = FLG_ENUMPREFIX;
259 else if (uentry_isDatatype (ue))
261 flag = FLG_TYPEPREFIX;
263 else if (uentry_isFileStatic (ue))
265 flag = FLG_FILESTATICPREFIX;
267 else if (uentry_isGlobal (ue))
269 flag = FLG_GLOBPREFIX;
271 else if (uentry_isVariable (ue))
273 if (uentry_isRefParam (ue))
275 return; /* already checked param */
278 if (context_inMacro ())
280 if (uentry_isAnyParam (ue))
282 if (uentry_isYield (ue))
284 flag = FLG_MACROVARPREFIX;
288 flag = FLG_LOCALPREFIX;
293 flag = FLG_MACROVARPREFIX;
298 flag = FLG_LOCALPREFIX;
301 else if (uentry_isConstant (ue))
303 flag = FLG_CONSTPREFIX;
305 else if (uentry_isIter (ue))
307 flag = FLG_ITERPREFIX;
309 else if (uentry_isExported (ue))
311 flag = FLG_EXTERNALPREFIX;
315 llcontbug (message ("What is it: %q", uentry_unparseFull (ue)));
319 if (flag == FLG_TYPEPREFIX || flag == FLG_GLOBPREFIX
320 || flag == FLG_ENUMPREFIX || flag == FLG_CONSTPREFIX)
322 if (flag == FLG_ENUMPREFIX)
324 if (!context_getFlag (flag))
326 flag = FLG_CONSTPREFIX;
330 if (!context_getFlag (flag))
332 flag = FLG_EXTERNALPREFIX;
336 if (context_getFlag (flag))
338 name = uentry_getName (ue);
341 if (!matchPrefix (name, context_getString (flag)))
345 message ("%s %s name is not consistent with %s "
346 "namespace prefix \"%s\"",
347 uentry_ekindName (ue),
349 namespaceName (flag),
350 context_getString (flag)),
351 uentry_whereLast (ue)))
353 uentry_setHasNameError (ue);
358 excludeFlagCodes (code)
362 if (context_getFlag (code))
364 /*@-loopswitchbreak@*/
367 case FLG_MACROVARPREFIXEXCLUDE:
368 check = (flag != FLG_MACROVARPREFIX);
370 case FLG_TAGPREFIXEXCLUDE:
371 check = (flag != FLG_TAGPREFIX);
373 case FLG_ENUMPREFIXEXCLUDE:
374 check = (flag != FLG_ENUMPREFIX);
376 case FLG_FILESTATICPREFIXEXCLUDE:
377 check = (flag != FLG_FILESTATICPREFIX);
379 case FLG_GLOBPREFIXEXCLUDE:
380 check = (flag != FLG_GLOBPREFIX);
382 case FLG_TYPEPREFIXEXCLUDE:
383 check = (flag != FLG_TYPEPREFIX);
385 case FLG_EXTERNALPREFIXEXCLUDE:
386 check = (flag != FLG_EXTERNALPREFIX
387 && flag != FLG_GLOBPREFIX
388 && flag != FLG_TYPEPREFIX
389 && flag != FLG_UNCHECKEDMACROPREFIX);
391 case FLG_UNCHECKEDMACROPREFIXEXCLUDE:
392 check = (flag != FLG_UNCHECKEDMACROPREFIX);
394 case FLG_LOCALPREFIXEXCLUDE:
395 check = (flag != FLG_LOCALPREFIX);
397 case FLG_CONSTPREFIXEXCLUDE:
398 check = (flag != FLG_CONSTPREFIX);
400 case FLG_ITERPREFIXEXCLUDE:
401 check = (flag != FLG_ITERPREFIX);
405 /*@=loopswitchbreak@*/
409 flagcode rcode = namespaceExcluded (code);
410 cstring pstring = context_getString (rcode);
412 if (cstring_isDefined (pstring))
414 if (cstring_isUndefined (name))
416 name = uentry_getName (ue);
419 if (matchPrefix (name, context_getString (rcode)))
424 ("%s %s name is not a %s (it is a %s), "
425 "but matches the %s "
426 "namespace prefix \"%s\"",
427 uentry_ekindName (ue),
429 namespaceName (rcode),
430 namespaceName (flag),
431 namespaceName (rcode),
432 context_getString (rcode)),
433 uentry_whereLast (ue)))
435 uentry_setHasNameError (ue);
441 } end_excludeFlagCodes ;
447 checkNationalName (uentry ue)
451 flagcode czechoslovakflag;
455 if (uentry_isFunction (ue)
456 || uentry_isIter (ue)
457 || uentry_isEndIter (ue))
459 czechflag = FLG_CZECHFUNCTIONS;
460 slovakflag = FLG_SLOVAKFUNCTIONS;
461 czechoslovakflag = FLG_CZECHOSLOVAKFUNCTIONS;
463 else if (uentry_isExpandedMacro (ue))
465 czechflag = FLG_CZECHMACROS;
466 slovakflag = FLG_SLOVAKMACROS;
467 czechoslovakflag = FLG_CZECHOSLOVAKMACROS;
469 else if (uentry_isVariable (ue))
471 if (uentry_isGlobal (ue) && context_getFlag (FLG_GLOBPREFIX))
473 /* prefix checks supercede national naming checks */
477 czechflag = FLG_CZECHVARS;
478 slovakflag = FLG_SLOVAKVARS;
479 czechoslovakflag = FLG_CZECHOSLOVAKVARS;
481 else if (uentry_isConstant (ue))
483 if (uentry_isGlobal (ue) && context_getFlag (FLG_CONSTPREFIX))
485 /* prefix checks supercede national naming checks */
489 czechflag = FLG_CZECHCONSTANTS;
490 slovakflag = FLG_SLOVAKCONSTANTS;
491 czechoslovakflag = FLG_CZECHOSLOVAKCONSTANTS;
495 if (uentry_isAnyTag (ue) || uentry_isEnumConstant (ue))
497 return; /* no errors for tags */
500 llassert (uentry_isDatatype (ue));
502 czechflag = FLG_CZECHTYPES;
503 slovakflag = FLG_SLOVAKTYPES;
504 czechoslovakflag = FLG_CZECHOSLOVAKTYPES;
507 gcf = context_getFlag (czechflag);
508 gsf = context_getFlag (slovakflag);
509 gcsf = context_getFlag (czechoslovakflag);
511 if (gcf || (uentry_isFunction (ue)
512 && context_getFlag (FLG_ACCESSCZECH)))
514 (void) checkCzechName (ue, czechflag, gcf);
517 if (gsf || (uentry_isFunction (ue)
518 && context_getFlag (FLG_ACCESSSLOVAK)))
520 (void) checkSlovakName (ue, slovakflag, gsf);
525 if (uentry_isDatatype (ue))
527 /* May not have either _'s or uppercase letter */
528 cstring name = uentry_rawName (ue);
531 cstring_chars (name, c)
533 if (isupper ((unsigned char) c))
536 (FLG_CZECHOSLOVAKTYPES,
538 ("%s %q name violates Czechoslovak naming convention. "
539 "Czechoslovak datatype names should not use uppercase "
541 uentry_ekindName (ue),
542 uentry_getName (ue)),
543 uentry_whereLast (ue)))
545 uentry_setHasNameError (ue);
550 if (c == '_' && charno != 2 && charno != 3)
553 (FLG_CZECHOSLOVAKTYPES,
554 message ("%s %q name violates Czechoslovak naming "
555 "convention. Czechoslovak datatype names "
556 "should not use the _ charater.",
557 uentry_ekindName (ue),
558 uentry_getName (ue)),
559 uentry_whereLast (ue)))
561 uentry_setHasNameError (ue);
571 bool okay = checkCzechName (ue, czechflag, FALSE);
573 /* still need to call, to set access */
574 okay |= checkSlovakName (ue, slovakflag, FALSE);
580 message ("%s %q name is not consistent with Czechoslovak "
581 "naming convention.",
582 uentry_ekindName (ue),
583 uentry_getName (ue)),
584 uentry_whereLast (ue)))
586 uentry_setHasNameError (ue);
593 static bool checkCzechName (uentry ue, flagcode czechflag, bool report)
595 if (uentry_isDatatype (ue))
598 ** Czech datatypes may not have _'s, except if there are 1 or 2 characters
599 ** before the only _.
602 cstring name = uentry_rawName (ue);
605 cstring_chars (name, c)
607 if (c == '_' && charno != 2 && charno != 3)
614 ("%s %q name violates Czech naming convention. "
615 "Czech datatype names should not use the _ charater.",
616 uentry_ekindName (ue),
617 uentry_getName (ue)),
618 uentry_whereLast (ue)))
620 uentry_setHasNameError (ue);
632 typeIdSet acc = context_fileAccessTypes ();
633 cstring pfx = czechPrefix (uentry_rawName (ue));
635 if (cstring_isEmpty (pfx))
637 if (uentry_isVariable (ue) || uentry_isConstant (ue))
639 ctype ct = uentry_getType (ue);
641 if (ctype_isAbstract (ct)
642 && context_hasAccess (ctype_typeId (ct)))
648 message ("%s %q name is not consistent with Czech "
649 "naming convention. The name should "
651 uentry_ekindName (ue),
654 uentry_whereLast (ue)))
656 uentry_setHasNameError (ue);
664 else if (uentry_isFunction (ue) || uentry_isIter (ue))
666 if (typeIdSet_isEmpty (acc))
668 ; /* okay - should not be czech name */
676 message ("%s %q name is not consistent with Czech "
677 "naming convention. Accessible types: %q",
678 uentry_ekindName (ue),
680 typeIdSet_unparse (acc)),
681 uentry_whereLast (ue)))
683 uentry_setHasNameError (ue);
698 if (usymtab_existsTypeEither (pfx))
700 ctype ct = usymtab_lookupAbstractType (pfx);
705 tid = ctype_typeId (ct);
707 if (ctype_isUser (ct) || context_hasAccess (tid))
713 if (context_getFlag (FLG_ACCESSCZECH)
714 || context_getFlag (FLG_ACCESSCZECHOSLOVAK))
716 if (!uentry_isVar (ue))
718 uentry_addAccessType (ue, tid);
728 ("%s %q name violates Czech naming "
729 "convention. Czech prefix %s names "
730 "an abstract type that is "
732 uentry_ekindName (ue),
736 ("Use +accessczech to allow access to "
737 "type <t> in functions "
738 "named <t>_<name>."),
739 uentry_whereLast (ue)))
741 uentry_setHasNameError (ue);
750 else if (ctype_isManifestBool (ct))
752 if (context_canAccessBool ())
758 if (context_getFlag (FLG_ACCESSCZECH)
759 || context_getFlag (FLG_ACCESSCZECHOSLOVAK))
761 if (!uentry_isVar (ue))
763 tid = usymtab_getTypeId (context_getBoolName ());
764 uentry_addAccessType (ue, tid);
774 ("%s %q name violates Czech naming "
775 "convention. Type bool is not accessible.",
776 uentry_ekindName (ue),
777 uentry_getName (ue)),
779 ("Use +accessczech to allow access to "
780 "type <t> in functions named <t>_<name>."),
781 uentry_whereLast (ue)))
783 uentry_setHasNameError (ue);
799 if (cstring_equalLit (pfx, "int")
800 || cstring_equalLit (pfx, "char")
801 || cstring_equalLit (pfx, "short")
802 || cstring_equalLit (pfx, "long")
803 || cstring_equalLit (pfx, "unsigned")
804 || cstring_equalLit (pfx, "signed")
805 || cstring_equalLit (pfx, "float")
806 || cstring_equalLit (pfx, "double"))
808 ; /* built-in types */
812 /* no accessible types, could match module name */
814 if (cstring_equal (pfx, context_moduleName ()))
825 ("%s %q name violates Czech naming convention. "
826 "Czech prefix %s is not the name of a type.",
827 uentry_ekindName (ue),
830 uentry_whereLast (ue)))
832 uentry_setHasNameError (ue);
848 static bool checkSlovakName (uentry ue, flagcode slovakflag, bool report)
850 if (uentry_isDatatype (ue))
853 ** Slovak datatypes may not have uppercase letters.
856 if (context_getFlag (FLG_SLOVAK))
858 cstring name = uentry_rawName (ue);
860 cstring_chars (name, c)
862 if (isupper ((unsigned char) c))
869 ("%s %q name violates Slovak naming convention. "
870 "Slovak datatype names should not use uppercase "
872 uentry_ekindName (ue),
873 uentry_getName (ue)),
874 uentry_whereLast (ue)))
876 uentry_setHasNameError (ue);
886 typeIdSet acc = context_fileAccessTypes ();
887 cstring pfx = slovakPrefix (uentry_rawName (ue));
889 if (cstring_isEmpty (pfx))
891 if (typeIdSet_isEmpty (acc))
893 ; /* okay - should not be slovak name */
897 if (uentry_isFunction (ue))
903 message ("%s %q name is not consistent with Slovak "
904 "naming convention. Accessible types: %q",
905 uentry_ekindName (ue),
907 typeIdSet_unparse (acc)),
908 uentry_whereLast (ue)))
910 uentry_setHasNameError (ue);
919 ctype ct = uentry_getType (ue);
927 message ("%s %q name is not consistent with "
928 "Slovak naming convention. The "
929 "name should begin with %s followed "
930 "by an uppercase letter.",
931 uentry_ekindName (ue),
934 uentry_whereLast (ue)))
936 uentry_setHasNameError (ue);
948 if (usymtab_existsTypeEither (pfx))
950 ctype ct = usymtab_lookupAbstractType (pfx);
955 tid = ctype_typeId (ct);
957 if (ctype_isUser (ct) || context_hasAccess (tid))
963 if (context_getFlag (FLG_ACCESSSLOVAK)
964 || context_getFlag (FLG_ACCESSCZECHOSLOVAK))
966 if (!uentry_isVar (ue))
968 uentry_addAccessType (ue, tid);
978 ("%s %q name violates Slovak naming "
979 "convention. Slovak prefix %s names "
980 "an abstract type that is not accessible.",
981 uentry_ekindName (ue),
985 ("Use +accessslovak to allow access to "
986 "type <t> in functions named <t>_<name>."),
987 uentry_whereLast (ue)))
989 uentry_setHasNameError (ue);
998 else if (ctype_isManifestBool (ct))
1000 if (context_canAccessBool ())
1006 if (context_getFlag (FLG_ACCESSSLOVAK)
1007 || context_getFlag (FLG_ACCESSCZECHOSLOVAK))
1009 if (!uentry_isVar (ue))
1011 tid = usymtab_getTypeId (context_getBoolName ());
1012 uentry_addAccessType (ue, tid);
1022 ("%s %q name violates Slovak naming convention. "
1023 "Type bool is not accessible.",
1024 uentry_ekindName (ue),
1025 uentry_getName (ue)),
1027 ("Use +accessslovak to allow access to "
1028 "type <t> in functions named <t>_<name>."),
1029 uentry_whereLast (ue)))
1031 uentry_setHasNameError (ue);
1047 if (cstring_equalLit (pfx, "int")
1048 || cstring_equalLit (pfx, "char")
1049 || cstring_equalLit (pfx, "short")
1050 || cstring_equalLit (pfx, "long")
1051 || cstring_equalLit (pfx, "unsigned")
1052 || cstring_equalLit (pfx, "signed")
1053 || cstring_equalLit (pfx, "float")
1054 || cstring_equalLit (pfx, "double"))
1056 ; /* built-in types */
1060 /* no accessible types, could match module name */
1062 if (cstring_equal (pfx, context_moduleName ()))
1073 ("%s %q name violates Slovak naming convention. "
1074 "Slovak prefix %s is not the name of a type.",
1075 uentry_ekindName (ue),
1076 uentry_getName (ue),
1078 uentry_whereLast (ue)))
1080 uentry_setHasNameError (ue);
1098 checkGlobalName (uentry ue)
1100 if (!uentry_isStatic (ue) && uentry_hasName (ue))
1102 checkNationalName (ue);
1111 checkLocalName (/*@unused@*/ uentry ue)
1117 ** Checks a name used by user source is not reserved by ANSI
1118 ** (or for future library functions).
1120 ** The restrictions are described in X3.159-1989: 4.13
1123 /*@constant int NRESERVEDNAMES; @*/
1124 # define NRESERVEDNAMES 201
1126 /*@constant int NCPPNAMES@*/
1127 # define NCPPNAMES 39
1129 bool checkCppName (cstring name, fileloc loc)
1131 static ob_mstring cppNames[NCPPNAMES] =
1133 "and", "and_eq", "asm",
1134 "bitand", "bitor", "bool", /* gasp: "bool", is special for lclint */
1135 "catch", "class", "compl", "const_class",
1136 "delete", "dynamic_cast", "false", "friend",
1137 "inline", "mutable", "namespace", "new",
1139 "operator", "or", "or_eq", "overload",
1140 "private", "protected", "public",
1141 "reinterpret_cast", "static_cast",
1142 "template", "this", "throw", "true", "try",
1143 "typeid", "using", "virtual", "xor", "xor_eq"
1146 if (cstring_isDefined (cstring_bsearch (name, &cppNames[0],
1151 message ("Name %s is a keyword or reserved word in C++",
1160 checkAnsiName (cstring name, fileloc loc)
1162 bool hasError = FALSE;
1163 int length = cstring_length (name);
1164 char fchar = (length >= 1) ? cstring_firstChar (name) : '\0';
1165 char schar = (length >= 2) ? cstring_secondChar (name) : '\0';
1166 char tchar = (length >= 3) ? cstring_getChar (name, 3) : '\0';
1167 char rchar = (length >= 4) ? cstring_getChar (name, 4) : '\0';
1171 ** taken from Linden, "Expert C Programming", p. 126-8.
1172 ** invariant: must be sorted (case-insensitive, lexicographically)
1173 ** must end with NULL
1176 static ob_mstring reservedNames[NRESERVEDNAMES] =
1178 # include "reservedNames.nf"
1181 if (fileloc_isSystemFile (loc) || fileloc_isBuiltin (loc))
1183 return FALSE; /* no errors for system files */
1189 char *lastname = NULL;
1192 while ((name = reservedNames[i]) != NULL)
1194 llassertprint (lastname == NULL
1195 || strcmp (name, lastname) > 0,
1196 ("%s / %s", lastname, name));
1201 nreservedNames = i - 1;
1205 if (cstring_isDefined (cstring_bsearch (name, &reservedNames[0],
1210 message ("Name %s is reserved for the standard library",
1217 hasError = optgenerror
1220 ("Name %s is in the implementation name space (any identifier "
1221 "beginning with underscore)",
1227 ** 4.13.1 Errors <errno.h>
1229 ** Macros that begin with E and a digit or E and an uppercase letter ...
1232 else if (fchar == 'E' && (isdigit ((int) schar)
1233 || isupper ((int) schar)))
1235 hasError = optgenerror
1238 ("Name %s is reserved for future ANSI library extensions. "
1239 "Macros beginning with E and a digit or uppercase letter "
1240 "may be added to <errno.h>. (See ANSI, Section 4.13.1)",
1246 ** 4.13.2 Character Handling <ctype.h>
1248 ** Function names that begin with either "is" or "to" and a lowercase letter ...
1251 else if (((fchar == 'i' && schar == 's')
1252 || (fchar == 't' && schar == 'o'))
1253 && (islower ((int) tchar)))
1255 hasError = optgenerror
1258 ("Name %s is reserved for future ANSI library extensions. "
1259 "Functions beginning with \"is\" or \"to\" and a lowercase "
1260 "letter may be added to <ctype.h>. (See ANSI, Section 4.13.2)",
1266 ** 4.13.3 Localization <locale.h>
1268 ** Macros that begin with LC_ and an uppercase letter ...
1271 else if (length >= 4
1275 && (isupper ((int) rchar)))
1277 hasError = optgenerror
1280 ("Name %s is reserved for future ANSI library extensions. "
1281 "Macros beginning with \"LC_\" and an uppercase letter may "
1282 "be added to <locale.h>. (See ANSI, Section 4.13.3)",
1288 ** 4.13.4 Mathematics <math.h>
1290 ** The names of all existing functions declared in the <math.h> header,
1291 ** suffixed with f or l...
1294 else if ((cstring_lastChar (name) == 'f' || cstring_lastChar (name) == 'l')
1297 && ((cstring_equalPrefix (name, "cos") ||
1298 cstring_equalPrefix (name, "sin") ||
1299 cstring_equalPrefix (name, "tan") ||
1300 cstring_equalPrefix (name, "exp") ||
1301 cstring_equalPrefix (name, "log") ||
1302 cstring_equalPrefix (name, "pow"))))
1304 && ((cstring_equalPrefix (name, "acos") ||
1305 cstring_equalPrefix (name, "asin") ||
1306 cstring_equalPrefix (name, "atan") ||
1307 cstring_equalPrefix (name, "cosh") ||
1308 cstring_equalPrefix (name, "sinh") ||
1309 cstring_equalPrefix (name, "sqrt") ||
1310 cstring_equalPrefix (name, "ceil") ||
1311 cstring_equalPrefix (name, "fabs") ||
1312 cstring_equalPrefix (name, "fmod") ||
1313 cstring_equalPrefix (name, "tanh") ||
1314 cstring_equalPrefix (name, "modf"))))
1316 && ((cstring_equalPrefix (name, "atan2") ||
1317 cstring_equalPrefix (name, "floor") ||
1318 cstring_equalPrefix (name, "frexp") ||
1319 cstring_equalPrefix (name, "ldexp") ||
1320 cstring_equalPrefix (name, "log10"))))))
1322 hasError = optgenerror
1325 ("Name %s is reserved for future ANSI library extensions. "
1326 "The names of all existing functions in <math.h> suffixed "
1327 "with 'f' or 'l' may be added to <math.h>. (See ANSI, Section 4.13.4)",
1333 ** 4.13.5 Signal Handling <signal.h>
1335 ** Macros that begin with either SIG or SIG_ and an uppercase letter or...
1338 else if (fchar == 'S' && schar == 'I' && tchar == 'G'
1339 && ((rchar == '_' && ((length >= 5
1340 && isupper ((int) cstring_getChar (name, 5)))))
1341 || (isupper ((int) rchar))))
1343 hasError = optgenerror
1346 ("Name %s is reserved for future ANSI library extensions. "
1347 "Macros that begin with SIG and an uppercase letter or SIG_ "
1348 "and an uppercase letter may be added to "
1349 "<signal.h>. (See ANSI, Section 4.13.5)",
1355 ** 4.13.6 Input/Output <stdio.h>
1357 ** (nothing to check)
1361 ** 4.13.7 General Utilities <stdlib.h>
1363 ** Functions names that begin with str and a lowercase letter may be added to <stdlib.h>.
1366 else if (fchar == 's' && schar == 't' && tchar == 'r'
1367 && (islower ((int) rchar)))
1369 hasError = optgenerror
1372 ("Name %s is reserved for future ANSI library extensions. "
1373 "Functions that begin with \"str\" and a lowercase letter "
1374 "may be added to <stdlib.h> or <string.h>. (See ANSI, Section 4.13.7)",
1380 ** 4.13.8 String Handling <string.h>
1382 ** Function names that begin with str, mem, or wcs and a lowercase letter ...
1384 ** (Note: already checked "str" above.)
1387 else if (((fchar == 'm' && schar == 'e' && tchar == 'm')
1388 || (fchar == 'w' && schar == 'c' && tchar == 's'))
1389 && (islower ((int) rchar)))
1391 hasError = optgenerror
1394 ("Name %s is reserved for future ANSI library extensions. "
1395 "Functions that begin with \"mem\" or \"wcs\" and a "
1396 "lowercase letter letter may be added to <string.h>. (See ANSI, Section 4.13.8)",
1408 void checkParamNames (uentry ue)
1410 cstring fpfx = context_getString (FLG_DECLPARAMPREFIX);
1411 bool noformal = context_getFlag (FLG_DECLPARAMNAME);
1413 llassert (uentry_isFunction (ue));
1415 if (cstring_isDefined (fpfx) || noformal)
1417 uentryList params = uentry_getParams (ue);
1419 uentryList_elements (params, p)
1421 if (uentry_hasName (p))
1423 if (noformal && !cstring_isDefined (fpfx))
1427 message ("Declaration parameter has name: %q",
1428 uentry_getName (p)),
1429 uentry_whereLast (p)))
1431 uentry_setHasNameError (p);
1436 cstring pname = uentry_getName (p);
1438 if (!cstring_equalPrefix (pname, cstring_toCharsSafe (fpfx)))
1440 if (context_getFlag (FLG_NAMECHECKS))
1443 (FLG_DECLPARAMPREFIX,
1444 message ("Declaration parameter name %s does not begin "
1445 "with protoparamprefix (%s)",
1447 uentry_whereLast (p)))
1449 uentry_setHasNameError (p);
1453 cstring_free (pname);
1456 } end_uentryList_elements ;