]> andersk Git - splint.git/blob - src/multiVal.c
96e79db571d9c2752e876f0147f726e8928e9710
[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   llassert (multiVal_isInt (m));
134
135   return m->value.ival;
136 }
137
138 char multiVal_forceChar (multiVal m)
139 {
140   llassert (multiVal_isChar (m));
141   
142   return m->value.cval;
143 }
144
145 double multiVal_forceDouble (multiVal m)
146 {
147   llassert (multiVal_isDouble (m));
148
149   return m->value.fval;
150 }
151
152 /*@dependent@*/ /*@observer@*/ cstring multiVal_forceString (multiVal m)
153 {
154   llassert (multiVal_isString (m));
155
156   return m->value.sval;
157 }
158
159 bool multiVal_isInt (multiVal m)
160 {
161   return (multiVal_isDefined (m) && m->kind == MVLONG);
162 }
163
164 bool multiVal_isChar (multiVal m)
165 {
166   return (multiVal_isDefined (m) && m->kind == MVCHAR);
167 }
168
169 bool multiVal_isDouble (multiVal m)
170 {
171   return (multiVal_isDefined (m) && m->kind == MVDOUBLE);
172 }
173
174 bool multiVal_isString (multiVal m)
175 {
176   return (multiVal_isDefined (m) && m->kind == MVSTRING);
177 }
178
179 /*@only@*/ cstring multiVal_unparse (multiVal m)
180 {
181   if (multiVal_isDefined (m))
182     {
183       switch (m->kind)
184         {
185         case MVLONG:
186           return message ("%d", (int)m->value.ival);
187         case MVCHAR:
188                   return message ("'%h'", m->value.cval);
189         case MVDOUBLE:
190           return message ("%f", (float)m->value.fval);
191         case MVSTRING:
192           return message ("%s", m->value.sval);
193         }
194       BADEXIT;
195     }
196   else
197     {
198       return (cstring_makeLiteral ("?"));
199     }
200 }
201
202 /*@only@*/ cstring multiVal_dump (multiVal m)
203 {
204   if (multiVal_isDefined (m))
205     {
206       switch (m->kind)
207         {
208         case MVLONG:
209           return (message ("i%d", (int)m->value.ival));
210         case MVCHAR:
211           return (message ("c%d", (int)m->value.cval));
212         case MVDOUBLE:
213           return (message ("d%f", (float)m->value.fval));
214         case MVSTRING:
215           return (message ("s%s", m->value.sval));
216         }
217       BADEXIT;
218     }
219   else
220     {
221       return (cstring_undefined);
222     }
223 }
224
225 /*@only@*/ multiVal multiVal_undump (char **s)
226 {
227   char tchar = **s;
228
229   switch (tchar)
230     {
231     case 'i':
232       (*s)++;
233       return multiVal_makeInt (reader_getInt (s));
234     case 'c':
235       (*s)++;
236       return multiVal_makeChar ((char) reader_getInt (s));
237     case 'd':
238       (*s)++;
239       return multiVal_makeDouble (reader_getDouble (s));
240     case 's':
241       {
242         cstring st = cstring_undefined;
243
244         (*s)++;
245         while (**s != '#')
246           {
247             st = cstring_appendChar (st, **s);
248             (*s)++;
249           }
250
251         return multiVal_makeString (st);
252       }
253     case '@':
254     case '#':
255       return multiVal_unknown ();
256     BADDEFAULT;
257     }
258   
259   BADEXIT;
260 }
261
262 int multiVal_compare (multiVal m1, multiVal m2)
263 {
264   if (multiVal_isUndefined (m1))
265     {
266       if (multiVal_isUndefined (m2)) 
267         {
268           return 0;
269         }
270
271       else return -1;
272     }
273   if (multiVal_isUndefined (m2))
274     {
275       return -1;
276     }
277
278   COMPARERETURN (generic_compare (m1->kind, m2->kind));
279
280   switch (m1->kind)
281     {
282     case MVLONG:   return (generic_compare (m1->value.ival, m2->value.ival));
283     case MVCHAR:   return (generic_compare (m1->value.cval, m2->value.cval));
284     case MVDOUBLE: return (generic_compare (m1->value.fval, m2->value.fval));
285     case MVSTRING: return (cstring_compare (m1->value.sval, m2->value.sval));
286     }
287
288   BADEXIT;
289 }
290
291 multiVal multiVal_add (multiVal m1, multiVal m2)
292 {
293   if (multiVal_isUndefined (m1) || multiVal_isUndefined (m2) || m1->kind != m2->kind)
294     {
295       return multiVal_undefined;
296     }
297
298   switch (m1->kind)
299     {
300     case MVLONG:   return (multiVal_makeInt (m1->value.ival + m2->value.ival));
301     case MVCHAR:   return (multiVal_makeChar ((char) (m1->value.cval + m2->value.cval)));
302     case MVDOUBLE: return (multiVal_makeDouble (m1->value.fval + m2->value.fval));
303     case MVSTRING: return multiVal_undefined;
304     }
305
306   BADEXIT;
307 }
308
309 multiVal multiVal_subtract (multiVal m1, multiVal m2)
310 {
311   if (multiVal_isUndefined (m1) || multiVal_isUndefined (m2) || m1->kind != m2->kind)
312     {
313       return multiVal_undefined;
314     }
315
316   switch (m1->kind)
317     {
318     case MVLONG:   return (multiVal_makeInt (m1->value.ival - m2->value.ival));
319     case MVCHAR:   return (multiVal_makeChar ((char) (m1->value.cval - m2->value.cval)));
320     case MVDOUBLE: return (multiVal_makeDouble (m1->value.fval - m2->value.fval));
321     case MVSTRING: return multiVal_undefined;
322     }
323
324   BADEXIT;
325 }
326
327 multiVal multiVal_multiply (multiVal m1, multiVal m2)
328 {
329   if (multiVal_isUndefined (m1) || multiVal_isUndefined (m2) || m1->kind != m2->kind)
330     {
331       return multiVal_undefined;
332     }
333
334   switch (m1->kind)
335     {
336     case MVLONG:   return (multiVal_makeInt (m1->value.ival * m2->value.ival));
337     case MVCHAR:   return (multiVal_makeChar ((char) (m1->value.cval * m2->value.cval)));
338     case MVDOUBLE: return (multiVal_makeDouble (m1->value.fval * m2->value.fval));
339     case MVSTRING: return multiVal_undefined;
340     }
341
342   BADEXIT;
343 }
344
345 multiVal multiVal_divide (multiVal m1, multiVal m2)
346 {
347   if (multiVal_isUndefined (m1) || multiVal_isUndefined (m2) || m1->kind != m2->kind)
348     {
349       return multiVal_undefined;
350     }
351
352   switch (m1->kind)
353     {
354     case MVLONG: 
355       if (m2->value.ival != 0)
356         {
357           return (multiVal_makeInt (m1->value.ival / m2->value.ival));
358         }
359       else
360         {
361           return multiVal_undefined;
362         }
363     case MVCHAR:   
364       if (m2->value.cval != (char) 0)
365         {
366           return (multiVal_makeChar ((char) (m1->value.cval / m2->value.cval)));
367         }
368       else
369         {
370           return multiVal_undefined;
371         }
372     case MVDOUBLE:
373       return multiVal_undefined; /* Don't attempt to divide floats */
374     case MVSTRING: return multiVal_undefined;
375     }
376
377   BADEXIT;
378 }
379
380 void multiVal_free (/*@only@*/ multiVal m)
381 {
382   if (multiVal_isDefined (m))
383     {
384       if (m->kind == MVSTRING)
385         {
386           cstring_free (m->value.sval);
387         }
388       
389       sfree (m);
390     }
391 }
392
393
394
395
This page took 0.698584 seconds and 3 git commands to generate.