mirror of
https://github.com/badvision/lawless-legends.git
synced 2025-08-06 09:25:06 +00:00
Initial import of PLASMA compiler and portable VM
This commit is contained in:
775
PLASMA/src/codegen.c
Executable file
775
PLASMA/src/codegen.c
Executable file
@@ -0,0 +1,775 @@
|
||||
#include <stdio.h>
|
||||
#include "tokens.h"
|
||||
#include "symbols.h"
|
||||
#include "codegen.h"
|
||||
/*
|
||||
* Symbol table and fixup information.
|
||||
*/
|
||||
static int consts = 0;
|
||||
static int externs = 0;
|
||||
static int globals = 0;
|
||||
static int locals = 0;
|
||||
static int defs = 0;
|
||||
static int codetags = 0;
|
||||
static int fixups = 0;
|
||||
static char idconst_name[1024][17];
|
||||
static int idconst_value[1024];
|
||||
static char idglobal_name[1024][17];
|
||||
static int idglobal_type[1024];
|
||||
static int idglobal_tag[1024];
|
||||
static int localsize = 0;
|
||||
static char idlocal_name[128][17];
|
||||
static int idlocal_type[128];
|
||||
static int idlocal_offset[128];
|
||||
static char fixup_size[255];
|
||||
static int fixup_type[255];
|
||||
static int fixup_tag[255];
|
||||
#define FIXUP_BYTE 0x00
|
||||
#define FIXUP_WORD 0x80
|
||||
int id_match(char *name, int len, char *id)
|
||||
{
|
||||
if (len == id[0])
|
||||
{
|
||||
if (len > 16) len = 16;
|
||||
while (len--)
|
||||
{
|
||||
if (name[len] != id[1 + len])
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
int idconst_lookup(char *name, int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < consts; i++)
|
||||
if (id_match(name, len, &(idconst_name[i][0])))
|
||||
return (i);
|
||||
return (-1);
|
||||
}
|
||||
int idlocal_lookup(char *name, int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < locals; i++)
|
||||
if (id_match(name, len, &(idlocal_name[i][0])))
|
||||
return (i);
|
||||
return (-1);
|
||||
}
|
||||
int idglobal_lookup(char *name, int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < globals; i++)
|
||||
if (id_match(name, len, &(idglobal_name[i][0])))
|
||||
return (i);
|
||||
return (-1);
|
||||
}
|
||||
int idconst_add(char *name, int len, int value)
|
||||
{
|
||||
if (consts > 1024)
|
||||
{
|
||||
printf("Constant count overflow\n");
|
||||
return (0);
|
||||
}
|
||||
char c = name[len];
|
||||
name[len] = '\0';
|
||||
emit_idconst(name, value);
|
||||
name[len] = c;
|
||||
idconst_name[consts][0] = len;
|
||||
if (len > 16) len = 16;
|
||||
while (len--)
|
||||
idconst_name[consts][1 + len] = name[len];
|
||||
idconst_value[consts] = value;
|
||||
consts++;
|
||||
return (1);
|
||||
}
|
||||
int idlocal_add(char *name, int len, int type, int size)
|
||||
{
|
||||
if (localsize > 255)
|
||||
{
|
||||
printf("Local variable size overflow\n");
|
||||
return (0);
|
||||
}
|
||||
char c = name[len];
|
||||
name[len] = '\0';
|
||||
emit_idlocal(name, localsize);
|
||||
name[len] = c;
|
||||
idlocal_name[locals][0] = len;
|
||||
if (len > 16) len = 16;
|
||||
while (len--)
|
||||
idlocal_name[locals][1 + len] = name[len];
|
||||
idlocal_type[locals] = type | LOCAL_TYPE;
|
||||
idlocal_offset[locals] = localsize;
|
||||
localsize += size;
|
||||
locals++;
|
||||
return (1);
|
||||
}
|
||||
int idglobal_add(char *name, int len, int type, int size)
|
||||
{
|
||||
if (globals > 1024)
|
||||
{
|
||||
printf("Global variable count overflow\n");
|
||||
return (0);
|
||||
}
|
||||
char c = name[len];
|
||||
name[len] = '\0';
|
||||
name[len] = c;
|
||||
idglobal_name[globals][0] = len;
|
||||
if (len > 16) len = 16;
|
||||
while (len--)
|
||||
idglobal_name[globals][1 + len] = name[len];
|
||||
idglobal_type[globals] = type;
|
||||
if (!(type & EXTERN_TYPE))
|
||||
{
|
||||
emit_idglobal(globals, size, name);
|
||||
idglobal_tag[globals] = globals++;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\t\t\t\t\t; %s -> X%03d\n", &idglobal_name[globals][1], externs);
|
||||
idglobal_tag[globals++] = externs++;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
int id_add(char *name, int len, int type, int size)
|
||||
{
|
||||
return ((type & LOCAL_TYPE) ? idlocal_add(name, len, type, size) : idglobal_add(name, len, type, size));
|
||||
}
|
||||
int idfunc_add(char *name, int len, int type, int tag)
|
||||
{
|
||||
if (globals > 1024)
|
||||
{
|
||||
printf("Global variable count overflow\n");
|
||||
return (0);
|
||||
}
|
||||
idglobal_name[globals][0] = len;
|
||||
if (len > 16) len = 16;
|
||||
while (len--)
|
||||
idglobal_name[globals][1 + len] = name[len];
|
||||
idglobal_type[globals] = type;
|
||||
idglobal_tag[globals++] = tag;
|
||||
if (type & EXTERN_TYPE)
|
||||
printf("\t\t\t\t\t; %s -> X%03d\n", &idglobal_name[globals - 1][1], tag);
|
||||
return (1);
|
||||
}
|
||||
int idfunc_set(char *name, int len, int type)
|
||||
{
|
||||
int i;
|
||||
if (((i = idglobal_lookup(name, len)) >= 0) && (idglobal_type[i] & FUNC_TYPE))
|
||||
{
|
||||
idglobal_type[i] = type;
|
||||
return (idglobal_type[i]);
|
||||
}
|
||||
parse_error("Undeclared identifier");
|
||||
return (0);
|
||||
}
|
||||
void idglobal_size(int type, int size, int constsize)
|
||||
{
|
||||
if (size > constsize)
|
||||
emit_data(0, 0, 0, size - constsize);
|
||||
else if (size)
|
||||
emit_data(0, 0, 0, size);
|
||||
}
|
||||
int idlocal_size(void)
|
||||
{
|
||||
return (localsize);
|
||||
}
|
||||
void idlocal_reset(void)
|
||||
{
|
||||
locals = 0;
|
||||
localsize = 2;
|
||||
}
|
||||
int id_tag(char *name, int len)
|
||||
{
|
||||
int i;
|
||||
if ((i = idlocal_lookup(name, len)) >= 0)
|
||||
return (idlocal_offset[i]);
|
||||
if ((i = idglobal_lookup(name, len)) >= 0)
|
||||
return (idglobal_tag[i]);
|
||||
parse_error("Undeclared identifier");
|
||||
return (-1);
|
||||
}
|
||||
int id_const(char *name, int len)
|
||||
{
|
||||
int i;
|
||||
if ((i = idconst_lookup(name, len)) >= 0)
|
||||
return (idconst_value[i]);
|
||||
parse_error("Undeclared constant");
|
||||
return (0);
|
||||
}
|
||||
int id_type(char *name, int len)
|
||||
{
|
||||
int i;
|
||||
if ((i = idconst_lookup(name, len)) >= 0)
|
||||
return (CONST_TYPE);
|
||||
if ((i = idlocal_lookup(name, len)) >= 0)
|
||||
return (idlocal_type[i] | LOCAL_TYPE);
|
||||
if ((i = idglobal_lookup(name, len)) >= 0)
|
||||
return (idglobal_type[i]);
|
||||
parse_error("Undeclared identifier");
|
||||
return (0);
|
||||
}
|
||||
int tag_new(int type)
|
||||
{
|
||||
if (type & EXTERN_TYPE)
|
||||
return (externs++);
|
||||
if (type & ASM_TYPE)
|
||||
return (globals);
|
||||
if (type & DEF_TYPE)
|
||||
return (defs++);
|
||||
if (type & BRANCH_TYPE)
|
||||
return (codetags++);
|
||||
return globals++;
|
||||
}
|
||||
int fixup_new(int tag, int type, int size)
|
||||
{
|
||||
if (fixups > 255)
|
||||
{
|
||||
printf("External variable count overflow\n");
|
||||
return (0);
|
||||
}
|
||||
fixup_tag[fixups] = tag;
|
||||
fixup_type[fixups] = type;
|
||||
fixup_size[fixups] = size;
|
||||
return (fixups++);
|
||||
}
|
||||
/*
|
||||
* Emit assembly code.
|
||||
*/
|
||||
#define BYTECODE_SEG 2
|
||||
static int outflags = 0;
|
||||
static char *DB = ".BYTE";
|
||||
static char *DW = ".WORD";
|
||||
static char *DS = ".RES";
|
||||
static char LBL = ':';
|
||||
char *tag_string(int tag, int type)
|
||||
{
|
||||
static char str[16];
|
||||
char t;
|
||||
|
||||
if (type & EXTERN_TYPE)
|
||||
t = 'X';
|
||||
else if (type & DEF_TYPE)
|
||||
t = 'C';
|
||||
else if (type & ASM_TYPE)
|
||||
t = 'A';
|
||||
else if (type & BRANCH_TYPE)
|
||||
t = 'B';
|
||||
else
|
||||
t = 'D';
|
||||
sprintf(str, "_%c%03d", t, tag);
|
||||
return str;
|
||||
}
|
||||
void emit_flags(int flags)
|
||||
{
|
||||
outflags = flags;
|
||||
if (outflags & ACME)
|
||||
{
|
||||
DB = "!BYTE";
|
||||
DW = "!WORD";
|
||||
DS = "!FILL";
|
||||
LBL = ' ';
|
||||
}
|
||||
}
|
||||
void emit_header(void)
|
||||
{
|
||||
if (outflags & ACME)
|
||||
printf("; ACME COMPATIBLE OUTPUT\n");
|
||||
else
|
||||
printf("; CA65 COMPATIBLE OUTPUT\n");
|
||||
printf("_SEGBEGIN%c\n", LBL);
|
||||
printf("\t%s\t_SEGEND-_SEGBEGIN\t; LENGTH OF HEADER + CODE/DATA + BYTECODE SEGMENT\n", DW);
|
||||
printf("\t%s\t$DA7E\t\t\t; MAGIC #\n", DW);
|
||||
printf("\t%s\t_SUBSEG\t\t\t; BYTECODE SUB-SEGMENT\n", DW);
|
||||
}
|
||||
void emit_trailer(void)
|
||||
{
|
||||
if (!(outflags & BYTECODE_SEG))
|
||||
emit_bytecode_seg();
|
||||
printf("_SEGEND%c\n", LBL);
|
||||
}
|
||||
char *supper(char *s)
|
||||
{
|
||||
static char su[80];
|
||||
int i;
|
||||
for (i = 0; s[i]; i++)
|
||||
su[i] = toupper(s[i]);
|
||||
su[i] = '\0';
|
||||
return su;
|
||||
}
|
||||
void emit_dci(char *str, int len)
|
||||
{
|
||||
if (len--)
|
||||
{
|
||||
printf("\t; DCI STRING: %s\n", supper(str));
|
||||
printf("\t%s\t$%02X", DB, toupper(*str++) | (len ? 0x80 : 0x00));
|
||||
while (len--)
|
||||
printf(",$%02X", toupper(*str++) | (len ? 0x80 : 0x00));
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
void emit_moddep(char *name, int len)
|
||||
{
|
||||
if (name)
|
||||
emit_dci(name, len);
|
||||
else
|
||||
printf("\t%s\t$00\t\t\t; END OF MODULE DEPENDENCIES\n", DB);
|
||||
}
|
||||
void emit_bytecode_seg(void)
|
||||
{
|
||||
if (!(outflags & BYTECODE_SEG))
|
||||
printf("_SUBSEG%c\t\t\t\t; BYTECODE STARTS\n", LBL);
|
||||
outflags |= BYTECODE_SEG;
|
||||
}
|
||||
void emit_comment(char *s)
|
||||
{
|
||||
printf("\t\t\t\t\t; %s\n", s);
|
||||
}
|
||||
void emit_asm(char *s)
|
||||
{
|
||||
printf("%s\n", s);
|
||||
}
|
||||
void emit_idlocal(char *name, int value)
|
||||
{
|
||||
printf("\t\t\t\t\t; %s -> [%d]\n", name, value);
|
||||
}
|
||||
void emit_idglobal(int tag, int size, char *name)
|
||||
{
|
||||
if (size == 0)
|
||||
printf("_D%03d%c\t\t\t\t\t; %s\n", tag, LBL, name);
|
||||
else
|
||||
printf("_D%03d%c\t%s\t%d\t\t\t; %s\n", tag, LBL, DS, size, name);
|
||||
}
|
||||
void emit_idfunc(int tag, int type, char *name)
|
||||
{
|
||||
printf("%s%c\t\t\t\t\t; %s()\n", tag_string(tag, type), LBL, name);
|
||||
}
|
||||
void emit_idconst(char *name, int value)
|
||||
{
|
||||
printf("\t\t\t\t\t; %s = %d\n", name, value);
|
||||
}
|
||||
int emit_data(int vartype, int consttype, long constval, int constsize)
|
||||
{
|
||||
int datasize, i;
|
||||
char *str;
|
||||
if (consttype == 0)
|
||||
{
|
||||
datasize = constsize;
|
||||
printf("\t%s\t$%02X\n", DS, constsize);
|
||||
}
|
||||
else if (consttype & STRING_TYPE)
|
||||
{
|
||||
datasize = constsize;
|
||||
str = (char *)constval;
|
||||
printf("\t%s\t$%02X\n", DB, --constsize);
|
||||
while (constsize-- > 0)
|
||||
{
|
||||
printf("\t%s\t$%02X", DB, *str++);
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
if (constsize-- > 0)
|
||||
printf(",$%02X", *str++);
|
||||
else
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
else if (consttype & ADDR_TYPE)
|
||||
{
|
||||
if (vartype == WORD_TYPE)
|
||||
{
|
||||
int fixup = fixup_new(constval, consttype, FIXUP_WORD);
|
||||
datasize = 2;
|
||||
if (consttype & EXTERN_TYPE)
|
||||
printf("_F%03d%c\t%s\t0\t\t\t; %s\n", fixup, LBL, DW, tag_string(constval, consttype));
|
||||
else
|
||||
printf("_F%03d%c\t%s\t%s\n", fixup, LBL, DW, tag_string(constval, consttype));
|
||||
}
|
||||
else
|
||||
{
|
||||
int fixup = fixup_new(constval, consttype, FIXUP_BYTE);
|
||||
datasize = 1;
|
||||
if (consttype & EXTERN_TYPE)
|
||||
printf("_F%03d%c\t%s\t0\t\t\t; %s\n", fixup, LBL, DB, tag_string(constval, consttype));
|
||||
else
|
||||
printf("_F%03d%c\t%s\t%s\n", fixup, LBL, DB, tag_string(constval, consttype));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vartype == WORD_TYPE)
|
||||
{
|
||||
datasize = 2;
|
||||
printf("\t%s\t$%04lX\n", DW, constval & 0xFFFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
datasize = 1;
|
||||
printf("\t%s\t$%02lX\n", DB, constval & 0xFF);
|
||||
}
|
||||
}
|
||||
return (datasize);
|
||||
}
|
||||
void emit_codetag(int tag)
|
||||
{
|
||||
printf("_B%03d%c\n", tag, LBL);
|
||||
}
|
||||
void emit_const(int cval)
|
||||
{
|
||||
if (cval == 0)
|
||||
printf("\t%s\t$00\t\t\t; ZERO\n", DB);
|
||||
else if (cval > 0 && cval < 256)
|
||||
printf("\t%s\t$2A,$%02X\t\t\t; CB\t%d\n", DB, cval, cval);
|
||||
else
|
||||
printf("\t%s\t$2C,$%02X,$%02X\t\t; CW\t%d\n", DB, cval&0xFF,(cval>>8)&0xFF, cval);
|
||||
}
|
||||
void emit_lb(void)
|
||||
{
|
||||
printf("\t%s\t$60\t\t\t; LB\n", DB);
|
||||
}
|
||||
void emit_lw(void)
|
||||
{
|
||||
printf("\t%s\t$62\t\t\t; LW\n", DB);
|
||||
}
|
||||
void emit_llb(int index)
|
||||
{
|
||||
printf("\t%s\t$64,$%02X\t\t\t; LLB\t[%d]\n", DB, index, index);
|
||||
}
|
||||
void emit_llw(int index)
|
||||
{
|
||||
printf("\t%s\t$66,$%02X\t\t\t; LLW\t[%d]\n", DB, index, index);
|
||||
}
|
||||
void emit_lab(int tag, int type)
|
||||
{
|
||||
int fixup = fixup_new(tag, type, FIXUP_WORD);
|
||||
char *taglbl = tag_string(tag, type);
|
||||
printf("\t%s\t$68\t\t\t; LAB\t%s\n", DB, taglbl);
|
||||
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
|
||||
}
|
||||
void emit_law(int tag, int type)
|
||||
{
|
||||
int fixup = fixup_new(tag, type, FIXUP_WORD);
|
||||
char *taglbl = tag_string(tag, type);
|
||||
printf("\t%s\t$6A\t\t\t; LAW\t%s\n", DB, taglbl);
|
||||
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
|
||||
}
|
||||
void emit_sb(void)
|
||||
{
|
||||
printf("\t%s\t$70\t\t\t; SB\n", DB);
|
||||
}
|
||||
void emit_sw(void)
|
||||
{
|
||||
printf("\t%s\t$72\t\t\t; SW\n", DB);
|
||||
}
|
||||
void emit_slb(int index)
|
||||
{
|
||||
printf("\t%s\t$74,$%02X\t\t\t; SLB\t[%d]\n", DB, index, index);
|
||||
}
|
||||
void emit_slw(int index)
|
||||
{
|
||||
printf("\t%s\t$76,$%02X\t\t\t; SLW\t[%d]\n", DB, index, index);
|
||||
}
|
||||
void emit_dlb(int index)
|
||||
{
|
||||
printf("\t%s\t$6C,$%02X\t\t\t; DLB\t[%d]\n", DB, index, index);
|
||||
}
|
||||
void emit_dlw(int index)
|
||||
{
|
||||
printf("\t%s\t$6E,$%02X\t\t\t; DLW\t[%d]\n", DB, index, index);
|
||||
}
|
||||
void emit_sab(int tag, int type)
|
||||
{
|
||||
int fixup = fixup_new(tag, type, FIXUP_WORD);
|
||||
char *taglbl = tag_string(tag, type);
|
||||
printf("\t%s\t$78\t\t\t; SAB\t%s\n", DB, taglbl);
|
||||
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
|
||||
}
|
||||
void emit_saw(int tag, int type)
|
||||
{
|
||||
int fixup = fixup_new(tag, type, FIXUP_WORD);
|
||||
char *taglbl = tag_string(tag, type);
|
||||
printf("\t%s\t$7A\t\t\t; SAW\t%s\n", DB, taglbl);
|
||||
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
|
||||
}
|
||||
void emit_dab(int tag, int type)
|
||||
{
|
||||
int fixup = fixup_new(tag, type, FIXUP_WORD);
|
||||
char *taglbl = tag_string(tag, type);
|
||||
printf("\t%s\t$7C\t\t\t; DAB\t%s\n", DB, taglbl);
|
||||
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
|
||||
}
|
||||
void emit_daw(int tag, int type)
|
||||
{
|
||||
int fixup = fixup_new(tag, type, FIXUP_WORD);
|
||||
char *taglbl = tag_string(tag, type);
|
||||
printf("\t%s\t$7E\t\t\t; DAW\t%s\n", DB, taglbl);
|
||||
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
|
||||
}
|
||||
void emit_localaddr(int index)
|
||||
{
|
||||
printf("\t%s\t$28,$%02X\t\t\t; LLA\t[%d]\n", DB, index, index);
|
||||
}
|
||||
void emit_globaladdr(int tag, int type)
|
||||
{
|
||||
int fixup = fixup_new(tag, type, FIXUP_WORD);
|
||||
char *taglbl = tag_string(tag, type);
|
||||
printf("\t%s\t$26\t\t\t; LA\t%s\n", DB, taglbl);
|
||||
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
|
||||
}
|
||||
void emit_globaladdrofst(int tag, int ofst, int type)
|
||||
{
|
||||
int fixup = fixup_new(tag, type, FIXUP_WORD);
|
||||
char *taglbl = tag_string(tag, type);
|
||||
printf("\t%s\t$26\t\t\t; LA\t%s+%d\n", DB, taglbl, ofst);
|
||||
printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "" : taglbl, ofst);
|
||||
}
|
||||
void emit_indexbyte(void)
|
||||
{
|
||||
printf("\t%s\t$02\t\t\t; IDXB\n", DB);
|
||||
}
|
||||
void emit_indexword(void)
|
||||
{
|
||||
printf("\t%s\t$1E\t\t\t; IDXW\n", DB);
|
||||
}
|
||||
void emit_brfls(int tag)
|
||||
{
|
||||
printf("\t%s\t$4C\t\t\t; BRFLS\t_B%03d\n", DB, tag);
|
||||
printf("\t%s\t_B%03d-*\n", DW, tag);
|
||||
}
|
||||
void emit_brtru(int tag)
|
||||
{
|
||||
printf("\t%s\t$4E\t\t\t; BRTRU\t_B%03d\n", DB, tag);
|
||||
printf("\t%s\t_B%03d-*\n", DW, tag);
|
||||
}
|
||||
void emit_brnch(int tag)
|
||||
{
|
||||
printf("\t%s\t$50\t\t\t; BRNCH\t_B%03d\n", DB, tag);
|
||||
printf("\t%s\t_B%03d-*\n", DW, tag);
|
||||
}
|
||||
void emit_breq(int tag)
|
||||
{
|
||||
printf("\t%s\t$3C\t\t\t; BREQ\t_B%03d\n", DB, tag);
|
||||
printf("\t%s\t_B%03d-*\n", DW, tag);
|
||||
}
|
||||
void emit_brne(int tag)
|
||||
{
|
||||
printf("\t%s\t$3E\t\t\t; BRNE\t_B%03d\n", DB, tag);
|
||||
printf("\t%s\t_B%03d-*\n", DW, tag);
|
||||
}
|
||||
void emit_brlt(int tag)
|
||||
{
|
||||
printf("\t%s\t$38\t\t\t; BRLT\t_B%03d\n", DB, tag);
|
||||
printf("\t%s\t_B%03d-*\n", DW, tag);
|
||||
}
|
||||
void emit_brgt(int tag)
|
||||
{
|
||||
printf("\t%s\t$3A\t\t\t; BRGT\t_B%03d\n", DB, tag);
|
||||
printf("\t%s\t_B%03d-*\n", DW, tag);
|
||||
}
|
||||
void emit_call(int tag, int type)
|
||||
{
|
||||
int fixup = fixup_new(tag, type, FIXUP_WORD);
|
||||
char *taglbl = tag_string(tag, type);
|
||||
printf("\t%s\t$54\t\t\t; CALL\t%s\n", DB, taglbl);
|
||||
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
|
||||
}
|
||||
void emit_ical(void)
|
||||
{
|
||||
printf("\t%s\t$56\t\t\t; ICAL\n", DB);
|
||||
}
|
||||
void emit_leave(int framesize)
|
||||
{
|
||||
if (framesize > 2)
|
||||
printf("\t%s\t$5A\t\t\t; LEAVE\n", DB);
|
||||
else
|
||||
printf("\t%s\t$5C\t\t\t; RET\n", DB);
|
||||
}
|
||||
void emit_ret(void)
|
||||
{
|
||||
printf("\t%s\t$5C\t\t\t; RET\n", DB);
|
||||
}
|
||||
void emit_def(int defopt)
|
||||
{
|
||||
}
|
||||
void emit_enter(int framesize, int cparams)
|
||||
{
|
||||
if (framesize > 2)
|
||||
printf("\t%s\t$58,$%02X,$%02X\t\t; ENTER\t%d,%d\n", DB, framesize, cparams, framesize, cparams);
|
||||
}
|
||||
void emit_start(void)
|
||||
{
|
||||
}
|
||||
void emit_dup(void)
|
||||
{
|
||||
printf("\t%s\t$32\t\t\t; DUP\n", DB);
|
||||
}
|
||||
void emit_push(void)
|
||||
{
|
||||
printf("\t%s\t$34\t\t\t; PUSH\n", DB);
|
||||
}
|
||||
void emit_pull(void)
|
||||
{
|
||||
printf("\t%s\t$36\t\t\t; PULL\n", DB);
|
||||
}
|
||||
void emit_swap(void)
|
||||
{
|
||||
printf("\t%s\t$2E\t\t\t; SWAP\n", DB);
|
||||
}
|
||||
void emit_drop(void)
|
||||
{
|
||||
printf("\t%s\t$30\t\t\t; DROP\n", DB);
|
||||
}
|
||||
int emit_unaryop(int op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case NEG_TOKEN:
|
||||
printf("\t%s\t$10\t\t\t; NEG\n", DB);
|
||||
break;
|
||||
case COMP_TOKEN:
|
||||
printf("\t%s\t$12\t\t\t; COMP\n", DB);
|
||||
break;
|
||||
case LOGIC_NOT_TOKEN:
|
||||
printf("\t%s\t$20\t\t\t; NOT\n", DB);
|
||||
break;
|
||||
case INC_TOKEN:
|
||||
printf("\t%s\t$0C\t\t\t; INCR\n", DB);
|
||||
break;
|
||||
case DEC_TOKEN:
|
||||
printf("\t%s\t$0E\t\t\t; DECR\n", DB);
|
||||
break;
|
||||
case BPTR_TOKEN:
|
||||
emit_lb();
|
||||
break;
|
||||
case WPTR_TOKEN:
|
||||
emit_lw();
|
||||
break;
|
||||
default:
|
||||
printf("emit_unaryop(%c) ???\n", op & 0x7F);
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
int emit_op(t_token op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case MUL_TOKEN:
|
||||
printf("\t%s\t$06\t\t\t; MUL\n", DB);
|
||||
break;
|
||||
case DIV_TOKEN:
|
||||
printf("\t%s\t$08\t\t\t; DIV\n", DB);
|
||||
break;
|
||||
case MOD_TOKEN:
|
||||
printf("\t%s\t$0A\t\t\t; MOD\n", DB);
|
||||
break;
|
||||
case ADD_TOKEN:
|
||||
printf("\t%s\t$02\t\t\t; ADD\n", DB);
|
||||
break;
|
||||
case SUB_TOKEN:
|
||||
printf("\t%s\t$04\t\t\t; SUB\n", DB);
|
||||
break;
|
||||
case SHL_TOKEN:
|
||||
printf("\t%s\t$1A\t\t\t; SHL\n", DB);
|
||||
break;
|
||||
case SHR_TOKEN:
|
||||
printf("\t%s\t$1C\t\t\t; SHR\n", DB);
|
||||
break;
|
||||
case AND_TOKEN:
|
||||
printf("\t%s\t$14\t\t\t; AND\n", DB);
|
||||
break;
|
||||
case OR_TOKEN:
|
||||
printf("\t%s\t$16\t\t\t; IOR\n", DB);
|
||||
break;
|
||||
case EOR_TOKEN:
|
||||
printf("\t%s\t$18\t\t\t; XOR\n", DB);
|
||||
break;
|
||||
case EQ_TOKEN:
|
||||
printf("\t%s\t$40\t\t\t; ISEQ\n", DB);
|
||||
break;
|
||||
case NE_TOKEN:
|
||||
printf("\t%s\t$42\t\t\t; ISNE\n", DB);
|
||||
break;
|
||||
case GE_TOKEN:
|
||||
printf("\t%s\t$48\t\t\t; ISGE\n", DB);
|
||||
break;
|
||||
case LT_TOKEN:
|
||||
printf("\t%s\t$46\t\t\t; ISLT\n", DB);
|
||||
break;
|
||||
case GT_TOKEN:
|
||||
printf("\t%s\t$44\t\t\t; ISGT\n", DB);
|
||||
break;
|
||||
case LE_TOKEN:
|
||||
printf("\t%s\t$4A\t\t\t; ISLE\n", DB);
|
||||
break;
|
||||
case LOGIC_OR_TOKEN:
|
||||
printf("\t%s\t$22\t\t\t; LOR\n", DB);
|
||||
break;
|
||||
case LOGIC_AND_TOKEN:
|
||||
printf("\t%s\t$24\t\t\t; LAND\n", DB);
|
||||
break;
|
||||
case COMMA_TOKEN:
|
||||
break;
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
void emit_rld(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf(";\n; RE-LOCATEABLE DICTIONARY\n;\n");
|
||||
/*
|
||||
* First emit the bytecode definition entrypoint information.
|
||||
*/
|
||||
for (i = 0; i < globals; i++)
|
||||
if (!(idglobal_type[i] & EXTERN_TYPE) && (idglobal_type[i] & DEF_TYPE))
|
||||
{
|
||||
printf("\t%s\t$02\t\t\t; CODE TABLE FIXUP\n", DB);
|
||||
printf("\t%s\t_C%03d\t\t\n", DW, idglobal_tag[i]);
|
||||
printf("\t%s\t$00\n", DB);
|
||||
}
|
||||
/*
|
||||
* Now emit the fixup table.
|
||||
*/
|
||||
for (i = 0; i < fixups; i++)
|
||||
{
|
||||
if (fixup_type[i] & EXTERN_TYPE)
|
||||
{
|
||||
printf("\t%s\t$%02X\t\t\t; EXTERNAL FIXUP\n", DB, 0x11 + fixup_size[i]);
|
||||
printf("\t%s\t_F%03d\t\t\n", DW, i);
|
||||
printf("\t%s\t%d\t\t\t; ESD INDEX\n", DB, fixup_tag[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\t%s\t$%02X\t\t\t; INTERNAL FIXUP\n", DB, 0x01 + fixup_size[i]);
|
||||
printf("\t%s\t_F%03d\t\t\n", DW, i);
|
||||
printf("\t%s\t$00\n", DB);
|
||||
}
|
||||
}
|
||||
printf("\t%s\t$00\t\t\t; END OF RLD\n", DB);
|
||||
}
|
||||
void emit_esd(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf(";\n; EXTERNAL/ENTRY SYMBOL DICTIONARY\n;\n");
|
||||
for (i = 0; i < globals; i++)
|
||||
{
|
||||
if (idglobal_type[i] & EXTERN_TYPE)
|
||||
{
|
||||
emit_dci(&idglobal_name[i][1], idglobal_name[i][0]);
|
||||
printf("\t%s\t$10\t\t\t; EXTERNAL SYMBOL FLAG\n", DB);
|
||||
printf("\t%s\t%d\t\t\t; ESD INDEX\n", DW, idglobal_tag[i]);
|
||||
}
|
||||
else if (idglobal_type[i] & EXPORT_TYPE)
|
||||
{
|
||||
emit_dci(&idglobal_name[i][1], idglobal_name[i][0]);
|
||||
printf("\t%s\t$08\t\t\t; ENTRY SYMBOL FLAG\n", DB);
|
||||
printf("\t%s\t%s\t\t\n", DW, tag_string(idglobal_tag[i], idglobal_type[i]));
|
||||
}
|
||||
}
|
||||
printf("\t%s\t$00\t\t\t; END OF ESD\n", DB);
|
||||
}
|
58
PLASMA/src/codegen.h
Executable file
58
PLASMA/src/codegen.h
Executable file
@@ -0,0 +1,58 @@
|
||||
#define ACME 1
|
||||
void emit_flags(int flags);
|
||||
void emit_header(void);
|
||||
void emit_trailer(void);
|
||||
void emit_moddep(char *name, int len);
|
||||
void emit_bytecode_seg(void);
|
||||
void emit_comment(char *s);
|
||||
void emit_asm(char *s);
|
||||
void emit_idlocal(char *name, int value);
|
||||
void emit_idglobal(int value, int size, char *name);
|
||||
void emit_idfunc(int tag, int type, char *name);
|
||||
void emit_idconst(char *name, int value);
|
||||
int emit_data(int vartype, int consttype, long constval, int constsize);
|
||||
void emit_codetag(int tag);
|
||||
void emit_const(int cval);
|
||||
void emit_lb(void);
|
||||
void emit_lw(void);
|
||||
void emit_llb(int index);
|
||||
void emit_llw(int index);
|
||||
void emit_lab(int tag, int type);
|
||||
void emit_law(int tag, int type);
|
||||
void emit_sb(void);
|
||||
void emit_sw(void);
|
||||
void emit_slb(int index);
|
||||
void emit_slw(int index);
|
||||
void emit_dlb(int index);
|
||||
void emit_dlw(int index);
|
||||
void emit_sab(int tag, int type);
|
||||
void emit_saw(int tag, int type);
|
||||
void emit_dab(int tag, int type);
|
||||
void emit_daw(int tag, int type);
|
||||
void emit_call(int tag, int type);
|
||||
void emit_ical(void);
|
||||
void emit_localaddr(int index);
|
||||
void emit_globaladdr(int tag, int type);
|
||||
void emit_globaladdrofst(int tag, int offset, int type);
|
||||
void emit_indexbyte(void);
|
||||
void emit_indexword(void);
|
||||
int emit_unaryop(int op);
|
||||
int emit_op(t_token op);
|
||||
void emit_brtru(int tag);
|
||||
void emit_brfls(int tag);
|
||||
void emit_brgt(int tag);
|
||||
void emit_brlt(int tag);
|
||||
void emit_brne(int tag);
|
||||
void emit_brnch(int tag);
|
||||
void emit_swap(void);
|
||||
void emit_dup(void);
|
||||
void emit_push(void);
|
||||
void emit_pull(void);
|
||||
void emit_drop(void);
|
||||
void emit_leave(int framesize);
|
||||
void emit_ret(void);
|
||||
void emit_def(int defopt);
|
||||
void emit_enter(int framesize, int cparams);
|
||||
void emit_start(void);
|
||||
void emit_rld(void);
|
||||
void emit_esd(void);
|
363
PLASMA/src/lex.c
Executable file
363
PLASMA/src/lex.c
Executable file
@@ -0,0 +1,363 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "tokens.h"
|
||||
#include "symbols.h"
|
||||
|
||||
char *statement, *scanpos, *tokenstr;
|
||||
t_token scantoken, prevtoken;
|
||||
int tokenlen;
|
||||
long constval;
|
||||
int lineno = 0;
|
||||
t_token keywords[] = {
|
||||
IF_TOKEN, 'I', 'F',
|
||||
ELSE_TOKEN, 'E', 'L', 'S', 'E',
|
||||
ELSEIF_TOKEN, 'E', 'L', 'S', 'I', 'F',
|
||||
FIN_TOKEN, 'F', 'I', 'N',
|
||||
WHILE_TOKEN, 'W', 'H', 'I', 'L', 'E',
|
||||
LOOP_TOKEN, 'L', 'O', 'O', 'P',
|
||||
CASE_TOKEN, 'W', 'H', 'E', 'N',
|
||||
OF_TOKEN, 'I', 'S',
|
||||
DEFAULT_TOKEN, 'O', 'T', 'H', 'E', 'R', 'W', 'I', 'S', 'E',
|
||||
ENDCASE_TOKEN, 'W', 'E', 'N', 'D',
|
||||
FOR_TOKEN, 'F', 'O', 'R',
|
||||
TO_TOKEN, 'T', 'O',
|
||||
DOWNTO_TOKEN, 'D', 'O', 'W', 'N', 'T', 'O',
|
||||
STEP_TOKEN, 'S', 'T', 'E', 'P',
|
||||
NEXT_TOKEN, 'N', 'E', 'X', 'T',
|
||||
REPEAT_TOKEN, 'R', 'E', 'P', 'E', 'A', 'T',
|
||||
UNTIL_TOKEN, 'U', 'N', 'T', 'I', 'L',
|
||||
BREAK_TOKEN, 'B', 'R', 'E', 'A', 'K',
|
||||
ASM_TOKEN, 'A', 'S', 'M',
|
||||
DEF_TOKEN, 'D', 'E', 'F',
|
||||
EXPORT_TOKEN, 'E', 'X', 'P', 'O', 'R', 'T',
|
||||
IMPORT_TOKEN, 'I', 'M', 'P', 'O', 'R', 'T',
|
||||
RETURN_TOKEN, 'R', 'E', 'T', 'U', 'R', 'N',
|
||||
END_TOKEN, 'E', 'N', 'D',
|
||||
START_TOKEN, 'S', 'T', 'A', 'R', 'T',
|
||||
EXIT_TOKEN, 'E', 'X', 'I', 'T',
|
||||
DONE_TOKEN, 'D', 'O', 'N', 'E',
|
||||
LOGIC_NOT_TOKEN, 'N', 'O', 'T',
|
||||
LOGIC_AND_TOKEN, 'A', 'N', 'D',
|
||||
LOGIC_OR_TOKEN, 'O', 'R',
|
||||
BYTE_TOKEN, 'B', 'Y', 'T', 'E',
|
||||
WORD_TOKEN, 'W', 'O', 'R', 'D',
|
||||
CONST_TOKEN, 'C', 'O', 'N', 'S', 'T',
|
||||
PREDEF_TOKEN, 'P', 'R', 'E', 'D', 'E', 'F',
|
||||
EOL_TOKEN
|
||||
};
|
||||
|
||||
void parse_error(char *errormsg)
|
||||
{
|
||||
char *error_carrot = statement;
|
||||
|
||||
fprintf(stderr, "\n%4d: %s\n ", lineno, statement);
|
||||
for (error_carrot = statement; error_carrot != tokenstr; error_carrot++)
|
||||
putc(*error_carrot == '\t' ? '\t' : ' ', stderr);
|
||||
fprintf(stderr, "^\nError: %s\n", errormsg);
|
||||
exit(1);
|
||||
}
|
||||
t_token scan(void)
|
||||
{
|
||||
prevtoken = scantoken;
|
||||
/*
|
||||
* Skip whitespace.
|
||||
*/
|
||||
while (*scanpos && (*scanpos == ' ' || *scanpos == '\t')) scanpos++;
|
||||
tokenstr = scanpos;
|
||||
/*
|
||||
* Scan for token based on first character.
|
||||
*/
|
||||
if (*scanpos == '\0' || *scanpos == '\n' || *scanpos == ';')
|
||||
scantoken = EOL_TOKEN;
|
||||
else if ((scanpos[0] >= 'a' && scanpos[0] <= 'z')
|
||||
|| (scanpos[0] >= 'A' && scanpos[0] <= 'Z')
|
||||
|| (scanpos[0] == '_'))
|
||||
{
|
||||
/*
|
||||
* ID, either variable name or reserved word.
|
||||
*/
|
||||
int keypos = 0, matchpos = 0;
|
||||
|
||||
do
|
||||
{
|
||||
scanpos++;
|
||||
}
|
||||
while ((*scanpos >= 'a' && *scanpos <= 'z')
|
||||
|| (*scanpos >= 'A' && *scanpos <= 'Z')
|
||||
|| (*scanpos == '_')
|
||||
|| (*scanpos >= '0' && *scanpos <= '9'));
|
||||
scantoken = ID_TOKEN;
|
||||
tokenlen = scanpos - tokenstr;
|
||||
/*
|
||||
* Search for matching keyword.
|
||||
*/
|
||||
while (keywords[keypos] != EOL_TOKEN)
|
||||
{
|
||||
while (keywords[keypos + 1 + matchpos] == toupper(tokenstr[matchpos]))
|
||||
matchpos++;
|
||||
if (IS_TOKEN(keywords[keypos + 1 + matchpos]) && (matchpos == tokenlen))
|
||||
{
|
||||
/*
|
||||
* A match.
|
||||
*/
|
||||
scantoken = keywords[keypos];
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Find next keyword.
|
||||
*/
|
||||
keypos += matchpos + 1;
|
||||
matchpos = 0;
|
||||
while (!IS_TOKEN(keywords[keypos])) keypos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (scanpos[0] >= '0' && scanpos[0] <= '9')
|
||||
{
|
||||
/*
|
||||
* Number constant.
|
||||
*/
|
||||
for (constval = 0; *scanpos >= '0' && *scanpos <= '9'; scanpos++)
|
||||
constval = constval * 10 + *scanpos - '0';
|
||||
scantoken = INT_TOKEN;
|
||||
}
|
||||
else if (scanpos[0] == '$')
|
||||
{
|
||||
/*
|
||||
* Hexadecimal constant.
|
||||
*/
|
||||
constval = 0;
|
||||
while (scanpos++)
|
||||
{
|
||||
if (*scanpos >= '0' && *scanpos <= '9')
|
||||
constval = constval * 16 + *scanpos - '0';
|
||||
else if (*scanpos >= 'A' && *scanpos <= 'F')
|
||||
constval = constval * 16 + *scanpos - 'A' + 10;
|
||||
else if (*scanpos >= 'a' && *scanpos <= 'f')
|
||||
constval = constval * 16 + *scanpos - 'a' + 10;
|
||||
else
|
||||
break;
|
||||
}
|
||||
scantoken = INT_TOKEN;
|
||||
}
|
||||
else if (scanpos[0] == '\'')
|
||||
{
|
||||
/*
|
||||
* Character constant.
|
||||
*/
|
||||
scantoken = CHAR_TOKEN;
|
||||
if (scanpos[1] != '\\')
|
||||
{
|
||||
constval = scanpos[1];
|
||||
if (scanpos[2] != '\'')
|
||||
{
|
||||
parse_error("Bad character constant");
|
||||
return (-1);
|
||||
}
|
||||
scanpos += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (scanpos[2])
|
||||
{
|
||||
case 'n':
|
||||
constval = '\n';
|
||||
break;
|
||||
case 'r':
|
||||
constval = '\r';
|
||||
break;
|
||||
case 't':
|
||||
constval = '\t';
|
||||
break;
|
||||
case '\'':
|
||||
constval = '\'';
|
||||
break;
|
||||
case '\\':
|
||||
constval = '\\';
|
||||
break;
|
||||
case '0':
|
||||
constval = '\0';
|
||||
break;
|
||||
default:
|
||||
parse_error("Bad character constant");
|
||||
return (-1);
|
||||
}
|
||||
if (scanpos[3] != '\'')
|
||||
{
|
||||
parse_error("Bad character constant");
|
||||
return (-1);
|
||||
}
|
||||
scanpos += 4;
|
||||
}
|
||||
}
|
||||
else if (scanpos[0] == '\"')
|
||||
{
|
||||
char *scanshift;
|
||||
/*
|
||||
* String constant.
|
||||
*/
|
||||
scantoken = STRING_TOKEN;
|
||||
constval = (long)++scanpos;
|
||||
while (*scanpos && *scanpos != '\"')
|
||||
{
|
||||
if (*scanpos == '\\')
|
||||
{
|
||||
switch (scanpos[1])
|
||||
{
|
||||
case 'n':
|
||||
*scanpos = '\n';
|
||||
break;
|
||||
case 'r':
|
||||
*scanpos = '\r';
|
||||
break;
|
||||
case 't':
|
||||
*scanpos = '\t';
|
||||
break;
|
||||
case '\'':
|
||||
*scanpos = '\'';
|
||||
break;
|
||||
case '\\':
|
||||
*scanpos = '\\';
|
||||
break;
|
||||
case '0':
|
||||
*scanpos = '\0';
|
||||
break;
|
||||
default:
|
||||
parse_error("Bad string constant");
|
||||
return (-1);
|
||||
}
|
||||
for (scanshift = scanpos + 1; *scanshift; scanshift++)
|
||||
scanshift[0] = scanshift[1];
|
||||
}
|
||||
else
|
||||
scanpos++;
|
||||
}
|
||||
if (!*scanpos++)
|
||||
{
|
||||
parse_error("Unterminated string");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Potential two and three character tokens.
|
||||
*/
|
||||
switch (scanpos[0])
|
||||
{
|
||||
case '>':
|
||||
if (scanpos[1] == '>')
|
||||
{
|
||||
scantoken = SHR_TOKEN;
|
||||
scanpos += 2;
|
||||
}
|
||||
else if (scanpos[1] == '=')
|
||||
{
|
||||
scantoken = GE_TOKEN;
|
||||
scanpos += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
scantoken = GT_TOKEN;
|
||||
scanpos++;
|
||||
}
|
||||
break;
|
||||
case '<':
|
||||
if (scanpos[1] == '<')
|
||||
{
|
||||
scantoken = SHL_TOKEN;
|
||||
scanpos += 2;
|
||||
}
|
||||
else if (scanpos[1] == '=')
|
||||
{
|
||||
scantoken = LE_TOKEN;
|
||||
scanpos += 2;
|
||||
}
|
||||
else if (scanpos[1] == '>')
|
||||
{
|
||||
scantoken = NE_TOKEN;
|
||||
scanpos += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
scantoken = LT_TOKEN;
|
||||
scanpos++;
|
||||
}
|
||||
break;
|
||||
case '=':
|
||||
if (scanpos[1] == '=')
|
||||
{
|
||||
scantoken = EQ_TOKEN;
|
||||
scanpos += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
scantoken = SET_TOKEN;
|
||||
scanpos++;
|
||||
}
|
||||
break;
|
||||
case '+':
|
||||
if (scanpos[1] == '+')
|
||||
{
|
||||
scantoken = INC_TOKEN;
|
||||
scanpos += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
scantoken = ADD_TOKEN;
|
||||
scanpos++;
|
||||
}
|
||||
break;
|
||||
case '-':
|
||||
if (scanpos[1] == '-')
|
||||
{
|
||||
scantoken = DEC_TOKEN;
|
||||
scanpos += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
scantoken = SUB_TOKEN;
|
||||
scanpos++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* Simple single character tokens.
|
||||
*/
|
||||
scantoken = TOKEN(*scanpos++);
|
||||
}
|
||||
}
|
||||
tokenlen = scanpos - tokenstr;
|
||||
return (scantoken);
|
||||
}
|
||||
void scan_rewind(char *backptr)
|
||||
{
|
||||
scanpos = backptr;
|
||||
}
|
||||
int scan_lookahead(void)
|
||||
{
|
||||
char *backpos = scanpos;
|
||||
char *backstr = tokenstr;
|
||||
int prevtoken = scantoken;
|
||||
int prevlen = tokenlen;
|
||||
int look = scan();
|
||||
scanpos = backpos;
|
||||
tokenstr = backstr;
|
||||
scantoken = prevtoken;
|
||||
tokenlen = prevlen;
|
||||
return (look);
|
||||
}
|
||||
char inputline[512];
|
||||
int next_line(void)
|
||||
{
|
||||
gets(inputline);
|
||||
lineno++;
|
||||
statement = inputline;
|
||||
scanpos = inputline;
|
||||
scantoken = EOL_TOKEN;
|
||||
scan();
|
||||
printf("; %03d: %s\n", lineno, inputline);
|
||||
return (1);
|
||||
}
|
10
PLASMA/src/lex.h
Executable file
10
PLASMA/src/lex.h
Executable file
@@ -0,0 +1,10 @@
|
||||
extern char *statement, *scanpos, *tokenstr;
|
||||
extern t_token scantoken, prevtoken;
|
||||
extern int tokenlen;
|
||||
extern long constval;
|
||||
extern char inputline[];
|
||||
void parse_error(char *errormsg);
|
||||
int next_line(void);
|
||||
void scan_rewind(char *backptr);
|
||||
int scan_lookahead(void);
|
||||
t_token scan(void);
|
42
PLASMA/src/makefile
Executable file
42
PLASMA/src/makefile
Executable file
@@ -0,0 +1,42 @@
|
||||
.SUFFIXES =
|
||||
AFLAGS = -o $@
|
||||
LFLAGS = -C default.cfg
|
||||
PLVM = plvm
|
||||
PLASM = plasm
|
||||
INCS = tokens.h symbols.h lex.h parse.h codegen.h
|
||||
OBJS = plasm.c parse.o lex.o codegen.o
|
||||
#
|
||||
# Image filetypes for Virtual ][
|
||||
#
|
||||
PLATYPE = .\$$ED
|
||||
BINTYPE = .BIN
|
||||
SYSTYPE = .SYS
|
||||
TXTTYPE = .TXT
|
||||
#
|
||||
# Image filetypes for CiderPress
|
||||
#
|
||||
#PLATYPE = \#ed0000
|
||||
#BINTYPE = \#060000
|
||||
#SYSTYPE = \#ff0000
|
||||
#TXTTYPE = \#040000
|
||||
|
||||
all: $(PLASM) $(PLVM)
|
||||
|
||||
clean:
|
||||
-rm *.o *~ *.a *.BIN
|
||||
|
||||
$(PLASM): $(OBJS) $(INCS)
|
||||
cc $(OBJS) -o $(PLASM)
|
||||
|
||||
$(PLVM): plvm.c
|
||||
cc plvm.c -o $(PLVM)
|
||||
|
||||
test: test.pla $(PLVM) $(PLASM)
|
||||
./$(PLASM) -A < test.pla > test.a
|
||||
acme --setpc 4096 -o TEST.BIN test.a
|
||||
./$(PLVM) TEST.BIN MAIN
|
||||
|
||||
debug: test.pla $(PLVM) $(PLASM)
|
||||
./$(PLASM) -A < test.pla > test.a
|
||||
acme --setpc 4096 -o TEST.BIN test.a
|
||||
./$(PLVM) -s TEST.BIN MAIN
|
1294
PLASMA/src/parse.c
Executable file
1294
PLASMA/src/parse.c
Executable file
File diff suppressed because it is too large
Load Diff
1
PLASMA/src/parse.h
Executable file
1
PLASMA/src/parse.h
Executable file
@@ -0,0 +1 @@
|
||||
int parse_module(void);
|
17
PLASMA/src/plasm.c
Executable file
17
PLASMA/src/plasm.c
Executable file
@@ -0,0 +1,17 @@
|
||||
#include <stdio.h>
|
||||
#include "tokens.h"
|
||||
#include "lex.h"
|
||||
#include "codegen.h"
|
||||
#include "parse.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'A')
|
||||
emit_flags(ACME);
|
||||
if (parse_module())
|
||||
{
|
||||
fprintf(stderr, "Compilation complete.\n");
|
||||
}
|
||||
return (0);
|
||||
}
|
895
PLASMA/src/plvm.c
Executable file
895
PLASMA/src/plvm.c
Executable file
@@ -0,0 +1,895 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef unsigned char code;
|
||||
typedef unsigned char byte;
|
||||
typedef signed short word;
|
||||
typedef unsigned short uword;
|
||||
typedef unsigned short address;
|
||||
/*
|
||||
* Debug
|
||||
*/
|
||||
int show_state = 0;
|
||||
/*
|
||||
* Bytecode memory
|
||||
*/
|
||||
#define BYTE_PTR(bp) ((byte)(*bp++))
|
||||
#define WORD_PTR(bp) ((word)(*bp++|(*++bp << 8)))
|
||||
#define UWORD_PTR(bp) ((uword)(*bp++|(*++bp << 8)))
|
||||
#define MOD_ADDR 0x1000
|
||||
#define DEF_CALL 0x0800
|
||||
#define DEF_CALLSZ 0x0800
|
||||
#define DEF_ENTRYSZ 6
|
||||
#define MEM_SIZE 65536
|
||||
byte mem_data[MEM_SIZE], mem_code[MEM_SIZE];
|
||||
byte *mem_bank[2] = {mem_data, mem_code};
|
||||
uword sp = 0x01FE, fp = 0xBEFF, heap = 0x6000, xheap = 0x0800, deftbl = DEF_CALL, lastdef = DEF_CALL;
|
||||
|
||||
#define EVAL_STACKSZ 16
|
||||
#define PUSH(v) (*(--esp))=(v)
|
||||
#define POP (*(esp++))
|
||||
#define UPOP ((uword)(*(esp++)))
|
||||
#define TOS (esp[0])
|
||||
word eval_stack[EVAL_STACKSZ];
|
||||
word *esp = eval_stack + EVAL_STACKSZ;
|
||||
|
||||
#define SYMTBLSZ 1024
|
||||
#define SYMSZ 16
|
||||
#define MODTBLSZ 128
|
||||
#define MODSZ 16
|
||||
#define MODLSTSZ 32
|
||||
byte symtbl[SYMTBLSZ];
|
||||
byte *lastsym = symtbl;
|
||||
byte modtbl[MODTBLSZ];
|
||||
byte *lastmod = modtbl;
|
||||
/*
|
||||
* Utility routines.
|
||||
*
|
||||
* A DCI string is one that has the high bit set for every character except the last.
|
||||
* More efficient than C or Pascal strings.
|
||||
*/
|
||||
int dcitos(byte *dci, char *str)
|
||||
{
|
||||
int len = 0;
|
||||
do
|
||||
str[len] = *dci & 0x7F;
|
||||
while ((len++ < 15) && (*dci++ & 0x80));
|
||||
str[len] = 0;
|
||||
return len;
|
||||
}
|
||||
int stodci(char *str, byte *dci)
|
||||
{
|
||||
int len = 0;
|
||||
do
|
||||
dci[len] = toupper(*str) | 0x80;
|
||||
while (*str++ && (len++ < 15));
|
||||
dci[len - 1] &= 0x7F;
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Heap routines.
|
||||
*/
|
||||
uword avail_heap(void)
|
||||
{
|
||||
return fp - heap;
|
||||
}
|
||||
uword alloc_heap(int size)
|
||||
{
|
||||
uword addr = heap;
|
||||
heap += size;
|
||||
if (heap >= fp)
|
||||
{
|
||||
printf("Error: heap/frame collision.\n");
|
||||
exit (1);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
uword free_heap(int size)
|
||||
{
|
||||
heap -= size;
|
||||
return fp - heap;
|
||||
}
|
||||
uword mark_heap(void)
|
||||
{
|
||||
return heap;
|
||||
}
|
||||
int release_heap(uword newheap)
|
||||
{
|
||||
heap = newheap;
|
||||
return fp - heap;
|
||||
}
|
||||
uword avail_xheap(void)
|
||||
{
|
||||
return 0xC000 - xheap;
|
||||
}
|
||||
uword alloc_xheap(int size)
|
||||
{
|
||||
uword addr = xheap;
|
||||
xheap += size;
|
||||
if (xheap >= 0xC000)
|
||||
{
|
||||
printf("Error: xheap extinguished.\n");
|
||||
exit (1);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
uword free_xheap(int size)
|
||||
{
|
||||
xheap -= size;
|
||||
return 0xC000 - heap;
|
||||
}
|
||||
uword mark_xheap(void)
|
||||
{
|
||||
return xheap;
|
||||
}
|
||||
int release_xheap(uword newxheap)
|
||||
{
|
||||
xheap = newxheap;
|
||||
return 0xC000 - xheap;
|
||||
}
|
||||
/*
|
||||
* Copy from data mem to code mem.
|
||||
*/
|
||||
void xmemcpy(uword src, uword dst, uword size)
|
||||
{
|
||||
while (size--)
|
||||
mem_code[dst + size] = mem_data[src + size];
|
||||
}
|
||||
/*
|
||||
* Copy from code mem to data mem.
|
||||
*/
|
||||
void memxcpy(uword src, uword dst, uword size)
|
||||
{
|
||||
while (size--)
|
||||
mem_data[dst + size] = mem_code[src + size];
|
||||
}
|
||||
/*
|
||||
* DCI table routines,
|
||||
*/
|
||||
void dump_tbl(byte *tbl)
|
||||
{
|
||||
int len;
|
||||
byte *entbl;
|
||||
while (*tbl)
|
||||
{
|
||||
len = 0;
|
||||
while (*tbl & 0x80)
|
||||
{
|
||||
putchar(*tbl++ & 0x7F);
|
||||
len++;
|
||||
}
|
||||
putchar(*tbl++);
|
||||
putchar(':');
|
||||
while (len++ < 15)
|
||||
putchar(' ');
|
||||
printf("$%04X\n", tbl[0] | (tbl[1] << 8));
|
||||
tbl += 2;
|
||||
}
|
||||
}
|
||||
uword lookup_tbl(byte *dci, byte *tbl)
|
||||
{
|
||||
char str[20];
|
||||
byte *match, *entry = tbl;
|
||||
while (*entry)
|
||||
{
|
||||
match = dci;
|
||||
while (*entry == *match)
|
||||
{
|
||||
if ((*entry & 0x80) == 0)
|
||||
return entry[1] | (entry[2] << 8);
|
||||
entry++;
|
||||
match++;
|
||||
}
|
||||
while (*entry++ & 0x80);
|
||||
entry += 2;
|
||||
}
|
||||
dcitos(dci, str);
|
||||
return 0;
|
||||
}
|
||||
int add_tbl(byte *dci, int val, byte *tbl, byte **last)
|
||||
{
|
||||
while (*dci & 0x80)
|
||||
*(*last)++ = *dci++;
|
||||
*(*last)++ = *dci++;
|
||||
*(*last)++ = val;
|
||||
*(*last)++ = val >> 8;
|
||||
}
|
||||
|
||||
/*
|
||||
* Symbol table routines.
|
||||
*/
|
||||
void dump_sym(void)
|
||||
{
|
||||
printf("\nSystem Symbol Table:\n");
|
||||
dump_tbl(symtbl);
|
||||
}
|
||||
uword lookup_sym(byte *sym)
|
||||
{
|
||||
return lookup_tbl(sym, symtbl);
|
||||
}
|
||||
int add_sym(byte *sym, int addr)
|
||||
{
|
||||
return add_tbl(sym, addr, symtbl, &lastsym);
|
||||
}
|
||||
|
||||
/*
|
||||
* Module routines.
|
||||
*/
|
||||
void dump_mod(void)
|
||||
{
|
||||
printf("\nSystem Module Table:\n");
|
||||
dump_tbl(modtbl);
|
||||
}
|
||||
uword lookup_mod(byte *mod)
|
||||
{
|
||||
return lookup_tbl(mod, modtbl);
|
||||
}
|
||||
int add_mod(byte *mod, int addr)
|
||||
{
|
||||
return add_tbl(mod, addr, symtbl, &lastmod);
|
||||
}
|
||||
defcall_add(int bank, int addr)
|
||||
{
|
||||
mem_data[lastdef] = bank ? 2 : 1;
|
||||
mem_data[lastdef + 1] = addr;
|
||||
mem_data[lastdef + 2] = addr >> 8;
|
||||
return lastdef++;
|
||||
}
|
||||
int def_lookup(byte *cdd, int defaddr)
|
||||
{
|
||||
int i, calldef = 0;
|
||||
for (i = 0; cdd[i * 4] == 0x02; i++)
|
||||
{
|
||||
if ((cdd[i * 4 + 1] | (cdd[i * 4 + 2] << 8)) == defaddr)
|
||||
{
|
||||
calldef = cdd + i * 4 - mem_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return calldef;
|
||||
}
|
||||
int extern_lookup(byte *esd, int index)
|
||||
{
|
||||
byte *sym;
|
||||
char string[32];
|
||||
while (*esd)
|
||||
{
|
||||
sym = esd;
|
||||
esd += dcitos(esd, string);
|
||||
if ((esd[0] & 0x10) && (esd[1] == index))
|
||||
return lookup_sym(sym);
|
||||
esd += 3;
|
||||
}
|
||||
printf("\nError: extern index %d not found in ESD.\n", index);
|
||||
return 0;
|
||||
}
|
||||
int load_mod(byte *mod)
|
||||
{
|
||||
int len, size, end, magic, bytecode, fixup, addr, modaddr = mark_heap();
|
||||
byte *moddep, *rld, *esd, *cdd, *sym;
|
||||
byte header[128];
|
||||
char filename[32], string[17];
|
||||
|
||||
dcitos(mod, filename);
|
||||
printf("Load module %s\n");
|
||||
int fd = open(filename, O_RDONLY, 0);
|
||||
if ((fd > 0) && (len = read(fd, header, 128)) > 0)
|
||||
{
|
||||
magic = header[2] | (header[3] << 8);
|
||||
if (magic == 0xDA7E)
|
||||
{
|
||||
/*
|
||||
* This is a relocatable bytecode module.
|
||||
*/
|
||||
bytecode = header[4] | (header[5] << 8);
|
||||
moddep = header + 6;
|
||||
if (*moddep)
|
||||
{
|
||||
/*
|
||||
* Load module dependencies.
|
||||
*/
|
||||
close(fd);
|
||||
while (*moddep)
|
||||
{
|
||||
if (lookup_mod(moddep) == 0)
|
||||
load_mod(moddep);
|
||||
moddep += dcitos(moddep, string);
|
||||
}
|
||||
modaddr = mark_heap();
|
||||
fd = open(filename, O_RDONLY, 0);
|
||||
len = read(fd, mem_data + modaddr, 128);
|
||||
}
|
||||
else
|
||||
memcpy(mem_data + modaddr, header, len);
|
||||
}
|
||||
addr = modaddr + len;
|
||||
while ((len = read(fd, mem_data + addr, 4096)) > 0)
|
||||
addr += len;
|
||||
close(fd);
|
||||
size = addr - modaddr;
|
||||
len = mem_data[modaddr + 0] | (mem_data[modaddr + 1] << 8);
|
||||
end = modaddr + len;
|
||||
rld = mem_data + modaddr + len; // Re-Locatable Directory
|
||||
esd = rld; // Extern+Entry Symbol Directory
|
||||
bytecode += modaddr - MOD_ADDR;
|
||||
while (*esd != 0x00) // Scan to end of RLD
|
||||
esd += 4;
|
||||
esd++;
|
||||
cdd = rld;
|
||||
if (show_state)
|
||||
{
|
||||
/*
|
||||
* Dump different parts of module.
|
||||
*/
|
||||
printf("Module size: %d\n", size);
|
||||
printf("Module code+data size: %d\n", len);
|
||||
printf("Module magic: $%04X\n", magic);
|
||||
printf("Module bytecode: $%04X\n", bytecode);
|
||||
}
|
||||
/*
|
||||
* Print out the Re-Location Dictionary.
|
||||
*/
|
||||
if (show_state)
|
||||
printf("\nRe-Location Dictionary:\n");
|
||||
while (*rld)
|
||||
{
|
||||
if (rld[0] == 0x02)
|
||||
{
|
||||
if (show_state) printf("\tDEF CODE");
|
||||
addr = rld[1] | (rld[2] << 8);
|
||||
addr += modaddr - MOD_ADDR;
|
||||
rld[1] = addr;
|
||||
rld[2] = addr >> 8;
|
||||
end = rld - mem_data + 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = rld[1] | (rld[2] << 8);
|
||||
addr += modaddr - MOD_ADDR;
|
||||
if (rld[0] & 0x80)
|
||||
fixup = mem_data[addr] | (mem_data[addr + 1] << 8);
|
||||
else
|
||||
fixup = mem_data[addr];
|
||||
if (rld[0] & 0x10)
|
||||
{
|
||||
if (show_state) printf("\tEXTERN[$%02X] ", rld[3]);
|
||||
fixup += extern_lookup(esd, rld[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (show_state) printf("\tINTERN ");
|
||||
fixup += modaddr - MOD_ADDR;
|
||||
if (fixup >= bytecode)
|
||||
/*
|
||||
* Replace with call def dictionary.
|
||||
*/
|
||||
fixup = def_lookup(cdd, fixup);
|
||||
}
|
||||
if (rld[0] & 0x80)
|
||||
{
|
||||
if (show_state) printf("WORD");
|
||||
mem_data[addr] = fixup;
|
||||
mem_data[addr + 1] = fixup >> 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (show_state) printf("BYTE");
|
||||
mem_data[addr] = fixup;
|
||||
}
|
||||
|
||||
}
|
||||
if (show_state) printf("@$%04X\n", addr);
|
||||
rld += 4;
|
||||
}
|
||||
if (show_state) printf("\nExternal/Entry Symbol Directory:\n");
|
||||
while (*esd)
|
||||
{
|
||||
sym = esd;
|
||||
esd += dcitos(esd, string);
|
||||
if (esd[0] & 0x10)
|
||||
{
|
||||
if (show_state) printf("\tIMPORT %s[$%02X]\n", string, esd[1]);
|
||||
}
|
||||
else if (esd[0] & 0x08)
|
||||
{
|
||||
addr = esd[1] | (esd[2] << 8);
|
||||
addr += modaddr - MOD_ADDR;
|
||||
if (show_state) printf("\tEXPORT %s@$%04X\n", string, addr);
|
||||
if (addr >= bytecode)
|
||||
addr = def_lookup(cdd, addr);
|
||||
add_sym(sym, addr);
|
||||
}
|
||||
esd += 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: Unable to load module %s\n", filename);
|
||||
exit (1);
|
||||
}
|
||||
/*
|
||||
* Reserve heap space for relocated module.
|
||||
*/
|
||||
alloc_heap(end - modaddr);
|
||||
return (fd > 0);
|
||||
}
|
||||
void interp(code *ip);
|
||||
|
||||
void call(word pc)
|
||||
{
|
||||
int i, s;
|
||||
char sz[64];
|
||||
|
||||
switch (mem_data[pc++])
|
||||
{
|
||||
case 0: // NULL call
|
||||
printf("NULL call code\n");
|
||||
break;
|
||||
case 1: // BYTECODE in mem_code
|
||||
interp(mem_code + (mem_data[pc] + (mem_data[pc + 1] << 8)));
|
||||
break;
|
||||
case 2: // BYTECODE in mem_data
|
||||
interp(mem_data + (mem_data[pc] + (mem_data[pc + 1] << 8)));
|
||||
break;
|
||||
case 3: // LIBRARY STDLIB::VIEWPORT
|
||||
printf("Set Window %d, %d, %d, %n/n", POP, POP, POP, POP);
|
||||
PUSH(0);
|
||||
break;
|
||||
case 4: // LIBRARY STDLIB::PUTC
|
||||
putchar(POP);
|
||||
PUSH(0);
|
||||
break;
|
||||
case 5: // LIBRARY STDLIB::PUTS
|
||||
s = POP;
|
||||
i = mem_data[s++];
|
||||
PUSH(i);
|
||||
while (i--)
|
||||
putchar(mem_data[s++]);
|
||||
break;
|
||||
case 6: // LIBRARY STDLIB::PUTSZ
|
||||
s = POP;
|
||||
while (i = mem_data[s++])
|
||||
{
|
||||
if (i == '\r')
|
||||
i = '\n';
|
||||
putchar(i);
|
||||
}
|
||||
PUSH(0);
|
||||
break;
|
||||
case 7: // LIBRARY STDLIB::GETC
|
||||
PUSH(getchar());
|
||||
break;
|
||||
case 8: // LIBRARY STDLIB::GETS
|
||||
gets(sz);
|
||||
i = 0;
|
||||
while (sz[i])
|
||||
mem_data[0x200 + i++] = sz[i];
|
||||
mem_data[0x200 + i] = 0;
|
||||
mem_data[0x1FF] = i;
|
||||
PUSH(i);
|
||||
break;
|
||||
case 9: // LIBRARY STDLIB::CLS
|
||||
puts("\033[2J");
|
||||
fflush(stdout);
|
||||
PUSH(0);
|
||||
PUSH(0);
|
||||
case 10: // LIBRARY STDLIB::GOTOXY
|
||||
s = POP + 1;
|
||||
i = POP + 1;
|
||||
printf("\033[%d;%df", s, i);
|
||||
fflush(stdout);
|
||||
PUSH(0);
|
||||
break;
|
||||
default:
|
||||
printf("Bad call code\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* OPCODE TABLE
|
||||
*
|
||||
OPTBL: DW ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E
|
||||
DW NEG,COMP,AND,IOR,XOR,SHL,SHR,IDXW ; 10 12 14 16 18 1A 1C 1E
|
||||
DW NOT,LOR,LAND,LA,LLA,CB,CW,SWAP ; 20 22 24 26 28 2A 2C 2E
|
||||
DW DROP,DUP,PUSH,PULL,BRGT,BRLT,BREQ,BRNE ; 30 32 34 36 38 3A 3C 3E
|
||||
DW ISEQ,ISNE,ISGT,ISLT,ISGE,ISLE,BRFLS,BRTRU ; 40 42 44 46 48 4A 4C 4E
|
||||
DW BRNCH,IBRNCH,CALL,ICAL,ENTER,LEAVE,RET,??? ; 50 52 54 56 58 5A 5C 5E
|
||||
DW LB,LW,LLB,LLW,LAB,LAW,DLB,DLW ; 60 62 64 66 68 6A 6C 6E
|
||||
DW SB,SW,SLB,SLW,SAB,SAW,DAB,DAW ; 70 72 74 76 78 7A 7C 7E
|
||||
*/
|
||||
void interp(code *ip)
|
||||
{
|
||||
word val, ea, frmsz, parmcnt;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (show_state)
|
||||
{
|
||||
word *dsp = &eval_stack[EVAL_STACKSZ - 1];
|
||||
printf("$%04X: $%02X [ ", ip - mem_data, *ip);
|
||||
while (dsp >= esp)
|
||||
printf("$%04X ", (*dsp--) & 0xFFFF);
|
||||
printf("]\n");
|
||||
}
|
||||
switch (*ip++)
|
||||
{
|
||||
/*
|
||||
* 0x00-0x0F
|
||||
*/
|
||||
case 0x00: // ZERO : TOS = 0
|
||||
PUSH(0);
|
||||
break;
|
||||
case 0x02: // ADD : TOS = TOS + TOS-1
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea + val);
|
||||
break;
|
||||
case 0x04: // SUB : TOS = TOS-1 - TOS
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea - val);
|
||||
break;
|
||||
case 0x06: // MUL : TOS = TOS * TOS-1
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea * val);
|
||||
break;
|
||||
case 0x08: // DIV : TOS = TOS-1 / TOS
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea / val);
|
||||
break;
|
||||
case 0x0A: // MOD : TOS = TOS-1 % TOS
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea % val);
|
||||
break;
|
||||
case 0x0C: // INCR : TOS = TOS + 1
|
||||
TOS++;
|
||||
break;
|
||||
case 0x0E: // DECR : TOS = TOS - 1
|
||||
TOS--;
|
||||
break;
|
||||
/*
|
||||
* 0x10-0x1F
|
||||
*/
|
||||
case 0x10: // NEG : TOS = -TOS
|
||||
TOS = -TOS;
|
||||
break;
|
||||
case 0x12: // COMP : TOS = ~TOS
|
||||
TOS = ~TOS;
|
||||
break;
|
||||
case 0x14: // AND : TOS = TOS & TOS-1
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea & val);
|
||||
break;
|
||||
case 0x16: // IOR : TOS = TOS ! TOS-1
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea | val);
|
||||
break;
|
||||
case 0x18: // XOR : TOS = TOS ^ TOS-1
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea ^ val);
|
||||
break;
|
||||
case 0x1A: // SHL : TOS = TOS-1 << TOS
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea << val);
|
||||
break;
|
||||
case 0x1C: // SHR : TOS = TOS-1 >> TOS
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea >> val);
|
||||
break;
|
||||
case 0x1E: // IDXW : TOS = TOS * 2
|
||||
TOS *= 2;
|
||||
break;
|
||||
/*
|
||||
* 0x20-0x2F
|
||||
*/
|
||||
case 0x20: // NOT : TOS = !TOS
|
||||
TOS = !TOS;
|
||||
break;
|
||||
case 0x22: // LOR : TOS = TOS || TOS-1
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea || val);
|
||||
break;
|
||||
case 0x24: // LAND : TOS = TOS && TOS-1
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea && val);
|
||||
break;
|
||||
case 0x26: // LA : TOS = @VAR ; equivalent to CW ADDRESSOF(VAR)
|
||||
PUSH(WORD_PTR(ip));
|
||||
break;
|
||||
case 0x28: // LLA : TOS = @LOCALVAR ; equivalent to CW FRAMEPTR+OFFSET(LOCALVAR)
|
||||
PUSH(fp + BYTE_PTR(ip));
|
||||
break;
|
||||
case 0x2A: // CB : TOS = CONSTANTBYTE (IP)
|
||||
PUSH(BYTE_PTR(ip));
|
||||
break;
|
||||
case 0x2C: // CW : TOS = CONSTANTWORD (IP)
|
||||
PUSH(WORD_PTR(ip));
|
||||
break;
|
||||
case 0x2E: // SWAP : TOS = TOS-1, TOS-1 = TOS
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(val);
|
||||
PUSH(ea);
|
||||
break;
|
||||
/*
|
||||
* 0x30-0x3F
|
||||
*/
|
||||
case 0x30: // DROP : TOS =
|
||||
esp++;;
|
||||
break;
|
||||
case 0x32: // DUP : TOS = TOS
|
||||
val = TOS;
|
||||
PUSH(val);
|
||||
break;
|
||||
case 0x34: // PUSH : TOSP = TOS
|
||||
val = POP;
|
||||
mem_data[sp--] = val >> 8;
|
||||
mem_data[sp--] = val;
|
||||
break;
|
||||
case 0x36: // PULL : TOS = TOSP
|
||||
PUSH(mem_data[++sp] | (mem_data[++sp] << 8));
|
||||
break;
|
||||
case 0x38: // BRGT : TOS-1 > TOS ? IP += (IP)
|
||||
val = POP;
|
||||
ea = POP;
|
||||
if (ea <= val)
|
||||
ip += WORD_PTR(ip) - 2;
|
||||
else
|
||||
ip += 2;
|
||||
break;
|
||||
case 0x3A: // BRLT : TOS-1 < TOS ? IP += (IP)
|
||||
val = POP;
|
||||
ea = TOS;
|
||||
if (ea >= val)
|
||||
ip += WORD_PTR(ip) - 2;
|
||||
else
|
||||
ip += 2;
|
||||
break;
|
||||
case 0x3C: // BREQ : TOS == TOS-1 ? IP += (IP)
|
||||
val = POP;
|
||||
ea = TOS;
|
||||
if (ea == val)
|
||||
ip += WORD_PTR(ip) - 2;
|
||||
else
|
||||
ip += 2;
|
||||
break;
|
||||
case 0x3E: // BRNE : TOS != TOS-1 ? IP += (IP)
|
||||
val = POP;
|
||||
ea = TOS;
|
||||
if (ea != val)
|
||||
ip += WORD_PTR(ip) - 2;
|
||||
else
|
||||
ip += 2;
|
||||
break;
|
||||
/*
|
||||
* 0x40-0x4F
|
||||
*/
|
||||
case 0x40: // ISEQ : TOS = TOS == TOS-1
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea == val);
|
||||
break;
|
||||
case 0x42: // ISNE : TOS = TOS != TOS-1
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea != val);
|
||||
break;
|
||||
case 0x44: // ISGT : TOS = TOS-1 > TOS
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea <= val);
|
||||
break;
|
||||
case 0x46: // ISLT : TOS = TOS-1 < TOS
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea >= val);
|
||||
break;
|
||||
case 0x48: // ISGE : TOS = TOS-1 >= TOS
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea < val);
|
||||
break;
|
||||
case 0x4A: // ISLE : TOS = TOS-1 <= TOS
|
||||
val = POP;
|
||||
ea = POP;
|
||||
PUSH(ea > val);
|
||||
break;
|
||||
case 0x4C: // BRFLS : !TOS ? IP += (IP)
|
||||
if (!POP)
|
||||
ip += WORD_PTR(ip) - 2;
|
||||
else
|
||||
ip += 2;
|
||||
break;
|
||||
case 0x4E: // BRTRU : TOS ? IP += (IP)
|
||||
if (POP)
|
||||
ip += WORD_PTR(ip) - 2;
|
||||
else
|
||||
ip += 2;
|
||||
break;
|
||||
/*
|
||||
* 0x50-0x5F
|
||||
*/
|
||||
case 0x50: // BRNCH : IP += (IP)
|
||||
ip += WORD_PTR(ip) - 2;
|
||||
break;
|
||||
case 0x52: // IBRNCH : IP += TOS
|
||||
ip += POP;
|
||||
break;
|
||||
case 0x54: // CALL : TOFP = IP, IP = (IP) ; call
|
||||
call(UWORD_PTR(ip));
|
||||
break;
|
||||
case 0x56: // ICALL : TOFP = IP, IP = (TOS) ; indirect call
|
||||
val = POP;
|
||||
ea = mem_data[val] | (mem_data[val + 1] << 8);
|
||||
call(ea);
|
||||
break;
|
||||
case 0x58: // ENTER : NEW FRAME, FOREACH PARAM LOCALVAR = TOS
|
||||
frmsz = BYTE_PTR(ip);
|
||||
mem_data[fp - frmsz] = fp;
|
||||
mem_data[fp - frmsz + 1] = fp >> 8;
|
||||
fp -= frmsz;
|
||||
parmcnt = BYTE_PTR(ip);
|
||||
while (parmcnt--)
|
||||
{
|
||||
val = POP;
|
||||
mem_data[fp + parmcnt + 2] = val;
|
||||
mem_data[fp + parmcnt + 3] = val >> 8;
|
||||
}
|
||||
break;
|
||||
case 0x5A: // LEAVE : DEL FRAME, IP = TOFP
|
||||
fp = mem_data[fp] | (mem_data[fp + 1] << 8);
|
||||
case 0x5C: // RET : IP = TOFP
|
||||
return;
|
||||
case 0x5E: // ???
|
||||
break;
|
||||
/*
|
||||
* 0x60-0x6F
|
||||
*/
|
||||
case 0x60: // LB : TOS = BYTE (TOS)
|
||||
val = UPOP;
|
||||
PUSH(mem_data[val]);
|
||||
break;
|
||||
case 0x62: // LW : TOS = WORD (TOS)
|
||||
ea = POP;
|
||||
PUSH(mem_data[ea] | (mem_data[ea + 1] << 8));
|
||||
break;
|
||||
case 0x64: // LLB : TOS = LOCALBYTE [IP]
|
||||
PUSH(mem_data[fp + BYTE_PTR(ip)]);
|
||||
break;
|
||||
case 0x66: // LLW : TOS = LOCALWORD [IP]
|
||||
ea = fp + BYTE_PTR(ip);
|
||||
PUSH(mem_data[ea] | (mem_data[ea + 1] << 8));
|
||||
break;
|
||||
case 0x68: // LAB : TOS = BYTE (IP)
|
||||
PUSH(mem_data[UWORD_PTR(ip)]);
|
||||
break;
|
||||
case 0x6A: // LAW : TOS = WORD (IP)
|
||||
ea = UWORD_PTR(ip);
|
||||
PUSH(mem_data[ea] | (mem_data[ea + 1] << 8));
|
||||
break;
|
||||
case 0x6C: // DLB : TOS = TOS, LOCALBYTE [IP] = TOS
|
||||
mem_data[fp + BYTE_PTR(ip)] = TOS;
|
||||
break;
|
||||
case 0x6E: // DLW : TOS = TOS, LOCALWORD [IP] = TOS
|
||||
ea = fp + BYTE_PTR(ip);
|
||||
mem_data[ea] = TOS;
|
||||
mem_data[ea + 1] = TOS >> 8;
|
||||
break;
|
||||
/*
|
||||
* 0x70-0x7F
|
||||
*/
|
||||
case 0x70: // SB : BYTE (TOS) = TOS-1
|
||||
val = POP;
|
||||
ea = POP;
|
||||
mem_data[ea] = val;
|
||||
break;
|
||||
case 0x72: // SW : WORD (TOS) = TOS-1
|
||||
val = POP;
|
||||
ea = POP;
|
||||
mem_data[ea] = val;
|
||||
mem_data[ea + 1] = val >> 8;
|
||||
break;
|
||||
case 0x74: // SLB : LOCALBYTE [TOS] = TOS-1
|
||||
mem_data[fp + BYTE_PTR(ip)] = POP;
|
||||
break;
|
||||
case 0x76: // SLW : LOCALWORD [TOS] = TOS-1
|
||||
ea = fp + BYTE_PTR(ip);
|
||||
val = POP;
|
||||
mem_data[ea] = val;
|
||||
mem_data[ea + 1] = val >> 8;
|
||||
break;
|
||||
case 0x78: // SAB : BYTE (IP) = TOS
|
||||
mem_data[WORD_PTR(ip)] = POP;
|
||||
break;
|
||||
case 0x7A: // SAW : WORD (IP) = TOS
|
||||
ea = WORD_PTR(ip);
|
||||
val = POP;
|
||||
mem_data[ea] = val;
|
||||
mem_data[ea + 1] = val >> 8;
|
||||
break;
|
||||
case 0x7C: // DAB : TOS = TOS, BYTE (IP) = TOS
|
||||
mem_data[WORD_PTR(ip)] = TOS;
|
||||
break;
|
||||
case 0x7E: // DAW : TOS = TOS, WORD (IP) = TOS
|
||||
ea = WORD_PTR(ip);
|
||||
mem_data[ea] = TOS;
|
||||
mem_data[ea + 1] = TOS >> 8;
|
||||
break;
|
||||
/*
|
||||
* Odd codes and everything else are errors.
|
||||
*/
|
||||
default:
|
||||
fprintf(stderr, "Illegal opcode 0x%02X @ 0x%04X\n", ip[-1], ip - mem_code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *stdlib_exp[] = {
|
||||
"VIEWPORT",
|
||||
"PUTC",
|
||||
"PUTS",
|
||||
"PUTSZ",
|
||||
"GETC",
|
||||
"GETS",
|
||||
"CLS",
|
||||
"GOTOXY"
|
||||
};
|
||||
|
||||
byte stdlib[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
byte dci[32];
|
||||
int i;
|
||||
|
||||
if (--argc)
|
||||
{
|
||||
argv++;
|
||||
if ((*argv)[0] == '-' && (*argv)[1] == 's')
|
||||
{
|
||||
show_state = 1;
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
/*
|
||||
* Add default library.
|
||||
*/
|
||||
stodci("STDLIB", dci);
|
||||
add_mod(dci, 0xFFFF);
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
mem_data[i] = i + 3;
|
||||
stodci(stdlib_exp[i], dci);
|
||||
add_sym(dci, i);
|
||||
}
|
||||
if (argc)
|
||||
{
|
||||
stodci(*argv, dci);
|
||||
load_mod(dci);
|
||||
if (show_state) dump_sym();
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
if (argc)
|
||||
{
|
||||
stodci(*argv, dci);
|
||||
call(lookup_sym(dci));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
147
PLASMA/src/samplib.s
Executable file
147
PLASMA/src/samplib.s
Executable file
@@ -0,0 +1,147 @@
|
||||
;
|
||||
; Sample PLASMA library.
|
||||
;
|
||||
!TO "samplib.bin", PLAIN
|
||||
* = $1000
|
||||
;
|
||||
; DATA/CODE SEGMENT
|
||||
;
|
||||
_SEGBEGIN
|
||||
!WORD _SEGEND-_SEGBEGIN ; LENGTH OF HEADER + CODE/DATA + BYTECODE SEGMENT
|
||||
;
|
||||
; MODULE HEADER
|
||||
;
|
||||
!WORD $DA7E ; MAGIC #
|
||||
!WORD _SUBSEG ; BYTECODE SUB-SEGMENT
|
||||
;
|
||||
; MODULE DEPENDENCY LIST
|
||||
; NOTE: DCI = PSUEDO OP FOR ASCII STRING WITH HI BIT SET EXCEPT LAST CHAR
|
||||
;
|
||||
;DCI "STDLIB"
|
||||
!CT "hi.ascii"
|
||||
!TX "STDLI"
|
||||
!CT RAW
|
||||
!TX 'B'
|
||||
;DCI "FILEIO"
|
||||
!CT "hi.ascii"
|
||||
!TX "FILEI"
|
||||
!CT RAW
|
||||
!TX 'O'
|
||||
!BYTE 0
|
||||
;
|
||||
; NATIVE CODE + GLOBAL DATA
|
||||
;
|
||||
COUNT !WORD 0
|
||||
INCCNT
|
||||
FIXUP1 INC COUNT
|
||||
BNE XINIT
|
||||
FIXUP2 INC COUNT+1
|
||||
XINIT RTS
|
||||
;
|
||||
; BYTECODE SUB-SEGMENT
|
||||
;
|
||||
_SUBSEG
|
||||
MYFUNC !BYTE $58, $01, $16 ; ENTER 1,16
|
||||
!BYTE $66, $02 ; LLW 2
|
||||
!BYTE $2A, $01 ; CB 1
|
||||
!BYTE $54 ; CALL EXTERN(1) "OPEN"
|
||||
FIXUP4 !WORD $0000
|
||||
!BYTE $6E, $04 ; DLW 4
|
||||
!BYTE $54 ; CALL EXTERN(3) "READ"
|
||||
FIXUP5 !WORD $0000
|
||||
!BYTE $30 ; DROP
|
||||
!BYTE $66, $04 ; LLW 4
|
||||
!BYTE $54 ; CALL EXTERN(2) ; "CLOSE"
|
||||
FIXUP6 !WORD $0000
|
||||
!BYTE $30 ; DROP
|
||||
!BYTE $6A ; LAW COUNT
|
||||
FIXUP7 !WORD $0000
|
||||
!BYTE $54 ; CALL INCNT
|
||||
FIXUP8 !WORD $0000
|
||||
!BYTE $5A ; LEAVE
|
||||
;
|
||||
; END OF CODE/DATA + BYTECODE SEGMENT
|
||||
;
|
||||
_SEGEND
|
||||
;
|
||||
; BYTCODE FUNCTION DICTIONARY
|
||||
;
|
||||
!BYTE $A1 ; FIXUP FLAGS
|
||||
!WORD MYFUNC ; FIXUP OFFSET
|
||||
!BYTE $00 ; FIXUP LO BYTE (OF HI BYTE)/IMPORT INDEX
|
||||
;
|
||||
; RE-LOCATION DICTIONARY (FIXUP TABLE)
|
||||
;
|
||||
!BYTE $81 ; FIXUP FLAGS
|
||||
!WORD FIXUP1+1 ; FIXUP OFFSET
|
||||
!BYTE $00 ; FIXUP LO BYTE (OF HI BYTE)/IMPORT INDEX
|
||||
!BYTE $81
|
||||
!WORD FIXUP2+1
|
||||
!BYTE $00
|
||||
!BYTE $91 ; IMPORT FIXUP
|
||||
!WORD FIXUP4
|
||||
!BYTE $01 ; IMPORT INDEX 1
|
||||
!BYTE $91
|
||||
!WORD FIXUP5
|
||||
!BYTE $03
|
||||
!BYTE $91
|
||||
!WORD FIXUP6
|
||||
!BYTE $02
|
||||
!BYTE $81
|
||||
!WORD FIXUP7
|
||||
!BYTE $00
|
||||
!BYTE $81
|
||||
!WORD FIXUP8
|
||||
!BYTE $00
|
||||
!BYTE 0 ; END OF RLD
|
||||
;
|
||||
; EXTERNAL/ENTRY SYMBOL DIRECTORY
|
||||
;;
|
||||
; IMPORT TABLE
|
||||
;
|
||||
IMPTBL ;DCI "OPEN" ; EXTERNAL SYMBOL NAME
|
||||
!CT "hi.ascii"
|
||||
!TX "OPE"
|
||||
!CT RAW
|
||||
!TX 'N'
|
||||
!BYTE $10 ; EXTERNAL SYMBOL FLAG
|
||||
!WORD 1 ; SYMBOL INDEX
|
||||
;DCI "CLOSE"
|
||||
!CT "hi.ascii"
|
||||
!TX "CLOS"
|
||||
!CT RAW
|
||||
!TX 'E'
|
||||
!BYTE $10
|
||||
!WORD 2
|
||||
;DCI "READ"
|
||||
!CT "hi.ascii"
|
||||
!TX "REA"
|
||||
!CT RAW
|
||||
!TX 'D'
|
||||
!BYTE $10
|
||||
!WORD 3
|
||||
;DCI "MEMSET"
|
||||
!CT "hi.ascii"
|
||||
!TX "MEMSE"
|
||||
!CT RAW
|
||||
!TX 'T'
|
||||
!BYTE $10
|
||||
!WORD 4
|
||||
;
|
||||
; EXPORT TABLE
|
||||
;
|
||||
EXPTBL ;DCI "INCNT" ; ENTRY SYMBOL NAME
|
||||
!CT "hi.ascii"
|
||||
!TX "INCN"
|
||||
!CT RAW
|
||||
!TX 'T'
|
||||
!BYTE $08 ; ENTRY SYMBOL FLAG
|
||||
!WORD INCCNT ; OFFSET
|
||||
;DCI "MYFUNC"
|
||||
!CT "hi.ascii"
|
||||
!TX "MYFUN"
|
||||
!CT RAW
|
||||
!TX 'C'
|
||||
!BYTE $08
|
||||
!WORD MYFUNC
|
||||
!BYTE 0 ; END OF ESD
|
39
PLASMA/src/symbols.h
Executable file
39
PLASMA/src/symbols.h
Executable file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Symbol table types.
|
||||
*/
|
||||
#define GLOBAL_TYPE (0)
|
||||
#define CONST_TYPE (1 << 0)
|
||||
#define WORD_TYPE (1 << 1)
|
||||
#define BYTE_TYPE (1 << 2)
|
||||
#define VAR_TYPE (WORD_TYPE | BYTE_TYPE)
|
||||
#define ASM_TYPE (1 << 3)
|
||||
#define DEF_TYPE (1 << 4)
|
||||
#define BRANCH_TYPE (1 << 5)
|
||||
#define FUNC_TYPE (ASM_TYPE | DEF_TYPE)
|
||||
#define LOCAL_TYPE (1 << 6)
|
||||
#define EXTERN_TYPE (1 << 7)
|
||||
#define ADDR_TYPE (VAR_TYPE | FUNC_TYPE | EXTERN_TYPE)
|
||||
#define WPTR_TYPE (1 << 8)
|
||||
#define BPTR_TYPE (1 << 9)
|
||||
#define PTR_TYPE (BPTR_TYPE | WPTR_TYPE)
|
||||
#define STRING_TYPE (1 << 10)
|
||||
#define TAG_TYPE (1 << 11)
|
||||
#define EXPORT_TYPE (1 << 12)
|
||||
|
||||
int id_match(char *name, int len, char *id);
|
||||
int idlocal_lookup(char *name, int len);
|
||||
int idglobal_lookup(char *name, int len);
|
||||
int idconst_lookup(char *name, int len);
|
||||
int idlocal_add(char *name, int len, int type, int size);
|
||||
int idglobal_add(char *name, int len, int type, int size);
|
||||
int id_add(char *name, int len, int type, int size);
|
||||
int idfunc_set(char *name, int len, int type);
|
||||
int idfunc_add(char *name, int len, int type, int tag);
|
||||
int idconst_add(char *name, int len, int value);
|
||||
int id_tag(char *name, int len);
|
||||
int id_const(char *name, int len);
|
||||
int id_type(char *name, int len);
|
||||
void idglobal_size(int type, int size, int constsize);
|
||||
int idlocal_size(void);
|
||||
void idlocal_reset(void);
|
||||
int tag_new(int type);
|
40
PLASMA/src/test.pla
Executable file
40
PLASMA/src/test.pla
Executable file
@@ -0,0 +1,40 @@
|
||||
;
|
||||
; Declare all imported modules and their data/functions.
|
||||
;
|
||||
import stdlib
|
||||
predef cls, gotoxy, puts, putc
|
||||
end
|
||||
;
|
||||
; Predeclare and functions called before defined.
|
||||
;
|
||||
predef main
|
||||
;
|
||||
; Declare all global variables for this module.
|
||||
;
|
||||
byte hello[] = "Hello, world.\n\n"
|
||||
word defptr = main
|
||||
;
|
||||
; Define functions.
|
||||
;
|
||||
|
||||
export def ascii
|
||||
byte i
|
||||
cls()
|
||||
for i = 32 to 127
|
||||
putc(i)
|
||||
next
|
||||
end
|
||||
|
||||
export def main
|
||||
cls()
|
||||
gotoxy(35,15)
|
||||
return puts(@hello)
|
||||
end
|
||||
|
||||
export def indirect
|
||||
word mainptr
|
||||
mainptr = @main
|
||||
mainptr()
|
||||
end
|
||||
|
||||
done
|
106
PLASMA/src/tokens.h
Executable file
106
PLASMA/src/tokens.h
Executable file
@@ -0,0 +1,106 @@
|
||||
|
||||
#define TOKEN(c) (0x80|(c))
|
||||
#define IS_TOKEN(c) (0x80&(c))
|
||||
/*
|
||||
* Identifier and constant tokens.
|
||||
*/
|
||||
#define ID_TOKEN TOKEN('V')
|
||||
#define CHAR_TOKEN TOKEN('Y')
|
||||
#define INT_TOKEN TOKEN('Z')
|
||||
#define FLOAT_TOKEN TOKEN('F')
|
||||
#define STRING_TOKEN TOKEN('S')
|
||||
/*
|
||||
* Keyword tokens.
|
||||
*/
|
||||
#define CONST_TOKEN TOKEN(1)
|
||||
#define BYTE_TOKEN TOKEN(2)
|
||||
#define WORD_TOKEN TOKEN(3)
|
||||
#define IF_TOKEN TOKEN(4)
|
||||
#define ELSEIF_TOKEN TOKEN(5)
|
||||
#define ELSE_TOKEN TOKEN(6)
|
||||
#define FIN_TOKEN TOKEN(7)
|
||||
#define END_TOKEN TOKEN(8)
|
||||
#define WHILE_TOKEN TOKEN(9)
|
||||
#define LOOP_TOKEN TOKEN(10)
|
||||
#define CASE_TOKEN TOKEN(11)
|
||||
#define OF_TOKEN TOKEN(12)
|
||||
#define DEFAULT_TOKEN TOKEN(13)
|
||||
#define ENDCASE_TOKEN TOKEN(14)
|
||||
#define FOR_TOKEN TOKEN(15)
|
||||
#define TO_TOKEN TOKEN(16)
|
||||
#define DOWNTO_TOKEN TOKEN(17)
|
||||
#define STEP_TOKEN TOKEN(18)
|
||||
#define NEXT_TOKEN TOKEN(19)
|
||||
#define REPEAT_TOKEN TOKEN(20)
|
||||
#define UNTIL_TOKEN TOKEN(21)
|
||||
#define PREDEF_TOKEN TOKEN(22)
|
||||
#define DEF_TOKEN TOKEN(23)
|
||||
#define ASM_TOKEN TOKEN(24)
|
||||
#define IMPORT_TOKEN TOKEN(25)
|
||||
#define EXPORT_TOKEN TOKEN(26)
|
||||
#define DONE_TOKEN TOKEN(27)
|
||||
#define RETURN_TOKEN TOKEN(28)
|
||||
#define BREAK_TOKEN TOKEN(29)
|
||||
#define START_TOKEN TOKEN(30)
|
||||
#define EXIT_TOKEN TOKEN(31)
|
||||
#define EVAL_TOKEN TOKEN(32)
|
||||
/*
|
||||
* Double operand operators.
|
||||
*/
|
||||
#define SET_TOKEN TOKEN('=')
|
||||
#define ADD_TOKEN TOKEN('+')
|
||||
#define ADD_SELF_TOKEN TOKEN('a')
|
||||
#define SUB_TOKEN TOKEN('-')
|
||||
#define SUB_SELF_TOKEN TOKEN('u')
|
||||
#define MUL_TOKEN TOKEN('*')
|
||||
#define MUL_SELF_TOKEN TOKEN('m')
|
||||
#define DIV_TOKEN TOKEN('/')
|
||||
#define DIV_SELF_TOKEN TOKEN('d')
|
||||
#define MOD_TOKEN TOKEN('%')
|
||||
#define OR_TOKEN TOKEN('|')
|
||||
#define OR_SELF_TOKEN TOKEN('o')
|
||||
#define EOR_TOKEN TOKEN('^')
|
||||
#define EOR_SELF_TOKEN TOKEN('x')
|
||||
#define AND_TOKEN TOKEN('&')
|
||||
#define AND_SELF_TOKEN TOKEN('n')
|
||||
#define SHR_TOKEN TOKEN('R')
|
||||
#define SHR_SELF_TOKEN TOKEN('r')
|
||||
#define SHL_TOKEN TOKEN('L')
|
||||
#define SHL_SELF_TOKEN TOKEN('l')
|
||||
#define GT_TOKEN TOKEN('>')
|
||||
#define GE_TOKEN TOKEN('H')
|
||||
#define LT_TOKEN TOKEN('<')
|
||||
#define LE_TOKEN TOKEN('B')
|
||||
#define NE_TOKEN TOKEN('U')
|
||||
#define EQ_TOKEN TOKEN('E')
|
||||
#define LOGIC_AND_TOKEN TOKEN('N')
|
||||
#define LOGIC_OR_TOKEN TOKEN('O')
|
||||
/*
|
||||
* Single operand operators.
|
||||
*/
|
||||
#define NEG_TOKEN TOKEN('-')
|
||||
#define COMP_TOKEN TOKEN('~')
|
||||
#define LOGIC_NOT_TOKEN TOKEN('!')
|
||||
#define INC_TOKEN TOKEN('P')
|
||||
#define DEC_TOKEN TOKEN('K')
|
||||
#define BPTR_TOKEN TOKEN('^')
|
||||
#define WPTR_TOKEN TOKEN('*')
|
||||
#define POST_INC_TOKEN TOKEN('p')
|
||||
#define POST_DEC_TOKEN TOKEN('k')
|
||||
#define OPEN_PAREN_TOKEN TOKEN('(')
|
||||
#define CLOSE_PAREN_TOKEN TOKEN(')')
|
||||
#define OPEN_BRACKET_TOKEN TOKEN('[')
|
||||
#define CLOSE_BRACKET_TOKEN TOKEN(']')
|
||||
/*
|
||||
* Misc. tokens.
|
||||
*/
|
||||
#define AT_TOKEN TOKEN('@')
|
||||
#define DOT_TOKEN TOKEN('.')
|
||||
#define COLON_TOKEN TOKEN(':')
|
||||
#define POUND_TOKEN TOKEN('#')
|
||||
#define COMMA_TOKEN TOKEN(',')
|
||||
#define COMMENT_TOKEN TOKEN(';')
|
||||
#define EOL_TOKEN TOKEN(0)
|
||||
#define EOF_TOKEN TOKEN(0x7F)
|
||||
|
||||
typedef unsigned char t_token;
|
Reference in New Issue
Block a user