]> andersk Git - splint.git/blob - src/multiVal.c
noexpand always false.
[splint.git] / src / multiVal.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 ** multiVal.c
26 */
27
28 # include "splintMacros.nf"
29 # include "basic.h"
30
31 /*@only@*/ multiVal multiVal_unknown ()
32 {
33   return multiVal_undefined;
34 }
35
36 static /*@special@*/ /*@notnull@*/ multiVal multiVal_create (mvkind kind)
37    /*@defines result->kind@*/
38 {
39   multiVal mv = (multiVal) dmalloc (sizeof (*mv));
40
41   mv->kind = kind;
42   return mv;
43 }
44
45 /*@only@*/ multiVal multiVal_makeInt (long x)
46 {
47   multiVal mv = multiVal_create (MVLONG);
48
49   mv->value.ival = x;
50   return mv;
51 }
52
53 /*@only@*/ multiVal multiVal_makeChar (char x)
54 {
55   multiVal mv = multiVal_create (MVCHAR);
56   mv->value.cval = x;
57   return mv;
58 }
59
60 /*@only@*/ multiVal multiVal_makeDouble (double x)
61 {
62   multiVal mv = multiVal_create (MVDOUBLE);
63
64     mv->value.fval = x;
65     return mv;
66 }
67
68 /*@only@*/ multiVal multiVal_makeString (/*@only@*/ cstring s)
69 {
70   multiVal mv = multiVal_create (MVSTRING);
71
72   mv->value.sval = s;
73   return mv;
74 }
75
76
77 /*@only@*/ multiVal multiVal_copy (multiVal m)
78 {
79   multiVal r;
80
81   if (multiVal_isUndefined (m))
82     {
83       return multiVal_undefined;
84     }
85
86   r = multiVal_create (m->kind);
87       
88   switch (m->kind)
89     {
90     case MVLONG:
91       r->value.ival = m->value.ival;
92       break;
93     case MVCHAR:
94       r->value.cval = m->value.cval;
95       break;
96     case MVDOUBLE:
97       r->value.fval = m->value.fval;
98       break;
99     case MVSTRING:
100       r->value.sval = cstring_copy (m->value.sval);
101       break;
102     }
103   
104   return r;
105 }
106
107 multiVal multiVal_invert (multiVal m)
108 {
109   if (multiVal_isUndefined (m))
110     {
111       return multiVal_undefined;
112     }
113       
114   switch (m->kind)
115     {
116     case MVLONG:
117       return multiVal_makeInt (-1 * m->value.ival);
118     case MVCHAR:
119       BADBRANCHCONT;
120       return multiVal_undefined;
121     case MVDOUBLE:
122       return multiVal_makeDouble (-1.0 * m->value.fval);
123     case MVSTRING:
124       BADBRANCHCONT;
125       return multiVal_undefined;
126     }
127
128   BADEXIT;
129 }
130
131 long multiVal_forceInt (multiVal m)
132 {
133   if (multiVal_isInt (m)) {
134     return m->value.ival;
135   } else {
136     llcontbug (message ("Multival is not int: %s", multiVal_unparse (m)));
137     return 0;
138   }
139 }
140
141 char multiVal_forceChar (multiVal m)
142 {
143   llassert (multiVal_isChar (m));
144   
145   return m->value.cval;
146 }
147
148 double multiVal_forceDouble (multiVal m)
149 {
150   llassert (multiVal_isDouble (m));
151
152   return m->value.fval;
153 }
154
155 /*@dependent@*/ /*@observer@*/ cstring multiVal_forceString (multiVal m)
156 {
157   llassert (multiVal_isString (m));
158
159   return m->value.sval;
160 }
161
162 bool multiVal_isInt (multiVal m)
163 {
164   return (multiVal_isDefined (m) && m->kind == MVLONG);
165 }
166
167 bool multiVal_isChar (multiVal m)
168 {
169   return (multiVal_isDefined (m) && m->kind == MVCHAR);
170 }
171
172 bool multiVal_isDouble (multiVal m)
173 {
174   return (multiVal_isDefined (m) && m->kind == MVDOUBLE);
175 }
176
177 bool multiVal_isString (multiVal m)
178 {
179   return (multiVal_isDefined (m) && m->kind == MVSTRING);
180 }
181
182 /*@only@*/ cstring multiVal_unparse (multiVal m)
183 {
184   if (multiVal_isDefined (m))
185     {
186       switch (m->kind)
187         {
188         case MVLONG:
189           return message ("%d", (int)m->value.ival);
190         case MVCHAR:
191                   return message ("'%h'", m->value.cval);
192         case MVDOUBLE:
193           return message ("%f", (float)m->value.fval);
194         case MVSTRING:
195           return message ("%s", m->value.sval);
196         }
197       BADEXIT;
198     }
199   else
200     {
201       return (cstring_makeLiteral ("?"));
202     }
203 }
204
205 /*@only@*/ cstring multiVal_dump (multiVal m)
206 {
207   if (multiVal_isDefined (m))
208     {
209       switch (m->kind)
210         {
211         case MVLONG:
212           return (message ("i%d", (int)m->value.ival));
213         case MVCHAR:
214           return (message ("c%d", (int)m->value.cval));
215         case MVDOUBLE:
216           return (message ("d%f", (float)m->value.fval));
217         case MVSTRING:
218           return (message ("s%s", m->value.sval));
219         }
220       BADEXIT;
221     }
222   else
223     {
224       return (cstring_undefined);
225     }
226 }
227
228 /*@only@*/ multiVal multiVal_undump (char **s)
229 {
230   char tchar = **s;
231
232   switch (tchar)
233     {
234     case 'i':
235       (*s)++;
236       return multiVal_makeInt (reader_getInt (s));
237     case 'c':
238       (*s)++;
239       return multiVal_makeChar ((char) reader_getInt (s));
240     case 'd':
241       (*s)++;
242       return multiVal_makeDouble (reader_getDouble (s));
243     case 's':
244       {
245         cstring st = cstring_undefined;
246
247         (*s)++;
248         while (**s != '#')
249           {
250             st = cstring_appendChar (st, **s);
251             (*s)++;
252           }
253
254         return multiVal_makeString (st);
255       }
256     case '@':
257     case '#':
258       return multiVal_unknown ();
259     BADDEFAULT;
260     }
261   
262   BADEXIT;
263 }
264
265 int multiVal_compare (multiVal m1, multiVal m2)
266 {
267   if (multiVal_isUndefined (m1))
268     {
269       if (multiVal_isUndefined (m2)) 
270         {
271           return 0;
272         }
273
274       else return -1;
275     }
276   if (multiVal_isUndefined (m2))
277     {
278       return -1;
279     }
280
281   COMPARERETURN (generic_compare (m1->kind, m2->kind));
282
283   switch (m1->kind)
284     {
285     case MVLONG:   return (generic_compare (m1->value.ival, m2->value.ival));
286     case MVCHAR:   return (generic_compare (m1->value.cval, m2->value.cval));
287     case MVDOUBLE: return (generic_compare (m1->value.fval, m2->value.fval));
288     case MVSTRING: return (cstring_compare (m1->value.sval, m2->value.sval));
289     }
290
291   BADEXIT;
292 }
293
294 multiVal multiVal_add (multiVal m1, multiVal m2)
295 {
296   if (multiVal_isUndefined (m1) || multiVal_isUndefined (m2) || m1->kind != m2->kind)
297     {
298       return multiVal_undefined;
299     }
300
301   switch (m1->kind)
302     {
303     case MVLONG:   return (multiVal_makeInt (m1->value.ival + m2->value.ival));
304     case MVCHAR:   return (multiVal_makeChar ((char) (m1->value.cval + m2->value.cval)));
305     case MVDOUBLE: return (multiVal_makeDouble (m1->value.fval + m2->value.fval));
306     case MVSTRING: return multiVal_undefined;
307     }
308
309   BADEXIT;
310 }
311
312 multiVal multiVal_subtract (multiVal m1, multiVal m2)
313 {
314   if (multiVal_isUndefined (m1) || multiVal_isUndefined (m2) || m1->kind != m2->kind)
315     {
316       return multiVal_undefined;
317     }
318
319   switch (m1->kind)
320     {
321     case MVLONG:   return (multiVal_makeInt (m1->value.ival - m2->value.ival));
322     case MVCHAR:   return (multiVal_makeChar ((char) (m1->value.cval - m2->value.cval)));
323     case MVDOUBLE: return (multiVal_makeDouble (m1->value.fval - m2->value.fval));
324     case MVSTRING: return multiVal_undefined;
325     }
326
327   BADEXIT;
328 }
329
330 multiVal multiVal_multiply (multiVal m1, multiVal m2)
331 {
332   if (multiVal_isUndefined (m1) || multiVal_isUndefined (m2) || m1->kind != m2->kind)
333     {
334       return multiVal_undefined;
335     }
336
337   switch (m1->kind)
338     {
339     case MVLONG:   return (multiVal_makeInt (m1->value.ival * m2->value.ival));
340     case MVCHAR:   return (multiVal_makeChar ((char) (m1->value.cval * m2->value.cval)));
341     case MVDOUBLE: return (multiVal_makeDouble (m1->value.fval * m2->value.fval));
342     case MVSTRING: return multiVal_undefined;
343     }
344
345   BADEXIT;
346 }
347
348 multiVal multiVal_divide (multiVal m1, multiVal m2)
349 {
350   if (multiVal_isUndefined (m1) || multiVal_isUndefined (m2) || m1->kind != m2->kind)
351     {
352       return multiVal_undefined;
353     }
354
355   switch (m1->kind)
356     {
357     case MVLONG: 
358       if (m2->value.ival != 0)
359         {
360           return (multiVal_makeInt (m1->value.ival / m2->value.ival));
361         }
362       else
363         {
364           return multiVal_undefined;
365         }
366     case MVCHAR:   
367       if (m2->value.cval != (char) 0)
368         {
369           return (multiVal_makeChar ((char) (m1->value.cval / m2->value.cval)));
370         }
371       else
372         {
373           return multiVal_undefined;
374         }
375     case MVDOUBLE:
376       return multiVal_undefined; /* Don't attempt to divide floats */
377     case MVSTRING: return multiVal_undefined;
378     }
379
380   BADEXIT;
381 }
382
383 void multiVal_free (/*@only@*/ multiVal m)
384 {
385   if (multiVal_isDefined (m))
386     {
387       if (m->kind == MVSTRING)
388         {
389           cstring_free (m->value.sval);
390         }
391       
392       sfree (m);
393     }
394 }
395
396
397
398
This page took 0.117562 seconds and 5 git commands to generate.