]> andersk Git - splint.git/blame_incremental - src/constraintTerm.c
Fixed data on readme.
[splint.git] / src / constraintTerm.c
... / ...
CommitLineData
1/*
2** Splint - annotation-assisted static program checker
3** Copyright (C) 1994-2002 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/*
26** constraintTerm.c
27*/
28
29/* #define DEBUGPRINT 1 */
30
31# include <ctype.h> /* for isdigit */
32# include "splintMacros.nf"
33# include "basic.h"
34# include "cgrammar.h"
35# include "cgrammar_tokens.h"
36
37# include "exprChecks.h"
38# include "exprNodeSList.h"
39
40/*@-czechfcns@*/
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! */
45
46/*@access exprNode@*/ /* !!! NO! Don't do this recklessly! */
47
48bool constraintTerm_isDefined (constraintTerm t)
49{
50 return t != NULL;
51}
52
53void constraintTerm_free (/*@only@*/ constraintTerm term)
54{
55 llassert (constraintTerm_isDefined (term));
56
57 fileloc_free (term->loc);
58
59 switch (term->kind)
60 {
61 case EXPRNODE:
62 /* we don't free an exprNode*/
63 break;
64 case SREF:
65 /* sref */
66 sRef_free (term->value.sref);
67 break;
68 case INTLITERAL:
69 /* don't free an int */
70 break;
71 case ERRORBADCONSTRAINTTERMTYPE:
72 default:
73 /* type was set incorrectly */
74 llcontbug (message("constraintTerm_free type was set incorrectly"));
75 }
76
77 term->kind = ERRORBADCONSTRAINTTERMTYPE;
78 free (term);
79}
80
81/*@only@*/ static/*@out@*/ constraintTerm new_constraintTermExpr (void)
82{
83 constraintTerm ret;
84 ret = dmalloc (sizeof (* ret ) );
85 ret->value.intlit = 0;
86 return ret;
87}
88
89
90bool constraintTerm_isIntLiteral (constraintTerm term)
91{
92 llassert(term != NULL);
93
94 if (term->kind == INTLITERAL)
95 return TRUE;
96
97 return FALSE;
98}
99
100
101bool constraintTerm_isInitBlock (/*@observer@*/ /*@temp@*/ constraintTerm c) /*@*/
102{
103 llassert (c != NULL);
104 if (c->kind == EXPRNODE)
105 {
106
107 if (exprNode_isInitBlock(c->value.expr) )
108 {
109 return TRUE;
110 }
111 }
112 return FALSE;
113}
114
115
116bool constraintTerm_isExprNode (/*@observer@*/ /*@temp@*/ constraintTerm c) /*@*/
117{
118 llassert (c != NULL);
119 if (c->kind == EXPRNODE)
120 {
121 return TRUE;
122 }
123 return FALSE;
124}
125
126
127int constraintTerm_getInitBlockLength (/*@observer@*/ /*@temp@*/ constraintTerm c) /*@*/
128{
129
130 exprNodeList list;
131 int ret;
132 llassert (c != NULL);
133 llassert (constraintTerm_isInitBlock (c) );
134 llassert (c->kind == EXPRNODE);
135
136 llassert(exprNode_isDefined(c->value.expr) );
137
138 if (exprNode_isUndefined(c->value.expr) )
139 {
140 return 1;
141 }
142
143 if (c->value.expr->edata == exprData_undefined)
144 {
145 return 1;
146 }
147 list = exprData_getArgs(c->value.expr->edata);
148
149 ret = exprNodeList_size(list);
150
151 return ret;
152}
153
154
155
156bool constraintTerm_isStringLiteral (constraintTerm c) /*@*/
157{
158 llassert (c != NULL);
159 if (c->kind == EXPRNODE)
160 {
161 if (exprNode_knownStringValue(c->value.expr) )
162 {
163 return TRUE;
164 }
165 }
166 return FALSE;
167}
168
169
170
171cstring constraintTerm_getStringLiteral (constraintTerm c)
172{
173 llassert (c != NULL);
174 llassert (constraintTerm_isStringLiteral (c) );
175 llassert (c->kind == EXPRNODE);
176
177 return (cstring_copy ( multiVal_forceString (exprNode_getValue (c->value.expr) ) ) );
178}
179
180constraintTerm constraintTerm_simplify (/*@returned@*/ constraintTerm term) /*@modifies term@*/
181{
182 if (term->kind == EXPRNODE)
183 {
184 if ( exprNode_knownIntValue (term->value.expr ) )
185 {
186 long int temp;
187
188 temp = exprNode_getLongValue (term->value.expr);
189 term->value.intlit = (int)temp;
190 term->kind = INTLITERAL;
191 }
192 }
193 return term;
194}
195
196fileloc constraintTerm_getFileloc (constraintTerm t)
197{
198 llassert (constraintTerm_isDefined (t));
199 return (fileloc_copy (t->loc) );
200}
201
202constraintTermType constraintTerm_getKind (constraintTerm t)
203{
204 llassert (constraintTerm_isDefined(t) );
205
206 return (t->kind);
207}
208
209/*@exposed@*/ sRef constraintTerm_getSRef (constraintTerm t)
210{
211 llassert (constraintTerm_isDefined(t) );
212 llassert (t->kind == SREF);
213
214 return (t->value.sref);
215}
216
217/*@only@*/ constraintTerm constraintTerm_makeExprNode (/*@dependent@*/ exprNode e)
218{
219 constraintTerm ret = new_constraintTermExpr();
220 ret->loc = fileloc_copy(exprNode_getfileloc(e));
221 ret->value.expr = e;
222 ret->kind = EXPRNODE;
223 ret = constraintTerm_simplify(ret);
224 return ret;
225}
226
227/*@only@*/ constraintTerm constraintTerm_makesRef (/*@temp@*/ /*@observer@*/ sRef s)
228{
229 constraintTerm ret = new_constraintTermExpr();
230 ret->loc = fileloc_undefined;
231 ret->value.sref = sRef_saveCopy(s);
232 ret->kind = SREF;
233 ret = constraintTerm_simplify(ret);
234 return ret;
235}
236
237
238
239constraintTerm constraintTerm_copy (constraintTerm term)
240{
241 constraintTerm ret;
242 ret = new_constraintTermExpr();
243 ret->loc = fileloc_copy (term->loc);
244
245 switch (term->kind)
246 {
247 case EXPRNODE:
248 ret->value.expr = term->value.expr;
249 break;
250 case INTLITERAL:
251 ret->value.intlit = term->value.intlit;
252 break;
253
254 case SREF:
255 ret->value.sref = sRef_saveCopy(term->value.sref);
256 break;
257 default:
258 BADEXIT;
259 }
260 ret->kind = term->kind;
261 return ret;
262}
263
264constraintTerm constraintTerm_setFileloc (/*@returned@*/ constraintTerm term, fileloc loc)
265{
266 llassert(term != NULL);
267
268 if ( fileloc_isDefined( term->loc ) )
269 fileloc_free(term->loc);
270
271 term->loc = fileloc_copy(loc);
272 return term;
273}
274
275
276static cstring constraintTerm_getName (constraintTerm term)
277{
278 cstring s;
279 s = cstring_undefined;
280
281 llassert (term != NULL);
282
283 switch (term->kind)
284 {
285 case EXPRNODE:
286 /*@i334*/ /*wtf*/
287 s = message ("%s", exprNode_unparse (term->value.expr) );
288 break;
289 case INTLITERAL:
290 s = message (" %d ", (int) term->value.intlit);
291 break;
292
293 case SREF:
294 s = message ("%q", sRef_unparse (term->value.sref) );
295
296 break;
297 default:
298 BADEXIT;
299 /*@notreached@*/
300 break;
301 }
302
303 return s;
304}
305
306constraintTerm
307constraintTerm_doSRefFixBaseParam (/*@returned@*/constraintTerm term, exprNodeList arglist) /*@modifies term@*/
308{
309 llassert (term != NULL);
310
311 switch (term->kind)
312 {
313 case EXPRNODE:
314 /*@i334*/ /*wtf*/
315 break;
316 case INTLITERAL:
317 break;
318
319 case SREF:
320 term->value.sref = sRef_fixBaseParam (term->value.sref, arglist);
321 break;
322 default:
323 BADEXIT;
324 }
325 return term;
326
327}
328
329cstring constraintTerm_print (constraintTerm term) /*@*/
330{
331 cstring s;
332 s = cstring_undefined;
333
334 llassert (term != NULL);
335
336 switch (term->kind)
337 {
338 case EXPRNODE:
339 /*@i334*/ /*wtf*/
340 s = message ("%s @ %q", exprNode_unparse (term->value.expr),
341 fileloc_unparse (term->loc) );
342 break;
343 case INTLITERAL:
344 s = message ("%d", (int)term->value.intlit);
345 break;
346
347 case SREF:
348 s = message ("%q", sRef_unparseDebug (term->value.sref) );
349
350 break;
351 default:
352 BADEXIT;
353 }
354
355 return s;
356}
357
358
359constraintTerm constraintTerm_makeIntLiteral (long i)
360{
361 constraintTerm ret = new_constraintTermExpr();
362 ret->value.intlit = i;
363 ret->kind = INTLITERAL;
364 ret->loc = fileloc_undefined;
365 return ret;
366}
367
368bool constraintTerm_canGetValue (constraintTerm term)
369{
370 if (term->kind == INTLITERAL)
371 {
372 return TRUE;
373 }
374 else if (term->kind == SREF)
375 {
376 if (sRef_hasValue (term->value.sref))
377 {
378 multiVal mval = sRef_getValue (term->value.sref);
379
380 return multiVal_isInt (mval); /* for now, only try to deal with int values */
381 }
382 else
383 {
384 return FALSE;
385 }
386 }
387 else if (term->kind == EXPRNODE)
388 {
389 return FALSE;
390 }
391 else
392 {
393 return FALSE;
394 }
395}
396
397long constraintTerm_getValue (constraintTerm term)
398{
399 llassert (constraintTerm_canGetValue (term));
400
401 if (term->kind == INTLITERAL)
402 {
403 return term->value.intlit;
404 }
405 else if (term->kind == SREF)
406 {
407 if (sRef_hasValue (term->value.sref))
408 {
409 multiVal mval = sRef_getValue (term->value.sref);
410
411 return multiVal_forceInt (mval); /* for now, only try to deal with int values */
412 }
413 else
414 {
415 BADBRANCH;
416 }
417 }
418 else if (term->kind == EXPRNODE)
419 {
420 BADBRANCH;
421 }
422 else
423 {
424 BADBRANCH;
425 }
426
427 BADEXIT;
428}
429
430/*drl added this 10.30.001
431 */
432
433/*@exposed@*/ exprNode constraintTerm_getExprNode (constraintTerm t)
434{
435 llassert (t != NULL);
436
437 llassert (t->kind == EXPRNODE);
438
439 return t->value.expr;
440
441}
442
443 /*@exposed@*/ sRef constraintTerm_getsRef (constraintTerm t)
444{
445 llassert (t != NULL);
446 if (t->kind == EXPRNODE)
447 {
448 return exprNode_getSref(t->value.expr);
449 }
450
451 if (t->kind == SREF)
452 {
453 return t->value.sref;
454 }
455
456 return sRef_undefined;
457}
458
459bool constraintTerm_probSame (constraintTerm term1, constraintTerm term2)
460{
461 cstring s1, s2;
462
463 llassert (term1 !=NULL && term2 !=NULL);
464
465 DPRINTF ((message
466 ("Comparing srefs for %s and %s ", constraintTerm_print(term1), constraintTerm_print(term2)
467 )
468 )
469 );
470
471 s1 = constraintTerm_getName (term1);
472 s2 = constraintTerm_getName (term2);
473
474 if (cstring_equal (s1, s2) )
475 {
476 DPRINTF ((message (" %q and %q are same", s1, s2 ) ) );
477 return TRUE;
478 }
479 else
480 {
481 DPRINTF ((message (" %q and %q are not same", s1, s2 ) ) );
482 return FALSE;
483 }
484}
485
486bool constraintTerm_similar (constraintTerm term1, constraintTerm term2)
487{
488 sRef s1, s2;
489
490 llassert (term1 !=NULL && term2 !=NULL);
491
492 if (constraintTerm_canGetValue (term1) && constraintTerm_canGetValue (term2))
493 /* evans 2001-07-24: was (term1->kind == INTLITERAL) && (term2->kind == INTLITERAL) ) */
494 {
495 long t1, t2;
496
497 t1 = constraintTerm_getValue (term1);
498 t2 = constraintTerm_getValue (term2);
499
500 return (t1 == t2);
501 }
502
503 if (constraintTerm_canGetValue (term1) || constraintTerm_canGetValue (term2))
504 {
505 /* evans 2001-07-24: is this right? */ /*@i534@*/
506 return FALSE;
507 }
508
509 s1 = constraintTerm_getsRef (term1);
510 s2 = constraintTerm_getsRef (term2);
511
512 if (!(sRef_isValid(s1) && sRef_isValid(s2)))
513 {
514 return FALSE;
515 }
516
517 DPRINTF((message
518 ("Comparing srefs for %s and %s ", constraintTerm_print(term1), constraintTerm_print(term2)
519 )
520 )
521 );
522
523 if (sRef_similarRelaxed(s1, s2) || sRef_sameName (s1, s2) )
524 {
525 DPRINTF ((message (" %s and %s are same", constraintTerm_print(term1), constraintTerm_print(term2) ) ));
526 return TRUE;
527 }
528 else
529 {
530 DPRINTF ((message (" %s and %s are not same", constraintTerm_print(term1), constraintTerm_print(term2) ) ));
531 return FALSE;
532 }
533}
534
535void constraintTerm_dump (/*@observer@*/ constraintTerm t, FILE *f)
536{
537 fileloc loc;
538 constraintTermValue value;
539 constraintTermType kind;
540 uentry u;
541
542 loc = t->loc;
543
544 value = t->value;
545
546 kind = t->kind;
547
548 fprintf(f, "%d\n", (int) kind);
549
550 switch (kind)
551 {
552
553 case EXPRNODE:
554 u = exprNode_getUentry(t->value.expr);
555 fprintf (f, "%s\n", cstring_toCharsSafe (uentry_rawName (u)));
556 break;
557
558 case SREF:
559 {
560 sRef s;
561
562 s = t->value.sref;
563
564 if (sRef_isResult (s ) )
565 {
566 fprintf(f, "Result\n");
567 }
568 else if (sRef_isParam (s))
569 {
570 int param;
571 ctype ct;
572 cstring ctString;
573
574
575 ct = sRef_getType (s);
576 param = sRef_getParam(s);
577
578 ctString = ctype_dump(ct);
579
580 fprintf(f, "Param %s %d\n", cstring_toCharsSafe(ctString), (int) param );
581 cstring_free(ctString);
582 }
583 else if (sRef_isField (s) )
584 {
585 fprintf(f, "sRef_dump %s\n", cstring_toCharsSafe(sRef_dump(s)) );
586 }
587 else
588 {
589 u = sRef_getUentry(s);
590 fprintf (f, "%s\n", cstring_toCharsSafe (uentry_rawName (u)));
591 }
592
593 }
594 break;
595
596 case INTLITERAL:
597 fprintf (f, "%ld\n", t->value.intlit);
598 break;
599
600 default:
601 BADEXIT;
602 }
603
604}
605
606
607/*@only@*/ constraintTerm constraintTerm_undump (FILE *f)
608{
609 constraintTermType kind;
610 constraintTerm ret;
611
612 uentry ue;
613
614 char *str;
615 char *os;
616
617 os = mstring_create (MAX_DUMP_LINE_LENGTH);
618
619 str = fgets (os, MAX_DUMP_LINE_LENGTH, f);
620
621 llassert (str != NULL);
622
623 kind = (constraintTermType) reader_getInt(&str);
624 str = fgets(os, MAX_DUMP_LINE_LENGTH, f);
625
626 llassert (str != NULL);
627
628 switch (kind)
629 {
630
631 case SREF:
632 {
633 sRef s;
634 char * term;
635 term = reader_getWord(&str);
636
637 if (strcmp (term, "Result") == 0 )
638 {
639 s = sRef_makeResult (ctype_unknown);
640 }
641 else if (strcmp (term, "Param" ) == 0 )
642 {
643 int param;
644 char *str2, *ostr2;
645
646 ctype t;
647
648 reader_checkChar(&str, ' ');
649 str2 = reader_getWord(&str);
650 param = reader_getInt(&str);
651
652 ostr2 = str2;
653 t = ctype_undump(&str2) ;
654 s = sRef_makeParam (param, t, stateInfo_makeLoc (g_currentloc, SA_CREATED));
655 free (ostr2);
656 }
657 else if (strcmp (term, "sRef_dump" ) == 0 )
658 {
659 reader_checkChar(&str, ' ');
660 s = sRef_undump (&str);
661 }
662 else /* This must be an identified that we can search for in usymTab */
663 {
664 cstring termStr = cstring_makeLiteralTemp(term);
665
666 ue = usymtab_lookup (termStr);
667 s = uentry_getSref(ue);
668 }
669
670 ret = constraintTerm_makesRef(s);
671
672 free(term);
673 }
674 break;
675
676 case EXPRNODE:
677 {
678 sRef s;
679 char * term;
680 cstring termStr;
681
682 term = reader_getWord(&str);
683 /* This must be an identifier that we can search for in usymTab */
684 termStr = cstring_makeLiteralTemp(term);
685
686 ue = usymtab_lookup (termStr);
687 s = uentry_getSref(ue);
688 ret = constraintTerm_makesRef(s);
689
690 free (term);
691 }
692 break;
693
694
695 case INTLITERAL:
696 {
697 int i;
698
699 i = reader_getInt(&str);
700 ret = constraintTerm_makeIntLiteral (i);
701 }
702 break;
703
704 default:
705 BADEXIT;
706 }
707 free (os);
708
709 return ret;
710}
711
712
713
714/* drl added sometime before 10/17/001*/
715ctype constraintTerm_getCType (constraintTerm term)
716{
717 ctype ct;
718
719 switch (term->kind)
720 {
721 case EXPRNODE:
722 ct = exprNode_getType (term->value.expr);
723 break;
724
725 case INTLITERAL:
726 /*@i888*/ /* hack */
727 ct = ctype_signedintegral;
728 break;
729
730 case SREF:
731 ct = sRef_getType (term->value.sref) ;
732 break;
733 default:
734 BADEXIT;
735 }
736 return ct;
737}
738
739bool constraintTerm_isConstantOnly (constraintTerm term)
740{
741 switch (term->kind)
742 {
743 case EXPRNODE:
744 if (exprNode_isNumLiteral (term->value.expr) ||
745 exprNode_isStringLiteral (term->value.expr) ||
746 exprNode_isCharLiteral (term->value.expr) )
747 {
748 return TRUE;
749 }
750 else
751 {
752 return FALSE;
753 }
754
755 case INTLITERAL:
756 return TRUE;
757
758 case SREF:
759 if ( sRef_isConst (term->value.sref) )
760 {
761 return TRUE;
762 }
763 else
764 {
765 return FALSE;
766 }
767 default:
768 BADEXIT;
769 }
770
771 BADEXIT;
772}
This page took 0.052607 seconds and 5 git commands to generate.