Mercurial > hg-old > index.cgi
view src/macro.c @ 8:f1df096aa76f 1.1
Tagged 1.1 bugfix release
author | lost |
---|---|
date | Sun, 04 Jan 2009 05:46:07 +0000 |
parents | 34568fab6058 |
children | 035b95a3690f |
line wrap: on
line source
/* macro.c Copyright © 2008 William Astle This file is part of LWASM. LWASM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Contains 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); }