Mercurial > hg-old > index.cgi
diff src/macro.c @ 0:57495da01900
Initial checking of LWASM
author | lost |
---|---|
date | Fri, 03 Oct 2008 02:44:20 +0000 |
parents | |
children | 34568fab6058 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/macro.c Fri Oct 03 02:44:20 2008 +0000 @@ -0,0 +1,215 @@ +/* + * macro.c + * + * stuff associated with macro processing + */ + +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include "lwasm.h" + +extern void resolve_insn(asmstate_t *as, sourceline_t *cl); + +void pseudo_macro(asmstate_t *as, sourceline_t *cl, char **optr) +{ + macrotab_t *m; + + if (as -> inmacro) + { + errorp1(ERR_MACRO); + return; + } + as -> inmacro = 1; + if (as -> passnum != 1) + return; + + for (m = as -> macros; m; m = m -> next) + { + if (!strcmp(m -> name, cl -> symstr)) + break; + } + if (m) + { + errorp1(ERR_DUPSYM); + return; + } + m = calloc(sizeof(macrotab_t), 1); + m -> name = strdup(cl -> symstr); + m -> next = as -> macros; + as -> macros = m; + cl -> hassym = 0; + while (**optr && !isspace(**optr)) + (*optr)++; + cl -> macrodef = 1; +} + +void pseudo_endm(asmstate_t *as, sourceline_t *cl, char **optr) +{ + if (!as -> inmacro) + { + errorp1(ERR_ENDM); + return; + } + + as -> inmacro = 0; + cl -> macrodef = 1; +} + +int add_macro_line(asmstate_t *as, sourceline_t *cl, 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; + return 1; +} + +void macro_add_to_buff(char **buff, int *loc, int *len, char c) +{ + if (*loc == *len) + { + *buff = realloc(*buff, *len + 32); + *len += 32; + } + (*buff)[(*loc)++] = c; +} + +// this is just like a regular operation function +/* +macro args are references by "\n" where 1 <= n <= 9 +or by "\{n}"; a \ can be included by writing \\ +*/ +void expand_macro(asmstate_t *as, sourceline_t *cl, char **optr) +{ + char **args = NULL; + int nargs = 0; + int c; + sourceline_t *nl; + int nline = 1; + macrotab_t *m; + macroline_t *ml; + char *buff = NULL; + int bufflen = 0, buffloc; + + m = cl -> macro; + + // step the first: parse arguments + while (**optr && !isspace(**optr)) + { + c = 0; + while ((*optr)[c] && !isspace((*optr)[c]) && (*optr)[c] != ',') + { + c++; + } + 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) + { + 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; + + buffloc = 0; + c = 0; + while (ml -> linetext[c]) + { + int ch; + ch = ml -> linetext[c++]; + if (ch == '{') + { + int v = 0; + again: + ch = ml -> linetext[c++]; + if (!ch) + { + c--; + continue; + } + if (ch >= '0' && ch <= '9') + { + v = v * 10 + (ch - '0'); + goto again; + } + if (ch == '}') + { + v--; + if (v < nargs) + { + char *t; + for (t = args[v]; *t; t++) + { + macro_add_to_buff(&buff, &buffloc, &bufflen, *t); + } + } + 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, '\\'); + } + } + else + { + macro_add_to_buff(&buff, &buffloc, &bufflen, ch); + } + } + macro_add_to_buff(&buff, &buffloc, &bufflen, 0); + nl -> line = strdup(buff); + + resolve_insn(as, nl); + cl = nl; + } + if (buff) + free(buff); +}