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