]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | ** Splint - annotation-assisted static program checker | |
3 | ** Copyright (C) 1994-2002 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 splint: info@splint.org | |
21 | ** To report a bug: splint-bug@splint.org | |
22 | ** For more information: http://www.splint.org | |
23 | */ | |
24 | /* | |
25 | ** nameChecks.c | |
26 | */ | |
27 | ||
28 | # include "splintMacros.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_warningstream@*/ ; | |
34 | ||
35 | static bool checkSlovakName (uentry p_ue, flagcode p_slovakflag, bool p_report) | |
36 | /*@modifies p_ue, g_warningstream@*/ ; | |
37 | ||
38 | static cstring czechPrefix (cstring name) | |
39 | { | |
40 | return (cstring_beforeChar (name, '_')); | |
41 | } | |
42 | ||
43 | static cstring slovakPrefix (cstring name) | |
44 | { | |
45 | size_t 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 | size_t namelen = cstring_length (name); | |
123 | int last = (int) '\0'; | |
124 | size_t n = 1; | |
125 | ||
126 | cstring_chars (prefix, pc) | |
127 | { | |
128 | int nc; | |
129 | ||
130 | if (pc == '*') | |
131 | { | |
132 | n++; | |
133 | ||
134 | while (n <= namelen) | |
135 | { | |
136 | nc = (int) cstring_getChar (name, n); | |
137 | ||
138 | if (!matchPrefixChar (nc, last)) | |
139 | { | |
140 | return FALSE; | |
141 | } | |
142 | ||
143 | n++; | |
144 | } | |
145 | ||
146 | return TRUE; | |
147 | } | |
148 | else | |
149 | { | |
150 | if (n > namelen) | |
151 | { | |
152 | if (namelen > 1 | |
153 | && (cstring_length (prefix) >= n + 1) | |
154 | && cstring_getChar (prefix, n + 1) == '*') | |
155 | { | |
156 | return TRUE; | |
157 | } | |
158 | else | |
159 | { | |
160 | return FALSE; | |
161 | } | |
162 | } | |
163 | ||
164 | nc = (int) cstring_getChar (name, n); | |
165 | ||
166 | if (!matchPrefixChar (nc, (int) pc)) | |
167 | { | |
168 | return FALSE; | |
169 | } | |
170 | } | |
171 | ||
172 | last = (int) pc; | |
173 | n++; | |
174 | } end_cstring_chars; | |
175 | ||
176 | return TRUE; | |
177 | } | |
178 | } | |
179 | ||
180 | static flagcode | |
181 | namespaceExcluded (flagcode code) /*@*/ | |
182 | { | |
183 | switch (code) | |
184 | { | |
185 | case FLG_MACROVARPREFIXEXCLUDE: | |
186 | return (FLG_MACROVARPREFIX); | |
187 | case FLG_TAGPREFIXEXCLUDE: | |
188 | return (FLG_TAGPREFIX); | |
189 | case FLG_ENUMPREFIXEXCLUDE: | |
190 | return (FLG_ENUMPREFIX); | |
191 | case FLG_FILESTATICPREFIXEXCLUDE: | |
192 | return (FLG_FILESTATICPREFIX); | |
193 | case FLG_GLOBPREFIXEXCLUDE: | |
194 | return (FLG_GLOBPREFIX); | |
195 | case FLG_TYPEPREFIXEXCLUDE: | |
196 | return (FLG_TYPEPREFIX); | |
197 | case FLG_EXTERNALPREFIXEXCLUDE: | |
198 | return (FLG_EXTERNALPREFIX); | |
199 | case FLG_UNCHECKEDMACROPREFIXEXCLUDE: | |
200 | return (FLG_UNCHECKEDMACROPREFIX); | |
201 | case FLG_LOCALPREFIXEXCLUDE: | |
202 | return (FLG_LOCALPREFIX); | |
203 | case FLG_ITERPREFIXEXCLUDE: | |
204 | return (FLG_ITERPREFIX); | |
205 | case FLG_CONSTPREFIXEXCLUDE: | |
206 | return (FLG_CONSTPREFIX); | |
207 | BADDEFAULT; | |
208 | } | |
209 | } | |
210 | ||
211 | static /*@observer@*/ cstring | |
212 | namespaceName (flagcode flag) /*@*/ | |
213 | { | |
214 | switch (flag) | |
215 | { | |
216 | case FLG_MACROVARPREFIX: | |
217 | return cstring_makeLiteralTemp ("macro variable"); | |
218 | case FLG_TAGPREFIX: | |
219 | return cstring_makeLiteralTemp ("tag"); | |
220 | case FLG_ENUMPREFIX: | |
221 | return cstring_makeLiteralTemp ("enum member"); | |
222 | case FLG_TYPEPREFIX: | |
223 | return cstring_makeLiteralTemp ("user-defined type"); | |
224 | case FLG_FILESTATICPREFIX: | |
225 | return cstring_makeLiteralTemp ("file static"); | |
226 | case FLG_GLOBPREFIX: | |
227 | return cstring_makeLiteralTemp ("global variable"); | |
228 | case FLG_EXTERNALPREFIX: | |
229 | return cstring_makeLiteralTemp ("external"); | |
230 | case FLG_LOCALPREFIX: | |
231 | return cstring_makeLiteralTemp ("local variable"); | |
232 | case FLG_CONSTPREFIX: | |
233 | return cstring_makeLiteralTemp ("constant"); | |
234 | case FLG_ITERPREFIX: | |
235 | return cstring_makeLiteralTemp ("iter"); | |
236 | case FLG_UNCHECKEDMACROPREFIX: | |
237 | return cstring_makeLiteralTemp ("unchecked macro"); | |
238 | BADDEFAULT; | |
239 | } | |
240 | } | |
241 | ||
242 | void | |
243 | checkPrefix (uentry ue) | |
244 | { | |
245 | cstring name = cstring_undefined; | |
246 | flagcode flag; | |
247 | ||
248 | if (uentry_isExpandedMacro (ue)) | |
249 | { | |
250 | flag = FLG_UNCHECKEDMACROPREFIX; | |
251 | } | |
252 | else if (uentry_isAnyTag (ue)) | |
253 | { | |
254 | flag = FLG_TAGPREFIX; | |
255 | } | |
256 | else if (uentry_isEnumConstant (ue)) | |
257 | { | |
258 | flag = FLG_ENUMPREFIX; | |
259 | } | |
260 | else if (uentry_isDatatype (ue)) | |
261 | { | |
262 | flag = FLG_TYPEPREFIX; | |
263 | } | |
264 | else if (uentry_isFileStatic (ue)) | |
265 | { | |
266 | flag = FLG_FILESTATICPREFIX; | |
267 | } | |
268 | else if (uentry_isGlobalVariable (ue)) | |
269 | { | |
270 | flag = FLG_GLOBPREFIX; | |
271 | } | |
272 | else if (uentry_isVariable (ue)) | |
273 | { | |
274 | if (uentry_isRefParam (ue)) | |
275 | { | |
276 | return; /* already checked param */ | |
277 | } | |
278 | ||
279 | if (context_inMacro ()) | |
280 | { | |
281 | if (uentry_isAnyParam (ue)) | |
282 | { | |
283 | if (uentry_isYield (ue)) | |
284 | { | |
285 | flag = FLG_MACROVARPREFIX; | |
286 | } | |
287 | else | |
288 | { | |
289 | flag = FLG_LOCALPREFIX; | |
290 | } | |
291 | } | |
292 | else | |
293 | { | |
294 | flag = FLG_MACROVARPREFIX; | |
295 | } | |
296 | } | |
297 | else | |
298 | { | |
299 | flag = FLG_LOCALPREFIX; | |
300 | } | |
301 | } | |
302 | else if (uentry_isConstant (ue)) | |
303 | { | |
304 | flag = FLG_CONSTPREFIX; | |
305 | } | |
306 | else if (uentry_isIter (ue)) | |
307 | { | |
308 | flag = FLG_ITERPREFIX; | |
309 | } | |
310 | else if (uentry_isExported (ue)) | |
311 | { | |
312 | flag = FLG_EXTERNALPREFIX; | |
313 | } | |
314 | else | |
315 | { | |
316 | llcontbug (message ("What is it: %q", uentry_unparseFull (ue))); | |
317 | return; | |
318 | } | |
319 | ||
320 | if (flag == FLG_TYPEPREFIX || flag == FLG_GLOBPREFIX | |
321 | || flag == FLG_ENUMPREFIX || flag == FLG_CONSTPREFIX) | |
322 | { | |
323 | if (flag == FLG_ENUMPREFIX) | |
324 | { | |
325 | if (!context_getFlag (flag)) | |
326 | { | |
327 | flag = FLG_CONSTPREFIX; | |
328 | } | |
329 | } | |
330 | ||
331 | if (!context_getFlag (flag)) | |
332 | { | |
333 | flag = FLG_EXTERNALPREFIX; | |
334 | } | |
335 | } | |
336 | ||
337 | if (context_getFlag (flag)) | |
338 | { | |
339 | name = uentry_observeRealName (ue); | |
340 | ||
341 | if (!matchPrefix (name, context_getString (flag))) | |
342 | { | |
343 | llassert (flag != FLG_NAMECHECKS); | |
344 | ||
345 | if (optgenerror2 | |
346 | (flag, FLG_NAMECHECKS, | |
347 | message ("%s %s name is not consistent with %s " | |
348 | "namespace prefix \"%s\"", | |
349 | uentry_ekindName (ue), | |
350 | name, | |
351 | namespaceName (flag), | |
352 | context_getString (flag)), | |
353 | uentry_whereLast (ue))) | |
354 | { | |
355 | uentry_setHasNameError (ue); | |
356 | } | |
357 | } | |
358 | } | |
359 | ||
360 | excludeFlagCodes (code) | |
361 | { | |
362 | bool check = FALSE; | |
363 | ||
364 | if (context_getFlag (code)) | |
365 | { | |
366 | /*@-loopswitchbreak@*/ | |
367 | switch (code) | |
368 | { | |
369 | case FLG_MACROVARPREFIXEXCLUDE: | |
370 | check = (flag != FLG_MACROVARPREFIX); | |
371 | break; | |
372 | case FLG_TAGPREFIXEXCLUDE: | |
373 | check = (flag != FLG_TAGPREFIX); | |
374 | break; | |
375 | case FLG_ENUMPREFIXEXCLUDE: | |
376 | check = (flag != FLG_ENUMPREFIX); | |
377 | break; | |
378 | case FLG_FILESTATICPREFIXEXCLUDE: | |
379 | check = (flag != FLG_FILESTATICPREFIX); | |
380 | break; | |
381 | case FLG_GLOBPREFIXEXCLUDE: | |
382 | check = (flag != FLG_GLOBPREFIX); | |
383 | break; | |
384 | case FLG_TYPEPREFIXEXCLUDE: | |
385 | check = (flag != FLG_TYPEPREFIX); | |
386 | break; | |
387 | case FLG_EXTERNALPREFIXEXCLUDE: | |
388 | check = (flag != FLG_EXTERNALPREFIX | |
389 | && flag != FLG_GLOBPREFIX | |
390 | && flag != FLG_TYPEPREFIX | |
391 | && flag != FLG_UNCHECKEDMACROPREFIX); | |
392 | break; | |
393 | case FLG_UNCHECKEDMACROPREFIXEXCLUDE: | |
394 | check = (flag != FLG_UNCHECKEDMACROPREFIX); | |
395 | break; | |
396 | case FLG_LOCALPREFIXEXCLUDE: | |
397 | check = (flag != FLG_LOCALPREFIX); | |
398 | break; | |
399 | case FLG_CONSTPREFIXEXCLUDE: | |
400 | check = (flag != FLG_CONSTPREFIX); | |
401 | break; | |
402 | case FLG_ITERPREFIXEXCLUDE: | |
403 | check = (flag != FLG_ITERPREFIX); | |
404 | break; | |
405 | BADDEFAULT; | |
406 | } | |
407 | /*@=loopswitchbreak@*/ | |
408 | ||
409 | if (check) | |
410 | { | |
411 | flagcode rcode = namespaceExcluded (code); | |
412 | cstring pstring = context_getString (rcode); | |
413 | ||
414 | if (cstring_isDefined (pstring)) | |
415 | { | |
416 | if (cstring_isUndefined (name)) | |
417 | { | |
418 | name = uentry_observeRealName (ue); | |
419 | } | |
420 | ||
421 | if (matchPrefix (name, context_getString (rcode))) | |
422 | { | |
423 | if (optgenerror2 | |
424 | (code, FLG_NAMECHECKS, | |
425 | message | |
426 | ("%s %s name is not a %s (it is a %s), " | |
427 | "but matches the %s " | |
428 | "namespace prefix \"%s\"", | |
429 | uentry_ekindName (ue), | |
430 | name, | |
431 | namespaceName (rcode), | |
432 | namespaceName (flag), | |
433 | namespaceName (rcode), | |
434 | context_getString (rcode)), | |
435 | uentry_whereLast (ue))) | |
436 | { | |
437 | uentry_setHasNameError (ue); | |
438 | } | |
439 | } | |
440 | } | |
441 | } | |
442 | } | |
443 | } end_excludeFlagCodes ; | |
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_isGlobalVariable (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_isGlobalVariable (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 (optgenerror2 | |
536 | (FLG_CZECHOSLOVAKTYPES, FLG_NAMECHECKS, | |
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 (optgenerror2 | |
553 | (FLG_CZECHOSLOVAKTYPES, FLG_NAMECHECKS, | |
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 (optgenerror2 | |
579 | (czechoslovakflag, FLG_NAMECHECKS, | |
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 (optgenerror2 | |
612 | (FLG_CZECHTYPES, FLG_NAMECHECKS, | |
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 (optgenerror2 | |
647 | (czechflag, FLG_NAMECHECKS, | |
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 (optgenerror2 | |
675 | (czechflag, FLG_NAMECHECKS, | |
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 (optgenerror2 | |
823 | (czechflag, FLG_NAMECHECKS, | |
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 (optgenerror2 | |
867 | (FLG_SLOVAKTYPES, FLG_NAMECHECKS, | |
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 (optgenerror2 | |
902 | (slovakflag, FLG_NAMECHECKS, | |
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 (optgenerror2 | |
926 | (slovakflag, FLG_NAMECHECKS, | |
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 (optgenerror2 | |
1071 | (slovakflag, FLG_NAMECHECKS, | |
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 | checkExternalName (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 | ** No local checks (yet) | |
1115 | */ | |
1116 | ||
1117 | return; | |
1118 | } | |
1119 | ||
1120 | void | |
1121 | checkFileScopeName (/*@unused@*/ uentry ue) | |
1122 | { | |
1123 | /* | |
1124 | ** No file scope checks (yet) | |
1125 | */ | |
1126 | ||
1127 | /*@i423 add a file scope naming convention policy? */ | |
1128 | ||
1129 | return; | |
1130 | } | |
1131 | ||
1132 | /* | |
1133 | ** Checks a name used by user source is not reserved by ANSI | |
1134 | ** (or for future library functions). | |
1135 | ** | |
1136 | ** The restrictions are described in X3.159-1989: 4.13 | |
1137 | */ | |
1138 | ||
1139 | /*@constant int NRESERVEDNAMES; @*/ | |
1140 | # define NRESERVEDNAMES 201 | |
1141 | ||
1142 | /*@constant int NCPPNAMES@*/ | |
1143 | # define NCPPNAMES 39 | |
1144 | ||
1145 | void | |
1146 | checkCppName (uentry ue) | |
1147 | { | |
1148 | cstring name = uentry_observeRealName (ue); | |
1149 | ||
1150 | static ob_mstring cppNames[NCPPNAMES] = | |
1151 | { | |
1152 | "and", "and_eq", "asm", | |
1153 | "bitand", "bitor", "bool", /* gasp: "bool", is special for splint */ | |
1154 | "catch", "class", "compl", "const_class", | |
1155 | "delete", "dynamic_cast", "false", "friend", | |
1156 | "inline", "mutable", "namespace", "new", | |
1157 | "not", "not_eq", | |
1158 | "operator", "or", "or_eq", "overload", | |
1159 | "private", "protected", "public", | |
1160 | "reinterpret_cast", "static_cast", | |
1161 | "template", "this", "throw", "true", "try", | |
1162 | "typeid", "using", "virtual", "xor", "xor_eq" | |
1163 | } ; | |
1164 | ||
1165 | if (cstring_isDefined (cstring_bsearch (name, &cppNames[0], | |
1166 | NCPPNAMES))) | |
1167 | { | |
1168 | if (optgenerror2 | |
1169 | (FLG_CPPNAMES, FLG_NAMECHECKS, | |
1170 | message ("Name %s is a keyword or reserved word in C++", | |
1171 | name), | |
1172 | uentry_whereLast (ue))) | |
1173 | { | |
1174 | uentry_setHasNameError (ue); | |
1175 | } | |
1176 | } | |
1177 | } | |
1178 | ||
1179 | void | |
1180 | checkAnsiName (uentry ue) | |
1181 | { | |
1182 | bool hasError = FALSE; | |
1183 | cstring name = uentry_observeRealName (ue); | |
1184 | size_t length = cstring_length (name); | |
1185 | char fchar = (length >= 1) ? cstring_firstChar (name) : '\0'; | |
1186 | char schar = (length >= 2) ? cstring_secondChar (name) : '\0'; | |
1187 | char tchar = (length >= 3) ? cstring_getChar (name, 3) : '\0'; | |
1188 | char rchar = (length >= 4) ? cstring_getChar (name, 4) : '\0'; | |
1189 | ||
1190 | /* | |
1191 | ** reservedNames | |
1192 | ** taken from Linden, "Expert C Programming", p. 126-8. | |
1193 | ** invariant: must be sorted (case-insensitive, lexicographically) | |
1194 | ** must end with NULL | |
1195 | */ | |
1196 | ||
1197 | static ob_mstring reservedNames[NRESERVEDNAMES] = | |
1198 | { | |
1199 | # include "reservedNames.nf" | |
1200 | } ; | |
1201 | ||
1202 | # if 0 | |
1203 | /* | |
1204 | ** This code is for checking reservedNames.nf | |
1205 | */ | |
1206 | ||
1207 | { | |
1208 | int i = 0; | |
1209 | char *lastname = NULL; | |
1210 | char *name; | |
1211 | ||
1212 | while ((name = reservedNames[i]) != NULL) | |
1213 | { | |
1214 | llassertprint (lastname == NULL | |
1215 | || strcmp (name, lastname) > 0, | |
1216 | ("%s / %s", lastname, name)); | |
1217 | lastname = name; | |
1218 | i++; | |
1219 | } | |
1220 | ||
1221 | nreservedNames = i - 1; | |
1222 | } | |
1223 | # endif | |
1224 | ||
1225 | if (fileloc_isSystemFile (uentry_whereLast (ue)) || fileloc_isBuiltin (uentry_whereLast (ue))) | |
1226 | { | |
1227 | return; /* no errors for system files */ | |
1228 | } | |
1229 | ||
1230 | if (cstring_isDefined (cstring_bsearch (name, &reservedNames[0], | |
1231 | NRESERVEDNAMES))) | |
1232 | { | |
1233 | hasError |= optgenerror2 | |
1234 | (FLG_ISORESERVED, FLG_NAMECHECKS, | |
1235 | message ("Name %s is reserved for the standard library", | |
1236 | name), | |
1237 | uentry_whereLast (ue)); | |
1238 | } | |
1239 | ||
1240 | if (uentry_isFileStatic (ue) || uentry_isVisibleExternally (ue) || uentry_isAnyTag (ue) | |
1241 | || context_getFlag (FLG_ISORESERVEDLOCAL)) | |
1242 | { | |
1243 | if (fchar == '_') | |
1244 | { | |
1245 | hasError |= optgenerror2 | |
1246 | (FLG_ISORESERVED, FLG_NAMECHECKS, | |
1247 | message | |
1248 | ("Name %s is in the implementation name space (any identifier " | |
1249 | "beginning with underscore)", | |
1250 | name), | |
1251 | uentry_whereLast (ue)); | |
1252 | } | |
1253 | } | |
1254 | else | |
1255 | { | |
1256 | /* | |
1257 | ** ISO 7.1.3: | |
1258 | ** - All identifiers that begin with an underscore and either an uppercase | |
1259 | ** letter or another underscore are always reserved for any use. | |
1260 | */ | |
1261 | ||
1262 | if (fchar == '_' | |
1263 | && (schar == '_' || isupper ((int) schar))) | |
1264 | { | |
1265 | hasError |= optgenerror2 | |
1266 | (FLG_ISORESERVED, FLG_NAMECHECKS, | |
1267 | message | |
1268 | ("Name %s is in the implementation name space (any identifier " | |
1269 | "beginning with underscore and either an uppercase letter or " | |
1270 | "another underscore is always reserved for any use)", | |
1271 | name), | |
1272 | uentry_whereLast (ue)); | |
1273 | } | |
1274 | } | |
1275 | ||
1276 | /* | |
1277 | ** 4.13.1 Errors <errno.h> | |
1278 | ** | |
1279 | ** Macros that begin with E and a digit or E and an uppercase letter ... | |
1280 | */ | |
1281 | ||
1282 | if (fchar == 'E' && (isdigit ((int) schar) | |
1283 | || isupper ((int) schar))) | |
1284 | { | |
1285 | hasError |= optgenerror2 | |
1286 | (FLG_ISORESERVED, FLG_NAMECHECKS, | |
1287 | message | |
1288 | ("Name %s is reserved for future library extensions. " | |
1289 | "Macros beginning with E and a digit or uppercase letter " | |
1290 | "may be added to <errno.h>. (ISO99:7.26.3)", | |
1291 | name), | |
1292 | uentry_whereLast (ue)); | |
1293 | } | |
1294 | ||
1295 | /* | |
1296 | ** 4.13.3 Localization <locale.h> | |
1297 | ** | |
1298 | ** Macros that begin with LC_ and an uppercase letter ... | |
1299 | */ | |
1300 | ||
1301 | if (length >= 4 | |
1302 | && ((fchar == 'L') | |
1303 | && (schar == 'C') | |
1304 | && (tchar == '_')) | |
1305 | && (isupper ((int) rchar))) | |
1306 | { | |
1307 | hasError |= optgenerror2 | |
1308 | (FLG_ISORESERVED, FLG_NAMECHECKS, | |
1309 | message | |
1310 | ("Name %s is reserved for future library extensions. " | |
1311 | "Macros beginning with \"LC_\" and an uppercase letter may " | |
1312 | "be added to <locale.h>. (ISO99:7.26.5)", | |
1313 | name), | |
1314 | uentry_whereLast (ue)); | |
1315 | } | |
1316 | ||
1317 | /* | |
1318 | ** 4.13.5 Signal Handling <signal.h> | |
1319 | ** | |
1320 | ** Macros that begin with either SIG or SIG_ and an uppercase letter or... | |
1321 | */ | |
1322 | ||
1323 | if (fchar == 'S' && schar == 'I' && tchar == 'G' | |
1324 | && ((rchar == '_' && ((length >= 5 | |
1325 | && isupper ((int) cstring_getChar (name, 5))))) | |
1326 | || (isupper ((int) rchar)))) | |
1327 | { | |
1328 | hasError |= optgenerror2 | |
1329 | (FLG_ISORESERVED, FLG_NAMECHECKS, | |
1330 | message | |
1331 | ("Name %s is reserved for future library extensions. " | |
1332 | "Macros that begin with SIG and an uppercase letter or SIG_ " | |
1333 | "and an uppercase letter may be added to " | |
1334 | "<signal.h>. (ISO99:7.14)", | |
1335 | name), | |
1336 | uentry_whereLast (ue)); | |
1337 | } | |
1338 | ||
1339 | DPRINTF (("Here...")); | |
1340 | ||
1341 | if ((uentry_isVisibleExternally (ue) && !uentry_isAnyTag (ue)) | |
1342 | || context_getFlag (FLG_ISORESERVEDLOCAL)) | |
1343 | { | |
1344 | flagcode flg; | |
1345 | ||
1346 | DPRINTF (("Okay...: %s", uentry_unparse (ue))); | |
1347 | ||
1348 | if (uentry_isVisibleExternally (ue) && !uentry_isAnyTag (ue)) | |
1349 | { | |
1350 | flg = FLG_ISORESERVED; | |
1351 | } | |
1352 | else | |
1353 | { | |
1354 | flg = FLG_ISORESERVEDLOCAL; | |
1355 | } | |
1356 | ||
1357 | DPRINTF (("ue: %s", uentry_unparseFull (ue))); | |
1358 | ||
1359 | /* | |
1360 | ** These restrictions only apply to identifiers with global linkage. | |
1361 | */ | |
1362 | ||
1363 | /* | |
1364 | ** 4.13.2 Character Handling <ctype.h> | |
1365 | ** | |
1366 | ** Function names that begin with either "is" or "to" and a lowercase letter ... | |
1367 | */ | |
1368 | ||
1369 | if (((fchar == 'i' && schar == 's') | |
1370 | || (fchar == 't' && schar == 'o')) | |
1371 | && (islower ((int) tchar))) | |
1372 | { | |
1373 | hasError |= optgenerror2 | |
1374 | (flg, FLG_NAMECHECKS, | |
1375 | message | |
1376 | ("Name %s is reserved for future library extensions. " | |
1377 | "Functions beginning with \"is\" or \"to\" and a lowercase " | |
1378 | "letter may be added to <ctype.h>. (ISO99:7.26.2)", | |
1379 | name), | |
1380 | uentry_whereLast (ue)); | |
1381 | ||
1382 | DPRINTF (("Externally visible: %s / %s", | |
1383 | uentry_unparseFull (ue), | |
1384 | bool_unparse (uentry_isVisibleExternally (ue)))); | |
1385 | } | |
1386 | ||
1387 | ||
1388 | /* | |
1389 | ** 4.13.4 Mathematics <math.h> | |
1390 | ** | |
1391 | ** The names of all existing functions declared in the <math.h> header, | |
1392 | ** suffixed with f or l... | |
1393 | */ | |
1394 | ||
1395 | DPRINTF (("Check name: %s", name)); | |
1396 | ||
1397 | if ((cstring_lastChar (name) == 'f' || cstring_lastChar (name) == 'l') | |
1398 | && | |
1399 | (((length == 4) | |
1400 | && ((cstring_equalPrefixLit (name, "cos") || | |
1401 | cstring_equalPrefixLit (name, "sin") || | |
1402 | cstring_equalPrefixLit (name, "tan") || | |
1403 | cstring_equalPrefixLit (name, "exp") || | |
1404 | cstring_equalPrefixLit (name, "log") || | |
1405 | cstring_equalPrefixLit (name, "pow")))) | |
1406 | || ((length == 5) | |
1407 | && ((cstring_equalPrefixLit (name, "acos") || | |
1408 | cstring_equalPrefixLit (name, "asin") || | |
1409 | cstring_equalPrefixLit (name, "atan") || | |
1410 | cstring_equalPrefixLit (name, "cosh") || | |
1411 | cstring_equalPrefixLit (name, "sinh") || | |
1412 | cstring_equalPrefixLit (name, "sqrt") || | |
1413 | cstring_equalPrefixLit (name, "ceil") || | |
1414 | cstring_equalPrefixLit (name, "fabs") || | |
1415 | cstring_equalPrefixLit (name, "fmod") || | |
1416 | cstring_equalPrefixLit (name, "tanh") || | |
1417 | cstring_equalPrefixLit (name, "modf")))) | |
1418 | || ((length == 6) | |
1419 | && ((cstring_equalPrefixLit (name, "atan2") || | |
1420 | cstring_equalPrefixLit (name, "floor") || | |
1421 | cstring_equalPrefixLit (name, "frexp") || | |
1422 | cstring_equalPrefixLit (name, "ldexp") || | |
1423 | cstring_equalPrefixLit (name, "log10")))))) | |
1424 | { | |
1425 | hasError |= optgenerror2 | |
1426 | (flg, FLG_NAMECHECKS, | |
1427 | message | |
1428 | ("Name %s is reserved for future library extensions. " | |
1429 | "The names of all existing functions in <math.h> suffixed " | |
1430 | "with 'f' or 'l' may be added to <math.h>. (ISO:7.26.1)", | |
1431 | name), | |
1432 | uentry_whereLast (ue)); | |
1433 | } | |
1434 | ||
1435 | /* | |
1436 | ** 4.13.6 Input/Output <stdio.h> | |
1437 | ** | |
1438 | ** (nothing to check) | |
1439 | */ | |
1440 | ||
1441 | /* | |
1442 | ** 4.13.7 General Utilities <stdlib.h> | |
1443 | ** | |
1444 | ** Functions names that begin with str and a lowercase letter may be added to <stdlib.h>. | |
1445 | */ | |
1446 | ||
1447 | if (fchar == 's' && schar == 't' && tchar == 'r' | |
1448 | && (islower ((int) rchar))) | |
1449 | { | |
1450 | hasError |= optgenerror2 | |
1451 | (flg, FLG_NAMECHECKS, | |
1452 | message | |
1453 | ("Name %s is reserved for future library extensions. " | |
1454 | "Functions that begin with \"str\" and a lowercase letter " | |
1455 | "may be added to <stdlib.h> or <string.h>. (ISO99:7.26.9)", | |
1456 | name), | |
1457 | uentry_whereLast (ue)); | |
1458 | } | |
1459 | ||
1460 | /* | |
1461 | ** 4.13.8 String Handling <string.h> | |
1462 | ** | |
1463 | ** Function names that begin with str, mem, or wcs and a lowercase letter ... | |
1464 | ** | |
1465 | ** (Note: already checked "str" above.) | |
1466 | */ | |
1467 | ||
1468 | if (((fchar == 'm' && schar == 'e' && tchar == 'm') | |
1469 | || (fchar == 'w' && schar == 'c' && tchar == 's')) | |
1470 | && (islower ((int) rchar))) | |
1471 | { | |
1472 | hasError |= optgenerror2 | |
1473 | (flg, FLG_NAMECHECKS, | |
1474 | message | |
1475 | ("Name %s is reserved for future library extensions. " | |
1476 | "Functions that begin with \"mem\" or \"wcs\" and a " | |
1477 | "lowercase letter letter may be added to <string.h>. (ISO:7.26.11)", | |
1478 | name), | |
1479 | uentry_whereLast (ue)); | |
1480 | } | |
1481 | } | |
1482 | else | |
1483 | { | |
1484 | DPRINTF (("Not checked: [%s] %s", bool_unparse (uentry_isVisibleExternally (ue)), | |
1485 | uentry_unparseFull (ue))); | |
1486 | } | |
1487 | ||
1488 | if (hasError) | |
1489 | { | |
1490 | uentry_setHasNameError (ue); | |
1491 | } | |
1492 | } | |
1493 | ||
1494 | void checkParamNames (uentry ue) | |
1495 | { | |
1496 | cstring fpfx = context_getString (FLG_DECLPARAMPREFIX); | |
1497 | bool noformal = context_getFlag (FLG_DECLPARAMNAME); | |
1498 | ||
1499 | llassert (uentry_isFunction (ue)); | |
1500 | ||
1501 | if (cstring_isDefined (fpfx) || noformal) | |
1502 | { | |
1503 | uentryList params = uentry_getParams (ue); | |
1504 | ||
1505 | uentryList_elements (params, p) | |
1506 | { | |
1507 | if (uentry_hasName (p)) | |
1508 | { | |
1509 | if (noformal && !cstring_isDefined (fpfx)) | |
1510 | { | |
1511 | if (optgenerror2 | |
1512 | (FLG_DECLPARAMNAME, FLG_NAMECHECKS, | |
1513 | message ("Declaration parameter has name: %q", | |
1514 | uentry_getName (p)), | |
1515 | uentry_whereLast (p))) | |
1516 | { | |
1517 | uentry_setHasNameError (p); | |
1518 | } | |
1519 | } | |
1520 | else | |
1521 | { | |
1522 | cstring pname = uentry_observeRealName (p); | |
1523 | ||
1524 | if (!cstring_equalPrefix (pname, fpfx)) | |
1525 | { | |
1526 | if (context_getFlag (FLG_NAMECHECKS)) | |
1527 | { | |
1528 | if (optgenerror2 | |
1529 | (FLG_DECLPARAMPREFIX, FLG_NAMECHECKS, | |
1530 | message ("Declaration parameter name %s does not begin " | |
1531 | "with protoparamprefix (%s)", | |
1532 | pname, fpfx), | |
1533 | uentry_whereLast (p))) | |
1534 | { | |
1535 | uentry_setHasNameError (p); | |
1536 | } | |
1537 | } | |
1538 | } | |
1539 | } | |
1540 | } | |
1541 | } end_uentryList_elements ; | |
1542 | } | |
1543 | } | |
1544 | ||
1545 | /*@i523 POSIX p. 527 - applications should not declare any symbols that end _MAX @*/ |