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 CTT_ERRORBADCONSTRAINTTERMTYPE:
65 /* type was set incorrectly */
66 llcontbug (message("constraintTerm_free type was set incorrectly"));
69 term->kind = CTT_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 == CTT_INTLITERAL)
93 bool constraintTerm_isInitBlock (/*@observer@*/ /*@temp@*/ constraintTerm c) /*@*/
97 if (c->kind == CTT_EXPR)
99 if (exprNode_isInitBlock (c->value.expr))
108 bool constraintTerm_isExprNode (/*@observer@*/ /*@temp@*/ constraintTerm c) /*@*/
110 llassert (c != NULL);
112 if (c->kind == CTT_EXPR)
119 /*@access exprNode@*/
120 int constraintTerm_getInitBlockLength (/*@observer@*/ /*@temp@*/ constraintTerm c) /*@*/
124 llassert (c != NULL);
125 llassert (constraintTerm_isInitBlock (c) );
126 llassert (c->kind == CTT_EXPR);
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 == CTT_EXPR)
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 == CTT_EXPR);
169 return (cstring_copy ( multiVal_forceString (exprNode_getValue (c->value.expr) ) ) );
172 constraintTerm constraintTerm_simplify (/*@returned@*/ constraintTerm term) /*@modifies term@*/
174 if (term->kind == CTT_EXPR)
176 if ( exprNode_knownIntValue (term->value.expr ) )
180 temp = exprNode_getLongValue (term->value.expr);
181 term->value.intlit = (int)temp;
182 term->kind = CTT_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 == CTT_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 = CTT_EXPR;
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);
224 ret->kind = CTT_SREF;
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_unparse (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 = CTT_INTLITERAL;
356 ret->loc = fileloc_undefined;
360 bool constraintTerm_canGetValue (constraintTerm term)
362 if (term->kind == CTT_INTLITERAL)
366 else if (term->kind == CTT_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 == CTT_EXPR)
389 long constraintTerm_getValue (constraintTerm term)
391 llassert (constraintTerm_canGetValue (term));
393 if (term->kind == CTT_INTLITERAL)
395 return term->value.intlit;
397 else if (term->kind == CTT_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 == CTT_EXPR)
422 /*drl added this 10.30.001
425 /*@exposed@*/ exprNode constraintTerm_getExprNode (constraintTerm t)
427 llassert (t != NULL);
429 llassert (t->kind == CTT_EXPR);
431 return t->value.expr;
435 /*@exposed@*/ sRef constraintTerm_getsRef (constraintTerm t)
437 llassert (t != NULL);
438 if (t->kind == CTT_EXPR)
440 return exprNode_getSref(t->value.expr);
443 if (t->kind == CTT_SREF)
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))
486 /*3/30/2003 comment updated to reflect name change form INTLITERAL to CTT_INTLITERAL*/
487 /* evans 2001-07-24: was (term1->kind == CTT_INTLITERAL) && (term2->kind == CTT_INTLITERAL) ) */
491 t1 = constraintTerm_getValue (term1);
492 t2 = constraintTerm_getValue (term2);
497 /*drl this if statement handles the case where constraintTerm_canGetValue only returns
498 true for term1 or term2 but no both
499 if constraintTerm_canGetValue returned tru for both we would have returned in the previous if statement
500 I suppose this could be done with xor but I've never used xor and don't feel like starting now
501 besides this way is more effecient.
503 if (constraintTerm_canGetValue (term1) || constraintTerm_canGetValue (term2))
509 s1 = constraintTerm_getsRef (term1);
510 s2 = constraintTerm_getsRef (term2);
512 if (!(sRef_isValid(s1) && sRef_isValid(s2)))
518 ("Comparing srefs for %s and %s ", constraintTerm_print(term1), constraintTerm_print(term2)
523 if (sRef_similarRelaxed(s1, s2) || sRef_sameName (s1, s2) )
525 DPRINTF ((message (" %s and %s are same", constraintTerm_print(term1), constraintTerm_print(term2) ) ));
530 DPRINTF ((message (" %s and %s are not same", constraintTerm_print(term1), constraintTerm_print(term2) ) ));
535 void constraintTerm_dump (/*@observer@*/ constraintTerm t, FILE *f)
538 constraintTermValue value;
539 constraintTermType kind;
548 fprintf(f, "%d\n", (int) kind);
554 u = exprNode_getUentry(t->value.expr);
555 fprintf (f, "%s\n", cstring_toCharsSafe (uentry_rawName (u)));
564 if (sRef_isResult (s ) )
566 fprintf(f, "Result\n");
568 else if (sRef_isParam (s))
575 ct = sRef_getType (s);
576 param = sRef_getParam(s);
578 ctString = ctype_dump(ct);
580 fprintf(f, "Param %s %d\n", cstring_toCharsSafe(ctString), (int) param );
581 cstring_free(ctString);
583 else if (sRef_isField (s) )
585 fprintf(f, "sRef_dump %s\n", cstring_toCharsSafe(sRef_dump(s)) );
589 u = sRef_getUentry(s);
590 fprintf (f, "%s\n", cstring_toCharsSafe (uentry_rawName (u)));
597 fprintf (f, "%ld\n", t->value.intlit);
607 /*@only@*/ constraintTerm constraintTerm_undump (FILE *f)
609 constraintTermType kind;
617 os = mstring_create (MAX_DUMP_LINE_LENGTH);
619 str = fgets (os, MAX_DUMP_LINE_LENGTH, f);
621 llassert (str != NULL);
623 kind = (constraintTermType) reader_getInt(&str);
624 str = fgets(os, MAX_DUMP_LINE_LENGTH, f);
626 llassert (str != NULL);
635 term = reader_getWord(&str);
639 llfatalbug (message ("Library file appears to be corrupted.") );
641 if (strcmp (term, "Result") == 0 )
643 s = sRef_makeResult (ctype_unknown);
645 else if (strcmp (term, "Param" ) == 0 )
652 reader_checkChar(&str, ' ');
653 str2 = reader_getWord(&str);
654 param = reader_getInt(&str);
658 llfatalbug (message ("Library file appears to be corrupted.") );
662 t = ctype_undump(&str2) ;
663 s = sRef_makeParam (param, t, stateInfo_makeLoc (g_currentloc, SA_CREATED));
666 else if (strcmp (term, "sRef_dump" ) == 0 )
668 reader_checkChar(&str, ' ');
669 s = sRef_undump (&str);
671 else /* This must be an identified that we can search for in usymTab */
673 cstring termStr = cstring_makeLiteralTemp(term);
675 ue = usymtab_lookup (termStr);
676 s = uentry_getSref(ue);
679 ret = constraintTerm_makesRef(s);
691 term = reader_getWord(&str);
695 llfatalbug (message ("Library file appears to be corrupted.") );
698 /* This must be an identifier that we can search for in usymTab */
699 termStr = cstring_makeLiteralTemp(term);
701 ue = usymtab_lookup (termStr);
702 s = uentry_getSref(ue);
703 ret = constraintTerm_makesRef(s);
714 i = reader_getInt(&str);
715 ret = constraintTerm_makeIntLiteral (i);
729 /* drl added sometime before 10/17/001*/
730 ctype constraintTerm_getCType (constraintTerm term)
737 ct = exprNode_getType (term->value.expr);
741 ct = ctype_signedintegral;
745 ct = sRef_getType (term->value.sref) ;
753 bool constraintTerm_isConstantOnly (constraintTerm term)
758 if (exprNode_isNumLiteral (term->value.expr) ||
759 exprNode_isStringLiteral (term->value.expr) ||
760 exprNode_isCharLiteral (term->value.expr) )
773 if ( sRef_isConst (term->value.sref) )