view 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 source

/*
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;
}