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