2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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"
41 /*@-nullderef@*/ /* !!! DRL needs to fix this code! */
42 /*@-nullstate@*/ /* !!! DRL needs to fix this code! */
43 /*@-nullpass@*/ /* !!! DRL needs to fix this code! */
44 /*@-temptrans@*/ /* !!! DRL needs to fix this code! */
46 /*@access exprNode@*/ /* !!! NO! Don't do this recklessly! */
48 bool constraintTerm_isDefined (constraintTerm t)
53 void constraintTerm_free (/*@only@*/ constraintTerm term)
55 llassert (constraintTerm_isDefined (term));
57 fileloc_free (term->loc);
62 /* we don't free an exprNode*/
66 sRef_free (term->value.sref);
69 /* don't free an int */
71 case ERRORBADCONSTRAINTTERMTYPE:
73 /* type was set incorrectly */
74 llcontbug (message("constraintTerm_free type was set incorrectly"));
77 term->kind = ERRORBADCONSTRAINTTERMTYPE;
81 /*@only@*/ static/*@out@*/ constraintTerm new_constraintTermExpr (void)
84 ret = dmalloc (sizeof (* ret ) );
85 ret->value.intlit = 0;
90 bool constraintTerm_isIntLiteral (constraintTerm term)
92 llassert(term != NULL);
94 if (term->kind == INTLITERAL)
101 bool constraintTerm_isInitBlock (/*@observer@*/ /*@temp@*/ constraintTerm c) /*@*/
103 llassert (c != NULL);
104 if (c->kind == EXPRNODE)
107 if (exprNode_isInitBlock(c->value.expr) )
116 bool constraintTerm_isExprNode (/*@observer@*/ /*@temp@*/ constraintTerm c) /*@*/
118 llassert (c != NULL);
119 if (c->kind == EXPRNODE)
127 int constraintTerm_getInitBlockLength (/*@observer@*/ /*@temp@*/ constraintTerm c) /*@*/
132 llassert (c != NULL);
133 llassert (constraintTerm_isInitBlock (c) );
134 llassert (c->kind == EXPRNODE);
136 llassert(exprNode_isDefined(c->value.expr) );
138 if (exprNode_isUndefined(c->value.expr) )
143 if (c->value.expr->edata == exprData_undefined)
147 list = exprData_getArgs(c->value.expr->edata);
149 ret = exprNodeList_size(list);
156 bool constraintTerm_isStringLiteral (constraintTerm c) /*@*/
158 llassert (c != NULL);
159 if (c->kind == EXPRNODE)
161 if (exprNode_knownStringValue(c->value.expr) )
171 cstring constraintTerm_getStringLiteral (constraintTerm c)
173 llassert (c != NULL);
174 llassert (constraintTerm_isStringLiteral (c) );
175 llassert (c->kind == EXPRNODE);
177 return (cstring_copy ( multiVal_forceString (exprNode_getValue (c->value.expr) ) ) );
180 constraintTerm constraintTerm_simplify (/*@returned@*/ constraintTerm term) /*@modifies term@*/
182 if (term->kind == EXPRNODE)
184 if ( exprNode_knownIntValue (term->value.expr ) )
188 temp = exprNode_getLongValue (term->value.expr);
189 term->value.intlit = (int)temp;
190 term->kind = INTLITERAL;
196 fileloc constraintTerm_getFileloc (constraintTerm t)
198 llassert (constraintTerm_isDefined (t));
199 return (fileloc_copy (t->loc) );
202 constraintTermType constraintTerm_getKind (constraintTerm t)
204 llassert (constraintTerm_isDefined(t) );
209 /*@exposed@*/ sRef constraintTerm_getSRef (constraintTerm t)
211 llassert (constraintTerm_isDefined(t) );
212 llassert (t->kind == SREF);
214 return (t->value.sref);
217 /*@only@*/ constraintTerm constraintTerm_makeExprNode (/*@dependent@*/ exprNode e)
219 constraintTerm ret = new_constraintTermExpr();
220 ret->loc = fileloc_copy(exprNode_getfileloc(e));
222 ret->kind = EXPRNODE;
223 ret = constraintTerm_simplify(ret);
227 /*@only@*/ constraintTerm constraintTerm_makesRef (/*@temp@*/ /*@observer@*/ sRef s)
229 constraintTerm ret = new_constraintTermExpr();
230 ret->loc = fileloc_undefined;
231 ret->value.sref = sRef_saveCopy(s);
233 ret = constraintTerm_simplify(ret);
239 constraintTerm constraintTerm_copy (constraintTerm term)
242 ret = new_constraintTermExpr();
243 ret->loc = fileloc_copy (term->loc);
248 ret->value.expr = term->value.expr;
251 ret->value.intlit = term->value.intlit;
255 ret->value.sref = sRef_saveCopy(term->value.sref);
260 ret->kind = term->kind;
264 constraintTerm constraintTerm_setFileloc (/*@returned@*/ constraintTerm term, fileloc loc)
266 llassert(term != NULL);
268 if ( fileloc_isDefined( term->loc ) )
269 fileloc_free(term->loc);
271 term->loc = fileloc_copy(loc);
276 static cstring constraintTerm_getName (constraintTerm term)
279 s = cstring_undefined;
281 llassert (term != NULL);
287 s = message ("%s", exprNode_unparse (term->value.expr) );
290 s = message (" %d ", (int) term->value.intlit);
294 s = message ("%q", sRef_unparse (term->value.sref) );
307 constraintTerm_doSRefFixBaseParam (/*@returned@*/constraintTerm term, exprNodeList arglist) /*@modifies term@*/
309 llassert (term != NULL);
320 term->value.sref = sRef_fixBaseParam (term->value.sref, arglist);
329 cstring constraintTerm_print (constraintTerm term) /*@*/
332 s = cstring_undefined;
334 llassert (term != NULL);
340 s = message ("%s @ %q", exprNode_unparse (term->value.expr),
341 fileloc_unparse (term->loc) );
344 s = message ("%d", (int)term->value.intlit);
348 s = message ("%q", sRef_unparseDebug (term->value.sref) );
359 constraintTerm constraintTerm_makeIntLiteral (long i)
361 constraintTerm ret = new_constraintTermExpr();
362 ret->value.intlit = i;
363 ret->kind = INTLITERAL;
364 ret->loc = fileloc_undefined;
368 bool constraintTerm_canGetValue (constraintTerm term)
370 if (term->kind == INTLITERAL)
374 else if (term->kind == SREF)
376 if (sRef_hasValue (term->value.sref))
378 multiVal mval = sRef_getValue (term->value.sref);
380 return multiVal_isInt (mval); /* for now, only try to deal with int values */
387 else if (term->kind == EXPRNODE)
397 long constraintTerm_getValue (constraintTerm term)
399 llassert (constraintTerm_canGetValue (term));
401 if (term->kind == INTLITERAL)
403 return term->value.intlit;
405 else if (term->kind == SREF)
407 if (sRef_hasValue (term->value.sref))
409 multiVal mval = sRef_getValue (term->value.sref);
411 return multiVal_forceInt (mval); /* for now, only try to deal with int values */
418 else if (term->kind == EXPRNODE)
430 /*drl added this 10.30.001
433 /*@exposed@*/ exprNode constraintTerm_getExprNode (constraintTerm t)
435 llassert (t != NULL);
437 llassert (t->kind == EXPRNODE);
439 return t->value.expr;
443 /*@exposed@*/ sRef constraintTerm_getsRef (constraintTerm t)
445 llassert (t != NULL);
446 if (t->kind == EXPRNODE)
448 return exprNode_getSref(t->value.expr);
453 return t->value.sref;
456 return sRef_undefined;
459 bool constraintTerm_probSame (constraintTerm term1, constraintTerm term2)
463 llassert (term1 !=NULL && term2 !=NULL);
466 ("Comparing srefs for %s and %s ", constraintTerm_print(term1), constraintTerm_print(term2)
471 s1 = constraintTerm_getName (term1);
472 s2 = constraintTerm_getName (term2);
474 if (cstring_equal (s1, s2) )
476 DPRINTF ((message (" %q and %q are same", s1, s2 ) ) );
481 DPRINTF ((message (" %q and %q are not same", s1, s2 ) ) );
486 bool constraintTerm_similar (constraintTerm term1, constraintTerm term2)
490 llassert (term1 !=NULL && term2 !=NULL);
492 if (constraintTerm_canGetValue (term1) && constraintTerm_canGetValue (term2))
493 /* evans 2001-07-24: was (term1->kind == INTLITERAL) && (term2->kind == INTLITERAL) ) */
497 t1 = constraintTerm_getValue (term1);
498 t2 = constraintTerm_getValue (term2);
503 if (constraintTerm_canGetValue (term1) || constraintTerm_canGetValue (term2))
505 /* evans 2001-07-24: is this right? */ /*@i534@*/
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);
637 if (strcmp (term, "Result") == 0 )
639 s = sRef_makeResult (ctype_unknown);
641 else if (strcmp (term, "Param" ) == 0 )
648 reader_checkChar(&str, ' ');
649 str2 = reader_getWord(&str);
650 param = reader_getInt(&str);
653 t = ctype_undump(&str2) ;
654 s = sRef_makeParam (param, t, stateInfo_makeLoc (g_currentloc, SA_CREATED));
657 else if (strcmp (term, "sRef_dump" ) == 0 )
659 reader_checkChar(&str, ' ');
660 s = sRef_undump (&str);
662 else /* This must be an identified that we can search for in usymTab */
664 cstring termStr = cstring_makeLiteralTemp(term);
666 ue = usymtab_lookup (termStr);
667 s = uentry_getSref(ue);
670 ret = constraintTerm_makesRef(s);
682 term = reader_getWord(&str);
683 /* This must be an identifier that we can search for in usymTab */
684 termStr = cstring_makeLiteralTemp(term);
686 ue = usymtab_lookup (termStr);
687 s = uentry_getSref(ue);
688 ret = constraintTerm_makesRef(s);
699 i = reader_getInt(&str);
700 ret = constraintTerm_makeIntLiteral (i);
714 /* drl added sometime before 10/17/001*/
715 ctype constraintTerm_getCType (constraintTerm term)
722 ct = exprNode_getType (term->value.expr);
727 ct = ctype_signedintegral;
731 ct = sRef_getType (term->value.sref) ;
739 bool constraintTerm_isConstantOnly (constraintTerm term)
744 if (exprNode_isNumLiteral (term->value.expr) ||
745 exprNode_isStringLiteral (term->value.expr) ||
746 exprNode_isCharLiteral (term->value.expr) )
759 if ( sRef_isConst (term->value.sref) )