]> andersk Git - splint.git/blob - src/cprim.c
Fixed scanf %x problem.
[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       /* We allow signed ints to match any integral if matchanyintegral is set */
112       if (context_getFlag (FLG_MATCHANYINTEGRAL)) {
113         return (cprim_isAnyInt (c2)
114                 || (cprim_isAnyChar (c2) && context_msgCharInt ()));
115       }
116       
117       if (context_getFlag (FLG_IGNOREQUALS))
118         {
119           if (context_getFlag (FLG_IGNORESIGNS)) 
120             {
121               return (cprim_isAnyUnsignedInt (c2)
122                       || (cprim_isUnsignedChar (c2) && context_msgCharInt ()));
123             }
124           else
125             {
126               return (cprim_isAnyInt (c2)
127                       || (cprim_isAnyChar (c2) && context_msgCharInt ()));
128             }
129         }
130       else if (context_getFlag (FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL))
131         {
132           return (cprim_closeEnough (CTX_ULINT, c2));
133         }
134       else
135         {
136           return FALSE;
137         }
138     }
139
140   if (c1 == CTX_SIGNEDINTEGRAL)
141     {
142       /* We allow signed ints to match any integral if matchanyintegral is set */
143       if (context_getFlag (FLG_MATCHANYINTEGRAL)) {
144         return (cprim_isAnyInt (c2)
145                 || (cprim_isAnyChar (c2) && context_msgCharInt ()));
146       }
147
148       if (context_getFlag (FLG_IGNOREQUALS))
149         {
150           return (cprim_isAnyInt (c2)
151                   || (cprim_isAnyChar (c2) && context_msgCharInt ()));
152         }
153       else if (context_getFlag (FLG_LONGSIGNEDINTEGRAL))
154         {
155           return (cprim_closeEnough (CTX_LINT, c2));
156         }
157       else
158         {
159           return FALSE;
160         }
161     }
162
163   if (c2 == CTX_ANYINTEGRAL)
164     {
165       if (context_getFlag (FLG_MATCHANYINTEGRAL))
166         {
167           return (cprim_isAnyInt (c1)
168                   || (cprim_isAnyChar (c1) && context_msgCharInt ()));
169         }
170       else if (context_getFlag (FLG_LONGINTEGRAL))
171         {
172           return (cprim_closeEnough (c1, CTX_LINT));
173         }
174       else if (context_getFlag (FLG_LONGUNSIGNEDINTEGRAL))
175         {
176           return (cprim_closeEnough (c1, CTX_ULINT));
177         }
178       else
179         {
180           return FALSE;
181         }
182     }
183
184   if (c2 == CTX_UNSIGNEDINTEGRAL)
185     {
186       if (context_getFlag (FLG_MATCHANYINTEGRAL))
187         {
188           return (cprim_isAnyInt (c1)
189                   || (cprim_isAnyChar (c1) && context_msgCharInt ()));
190         }
191       else if (context_getFlag (FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL))
192         {
193           return (cprim_closeEnough (c1, CTX_ULINT));
194         }
195       else
196         {
197           return FALSE;
198         }
199     }
200
201   if (c2 == CTX_SIGNEDINTEGRAL)
202     {
203       if (context_getFlag (FLG_MATCHANYINTEGRAL))
204         {
205           return (cprim_isAnyInt (c2)
206                   || (cprim_isAnyChar (c2) && context_msgCharInt ()));
207         }
208       else if (context_getFlag (FLG_LONGSIGNEDINTEGRAL))
209         {
210           return (cprim_closeEnough (c1, CTX_LINT));
211         }
212       else
213         {
214           return FALSE;
215         }
216     }
217
218
219   DPRINTF (("cprim close: %s / %s", cprim_unparse (c1), cprim_unparse (c2)));
220
221   if (context_getFlag (FLG_RELAXTYPES))
222     {
223       if (cprim_isNumeric (c1) && cprim_isNumeric (c2)) return TRUE;
224     }
225
226   if (context_getFlag (FLG_IGNOREQUALS))
227     {
228       switch (c1)
229         {
230         case CTX_CHAR:
231         case CTX_UCHAR:
232           if (cprim_isAnyChar (c2) 
233               || (cprim_isAnyInt (c2) && (context_msgCharInt ()))) {
234             return TRUE;
235           } 
236           break;
237         case CTX_DOUBLE:
238         case CTX_FLOAT:
239         case CTX_LDOUBLE:
240           if (c2 == CTX_DOUBLE || c2 == CTX_FLOAT || c2 == CTX_LDOUBLE) {
241             return TRUE;
242           }
243           break;
244         case CTX_INT:
245         case CTX_LINT:
246         case CTX_LLINT:
247         case CTX_ULLINT:
248         case CTX_SINT:
249         case CTX_UINT:
250         case CTX_ULINT:
251         case CTX_USINT:
252           if (cprim_isAnyInt (c2) 
253               || (cprim_isAnyChar (c2) && context_msgCharInt ())) {
254             return TRUE;
255           }
256           /*@fallthrough@*/ 
257         default:
258           ;
259         }
260     }
261
262   if (context_getFlag (FLG_IGNORESIGNS))
263     {
264       if (c1 == CTX_UCHAR)  
265         {
266           c1 = CTX_CHAR;
267         }
268       else if (c1 == CTX_UINT)  
269         {
270           c1 = CTX_INT;
271         }
272       else if (c1 == CTX_ULINT) 
273         {
274           c1 = CTX_LINT;
275         }
276       /* 2001-06-10: This fix provided by Jim Zelenka: */
277       else if (c1 == CTX_ULLINT) 
278         {
279           c1 = CTX_LLINT;
280         }
281       /* End fix */
282       else if (c1 == CTX_USINT)  
283         {
284           c1 = CTX_SINT;
285         }
286       else
287         {
288           ;
289         }
290       
291       if (c2 == CTX_UCHAR)  
292         {
293           c2 = CTX_CHAR;
294         }
295       else if (c2 == CTX_UINT)   
296         {
297           c2 = CTX_INT;
298         }
299       else if (c2 == CTX_ULINT) 
300         {
301           c2 = CTX_LINT;
302         }
303       /* 2001-06-10: This fix provided by Jim Zelenka: */
304       else if (c2 == CTX_ULLINT)
305         {
306           c2 = CTX_LLINT;
307         }
308       /* End fix */
309       else if (c2 == CTX_USINT)  
310         {
311           c2 = CTX_SINT;
312         }
313       else
314         {
315           ;
316         }
317     }
318
319   if (c1 == c2) return TRUE;
320   
321   if (context_getFlag (FLG_FLOATDOUBLE))
322     {
323       if (c1 == CTX_FLOAT && c2 == CTX_DOUBLE) 
324         {
325           return TRUE;
326         }
327       if (c2 == CTX_FLOAT && c1 == CTX_DOUBLE)
328         {
329           return TRUE;
330         }
331     }
332   
333   DPRINTF (("cprim close: %s / %s", cprim_unparse (c1), cprim_unparse (c2)));
334   
335   if (!deep && context_getFlag (FLG_RELAXQUALS))
336     {
337       switch (c1)
338         {
339         case CTX_DOUBLE:
340           return (c2 == CTX_FLOAT);
341         case CTX_LDOUBLE:
342           return (c2 == CTX_DOUBLE || c2 == CTX_FLOAT);
343         case CTX_SINT:
344           return ((c2 == CTX_CHAR && context_msgCharInt ()) 
345                   || (c2 == CTX_INT && context_msgShortInt ())
346                   || (c2 == CTX_LINT && context_msgShortInt () && context_msgLongInt ()));
347
348         case CTX_INT:
349           return ((c2 == CTX_SINT
350                    || (cprim_isAnyChar (c2) && context_msgCharInt ())
351                    || (c2 == CTX_LINT && context_msgLongInt ())));
352
353         case CTX_LLINT:
354           return (c2 == CTX_SINT
355                   || c2 == CTX_INT 
356                       || c2 == CTX_LINT
357                   || (cprim_isAnyChar (c2) && context_msgCharInt ()));
358         case CTX_ULLINT:
359           return (c2 == CTX_USINT
360                   || c2 == CTX_UINT 
361                   || c2 == CTX_ULINT
362                   /* 2001-06-10: This fix provided by Jim Zelenka: */
363                   || (cprim_isAnyChar (c2) && context_msgCharInt ()));
364         case CTX_LINT:
365           return (c2 == CTX_SINT
366                   || c2 == CTX_INT 
367                   || (cprim_isAnyChar (c2) && context_msgCharInt ()));
368         case CTX_UINT:
369           return (c2 == CTX_USINT 
370                   || (c2 == CTX_UCHAR && context_msgCharInt ()));
371         case CTX_USINT:
372           return (c2 == CTX_UCHAR && context_msgCharInt ());
373         case CTX_ULINT:
374           /* 2001-06-10: This fix provided by Jim Zelenka: */
375           return (c2 == CTX_UINT || c2 == CTX_USINT
376                   || (c2 == CTX_UCHAR && context_msgCharInt()));
377         case CTX_UCHAR:
378           return (c2 == CTX_UINT && context_msgCharInt ());
379         case CTX_CHAR:
380           return ((c2 == CTX_INT || c2 == CTX_SINT)
381                   && context_msgCharInt ());
382         default:
383           return FALSE;
384         }
385     }
386   else
387     {
388       switch (c1)
389         {
390         case CTX_DOUBLE:
391         case CTX_LDOUBLE:
392           return FALSE;
393         case CTX_SINT:
394           if (c2 == CTX_INT && context_msgShortInt ()) {
395             return TRUE;
396           }
397           /*@fallthrough@*/
398         case CTX_INT:
399           if (c2 == CTX_INT && context_msgLongInt ()) {
400             return TRUE;
401           }
402           
403           if (c2 == CTX_SINT && context_msgShortInt ()) {
404             return TRUE;
405           }
406           /*@fallthrough@*/
407         case CTX_LINT:
408           if (c2 == CTX_INT && context_msgLongInt ()) {
409             return TRUE;
410           }
411           /*@fallthrough@*/
412         case CTX_LLINT:
413           return (c2 == CTX_CHAR && context_msgCharInt ());
414         case CTX_UINT:
415         case CTX_USINT:
416         case CTX_ULINT:
417         case CTX_ULLINT:
418           return (c2 == CTX_UCHAR && context_msgCharInt ());
419         case CTX_UCHAR:
420           return (c2 == CTX_UINT && context_msgCharInt ());
421         case CTX_CHAR:
422           return ((c2 == CTX_INT || c2 == CTX_SINT)
423                   && context_msgCharInt ());
424         default:
425           return FALSE;
426         }
427     }
428 }
429
430 /*@only@*/ cstring
431 cprim_unparse (cprim c)
432 {
433   switch (c)
434     {
435     case CTX_UNKNOWN:
436       return cstring_makeLiteral ("-");
437     case CTX_VOID:
438       return cstring_makeLiteral ("void");
439     case CTX_CHAR:
440       return cstring_makeLiteral ("char");
441     case CTX_UCHAR:
442       return cstring_makeLiteral ("unsigned char");
443    case CTX_DOUBLE:
444       return cstring_makeLiteral ("double");
445     case CTX_LDOUBLE:
446       return cstring_makeLiteral ("long double");
447     case CTX_FLOAT:
448       return cstring_makeLiteral ("float");
449     case CTX_INT:
450       return cstring_makeLiteral ("int");
451     case CTX_LINT:
452       return cstring_makeLiteral ("long int");
453     case CTX_LLINT:
454       return cstring_makeLiteral ("long long");
455     case CTX_ULLINT:
456       return cstring_makeLiteral ("unsigned long long");
457     case CTX_SINT:
458       return cstring_makeLiteral ("short int");
459     case CTX_UINT:
460       return cstring_makeLiteral ("unsigned int");
461     case CTX_ULINT:
462       return cstring_makeLiteral ("unsigned long int");
463     case CTX_USINT:
464       return cstring_makeLiteral ("unsigned short int");
465     case CTX_UNSIGNEDINTEGRAL:
466       return cstring_makeLiteral ("arbitrary unsigned integral type");
467     case CTX_SIGNEDINTEGRAL:
468       return cstring_makeLiteral ("arbitrary signed integral type");
469     case CTX_ANYINTEGRAL:
470       return cstring_makeLiteral ("arbitrary integral type");
471     default:
472       return cstring_makeLiteral ("unknown prim");
473     }
474 }
475
476 bool cprim_isInt (cprim c) 
477 {
478   return (cprim_isAnyInt (c)
479           || (cprim_isAnyChar (c) && context_msgCharInt ()));
480 }
481     
482 int cprim_getExpectedBits (cprim c)
483 {
484   /* Any basis to these numbers?  Just guesses for now..., check ISO spec */
485   switch (c)
486     {
487     case CTX_UNKNOWN:
488       return 0;
489     case CTX_VOID:
490       return 0;
491     case CTX_CHAR:
492       return 8;
493     case CTX_UCHAR:
494       return 8;
495    case CTX_DOUBLE:
496       return 64;
497     case CTX_LDOUBLE:
498       return 128;
499     case CTX_FLOAT:
500       return 32;
501     case CTX_INT:
502       return 32;
503     case CTX_LINT:
504       return 64;
505     case CTX_LLINT:
506       return 128;
507     case CTX_ULLINT:
508       return 128;
509     case CTX_SINT:
510       return 8;
511     case CTX_UINT:
512       return 32;
513     case CTX_ULINT:
514       return 64;
515     case CTX_USINT:
516       return 8;
517     case CTX_UNSIGNEDINTEGRAL:
518       return 64;
519     case CTX_SIGNEDINTEGRAL:
520       return 64;
521     case CTX_ANYINTEGRAL:
522       return 64;
523     default:
524       return 0;
525     }
526 }
This page took 0.108859 seconds and 5 git commands to generate.