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