translate: improve epilogue search, clear with and op
[ia32rtools.git] / tools / cvt_data.c
CommitLineData
7637b6cc 1/*
2 * ia32rtools
3 * (C) notaz, 2013,2014
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>
13
14#include "my_assert.h"
15#include "my_str.h"
16
17#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
18#define IS(w, y) !strcmp(w, y)
19#define IS_START(w, y) !strncmp(w, y, strlen(y))
20
21#include "protoparse.h"
22
23static const char *asmfn;
24static int asmln;
054f95b2 25
b545ba7c 26static const struct parsed_proto *g_func_sym_pp;
27static char g_comment[256];
28static int g_warn_cnt;
77f3a833 29static int g_cconv_novalidate;
f0be238a 30static int g_arm_mode;
b545ba7c 31
36595fd2 32// note: must be in ascending order
054f95b2 33enum dx_type {
34 DXT_UNSPEC,
35 DXT_BYTE,
36 DXT_WORD,
37 DXT_DWORD,
38 DXT_QUAD,
39 DXT_TEN,
40};
41
36595fd2 42#define anote(fmt, ...) \
43 printf("%s:%d: note: " fmt, asmfn, asmln, ##__VA_ARGS__)
b545ba7c 44#define awarn(fmt, ...) do { \
45 printf("%s:%d: warning: " fmt, asmfn, asmln, ##__VA_ARGS__); \
46 if (++g_warn_cnt == 10) { \
47 fcloseall(); \
48 exit(1); \
49 } \
50} while (0)
054f95b2 51#define aerr(fmt, ...) do { \
52 printf("%s:%d: error: " fmt, asmfn, asmln, ##__VA_ARGS__); \
53 fcloseall(); \
54 exit(1); \
55} while (0)
56
57#include "masm_tools.h"
58
59static char *next_word_s(char *w, size_t wsize, char *s)
60{
61 int quote = 0;
62 size_t i;
63
64 s = sskip(s);
65
66 for (i = 0; i < wsize - 1; i++) {
67 if (s[i] == '\'')
68 quote ^= 1;
69 if (s[i] == 0 || (!quote && (my_isblank(s[i]) || s[i] == ',')))
70 break;
71 w[i] = s[i];
72 }
73 w[i] = 0;
74
75 if (s[i] != 0 && !my_isblank(s[i]) && s[i] != ',')
76 printf("warning: '%s' truncated\n", w);
77
78 return s + i;
79}
80
81static void next_section(FILE *fasm, char *name)
82{
83 char words[2][256];
84 char line[256];
85 int wordc;
86 char *p;
87
88 name[0] = 0;
89
90 while (fgets(line, sizeof(line), fasm))
91 {
92 wordc = 0;
93 asmln++;
94
95 p = sskip(line);
96 if (*p == 0)
97 continue;
98
99 if (*p == ';') {
100 while (strlen(line) == sizeof(line) - 1) {
101 // one of those long comment lines..
102 if (!fgets(line, sizeof(line), fasm))
103 break;
104 }
105 continue;
106 }
107
108 for (wordc = 0; wordc < ARRAY_SIZE(words); wordc++) {
109 p = sskip(next_word(words[wordc], sizeof(words[0]), p));
110 if (*p == 0 || *p == ';') {
111 wordc++;
112 break;
113 }
114 }
115
116 if (wordc < 2)
117 continue;
118
119 if (!IS(words[1], "segment"))
120 continue;
121
122 strcpy(name, words[0]);
123 break;
124 }
125}
126
127static enum dx_type parse_dx_directive(const char *name)
128{
129 if (IS(name, "dd"))
130 return DXT_DWORD;
131 if (IS(name, "dw"))
132 return DXT_WORD;
133 if (IS(name, "db"))
134 return DXT_BYTE;
135 if (IS(name, "dq"))
136 return DXT_QUAD;
137 if (IS(name, "dt"))
138 return DXT_TEN;
139
140 return DXT_UNSPEC;
141}
142
143static const char *type_name(enum dx_type type)
144{
145 switch (type) {
146 case DXT_BYTE:
147 return ".byte";
148 case DXT_WORD:
b0d802b2 149 return ".hword";
054f95b2 150 case DXT_DWORD:
151 return ".long";
152 case DXT_QUAD:
153 return ".quad";
154 case DXT_TEN:
155 return ".tfloat";
156 case DXT_UNSPEC:
157 break;
158 }
159 return "<bad>";
160}
161
36595fd2 162static const char *type_name_float(enum dx_type type)
163{
164 switch (type) {
165 case DXT_DWORD:
166 return ".float";
167 case DXT_QUAD:
168 return ".double";
169 case DXT_TEN:
170 return ".tfloat";
171 default:
172 break;
173 }
174 return "<bad_float>";
175}
176
054f95b2 177static int type_size(enum dx_type type)
178{
179 switch (type) {
180 case DXT_BYTE:
181 return 1;
182 case DXT_WORD:
183 return 2;
184 case DXT_DWORD:
185 return 4;
186 case DXT_QUAD:
187 return 8;
188 case DXT_TEN:
189 return 10;
190 case DXT_UNSPEC:
191 break;
192 }
193 return -1;
194}
195
196static char *escape_string(char *s)
197{
198 char buf[256];
199 char *t = buf;
200
201 for (; *s != 0; s++) {
202 if (*s == '"') {
203 strcpy(t, "\\22");
204 t += strlen(t);
205 continue;
206 }
207 if (*s == '\\') {
208 strcpy(t, "\\\\");
209 t += strlen(t);
210 continue;
211 }
212 *t++ = *s;
213 }
214 *t = *s;
215 return strcpy(s, buf);
216}
217
b545ba7c 218static void sprint_pp_short(const struct parsed_proto *pp, char *buf,
219 size_t buf_size)
220{
221 char *p = buf;
222 size_t l;
223 int i;
224
225 if (pp->ret_type.is_ptr)
226 *p++ = 'p';
227 else if (IS(pp->ret_type.name, "void"))
228 *p++ = 'v';
229 else
230 *p++ = 'i';
231 *p++ = '(';
232 l = 2;
233
234 for (i = 0; i < pp->argc; i++) {
235 if (pp->arg[i].reg != NULL)
236 snprintf(buf + l, buf_size - l, "%s%s",
237 i == 0 ? "" : ",", pp->arg[i].reg);
238 else
239 snprintf(buf + l, buf_size - l, "%sa%d",
240 i == 0 ? "" : ",", i + 1);
241 l = strlen(buf);
242 }
243 snprintf(buf + l, buf_size - l, ")");
244}
245
c0050df6 246static const struct parsed_proto *check_var(FILE *fhdr,
247 const char *sym, const char *varname)
b545ba7c 248{
249 const struct parsed_proto *pp, *pp_sym;
179b79a9 250 char fp_sym[256], fp_var[256], *p;
251 int i;
b545ba7c 252
253 pp = proto_parse(fhdr, varname, 1);
36595fd2 254 if (pp == NULL) {
b545ba7c 255 if (IS_START(varname, "sub_"))
256 awarn("sub_ sym missing proto: '%s'\n", varname);
c0050df6 257 return NULL;
36595fd2 258 }
259
260 if (!pp->is_func && !pp->is_fptr)
c0050df6 261 return NULL;
b545ba7c 262
b74c31e3 263 pp_print(fp_var, sizeof(fp_var), pp);
b545ba7c 264
36595fd2 265 if (pp->argc_reg == 0)
b545ba7c 266 goto check_sym;
36595fd2 267 if (pp->argc_reg == 1 && pp->argc_stack == 0
268 && IS(pp->arg[0].reg, "ecx"))
269 {
b545ba7c 270 goto check_sym;
36595fd2 271 }
77f3a833 272 if (!g_cconv_novalidate
273 && (pp->argc_reg != 2
274 || !IS(pp->arg[0].reg, "ecx")
275 || !IS(pp->arg[1].reg, "edx")))
36595fd2 276 {
b545ba7c 277 awarn("unhandled reg call: %s\n", fp_var);
36595fd2 278 }
36595fd2 279
b545ba7c 280check_sym:
179b79a9 281 // fptrs must use 32bit args, callsite might have no information and
282 // lack a cast to smaller types, which results in incorrectly masked
283 // args passed (callee may assume masked args, it does on ARM)
284 for (i = 0; i < pp->argc; i++) {
285 if (pp->arg[i].type.is_ptr)
286 continue;
287 p = pp->arg[i].type.name;
288 if (strstr(p, "int8") || strstr(p, "int16")
289 || strstr(p, "char") || strstr(p, "short"))
290 {
291 awarn("reference to %s with arg%d '%s'\n", pp->name, i + 1, p);
292 }
293 }
294
b545ba7c 295 sprint_pp_short(pp, g_comment, sizeof(g_comment));
296
297 if (sym != NULL) {
298 g_func_sym_pp = NULL;
299 pp_sym = proto_parse(fhdr, sym, 1);
300 if (pp_sym == NULL)
c0050df6 301 return pp;
b545ba7c 302 if (!pp_sym->is_fptr)
303 aerr("func ptr data, but label '%s' !is_fptr\n", pp_sym->name);
304 g_func_sym_pp = pp_sym;
36595fd2 305 }
b545ba7c 306 else {
307 pp_sym = g_func_sym_pp;
308 if (pp_sym == NULL)
c0050df6 309 return pp;
b545ba7c 310 }
311
27ebfaed 312 if (pp_cmp_func(pp, pp_sym)) {
b74c31e3 313 pp_print(fp_sym, sizeof(fp_sym), pp_sym);
b545ba7c 314 anote("var: %s\n", fp_var);
315 anote("sym: %s\n", fp_sym);
316 awarn("^ mismatch\n");
36595fd2 317 }
c0050df6 318
319 return pp;
36595fd2 320}
321
aa1aa2c2 322static void output_decorated_pp(FILE *fout,
323 const struct parsed_proto *pp)
324{
325 if (pp->name[0] != '_')
326 fprintf(fout, pp->is_fastcall ? "@" : "_");
327 fprintf(fout, "%s", pp->name);
328 if (pp->is_stdcall && pp->argc > 0)
329 fprintf(fout, "@%d", pp->argc * 4);
330}
331
f0be238a 332static int align_value(int src_val)
333{
334 if (src_val <= 0) {
335 awarn("bad align: %d\n", src_val);
336 src_val = 1;
337 }
338 if (!g_arm_mode)
339 return src_val;
340
341 return __builtin_ffs(src_val) - 1;
342}
343
36595fd2 344static int cmpstringp(const void *p1, const void *p2)
345{
346 return strcmp(*(char * const *)p1, *(char * const *)p2);
347}
348
c87eb470 349/* XXX: maybe move to external file? */
350static const char *unwanted_syms[] = {
351 "aRuntimeError",
352 "aTlossError",
353 "aSingError",
354 "aDomainError",
355 "aR6029ThisAppli",
356 "aR6028UnableToI",
357 "aR6027NotEnough",
358 "aR6026NotEnough",
359 "aR6025PureVirtu",
360 "aR6024NotEnough",
361 "aR6019UnableToO",
362 "aR6018Unexpecte",
363 "aR6017Unexpecte",
364 "aR6016NotEnough",
365 "aAbnormalProgra",
366 "aR6009NotEnough",
367 "aR6008NotEnough",
368 "aR6002FloatingP",
369 "aMicrosoftVisua",
370 "aRuntimeErrorPr",
371 "aThisApplicatio",
372 "aMicrosoftFindF",
373 "aMicrosoftOffic",
374};
375
376static int is_unwanted_sym(const char *sym)
377{
378 return bsearch(&sym, unwanted_syms, ARRAY_SIZE(unwanted_syms),
379 sizeof(unwanted_syms[0]), cmpstringp) != NULL;
380}
381
054f95b2 382int main(int argc, char *argv[])
383{
afdd4566 384 FILE *fout, *fasm, *fhdr = NULL, *frlist;
b545ba7c 385 const struct parsed_proto *pp;
aa1aa2c2 386 int no_decorations = 0;
f0be238a 387 char comment_char = '#';
054f95b2 388 char words[20][256];
054f95b2 389 char word[256];
390 char line[256];
c87eb470 391 char last_sym[32];
054f95b2 392 unsigned long val;
393 unsigned long cnt;
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
465 while (fgets(line, sizeof(line), frlist)) {
466 p = sskip(line);
467 if (*p == 0 || *p == ';')
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
517 while (fgets(line, sizeof(line), fasm))
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 }
054f95b2 533 continue;
b0d802b2 534 }
054f95b2 535
536 for (wordc = 0; wordc < ARRAY_SIZE(words); wordc++) {
054f95b2 537 p = sskip(next_word_s(words[wordc], sizeof(words[0]), p));
538 if (*p == 0 || *p == ';') {
539 wordc++;
540 break;
541 }
542 if (*p == ',') {
054f95b2 543 p = sskip(p + 1);
544 }
545 }
546
b545ba7c 547 if (*p == ';') {
548 p = sskip(p + 1);
549 if (IS_START(p, "sctclrtype"))
550 g_func_sym_pp = NULL;
551 }
552
054f95b2 553 if (wordc == 2 && IS(words[1], "ends"))
554 break;
36595fd2 555 if (wordc <= 2 && IS(words[0], "end"))
556 break;
054f95b2 557 if (wordc < 2)
558 aerr("unhandled: '%s'\n", words[0]);
559
560 // don't cares
561 if (IS(words[0], "assume"))
562 continue;
563
564 if (IS(words[0], "align")) {
afdd4566 565 if (header_mode)
566 continue;
567
054f95b2 568 val = parse_number(words[1]);
f0be238a 569 fprintf(fout, "\t\t .align %d", align_value(val));
054f95b2 570 goto fin;
571 }
572
573 w = 1;
574 type = parse_dx_directive(words[0]);
575 if (type == DXT_UNSPEC) {
576 type = parse_dx_directive(words[1]);
577 sym = words[0];
578 w = 2;
579 }
580 if (type == DXT_UNSPEC)
581 aerr("unhandled decl: '%s %s'\n", words[0], words[1]);
582
afdd4566 583 if (sym != NULL)
584 {
585 if (header_mode) {
586 int is_str = 0;
587
588 fprintf(fout, "extern ");
589 if (is_ro)
590 fprintf(fout, "const ");
591
592 switch (type) {
593 case DXT_BYTE:
594 for (i = w; i < wordc; i++)
595 if (words[i][0] == '\'')
596 is_str = 1;
597 if (is_str)
598 fprintf(fout, "char %s[];\n", sym);
599 else
600 fprintf(fout, "uint8_t %s;\n", sym);
601 break;
602
603 case DXT_WORD:
604 fprintf(fout, "uint16_t %s;\n", sym);
605 break;
606
607 case DXT_DWORD:
608 fprintf(fout, "uint32_t %s;\n", sym);
609 break;
610
611 default:
612 fprintf(fout, "_UNKNOWN %s;\n", sym);
613 break;
614 }
615
616 continue;
617 }
618
c87eb470 619 snprintf(last_sym, sizeof(last_sym), "%s", sym);
36595fd2 620
b545ba7c 621 pp = proto_parse(fhdr, sym, 1);
c87eb470 622 if (pp != NULL) {
b545ba7c 623 g_func_sym_pp = NULL;
624
c87eb470 625 // public/global name
626 if (pub_sym_cnt >= pub_sym_alloc) {
627 pub_sym_alloc *= 2;
628 pub_syms = realloc(pub_syms, pub_sym_alloc * sizeof(pub_syms[0]));
629 my_assert_not(pub_syms, NULL);
630 }
631 pub_syms[pub_sym_cnt++] = strdup(sym);
632 }
633
054f95b2 634 len = strlen(sym);
aa1aa2c2 635 fprintf(fout, "%s%s:", no_decorations ? "" : "_", sym);
054f95b2 636
637 len += 2;
638 if (len < 8)
639 fprintf(fout, "\t");
640 if (len < 16)
641 fprintf(fout, "\t");
642 if (len <= 16)
643 fprintf(fout, " ");
644 else
645 fprintf(fout, " ");
646 }
647 else {
afdd4566 648 if (header_mode)
649 continue;
650
054f95b2 651 fprintf(fout, "\t\t ");
652 }
653
c87eb470 654 // fill out some unwanted strings with zeroes..
655 if (type == DXT_BYTE && words[w][0] == '\''
656 && is_unwanted_sym(last_sym))
657 {
658 len = 0;
659 for (; w < wordc; w++) {
660 if (words[w][0] == '\'') {
661 p = words[w] + 1;
662 for (; *p && *p != '\''; p++)
663 len++;
664 }
665 else {
666 // assume encoded byte
667 len++;
668 }
669 }
670 fprintf(fout, ".skip %d", len);
671 goto fin;
672 }
673 else if (type == DXT_BYTE
efea2951 674 && (words[w][0] == '\''
675 || (w + 1 < wordc && words[w + 1][0] == '\'')))
676 {
054f95b2 677 // string; use asciz for most common case
678 if (w == wordc - 2 && IS(words[w + 1], "0")) {
679 fprintf(fout, ".asciz \"");
680 wordc--;
681 }
682 else
683 fprintf(fout, ".ascii \"");
684
685 for (; w < wordc; w++) {
686 if (words[w][0] == '\'') {
687 p = words[w] + 1;
688 p2 = strchr(p, '\'');
689 if (p2 == NULL)
690 aerr("unterminated string? '%s'\n", p);
691 memcpy(word, p, p2 - p);
692 word[p2 - p] = 0;
693 fprintf(fout, "%s", escape_string(word));
694 }
695 else {
696 val = parse_number(words[w]);
697 if (val & ~0xff)
698 aerr("bad string trailing byte?\n");
699 fprintf(fout, "\\x%02lx", val);
700 }
701 }
702 fprintf(fout, "\"");
703 goto fin;
704 }
705
706 if (w == wordc - 2) {
707 if (IS_START(words[w + 1], "dup(")) {
708 cnt = parse_number(words[w]);
709 p = words[w + 1] + 4;
710 p2 = strchr(p, ')');
711 if (p2 == NULL)
712 aerr("bad dup?\n");
713 memmove(word, p, p2 - p);
714 word[p2 - p] = 0;
36595fd2 715
716 val = 0;
717 if (!IS(word, "?"))
718 val = parse_number(word);
054f95b2 719
720 fprintf(fout, ".fill 0x%02lx,%d,0x%02lx",
721 cnt, type_size(type), val);
722 goto fin;
723 }
724 }
725
726 if (type == DXT_DWORD && words[w][0] == '\''
727 && words[w][5] == '\'' && strlen(words[w]) == 6)
728 {
729 if (w != wordc - 1)
730 aerr("TODO\n");
731
732 p = words[w];
733 val = (p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4];
734 fprintf(fout, ".long 0x%lx", val);
b545ba7c 735 snprintf(g_comment, sizeof(g_comment), "%s", words[w]);
054f95b2 736 goto fin;
737 }
738
36595fd2 739 if (type >= DXT_DWORD && strchr(words[w], '.'))
054f95b2 740 {
741 if (w != wordc - 1)
742 aerr("TODO\n");
743
f0be238a 744 if (g_arm_mode && type == DXT_TEN) {
745 fprintf(fout, ".fill 10");
746 snprintf(g_comment, sizeof(g_comment), "%s %s",
747 type_name_float(type), words[w]);
748 }
749 else
750 fprintf(fout, "%s %s", type_name_float(type), words[w]);
054f95b2 751 goto fin;
752 }
753
754 first = 1;
755 fprintf(fout, "%s ", type_name(type));
756 for (; w < wordc; w++)
757 {
758 if (!first)
759 fprintf(fout, ", ");
760
36595fd2 761 is_label = is_bss = 0;
762 if (w <= wordc - 2 && IS(words[w], "offset")) {
054f95b2 763 is_label = 1;
764 w++;
765 }
36595fd2 766 else if (IS(words[w], "?")) {
767 is_bss = 1;
768 }
054f95b2 769 else if (type == DXT_DWORD
770 && !('0' <= words[w][0] && words[w][0] <= '9'))
771 {
772 // assume label
773 is_label = 1;
774 }
775
36595fd2 776 if (is_bss) {
777 fprintf(fout, "0");
778 }
779 else if (is_label) {
054f95b2 780 p = words[w];
ddaf8bd7 781 if (IS_START(p, "loc_") || IS_START(p, "__imp")
782 || strchr(p, '?') || strchr(p, '@')
36595fd2 783 || bsearch(&p, rlist, rlist_cnt, sizeof(rlist[0]),
784 cmpstringp))
054f95b2 785 {
786 fprintf(fout, "0");
b545ba7c 787 snprintf(g_comment, sizeof(g_comment), "%s", p);
36595fd2 788 }
789 else {
c0050df6 790 pp = check_var(fhdr, sym, p);
aa1aa2c2 791 if (pp == NULL) {
792 fprintf(fout, "%s%s",
793 (no_decorations || p[0] == '_') ? "" : "_", p);
794 }
795 else {
796 if (no_decorations)
797 fprintf(fout, "%s", pp->name);
798 else
799 output_decorated_pp(fout, pp);
800 }
054f95b2 801 }
054f95b2 802 }
803 else {
804 val = parse_number(words[w]);
805 if (val < 10)
806 fprintf(fout, "%ld", val);
807 else
808 fprintf(fout, "0x%lx", val);
809 }
810
811 first = 0;
812 }
813
814fin:
b545ba7c 815 if (g_comment[0] != 0) {
f0be238a 816 fprintf(fout, "\t\t%c %s", comment_char, g_comment);
b545ba7c 817 g_comment[0] = 0;
054f95b2 818 }
819 fprintf(fout, "\n");
054f95b2 820 }
821 }
822
36595fd2 823 fprintf(fout, "\n");
824
825 // dump public syms
826 for (i = 0; i < pub_sym_cnt; i++)
aa1aa2c2 827 fprintf(fout, ".global %s%s\n",
828 no_decorations ? "" : "_", pub_syms[i]);
36595fd2 829
054f95b2 830 fclose(fout);
831 fclose(fasm);
afdd4566 832 if (fhdr != NULL)
833 fclose(fhdr);
054f95b2 834
835 return 0;
836}
837
838// vim:ts=2:shiftwidth=2:expandtab