Mercurial > hg-old > index.cgi
diff src/macro.c @ 57:035b95a3690f
Added conditional assembly and macros
author | lost |
---|---|
date | Mon, 05 Jan 2009 00:01:21 +0000 |
parents | 34568fab6058 |
children | d5fe306f1ab1 |
line wrap: on
line diff
--- a/src/macro.c Sun Jan 04 21:43:05 2009 +0000 +++ b/src/macro.c Mon Jan 05 00:01:21 2009 +0000 @@ -24,71 +24,95 @@ #include <stdlib.h> #include <string.h> #include "lwasm.h" +#include "instab.h" +#include "util.h" -extern void resolve_insn(asmstate_t *as, sourceline_t *cl); - -void pseudo_macro(asmstate_t *as, sourceline_t *cl, char **optr) +OPFUNC(pseudo_macro) { macrotab_t *m; + // if skipping a condition, flag in a macro + if (as -> skipcond) + { + as -> skipmacro = 1; + return; + } + + // actually define a macro if (as -> inmacro) { - errorp1(ERR_MACRO); + register_error(as, l, 1, "Attempt to define a macro inside a macro"); return; } + as -> inmacro = 1; + + // don't actually do anything if not pass 1 if (as -> passnum != 1) return; + + + if (!l -> sym) + { + register_error(as, l, 1, "Macro definition with no effect - no symbol"); + return; + } + // search for macro by same name... for (m = as -> macros; m; m = m -> next) { - if (!strcmp(m -> name, cl -> symstr)) + if (!strcmp(m -> name, l -> sym)) break; } if (m) { - errorp1(ERR_DUPSYM); + register_error(as, l, 1, "Duplicate macro definition"); return; } - m = calloc(sizeof(macrotab_t), 1); - m -> name = strdup(cl -> symstr); + + m = lwasm_alloc(sizeof(macrotab_t)); + m -> name = lwasm_strdup(l -> sym); m -> next = as -> macros; + m -> lines = NULL; + m -> numlines = 0; as -> macros = m; - cl -> hassym = 0; - while (**optr && !isspace(**optr)) - (*optr)++; - cl -> macrodef = 1; + + while (**p && !isspace(**p)) + (*p)++; } -void pseudo_endm(asmstate_t *as, sourceline_t *cl, char **optr) +OPFUNC(pseudo_endm) { + if (as -> skipcond) + { + as -> skipmacro = 0; + return; + } + if (!as -> inmacro) { - errorp1(ERR_ENDM); + register_error(as, l, 1, "ENDM without MACRO"); return; } as -> inmacro = 0; - cl -> macrodef = 1; + + // a macro definition counts as a context break for local symbols + as -> context = lwasm_next_context(as); } -int add_macro_line(asmstate_t *as, sourceline_t *cl, char *optr) +// the current macro will ALWAYS be the first one in the table +int add_macro_line(asmstate_t *as, char *optr) { - macroline_t *l; - if (!as -> inmacro) return 0; if (as -> passnum == 2) return 1; - l = calloc(sizeof(macroline_t), 1); - l -> linetext = strdup(optr); - if (as -> macros -> linetail) - as -> macros -> linetail -> next = l; - as -> macros -> linetail = l; - if (!(as -> macros -> linehead)) - as -> macros -> linehead = l; + as -> macros -> lines = lwasm_realloc(as -> macros -> lines, sizeof(char *) * as -> macros -> numlines + 1); + as -> macros -> lines[as -> macros -> numlines] = lwasm_strdup(optr); + as -> macros -> numlines += 1; return 1; } @@ -104,128 +128,196 @@ // this is just like a regular operation function /* -macro args are references by "\n" where 1 <= n <= 9 +macro args are referenced by "\n" where 1 <= n <= 9 or by "\{n}"; a \ can be included by writing \\ +a comma separates argument but one can be included with "\," +whitespace ends argument list but can be included with "\ " or the like + +In pass 1, actually add the lines to the system, in pass 2, do not +In pass 2, track the number of lines to skip because they already will be +processed by this function - this will be in as -> skiplines + */ -void expand_macro(asmstate_t *as, sourceline_t *cl, char **optr) +int expand_macro(asmstate_t *as, lwasm_line_t *l, char **p, char *opc) { - char **args = NULL; - int nargs = 0; - int c; - sourceline_t *nl; - int nline = 1; + int lc; + lwasm_line_t *cl, *nl; + int oldcontext; macrotab_t *m; - macroline_t *ml; - char *buff = NULL; - int bufflen = 0, buffloc; + + char **args = NULL; // macro arguments + int nargs; // number of arguments + + char *p2, *p3; - m = cl -> macro; + int bloc, blen; + char *linebuff; + + for (m = as -> macros; m; m = m -> next) + { + if (!strcmp(opc, m -> name)) + break; + } + // signal no macro expansion + if (!m) + return -1; - // step the first: parse arguments - while (**optr && !isspace(**optr)) + + // save current symbol context for after macro expansion + oldcontext = as -> context; + + cl = l; + + as -> context = lwasm_next_context(as); + + // step 1: parse arguments (pass 1 only) + if (as -> passnum == 1) { - c = 0; - while ((*optr)[c] && !isspace((*optr)[c]) && (*optr)[c] != ',') + while (**p && !isspace(**p) && **p != ',') { - c++; + p2 = *p; + while (*p2 && !isspace(*p2) && *p2 != ',') + { + if (*p2 == '\\') + { + if (p2[1]) + p2++; + } + } + + // have arg here + args = lwasm_realloc(args, nargs + 1); + args[nargs] = lwasm_alloc(p2 - *p + 1); + args[nargs][p2 - *p] = '\0'; + memcpy(args[nargs], *p, p2 - *p); + *p = p2; + + // now collapse out "\" characters + for (p3 = p2 = args[nargs]; *p2; p2++, p3++) + { + if (*p2 == '\\' && p2[1]) + { + p2++; + } + *p3 = *p2; + } + *p3 = '\0'; + + nargs++; } - args = realloc(args, sizeof(char *) * (nargs + 1)); - args[nargs] = malloc(c + 1); - strncpy(args[nargs], *optr, c); - args[nargs][c] = '\0'; - nargs++; - *optr += c; - if (**optr == ',') - (*optr)++; } - // step the second: iterate over the lines and expand arguments and add - // them after "cl" - for (ml = m -> linehead; ml; ml = ml -> next) + // step 2: iterate over the lines + if (as -> passnum == 2) + { + // pass 2 only - parse the lines and count them + for (lc = 0; lc < m -> numlines; lc++) + { + cl = cl -> next; + as -> skiplines++; + lwasm_parse_line(as, cl); + } + } + else { - nl = calloc(sizeof(sourceline_t), 1); - - nl -> lineno = nline++; - nl -> sourcefile = m -> name; - nl -> opcode = -1; - nl -> addrmode = -1; - nl -> addr = as -> addr; - nl -> dpval = as -> dpval; - nl -> prev = cl; - if (!(cl -> next)) - as -> source_tail = nl; - nl -> next = cl -> next; - cl -> next = nl; + // pass 1 only - construct the lines and parse them + for (lc = 0; lc < m -> numlines; lc++) + { + nl = lwasm_alloc(sizeof(lwasm_line_t)); + nl -> text = lwasm_strdup(linebuff); + nl -> lineno = lc + 1; + nl -> filename = m -> name; + nl -> next = NULL; + nl -> prev = as -> linestail; + nl -> err = NULL; + nl -> fsize = 0; + nl -> sym = NULL; + nl -> bytes = NULL; + nl -> codelen = 0; + nl -> codesize = 0; + nl -> nocodelen = 0; + nl -> addrset = 0; + nl -> symaddr = -1; + if (as -> linestail) + as -> linestail -> next = nl; + as -> linestail = nl; + if (!(as -> lineshead)) + as -> lineshead = nl; - buffloc = 0; - c = 0; - while (ml -> linetext[c]) - { - int ch; - ch = ml -> linetext[c++]; - if (ch == '{') + bloc = blen = 0; + linebuff = NULL; + for (p2 = m -> lines[lc]; *p2; p2++) { - int v = 0; - again: - ch = ml -> linetext[c++]; - if (!ch) + if (*p2 == '\\' && isdigit(p2[1])) { - c--; + int n; + + p2++; + n = *p2 - '0'; + if (n == 0) + { + for (p3 = m -> name; p3; p3++) + macro_add_to_buff(&linebuff, &bloc, &blen, *p3); + continue; + } + if (n < 1 || n > nargs) + continue; + for (p3 = args[n]; p3; p3++) + macro_add_to_buff(&linebuff, &bloc, &blen, *p3); continue; } - if (ch >= '0' && ch <= '9') - { - v = v * 10 + (ch - '0'); - goto again; - } - if (ch == '}') + else if (*p2 == '{') { - v--; - if (v < nargs) + int n = 0, n2; + p2++; + while (*p2 && isdigit(*p2)) { - char *t; - for (t = args[v]; *t; t++) - { - macro_add_to_buff(&buff, &buffloc, &bufflen, *t); - } + n2 = *p2 - '0'; + if (n2 < 0 || n2 > 9) + n2 = 0; + n = n * 10 + n2; + p2++; } + if (*p2 == '}') + p2++; + + if (n == 0) + { + for (p3 = m -> name; p3; p3++) + macro_add_to_buff(&linebuff, &bloc, &blen, *p3); + continue; + } + if (n < 1 || n > nargs) + continue; + for (p3 = args[n]; p3; p3++) + macro_add_to_buff(&linebuff, &bloc, &blen, *p3); continue; } else - continue; - } - else if (ch == '\\' && ml -> linetext[c]) - { - ch = ml -> linetext[c++]; - if (ch >= '1' && ch <= '9') { - ch -= '1'; - if (ch < nargs) - { - char *t; - for (t = args[ch]; *t; t++) - { - macro_add_to_buff(&buff, &buffloc, &bufflen, *t); - } - } - } - else - { - c--; - macro_add_to_buff(&buff, &buffloc, &bufflen, '\\'); + macro_add_to_buff(&linebuff, &bloc, &blen, *p2); } } - else - { - macro_add_to_buff(&buff, &buffloc, &bufflen, ch); - } + + nl -> text = linebuff; + + lwasm_parse_line(as, nl); + if (as -> endseen) + break; + } - macro_add_to_buff(&buff, &buffloc, &bufflen, 0); - nl -> line = strdup(buff); + } + + // restore context from before the macro was called + as -> context = oldcontext; - resolve_insn(as, nl); - cl = nl; + // clean up + while (nargs) + { + lwasm_free(args[--nargs]); } - if (buff) - free(buff); + lwasm_free(args); + + // indicate a macro was expanded + return 0; }