]> andersk Git - splint.git/blob - src/cprim.c
Merged code tree with Dave Evans's version. Many changes to numberous to list....
[splint.git] / src / cprim.c
1 /*
2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 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 ** cprim.c
26 */
27
28 # include "lclintMacros.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   if (c1 == CTX_ANYINTEGRAL)
86     {
87       if (context_getFlag (FLG_MATCHANYINTEGRAL)
88           || context_getFlag (FLG_IGNOREQUALS))
89         {
90           return (cprim_isAnyInt (c2)
91                   || (cprim_isAnyChar (c2) && context_msgCharInt ()));
92         }
93       else if (context_getFlag (FLG_LONGINTEGRAL))
94         {
95           return (cprim_closeEnough (CTX_LINT, c2));
96         }
97       else if (context_getFlag (FLG_LONGUNSIGNEDINTEGRAL))
98         {
99           return (cprim_closeEnough (CTX_ULINT, c2));
100         }
101       else
102         {
103           return FALSE;
104         }
105     }
106
107   if (c1 == CTX_UNSIGNEDINTEGRAL)
108     {
109       if (context_getFlag (FLG_MATCHANYINTEGRAL)
110           || context_getFlag (FLG_IGNOREQUALS))
111         {
112           return (cprim_isAnyInt (c2)
113                   || (cprim_isAnyChar (c2) && context_msgCharInt ()));
114         }
115       else if (context_getFlag (FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL))
116         {
117           return (cprim_closeEnough (CTX_ULINT, c2));
118         }
119       else
120         {
121           return FALSE;
122         }
123     }
124
125   if (c1 == CTX_SIGNEDINTEGRAL)
126     {
127       if (context_getFlag (FLG_MATCHANYINTEGRAL)
128           || context_getFlag (FLG_IGNOREQUALS))
129         {
130           return (cprim_isAnyInt (c2)
131                   || (cprim_isAnyChar (c2) && context_msgCharInt ()));
132         }
133       else if (context_getFlag (FLG_LONGSIGNEDINTEGRAL))
134         {
135           return (cprim_closeEnough (CTX_LINT, c2));
136         }
137       else
138         {
139           return FALSE;
140         }
141     }
142
143   if (c2 == CTX_ANYINTEGRAL)
144     {
145       if (context_getFlag (FLG_MATCHANYINTEGRAL))
146         {
147           return (cprim_isAnyInt (c1)
148                   || (cprim_isAnyChar (c1) && context_msgCharInt ()));
149         }
150       else if (context_getFlag (FLG_LONGINTEGRAL))
151         {
152           return (cprim_closeEnough (c1, CTX_LINT));
153         }
154       else if (context_getFlag (FLG_LONGUNSIGNEDINTEGRAL))
155         {
156           return (cprim_closeEnough (c1, CTX_ULINT));
157         }
158       else
159         {
160           return FALSE;
161         }
162     }
163
164   if (c2 == CTX_UNSIGNEDINTEGRAL)
165     {
166       if (context_getFlag (FLG_MATCHANYINTEGRAL))
167         {
168           return (cprim_isAnyInt (c1)
169                   || (cprim_isAnyChar (c1) && context_msgCharInt ()));
170         }
171       else if (context_getFlag (FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL))
172         {
173           return (cprim_closeEnough (c1, CTX_ULINT));
174         }
175       else
176         {
177           return FALSE;
178         }
179     }
180
181   if (c2 == CTX_SIGNEDINTEGRAL)
182     {
183       if (context_getFlag (FLG_MATCHANYINTEGRAL))
184         {
185           return (cprim_isAnyInt (c2)
186                   || (cprim_isAnyChar (c2) && context_msgCharInt ()));
187         }
188       else if (context_getFlag (FLG_LONGSIGNEDINTEGRAL))
189         {
190           return (cprim_closeEnough (c1, CTX_LINT));
191         }
192       else
193         {
194           return FALSE;
195         }
196     }
197
198   if (context_getFlag (FLG_RELAXTYPES))
199     {
200       if (cprim_isNumeric (c1) && cprim_isNumeric (c2)) return TRUE;
201     }
202
203   if (context_getFlag (FLG_IGNOREQUALS))
204     {
205       switch (c1)
206         {
207         case CTX_CHAR:
208         case CTX_UCHAR:
209           return (cprim_isAnyChar (c2) 
210                   || (cprim_isAnyInt (c2) && (context_msgCharInt ())));
211         case CTX_DOUBLE:
212         case CTX_FLOAT:
213         case CTX_LDOUBLE:
214           return (c2 == CTX_DOUBLE || c2 == CTX_FLOAT || c2 == CTX_LDOUBLE);
215         case CTX_INT:
216         case CTX_LINT:
217         case CTX_LLINT:
218         case CTX_ULLINT:
219         case CTX_SINT:
220         case CTX_UINT:
221         case CTX_ULINT:
222         case CTX_USINT:
223           return (cprim_isAnyInt (c2) 
224                   || (cprim_isAnyChar (c2) && context_msgCharInt ()));
225         default:
226           return FALSE;
227         }
228     }
229   else 
230     {
231       if (context_getFlag (FLG_IGNORESIGNS))
232         {
233           if (c1 == CTX_UCHAR)  
234             {
235               c1 = CTX_CHAR;
236             }
237           else if (c1 == CTX_UINT)  
238             {
239               c1 = CTX_INT;
240             }
241           else if (c1 == CTX_ULINT) 
242             {
243               c1 = CTX_LINT;
244             }
245           /* 2001-06-10: This fix provided by Jim Zelenka: */
246           else if (c1 == CTX_ULLINT) 
247             {
248               c1 = CTX_LLINT;
249             }
250           /* End fix */
251           else if (c1 == CTX_USINT)  
252             {
253               c1 = CTX_SINT;
254             }
255           else
256             {
257               ;
258             }
259
260           if (c2 == CTX_UCHAR)  
261             {
262               c2 = CTX_CHAR;
263             }
264           else if (c2 == CTX_UINT)   
265             {
266               c2 = CTX_INT;
267             }
268           else if (c2 == CTX_ULINT) 
269             {
270               c2 = CTX_LINT;
271             }
272           /* 2001-06-10: This fix provided by Jim Zelenka: */
273           else if (c2 == CTX_ULLINT)
274             {
275               c2 = CTX_LLINT;
276             }
277           /* End fix */
278           else if (c2 == CTX_USINT)  
279             {
280               c2 = CTX_SINT;
281             }
282           else
283             {
284               ;
285             }
286         }
287
288       if (c1 == c2) return TRUE;
289
290       if (context_getFlag (FLG_FLOATDOUBLE))
291         {
292           if (c1 == CTX_FLOAT && c2 == CTX_DOUBLE) 
293             {
294               return TRUE;
295             }
296           if (c2 == CTX_FLOAT && c1 == CTX_DOUBLE)
297             {
298               return TRUE;
299             }
300         }
301
302       if (!deep && context_getFlag (FLG_RELAXQUALS))
303         {
304           switch (c1)
305             {
306             case CTX_DOUBLE:
307               return (c2 == CTX_FLOAT);
308             case CTX_LDOUBLE:
309               return (c2 == CTX_DOUBLE || c2 == CTX_FLOAT);
310             case CTX_SINT:
311               return (c2 == CTX_CHAR && context_msgCharInt ());
312             case CTX_INT:
313               return (c2 == CTX_SINT
314                       || (cprim_isAnyChar (c2) && context_msgCharInt ()));
315             case CTX_LLINT:
316               return (c2 == CTX_SINT
317                       || c2 == CTX_INT 
318                       || c2 == CTX_LINT
319                       || (cprim_isAnyChar (c2) && context_msgCharInt ()));
320             case CTX_ULLINT:
321               return (c2 == CTX_USINT
322                       || c2 == CTX_UINT 
323                       || c2 == CTX_ULINT
324                       /* 2001-06-10: This fix provided by Jim Zelenka: */
325                       || (cprim_isAnyChar (c2) && context_msgCharInt ()));
326             case CTX_LINT:
327               return (c2 == CTX_SINT
328                       || c2 == CTX_INT 
329                       || (cprim_isAnyChar (c2) && context_msgCharInt ()));
330             case CTX_UINT:
331               return (c2 == CTX_USINT 
332                       || (c2 == CTX_UCHAR && context_msgCharInt ()));
333             case CTX_USINT:
334               return (c2 == CTX_UCHAR && context_msgCharInt ());
335             case CTX_ULINT:
336               /* 2001-06-10: This fix provided by Jim Zelenka: */
337               return (c2 == CTX_UINT || c2 == CTX_USINT
338                       || (c2 == CTX_UCHAR && context_msgCharInt()));
339             case CTX_UCHAR:
340               return (c2 == CTX_UINT && context_msgCharInt ());
341             case CTX_CHAR:
342               return ((c2 == CTX_INT || c2 == CTX_SINT)
343                       && context_msgCharInt ());
344             default:
345               return FALSE;
346             }
347         }
348       else
349         {
350           switch (c1)
351             {
352             case CTX_DOUBLE:
353             case CTX_LDOUBLE:
354               return FALSE;
355             case CTX_SINT:
356             case CTX_INT:
357             case CTX_LINT:
358             case CTX_LLINT:
359               return (c2 == CTX_CHAR && context_msgCharInt ());
360             case CTX_UINT:
361             case CTX_USINT:
362             case CTX_ULINT:
363             case CTX_ULLINT:
364               return (c2 == CTX_UCHAR && context_msgCharInt ());
365             case CTX_UCHAR:
366               return (c2 == CTX_UINT && context_msgCharInt ());
367             case CTX_CHAR:
368               return ((c2 == CTX_INT || c2 == CTX_SINT)
369                       && context_msgCharInt ());
370             default:
371               return FALSE;
372             }
373         }
374     }
375 }
376
377 /*@only@*/ cstring
378 cprim_unparse (cprim c)
379 {
380   switch (c)
381     {
382     case CTX_UNKNOWN:
383       return cstring_makeLiteral ("-");
384     case CTX_VOID:
385       return cstring_makeLiteral ("void");
386     case CTX_CHAR:
387       return cstring_makeLiteral ("char");
388     case CTX_UCHAR:
389       return cstring_makeLiteral ("unsigned char");
390    case CTX_DOUBLE:
391       return cstring_makeLiteral ("double");
392     case CTX_LDOUBLE:
393       return cstring_makeLiteral ("long double");
394     case CTX_FLOAT:
395       return cstring_makeLiteral ("float");
396     case CTX_INT:
397       return cstring_makeLiteral ("int");
398     case CTX_LINT:
399       return cstring_makeLiteral ("long int");
400     case CTX_LLINT:
401       return cstring_makeLiteral ("long long");
402     case CTX_ULLINT:
403       return cstring_makeLiteral ("unsigned long long");
404     case CTX_SINT:
405       return cstring_makeLiteral ("short int");
406     case CTX_UINT:
407       return cstring_makeLiteral ("unsigned int");
408     case CTX_ULINT:
409       return cstring_makeLiteral ("unsigned long int");
410     case CTX_USINT:
411       return cstring_makeLiteral ("unsigned short int");
412     case CTX_UNSIGNEDINTEGRAL:
413       return cstring_makeLiteral ("arbitrary unsigned integral type");
414     case CTX_SIGNEDINTEGRAL:
415       return cstring_makeLiteral ("arbitrary signed integral type");
416     case CTX_ANYINTEGRAL:
417       return cstring_makeLiteral ("arbitrary integral type");
418     default:
419       return cstring_makeLiteral ("unknown prim");
420     }
421 }
422
423 bool cprim_isInt (cprim c) 
424 {
425   return (cprim_isAnyInt (c)
426           || (cprim_isAnyChar (c) && context_msgCharInt ()));
427 }
428     
429
430
431
This page took 0.092334 seconds and 5 git commands to generate.