Initial import of PLASMA compiler and portable VM

This commit is contained in:
David Schmenk
2014-04-27 13:41:54 -07:00
parent 175a2b12d7
commit e29c5808b4
13 changed files with 3787 additions and 0 deletions

775
PLASMA/src/codegen.c Executable file
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

1
PLASMA/src/parse.h Executable file
View File

@@ -0,0 +1 @@
int parse_module(void);

17
PLASMA/src/plasm.c Executable file
View 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
View 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
View 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
View 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
View 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
View 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;