starting data converter tool
[ia32rtools.git] / tools / cvt_data.c
CommitLineData
054f95b2 1#define _GNU_SOURCE
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5
6#include "my_assert.h"
7#include "my_str.h"
8
9#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
10#define IS(w, y) !strcmp(w, y)
11#define IS_START(w, y) !strncmp(w, y, strlen(y))
12
13#include "protoparse.h"
14
15static const char *asmfn;
16static int asmln;
17static FILE *g_fhdr;
18
19enum dx_type {
20 DXT_UNSPEC,
21 DXT_BYTE,
22 DXT_WORD,
23 DXT_DWORD,
24 DXT_QUAD,
25 DXT_TEN,
26};
27
28#define aerr(fmt, ...) do { \
29 printf("%s:%d: error: " fmt, asmfn, asmln, ##__VA_ARGS__); \
30 fcloseall(); \
31 exit(1); \
32} while (0)
33
34#include "masm_tools.h"
35
36static char *next_word_s(char *w, size_t wsize, char *s)
37{
38 int quote = 0;
39 size_t i;
40
41 s = sskip(s);
42
43 for (i = 0; i < wsize - 1; i++) {
44 if (s[i] == '\'')
45 quote ^= 1;
46 if (s[i] == 0 || (!quote && (my_isblank(s[i]) || s[i] == ',')))
47 break;
48 w[i] = s[i];
49 }
50 w[i] = 0;
51
52 if (s[i] != 0 && !my_isblank(s[i]) && s[i] != ',')
53 printf("warning: '%s' truncated\n", w);
54
55 return s + i;
56}
57
58static void next_section(FILE *fasm, char *name)
59{
60 char words[2][256];
61 char line[256];
62 int wordc;
63 char *p;
64
65 name[0] = 0;
66
67 while (fgets(line, sizeof(line), fasm))
68 {
69 wordc = 0;
70 asmln++;
71
72 p = sskip(line);
73 if (*p == 0)
74 continue;
75
76 if (*p == ';') {
77 while (strlen(line) == sizeof(line) - 1) {
78 // one of those long comment lines..
79 if (!fgets(line, sizeof(line), fasm))
80 break;
81 }
82 continue;
83 }
84
85 for (wordc = 0; wordc < ARRAY_SIZE(words); wordc++) {
86 p = sskip(next_word(words[wordc], sizeof(words[0]), p));
87 if (*p == 0 || *p == ';') {
88 wordc++;
89 break;
90 }
91 }
92
93 if (wordc < 2)
94 continue;
95
96 if (!IS(words[1], "segment"))
97 continue;
98
99 strcpy(name, words[0]);
100 break;
101 }
102}
103
104static enum dx_type parse_dx_directive(const char *name)
105{
106 if (IS(name, "dd"))
107 return DXT_DWORD;
108 if (IS(name, "dw"))
109 return DXT_WORD;
110 if (IS(name, "db"))
111 return DXT_BYTE;
112 if (IS(name, "dq"))
113 return DXT_QUAD;
114 if (IS(name, "dt"))
115 return DXT_TEN;
116
117 return DXT_UNSPEC;
118}
119
120static const char *type_name(enum dx_type type)
121{
122 switch (type) {
123 case DXT_BYTE:
124 return ".byte";
125 case DXT_WORD:
126 return ".word";
127 case DXT_DWORD:
128 return ".long";
129 case DXT_QUAD:
130 return ".quad";
131 case DXT_TEN:
132 return ".tfloat";
133 case DXT_UNSPEC:
134 break;
135 }
136 return "<bad>";
137}
138
139static int type_size(enum dx_type type)
140{
141 switch (type) {
142 case DXT_BYTE:
143 return 1;
144 case DXT_WORD:
145 return 2;
146 case DXT_DWORD:
147 return 4;
148 case DXT_QUAD:
149 return 8;
150 case DXT_TEN:
151 return 10;
152 case DXT_UNSPEC:
153 break;
154 }
155 return -1;
156}
157
158static char *escape_string(char *s)
159{
160 char buf[256];
161 char *t = buf;
162
163 for (; *s != 0; s++) {
164 if (*s == '"') {
165 strcpy(t, "\\22");
166 t += strlen(t);
167 continue;
168 }
169 if (*s == '\\') {
170 strcpy(t, "\\\\");
171 t += strlen(t);
172 continue;
173 }
174 *t++ = *s;
175 }
176 *t = *s;
177 return strcpy(s, buf);
178}
179
180int main(int argc, char *argv[])
181{
182 FILE *fout, *fasm;
183 char words[20][256];
184 //int sep_after[20];
185 char word[256];
186 char line[256];
187 char comment[256];
188 unsigned long val;
189 unsigned long cnt;
190 const char *sym;
191 enum dx_type type;
192 int is_label;
193 int wordc;
194 int first;
195 int arg_out;
196 int arg = 1;
197 int len;
198 int w;
199 char *p;
200 char *p2;
201
202 if (argc != 4) {
203 printf("usage:\n%s <.s> <.asm> <hdrf>\n",
204 argv[0]);
205 return 1;
206 }
207
208 arg_out = arg++;
209
210 asmfn = argv[arg++];
211 fasm = fopen(asmfn, "r");
212 my_assert_not(fasm, NULL);
213
214 hdrfn = argv[arg++];
215 g_fhdr = fopen(hdrfn, "r");
216 my_assert_not(g_fhdr, NULL);
217
218 fout = fopen(argv[arg_out], "w");
219 my_assert_not(fout, NULL);
220
221 comment[0] = 0;
222
223 while (!feof(fasm)) {
224 next_section(fasm, line);
225 if (IS(line + 1, "text"))
226 continue;
227
228 if (IS(line + 1, "rdata"))
229 fprintf(fout, "\n.section .rodata\n");
230 else if (IS(line + 1, "data"))
231 fprintf(fout, "\n.data\n");
232 else
233 aerr("unhandled section: '%s'\n", line);
234
235 fprintf(fout, ".align 4\n");
236
237 while (fgets(line, sizeof(line), fasm))
238 {
239 sym = NULL;
240 asmln++;
241
242 p = sskip(line);
243 if (*p == 0 || *p == ';')
244 continue;
245
246 for (wordc = 0; wordc < ARRAY_SIZE(words); wordc++) {
247 //sep_after[wordc] = 0;
248 p = sskip(next_word_s(words[wordc], sizeof(words[0]), p));
249 if (*p == 0 || *p == ';') {
250 wordc++;
251 break;
252 }
253 if (*p == ',') {
254 //sep_after[wordc] = 1;
255 p = sskip(p + 1);
256 }
257 }
258
259 if (wordc == 2 && IS(words[1], "ends"))
260 break;
261 if (wordc < 2)
262 aerr("unhandled: '%s'\n", words[0]);
263
264 // don't cares
265 if (IS(words[0], "assume"))
266 continue;
267
268 if (IS(words[0], "align")) {
269 val = parse_number(words[1]);
270 fprintf(fout, "\t\t .align %ld", val);
271 goto fin;
272 }
273
274 w = 1;
275 type = parse_dx_directive(words[0]);
276 if (type == DXT_UNSPEC) {
277 type = parse_dx_directive(words[1]);
278 sym = words[0];
279 w = 2;
280 }
281 if (type == DXT_UNSPEC)
282 aerr("unhandled decl: '%s %s'\n", words[0], words[1]);
283
284 if (sym != NULL) {
285 len = strlen(sym);
286 fprintf(fout, "_%s:", sym);
287
288 len += 2;
289 if (len < 8)
290 fprintf(fout, "\t");
291 if (len < 16)
292 fprintf(fout, "\t");
293 if (len <= 16)
294 fprintf(fout, " ");
295 else
296 fprintf(fout, " ");
297 }
298 else {
299 fprintf(fout, "\t\t ");
300 }
301
302 if (type == DXT_BYTE && words[w][0] == '\'') {
303 // string; use asciz for most common case
304 if (w == wordc - 2 && IS(words[w + 1], "0")) {
305 fprintf(fout, ".asciz \"");
306 wordc--;
307 }
308 else
309 fprintf(fout, ".ascii \"");
310
311 for (; w < wordc; w++) {
312 if (words[w][0] == '\'') {
313 p = words[w] + 1;
314 p2 = strchr(p, '\'');
315 if (p2 == NULL)
316 aerr("unterminated string? '%s'\n", p);
317 memcpy(word, p, p2 - p);
318 word[p2 - p] = 0;
319 fprintf(fout, "%s", escape_string(word));
320 }
321 else {
322 val = parse_number(words[w]);
323 if (val & ~0xff)
324 aerr("bad string trailing byte?\n");
325 fprintf(fout, "\\x%02lx", val);
326 }
327 }
328 fprintf(fout, "\"");
329 goto fin;
330 }
331
332 if (w == wordc - 2) {
333 if (IS_START(words[w + 1], "dup(")) {
334 cnt = parse_number(words[w]);
335 p = words[w + 1] + 4;
336 p2 = strchr(p, ')');
337 if (p2 == NULL)
338 aerr("bad dup?\n");
339 memmove(word, p, p2 - p);
340 word[p2 - p] = 0;
341 val = parse_number(word);
342
343 fprintf(fout, ".fill 0x%02lx,%d,0x%02lx",
344 cnt, type_size(type), val);
345 goto fin;
346 }
347 }
348
349 if (type == DXT_DWORD && words[w][0] == '\''
350 && words[w][5] == '\'' && strlen(words[w]) == 6)
351 {
352 if (w != wordc - 1)
353 aerr("TODO\n");
354
355 p = words[w];
356 val = (p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4];
357 fprintf(fout, ".long 0x%lx", val);
358 snprintf(comment, sizeof(comment), "%s", words[w]);
359 goto fin;
360 }
361
362 if ((type == DXT_QUAD || type == DXT_TEN)
363 && strchr(words[w], '.'))
364 {
365 if (w != wordc - 1)
366 aerr("TODO\n");
367
368 fprintf(fout, type == DXT_TEN ? ".tfloat " : ".double ");
369 fprintf(fout, "%s", words[w]);
370 goto fin;
371 }
372
373 first = 1;
374 fprintf(fout, "%s ", type_name(type));
375 for (; w < wordc; w++)
376 {
377 if (!first)
378 fprintf(fout, ", ");
379
380 is_label = 0;
381 if (w >= wordc - 2 && IS(words[w], "offset")) {
382 is_label = 1;
383 w++;
384 }
385 else if (type == DXT_DWORD
386 && !('0' <= words[w][0] && words[w][0] <= '9'))
387 {
388 // assume label
389 is_label = 1;
390 }
391
392 if (is_label) {
393 p = words[w];
394 if (IS_START(p, "loc_") || strchr(p, '?') || strchr(p, '@'))
395 {
396 fprintf(fout, "0");
397 snprintf(comment, sizeof(comment), "%s", words[w + 1]);
398 goto fin;
399 }
400 fprintf(fout, "_%s", p);
401 }
402 else {
403 val = parse_number(words[w]);
404 if (val < 10)
405 fprintf(fout, "%ld", val);
406 else
407 fprintf(fout, "0x%lx", val);
408 }
409
410 first = 0;
411 }
412
413fin:
414 if (comment[0] != 0) {
415 fprintf(fout, "\t\t# %s", comment);
416 comment[0] = 0;
417 }
418 fprintf(fout, "\n");
419 (void)proto_parse;
420 }
421 }
422
423 fclose(fout);
424 fclose(fasm);
425 fclose(g_fhdr);
426
427 return 0;
428}
429
430// vim:ts=2:shiftwidth=2:expandtab