2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
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.
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.
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.
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
28 # include "splintMacros.nf"
31 /*@only@*/ multiVal
multiVal_unknown (void)
33 return multiVal_undefined
;
36 static /*@special@*/ /*@notnull@*/ multiVal
multiVal_create (mvkind kind
)
37 /*@defines result->kind@*/
39 multiVal mv
= (multiVal
) dmalloc (sizeof (*mv
));
45 /*@only@*/ multiVal
multiVal_makeInt (long x
)
47 multiVal mv
= multiVal_create (MVLONG
);
53 /*@only@*/ multiVal
multiVal_makeChar (char x
)
55 multiVal mv
= multiVal_create (MVCHAR
);
60 /*@only@*/ multiVal
multiVal_makeDouble (double x
)
62 multiVal mv
= multiVal_create (MVDOUBLE
);
68 /*@only@*/ multiVal
multiVal_makeString (/*@only@*/ cstring s
)
70 multiVal mv
= multiVal_create (MVSTRING
);
77 /*@only@*/ multiVal
multiVal_copy (multiVal m
)
81 if (multiVal_isUndefined (m
))
83 return multiVal_undefined
;
86 r
= multiVal_create (m
->kind
);
91 r
->value
.ival
= m
->value
.ival
;
94 r
->value
.cval
= m
->value
.cval
;
97 r
->value
.fval
= m
->value
.fval
;
100 r
->value
.sval
= cstring_copy (m
->value
.sval
);
107 multiVal
multiVal_invert (multiVal m
)
109 if (multiVal_isUndefined (m
))
111 return multiVal_undefined
;
117 return multiVal_makeInt (-1 * m
->value
.ival
);
120 return multiVal_undefined
;
122 return multiVal_makeDouble (-1.0 * m
->value
.fval
);
125 return multiVal_undefined
;
131 long multiVal_forceInt (multiVal m
)
133 if (multiVal_isInt (m
)) {
134 return m
->value
.ival
;
136 llcontbug (message ("Multival is not int: %s", multiVal_unparse (m
)));
141 char multiVal_forceChar (multiVal m
)
143 llassert (multiVal_isChar (m
));
145 return m
->value
.cval
;
149 double multiVal_forceDouble (multiVal m
)
151 llassert (multiVal_isDouble (m
));
153 return m
->value
.fval
;
155 # endif /* DEADCODE */
157 /*@dependent@*/ /*@observer@*/ cstring
multiVal_forceString (multiVal m
)
159 llassert (multiVal_isString (m
));
161 return m
->value
.sval
;
164 bool multiVal_isInt (multiVal m
)
166 return (multiVal_isDefined (m
) && m
->kind
== MVLONG
);
169 bool multiVal_isChar (multiVal m
)
171 return (multiVal_isDefined (m
) && m
->kind
== MVCHAR
);
174 bool multiVal_isDouble (multiVal m
)
176 return (multiVal_isDefined (m
) && m
->kind
== MVDOUBLE
);
179 bool multiVal_isString (multiVal m
)
181 return (multiVal_isDefined (m
) && m
->kind
== MVSTRING
);
184 /*@only@*/ cstring
multiVal_unparse (multiVal m
)
186 if (multiVal_isDefined (m
))
191 return message ("%d", (int)m
->value
.ival
);
193 return message ("'%h'", m
->value
.cval
);
195 return message ("%f", (float)m
->value
.fval
);
197 return message ("%s", m
->value
.sval
);
203 return (cstring_makeLiteral ("?"));
207 /*@only@*/ cstring
multiVal_dump (multiVal m
)
209 if (multiVal_isDefined (m
))
214 return (message ("i%d", (int)m
->value
.ival
));
216 return (message ("c%d", (int)m
->value
.cval
));
218 return (message ("d%f", (float)m
->value
.fval
));
220 return (message ("s%s", m
->value
.sval
));
226 return (cstring_undefined
);
230 /*@only@*/ multiVal
multiVal_undump (char **s
)
238 return multiVal_makeInt (reader_getInt (s
));
241 return multiVal_makeChar ((char) reader_getInt (s
));
244 return multiVal_makeDouble (reader_getDouble (s
));
247 cstring st
= cstring_undefined
;
252 st
= cstring_appendChar (st
, **s
);
256 return multiVal_makeString (st
);
260 return multiVal_unknown ();
267 int multiVal_compare (multiVal m1
, multiVal m2
)
269 if (multiVal_isUndefined (m1
))
271 if (multiVal_isUndefined (m2
))
278 if (multiVal_isUndefined (m2
))
283 COMPARERETURN (generic_compare (m1
->kind
, m2
->kind
));
287 case MVLONG
: return (generic_compare (m1
->value
.ival
, m2
->value
.ival
));
288 case MVCHAR
: return (generic_compare (m1
->value
.cval
, m2
->value
.cval
));
289 case MVDOUBLE
: return (generic_compare (m1
->value
.fval
, m2
->value
.fval
));
290 case MVSTRING
: return (cstring_compare (m1
->value
.sval
, m2
->value
.sval
));
296 multiVal
multiVal_add (multiVal m1
, multiVal m2
)
298 if (multiVal_isUndefined (m1
) || multiVal_isUndefined (m2
) || m1
->kind
!= m2
->kind
)
300 return multiVal_undefined
;
305 case MVLONG
: return (multiVal_makeInt (m1
->value
.ival
+ m2
->value
.ival
));
306 case MVCHAR
: return (multiVal_makeChar ((char) (m1
->value
.cval
+ m2
->value
.cval
)));
307 case MVDOUBLE
: return (multiVal_makeDouble (m1
->value
.fval
+ m2
->value
.fval
));
308 case MVSTRING
: return multiVal_undefined
;
314 multiVal
multiVal_subtract (multiVal m1
, multiVal m2
)
316 if (multiVal_isUndefined (m1
) || multiVal_isUndefined (m2
) || m1
->kind
!= m2
->kind
)
318 return multiVal_undefined
;
323 case MVLONG
: return (multiVal_makeInt (m1
->value
.ival
- m2
->value
.ival
));
324 case MVCHAR
: return (multiVal_makeChar ((char) (m1
->value
.cval
- m2
->value
.cval
)));
325 case MVDOUBLE
: return (multiVal_makeDouble (m1
->value
.fval
- m2
->value
.fval
));
326 case MVSTRING
: return multiVal_undefined
;
332 multiVal
multiVal_multiply (multiVal m1
, multiVal m2
)
334 if (multiVal_isUndefined (m1
) || multiVal_isUndefined (m2
) || m1
->kind
!= m2
->kind
)
336 return multiVal_undefined
;
341 case MVLONG
: return (multiVal_makeInt (m1
->value
.ival
* m2
->value
.ival
));
342 case MVCHAR
: return (multiVal_makeChar ((char) (m1
->value
.cval
* m2
->value
.cval
)));
343 case MVDOUBLE
: return (multiVal_makeDouble (m1
->value
.fval
* m2
->value
.fval
));
344 case MVSTRING
: return multiVal_undefined
;
350 multiVal
multiVal_divide (multiVal m1
, multiVal m2
)
352 if (multiVal_isUndefined (m1
) || multiVal_isUndefined (m2
) || m1
->kind
!= m2
->kind
)
354 return multiVal_undefined
;
360 if (m2
->value
.ival
!= 0)
362 return (multiVal_makeInt (m1
->value
.ival
/ m2
->value
.ival
));
366 return multiVal_undefined
;
369 if (m2
->value
.cval
!= (char) 0)
371 return (multiVal_makeChar ((char) (m1
->value
.cval
/ m2
->value
.cval
)));
375 return multiVal_undefined
;
378 return multiVal_undefined
; /* Don't attempt to divide floats */
379 case MVSTRING
: return multiVal_undefined
;
385 void multiVal_free (/*@only@*/ multiVal m
)
387 if (multiVal_isDefined (m
))
389 if (m
->kind
== MVSTRING
)
391 cstring_free (m
->value
.sval
);