view src/parse.c @ 37:538e15927776

Added symbol handling to expression subsystem; adpated instruction handlers to the new scheme; misc fixes
author lost
date Sat, 03 Jan 2009 04:20:49 +0000
parents 99e3b3310bac
children 9bd584bb6296
line wrap: on
line source

/*
parse.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 the general parser
*/

#define __parse_c_seen__

#include <ctype.h>
#include <string.h>

#include "lwasm.h"
#include "instab.h"
#include "util.h"

// parse a line and despatch to the appropriate handlers for opcodes
int lwasm_parse_line(asmstate_t *as, lwasm_line_t *l)
{
	char *p, *p2;
	char *opc;
	int opnum;
	char *sym;
	
	p = l -> text;
	
	if (!*p)
	{
		as -> context += 1;
		return 0;
	}
	
	if (!isspace(*p) && *p != '*' && *p != ';')
	{
		// we have a symbol specified here
		// parse it and define
		// need to handle local symbols here...
		for (p2 = p; *p2 && !isspace(*p2); p2++)
			/* do nothing */ ;
		
		sym = lwasm_alloc((p2 - p) + 1);
		sym[p2 - p] = '\0';
		memcpy(sym, p, p2 - p);
		
		l -> sym = sym;
		// have a symbol; now determine if it is valid and register it
		// at the current address of the line
		if (lwasm_register_symbol(as, l, sym, as -> addr) < 0)
			l -> sym = NULL;
	}
	else
	{
		while (*p && isspace(*p))
			(*p)++;
		if (!*p)
		{
			as -> context += 1;
			return 0;
		}
	}

	// skip white space
	while (*p && isspace(*p))
		p++;
	
	// if comment or end of line, return
	if (!*p || *p == '*' || *p == ';')
	{
		lwasm_free(l -> sym);
		return 0;
	}
	
	// parse the opcode
	for (p2 = p; *p2 && !isspace(*p2); p2++)
		/* do nothing */ ;
	
	opc = lwasm_alloc((p2 - p) + 1);
	memcpy(opc, p, p2 - p);
	opc[p2 - p] = '\0';

	// skip intervening whitespace if present
	while (*p2 && isspace(*p2))
		p2++;

	// check for macro (pass 1)
	
	// look up instruction in insn table
	for (opnum = 0; instab[opnum].opcode; opnum++)
	{
		if (!strcasecmp(instab[opnum].opcode, opc))
			break;
	}
	
	if (!(instab[opnum].opcode) || !(instab[opnum].fn))
	{
		// invalid operation code, throw error
		register_error(as, l, 1, "Invalid operation code '%s'", opc);
		lwasm_free(l -> sym);
		lwasm_free(opc);
		return -1;
	}

	// dispatch handler
	(instab[opnum].fn)(as, l, &p2, opnum);
	
	lwasm_free(opc);
	lwasm_free(sym);
}