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