Mercurial > hg-old > index.cgi
diff lwasm/struct.c @ 254:c7a41b4c89b3 2.x
Added struct support to LWASM
author | lost |
---|---|
date | Sat, 19 Dec 2009 06:38:43 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwasm/struct.c Sat Dec 19 06:38:43 2009 +0000 @@ -0,0 +1,174 @@ +/* +struct.c +Copyright © 2009 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 structure definition. + +Structures have their own name space. Macros will shadow structures so it's +a good idea to make sure no structures are name the same as macros. +*/ + +#include <config.h> + +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include "lwasm.h" +#include "instab.h" +#include "util.h" + +OPFUNC(pseudo_struct) +{ + structtab_t *m; + + // actually define a structure + if (as -> instruct) + { + register_error(as, l, 1, "Attempt to define a structure inside a structure"); + return; + } + + as -> instruct = 1; + + // don't actually do anything if not pass 1 + if (as -> passnum != 1) + return; + + + if (!l -> sym) + { + register_error(as, l, 1, "Structure definition with no effect - no symbol"); + return; + } + + // search for macro by same name... + for (m = as -> structs; m; m = m -> next) + { + if (!strcmp(m -> name, l -> sym)) + break; + } + if (m) + { + register_error(as, l, 1, "Duplicate structure definition"); + return; + } + + m = lwasm_alloc(sizeof(structtab_t)); + m -> name = lwasm_strdup(l -> sym); + m -> next = as -> structs; + m -> fields = NULL; + m -> size = 0; + as -> structs = m; + as -> cstruct = m; + + while (**p && !isspace(**p)) + (*p)++; +} + + + +pseudo_endstruct_aux(asmstate_t *as, lwasm_line_t *l, struct struct_sym_e *e, const char *prefix, int *coff) +{ + char *symname = NULL; + + while (e) + { + if (e -> name) + 0 == asprintf(&symname, "%s.%s", prefix, e -> name); + else + 0 == asprintf(&symname, "%s.___%d", prefix, *coff); + + // register symbol "symname" as global at coff + lwasm_register_symbol(as, l, symname, *coff, SYMBOL_NOCHECK); + + if (e -> substruct) + { + char * t; + 0 == asprintf(&t, "sizeof{%s}", symname); + lwasm_register_symbol(as, l, t, e -> substruct -> size, SYMBOL_NOCHECK); + lwasm_free(t); + pseudo_endstruct_aux(as, l, e -> substruct -> fields, symname, coff); + } + else + { + *coff += e -> size; + } + + lwasm_free(symname); + e = e -> next; + } +} + +OPFUNC(pseudo_endstruct) +{ + int coff = 0; + char *t; + + as -> instruct = 0; + + if (as -> passnum != 1) + return; + + // now register the global symbols for the structure + // this is a recursive process + 0 == asprintf(&t, "sizeof{%s}", as -> cstruct -> name); + lwasm_register_symbol(as, l, t, as -> cstruct -> size, SYMBOL_NOCHECK); + lwasm_free(t); + + pseudo_endstruct_aux(as, l, as -> cstruct -> fields, as -> cstruct -> name, &coff); +} + + +int expand_struct(asmstate_t *as, lwasm_line_t *l, char **p, char *opc) +{ + structtab_t *s; + int addr; + char *t; + + if (as -> passnum != 1) + return 0; + + for (s = as -> structs; s; s = s -> next) + { + if (!strcmp(opc, s -> name)) + break; + } + if (!s) + return -1; + + if (!(l -> sym)) + { + register_error(as, l, 1, "Cannot declare a structure without a symbol name."); + return; + } + + l -> nocodelen = s -> size; + + addr = as -> addr; + as -> addr += s -> size; + + // now register the global symbols for the structure + // this is a recursive process + 0 == asprintf(&t, "sizeof{%s}", l -> sym); + lwasm_register_symbol(as, l, t, s -> size, SYMBOL_NOCHECK); + lwasm_free(t); + + pseudo_endstruct_aux(as, l, s -> fields, l -> sym, &addr); + + return 0; +}