Added PLASMA support for single-level source code include statement, without needing m4. Usage: include "yourfile.pla"

This commit is contained in:
Martin Haye 2015-09-13 09:29:42 -07:00
parent a4e87954a3
commit fa6bdfb86d
5 changed files with 80 additions and 13 deletions

View File

@ -11,6 +11,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <string.h>
#include "tokens.h" #include "tokens.h"
#include "symbols.h" #include "symbols.h"
@ -18,7 +19,12 @@ char *statement, *tokenstr, *scanpos = "";
t_token scantoken, prevtoken; t_token scantoken, prevtoken;
int tokenlen; int tokenlen;
long constval; long constval;
FILE* inputfile;
char *filename;
int lineno = 0; int lineno = 0;
FILE* outer_inputfile = NULL;
char* outer_filename;
int outer_lineno;
t_token keywords[] = { t_token keywords[] = {
IF_TOKEN, 'I', 'F', IF_TOKEN, 'I', 'F',
ELSE_TOKEN, 'E', 'L', 'S', 'E', ELSE_TOKEN, 'E', 'L', 'S', 'E',
@ -43,6 +49,7 @@ t_token keywords[] = {
DEF_TOKEN, 'D', 'E', 'F', DEF_TOKEN, 'D', 'E', 'F',
EXPORT_TOKEN, 'E', 'X', 'P', 'O', 'R', 'T', EXPORT_TOKEN, 'E', 'X', 'P', 'O', 'R', 'T',
IMPORT_TOKEN, 'I', 'M', 'P', 'O', 'R', 'T', IMPORT_TOKEN, 'I', 'M', 'P', 'O', 'R', 'T',
INCLUDE_TOKEN, 'I', 'N', 'C', 'L', 'U', 'D', 'E',
RETURN_TOKEN, 'R', 'E', 'T', 'U', 'R', 'N', RETURN_TOKEN, 'R', 'E', 'T', 'U', 'R', 'N',
END_TOKEN, 'E', 'N', 'D', END_TOKEN, 'E', 'N', 'D',
DONE_TOKEN, 'D', 'O', 'N', 'E', DONE_TOKEN, 'D', 'O', 'N', 'E',
@ -62,7 +69,7 @@ void parse_error(char *errormsg)
{ {
char *error_carrot = statement; char *error_carrot = statement;
fprintf(stderr, "\n%4d: %s\n ", lineno, statement); fprintf(stderr, "\n%s %4d: %s\n%*s ", filename, lineno, statement, (int)strlen(filename), "");
for (error_carrot = statement; error_carrot != tokenstr; error_carrot++) for (error_carrot = statement; error_carrot != tokenstr; error_carrot++)
putc(*error_carrot == '\t' ? '\t' : ' ', stderr); putc(*error_carrot == '\t' ? '\t' : ' ', stderr);
fprintf(stderr, "^\nError: %s\n", errormsg); fprintf(stderr, "^\nError: %s\n", errormsg);
@ -79,7 +86,9 @@ t_token scan(void)
/* /*
* Scan for token based on first character. * Scan for token based on first character.
*/ */
if (*scanpos == '\0' || *scanpos == '\n' || *scanpos == ';') if (scantoken == EOF_TOKEN)
;
else if (*scanpos == '\0' || *scanpos == '\n' || *scanpos == ';')
scantoken = EOL_TOKEN; scantoken = EOL_TOKEN;
else if ((scanpos[0] >= 'a' && scanpos[0] <= 'z') else if ((scanpos[0] >= 'a' && scanpos[0] <= 'z')
|| (scanpos[0] >= 'A' && scanpos[0] <= 'Z') || (scanpos[0] >= 'A' && scanpos[0] <= 'Z')
@ -385,6 +394,14 @@ int scan_lookahead(void)
char inputline[512]; char inputline[512];
int next_line(void) int next_line(void)
{ {
int len;
t_token token;
char* new_filename;
if (inputfile == NULL) {
// First-time init
inputfile = stdin;
filename = "<stdin>";
}
if (*scanpos == ';') if (*scanpos == ';')
{ {
statement = ++scanpos; statement = ++scanpos;
@ -392,12 +409,61 @@ int next_line(void)
} }
else else
{ {
gets(inputline);
lineno++;
statement = inputline; statement = inputline;
scanpos = inputline; scanpos = inputline;
// Read next line from the current file, and strip newline from the end.
if (fgets(inputline, 512, inputfile) == NULL) {
inputline[0] = 0;
// At end of file, return to previous file if any, else return EOF_TOKEN
if (outer_inputfile != NULL) {
fclose(inputfile);
free(filename);
inputfile = outer_inputfile;
filename = outer_filename;
lineno = outer_lineno - 1; // -1 because we're about to incr again
outer_inputfile = NULL;
}
else {
scantoken = EOF_TOKEN;
return EOF_TOKEN;
}
}
len = strlen(inputline);
if (len > 0 && inputline[len-1] == '\n')
inputline[len-1] = '\0';
lineno++;
scantoken = EOL_TOKEN; scantoken = EOL_TOKEN;
printf("; %03d: %s\n", lineno, inputline); printf("; %s: %04d: %s\n", filename, lineno, inputline);
} }
return (scan()); token = scan();
// Handle single level of file inclusion
if (token == INCLUDE_TOKEN) {
token = scan();
if (token != STRING_TOKEN) {
parse_error("Missing include filename");
scantoken = EOF_TOKEN;
return EOF_TOKEN;
}
if (outer_inputfile != NULL) {
parse_error("Only one level of includes allowed");
scantoken = EOF_TOKEN;
return EOF_TOKEN;
}
outer_inputfile = inputfile;
outer_filename = filename;
outer_lineno = lineno;
new_filename = malloc(tokenlen-1);
strncpy(new_filename, (char*)constval, tokenlen-2);
new_filename[tokenlen-2] = 0;
inputfile = fopen(new_filename, "r");
if (inputfile == NULL) {
parse_error("Error opening include file");
scantoken = EOF_TOKEN;
return EOF_TOKEN;
}
filename = new_filename;
lineno = 0;
return next_line();
}
return token;
} }

View File

@ -41,20 +41,20 @@ $(CMD): cmd.pla cmdstub.s $(PLVM) $(PLASM)
acme --setpc 8192 -o $(CMD) cmdstub.s acme --setpc 8192 -o $(CMD) cmdstub.s
TESTLIB\#FE1000: testlib.pla $(PLVM) $(PLASM) TESTLIB\#FE1000: testlib.pla $(PLVM) $(PLASM)
m4 < testlib.pla |./$(PLASM) -AM > testlib.a ./$(PLASM) -AM < testlib.pla > testlib.a
acme --setpc 4094 -o TESTLIB\#FE1000 testlib.a acme --setpc 4094 -o TESTLIB\#FE1000 testlib.a
test: test.pla TESTLIB\#FE1000 $(PLVM) $(PLASM) test: test.pla TESTLIB\#FE1000 $(PLVM) $(PLASM)
m4 < test.pla | ./$(PLASM) -AM > test.a ./$(PLASM) -AM < test.pla > test.a
acme --setpc 4094 -o TEST\#FE1000 test.a acme --setpc 4094 -o TEST\#FE1000 test.a
./$(PLVM) TEST ./$(PLVM) TEST
debug: test.pla TESTLIB $(PLVM) $(PLASM) debug: test.pla TESTLIB $(PLVM) $(PLASM)
m4 < test.pla | ./$(PLASM) -AM > test.a ./$(PLASM) -AM < test.pla > test.a
acme --setpc 4094 -o TEST\#FE1000 test.a acme --setpc 4094 -o TEST\#FE1000 test.a
./$(PLVM) -s TEST MAIN ./$(PLVM) -s TEST MAIN
hello: hello.pla $(PLVM) $(PLASM) hello: hello.pla $(PLVM) $(PLASM)
m4 < hello.pla | ./$(PLASM) -AM > hello.a ./$(PLASM) -AM < hello.pla > hello.a
acme --setpc 4094 -o HELLO\#FE1000 hello.a acme --setpc 4094 -o HELLO\#FE1000 hello.a
./$(PLVM) HELLO ./$(PLVM) HELLO

View File

@ -11,8 +11,8 @@
// //
// Include all imported modules and their data/functions. // Include all imported modules and their data/functions.
// //
include(cmdsys.plh) include "cmdsys.plh"
include(testlib.plh) include "testlib.plh"
// //
// Structure definition. // Structure definition.
// //

View File

@ -11,7 +11,7 @@
// //
// Include all imported modules and their data/functions. // Include all imported modules and their data/functions.
// //
include(cmdsys.plh) include "cmdsys.plh"
// //
// Module data. // Module data.
// //

View File

@ -113,6 +113,7 @@
#define COMMA_TOKEN TOKEN(',') #define COMMA_TOKEN TOKEN(',')
#define COMMENT_TOKEN TOKEN(';') #define COMMENT_TOKEN TOKEN(';')
#define EOL_TOKEN TOKEN(0) #define EOL_TOKEN TOKEN(0)
#define INCLUDE_TOKEN TOKEN(0x7E)
#define EOF_TOKEN TOKEN(0x7F) #define EOF_TOKEN TOKEN(0x7F)
typedef unsigned char t_token; typedef unsigned char t_token;