~ndiddy/a65

f5e06112bef6f169a9e239d6d0b87ea2034e5a99 — Nathan Misner 1 year, 8 months ago 16192d4
improved error handling
6 files changed, 87 insertions(+), 15 deletions(-)

M a65.c
M a65.h
M a65eval.c
M a65util.c
M a65util.h
M readme.txt
M a65.c => a65.c +22 -9
@@ 64,7 64,7 @@ char errcode, line[MAXLINE + 1], title[MAXLINE];
int pass = 0;
int eject, filesp, forwd, forceabs, listhex;
unsigned address, argattr, bytes, errors, listleft, obj[MAXLINE], pagelen, pc;
FILE *filestk[FILES], *source;
FILE_INFO filestk[FILES], *source;
TOKEN token;

/* Static function definitions: */


@@ 110,13 110,21 @@ int main(int argc, char **argv) {
				warning(BADOPT);
			}
		}
		else if (filestk[0]) warning(TWOASM);
		else if (!(filestk[0] = fopen(*argv,"r"))) fatal_error(ASMOPEN);
		else if (filestk[0].fp) warning(TWOASM);
		else {
			filestk[0].fp = fopen(*argv, "r");
			if (!filestk[0].fp) {
				fatal_error(ASMOPEN);
			}
			strcpy(filestk[0].filename, *argv);
			filestk[0].linenum = 1;
		}
    }
    if (!filestk[0]) fatal_error(NOASM);
    if (!filestk[0].fp) fatal_error(NOASM);

    while (++pass < 3) {
		fseek(source = filestk[0],0L,0);  done = off = FALSE;
		fseek(source = filestk[0].fp,0L,0);  done = off = FALSE;
		filestk[0].linenum = 1;
		errors = filesp = ifsp = pagelen = pc = 0;  title[0] = '\0';
		while (!done) {
			errcode = ' ';


@@ 135,7 143,7 @@ int main(int argc, char **argv) {
		}
    }

    fclose(filestk[0]);  lclose();  bclose();
    fclose(filestk[0].fp);  lclose();  bclose();

    if (errors) printf("%d Error(s)\n",errors);
    else printf("No Errors\n");


@@ 192,7 200,7 @@ static void asm_line() {
		else normal_op();
		while ((i = popc()) != '\n') if (i != ' ') error('T');
    }
    source = filestk[filesp];
    source = filestk[filesp].fp;
    return;
}



@@ 434,8 442,13 @@ static void pseudo_op() {
		listhex = FALSE;  do_label();
		if ((lex() -> attr & TYPE) == STR) {
			if (++filesp == FILES) fatal_error(FLOFLOW);
			if (!(filestk[filesp] = fopen(token.sval,"r"))) {
				--filesp;  error('V');
			filestk[filesp].fp = fopen(token.sval, "r");
			if (!filestk[filesp].fp) {
				--filesp; error('V');
			}
			else {
				strcpy(filestk[filesp].filename, token.sval);
				filestk[filesp].linenum = 0;
			}
		}
		else error('S');

M a65.h => a65.h +7 -0
@@ 148,6 148,13 @@ typedef enum {
#define	LDXY		9
#define	INCOP		10

/* Line assembler (a65.c) file struct */
typedef struct {
	FILE *fp;
	char filename[MAXLINE];
	int linenum;
} FILE_INFO;

/*  Opcode argument field parser (A65EVAL.C) attribute bit masks:	*/

#define	ARGA		040	/*  A register specified.		*/

M a65eval.c => a65eval.c +4 -2
@@ 60,7 60,8 @@ arithmetic expressions.
extern char line[];
extern int filesp, forwd, forceabs, pass;
extern unsigned argattr, pc;
extern FILE *filestk[], *source;
extern FILE_INFO filestk[];
extern FILE *source;
extern TOKEN token;

/* Static function definitions: */


@@ 481,13 482,14 @@ void pushc(char c) {
/*  EOF	has been reached on the main source file, zero otherwise.	*/

int newline() {
	filestk[filesp].linenum++;
    oldc = '\0';  lptr = line;
    oldt = eol = FALSE;
    while (feof(source)) {
		if (ferror(source)) fatal_error(ASMREAD);
		if (filesp) {
			fclose(source);
			source = filestk[--filesp];
			source = filestk[--filesp].fp;
		}
		else return TRUE;
    }

M a65util.c => a65util.c +32 -2
@@ 67,8 67,9 @@ This module contains the following utility packages:
/*  Get access to global mailboxes defined in A65.C:			*/

extern char errcode, line[], title[];
extern int eject, listhex;
extern int eject, filesp, listhex, pass;
extern unsigned address, bytes, errors, listleft, obj[], pagelen;
extern FILE_INFO filestk[];

/*  The symbol table is a binary tree of variable-length blocks drawn	*/
/*  from the heap with the calloc() function.  The root pointer lives	*/


@@ 423,7 424,36 @@ static void record() {
/*  is adjusted.							*/

void error(char code) {
    if (errcode == ' ') { errcode = code;  ++errors; }
	char *description;

    if (errcode == ' ') {
		errcode = code;
		++errors;
		if (pass == 2) {
			switch (code) {
			case '*':	description = ERR_STATEMENT;	break;
			case '(':	description = ERR_PAREN;		break;
			case '"':	description = ERR_QUOTE;		break;
			case 'A':	description = ERR_A;			break;
			case 'B':	description = ERR_B;			break;
			case 'D':	description = ERR_D;			break;
			case 'E':	description = ERR_E;			break;
			case 'I':	description = ERR_I;			break;
			case 'L':	description = ERR_L;			break;
			case 'M':	description = ERR_M;			break;
			case 'O':	description = ERR_O;			break;
			case 'P':	description = ERR_P;			break;
			case 'R':	description = ERR_R;			break;
			case 'S':	description = ERR_S;			break;
			case 'T':	description = ERR_T;			break;
			case 'U':	description = ERR_U;			break;
			case 'V':	description = ERR_V;			break;
			default:	description = ERR_UNKNOWN;		break;
			}

			printf("%s:%d: %c -- %s\n", filestk[filesp].filename, filestk[filesp].linenum, code, description);
		}
	}
    return;
}


M a65util.h => a65util.h +20 -0
@@ 59,6 59,26 @@ utility packages:

#include "a65.h"

/* Error code descriptions */
#define ERR_STATEMENT	"Illegal or missing statement"
#define ERR_PAREN		"Parenthesis imbalance"
#define ERR_QUOTE		"Missing quotation mark"
#define ERR_A			"Illegal addressing mode"
#define ERR_B			"Branch target too distant"
#define ERR_D			"Illegal digit"
#define ERR_E			"Illegal expression"
#define ERR_I			"IF-ENDI imbalance"
#define ERR_L			"Illegal label"
#define ERR_M			"Multiply defined label"
#define ERR_O			"Illegal opcode"
#define ERR_P			"Phasing error"
#define ERR_R			"Illegal register"
#define ERR_S			"Illegal syntax"
#define ERR_T			"Too many arguments"
#define ERR_U			"Undefined label"
#define ERR_V			"Illegal value"
#define ERR_UNKNOWN		"Unknown error"

/*  Add new symbol to symbol table.  Returns pointer to symbol even if	*/
/*  the symbol already exists.  If there's not enough memory to store	*/
/*  the new symbol, a fatal error occurs.								*/

M readme.txt => readme.txt +2 -2
@@ 33,8 33,8 @@ your workflow.
- Change the assembler to output binary files instead of Intel HEX - done
- Allow for forcing loads/stores to not be optimized for zero page - done (! operator)
- Add a "MSG" statement that prints out arbitrary strings and symbols
- Print the error messages to stdout instead of the assembler listing
- Add a makefile for our GNU/Linux and Mac OS X using friends
- Print the error messages to stdout instead of the assembler listing - done
- Add a makefile for our GNU/Linux and Mac OS X using friends - done
- Update A65.DOC with the new changes

=====Future goals=====