9 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
10 #define IS(w, y) !strcmp(w, y)
11 #define IS_START(w, y) !strncmp(w, y, strlen(y))
13 #include "protoparse.h"
15 static const char *asmfn;
28 #define aerr(fmt, ...) do { \
29 printf("%s:%d: error: " fmt, asmfn, asmln, ##__VA_ARGS__); \
34 #include "masm_tools.h"
36 static char *next_word_s(char *w, size_t wsize, char *s)
43 for (i = 0; i < wsize - 1; i++) {
46 if (s[i] == 0 || (!quote && (my_isblank(s[i]) || s[i] == ',')))
52 if (s[i] != 0 && !my_isblank(s[i]) && s[i] != ',')
53 printf("warning: '%s' truncated\n", w);
58 static void next_section(FILE *fasm, char *name)
67 while (fgets(line, sizeof(line), fasm))
77 while (strlen(line) == sizeof(line) - 1) {
78 // one of those long comment lines..
79 if (!fgets(line, sizeof(line), fasm))
85 for (wordc = 0; wordc < ARRAY_SIZE(words); wordc++) {
86 p = sskip(next_word(words[wordc], sizeof(words[0]), p));
87 if (*p == 0 || *p == ';') {
96 if (!IS(words[1], "segment"))
99 strcpy(name, words[0]);
104 static enum dx_type parse_dx_directive(const char *name)
120 static const char *type_name(enum dx_type type)
139 static int type_size(enum dx_type type)
158 static char *escape_string(char *s)
163 for (; *s != 0; s++) {
177 return strcpy(s, buf);
180 int main(int argc, char *argv[])
203 printf("usage:\n%s <.s> <.asm> <hdrf>\n",
211 fasm = fopen(asmfn, "r");
212 my_assert_not(fasm, NULL);
215 g_fhdr = fopen(hdrfn, "r");
216 my_assert_not(g_fhdr, NULL);
218 fout = fopen(argv[arg_out], "w");
219 my_assert_not(fout, NULL);
223 while (!feof(fasm)) {
224 next_section(fasm, line);
225 if (IS(line + 1, "text"))
228 if (IS(line + 1, "rdata"))
229 fprintf(fout, "\n.section .rodata\n");
230 else if (IS(line + 1, "data"))
231 fprintf(fout, "\n.data\n");
233 aerr("unhandled section: '%s'\n", line);
235 fprintf(fout, ".align 4\n");
237 while (fgets(line, sizeof(line), fasm))
243 if (*p == 0 || *p == ';')
246 for (wordc = 0; wordc < ARRAY_SIZE(words); wordc++) {
247 //sep_after[wordc] = 0;
248 p = sskip(next_word_s(words[wordc], sizeof(words[0]), p));
249 if (*p == 0 || *p == ';') {
254 //sep_after[wordc] = 1;
259 if (wordc == 2 && IS(words[1], "ends"))
262 aerr("unhandled: '%s'\n", words[0]);
265 if (IS(words[0], "assume"))
268 if (IS(words[0], "align")) {
269 val = parse_number(words[1]);
270 fprintf(fout, "\t\t .align %ld", val);
275 type = parse_dx_directive(words[0]);
276 if (type == DXT_UNSPEC) {
277 type = parse_dx_directive(words[1]);
281 if (type == DXT_UNSPEC)
282 aerr("unhandled decl: '%s %s'\n", words[0], words[1]);
286 fprintf(fout, "_%s:", sym);
299 fprintf(fout, "\t\t ");
302 if (type == DXT_BYTE && words[w][0] == '\'') {
303 // string; use asciz for most common case
304 if (w == wordc - 2 && IS(words[w + 1], "0")) {
305 fprintf(fout, ".asciz \"");
309 fprintf(fout, ".ascii \"");
311 for (; w < wordc; w++) {
312 if (words[w][0] == '\'') {
314 p2 = strchr(p, '\'');
316 aerr("unterminated string? '%s'\n", p);
317 memcpy(word, p, p2 - p);
319 fprintf(fout, "%s", escape_string(word));
322 val = parse_number(words[w]);
324 aerr("bad string trailing byte?\n");
325 fprintf(fout, "\\x%02lx", val);
332 if (w == wordc - 2) {
333 if (IS_START(words[w + 1], "dup(")) {
334 cnt = parse_number(words[w]);
335 p = words[w + 1] + 4;
339 memmove(word, p, p2 - p);
341 val = parse_number(word);
343 fprintf(fout, ".fill 0x%02lx,%d,0x%02lx",
344 cnt, type_size(type), val);
349 if (type == DXT_DWORD && words[w][0] == '\''
350 && words[w][5] == '\'' && strlen(words[w]) == 6)
356 val = (p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4];
357 fprintf(fout, ".long 0x%lx", val);
358 snprintf(comment, sizeof(comment), "%s", words[w]);
362 if ((type == DXT_QUAD || type == DXT_TEN)
363 && strchr(words[w], '.'))
368 fprintf(fout, type == DXT_TEN ? ".tfloat " : ".double ");
369 fprintf(fout, "%s", words[w]);
374 fprintf(fout, "%s ", type_name(type));
375 for (; w < wordc; w++)
381 if (w >= wordc - 2 && IS(words[w], "offset")) {
385 else if (type == DXT_DWORD
386 && !('0' <= words[w][0] && words[w][0] <= '9'))
394 if (IS_START(p, "loc_") || strchr(p, '?') || strchr(p, '@'))
397 snprintf(comment, sizeof(comment), "%s", words[w + 1]);
400 fprintf(fout, "_%s", p);
403 val = parse_number(words[w]);
405 fprintf(fout, "%ld", val);
407 fprintf(fout, "0x%lx", val);
414 if (comment[0] != 0) {
415 fprintf(fout, "\t\t# %s", comment);
430 // vim:ts=2:shiftwidth=2:expandtab