1 // Derived from Inferno utils/8c/list.c
2 // http://code.google.com/p/inferno-os/source/browse/utils/8c/list.c
3 //
4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
6 // Portions Copyright © 1997-1999 Vita Nuova Limited
7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
8 // Portions Copyright © 2004,2006 Bruce Ellis
9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
11 // Portions Copyright © 2009 The Go Authors. All rights reserved.
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a copy
14 // of this software and associated documentation files (the "Software"), to deal
15 // in the Software without restriction, including without limitation the rights
16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 // copies of the Software, and to permit persons to whom the Software is
18 // furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included in
21 // all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 // THE SOFTWARE.
30
31 #include "gg.h"
32
33 static int sconsize;
34 void
35 listinit(void)
36 {
37
38 fmtinstall('A', Aconv); // as
39 fmtinstall('P', Pconv); // Prog*
40 fmtinstall('D', Dconv); // Addr*
41 fmtinstall('R', Rconv); // reg
42 fmtinstall('Y', Yconv); // sconst
43 }
44
45 int
46 Pconv(Fmt *fp)
47 {
48 char str[STRINGSZ];
49 Prog *p;
50 char scale[40];
51
52 p = va_arg(fp->args, Prog*);
53 sconsize = 8;
54 scale[0] = '\0';
55 if(p->from.scale != 0 && (p->as == AGLOBL || p->as == ATEXT))
56 snprint(scale, sizeof scale, "%d,", p->from.scale);
57 switch(p->as) {
58 default:
59 snprint(str, sizeof(str), "%.4d (%L) %-7A %D,%s%D",
60 p->loc, p->lineno, p->as, &p->from, scale, &p->to);
61 break;
62
63 case ADATA:
64 sconsize = p->from.scale;
65 snprint(str, sizeof(str), "%.4d (%L) %-7A %D/%d,%D",
66 p->loc, p->lineno, p->as, &p->from, sconsize, &p->to);
67 break;
68
69 case ATEXT:
70 snprint(str, sizeof(str), "%.4d (%L) %-7A %D,%s%lD",
71 p->loc, p->lineno, p->as, &p->from, scale, &p->to);
72 break;
73 }
74 return fmtstrcpy(fp, str);
75 }
76
77 int
78 Dconv(Fmt *fp)
79 {
80 char str[STRINGSZ], s[STRINGSZ];
81 Addr *a;
82 int i;
83 uint32 d1, d2;
84
85 a = va_arg(fp->args, Addr*);
86 i = a->type;
87 if(i >= D_INDIR) {
88 if(a->offset)
89 snprint(str, sizeof(str), "%d(%R)", a->offset, i-D_INDIR);
90 else
91 snprint(str, sizeof(str), "(%R)", i-D_INDIR);
92 goto brk;
93 }
94 switch(i) {
95
96 default:
97 if(a->offset)
98 snprint(str, sizeof(str), "$%d,%R", a->offset, i);
99 else
100 snprint(str, sizeof(str), "%R", i);
101 break;
102
103 case D_NONE:
104 str[0] = 0;
105 break;
106
107 case D_BRANCH:
108 snprint(str, sizeof(str), "%d", a->branch->loc);
109 break;
110
111 case D_EXTERN:
112 snprint(str, sizeof(str), "%S+%d(SB)", a->sym, a->offset);
113 break;
114
115 case D_STATIC:
116 snprint(str, sizeof(str), "%S<>+%d(SB)", a->sym, a->offset);
117 break;
118
119 case D_AUTO:
120 snprint(str, sizeof(str), "%S+%d(SP)", a->sym, a->offset);
121 break;
122
123 case D_PARAM:
124 snprint(str, sizeof(str), "%S+%d(FP)", a->sym, a->offset);
125 break;
126
127 case D_CONST:
128 if(fp->flags & FmtLong) {
129 d1 = a->offset;
130 d2 = a->offset2;
131 snprint(str, sizeof(str), "$%ud-%ud", (ulong)d1, (ulong)d2);
132 break;
133 }
134 snprint(str, sizeof(str), "$%d", a->offset);
135 break;
136
137 case D_FCONST:
138 snprint(str, sizeof(str), "$(%.17e)", a->dval);
139 break;
140
141 case D_SCONST:
142 snprint(str, sizeof(str), "$\"%Y\"", a->sval);
143 break;
144
145 case D_ADDR:
146 a->type = a->index;
147 a->index = D_NONE;
148 snprint(str, sizeof(str), "$%D", a);
149 a->index = a->type;
150 a->type = D_ADDR;
151 goto conv;
152 }
153 brk:
154 if(a->index != D_NONE) {
155 snprint(s, sizeof(s), "(%R*%d)", (int)a->index, (int)a->scale);
156 strcat(str, s);
157 }
158 conv:
159 return fmtstrcpy(fp, str);
160 }
161
162 static char* regstr[] =
163 {
164 "AL", /* [D_AL] */
165 "CL",
166 "DL",
167 "BL",
168
169 "AH", /* [D_AH] */
170 "CH",
171 "DH",
172 "BH",
173
174 "AX", /* [D_AX] */
175 "CX",
176 "DX",
177 "BX",
178 "SP",
179 "BP",
180 "SI",
181 "DI",
182
183 "F0", /* [D_F0] */
184 "F1",
185 "F2",
186 "F3",
187 "F4",
188 "F5",
189 "F6",
190 "F7",
191
192 "CS", /* [D_CS] */
193 "SS",
194 "DS",
195 "ES",
196 "FS",
197 "GS",
198
199 "GDTR", /* [D_GDTR] */
200 "IDTR", /* [D_IDTR] */
201 "LDTR", /* [D_LDTR] */
202 "MSW", /* [D_MSW] */
203 "TASK", /* [D_TASK] */
204
205 "CR0", /* [D_CR] */
206 "CR1",
207 "CR2",
208 "CR3",
209 "CR4",
210 "CR5",
211 "CR6",
212 "CR7",
213
214 "DR0", /* [D_DR] */
215 "DR1",
216 "DR2",
217 "DR3",
218 "DR4",
219 "DR5",
220 "DR6",
221 "DR7",
222
223 "TR0", /* [D_TR] */
224 "TR1",
225 "TR2",
226 "TR3",
227 "TR4",
228 "TR5",
229 "TR6",
230 "TR7",
231
232 "NONE", /* [D_NONE] */
233 };
234
235 int
236 Rconv(Fmt *fp)
237 {
238 char str[STRINGSZ];
239 int r;
240
241 r = va_arg(fp->args, int);
242 if(r < 0 || r >= nelem(regstr) || regstr[r] == nil) {
243 snprint(str, sizeof(str), "BAD_R(%d)", r);
244 return fmtstrcpy(fp, str);
245 }
246 return fmtstrcpy(fp, regstr[r]);
247 }
248
249 int
250 Aconv(Fmt *fp)
251 {
252 int i;
253
254 i = va_arg(fp->args, int);
255 return fmtstrcpy(fp, anames[i]);
256 }
257
258
259 int
260 Yconv(Fmt *fp)
261 {
262 int i, c;
263 char str[STRINGSZ], *p, *a;
264
265 a = va_arg(fp->args, char*);
266 p = str;
267 for(i=0; i<sconsize; i++) {
268 c = a[i] & 0xff;
269 if((c >= 'a' && c <= 'z') ||
270 (c >= 'A' && c <= 'Z') ||
271 (c >= '0' && c <= '9')) {
272 *p++ = c;
273 continue;
274 }
275 *p++ = '\\';
276 switch(c) {
277 default:
278 if(c < 040 || c >= 0177)
279 break; /* not portable */
280 p[-1] = c;
281 continue;
282 case 0:
283 *p++ = 'z';
284 continue;
285 case '\\':
286 case '"':
287 *p++ = c;
288 continue;
289 case '\n':
290 *p++ = 'n';
291 continue;
292 case '\t':
293 *p++ = 't';
294 continue;
295 }
296 *p++ = (c>>6) + '0';
297 *p++ = ((c>>3) & 7) + '0';
298 *p++ = (c & 7) + '0';
299 }
300 *p = 0;
301 return fmtstrcpy(fp, str);
302 }