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
29 /* #define DEBUGPRINT 1 */
31 # include <ctype.h> /* for isdigit */
32 # include "splintMacros.nf"
34 # include "cgrammar.h"
35 # include "cgrammar_tokens.h"
37 # include "exprChecks.h"
38 # include "exprNodeSList.h"
40 bool constraintTerm_isDefined (constraintTerm t)
45 void constraintTerm_free (/*@only@*/ constraintTerm term)
47 llassert (constraintTerm_isDefined (term));
49 fileloc_free (term->loc);
54 /* we don't free an exprNode*/
58 sRef_free (term->value.sref);
61 /* don't free an int */
63 case ERRORBADCONSTRAINTTERMTYPE:
65 /* type was set incorrectly */
66 llcontbug (message("constraintTerm_free type was set incorrectly"));
69 term->kind = ERRORBADCONSTRAINTTERMTYPE;
73 /*@only@*/ static/*@out@*/ constraintTerm new_constraintTermExpr (void)
76 ret = dmalloc (sizeof (* ret ) );
77 ret->value.intlit = 0;
82 bool constraintTerm_isIntLiteral (constraintTerm term)
84 llassert(term != NULL);
86 if (term->kind == INTLITERAL)
93 bool constraintTerm_isInitBlock (/*@observer@*/ /*@temp@*/ constraintTerm c) /*@*/
96 if (c->kind == EXPRNODE)
99 if (exprNode_isInitBlock(c->value.expr) )
108 bool constraintTerm_isExprNode (/*@observer@*/ /*@temp@*/ constraintTerm c) /*@*/
110 llassert (c != NULL);
111 if (c->kind == EXPRNODE)
118 /*@access exprNode@*/
119 int constraintTerm_getInitBlockLength (/*@observer@*/ /*@temp@*/ constraintTerm c) /*@*/
124 llassert (c != NULL);
125 llassert (constraintTerm_isInitBlock (c) );
126 llassert (c->kind == EXPRNODE);
128 llassert(exprNode_isDefined(c->value.expr) );
130 if (exprNode_isUndefined(c->value.expr) )
135 if (c->value.expr->edata == exprData_undefined)
139 list = exprData_getArgs(c->value.expr->edata);
141 ret = exprNodeList_size(list);
145 /*@noaccess exprNode@*/
148 bool constraintTerm_isStringLiteral (constraintTerm c) /*@*/
150 llassert (c != NULL);
151 if (c->kind == EXPRNODE)
153 if (exprNode_knownStringValue(c->value.expr) )
163 cstring constraintTerm_getStringLiteral (constraintTerm c)
165 llassert (c != NULL);
166 llassert (constraintTerm_isStringLiteral (c) );
167 llassert (c->kind == EXPRNODE);
169 return (cstring_copy ( multiVal_forceString (exprNode_getValue (c->value.expr) ) ) );
172 constraintTerm constraintTerm_simplify (/*@returned@*/ constraintTerm term) /*@modifies term@*/
174 if (term->kind == EXPRNODE)
176 if ( exprNode_knownIntValue (term->value.expr ) )
180 temp = exprNode_getLongValue (term->value.expr);
181 term->value.intlit = (int)temp;
182 term->kind = INTLITERAL;
188 fileloc constraintTerm_getFileloc (constraintTerm t)
190 llassert (constraintTerm_isDefined (t));
191 return (fileloc_copy (t->loc) );
194 constraintTermType constraintTerm_getKind (constraintTerm t)
196 llassert (constraintTerm_isDefined(t) );
201 /*@exposed@*/ sRef constraintTerm_getSRef (constraintTerm t)
203 llassert (constraintTerm_isDefined(t) );
204 llassert (t->kind == SREF);
206 return (t->value.sref);
209 /*@only@*/ constraintTerm constraintTerm_makeExprNode (/*@dependent@*/ exprNode e)
211 constraintTerm ret = new_constraintTermExpr();
212 ret->loc = fileloc_copy(exprNode_getfileloc(e));
214 ret->kind = EXPRNODE;
215 ret = constraintTerm_simplify(ret);
219 /*@only@*/ constraintTerm constraintTerm_makesRef (/*@temp@*/ /*@observer@*/ sRef s)
221 constraintTerm ret = new_constraintTermExpr();
222 ret->loc = fileloc_undefined;
223 ret->value.sref = sRef_saveCopy(s);
225 ret = constraintTerm_simplify(ret);
231 constraintTerm constraintTerm_copy (constraintTerm term)
234 ret = new_constraintTermExpr();
235 ret->loc = fileloc_copy (term->loc);
240 ret->value.expr = term->value.expr;
243 ret->value.intlit = term->value.intlit;
247 ret->value.sref = sRef_saveCopy(term->value.sref);
252 ret->kind = term->kind;
256 constraintTerm constraintTerm_setFileloc (/*@returned@*/ constraintTerm term, fileloc loc)
258 llassert(term != NULL);
260 if ( fileloc_isDefined( term->loc ) )
261 fileloc_free(term->loc);
263 term->loc = fileloc_copy(loc);
268 static cstring constraintTerm_getName (constraintTerm term)
271 s = cstring_undefined;
273 llassert (term != NULL);
279 s = message ("%s", exprNode_unparse (term->value.expr) );
282 s = message (" %d ", (int) term->value.intlit);
286 s = message ("%q", sRef_unparse (term->value.sref) );
299 constraintTerm_doSRefFixBaseParam (/*@returned@*/constraintTerm term, exprNodeList arglist) /*@modifies term@*/
301 llassert (term != NULL);
312 term->value.sref = sRef_fixBaseParam (term->value.sref, arglist);
321 cstring constraintTerm_print (constraintTerm term) /*@*/
324 s = cstring_undefined;
326 llassert (term != NULL);
332 s = message ("%s @ %q", exprNode_unparse (term->value.expr),
333 fileloc_unparse (term->loc) );
336 s = message ("%d", (int)term->value.intlit);
340 s = message ("%q", sRef_unparseDebug (term->value.sref) );
351 constraintTerm constraintTerm_makeIntLiteral (long i)
353 constraintTerm ret = new_constraintTermExpr();
354 ret->value.intlit = i;
355 ret->kind = INTLITERAL;
356 ret->loc = fileloc_undefined;
360 bool constraintTerm_canGetValue (constraintTerm term)
362 if (term->kind == INTLITERAL)
366 else if (term->kind == SREF)
368 if (sRef_hasValue (term->value.sref))
370 multiVal mval = sRef_getValue (term->value.sref);
372 return multiVal_isInt (mval); /* for now, only try to deal with int values */
379 else if (term->kind == EXPRNODE)
389 long constraintTerm_getValue (constraintTerm term)
391 llassert (constraintTerm_canGetValue (term));
393 if (term->kind == INTLITERAL)
395 return term->value.intlit;
397 else if (term->kind == SREF)
399 if (sRef_hasValue (term->value.sref))
401 multiVal mval = sRef_getValue (term->value.sref);
403 return multiVal_forceInt (mval); /* for now, only try to deal with int values */
410 else if (term->kind == EXPRNODE)
422 /*drl added this 10.30.001
425 /*@exposed@*/ exprNode constraintTerm_getExprNode (constraintTerm t)
427 llassert (t != NULL);
429 llassert (t->kind == EXPRNODE);
431 return t->value.expr;
435 /*@exposed@*/ sRef constraintTerm_getsRef (constraintTerm t)
437 llassert (t != NULL);
438 if (t->kind == EXPRNODE)
440 return exprNode_getSref(t->value.expr);
445 return t->value.sref;
448 return sRef_undefined;
451 bool constraintTerm_probSame (constraintTerm term1, constraintTerm term2)
455 llassert (term1 !=NULL && term2 !=NULL);
458 ("Comparing srefs for %s and %s ", constraintTerm_print(term1), constraintTerm_print(term2)
463 s1 = constraintTerm_getName (term1);
464 s2 = constraintTerm_getName (term2);
466 if (cstring_equal (s1, s2) )
468 DPRINTF ((message (" %q and %q are same", s1, s2 ) ) );
473 DPRINTF ((message (" %q and %q are not same", s1, s2 ) ) );
478 bool constraintTerm_similar (constraintTerm term1, constraintTerm term2)
482 llassert (term1 !=NULL && term2 !=NULL);
484 if (constraintTerm_canGetValue (term1) && constraintTerm_canGetValue (term2))
485 /* evans 2001-07-24: was (term1->kind == INTLITERAL) && (term2->kind == INTLITERAL) ) */
489 t1 = constraintTerm_getValue (term1);
490 t2 = constraintTerm_getValue (term2);
495 if (constraintTerm_canGetValue (term1) || constraintTerm_canGetValue (term2))
497 /* evans 2001-07-24: is this right? */ /*@i534@*/
501 s1 = constraintTerm_getsRef (term1);
502 s2 = constraintTerm_getsRef (term2);
504 if (!(sRef_isValid(s1) && sRef_isValid(s2)))
510 ("Comparing srefs for %s and %s ", constraintTerm_print(term1), constraintTerm_print(term2)
515 if (sRef_similarRelaxed(s1, s2) || sRef_sameName (s1, s2) )
517 DPRINTF ((message (" %s and %s are same", constraintTerm_print(term1), constraintTerm_print(term2) ) ));
522 DPRINTF ((message (" %s and %s are not same", constraintTerm_print(term1), constraintTerm_print(term2) ) ));
527 void constraintTerm_dump (/*@observer@*/ constraintTerm t, FILE *f)
530 constraintTermValue value;
531 constraintTermType kind;
540 fprintf(f, "%d\n", (int) kind);
546 u = exprNode_getUentry(t->value.expr);
547 fprintf (f, "%s\n", cstring_toCharsSafe (uentry_rawName (u)));
556 if (sRef_isResult (s ) )
558 fprintf(f, "Result\n");
560 else if (sRef_isParam (s))
567 ct = sRef_getType (s);
568 param = sRef_getParam(s);
570 ctString = ctype_dump(ct);
572 fprintf(f, "Param %s %d\n", cstring_toCharsSafe(ctString), (int) param );
573 cstring_free(ctString);
575 else if (sRef_isField (s) )
577 fprintf(f, "sRef_dump %s\n", cstring_toCharsSafe(sRef_dump(s)) );
581 u = sRef_getUentry(s);
582 fprintf (f, "%s\n", cstring_toCharsSafe (uentry_rawName (u)));
589 fprintf (f, "%ld\n", t->value.intlit);
599 /*@only@*/ constraintTerm constraintTerm_undump (FILE *f)
601 constraintTermType kind;
609 os = mstring_create (MAX_DUMP_LINE_LENGTH);
611 str = fgets (os, MAX_DUMP_LINE_LENGTH, f);
613 llassert (str != NULL);
615 kind = (constraintTermType) reader_getInt(&str);
616 str = fgets(os, MAX_DUMP_LINE_LENGTH, f);
618 llassert (str != NULL);
627 term = reader_getWord(&str);
631 llfatalbug (message ("Library file appears to be corrupted.") );
633 if (strcmp (term, "Result") == 0 )
635 s = sRef_makeResult (ctype_unknown);
637 else if (strcmp (term, "Param" ) == 0 )
644 reader_checkChar(&str, ' ');
645 str2 = reader_getWord(&str);
646 param = reader_getInt(&str);
650 llfatalbug (message ("Library file appears to be corrupted.") );
654 t = ctype_undump(&str2) ;
655 s = sRef_makeParam (param, t, stateInfo_makeLoc (g_currentloc, SA_CREATED));
658 else if (strcmp (term, "sRef_dump" ) == 0 )
660 reader_checkChar(&str, ' ');
661 s = sRef_undump (&str);
663 else /* This must be an identified that we can search for in usymTab */
665 cstring termStr = cstring_makeLiteralTemp(term);
667 ue = usymtab_lookup (termStr);
668 s = uentry_getSref(ue);
671 ret = constraintTerm_makesRef(s);
683 term = reader_getWord(&str);
687 llfatalbug (message ("Library file appears to be corrupted.") );
690 /* This must be an identifier that we can search for in usymTab */
691 termStr = cstring_makeLiteralTemp(term);
693 ue = usymtab_lookup (termStr);
694 s = uentry_getSref(ue);
695 ret = constraintTerm_makesRef(s);
706 i = reader_getInt(&str);
707 ret = constraintTerm_makeIntLiteral (i);
721 /* drl added sometime before 10/17/001*/
722 ctype constraintTerm_getCType (constraintTerm term)
729 ct = exprNode_getType (term->value.expr);
734 ct = ctype_signedintegral;
738 ct = sRef_getType (term->value.sref) ;
746 bool constraintTerm_isConstantOnly (constraintTerm term)
751 if (exprNode_isNumLiteral (term->value.expr) ||
752 exprNode_isStringLiteral (term->value.expr) ||
753 exprNode_isCharLiteral (term->value.expr) )
766 if ( sRef_isConst (term->value.sref) )