]> andersk Git - splint.git/blob - src/cprim.c
df3b7095016de6db85dde9625cb429ba7f129fb8
[splint.git] / src / cprim.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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 ** cprim.c
26 */
27
28 # include "splintMacros.nf"
29 # include "basic.h"
30
31 static bool cprim_isReal (cprim c)
32 {
33   return (cprim_isAnyReal (c));
34 }
35
36 static bool cprim_isNumeric (cprim c)
37 {
38   return (cprim_isReal (c) || cprim_isInt (c));
39 }
40
41 cprim
42 cprim_fromInt (int i)
43 {
44   if (i < CTX_UNKNOWN || i > CTX_LAST)
45     {
46       llcontbug (message ("cprim_fromInt: out of range: %d", i));
47       return CTX_UNKNOWN;
48     }
49   return (cprim) i;
50 }
51
52
53 /*
54 ** not symmetric:  c1 := c2 or c2 is passed as c1
55 **    (if RELAXQUALS, c1 must be "bigger" than c2)
56 */
57
58 static bool cprim_closeEnoughAux (cprim p_c1, cprim p_c2, bool p_deep);
59
60 bool
61 cprim_closeEnoughDeep (cprim c1, cprim c2) 
62 {
63   /*
64   ** If * c2 is passed as * c1
65   ** Comparison is slightly different since it is safe to pass int as long,
66   ** but not to pass int * as long *!
67   **
68   ** For deep comparisons, +relaxquals does not permit the long/int break.
69   */
70
71   return cprim_closeEnoughAux (c1, c2, TRUE);
72 }
73
74 bool
75 cprim_closeEnough (cprim c1, cprim c2)
76 {
77   return cprim_closeEnoughAux (c1, c2, FALSE);
78 }
79
80 static bool
81 cprim_closeEnoughAux (cprim c1, cprim c2, bool deep)
82 {
83   if (c1 == c2) return TRUE;
84
85   DPRINTF (("cprim close: %s / %s", cprim_unparse (c1), cprim_unparse (c2)));
86
87   if (c1 == CTX_ANYINTEGRAL)
88     {
89       if (context_getFlag (FLG_MATCHANYINTEGRAL)
90           || context_getFlag (FLG_IGNOREQUALS))
91         {
92           return (cprim_isAnyInt (c2)
93                   || (cprim_isAnyChar (c2) && context_msgCharInt ()));
94         }
95       else if (context_getFlag (FLG_LONGINTEGRAL))
96         {
97           return (cprim_closeEnough (CTX_LINT, c2));
98         }
99       else if (context_getFlag (FLG_LONGUNSIGNEDINTEGRAL))
100         {
101           return (cprim_closeEnough (CTX_ULINT, c2));
102         }
103       else
104         {
105           return FALSE;
106         }
107     }
108
109   if (c1 == CTX_UNSIGNEDINTEGRAL)
110     {
111       if (context_getFlag (FLG_MATCHANYINTEGRAL)
112           || context_getFlag (FLG_IGNOREQUALS))
113         {
114           if (context_getFlag (FLG_IGNORESIGNS)) 
115             {
116               return (cprim_isAnyUnsignedInt (c2)
117                       || (cprim_isUnsignedChar (c2) && context_msgCharInt ()));
118             }
119           else
120             {
121               return (cprim_isAnyInt (c2)
122                       || (cprim_isAnyChar (c2) && context_msgCharInt ()));
123             }
124         }
125       else if (context_getFlag (FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL))
126         {
127           return (cprim_closeEnough (CTX_ULINT, c2));
128         }
129       else
130         {
131           return FALSE;
132         }
133     }
134
135   if (c1 == CTX_SIGNEDINTEGRAL)
136     {
137       if (context_getFlag (FLG_MATCHANYINTEGRAL)
138           || context_getFlag (FLG_IGNOREQUALS))
139         {
140           return (cprim_isAnyInt (c2)
141                   || (cprim_isAnyChar (c2) && context_msgCharInt ()));
142         }
143       else if (context_getFlag (FLG_LONGSIGNEDINTEGRAL))
144         {
145           return (cprim_closeEnough (CTX_LINT, c2));
146         }
147       else
148         {
149           return FALSE;
150         }
151     }
152
153   if (c2 == CTX_ANYINTEGRAL)
154     {
155       if (context_getFlag (FLG_MATCHANYINTEGRAL))
156         {
157           return (cprim_isAnyInt (c1)
158                   || (cprim_isAnyChar (c1) && context_msgCharInt ()));
159         }
160       else if (context_getFlag (FLG_LONGINTEGRAL))
161         {
162           return (cprim_closeEnough (c1, CTX_LINT));
163         }
164       else if (context_getFlag (FLG_LONGUNSIGNEDINTEGRAL))
165         {
166           return (cprim_closeEnough (c1, CTX_ULINT));
167         }
168       else
169         {
170           return FALSE;
171         }
172     }
173
174   if (c2 == CTX_UNSIGNEDINTEGRAL)
175     {
176       if (context_getFlag (FLG_MATCHANYINTEGRAL))
177         {
178           return (cprim_isAnyInt (c1)
179                   || (cprim_isAnyChar (c1) && context_msgCharInt ()));
180         }
181       else if (context_getFlag (FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL))
182         {
183           return (cprim_closeEnough (c1, CTX_ULINT));
184         }
185       else
186         {
187           return FALSE;
188         }
189     }
190
191   if (c2 == CTX_SIGNEDINTEGRAL)
192     {
193       if (context_getFlag (FLG_MATCHANYINTEGRAL))
194         {
195           return (cprim_isAnyInt (c2)
196                   || (cprim_isAnyChar (c2) && context_msgCharInt ()));
197         }
198       else if (context_getFlag (FLG_LONGSIGNEDINTEGRAL))
199         {
200           return (cprim_closeEnough (c1, CTX_LINT));
201         }
202       else
203         {
204           return FALSE;
205         }
206     }
207
208
209   DPRINTF (("cprim close: %s / %s", cprim_unparse (c1), cprim_unparse (c2)));
210
211   if (context_getFlag (FLG_RELAXTYPES))
212     {
213       if (cprim_isNumeric (c1) && cprim_isNumeric (c2)) return TRUE;
214     }
215
216   if (context_getFlag (FLG_IGNOREQUALS))
217     {
218       switch (c1)
219         {
220         case CTX_CHAR:
221         case CTX_UCHAR:
222           if (cprim_isAnyChar (c2) 
223               || (cprim_isAnyInt (c2) && (context_msgCharInt ()))) {
224             return TRUE;
225           } 
226           break;
227         case CTX_DOUBLE:
228         case CTX_FLOAT:
229         case CTX_LDOUBLE:
230           if (c2 == CTX_DOUBLE || c2 == CTX_FLOAT || c2 == CTX_LDOUBLE) {
231             return TRUE;
232           }
233           break;
234         case CTX_INT:
235         case CTX_LINT:
236         case CTX_LLINT:
237         case CTX_ULLINT:
238         case CTX_SINT:
239         case CTX_UINT:
240         case CTX_ULINT:
241         case CTX_USINT:
242           if (cprim_isAnyInt (c2) 
243               || (cprim_isAnyChar (c2) && context_msgCharInt ())) {
244             return TRUE;
245           }
246           /*@fallthrough@*/ 
247         default:
248           ;
249         }
250     }
251
252   if (context_getFlag (FLG_IGNORESIGNS))
253     {
254       if (c1 == CTX_UCHAR)  
255         {
256           c1 = CTX_CHAR;
257         }
258       else if (c1 == CTX_UINT)  
259         {
260           c1 = CTX_INT;
261         }
262       else if (c1 == CTX_ULINT) 
263         {
264           c1 = CTX_LINT;
265         }
266       /* 2001-06-10: This fix provided by Jim Zelenka: */
267       else if (c1 == CTX_ULLINT) 
268         {
269           c1 = CTX_LLINT;
270         }
271       /* End fix */
272       else if (c1 == CTX_USINT)  
273         {
274           c1 = CTX_SINT;
275         }
276       else
277         {
278           ;
279         }
280       
281       if (c2 == CTX_UCHAR)  
282         {
283           c2 = CTX_CHAR;
284         }
285       else if (c2 == CTX_UINT)   
286         {
287           c2 = CTX_INT;
288         }
289       else if (c2 == CTX_ULINT) 
290         {
291           c2 = CTX_LINT;
292         }
293       /* 2001-06-10: This fix provided by Jim Zelenka: */
294       else if (c2 == CTX_ULLINT)
295         {
296           c2 = CTX_LLINT;
297         }
298       /* End fix */
299       else if (c2 == CTX_USINT)  
300         {
301           c2 = CTX_SINT;
302         }
303       else
304         {
305           ;
306         }
307     }
308
309   if (c1 == c2) return TRUE;
310   
311   if (context_getFlag (FLG_FLOATDOUBLE))
312     {
313       if (c1 == CTX_FLOAT && c2 == CTX_DOUBLE) 
314         {
315           return TRUE;
316         }
317       if (c2 == CTX_FLOAT && c1 == CTX_DOUBLE)
318         {
319           return TRUE;
320         }
321     }
322   
323   DPRINTF (("cprim close: %s / %s", cprim_unparse (c1), cprim_unparse (c2)));
324   
325   if (!deep && context_getFlag (FLG_RELAXQUALS))
326     {
327       switch (c1)
328         {
329         case CTX_DOUBLE:
330           return (c2 == CTX_FLOAT);
331         case CTX_LDOUBLE:
332           return (c2 == CTX_DOUBLE || c2 == CTX_FLOAT);
333         case CTX_SINT:
334           return ((c2 == CTX_CHAR && context_msgCharInt ()) 
335                   || (c2 == CTX_INT && context_msgShortInt ())
336                   || (c2 == CTX_LINT && context_msgShortInt () && context_msgLongInt ()));
337
338         case CTX_INT:
339           return ((c2 == CTX_SINT
340                    || (cprim_isAnyChar (c2) && context_msgCharInt ())
341                    || (c2 == CTX_LINT && context_msgLongInt ())));
342
343         case CTX_LLINT:
344           return (c2 == CTX_SINT
345                   || c2 == CTX_INT 
346                       || c2 == CTX_LINT
347                   || (cprim_isAnyChar (c2) && context_msgCharInt ()));
348         case CTX_ULLINT:
349           return (c2 == CTX_USINT
350                   || c2 == CTX_UINT 
351                   || c2 == CTX_ULINT
352                   /* 2001-06-10: This fix provided by Jim Zelenka: */
353                   || (cprim_isAnyChar (c2) && context_msgCharInt ()));
354         case CTX_LINT:
355           return (c2 == CTX_SINT
356                   || c2 == CTX_INT 
357                   || (cprim_isAnyChar (c2) && context_msgCharInt ()));
358         case CTX_UINT:
359           return (c2 == CTX_USINT 
360                   || (c2 == CTX_UCHAR && context_msgCharInt ()));
361         case CTX_USINT:
362           return (c2 == CTX_UCHAR && context_msgCharInt ());
363         case CTX_ULINT:
364           /* 2001-06-10: This fix provided by Jim Zelenka: */
365           return (c2 == CTX_UINT || c2 == CTX_USINT
366                   || (c2 == CTX_UCHAR && context_msgCharInt()));
367         case CTX_UCHAR:
368           return (c2 == CTX_UINT && context_msgCharInt ());
369         case CTX_CHAR:
370           return ((c2 == CTX_INT || c2 == CTX_SINT)
371                   && context_msgCharInt ());
372         default:
373           return FALSE;
374         }
375     }
376   else
377     {
378       switch (c1)
379         {
380         case CTX_DOUBLE:
381         case CTX_LDOUBLE:
382           return FALSE;
383         case CTX_SINT:
384           if (c2 == CTX_INT && context_msgShortInt ()) {
385             return TRUE;
386           }
387           /*@fallthrough@*/
388         case CTX_INT:
389           if (c2 == CTX_INT && context_msgLongInt ()) {
390             return TRUE;
391           }
392           
393           if (c2 == CTX_SINT && context_msgShortInt ()) {
394             return TRUE;
395           }
396           /*@fallthrough@*/
397         case CTX_LINT:
398           if (c2 == CTX_INT && context_msgLongInt ()) {
399             return TRUE;
400           }
401           /*@fallthrough@*/
402         case CTX_LLINT:
403           return (c2 == CTX_CHAR && context_msgCharInt ());
404         case CTX_UINT:
405         case CTX_USINT:
406         case CTX_ULINT:
407         case CTX_ULLINT:
408           return (c2 == CTX_UCHAR && context_msgCharInt ());
409         case CTX_UCHAR:
410           return (c2 == CTX_UINT && context_msgCharInt ());
411         case CTX_CHAR:
412           return ((c2 == CTX_INT || c2 == CTX_SINT)
413                   && context_msgCharInt ());
414         default:
415           return FALSE;
416         }
417     }
418 }
419
420 /*@only@*/ cstring
421 cprim_unparse (cprim c)
422 {
423   switch (c)
424     {
425     case CTX_UNKNOWN:
426       return cstring_makeLiteral ("-");
427     case CTX_VOID:
428       return cstring_makeLiteral ("void");
429     case CTX_CHAR:
430       return cstring_makeLiteral ("char");
431     case CTX_UCHAR:
432       return cstring_makeLiteral ("unsigned char");
433    case CTX_DOUBLE:
434       return cstring_makeLiteral ("double");
435     case CTX_LDOUBLE:
436       return cstring_makeLiteral ("long double");
437     case CTX_FLOAT:
438       return cstring_makeLiteral ("float");
439     case CTX_INT:
440       return cstring_makeLiteral ("int");
441     case CTX_LINT:
442       return cstring_makeLiteral ("long int");
443     case CTX_LLINT:
444       return cstring_makeLiteral ("long long");
445     case CTX_ULLINT:
446       return cstring_makeLiteral ("unsigned long long");
447     case CTX_SINT:
448       return cstring_makeLiteral ("short int");
449     case CTX_UINT:
450       return cstring_makeLiteral ("unsigned int");
451     case CTX_ULINT:
452       return cstring_makeLiteral ("unsigned long int");
453     case CTX_USINT:
454       return cstring_makeLiteral ("unsigned short int");
455     case CTX_UNSIGNEDINTEGRAL:
456       return cstring_makeLiteral ("arbitrary unsigned integral type");
457     case CTX_SIGNEDINTEGRAL:
458       return cstring_makeLiteral ("arbitrary signed integral type");
459     case CTX_ANYINTEGRAL:
460       return cstring_makeLiteral ("arbitrary integral type");
461     default:
462       return cstring_makeLiteral ("unknown prim");
463     }
464 }
465
466 bool cprim_isInt (cprim c) 
467 {
468   return (cprim_isAnyInt (c)
469           || (cprim_isAnyChar (c) && context_msgCharInt ()));
470 }
471     
472 int cprim_getExpectedBits (cprim c)
473 {
474   /* Any basis to these numbers?  Just guesses for now..., check ISO spec */
475   switch (c)
476     {
477     case CTX_UNKNOWN:
478       return 0;
479     case CTX_VOID:
480       return 0;
481     case CTX_CHAR:
482       return 8;
483     case CTX_UCHAR:
484       return 8;
485    case CTX_DOUBLE:
486       return 64;
487     case CTX_LDOUBLE:
488       return 128;
489     case CTX_FLOAT:
490       return 32;
491     case CTX_INT:
492       return 32;
493     case CTX_LINT:
494       return 64;
495     case CTX_LLINT:
496       return 128;
497     case CTX_ULLINT:
498       return 128;
499     case CTX_SINT:
500       return 8;
501     case CTX_UINT:
502       return 32;
503     case CTX_ULINT:
504       return 64;
505     case CTX_USINT:
506       return 8;
507     case CTX_UNSIGNEDINTEGRAL:
508       return 64;
509     case CTX_SIGNEDINTEGRAL:
510       return 64;
511     case CTX_ANYINTEGRAL:
512       return 64;
513     default:
514       return 0;
515     }
516 }
This page took 0.071981 seconds and 3 git commands to generate.