1 #include "cc.h"
2
3 static char *kwd[] =
4 {
5 "$adt", "$aggr", "$append", "$complex", "$defn",
6 "$delete", "$do", "$else", "$eval", "$head", "$if",
7 "$local", "$loop", "$return", "$tail", "$then",
8 "$union", "$whatis", "$while",
9 };
10 static char picklestr[] = "\tpickle(s, un, ";
11
12 static char*
pmap(char * s)13 pmap(char *s)
14 {
15 int i, bot, top, new;
16
17 bot = 0;
18 top = bot + nelem(kwd) - 1;
19 while(bot <= top){
20 new = bot + (top - bot)/2;
21 i = strcmp(kwd[new]+1, s);
22 if(i == 0)
23 return kwd[new];
24
25 if(i < 0)
26 bot = new + 1;
27 else
28 top = new - 1;
29 }
30 return s;
31 }
32
33 Sym*
picklesue(Type * t)34 picklesue(Type *t)
35 {
36 int h;
37 Sym *s;
38
39 if(t != T)
40 for(h=0; h<nelem(hash); h++)
41 for(s = hash[h]; s != S; s = s->link)
42 if(s->suetag && s->suetag->link == t)
43 return s;
44 return 0;
45 }
46
47 Sym*
picklefun(Type * t)48 picklefun(Type *t)
49 {
50 int h;
51 Sym *s;
52
53 for(h=0; h<nelem(hash); h++)
54 for(s = hash[h]; s != S; s = s->link)
55 if(s->type == t)
56 return s;
57 return 0;
58 }
59
60 char picklechar[NTYPE];
61 Init picklecinit[] =
62 {
63 TCHAR, 'C', 0,
64 TUCHAR, 'b', 0,
65 TSHORT, 'd', 0,
66 TUSHORT, 'u', 0,
67 TLONG, 'D', 0,
68 TULONG, 'U', 0,
69 TVLONG, 'V', 0,
70 TUVLONG, 'W', 0,
71 TFLOAT, 'f', 0,
72 TDOUBLE, 'F', 0,
73 TARRAY, 'a', 0,
74 TIND, 'X', 0,
75 -1, 0, 0,
76 };
77
78 static void
pickleinit(void)79 pickleinit(void)
80 {
81 Init *p;
82
83 for(p=picklecinit; p->code >= 0; p++)
84 picklechar[p->code] = p->value;
85
86 picklechar[TINT] = picklechar[TLONG];
87 picklechar[TUINT] = picklechar[TULONG];
88 if(types[TINT]->width != types[TLONG]->width) {
89 picklechar[TINT] = picklechar[TSHORT];
90 picklechar[TUINT] = picklechar[TUSHORT];
91 if(types[TINT]->width != types[TSHORT]->width)
92 warn(Z, "picklemember int not long or short");
93 }
94
95 }
96
97 void
picklemember(Type * t,long off)98 picklemember(Type *t, long off)
99 {
100 Sym *s, *s1;
101 static int picklecharinit = 0;
102
103 if(picklecharinit == 0) {
104 pickleinit();
105 picklecharinit = 1;
106 }
107 s = t->sym;
108 switch(t->etype) {
109 default:
110 Bprint(&outbuf, " T%d\n", t->etype);
111 break;
112
113 case TIND:
114 if(s == S)
115 Bprint(&outbuf,
116 "%s\"p\", (char*)addr+%ld+_i*%ld);\n",
117 picklestr, t->offset+off, t->width);
118 else
119 Bprint(&outbuf,
120 "%s\"p\", &addr->%s);\n",
121 picklestr, pmap(s->name));
122 break;
123
124 case TINT:
125 case TUINT:
126 case TCHAR:
127 case TUCHAR:
128 case TSHORT:
129 case TUSHORT:
130 case TLONG:
131 case TULONG:
132 case TVLONG:
133 case TUVLONG:
134 case TFLOAT:
135 case TDOUBLE:
136 if(s == S)
137 Bprint(&outbuf, "%s\"%c\", (char*)addr+%ld+_i*%ld);\n",
138 picklestr, picklechar[t->etype], t->offset+off, t->width);
139 else
140 Bprint(&outbuf, "%s\"%c\", &addr->%s);\n",
141 picklestr, picklechar[t->etype], pmap(s->name));
142 break;
143 case TARRAY:
144 Bprint(&outbuf, "\tfor(_i = 0; _i < %ld; _i++) {\n\t",
145 t->width/t->link->width);
146 picklemember(t->link, t->offset+off);
147 Bprint(&outbuf, "\t}\n\t_i = 0;\n\tUSED(_i);\n");
148 break;
149
150 case TSTRUCT:
151 case TUNION:
152 s1 = picklesue(t->link);
153 if(s1 == S)
154 break;
155 if(s == S) {
156 Bprint(&outbuf, "\tpickle_%s(s, un, (%s*)((char*)addr+%ld+_i*%ld));\n",
157 pmap(s1->name), pmap(s1->name), t->offset+off, t->width);
158 } else {
159 Bprint(&outbuf, "\tpickle_%s(s, un, &addr->%s);\n",
160 pmap(s1->name), pmap(s->name));
161 }
162 break;
163 }
164 }
165
166 void
pickletype(Type * t)167 pickletype(Type *t)
168 {
169 Sym *s;
170 Type *l;
171 Io *i;
172 int n;
173 char *an;
174
175 if(!debug['P'])
176 return;
177 if(debug['P'] > 1) {
178 n = 0;
179 for(i=iostack; i; i=i->link)
180 n++;
181 if(n > 1)
182 return;
183 }
184 s = picklesue(t->link);
185 if(s == S)
186 return;
187 switch(t->etype) {
188 default:
189 Bprint(&outbuf, "T%d\n", t->etype);
190 return;
191
192 case TUNION:
193 case TSTRUCT:
194 if(debug['s'])
195 goto asmstr;
196 an = pmap(s->name);
197
198 Bprint(&outbuf, "void\npickle_%s(void *s, int un, %s *addr)\n{\n\tint _i = 0;\n\n\tUSED(_i);\n", an, an);
199 for(l = t->link; l != T; l = l->down)
200 picklemember(l, 0);
201 Bprint(&outbuf, "}\n\n");
202 break;
203 asmstr:
204 if(s == S)
205 break;
206 for(l = t->link; l != T; l = l->down)
207 if(l->sym != S)
208 Bprint(&outbuf, "#define\t%s.%s\t%ld\n",
209 s->name,
210 l->sym->name,
211 l->offset);
212 break;
213 }
214 }
215
216 void
picklevar(Sym * s)217 picklevar(Sym *s)
218 {
219 int n;
220 Io *i;
221 Type *t;
222 Sym *s1, *s2;
223
224 if(!debug['P'] || debug['s'])
225 return;
226 if(debug['P'] > 1) {
227 n = 0;
228 for(i=iostack; i; i=i->link)
229 n++;
230 if(n > 1)
231 return;
232 }
233 t = s->type;
234 while(t && t->etype == TIND)
235 t = t->link;
236 if(t == T)
237 return;
238 if(t->etype == TENUM) {
239 Bprint(&outbuf, "%s = ", pmap(s->name));
240 if(!typefd[t->etype])
241 Bprint(&outbuf, "%lld;\n", s->vconst);
242 else
243 Bprint(&outbuf, "%f\n;", s->fconst);
244 return;
245 }
246 if(!typesu[t->etype])
247 return;
248 s1 = picklesue(t->link);
249 if(s1 == S)
250 return;
251 switch(s->class) {
252 case CAUTO:
253 case CPARAM:
254 s2 = picklefun(thisfn);
255 if(s2)
256 Bprint(&outbuf, "complex %s %s:%s;\n",
257 pmap(s1->name), pmap(s2->name), pmap(s->name));
258 break;
259
260 case CSTATIC:
261 case CEXTERN:
262 case CGLOBL:
263 case CLOCAL:
264 Bprint(&outbuf, "complex %s %s;\n",
265 pmap(s1->name), pmap(s->name));
266 break;
267 }
268 }
269