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=====