cvt_data: zero out import tables
[ia32rtools.git] / tools / cvt_data.c
CommitLineData
7637b6cc 1/*
2 * ia32rtools
9bbecbfb 3 * (C) notaz, 2013-2015
7637b6cc 4 *
5 * This work is licensed under the terms of 3-clause BSD license.
6 * See COPYING file in the top-level directory.
7 */
8
054f95b2 9#define _GNU_SOURCE
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
e27467d0 13#include <stdint.h>
14#include <inttypes.h>
054f95b2 15
16#include "my_assert.h"
17#include "my_str.h"
9ea60b8d 18#include "common.h"
054f95b2 19
054f95b2 20#include "protoparse.h"
21
22static const char *asmfn;
23static int asmln;
054f95b2 24
b545ba7c 25static const struct parsed_proto *g_func_sym_pp;
26static char g_comment[256];
27static int g_warn_cnt;
77f3a833 28static int g_cconv_novalidate;
f0be238a 29static int g_arm_mode;
b545ba7c 30
36595fd2 31// note: must be in ascending order
054f95b2 32enum dx_type {
33 DXT_UNSPEC,
34 DXT_BYTE,
35 DXT_WORD,
36 DXT_DWORD,
37 DXT_QUAD,
38 DXT_TEN,
39};
40
36595fd2 41#define anote(fmt, ...) \
42 printf("%s:%d: note: " fmt, asmfn, asmln, ##__VA_ARGS__)
b545ba7c 43#define awarn(fmt, ...) do { \
44 printf("%s:%d: warning: " fmt, asmfn, asmln, ##__VA_ARGS__); \
45 if (++g_warn_cnt == 10) { \
46 fcloseall(); \
47 exit(1); \
48 } \
49} while (0)
054f95b2 50#define aerr(fmt, ...) do { \
51 printf("%s:%d: error: " fmt, asmfn, asmln, ##__VA_ARGS__); \
52 fcloseall(); \
53 exit(1); \
54} while (0)
55
56#include "masm_tools.h"
57
58static char *next_word_s(char *w, size_t wsize, char *s)
59{
60 int quote = 0;
61 size_t i;
62
63 s = sskip(s);
64
65 for (i = 0; i < wsize - 1; i++) {
66 if (s[i] == '\'')
67 quote ^= 1;
68 if (s[i] == 0 || (!quote && (my_isblank(s[i]) || s[i] == ',')))
69 break;
70 w[i] = s[i];
71 }
72 w[i] = 0;
73
74 if (s[i] != 0 && !my_isblank(s[i]) && s[i] != ',')
75 printf("warning: '%s' truncated\n", w);
76
77 return s + i;
78}
79
80static void next_section(FILE *fasm, char *name)
81{
82 char words[2][256];
83 char line[256];
84 int wordc;
85 char *p;
86
87 name[0] = 0;
88
9ea60b8d 89 while (my_fgets(line, sizeof(line), fasm))
054f95b2 90 {
91 wordc = 0;
92 asmln++;
93
94 p = sskip(line);
95 if (*p == 0)
96 continue;
97
9ea60b8d 98 if (*p == ';')
054f95b2 99 continue;
054f95b2 100
101 for (wordc = 0; wordc < ARRAY_SIZE(words); wordc++) {
102 p = sskip(next_word(words[wordc], sizeof(words[0]), p));
103 if (*p == 0 || *p == ';') {
104 wordc++;
105 break;
106 }
107 }
108
109 if (wordc < 2)
110 continue;
111
112 if (!IS(words[1], "segment"))
113 continue;
114
115 strcpy(name, words[0]);
116 break;
117 }
118}
119
120static enum dx_type parse_dx_directive(const char *name)
121{
122 if (IS(name, "dd"))
123 return DXT_DWORD;
124 if (IS(name, "dw"))
125 return DXT_WORD;
126 if (IS(name, "db"))
127 return DXT_BYTE;
128 if (IS(name, "dq"))
129 return DXT_QUAD;
130 if (IS(name, "dt"))
131 return DXT_TEN;
132
133 return DXT_UNSPEC;
134}
135
136static const char *type_name(enum dx_type type)
137{
138 switch (type) {
139 case DXT_BYTE:
140 return ".byte";
141 case DXT_WORD:
b0d802b2 142 return ".hword";
054f95b2 143 case DXT_DWORD:
144 return ".long";
145 case DXT_QUAD:
146 return ".quad";
147 case DXT_TEN:
148 return ".tfloat";
149 case DXT_UNSPEC:
150 break;
151 }
152 return "<bad>";
153}
154
36595fd2 155static const char *type_name_float(enum dx_type type)
156{
157 switch (type) {
158 case DXT_DWORD:
159 return ".float";
160 case DXT_QUAD:
161 return ".double";
162 case DXT_TEN:
163 return ".tfloat";
164 default:
165 break;
166 }
167 return "<bad_float>";
168}
169
054f95b2 170static int type_size(enum dx_type type)
171{
172 switch (type) {
173 case DXT_BYTE:
174 return 1;
175 case DXT_WORD:
176 return 2;
177 case DXT_DWORD:
178 return 4;
179 case DXT_QUAD:
180 return 8;
181 case DXT_TEN:
182 return 10;
183 case DXT_UNSPEC:
184 break;
185 }
186 return -1;
187}
188
189static char *escape_string(char *s)
190{
191 char buf[256];
192 char *t = buf;
193
194 for (; *s != 0; s++) {
195 if (*s == '"') {
206c0727 196 strcpy(t, "\\\"");
054f95b2 197 t += strlen(t);
198 continue;
199 }
200 if (*s == '\\') {
201 strcpy(t, "\\\\");
202 t += strlen(t);
203 continue;
204 }
205 *t++ = *s;
206 }
206c0727 207 *t++ = *s;
208 if (t - buf > sizeof(buf))
209 aerr("string is too long\n");
054f95b2 210 return strcpy(s, buf);
211}
212
b545ba7c 213static void sprint_pp_short(const struct parsed_proto *pp, char *buf,
214 size_t buf_size)
215{
216 char *p = buf;
217 size_t l;
218 int i;
219
220 if (pp->ret_type.is_ptr)
221 *p++ = 'p';
222 else if (IS(pp->ret_type.name, "void"))
223 *p++ = 'v';
224 else
225 *p++ = 'i';
226 *p++ = '(';
227 l = 2;
228
229 for (i = 0; i < pp->argc; i++) {
230 if (pp->arg[i].reg != NULL)
231 snprintf(buf + l, buf_size - l, "%s%s",
232 i == 0 ? "" : ",", pp->arg[i].reg);
233 else
234 snprintf(buf + l, buf_size - l, "%sa%d",
235 i == 0 ? "" : ",", i + 1);
236 l = strlen(buf);
237 }
238 snprintf(buf + l, buf_size - l, ")");
239}
240
c0050df6 241static const struct parsed_proto *check_var(FILE *fhdr,
9bbecbfb 242 const char *sym, const char *varname, int is_export)
b545ba7c 243{
244 const struct parsed_proto *pp, *pp_sym;
179b79a9 245 char fp_sym[256], fp_var[256], *p;
246 int i;
b545ba7c 247
248 pp = proto_parse(fhdr, varname, 1);
36595fd2 249 if (pp == NULL) {
b545ba7c 250 if (IS_START(varname, "sub_"))
251 awarn("sub_ sym missing proto: '%s'\n", varname);
c0050df6 252 return NULL;
36595fd2 253 }
254
9bbecbfb 255 if (is_export)
256 return NULL;
36595fd2 257 if (!pp->is_func && !pp->is_fptr)
c0050df6 258 return NULL;
b545ba7c 259
b74c31e3 260 pp_print(fp_var, sizeof(fp_var), pp);
b545ba7c 261
36595fd2 262 if (pp->argc_reg == 0)
b545ba7c 263 goto check_sym;
36595fd2 264 if (pp->argc_reg == 1 && pp->argc_stack == 0
265 && IS(pp->arg[0].reg, "ecx"))
266 {
b545ba7c 267 goto check_sym;
36595fd2 268 }
77f3a833 269 if (!g_cconv_novalidate
270 && (pp->argc_reg != 2
271 || !IS(pp->arg[0].reg, "ecx")
272 || !IS(pp->arg[1].reg, "edx")))
36595fd2 273 {
b545ba7c 274 awarn("unhandled reg call: %s\n", fp_var);
36595fd2 275 }
36595fd2 276
b545ba7c 277check_sym:
179b79a9 278 // fptrs must use 32bit args, callsite might have no information and
279 // lack a cast to smaller types, which results in incorrectly masked
280 // args passed (callee may assume masked args, it does on ARM)
281 for (i = 0; i < pp->argc; i++) {
282 if (pp->arg[i].type.is_ptr)
283 continue;
284 p = pp->arg[i].type.name;
285 if (strstr(p, "int8") || strstr(p, "int16")
286 || strstr(p, "char") || strstr(p, "short"))
287 {
288 awarn("reference to %s with arg%d '%s'\n", pp->name, i + 1, p);
289 }
290 }
291
b545ba7c 292 sprint_pp_short(pp, g_comment, sizeof(g_comment));
293
294 if (sym != NULL) {
295 g_func_sym_pp = NULL;
296 pp_sym = proto_parse(fhdr, sym, 1);
297 if (pp_sym == NULL)
c0050df6 298 return pp;
b545ba7c 299 if (!pp_sym->is_fptr)
300 aerr("func ptr data, but label '%s' !is_fptr\n", pp_sym->name);
301 g_func_sym_pp = pp_sym;
36595fd2 302 }
b545ba7c 303 else {
304 pp_sym = g_func_sym_pp;
305 if (pp_sym == NULL)
c0050df6 306 return pp;
b545ba7c 307 }
308
27ebfaed 309 if (pp_cmp_func(pp, pp_sym)) {
7a7487be 310 if (pp_sym->argc_stack == 0 && pp_sym->is_fastcall
311 && pp->argc_stack == 0
312 && (pp->is_fastcall || pp->argc_reg == 0)
313 && pp_sym->argc_reg > pp->argc_reg)
314 ; /* fascall compatible func doesn't use all args -> ok */
315 else {
316 pp_print(fp_sym, sizeof(fp_sym), pp_sym);
317 anote("var: %s\n", fp_var);
318 anote("sym: %s\n", fp_sym);
319 awarn("^ mismatch\n");
320 }
36595fd2 321 }
c0050df6 322
323 return pp;
36595fd2 324}
325
aa1aa2c2 326static void output_decorated_pp(FILE *fout,
327 const struct parsed_proto *pp)
328{
329 if (pp->name[0] != '_')
330 fprintf(fout, pp->is_fastcall ? "@" : "_");
331 fprintf(fout, "%s", pp->name);
332 if (pp->is_stdcall && pp->argc > 0)
333 fprintf(fout, "@%d", pp->argc * 4);
334}
335
f0be238a 336static int align_value(int src_val)
337{
338 if (src_val <= 0) {
339 awarn("bad align: %d\n", src_val);
340 src_val = 1;
341 }
342 if (!g_arm_mode)
343 return src_val;
344
345 return __builtin_ffs(src_val) - 1;
346}
347
36595fd2 348static int cmpstringp(const void *p1, const void *p2)
349{
350 return strcmp(*(char * const *)p1, *(char * const *)p2);
351}
352
c87eb470 353/* XXX: maybe move to external file? */
354static const char *unwanted_syms[] = {
355 "aRuntimeError",
356 "aTlossError",
357 "aSingError",
358 "aDomainError",
359 "aR6029ThisAppli",
360 "aR6028UnableToI",
361 "aR6027NotEnough",
362 "aR6026NotEnough",
363 "aR6025PureVirtu",
364 "aR6024NotEnough",
365 "aR6019UnableToO",
366 "aR6018Unexpecte",
367 "aR6017Unexpecte",
368 "aR6016NotEnough",
369 "aAbnormalProgra",
370 "aR6009NotEnough",
371 "aR6008NotEnough",
372 "aR6002FloatingP",
373 "aMicrosoftVisua",
374 "aRuntimeErrorPr",
375 "aThisApplicatio",
376 "aMicrosoftFindF",
377 "aMicrosoftOffic",
378};
379
380static int is_unwanted_sym(const char *sym)
381{
382 return bsearch(&sym, unwanted_syms, ARRAY_SIZE(unwanted_syms),
383 sizeof(unwanted_syms[0]), cmpstringp) != NULL;
384}
385
054f95b2 386int main(int argc, char *argv[])
387{
afdd4566 388 FILE *fout, *fasm, *fhdr = NULL, *frlist;
b545ba7c 389 const struct parsed_proto *pp;
aa1aa2c2 390 int no_decorations = 0;
9bbecbfb 391 int in_export_table = 0;
b0d1f7aa 392 int rm_labels_lines = 0;
f0be238a 393 char comment_char = '#';
054f95b2 394 char words[20][256];
054f95b2 395 char word[256];
396 char line[256];
c87eb470 397 char last_sym[32];
054f95b2 398 unsigned long val;
399 unsigned long cnt;
e27467d0 400 uint64_t val64;
054f95b2 401 const char *sym;
402 enum dx_type type;
36595fd2 403 char **pub_syms;
404 int pub_sym_cnt = 0;
405 int pub_sym_alloc;
406 char **rlist;
407 int rlist_cnt = 0;
408 int rlist_alloc;
afdd4566 409 int header_mode = 0;
410 int is_ro = 0;
054f95b2 411 int is_label;
36595fd2 412 int is_bss;
054f95b2 413 int wordc;
414 int first;
415 int arg_out;
416 int arg = 1;
417 int len;
36595fd2 418 int w, i;
054f95b2 419 char *p;
420 char *p2;
421
36595fd2 422 if (argc < 4) {
aa1aa2c2 423 // -nd: no symbol decorations
afdd4566 424 printf("usage:\n%s [-nd] [-i] [-a] <.s> <.asm> <hdrf> [rlist]*\n"
425 "%s -hdr <.h> <.asm>\n",
426 argv[0], argv[0]);
054f95b2 427 return 1;
428 }
429
aa1aa2c2 430 for (arg = 1; arg < argc; arg++) {
431 if (IS(argv[arg], "-nd"))
432 no_decorations = 1;
77f3a833 433 else if (IS(argv[arg], "-i"))
434 g_cconv_novalidate = 1;
f0be238a 435 else if (IS(argv[arg], "-a")) {
436 comment_char = '@';
437 g_arm_mode = 1;
438 }
afdd4566 439 else if (IS(argv[arg], "-hdr"))
440 header_mode = 1;
aa1aa2c2 441 else
442 break;
443 }
444
054f95b2 445 arg_out = arg++;
446
447 asmfn = argv[arg++];
448 fasm = fopen(asmfn, "r");
449 my_assert_not(fasm, NULL);
450
afdd4566 451 if (!header_mode) {
452 hdrfn = argv[arg++];
453 fhdr = fopen(hdrfn, "r");
454 my_assert_not(fhdr, NULL);
455 }
054f95b2 456
457 fout = fopen(argv[arg_out], "w");
458 my_assert_not(fout, NULL);
459
36595fd2 460 pub_sym_alloc = 64;
461 pub_syms = malloc(pub_sym_alloc * sizeof(pub_syms[0]));
462 my_assert_not(pub_syms, NULL);
463
464 rlist_alloc = 64;
465 rlist = malloc(rlist_alloc * sizeof(rlist[0]));
466 my_assert_not(rlist, NULL);
467
468 for (; arg < argc; arg++) {
469 frlist = fopen(argv[arg], "r");
470 my_assert_not(frlist, NULL);
471
9ea60b8d 472 while (my_fgets(line, sizeof(line), frlist)) {
36595fd2 473 p = sskip(line);
9bbecbfb 474 if (*p == 0 || *p == ';' || *p == '#')
36595fd2 475 continue;
476
477 p = next_word(words[0], sizeof(words[0]), p);
478 if (words[0][0] == 0)
479 continue;
480
481 if (rlist_cnt >= rlist_alloc) {
482 rlist_alloc = rlist_alloc * 2 + 64;
483 rlist = realloc(rlist, rlist_alloc * sizeof(rlist[0]));
484 my_assert_not(rlist, NULL);
485 }
486 rlist[rlist_cnt++] = strdup(words[0]);
487 }
488
489 fclose(frlist);
490 frlist = NULL;
491 }
492
493 if (rlist_cnt > 0)
494 qsort(rlist, rlist_cnt, sizeof(rlist[0]), cmpstringp);
495
c87eb470 496 qsort(unwanted_syms, ARRAY_SIZE(unwanted_syms),
497 sizeof(unwanted_syms[0]), cmpstringp);
498
499 last_sym[0] = 0;
500
36595fd2 501 while (1) {
054f95b2 502 next_section(fasm, line);
36595fd2 503 if (feof(fasm))
504 break;
054f95b2 505 if (IS(line + 1, "text"))
506 continue;
507
afdd4566 508 if (IS(line + 1, "rdata")) {
509 is_ro = 1;
510 if (!header_mode)
511 fprintf(fout, "\n.section .rodata\n");
512 }
513 else if (IS(line + 1, "data")) {
514 is_ro = 0;
515 if (!header_mode)
516 fprintf(fout, "\n.data\n");
517 }
054f95b2 518 else
519 aerr("unhandled section: '%s'\n", line);
520
afdd4566 521 if (!header_mode)
522 fprintf(fout, ".align %d\n", align_value(4));
054f95b2 523
9ea60b8d 524 while (my_fgets(line, sizeof(line), fasm))
054f95b2 525 {
526 sym = NULL;
527 asmln++;
528
529 p = sskip(line);
b0d802b2 530 if (*p == 0)
531 continue;
532
533 if (*p == ';') {
534 if (IS_START(p, ";org") && sscanf(p + 5, "%Xh", &i) == 1) {
535 // ;org is only seen at section start, so assume . addr 0
536 i &= 0xfff;
afdd4566 537 if (i != 0 && !header_mode)
b0d802b2 538 fprintf(fout, "\t\t .skip 0x%x\n", i);
539 }
9bbecbfb 540 else if (IS_START(p, "; Export Address"))
541 in_export_table = 1;
542 else if (IS_START(p, "; Export"))
543 in_export_table = 0;
054f95b2 544 continue;
b0d802b2 545 }
054f95b2 546
547 for (wordc = 0; wordc < ARRAY_SIZE(words); wordc++) {
054f95b2 548 p = sskip(next_word_s(words[wordc], sizeof(words[0]), p));
549 if (*p == 0 || *p == ';') {
550 wordc++;
551 break;
552 }
553 if (*p == ',') {
054f95b2 554 p = sskip(p + 1);
555 }
556 }
557
b545ba7c 558 if (*p == ';') {
559 p = sskip(p + 1);
560 if (IS_START(p, "sctclrtype"))
561 g_func_sym_pp = NULL;
562 }
563
054f95b2 564 if (wordc == 2 && IS(words[1], "ends"))
565 break;
36595fd2 566 if (wordc <= 2 && IS(words[0], "end"))
567 break;
054f95b2 568 if (wordc < 2)
569 aerr("unhandled: '%s'\n", words[0]);
570
571 // don't cares
572 if (IS(words[0], "assume"))
573 continue;
574
575 if (IS(words[0], "align")) {
afdd4566 576 if (header_mode)
577 continue;
578
e27467d0 579 val = parse_number(words[1], 0);
f0be238a 580 fprintf(fout, "\t\t .align %d", align_value(val));
054f95b2 581 goto fin;
582 }
583
c1fbaecc 584 if (IS(words[0], "public")) {
585 // skip, sym should appear in header anyway
586 continue;
587 }
588
054f95b2 589 w = 1;
590 type = parse_dx_directive(words[0]);
591 if (type == DXT_UNSPEC) {
592 type = parse_dx_directive(words[1]);
593 sym = words[0];
594 w = 2;
595 }
596 if (type == DXT_UNSPEC)
597 aerr("unhandled decl: '%s %s'\n", words[0], words[1]);
598
afdd4566 599 if (sym != NULL)
600 {
601 if (header_mode) {
602 int is_str = 0;
603
604 fprintf(fout, "extern ");
605 if (is_ro)
606 fprintf(fout, "const ");
607
608 switch (type) {
609 case DXT_BYTE:
610 for (i = w; i < wordc; i++)
611 if (words[i][0] == '\'')
612 is_str = 1;
613 if (is_str)
614 fprintf(fout, "char %s[];\n", sym);
615 else
616 fprintf(fout, "uint8_t %s;\n", sym);
617 break;
618
619 case DXT_WORD:
620 fprintf(fout, "uint16_t %s;\n", sym);
621 break;
622
623 case DXT_DWORD:
624 fprintf(fout, "uint32_t %s;\n", sym);
625 break;
626
627 default:
628 fprintf(fout, "_UNKNOWN %s;\n", sym);
629 break;
630 }
631
632 continue;
633 }
634
c87eb470 635 snprintf(last_sym, sizeof(last_sym), "%s", sym);
b0d1f7aa 636 if (IS_START(sym, "__IMPORT_DESCRIPTOR_"))
637 rm_labels_lines = 5;
36595fd2 638
b545ba7c 639 pp = proto_parse(fhdr, sym, 1);
c87eb470 640 if (pp != NULL) {
b545ba7c 641 g_func_sym_pp = NULL;
642
c87eb470 643 // public/global name
644 if (pub_sym_cnt >= pub_sym_alloc) {
645 pub_sym_alloc *= 2;
646 pub_syms = realloc(pub_syms, pub_sym_alloc * sizeof(pub_syms[0]));
647 my_assert_not(pub_syms, NULL);
648 }
649 pub_syms[pub_sym_cnt++] = strdup(sym);
650 }
651
054f95b2 652 len = strlen(sym);
aa1aa2c2 653 fprintf(fout, "%s%s:", no_decorations ? "" : "_", sym);
054f95b2 654
655 len += 2;
656 if (len < 8)
657 fprintf(fout, "\t");
658 if (len < 16)
659 fprintf(fout, "\t");
660 if (len <= 16)
661 fprintf(fout, " ");
662 else
663 fprintf(fout, " ");
664 }
665 else {
afdd4566 666 if (header_mode)
667 continue;
668
054f95b2 669 fprintf(fout, "\t\t ");
670 }
671
c87eb470 672 // fill out some unwanted strings with zeroes..
673 if (type == DXT_BYTE && words[w][0] == '\''
674 && is_unwanted_sym(last_sym))
675 {
676 len = 0;
677 for (; w < wordc; w++) {
678 if (words[w][0] == '\'') {
679 p = words[w] + 1;
680 for (; *p && *p != '\''; p++)
681 len++;
682 }
683 else {
684 // assume encoded byte
685 len++;
686 }
687 }
688 fprintf(fout, ".skip %d", len);
689 goto fin;
690 }
691 else if (type == DXT_BYTE
efea2951 692 && (words[w][0] == '\''
693 || (w + 1 < wordc && words[w + 1][0] == '\'')))
694 {
054f95b2 695 // string; use asciz for most common case
696 if (w == wordc - 2 && IS(words[w + 1], "0")) {
697 fprintf(fout, ".asciz \"");
698 wordc--;
699 }
700 else
701 fprintf(fout, ".ascii \"");
702
703 for (; w < wordc; w++) {
704 if (words[w][0] == '\'') {
705 p = words[w] + 1;
706 p2 = strchr(p, '\'');
707 if (p2 == NULL)
708 aerr("unterminated string? '%s'\n", p);
709 memcpy(word, p, p2 - p);
710 word[p2 - p] = 0;
711 fprintf(fout, "%s", escape_string(word));
712 }
713 else {
e27467d0 714 val = parse_number(words[w], 0);
054f95b2 715 if (val & ~0xff)
716 aerr("bad string trailing byte?\n");
206c0727 717 // unfortunately \xHH is unusable - gas interprets
718 // things like \x27b as 0x7b, so have to use octal here
719 fprintf(fout, "\\%03lo", val);
054f95b2 720 }
721 }
722 fprintf(fout, "\"");
723 goto fin;
724 }
725
726 if (w == wordc - 2) {
727 if (IS_START(words[w + 1], "dup(")) {
e27467d0 728 cnt = parse_number(words[w], 0);
054f95b2 729 p = words[w + 1] + 4;
730 p2 = strchr(p, ')');
731 if (p2 == NULL)
732 aerr("bad dup?\n");
733 memmove(word, p, p2 - p);
734 word[p2 - p] = 0;
36595fd2 735
736 val = 0;
737 if (!IS(word, "?"))
e27467d0 738 val = parse_number(word, 0);
054f95b2 739
740 fprintf(fout, ".fill 0x%02lx,%d,0x%02lx",
741 cnt, type_size(type), val);
742 goto fin;
743 }
744 }
745
746 if (type == DXT_DWORD && words[w][0] == '\''
747 && words[w][5] == '\'' && strlen(words[w]) == 6)
748 {
749 if (w != wordc - 1)
750 aerr("TODO\n");
751
752 p = words[w];
753 val = (p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4];
754 fprintf(fout, ".long 0x%lx", val);
b545ba7c 755 snprintf(g_comment, sizeof(g_comment), "%s", words[w]);
054f95b2 756 goto fin;
757 }
758
36595fd2 759 if (type >= DXT_DWORD && strchr(words[w], '.'))
054f95b2 760 {
761 if (w != wordc - 1)
762 aerr("TODO\n");
763
f0be238a 764 if (g_arm_mode && type == DXT_TEN) {
765 fprintf(fout, ".fill 10");
766 snprintf(g_comment, sizeof(g_comment), "%s %s",
767 type_name_float(type), words[w]);
768 }
769 else
770 fprintf(fout, "%s %s", type_name_float(type), words[w]);
054f95b2 771 goto fin;
772 }
773
774 first = 1;
775 fprintf(fout, "%s ", type_name(type));
776 for (; w < wordc; w++)
777 {
778 if (!first)
779 fprintf(fout, ", ");
780
36595fd2 781 is_label = is_bss = 0;
782 if (w <= wordc - 2 && IS(words[w], "offset")) {
054f95b2 783 is_label = 1;
784 w++;
785 }
36595fd2 786 else if (IS(words[w], "?")) {
787 is_bss = 1;
788 }
054f95b2 789 else if (type == DXT_DWORD
790 && !('0' <= words[w][0] && words[w][0] <= '9'))
791 {
792 // assume label
793 is_label = 1;
794 }
795
36595fd2 796 if (is_bss) {
797 fprintf(fout, "0");
798 }
799 else if (is_label) {
054f95b2 800 p = words[w];
ddaf8bd7 801 if (IS_START(p, "loc_") || IS_START(p, "__imp")
802 || strchr(p, '?') || strchr(p, '@')
b0d1f7aa 803 || rm_labels_lines > 0
36595fd2 804 || bsearch(&p, rlist, rlist_cnt, sizeof(rlist[0]),
805 cmpstringp))
054f95b2 806 {
807 fprintf(fout, "0");
b545ba7c 808 snprintf(g_comment, sizeof(g_comment), "%s", p);
36595fd2 809 }
810 else {
9bbecbfb 811 pp = check_var(fhdr, sym, p, in_export_table);
aa1aa2c2 812 if (pp == NULL) {
813 fprintf(fout, "%s%s",
814 (no_decorations || p[0] == '_') ? "" : "_", p);
815 }
816 else {
817 if (no_decorations)
818 fprintf(fout, "%s", pp->name);
819 else
820 output_decorated_pp(fout, pp);
821 }
054f95b2 822 }
054f95b2 823 }
824 else {
e27467d0 825 val64 = parse_number(words[w], 1);
826 if (val64 < 10)
827 fprintf(fout, "%d", (int)val64);
054f95b2 828 else
e27467d0 829 fprintf(fout, "0x%" PRIx64, val64);
054f95b2 830 }
831
832 first = 0;
833 }
834
835fin:
b0d1f7aa 836 if (rm_labels_lines > 0)
837 rm_labels_lines--;
838
b545ba7c 839 if (g_comment[0] != 0) {
f0be238a 840 fprintf(fout, "\t\t%c %s", comment_char, g_comment);
b545ba7c 841 g_comment[0] = 0;
054f95b2 842 }
843 fprintf(fout, "\n");
054f95b2 844 }
845 }
846
36595fd2 847 fprintf(fout, "\n");
848
849 // dump public syms
850 for (i = 0; i < pub_sym_cnt; i++)
aa1aa2c2 851 fprintf(fout, ".global %s%s\n",
852 no_decorations ? "" : "_", pub_syms[i]);
36595fd2 853
054f95b2 854 fclose(fout);
855 fclose(fasm);
afdd4566 856 if (fhdr != NULL)
857 fclose(fhdr);
054f95b2 858
859 return 0;
860}
861
862// vim:ts=2:shiftwidth=2:expandtab