]> andersk Git - splint.git/blob - src/cprim.c
Finshed basic merge. Still trying to get it through the test suit.
[splint.git] / src / cprim.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 ** 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           else if (c1 == CTX_USINT)  
246             {
247               c1 = CTX_SINT;
248             }
249           else
250             {
251               ;
252             }
253
254           if (c2 == CTX_UCHAR)  
255             {
256               c2 = CTX_CHAR;
257             }
258           else if (c2 == CTX_UINT)   
259             {
260               c2 = CTX_INT;
261             }
262           else if (c2 == CTX_ULINT) 
263             {
264               c2 = CTX_LINT;
265             }
266           else if (c2 == CTX_USINT)  
267             {
268               c2 = CTX_SINT;
269             }
270           else
271             {
272               ;
273             }
274         }
275
276       if (c1 == c2) return TRUE;
277
278       if (context_getFlag (FLG_FLOATDOUBLE))
279         {
280           if (c1 == CTX_FLOAT && c2 == CTX_DOUBLE) 
281             {
282               return TRUE;
283             }
284           if (c2 == CTX_FLOAT && c1 == CTX_DOUBLE)
285             {
286               return TRUE;
287             }
288         }
289
290       if (!deep && context_getFlag (FLG_RELAXQUALS))
291         {
292           switch (c1)
293             {
294             case CTX_DOUBLE:
295               return (c2 == CTX_FLOAT);
296             case CTX_LDOUBLE:
297               return (c2 == CTX_DOUBLE || c2 == CTX_FLOAT);
298             case CTX_SINT:
299               return (c2 == CTX_CHAR && context_msgCharInt ());
300             case CTX_INT:
301               return (c2 == CTX_SINT
302                       || (cprim_isAnyChar (c2) && context_msgCharInt ()));
303             case CTX_LLINT:
304               return (c2 == CTX_SINT
305                       || c2 == CTX_INT 
306                       || c2 == CTX_LINT
307                       || (cprim_isAnyChar (c2) && context_msgCharInt ()));
308             case CTX_ULLINT:
309               return (c2 == CTX_USINT
310                       || c2 == CTX_UINT 
311                       || c2 == CTX_ULINT);
312             case CTX_LINT:
313               return (c2 == CTX_SINT
314                       || c2 == CTX_INT 
315                       || (cprim_isAnyChar (c2) && context_msgCharInt ()));
316             case CTX_UINT:
317               return (c2 == CTX_USINT 
318                       || (c2 == CTX_UCHAR && context_msgCharInt ()));
319             case CTX_USINT:
320               return (c2 == CTX_UCHAR && context_msgCharInt ());
321             case CTX_ULINT:
322               return (c2 == CTX_UINT || c2 == CTX_USINT);
323             case CTX_UCHAR:
324               return (c2 == CTX_UINT && context_msgCharInt ());
325             case CTX_CHAR:
326               return ((c2 == CTX_INT || c2 == CTX_SINT)
327                       && context_msgCharInt ());
328             default:
329               return FALSE;
330             }
331         }
332       else
333         {
334           switch (c1)
335             {
336             case CTX_DOUBLE:
337             case CTX_LDOUBLE:
338               return FALSE;
339             case CTX_SINT:
340             case CTX_INT:
341             case CTX_LINT:
342             case CTX_LLINT:
343               return (c2 == CTX_CHAR && context_msgCharInt ());
344             case CTX_UINT:
345             case CTX_USINT:
346             case CTX_ULINT:
347             case CTX_ULLINT:
348               return (c2 == CTX_UCHAR && context_msgCharInt ());
349             case CTX_UCHAR:
350               return (c2 == CTX_UINT && context_msgCharInt ());
351             case CTX_CHAR:
352               return ((c2 == CTX_INT || c2 == CTX_SINT)
353                       && context_msgCharInt ());
354             default:
355               return FALSE;
356             }
357         }
358     }
359 }
360
361 /*@only@*/ cstring
362 cprim_unparse (cprim c)
363 {
364   switch (c)
365     {
366     case CTX_UNKNOWN:
367       return cstring_makeLiteral ("-");
368     case CTX_VOID:
369       return cstring_makeLiteral ("void");
370     case CTX_CHAR:
371       return cstring_makeLiteral ("char");
372     case CTX_UCHAR:
373       return cstring_makeLiteral ("unsigned char");
374    case CTX_DOUBLE:
375       return cstring_makeLiteral ("double");
376     case CTX_LDOUBLE:
377       return cstring_makeLiteral ("long double");
378     case CTX_FLOAT:
379       return cstring_makeLiteral ("float");
380     case CTX_INT:
381       return cstring_makeLiteral ("int");
382     case CTX_LINT:
383       return cstring_makeLiteral ("long int");
384     case CTX_LLINT:
385       return cstring_makeLiteral ("long long");
386     case CTX_ULLINT:
387       return cstring_makeLiteral ("unsigned long long");
388     case CTX_SINT:
389       return cstring_makeLiteral ("short int");
390     case CTX_UINT:
391       return cstring_makeLiteral ("unsigned int");
392     case CTX_ULINT:
393       return cstring_makeLiteral ("unsigned long int");
394     case CTX_USINT:
395       return cstring_makeLiteral ("unsigned short int");
396     case CTX_UNSIGNEDINTEGRAL:
397       return cstring_makeLiteral ("arbitrary unsigned integral type");
398     case CTX_SIGNEDINTEGRAL:
399       return cstring_makeLiteral ("arbitrary signed integral type");
400     case CTX_ANYINTEGRAL:
401       return cstring_makeLiteral ("arbitrary integral type");
402     default:
403       return cstring_makeLiteral ("unknown prim");
404     }
405 }
406
407 bool cprim_isInt (cprim c) 
408 {
409   return (cprim_isAnyInt (c)
410           || (cprim_isAnyChar (c) && context_msgCharInt ()));
411 }
412     
413
414
415
This page took 2.381103 seconds and 5 git commands to generate.