Fixed some bugs...
[repair.git] / Repair / RepairInterpreter / tmap.cc
1 #include <stdio.h>
2 #include "tmap.h"
3 extern "C" {
4 #include "redblack.h"
5 }
6 #include "tmodel.h"
7 #include "model.h"
8 #include "processabstract.h"
9 #include "element.h"
10
11 #define CHECKTYPE
12 #define CHECKMEMORY
13
14 typemap::typemap(model *m) {
15   alloctree=rbinit();
16   typetree=rbinit();
17   globalmodel=m;
18 }
19
20 void freefunction(void *ptr) {
21   if(ptr!=NULL) {
22     delete((structuremap *)ptr);
23   }
24 }
25
26 typemap::~typemap() {
27   rbdestroy(typetree,freefunction);
28   rbdestroy(alloctree,freefunction);
29 }
30
31 void typemap::reset() {
32   rbdestroy(typetree,freefunction);
33   typetree=rbinit();
34 }
35
36 structuremap::structuremap(structure *s) {
37   str=s;
38   typetree=rbinit();
39 }
40
41 structuremap::~structuremap() {
42   rbdestroy(typetree,freefunction);
43 }
44
45 bool typemap::asserttype(void *ptr, structure *s) {
46
47 #ifdef CHECKTYPE
48   bool b=checktype(true,ptr,s);
49   if (!b) {
50     printf("Assertion failure\n");
51     bool testb=checktype(true,ptr,s);
52   }
53   return b;
54 #endif
55
56   return assertvalidmemory(ptr, s);
57 }
58
59 bool typemap::assertvalidmemory(void* low, void* high) {
60
61 #ifdef CHECKMEMORY
62   return checkmemory(low, high);
63 #endif
64
65   return true;
66 }
67
68 bool typemap::assertvalidmemory(void* ptr, structure* s) {
69
70 #ifdef CHECKMEMORY
71   int size=s->getsize(globalmodel->getbitreader(),globalmodel,globalmodel->gethashtable());
72   void *low=ptr;
73   void *high=((char *)low)+size;
74   return checkmemory(low, high);
75 #endif
76   
77   return true;
78 }
79
80 bool typemap::istype(void *ptr, structure *s) {
81
82 #ifdef CHECKTYPE
83   bool b=checktype(false,ptr,s);
84   if (!b) {
85     printf("Verify failure\n");
86     bool testb=checktype(false,ptr,s);
87   }
88   return b;
89 #endif
90
91   return assertvalidmemory(ptr, s);
92 }
93
94 void typemap::allocate(void *ptr, int size) {
95   void *low=ptr;
96   void *high=((char *)ptr)+size;
97   int val=rbinsert(low,high,NULL,alloctree);
98   if (val==0)
99     printf("Error\n");
100 }
101
102 structure * typemap::findoffsetstructure(structure *s, int offset) {
103   int count=0;
104   for(int i=0;i<s->getnumfields();i++) {
105     int mult=1;
106     ttype *ttype=s->getfield(i)->gettype();
107     if (ttype->getsize()!=NULL) {
108       Element * number=evaluateexpr(globalmodel,ttype->getsize(),globalmodel->gethashtable(),true,false);
109       mult=number->intvalue();
110       delete(number);
111     }
112     int increment=ttype->basesize(globalmodel->getbitreader(),globalmodel,globalmodel->gethashtable());
113
114     int delt=offset-count;
115     if (delt<mult*increment) {
116       if (delt%increment==0) {
117         return globalmodel->getstructure(ttype->getname());
118       } else
119         return NULL;
120     }
121
122     count+=mult*increment;
123   }
124   
125   return NULL;
126 }
127
128 void typemap::deallocate(void *ptr) {
129   if (rbdelete(ptr,alloctree)==NULL)
130     printf("Freeing unallocated memory\n");
131 }
132
133 bool typemap::checkmemory(void* low, void* high) {
134   struct pair allocp=rbfind(low,high,alloctree);
135
136   if (allocp.low == NULL) {
137       return false; 
138   } else if ((allocp.low > low) || (allocp.high < high)) { /* make sure this block is used */
139       return false;
140   } else {
141       return true;
142   }
143 }
144
145
146 bool typemap::checktype(bool doaction,void *ptr, structure *structure) {
147   int size=structure->getsize(globalmodel->getbitreader(),globalmodel,globalmodel->gethashtable());
148   void *low=ptr;
149   void *high=((char *)low)+size;
150   struct pair allocp=rbfind(low,high,alloctree);
151   if (allocp.low==NULL)
152     return false;
153   if (allocp.low>low||allocp.high<high) /* make sure this block is used */
154     return false;
155   struct pair typep=rbfind(low,high,typetree);
156   structuremap *smap=(structuremap *)rblookup(low,high,typetree);
157   
158   if (typep.low==NULL) {
159     if(!doaction)
160       return true;
161     structuremap *sm=new structuremap(structure);
162     int flag=rbinsert(low, high, sm, typetree);
163     if (flag==0) {
164       printf("Error in asserttype\n");
165       return false;
166     } else
167       return true;
168   }
169
170   return checktype(doaction, low,high, structure, typetree);
171 }
172
173 bool typemap::checktype(bool doaction, void *low, void *high,structure *structre, struct rbtree *ttree) {
174   struct pair typep=rbfind(low,high,ttree);
175   structuremap *smap=(structuremap *)rblookup(low,high,ttree);
176   
177   if (typep.low==low&&typep.high==high) {
178     /* Recast */
179     if (globalmodel->subtypeof(structre,smap->str)) {
180       /* narrowing cast */
181       if (!doaction)
182         return true;
183       smap->str=structre;
184       return true;
185     } else if (globalmodel->subtypeof(smap->str,structre)) {
186       /* widening cast */
187       return true;
188     } else
189       return false; /* incompatible types */
190   } else if (typep.low<=low&&typep.high>=high) {
191     /* See if it matches up with structure inside typep */
192     if (rbsearch(low,high,smap->typetree)) {
193       /* recurse */
194       return checktype(doaction,low,high, structre, smap->typetree);
195     } else {
196       /* check to see if data lines up correctly */
197       int offset=((char *)low)-((char *)typep.low);
198       structure * st=findoffsetstructure(smap->str,offset);
199       if (st==NULL)
200         return false;
201       if (globalmodel->subtypeof(structre,st)) {
202         if (!doaction)
203           return true;
204         structuremap *newsm=new structuremap(structre);
205         int flag=rbinsert(low, high, newsm, smap->typetree);
206         return (flag==1);
207       } else if (globalmodel->subtypeof(st,structre)) {
208         if (!doaction)
209           return true;
210         structuremap *newsm=new structuremap(st);
211         int flag=rbinsert(low, high, newsm, smap->typetree);
212         return (flag==1);
213       } else
214         return false;
215     }
216   } else
217     return false;
218 }