translate: add fptr-arg checking
[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
17ed469e 309 if (!pp_compatible_func(pp_sym, pp)) {
310 pp_print(fp_sym, sizeof(fp_sym), pp_sym);
311 anote("entry: %s\n", fp_var);
312 anote("label: %s\n", fp_sym);
313 awarn("^ mismatch\n");
36595fd2 314 }
c0050df6 315
316 return pp;
36595fd2 317}
318
aa1aa2c2 319static void output_decorated_pp(FILE *fout,
320 const struct parsed_proto *pp)
321{
322 if (pp->name[0] != '_')
323 fprintf(fout, pp->is_fastcall ? "@" : "_");
324 fprintf(fout, "%s", pp->name);
325 if (pp->is_stdcall && pp->argc > 0)
326 fprintf(fout, "@%d", pp->argc * 4);
327}
328
f0be238a 329static int align_value(int src_val)
330{
331 if (src_val <= 0) {
332 awarn("bad align: %d\n", src_val);
333 src_val = 1;
334 }
335 if (!g_arm_mode)
336 return src_val;
337
338 return __builtin_ffs(src_val) - 1;
339}
340
36595fd2 341static int cmpstringp(const void *p1, const void *p2)
342{
343 return strcmp(*(char * const *)p1, *(char * const *)p2);
344}
345
c87eb470 346/* XXX: maybe move to external file? */
347static const char *unwanted_syms[] = {
348 "aRuntimeError",
349 "aTlossError",
350 "aSingError",
351 "aDomainError",
352 "aR6029ThisAppli",
353 "aR6028UnableToI",
354 "aR6027NotEnough",
355 "aR6026NotEnough",
356 "aR6025PureVirtu",
357 "aR6024NotEnough",
358 "aR6019UnableToO",
359 "aR6018Unexpecte",
360 "aR6017Unexpecte",
361 "aR6016NotEnough",
362 "aAbnormalProgra",
363 "aR6009NotEnough",
364 "aR6008NotEnough",
365 "aR6002FloatingP",
366 "aMicrosoftVisua",
367 "aRuntimeErrorPr",
368 "aThisApplicatio",
369 "aMicrosoftFindF",
370 "aMicrosoftOffic",
371};
372
373static int is_unwanted_sym(const char *sym)
374{
375 return bsearch(&sym, unwanted_syms, ARRAY_SIZE(unwanted_syms),
376 sizeof(unwanted_syms[0]), cmpstringp) != NULL;
377}
378
054f95b2 379int main(int argc, char *argv[])
380{
afdd4566 381 FILE *fout, *fasm, *fhdr = NULL, *frlist;
b545ba7c 382 const struct parsed_proto *pp;
aa1aa2c2 383 int no_decorations = 0;
9bbecbfb 384 int in_export_table = 0;
b0d1f7aa 385 int rm_labels_lines = 0;
f0be238a 386 char comment_char = '#';
054f95b2 387 char words[20][256];
054f95b2 388 char word[256];
389 char line[256];
c87eb470 390 char last_sym[32];
054f95b2 391 unsigned long val;
392 unsigned long cnt;
e27467d0 393 uint64_t val64;
054f95b2 394 const char *sym;
395 enum dx_type type;
36595fd2 396 char **pub_syms;
397 int pub_sym_cnt = 0;
398 int pub_sym_alloc;
399 char **rlist;
400 int rlist_cnt = 0;
401 int rlist_alloc;
afdd4566 402 int header_mode = 0;
403 int is_ro = 0;
054f95b2 404 int is_label;
36595fd2 405 int is_bss;
054f95b2 406 int wordc;
407 int first;
408 int arg_out;
409 int arg = 1;
410 int len;
36595fd2 411 int w, i;
054f95b2 412 char *p;
413 char *p2;
414
36595fd2 415 if (argc < 4) {
aa1aa2c2 416 // -nd: no symbol decorations
afdd4566 417 printf("usage:\n%s [-nd] [-i] [-a] <.s> <.asm> <hdrf> [rlist]*\n"
418 "%s -hdr <.h> <.asm>\n",
419 argv[0], argv[0]);
054f95b2 420 return 1;
421 }
422
aa1aa2c2 423 for (arg = 1; arg < argc; arg++) {
424 if (IS(argv[arg], "-nd"))
425 no_decorations = 1;
77f3a833 426 else if (IS(argv[arg], "-i"))
427 g_cconv_novalidate = 1;
f0be238a 428 else if (IS(argv[arg], "-a")) {
429 comment_char = '@';
430 g_arm_mode = 1;
431 }
afdd4566 432 else if (IS(argv[arg], "-hdr"))
433 header_mode = 1;
aa1aa2c2 434 else
435 break;
436 }
437
054f95b2 438 arg_out = arg++;
439
440 asmfn = argv[arg++];
441 fasm = fopen(asmfn, "r");
442 my_assert_not(fasm, NULL);
443
afdd4566 444 if (!header_mode) {
445 hdrfn = argv[arg++];
446 fhdr = fopen(hdrfn, "r");
447 my_assert_not(fhdr, NULL);
448 }
054f95b2 449
450 fout = fopen(argv[arg_out], "w");
451 my_assert_not(fout, NULL);
452
36595fd2 453 pub_sym_alloc = 64;
454 pub_syms = malloc(pub_sym_alloc * sizeof(pub_syms[0]));
455 my_assert_not(pub_syms, NULL);
456
457 rlist_alloc = 64;
458 rlist = malloc(rlist_alloc * sizeof(rlist[0]));
459 my_assert_not(rlist, NULL);
460
461 for (; arg < argc; arg++) {
462 frlist = fopen(argv[arg], "r");
463 my_assert_not(frlist, NULL);
464
9ea60b8d 465 while (my_fgets(line, sizeof(line), frlist)) {
36595fd2 466 p = sskip(line);
9bbecbfb 467 if (*p == 0 || *p == ';' || *p == '#')
36595fd2 468 continue;
469
470 p = next_word(words[0], sizeof(words[0]), p);
471 if (words[0][0] == 0)
472 continue;
473
474 if (rlist_cnt >= rlist_alloc) {
475 rlist_alloc = rlist_alloc * 2 + 64;
476 rlist = realloc(rlist, rlist_alloc * sizeof(rlist[0]));
477 my_assert_not(rlist, NULL);
478 }
479 rlist[rlist_cnt++] = strdup(words[0]);
480 }
481
482 fclose(frlist);
483 frlist = NULL;
484 }
485
486 if (rlist_cnt > 0)
487 qsort(rlist, rlist_cnt, sizeof(rlist[0]), cmpstringp);
488
c87eb470 489 qsort(unwanted_syms, ARRAY_SIZE(unwanted_syms),
490 sizeof(unwanted_syms[0]), cmpstringp);
491
492 last_sym[0] = 0;
493
36595fd2 494 while (1) {
054f95b2 495 next_section(fasm, line);
36595fd2 496 if (feof(fasm))
497 break;
054f95b2 498 if (IS(line + 1, "text"))
499 continue;
500
afdd4566 501 if (IS(line + 1, "rdata")) {
502 is_ro = 1;
503 if (!header_mode)
504 fprintf(fout, "\n.section .rodata\n");
505 }
506 else if (IS(line + 1, "data")) {
507 is_ro = 0;
508 if (!header_mode)
509 fprintf(fout, "\n.data\n");
510 }
054f95b2 511 else
512 aerr("unhandled section: '%s'\n", line);
513
afdd4566 514 if (!header_mode)
515 fprintf(fout, ".align %d\n", align_value(4));
054f95b2 516
9ea60b8d 517 while (my_fgets(line, sizeof(line), fasm))
054f95b2 518 {
519 sym = NULL;
520 asmln++;
521
522 p = sskip(line);
b0d802b2 523 if (*p == 0)
524 continue;
525
526 if (*p == ';') {
527 if (IS_START(p, ";org") && sscanf(p + 5, "%Xh", &i) == 1) {
528 // ;org is only seen at section start, so assume . addr 0
529 i &= 0xfff;
afdd4566 530 if (i != 0 && !header_mode)
b0d802b2 531 fprintf(fout, "\t\t .skip 0x%x\n", i);
532 }
9bbecbfb 533 else if (IS_START(p, "; Export Address"))
534 in_export_table = 1;
535 else if (IS_START(p, "; Export"))
536 in_export_table = 0;
054f95b2 537 continue;
b0d802b2 538 }
054f95b2 539
540 for (wordc = 0; wordc < ARRAY_SIZE(words); wordc++) {
054f95b2 541 p = sskip(next_word_s(words[wordc], sizeof(words[0]), p));
542 if (*p == 0 || *p == ';') {
543 wordc++;
544 break;
545 }
546 if (*p == ',') {
054f95b2 547 p = sskip(p + 1);
548 }
549 }
550
b545ba7c 551 if (*p == ';') {
552 p = sskip(p + 1);
553 if (IS_START(p, "sctclrtype"))
554 g_func_sym_pp = NULL;
555 }
556
054f95b2 557 if (wordc == 2 && IS(words[1], "ends"))
558 break;
36595fd2 559 if (wordc <= 2 && IS(words[0], "end"))
560 break;
054f95b2 561 if (wordc < 2)
562 aerr("unhandled: '%s'\n", words[0]);
563
564 // don't cares
565 if (IS(words[0], "assume"))
566 continue;
567
568 if (IS(words[0], "align")) {
afdd4566 569 if (header_mode)
570 continue;
571
e27467d0 572 val = parse_number(words[1], 0);
f0be238a 573 fprintf(fout, "\t\t .align %d", align_value(val));
054f95b2 574 goto fin;
575 }
576
c1fbaecc 577 if (IS(words[0], "public")) {
578 // skip, sym should appear in header anyway
579 continue;
580 }
581
054f95b2 582 w = 1;
583 type = parse_dx_directive(words[0]);
584 if (type == DXT_UNSPEC) {
585 type = parse_dx_directive(words[1]);
586 sym = words[0];
587 w = 2;
588 }
589 if (type == DXT_UNSPEC)
590 aerr("unhandled decl: '%s %s'\n", words[0], words[1]);
591
afdd4566 592 if (sym != NULL)
593 {
594 if (header_mode) {
595 int is_str = 0;
596
597 fprintf(fout, "extern ");
598 if (is_ro)
599 fprintf(fout, "const ");
600
601 switch (type) {
602 case DXT_BYTE:
603 for (i = w; i < wordc; i++)
604 if (words[i][0] == '\'')
605 is_str = 1;
606 if (is_str)
607 fprintf(fout, "char %s[];\n", sym);
608 else
609 fprintf(fout, "uint8_t %s;\n", sym);
610 break;
611
612 case DXT_WORD:
613 fprintf(fout, "uint16_t %s;\n", sym);
614 break;
615
616 case DXT_DWORD:
617 fprintf(fout, "uint32_t %s;\n", sym);
618 break;
619
620 default:
621 fprintf(fout, "_UNKNOWN %s;\n", sym);
622 break;
623 }
624
625 continue;
626 }
627
c87eb470 628 snprintf(last_sym, sizeof(last_sym), "%s", sym);
b0d1f7aa 629 if (IS_START(sym, "__IMPORT_DESCRIPTOR_"))
630 rm_labels_lines = 5;
36595fd2 631
b545ba7c 632 pp = proto_parse(fhdr, sym, 1);
c87eb470 633 if (pp != NULL) {
b545ba7c 634 g_func_sym_pp = NULL;
635
c87eb470 636 // public/global name
637 if (pub_sym_cnt >= pub_sym_alloc) {
638 pub_sym_alloc *= 2;
639 pub_syms = realloc(pub_syms, pub_sym_alloc * sizeof(pub_syms[0]));
640 my_assert_not(pub_syms, NULL);
641 }
642 pub_syms[pub_sym_cnt++] = strdup(sym);
643 }
644
054f95b2 645 len = strlen(sym);
aa1aa2c2 646 fprintf(fout, "%s%s:", no_decorations ? "" : "_", sym);
054f95b2 647
648 len += 2;
649 if (len < 8)
650 fprintf(fout, "\t");
651 if (len < 16)
652 fprintf(fout, "\t");
653 if (len <= 16)
654 fprintf(fout, " ");
655 else
656 fprintf(fout, " ");
657 }
658 else {
afdd4566 659 if (header_mode)
660 continue;
661
054f95b2 662 fprintf(fout, "\t\t ");
663 }
664
c87eb470 665 // fill out some unwanted strings with zeroes..
666 if (type == DXT_BYTE && words[w][0] == '\''
667 && is_unwanted_sym(last_sym))
668 {
669 len = 0;
670 for (; w < wordc; w++) {
671 if (words[w][0] == '\'') {
672 p = words[w] + 1;
673 for (; *p && *p != '\''; p++)
674 len++;
675 }
676 else {
677 // assume encoded byte
678 len++;
679 }
680 }
681 fprintf(fout, ".skip %d", len);
682 goto fin;
683 }
684 else if (type == DXT_BYTE
efea2951 685 && (words[w][0] == '\''
686 || (w + 1 < wordc && words[w + 1][0] == '\'')))
687 {
054f95b2 688 // string; use asciz for most common case
689 if (w == wordc - 2 && IS(words[w + 1], "0")) {
690 fprintf(fout, ".asciz \"");
691 wordc--;
692 }
693 else
694 fprintf(fout, ".ascii \"");
695
696 for (; w < wordc; w++) {
697 if (words[w][0] == '\'') {
698 p = words[w] + 1;
699 p2 = strchr(p, '\'');
700 if (p2 == NULL)
701 aerr("unterminated string? '%s'\n", p);
702 memcpy(word, p, p2 - p);
703 word[p2 - p] = 0;
704 fprintf(fout, "%s", escape_string(word));
705 }
706 else {
e27467d0 707 val = parse_number(words[w], 0);
054f95b2 708 if (val & ~0xff)
709 aerr("bad string trailing byte?\n");
206c0727 710 // unfortunately \xHH is unusable - gas interprets
711 // things like \x27b as 0x7b, so have to use octal here
712 fprintf(fout, "\\%03lo", val);
054f95b2 713 }
714 }
715 fprintf(fout, "\"");
716 goto fin;
717 }
718
719 if (w == wordc - 2) {
720 if (IS_START(words[w + 1], "dup(")) {
e27467d0 721 cnt = parse_number(words[w], 0);
054f95b2 722 p = words[w + 1] + 4;
723 p2 = strchr(p, ')');
724 if (p2 == NULL)
725 aerr("bad dup?\n");
726 memmove(word, p, p2 - p);
727 word[p2 - p] = 0;
36595fd2 728
729 val = 0;
730 if (!IS(word, "?"))
e27467d0 731 val = parse_number(word, 0);
054f95b2 732
733 fprintf(fout, ".fill 0x%02lx,%d,0x%02lx",
734 cnt, type_size(type), val);
735 goto fin;
736 }
737 }
738
739 if (type == DXT_DWORD && words[w][0] == '\''
740 && words[w][5] == '\'' && strlen(words[w]) == 6)
741 {
742 if (w != wordc - 1)
743 aerr("TODO\n");
744
745 p = words[w];
746 val = (p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4];
747 fprintf(fout, ".long 0x%lx", val);
b545ba7c 748 snprintf(g_comment, sizeof(g_comment), "%s", words[w]);
054f95b2 749 goto fin;
750 }
751
36595fd2 752 if (type >= DXT_DWORD && strchr(words[w], '.'))
054f95b2 753 {
754 if (w != wordc - 1)
755 aerr("TODO\n");
756
f0be238a 757 if (g_arm_mode && type == DXT_TEN) {
758 fprintf(fout, ".fill 10");
759 snprintf(g_comment, sizeof(g_comment), "%s %s",
760 type_name_float(type), words[w]);
761 }
762 else
763 fprintf(fout, "%s %s", type_name_float(type), words[w]);
054f95b2 764 goto fin;
765 }
766
767 first = 1;
768 fprintf(fout, "%s ", type_name(type));
769 for (; w < wordc; w++)
770 {
771 if (!first)
772 fprintf(fout, ", ");
773
36595fd2 774 is_label = is_bss = 0;
775 if (w <= wordc - 2 && IS(words[w], "offset")) {
054f95b2 776 is_label = 1;
777 w++;
778 }
36595fd2 779 else if (IS(words[w], "?")) {
780 is_bss = 1;
781 }
054f95b2 782 else if (type == DXT_DWORD
783 && !('0' <= words[w][0] && words[w][0] <= '9'))
784 {
785 // assume label
786 is_label = 1;
787 }
788
36595fd2 789 if (is_bss) {
790 fprintf(fout, "0");
791 }
792 else if (is_label) {
054f95b2 793 p = words[w];
ddaf8bd7 794 if (IS_START(p, "loc_") || IS_START(p, "__imp")
795 || strchr(p, '?') || strchr(p, '@')
b0d1f7aa 796 || rm_labels_lines > 0
36595fd2 797 || bsearch(&p, rlist, rlist_cnt, sizeof(rlist[0]),
798 cmpstringp))
054f95b2 799 {
800 fprintf(fout, "0");
b545ba7c 801 snprintf(g_comment, sizeof(g_comment), "%s", p);
36595fd2 802 }
803 else {
9bbecbfb 804 pp = check_var(fhdr, sym, p, in_export_table);
aa1aa2c2 805 if (pp == NULL) {
806 fprintf(fout, "%s%s",
807 (no_decorations || p[0] == '_') ? "" : "_", p);
808 }
809 else {
810 if (no_decorations)
811 fprintf(fout, "%s", pp->name);
812 else
813 output_decorated_pp(fout, pp);
814 }
054f95b2 815 }
054f95b2 816 }
817 else {
e27467d0 818 val64 = parse_number(words[w], 1);
819 if (val64 < 10)
820 fprintf(fout, "%d", (int)val64);
054f95b2 821 else
e27467d0 822 fprintf(fout, "0x%" PRIx64, val64);
054f95b2 823 }
824
825 first = 0;
826 }
827
828fin:
b0d1f7aa 829 if (rm_labels_lines > 0)
830 rm_labels_lines--;
831
b545ba7c 832 if (g_comment[0] != 0) {
f0be238a 833 fprintf(fout, "\t\t%c %s", comment_char, g_comment);
b545ba7c 834 g_comment[0] = 0;
054f95b2 835 }
836 fprintf(fout, "\n");
054f95b2 837 }
838 }
839
36595fd2 840 fprintf(fout, "\n");
841
842 // dump public syms
843 for (i = 0; i < pub_sym_cnt; i++)
aa1aa2c2 844 fprintf(fout, ".global %s%s\n",
845 no_decorations ? "" : "_", pub_syms[i]);
36595fd2 846
054f95b2 847 fclose(fout);
848 fclose(fasm);
afdd4566 849 if (fhdr != NULL)
850 fclose(fhdr);
054f95b2 851
852 return 0;
853}
854
855// vim:ts=2:shiftwidth=2:expandtab