]> andersk Git - splint.git/blob - src/nameChecks.c
Readded files.
[splint.git] / src / nameChecks.c
1 /*
2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 University of Virginia,
4 **         Massachusetts Institute of Technology
5 **
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.
10 ** 
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.
15 ** 
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.
19 **
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
23 */
24 /*
25 ** nameChecks.c
26 */
27
28 # include "lclintMacros.nf"
29 # include "basic.h"
30 # include "nameChecks.h"
31
32 static bool checkCzechName (uentry p_ue, flagcode p_czechflag, bool p_report)
33   /*@modifies p_ue, g_msgstream@*/ ;
34
35 static bool checkSlovakName (uentry p_ue, flagcode p_slovakflag, bool p_report)
36   /*@modifies p_ue, g_msgstream@*/ ;
37
38 static cstring czechPrefix (cstring name)
39 {
40   return (cstring_beforeChar (name, '_'));
41 }
42
43 static cstring slovakPrefix (cstring name)
44 {
45   int i = 0;
46
47   cstring_chars (name, c)
48     {
49       if (isupper ((unsigned char) c))
50         {
51           return (cstring_prefix (name, i));
52         }
53       i++;
54     } end_cstring_chars;
55
56   return cstring_undefined;
57 }
58
59 static flagcode excludeCodes [] = 
60  {
61    FLG_MACROVARPREFIXEXCLUDE,
62    FLG_TAGPREFIXEXCLUDE,
63    FLG_ENUMPREFIXEXCLUDE,
64    FLG_FILESTATICPREFIXEXCLUDE,
65    FLG_GLOBPREFIXEXCLUDE,
66    FLG_TYPEPREFIXEXCLUDE,
67    FLG_EXTERNALPREFIXEXCLUDE,
68    FLG_UNCHECKEDMACROPREFIXEXCLUDE,
69    FLG_LOCALPREFIXEXCLUDE,
70    INVALID_FLAG
71    } ;
72
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++; 
77
78 # define end_excludeFlagCodes }}
79
80 static bool matchPrefixChar (int nc, int pc)
81 {
82   if (nc == pc)
83     {
84       return TRUE;
85     }
86   else
87     {
88       switch (pc)
89         {
90         case PFX_UPPERCASE: 
91           return isupper (nc);
92         case PFX_LOWERCASE:
93           return islower (nc);
94         case PFX_ANY:
95           return TRUE;
96         case PFX_DIGIT:
97           return isdigit (nc);
98         case PFX_NOTUPPER:
99           return !isupper (nc);
100         case PFX_NOTLOWER:
101           return !islower (nc);
102         case PFX_ANYLETTER:
103           return isalpha (nc);
104         case PFX_ANYLETTERDIGIT: 
105           return (isdigit (nc) || isalpha (nc));
106         default: return FALSE;
107         }
108     }
109
110   BADEXIT;
111 }
112
113 static bool matchPrefix (cstring name, cstring prefix)
114 {
115   if (cstring_isUndefined (name)
116       || cstring_isUndefined (prefix))
117     {
118       return TRUE;
119     }
120   else
121     {
122       int namelen = cstring_length (name);
123       int last = (int) '\0';
124       int n = 1;
125
126       cstring_chars (prefix, pc)
127         {
128           int nc;
129
130           if (pc == '*')
131             {
132               n++;
133
134               
135               while (n <= namelen)
136                 {
137                   nc = (int) cstring_getChar (name, n);
138
139                   if (!matchPrefixChar (nc, last))
140                     {
141                       return FALSE;
142                     }
143                   n++;
144                 }
145
146               return TRUE;
147             }
148           else
149             {
150               if (n > namelen)
151                 {
152                   if ((cstring_length (prefix) >= n + 1)
153                       && cstring_getChar (prefix, n + 1) == '*')
154                     {
155                       return TRUE;
156                     }
157                   else
158                     {
159                       return FALSE;
160                     }
161                 }
162               
163               nc = (int) cstring_getChar (name, n);
164               
165               if (!matchPrefixChar (nc, (int) pc))
166                 {
167                   return FALSE;
168                 }
169             }
170         
171           last = (int) pc;
172           n++;
173         } end_cstring_chars;
174
175       return TRUE;
176     }
177 }
178
179 static flagcode
180 namespaceExcluded (flagcode code) /*@*/ 
181 {
182   switch (code)
183     {
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);
206     BADDEFAULT;
207     }
208 }
209
210 static /*@observer@*/ cstring
211 namespaceName (flagcode flag) /*@*/
212 {
213   switch (flag)
214     {
215     case FLG_MACROVARPREFIX: 
216       return cstring_makeLiteralTemp ("macro variable");
217     case FLG_TAGPREFIX:  
218       return cstring_makeLiteralTemp ("tag");
219     case FLG_ENUMPREFIX:  
220       return cstring_makeLiteralTemp ("enum member");
221     case FLG_TYPEPREFIX:     
222       return cstring_makeLiteralTemp ("user-defined type");
223     case FLG_FILESTATICPREFIX:
224       return cstring_makeLiteralTemp ("file static");
225     case FLG_GLOBPREFIX: 
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");
233     case FLG_ITERPREFIX: 
234       return cstring_makeLiteralTemp ("iter");
235     case FLG_UNCHECKEDMACROPREFIX: 
236       return cstring_makeLiteralTemp ("unchecked macro");
237     BADDEFAULT;
238     }
239 }
240
241 void 
242 checkPrefix (uentry ue)
243 {
244   cstring name = cstring_undefined;
245   flagcode flag;
246
247   if (uentry_isExpandedMacro (ue))
248     {
249       flag = FLG_UNCHECKEDMACROPREFIX;
250     }
251   else if (uentry_isAnyTag (ue))
252     {
253       flag = FLG_TAGPREFIX;
254     }
255   else if (uentry_isEnumConstant (ue))
256     {
257       flag = FLG_ENUMPREFIX;
258     }
259   else if (uentry_isDatatype (ue))
260     {
261       flag = FLG_TYPEPREFIX;
262     }
263   else if (uentry_isFileStatic (ue))
264     {
265       flag = FLG_FILESTATICPREFIX;
266     }
267   else if (uentry_isGlobal (ue))
268     {
269       flag = FLG_GLOBPREFIX;
270     }
271   else if (uentry_isVariable (ue))
272     {
273       if (uentry_isRefParam (ue))
274         {
275           return; /* already checked param */
276         }
277
278       if (context_inMacro ())
279         {
280           if (uentry_isAnyParam (ue))
281             {
282               if (uentry_isYield (ue))
283                 {
284                   flag = FLG_MACROVARPREFIX;
285                 }
286               else
287                 {
288                   flag = FLG_LOCALPREFIX;
289                 }
290             }
291           else
292             {
293               flag = FLG_MACROVARPREFIX;
294             }
295         }
296       else
297         {
298           flag = FLG_LOCALPREFIX;
299         }
300     }
301   else if (uentry_isConstant (ue))
302     {
303       flag = FLG_CONSTPREFIX;
304     }
305   else if (uentry_isIter (ue))
306     {
307       flag = FLG_ITERPREFIX;
308     }
309   else if (uentry_isExported (ue))
310     {
311       flag = FLG_EXTERNALPREFIX;
312     }
313   else
314     {
315       llcontbug (message ("What is it: %q", uentry_unparseFull (ue)));
316       return;
317     }
318
319   if (flag == FLG_TYPEPREFIX || flag == FLG_GLOBPREFIX
320       || flag == FLG_ENUMPREFIX || flag == FLG_CONSTPREFIX)
321     {
322       if (flag == FLG_ENUMPREFIX)
323         {
324           if (!context_getFlag (flag))
325             {
326               flag = FLG_CONSTPREFIX;
327             }
328         }
329
330       if (!context_getFlag (flag))
331         {
332           flag = FLG_EXTERNALPREFIX;
333         }
334     }
335
336   if (context_getFlag (flag))
337     {
338       name = uentry_getName (ue);
339       
340       
341       if (!matchPrefix (name, context_getString (flag)))
342         {
343           if (optgenerror
344               (flag,
345                message ("%s %s name is not consistent with %s "
346                         "namespace prefix \"%s\"",
347                         uentry_ekindName (ue),
348                         name,
349                         namespaceName (flag),
350                         context_getString (flag)),
351                uentry_whereLast (ue)))
352             {
353               uentry_setHasNameError (ue);
354             }
355         }
356     }  
357
358   excludeFlagCodes (code)
359     {
360       bool check = FALSE;
361
362       if (context_getFlag (code))
363         {
364           /*@-loopswitchbreak@*/
365           switch (code)
366             {
367             case FLG_MACROVARPREFIXEXCLUDE:
368               check = (flag != FLG_MACROVARPREFIX);
369               break;
370             case FLG_TAGPREFIXEXCLUDE:
371               check = (flag != FLG_TAGPREFIX);
372               break;
373             case FLG_ENUMPREFIXEXCLUDE:
374               check = (flag != FLG_ENUMPREFIX);
375               break;
376             case FLG_FILESTATICPREFIXEXCLUDE:
377               check = (flag != FLG_FILESTATICPREFIX);
378               break;
379             case FLG_GLOBPREFIXEXCLUDE:
380               check = (flag != FLG_GLOBPREFIX);
381               break;
382             case FLG_TYPEPREFIXEXCLUDE:
383               check = (flag != FLG_TYPEPREFIX);
384               break;
385             case FLG_EXTERNALPREFIXEXCLUDE:
386               check = (flag != FLG_EXTERNALPREFIX
387                        && flag != FLG_GLOBPREFIX
388                        && flag != FLG_TYPEPREFIX
389                        && flag != FLG_UNCHECKEDMACROPREFIX);
390               break;
391             case FLG_UNCHECKEDMACROPREFIXEXCLUDE:
392               check = (flag != FLG_UNCHECKEDMACROPREFIX);
393               break;
394             case FLG_LOCALPREFIXEXCLUDE:
395               check = (flag != FLG_LOCALPREFIX);
396               break;
397             case FLG_CONSTPREFIXEXCLUDE:
398               check = (flag != FLG_CONSTPREFIX);
399               break;
400             case FLG_ITERPREFIXEXCLUDE:
401               check = (flag != FLG_ITERPREFIX);
402               break;
403             BADDEFAULT;
404             }
405           /*@=loopswitchbreak@*/
406
407           if (check)
408             {
409               flagcode rcode = namespaceExcluded (code);
410               cstring pstring = context_getString (rcode);
411
412               if (cstring_isDefined (pstring))
413                 {
414                   if (cstring_isUndefined (name))
415                     {
416                       name = uentry_getName (ue);
417                     }
418                   
419                   if (matchPrefix (name, context_getString (rcode)))
420                     {
421                       if (optgenerror
422                           (code,
423                            message
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),
428                             name,
429                             namespaceName (rcode),
430                             namespaceName (flag),
431                             namespaceName (rcode),
432                             context_getString (rcode)),
433                            uentry_whereLast (ue)))
434                         {
435                           uentry_setHasNameError (ue);
436                         }
437                     }
438                 }
439             }
440         } 
441     } end_excludeFlagCodes ;
442
443   cstring_free (name);
444 }
445
446 static void
447 checkNationalName (uentry ue)
448 {
449   flagcode czechflag;
450   flagcode slovakflag;
451   flagcode czechoslovakflag;
452   bool gcf, gsf, gcsf;
453
454   
455   if (uentry_isFunction (ue)
456       || uentry_isIter (ue)
457       || uentry_isEndIter (ue))
458     {
459       czechflag = FLG_CZECHFUNCTIONS;
460       slovakflag = FLG_SLOVAKFUNCTIONS;
461       czechoslovakflag = FLG_CZECHOSLOVAKFUNCTIONS;
462     }
463   else if (uentry_isExpandedMacro (ue))
464     {
465       czechflag = FLG_CZECHMACROS;
466       slovakflag = FLG_SLOVAKMACROS;
467       czechoslovakflag = FLG_CZECHOSLOVAKMACROS;
468     }
469   else if (uentry_isVariable (ue))
470     {
471       if (uentry_isGlobal (ue) && context_getFlag (FLG_GLOBPREFIX))
472         {
473           /* prefix checks supercede national naming checks */
474           return;
475         }
476
477       czechflag = FLG_CZECHVARS;
478       slovakflag = FLG_SLOVAKVARS;
479       czechoslovakflag = FLG_CZECHOSLOVAKVARS;
480     }
481   else if (uentry_isConstant (ue))
482     {
483       if (uentry_isGlobal (ue) && context_getFlag (FLG_CONSTPREFIX))
484         {
485           /* prefix checks supercede national naming checks */
486           return;
487         }
488
489       czechflag = FLG_CZECHCONSTANTS;
490       slovakflag = FLG_SLOVAKCONSTANTS;
491       czechoslovakflag = FLG_CZECHOSLOVAKCONSTANTS;
492     }
493   else
494     {
495       if (uentry_isAnyTag (ue) || uentry_isEnumConstant (ue))
496         {
497           return; /* no errors for tags */
498         }
499       
500       llassert (uentry_isDatatype (ue));
501
502       czechflag = FLG_CZECHTYPES;
503       slovakflag = FLG_SLOVAKTYPES;
504       czechoslovakflag = FLG_CZECHOSLOVAKTYPES;
505     }
506
507   gcf = context_getFlag (czechflag);
508   gsf = context_getFlag (slovakflag);
509   gcsf = context_getFlag (czechoslovakflag);
510
511   if (gcf || (uentry_isFunction (ue) 
512               && context_getFlag (FLG_ACCESSCZECH)))
513     {
514             (void) checkCzechName (ue, czechflag, gcf);
515     }
516
517   if (gsf || (uentry_isFunction (ue) 
518               && context_getFlag (FLG_ACCESSSLOVAK)))
519     {
520       (void) checkSlovakName (ue, slovakflag, gsf);
521     }
522
523   if (gcsf)
524     {
525       if (uentry_isDatatype (ue))
526         {
527           /* May not have either _'s or uppercase letter */
528           cstring name = uentry_rawName (ue);
529           int charno = 1;
530
531           cstring_chars (name, c)
532             {
533               if (isupper ((unsigned char) c))
534                 {
535                   if (optgenerror
536                       (FLG_CZECHOSLOVAKTYPES,
537                        message
538                        ("%s %q name violates Czechoslovak naming convention.  "
539                         "Czechoslovak datatype names should not use uppercase "
540                         "letters.",
541                         uentry_ekindName (ue),
542                         uentry_getName (ue)),
543                        uentry_whereLast (ue)))
544                     {
545                       uentry_setHasNameError (ue);
546                     }
547                   break;
548                 }
549
550               if (c == '_' && charno != 2 && charno != 3)
551                 {
552                   if (optgenerror
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)))
560                     {
561                       uentry_setHasNameError (ue);
562                     }
563                   break;
564                 }
565               
566               charno++;
567             } end_cstring_chars;
568         }
569       else
570         {
571           bool okay = checkCzechName (ue, czechflag, FALSE);
572           
573           /* still need to call, to set access */
574           okay |= checkSlovakName (ue, slovakflag, FALSE);
575           
576           if (!okay)
577             {
578               if (optgenerror
579                   (czechoslovakflag,
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)))
585                 {
586                   uentry_setHasNameError (ue);
587                 }
588             }
589         }
590     }
591 }
592
593 static bool checkCzechName (uentry ue, flagcode czechflag, bool report)
594 {
595   if (uentry_isDatatype (ue))
596     {
597       /*
598       ** Czech datatypes may not have _'s, except if there are 1 or 2 characters
599       ** before the only _.
600       */
601
602       cstring name = uentry_rawName (ue);
603       int charno = 1;
604       
605       cstring_chars (name, c)
606         {
607           if (c == '_' && charno != 2 && charno != 3)
608             {
609               if (report)
610                 {
611                   if (optgenerror
612                       (FLG_CZECHTYPES,
613                        message 
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)))
619                     {
620                       uentry_setHasNameError (ue);
621                     }
622                 }
623
624               return FALSE;
625             }
626           
627           charno++;
628         } end_cstring_chars;
629     }
630   else
631     {
632       typeIdSet acc = context_fileAccessTypes ();
633       cstring pfx = czechPrefix (uentry_rawName (ue));
634
635       if (cstring_isEmpty (pfx))
636         {
637           if (uentry_isVariable (ue) || uentry_isConstant (ue))
638             {
639               ctype ct = uentry_getType (ue);
640               
641               if (ctype_isAbstract (ct)
642                   && context_hasAccess (ctype_typeId (ct)))
643                 {
644                   if (report)
645                     {
646                       if (optgenerror
647                           (czechflag,
648                            message ("%s %q name is not consistent with Czech "
649                                     "naming convention.  The name should "
650                                     "begin with %s_",
651                                     uentry_ekindName (ue),
652                                     uentry_getName (ue),
653                                     ctype_unparse (ct)),
654                            uentry_whereLast (ue)))
655                         {
656                           uentry_setHasNameError (ue);
657                         }
658                     }
659
660                   cstring_free (pfx);
661                   return FALSE;
662                 }
663             }
664           else if (uentry_isFunction (ue) || uentry_isIter (ue))
665             {
666               if (typeIdSet_isEmpty (acc))
667                 {
668                   ; /* okay - should not be czech name */
669                 }
670               else
671                 {
672                   if (report)
673                     {
674                       if (optgenerror
675                           (czechflag,
676                            message ("%s %q name is not consistent with Czech "
677                                     "naming convention.  Accessible types: %q",
678                                     uentry_ekindName (ue),
679                                     uentry_getName (ue),
680                                     typeIdSet_unparse (acc)),
681                            uentry_whereLast (ue)))
682                         {
683                           uentry_setHasNameError (ue);
684                         }
685                     }
686
687                   cstring_free (pfx);
688                   return FALSE;
689                 }
690             }
691           else
692             {
693               ;
694             }
695         }
696       else
697         {
698           if (usymtab_existsTypeEither (pfx))
699             {
700               ctype ct = usymtab_lookupAbstractType (pfx);
701               typeId tid;
702               
703               if (ctype_isUA (ct))
704                 {
705                   tid = ctype_typeId (ct);
706                   
707                   if (ctype_isUser (ct) || context_hasAccess (tid))
708                     {
709                       ;
710                     }
711                   else
712                     {
713                       if (context_getFlag (FLG_ACCESSCZECH)
714                           || context_getFlag (FLG_ACCESSCZECHOSLOVAK))
715                         {
716                           if (!uentry_isVar (ue))
717                             {
718                               uentry_addAccessType (ue, tid);
719                             }
720                         }
721                       else
722                         {
723                           if (report)
724                             {
725                               if (llgenhinterror
726                                   (czechflag,
727                                    message 
728                                    ("%s %q name violates Czech naming "
729                                     "convention. Czech prefix %s names "
730                                     "an abstract type that is "
731                                     "not accessible.",
732                                     uentry_ekindName (ue),
733                                     uentry_getName (ue),
734                                     pfx),
735                                    cstring_makeLiteral 
736                                    ("Use +accessczech to allow access to "
737                                     "type <t> in functions "
738                                     "named <t>_<name>."), 
739                                    uentry_whereLast (ue)))
740                                 {
741                                   uentry_setHasNameError (ue);
742                                 }
743                             }
744                           
745                           cstring_free (pfx);
746                           return FALSE;
747                         }
748                     }
749                 }
750               else if (ctype_isManifestBool (ct))
751                 {
752                   if (context_canAccessBool ())
753                     {
754                       ;
755                     }
756                   else
757                     {
758                       if (context_getFlag (FLG_ACCESSCZECH)
759                           || context_getFlag (FLG_ACCESSCZECHOSLOVAK))
760                         {
761                           if (!uentry_isVar (ue))
762                             {
763                               tid = usymtab_getTypeId (context_getBoolName ());
764                               uentry_addAccessType (ue, tid);
765                             }
766                         }
767                       else
768                         {
769                           if (report)
770                             {
771                               if (llgenhinterror
772                                   (czechflag,
773                                    message
774                                    ("%s %q name violates Czech naming "
775                                     "convention. Type bool is not accessible.",
776                                     uentry_ekindName (ue),
777                                     uentry_getName (ue)),
778                                    cstring_makeLiteral 
779                                    ("Use +accessczech to allow access to "
780                                     "type <t> in functions named <t>_<name>."), 
781                                    uentry_whereLast (ue)))
782                                 {
783                                   uentry_setHasNameError (ue);
784                                 }
785                             }
786                           
787                           cstring_free (pfx);
788                           return FALSE;
789                         }
790                     }
791                 }
792               else
793                 {
794                   ;
795                 }
796             }
797           else
798             {
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"))
807                 {
808                   ; /* built-in types */
809                 }
810               else
811                 {
812                   /* no accessible types, could match module name */
813                   
814                   if (cstring_equal (pfx, context_moduleName ()))
815                     {
816                       ;
817                     }
818                   else
819                     {
820                       if (report)
821                         {
822                           if (optgenerror
823                               (czechflag,
824                                message 
825                                ("%s %q name violates Czech naming convention.  "
826                                 "Czech prefix %s is not the name of a type.",
827                                 uentry_ekindName (ue),
828                                 uentry_getName (ue),
829                                 pfx),
830                                uentry_whereLast (ue)))
831                             {
832                               uentry_setHasNameError (ue);
833                             }
834                         }
835
836                       cstring_free (pfx);                     
837                       return FALSE;
838                     }
839                 }
840             }
841         }
842       cstring_free (pfx);
843     }
844
845   return TRUE;
846 }
847
848 static bool checkSlovakName (uentry ue, flagcode slovakflag, bool report)
849 {
850   if (uentry_isDatatype (ue))
851     {
852       /*
853       ** Slovak datatypes may not have uppercase letters.
854       */
855
856       if (context_getFlag (FLG_SLOVAK))
857         {
858           cstring name = uentry_rawName (ue);
859
860           cstring_chars (name, c)
861             {
862               if (isupper ((unsigned char) c))
863                 {
864                   if (report)
865                     {
866                       if (optgenerror
867                           (FLG_SLOVAKTYPES,
868                            message 
869                            ("%s %q name violates Slovak naming convention.  "
870                             "Slovak datatype names should not use uppercase "
871                             "letters.",
872                             uentry_ekindName (ue),
873                             uentry_getName (ue)),
874                            uentry_whereLast (ue)))
875                         {
876                           uentry_setHasNameError (ue);
877                         }
878                     }
879                   return FALSE;
880                 }
881             } end_cstring_chars;
882         }
883     }
884   else
885     {
886       typeIdSet acc = context_fileAccessTypes ();
887       cstring pfx = slovakPrefix (uentry_rawName (ue));
888       
889       if (cstring_isEmpty (pfx))
890         {
891           if (typeIdSet_isEmpty (acc))
892             {
893               ; /* okay - should not be slovak name */
894             }
895           else
896             {
897               if (uentry_isFunction (ue))
898                 {
899                   if (report)
900                     {
901                       if (optgenerror
902                           (slovakflag,
903                            message ("%s %q name is not consistent with Slovak "
904                                     "naming convention.  Accessible types: %q",
905                                     uentry_ekindName (ue),
906                                     uentry_getName (ue),
907                                     typeIdSet_unparse (acc)),
908                            uentry_whereLast (ue)))
909                         {
910                           uentry_setHasNameError (ue);
911                         }
912                     }
913                   
914                   cstring_free (pfx);
915                   return FALSE;
916                 }
917               else
918                 {
919                   ctype ct = uentry_getType (ue);
920                   
921                   if (ctype_isUA (ct))
922                     {
923                       if (report)
924                         {
925                           if (optgenerror
926                               (slovakflag,
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),
932                                         uentry_getName (ue),
933                                         ctype_unparse (ct)),
934                                uentry_whereLast (ue)))
935                             {
936                               uentry_setHasNameError (ue);
937                             }   
938                         }
939                       
940                       cstring_free (pfx);
941                       return FALSE;
942                     }
943                 }
944             }
945         }
946       else
947         {
948           if (usymtab_existsTypeEither (pfx))
949             {
950               ctype ct = usymtab_lookupAbstractType (pfx);
951               typeId tid;
952               
953               if (ctype_isUA (ct))
954                 {
955                   tid = ctype_typeId (ct);
956                   
957                   if (ctype_isUser (ct) || context_hasAccess (tid))
958                     {
959                       ;
960                     }
961                   else
962                     {
963                       if (context_getFlag (FLG_ACCESSSLOVAK)
964                           || context_getFlag (FLG_ACCESSCZECHOSLOVAK))
965                         {
966                           if (!uentry_isVar (ue))
967                             {
968                               uentry_addAccessType (ue, tid);
969                             }
970                         }
971                       else
972                         {
973                           if (report)
974                             {
975                               if (llgenhinterror
976                                   (slovakflag,
977                                    message 
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),
982                                     uentry_getName (ue),
983                                     pfx),
984                                    cstring_makeLiteral 
985                                    ("Use +accessslovak to allow access to "
986                                     "type <t> in functions named <t>_<name>."), 
987                                    uentry_whereLast (ue)))
988                                 {
989                                   uentry_setHasNameError (ue);
990                                 }
991                             }
992                           
993                           cstring_free (pfx);
994                           return FALSE;
995                         }
996                     }
997                 }
998               else if (ctype_isManifestBool (ct))
999                 {
1000                   if (context_canAccessBool ())
1001                     {
1002                       ;
1003                     }
1004                   else
1005                     {
1006                       if (context_getFlag (FLG_ACCESSSLOVAK)
1007                           || context_getFlag (FLG_ACCESSCZECHOSLOVAK))
1008                         {
1009                           if (!uentry_isVar (ue))
1010                             {
1011                               tid = usymtab_getTypeId (context_getBoolName ());
1012                               uentry_addAccessType (ue, tid);
1013                             }
1014                         }
1015                       else
1016                         {
1017                           if (report)
1018                             {
1019                               if (llgenhinterror
1020                                   (slovakflag,
1021                                    message
1022                                    ("%s %q name violates Slovak naming convention.  "
1023                                     "Type bool is not accessible.",
1024                                     uentry_ekindName (ue),
1025                                     uentry_getName (ue)),
1026                                    cstring_makeLiteral
1027                                    ("Use +accessslovak to allow access to "
1028                                     "type <t> in functions named <t>_<name>."),
1029                                    uentry_whereLast (ue)))
1030                                 {
1031                                   uentry_setHasNameError (ue);
1032                                 }
1033                             }
1034                           
1035                           cstring_free (pfx);
1036                           return FALSE;
1037                         }
1038                     }
1039                 }
1040               else
1041                 {
1042                   ;
1043                 }
1044             }
1045           else
1046             {
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"))
1055                 {
1056                   ; /* built-in types */
1057                 }
1058               else
1059                 {
1060                   /* no accessible types, could match module name */
1061                   
1062                   if (cstring_equal (pfx, context_moduleName ()))
1063                     {
1064                       ;
1065                     }
1066                   else
1067                     {
1068                       if (report)
1069                         {
1070                           if (optgenerror
1071                               (slovakflag,
1072                                message 
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),
1077                                 pfx),
1078                                uentry_whereLast (ue)))
1079                             {
1080                               uentry_setHasNameError (ue);
1081                             }
1082                         }
1083
1084                       cstring_free (pfx);
1085                       return FALSE;
1086                     }
1087                 }
1088             }
1089         }
1090
1091       cstring_free (pfx);
1092     }
1093
1094   return TRUE;
1095 }
1096
1097 void
1098 checkGlobalName (uentry ue)
1099 {
1100   if (!uentry_isStatic (ue) && uentry_hasName (ue))
1101     {
1102       checkNationalName (ue);
1103     }
1104   else
1105     {
1106       ;
1107     }
1108 }
1109
1110 void
1111 checkLocalName (/*@unused@*/ uentry ue)
1112 {
1113   ;
1114 }
1115
1116 /*
1117 ** Checks a name used by user source is not reserved by ANSI 
1118 ** (or for future library functions).
1119 **
1120 ** The restrictions are described in X3.159-1989: 4.13
1121 */
1122
1123 /*@constant int NRESERVEDNAMES; @*/
1124 # define NRESERVEDNAMES 201
1125
1126 /*@constant int NCPPNAMES@*/
1127 # define NCPPNAMES 39
1128
1129 bool checkCppName (cstring name, fileloc loc)
1130 {
1131   static ob_mstring cppNames[NCPPNAMES] =
1132     {
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",
1138       "not", "not_eq",
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"
1144       } ;
1145   
1146   if (cstring_isDefined (cstring_bsearch (name, &cppNames[0],
1147                                           NCPPNAMES)))
1148     {
1149       return (optgenerror
1150               (FLG_CPPNAMES,
1151                message ("Name %s is a keyword or reserved word in C++",
1152                         name),
1153                loc));
1154     }
1155
1156   return FALSE;
1157 }
1158
1159 bool
1160 checkAnsiName (cstring name, fileloc loc)
1161 {
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';
1168
1169   /* 
1170   ** reservedNames
1171   **   taken from Linden, "Expert C Programming", p. 126-8. 
1172   **   invariant:  must be sorted (case-insensitive, lexicographically)
1173   **               must end with NULL
1174   */
1175
1176   static ob_mstring reservedNames[NRESERVEDNAMES] =
1177     { 
1178 # include "reservedNames.nf"
1179     } ;
1180
1181   if (fileloc_isSystemFile (loc) || fileloc_isBuiltin (loc))
1182     {
1183       return FALSE;  /* no errors for system files */
1184     }
1185
1186 # if 0
1187   {
1188     int i = 0;
1189     char *lastname = NULL;
1190     char *name;
1191     
1192     while ((name = reservedNames[i]) != NULL)
1193       {
1194         llassertprint (lastname == NULL
1195                        || strcmp (name, lastname) > 0,
1196                        ("%s / %s", lastname, name));
1197         lastname = name;
1198         i++;
1199       }
1200     
1201     nreservedNames = i - 1;
1202   }
1203 # endif
1204   
1205   if (cstring_isDefined (cstring_bsearch (name, &reservedNames[0],
1206                                           NRESERVEDNAMES)))
1207     {
1208       return (optgenerror
1209               (FLG_ANSIRESERVED,
1210                message ("Name %s is reserved for the standard library",
1211                         name),
1212                loc));
1213     }
1214
1215   if (fchar == '_')
1216     {
1217       hasError = optgenerror
1218         (FLG_ANSIRESERVED,
1219          message 
1220          ("Name %s is in the implementation name space (any identifier "
1221           "beginning with underscore)", 
1222           name),
1223          loc);
1224     }
1225
1226   /*
1227   ** 4.13.1 Errors <errno.h>
1228   **
1229   ** Macros that begin with E and a digit or E and an uppercase letter ...
1230   */
1231
1232   else if (fchar == 'E' && (isdigit ((int) schar) 
1233                             || isupper ((int) schar)))
1234     {
1235       hasError = optgenerror
1236         (FLG_ANSIRESERVED,
1237          message 
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)",
1241           name),
1242          loc);
1243     }
1244   
1245   /*
1246   ** 4.13.2 Character Handling <ctype.h>
1247   **
1248   ** Function names that begin with either "is" or "to" and a lowercase letter ...
1249   */
1250
1251   else if (((fchar == 'i' && schar == 's') 
1252             || (fchar == 't' && schar == 'o'))
1253            && (islower ((int) tchar)))
1254     {
1255       hasError = optgenerror
1256         (FLG_ANSIRESERVED,
1257          message
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)",
1261           name),
1262          loc);
1263     }
1264   
1265   /*
1266   ** 4.13.3 Localization <locale.h>
1267   **
1268   ** Macros that begin with LC_ and an uppercase letter ...
1269   */
1270
1271   else if (length >= 4 
1272            && ((fchar == 'L')
1273                && (schar == 'C')
1274                && (tchar == '_'))
1275            && (isupper ((int) rchar)))
1276     {
1277       hasError = optgenerror
1278         (FLG_ANSIRESERVED,
1279          message
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)",
1283           name),
1284          loc);
1285     }
1286   
1287   /*
1288   ** 4.13.4 Mathematics <math.h>
1289   **
1290   ** The names of all existing functions declared in the <math.h> header, 
1291   ** suffixed with f or l...
1292   */
1293
1294   else if ((cstring_lastChar (name) == 'f' || cstring_lastChar (name) == 'l')
1295            && 
1296            (((length == 4)
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"))))
1303             || ((length == 5)
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"))))
1315             || ((length == 6)
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"))))))
1321     {
1322       hasError = optgenerror
1323         (FLG_ANSIRESERVED,
1324          message
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)",
1328           name),
1329          loc);
1330     }
1331   
1332   /*
1333   ** 4.13.5 Signal Handling <signal.h>
1334   **
1335   ** Macros that begin with either SIG or SIG_ and an uppercase letter or...
1336   */
1337
1338   else if (fchar == 'S' && schar == 'I' && tchar == 'G'
1339            && ((rchar == '_' && ((length >= 5 
1340                                   && isupper ((int) cstring_getChar (name, 5)))))
1341                || (isupper ((int) rchar))))
1342     {
1343       hasError = optgenerror
1344         (FLG_ANSIRESERVED,
1345          message
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)",
1350           name),
1351          loc);
1352     }
1353   
1354   /*
1355   ** 4.13.6 Input/Output <stdio.h>
1356   **
1357   ** (nothing to check)
1358   */
1359
1360   /*
1361   ** 4.13.7 General Utilities <stdlib.h>
1362   **
1363   ** Functions names that begin with str and a lowercase letter may be added to <stdlib.h>.
1364   */
1365
1366   else if (fchar == 's' && schar == 't' && tchar == 'r' 
1367            && (islower ((int) rchar)))
1368     {
1369       hasError = optgenerror
1370         (FLG_ANSIRESERVED,
1371          message
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)",
1375           name),
1376          loc);
1377     }
1378   
1379   /*
1380   ** 4.13.8 String Handling <string.h>
1381   **
1382   ** Function names that begin with str, mem, or wcs and a lowercase letter ...
1383   **
1384   ** (Note: already checked "str" above.)
1385   */
1386
1387   else if (((fchar == 'm' && schar == 'e' && tchar == 'm')
1388             || (fchar == 'w' && schar == 'c' && tchar == 's'))
1389            && (islower ((int) rchar)))
1390     {
1391       hasError = optgenerror
1392         (FLG_ANSIRESERVED,
1393          message
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)",
1397           name),
1398          loc);
1399     }
1400   else
1401     {
1402       ;
1403     }
1404
1405   return hasError;
1406 }
1407
1408 void checkParamNames (uentry ue)
1409 {
1410   cstring fpfx = context_getString (FLG_DECLPARAMPREFIX);
1411   bool noformal = context_getFlag (FLG_DECLPARAMNAME);
1412
1413   llassert (uentry_isFunction (ue));
1414   
1415   if (cstring_isDefined (fpfx) || noformal)
1416     {
1417       uentryList params = uentry_getParams (ue);
1418       
1419       uentryList_elements (params, p)
1420         {
1421           if (uentry_hasName (p))
1422             {
1423               if (noformal && !cstring_isDefined (fpfx))
1424                 {
1425                   if (optgenerror
1426                       (FLG_DECLPARAMNAME, 
1427                        message ("Declaration parameter has name: %q",
1428                                 uentry_getName (p)),
1429                        uentry_whereLast (p)))
1430                     {
1431                       uentry_setHasNameError (p);
1432                     }
1433                 }
1434               else
1435                 {
1436                   cstring pname = uentry_getName (p);
1437                   
1438                   if (!cstring_equalPrefix (pname, cstring_toCharsSafe (fpfx)))
1439                     {
1440                       if (context_getFlag (FLG_NAMECHECKS))
1441                         {
1442                           if (optgenerror
1443                               (FLG_DECLPARAMPREFIX, 
1444                                message ("Declaration parameter name %s does not begin "
1445                                         "with protoparamprefix (%s)",
1446                                         pname, fpfx),
1447                                uentry_whereLast (p)))
1448                             {
1449                               uentry_setHasNameError (p);
1450                             }
1451                         }
1452                     }
1453                   cstring_free (pname);
1454                 }
1455             }
1456         } end_uentryList_elements ;
1457     }
1458 }
1459
1460
1461
1462
This page took 0.163631 seconds and 5 git commands to generate.