/*--------------------------------------------------------------*/
/*
TinC - Tiny, in C
tinc13.c
Jan 2005, Peter F. Gray
Extrapolated from Tiny 1.1 coded by Jack W. Crenshaw, in Pascal,
as part of Jack's "Let's Build A Compiler" tutorial.
*/
/*--------------------------------------------------------------*/
#include "tinc13.h"
#include <stdio.h>
FILE *ip[MAXINCL] = {NULL}; // input (source) file
int slevel = 0; // source level (for #includes)
long linenumber[MAXINCL] = {1}; // current source line number
char sname[MAXINCL][STRTMPSIZE];// current source name
FILE *op = NULL; // output file
FILE *op1 = NULL; // output file 1
FILE *op2 = NULL; // output file 2
FILE *tr = NULL; // trace file
FILE *pcd = NULL; // pcode dump file
FILE *sym = NULL; // symbol table file
int tracing = TRUE; // tracing flag
int opfile1 = TRUE; // output file flag 1
int opfile2 = TRUE; // output file flag 2
int genreguse = TRUE; // generate reg use pcodes
int genreguse2 = FALSE; // as above, but for the final code
int pcdump = TRUE; // unoptimized pcode dump flag
int pcdump2 = TRUE; // optimized pcode dump flag
int warn = TRUE; // warning flag
int wcount = 0; // warning count
int interactive = 0; // interactive flag
int trindent = 0; // trace indent level
long totallines = 0; // total number of source lines
int endofallsource = FALSE; // no more source to process
int ifdeflevel = 0; // #ifdef level
int section = -1; // section type
int optlevel = 1; // optimization level
extern void Gen_Item (int pcode, char *s1, char *s2, char *s3,
int t1, int t2);
extern void InitRegs();
extern void Optimize ();
static int BoolExpression(int);
static int Expression(int);
static void Block();
static void Next();
static void Scan();
void Abort();
int IsConst(char *);
void Header();
void Trailer();
/*--------------------------------------------------------------*/
/* Symbol Tables etc */
static Symbol GS_Name[MAXGLOBALS]; // global symbol table (name)
static int GS_Type[MAXGLOBALS]; // data type
static int GS_Size[MAXGLOBALS]; // size (in 'data type' units)
static int GS_ParamCount[MAXGLOBALS];
static int GS_ParamType[MAXGLOBALS][MAXPARAMS];
static Symbol LS_Name[MAXLOCALS]; // local symbol table (name)
static int LS_Type[MAXLOCALS]; // data type
static int LS_Size[MAXLOCALS]; // size (in 'data type' units)
static long NumGlobals = 0; // number of globals used
static long NumLocals = 0; // number of locals used
static int TotLocSize; // space required for locals
static Symbol DS_Name[MAXDEFS]; // definition table (name)
static Symbol DS_Value[MAXDEFS]; // definition table (value)
static long NumDefs = 0; // number of Defs used
static Symbol PS_Name[MAXPARAMS]; // parameter list (name)
static int PS_Type[MAXPARAMS]; // data type
static long NumParams = 0;
Symbol CS_Name[MAXCONSTS]; // constant symbol table (name)
int CS_Type[MAXCONSTS]; // data type
char CS_Value[MAXCONSTS][MAXCONSTSIZE];
static int CCount = 0; // # of autogen constants
int NumConsts = 0; // total # of constants
static long LCount = 0; // label Count
/*--------------------------------------------------------------*/
/* Definition of Keywords, etc */
static char Look = LF; // lookahead character
static char PrevLook; // previous 'Look'
static int Token; // encoded Token
static char Value[STRTMPSIZE] = {0}; // unencoded Token
/*--------------------------------------------------------------*/
/* Staging Buffer */
struct sbuff_struct {
int pcode;
char s1[MAXLINESIZE]; // allow for #inline
char s2[MAXSYMSIZE];
char s3[MAXSYMSIZE];
int t1;
int t2;
} sbuff[MAXSTAGE];
long int sbufftop = 0; // top of the staging buffer
long int sbuffopt = 0; // pcode reduction by optimizer
/*--------------------------------------------------------------*/
/* Register Control */
struct vreg_struct {
char inuse; // reg in use flag
int allowed; // data types this reg can be used for
int datatype; // data type being held in reg
char type; // type of reg (NORMAL or STACK)
} vreg[MAXREGS];
/*--------------------------------------------------------------*/
/* Return Data Type Description */
char *DataTypeDesc (int dtype)
{
switch (dtype) {
case DT_CHAR:
return "char"; break;
case DT_UCHAR:
return "uchar"; break;
case DT_INT:
return "int"; break;
case DT_UINT:
return "uint"; break;
case DT_CPTR:
return "char ptr"; break;
case DT_IPTR:
return "int ptr"; break;
case DT_UCPTR:
return "uchar ptr"; break;
case DT_UIPTR:
return "uint ptr"; break;
case DT_PROCEDURE:
return "procedure"; break;
case DT_INTERRUPT:
return "interrupt"; break;
default:
return "unknown"; break;
}
}
/*--------------------------------------------------------------*/
/* Return the datatype being held in Reg */
int RegDT (int regnum)
{
return vreg[regnum].datatype;
}
/*--------------------------------------------------------------*/
/* Dump the symbol tables */
static void dump_symbol()
{
int tmp,tmp2;
char STR1[STRTMPSIZE];
sprintf (STR1,"%%3d %%%ds %%%ds %%d\n",MAXSYMSIZE,TYPEDESCSIZE);
fprintf (sym,"\nSymbol Table\n\n");
for (tmp=0; tmp<NumGlobals; tmp++) {
fprintf (sym,STR1, tmp, GS_Name[tmp], DataTypeDesc(GS_Type[tmp]),
GS_Size[tmp]);
if (GS_Type[tmp] == DT_PROCEDURE) {
for (tmp2=0; tmp2<GS_ParamCount[tmp]; tmp2++)
fprintf (sym,"#%-3d %s\n",tmp2,DataTypeDesc(GS_ParamType[tmp][tmp2]));
}
}
fprintf (sym,"\n");
if (NumLocals>0) {
fprintf (sym,"\nLocal Table\n\n");
for (tmp=0; tmp<NumLocals; tmp++)
fprintf (sym,STR1, tmp, LS_Name[tmp], DataTypeDesc(LS_Type[tmp]),
LS_Size[tmp]);
fprintf (sym,"\n");
}
if (NumDefs>0) {
fprintf (sym,"\nDefinition Table\n\n");
sprintf (STR1,"%%3d %%%ds %%%ds\n",MAXSYMSIZE,MAXSYMSIZE);
for (tmp=0; tmp<NumDefs; tmp++)
fprintf (sym,STR1, tmp, DS_Name[tmp], DS_Value[tmp]);
fprintf (sym,"\n");
}
if (NumConsts>0) {
fprintf (sym,"\nConstants Table\n\n");
for (tmp=0; tmp<NumConsts; tmp++) {
fprintf (sym,"#%-3d %s %s\n",tmp,CS_Name[tmp],DataTypeDesc(CS_Type[tmp]));
tmp2 = 0;
while (CS_Value[tmp][tmp2]) {
fprintf(sym,"%c",CS_Value[tmp][tmp2]);
tmp2++;
}
fprintf(sym,"\n");
}
fprintf (sym,"\n");
}
}
/*--------------------------------------------------------------*/
/* Dump the Staging Buffer */
static void dump_pcodes ()
{
int tmp;
char STR1[STRTMPSIZE];
if (sbufftop>0) {
sprintf (STR1,"%%5d %%3d %%%ds %%%ds %%%ds %%%ds %%%ds\n",
MAXSYMSIZE,MAXSYMSIZE,MAXSYMSIZE,TYPEDESCSIZE,TYPEDESCSIZE);
fprintf (pcd,"\nPCODES\n\n");
for (tmp=0; tmp<sbufftop; tmp++) {
fprintf (pcd,STR1, tmp, sbuff[tmp].pcode,
sbuff[tmp].s1,sbuff[tmp].s2,sbuff[tmp].s3,
DataTypeDesc(sbuff[tmp].t1),DataTypeDesc(sbuff[tmp].t2));
}
}
}
/*--------------------------------------------------------------*/
/* Compiler trace routine */
void trace (char porm, char *routine, char *p1, char *p2, char *p3)
{
int i;
if (tracing) {
if (porm == '-') trindent--;
for (i=0; i<trindent; i++) fprintf (tr," ");
if (p1[0] == 0)
fprintf (tr,"%c%s\n",porm,routine);
else
if (p2[0] == 0)
fprintf (tr,"%c%s [%s]\n",porm,routine,p1);
else
if (p3[0] == 0)
fprintf (tr,"%c%s [%s] [%s]\n",porm,routine,p1,p2);
else
fprintf (tr,"%c%s [%s] [%s] (%s)\n",porm,routine,p1,p2,p3);
if (porm == '+') trindent++;
}
}
/*--------------------------------------------------------------*/
/* Write the pcode to the Staging Buffer */
void EmitLn();
void EmitLn_notab();
void Abort();
void EmitChar(char);
void Stage (int pcode, char *s1, char *s2, char *s3, int t1, int t2)
{
sbuff[sbufftop].pcode = pcode;
strcpy (sbuff[sbufftop].s1,s1);
strcpy (sbuff[sbufftop].s2,s2);
strcpy (sbuff[sbufftop].s3,s3);
sbuff[sbufftop].t1 = t1;
sbuff[sbufftop].t2 = t2;
sbufftop++;
}
/*--------------------------------------------------------------*/
/* Process the Staging Buffer and generate assembly code */
static void Gen_Code (FILE *thisop)
{
FILE *saved_op;
saved_op = op;
op = thisop;
long int tmp;
for (tmp=0; tmp<sbufftop; tmp++) {
Gen_Item (sbuff[tmp].pcode,sbuff[tmp].s1,sbuff[tmp].s2,sbuff[tmp].s3,
sbuff[tmp].t1,sbuff[tmp].t2);
}
EmitLn("");
EmitLn("");
op = saved_op;
}
/*--------------------------------------------------------------*/
/* Trace and Stage a Register Instruction */
static void TraceGenReg (int pcode, char *txt, int regA, int regB, int extra)
{
char rA[4], rB[4];
sprintf (rA,"%d",regA);
sprintf (rB,"%d",regB);
switch (pcode) {
case PC_GETREG:
trace (' ',txt,DataTypeDesc(regB),rA,""); break;
case PC_FREEREG:
case PC_CLEAR_REG:
case PC_NOT_REG:
case PC_SET_REG_EQ:
case PC_SET_REG_NE:
case PC_SET_REG_GT:
case PC_SET_REG_LT:
case PC_SET_REG_LE:
case PC_SET_REG_GE:
trace (' ',txt,rA,"",""); break;
case PC_MOVE_REG_I:
trace (' ',txt,rA,rB,DataTypeDesc(extra));
Stage (pcode,rA,rB,DataTypeDesc(extra),RegDT(regA),RegDT(regB));
return;
case PC_PUSH_REG:
trace (' ',txt,rA,DataTypeDesc(RegDT(regA)),DataTypeDesc(regB));
Stage (pcode,rA,"","",RegDT(regA),regB);
return;
default:
trace (' ',txt,rA,rB,""); break;
}
if ( (pcode != PC_GETREG && pcode != PC_FREEREG) ||
((pcode == PC_GETREG || pcode == PC_FREEREG) && genreguse) )
Stage (pcode,rA,rB,"",RegDT(regA),RegDT(regB));
}
/*--------------------------------------------------------------*/
/* Grab a free register */
static int GetReg(char datatype)
{
int tmp;
for (tmp=0; tmp<MAXREGS; tmp++) if (!vreg[tmp].inuse) {
if (!(datatype & vreg[tmp].allowed)) continue;
vreg[tmp].inuse = TRUE;
vreg[tmp].datatype = datatype;
TraceGenReg (PC_GETREG,"GetReg",tmp,datatype,0);
return tmp;
}
// not enough available registers to process expression...
Abort("Stack depth exceeded (Expression too complex)");
}
/*--------------------------------------------------------------*/
/* Free a register */
static void FreeReg(int regnum)
{
vreg[regnum].inuse = FALSE;
vreg[regnum].datatype = ' ';
TraceGenReg (PC_FREEREG,"FreeReg",regnum,0,0);
}
/*--------------------------------------------------------------*/
/* Move a register */
static void MoveReg(int fromreg, int toreg)
{
TraceGenReg (PC_MOVE_REG,"MoveReg",fromreg,toreg,0);
}
/*--------------------------------------------------------------*/
/* Add a register */
static void AddReg(int fromreg, int toreg)
{
TraceGenReg (PC_ADD_REG,"AddReg",fromreg,toreg,0);
}
/*--------------------------------------------------------------*/
/* Subtract a register */
static void SubReg(int fromreg, int toreg)
{
TraceGenReg (PC_SUB_REG,"SubReg",fromreg,toreg,0);
}
/*--------------------------------------------------------------*/
/* Multiply a register */
static void MulReg(int fromreg, int toreg)
{
TraceGenReg (PC_MUL_REG,"MulReg",fromreg,toreg,0);
}
/*--------------------------------------------------------------*/
/* Divide a register */
static void DivReg(int fromreg, int toreg)
{
TraceGenReg (PC_DIV_REG,"DivReg",fromreg,toreg,0);
}
/*--------------------------------------------------------------*/
/* Compare a register */
static void CompareReg(int fromreg, int toreg)
{
TraceGenReg (PC_COMPARE_REG,"CompareReg",fromreg,toreg,0);
}
/*--------------------------------------------------------------*/
/* AND a register */
static void AndReg(int fromreg, int toreg)
{
TraceGenReg (PC_AND_REG,"AndReg",fromreg,toreg,0);
}
/*--------------------------------------------------------------*/
/* OR a register */
static void OrReg(int fromreg, int toreg)
{
TraceGenReg (PC_OR_REG,"OrReg",fromreg,toreg,0);
}
/*--------------------------------------------------------------*/
/* XOR a register */
static void XorReg(int fromreg, int toreg)
{
TraceGenReg (PC_XOR_REG,"XorReg",fromreg,toreg,0);
}
/*--------------------------------------------------------------*/
/* Move [thisreg] to thatreg */
static void MoveIReg(int thisreg, int thatreg)
{
TraceGenReg (PC_MOVE_I_REG,"MoveIReg",thisreg,thatreg,0);
}
/*--------------------------------------------------------------*/
/* Move thisreg to [thatreg] */
static void MoveRegI(int thisreg, int thatreg, int targettype)
{
TraceGenReg (PC_MOVE_REG_I,"MoveRegI",thisreg,thatreg,targettype);
}
/*---------------------------------------------------------------*/
/* Clear a Register */
static void ClearReg(int thisreg)
{
TraceGenReg (PC_CLEAR_REG,"ClearReg",thisreg,0,0);
}
/*---------------------------------------------------------------*/
/* NOT (Completement) a Register */
static void NotReg(int thisreg)
{
TraceGenReg (PC_NOT_REG,"NotReg",thisreg,0,0);
}
/*---------------------------------------------------------------*/
/* Set Reg If Compare was = */
static void SetEqual(int thisreg)
{
TraceGenReg (PC_SET_REG_EQ,"SetRegEQ",thisreg,0,0);
}
/*---------------------------------------------------------------*/
/* Set Reg If Compare was <> */
static void SetNEqual(int thisreg)
{
TraceGenReg (PC_SET_REG_NE,"SetRegNE",thisreg,0,0);
}
/*---------------------------------------------------------------*/
/* Set Reg If Compare was > */
static void SetGreater(int thisreg)
{
TraceGenReg (PC_SET_REG_GT,"SetRegGT",thisreg,0,0);
}
/*---------------------------------------------------------------*/
/* Set Reg If Compare was < */
static void SetLess(int thisreg)
{
TraceGenReg (PC_SET_REG_LT,"SetRegLT",thisreg,0,0);
}
/*---------------------------------------------------------------*/
/* Set Reg If Compare was <= */
static void SetLessOrEqual(int thisreg)
{
TraceGenReg (PC_SET_REG_LE,"SetRegLE",thisreg,0,0);
}
/*---------------------------------------------------------------*/
/* Set Reg If Compare was >= */
static void SetGreaterOrEqual(int thisreg)
{
TraceGenReg (PC_SET_REG_GE,"SetRegGE",thisreg,0,0);
}
/*--------------------------------------------------------------*/
/* Read New character From Input Stream */
void GetcharX()
{
PrevLook = Look;
if (ip[slevel] == NULL)
Look = getchar();
else
Look = fgetc(ip[slevel]);
if (Look == -1) endofallsource = TRUE;
if (endofallsource && slevel > 0) {
fclose (ip[slevel]);
linenumber[slevel] = 0;
slevel--;
Look = LF;
endofallsource = FALSE;
}
}
/*--------------------------------------------------------------*/
/* Read New character, intercept comment */
void Getchar()
{
static char Tempchar = ' ';
if (Tempchar != ' ') {
Look = Tempchar;
Tempchar = ' ';
}
else {
GetcharX();
if (Look == '/') { // possible comment...
if (ip[slevel] == NULL)
Tempchar = getchar();
else
Tempchar = fgetc(ip[slevel]);
if (Tempchar == '*') { // yes, block comment...
Look = TOK_BLOCK_COMMENT;
Tempchar = ' ';
}
if (Tempchar == '/') { // yes, single-line comment...
Look = TOK_LINE_COMMENT;
Tempchar = ' ';
}
}
}
}
/*--------------------------------------------------------------*/
/* Report Error and Halt */
void Abort(char *s)
{
char STR1[STRTMPSIZE];
interactive = TRUE;
sprintf(STR1,"Error, line %d of %s : (%s) %s.",
linenumber[slevel],sname[slevel],Value,s);
EmitLn_notab (STR1);
dump_symbol();
exit(EXIT_FAIL);
}
/*--------------------------------------------------------------*/
/* Report an Warning */
static void Warn(char *s)
{
char STR1[STRTMPSIZE];
int tmp;
wcount++;
if (!warn) return;
tmp = interactive;
interactive = TRUE;
sprintf(STR1,"Warning, line %d of %s : (%s) %s.",
linenumber[slevel],sname[slevel],Value,s);
EmitLn_notab (STR1);
interactive = tmp;
}
/*--------------------------------------------------------------*/
/* Return the size (in base units) of a standard data type */
static int SizeOfType (int datatype)
{
switch (datatype) {
case DT_CHAR:
case DT_UCHAR:
return SIZEOFCHAR;
case DT_INT:
case DT_UINT:
case DT_CPTR:
case DT_IPTR:
case DT_UCPTR:
case DT_UIPTR:
return SIZEOFINT;
default:
Abort ("SizeOfType() - Unknown Data Type");
}
}
/*--------------------------------------------------------------*/
/* Pointer test for a data type (true or false returned) */
static int IsPointer (int datatype)
{
switch (datatype) {
case DT_CPTR:
case DT_IPTR:
case DT_UCPTR:
case DT_UIPTR:
return TRUE;
default:
return FALSE;
}
}
/*--------------------------------------------------------------*/
/* Report What Was Expected */
static void Expected(char *s)
{
char STR1[STRTMPSIZE];
sprintf(STR1, "%s expected", s);
Abort(STR1);
}
/*--------------------------------------------------------------*/
/* Report an Undefined Identifier */
static void Undefined(char *n)
{
char STR1[STRTMPSIZE];
sprintf(STR1, "Undefined Identifier '%s'", n);
Abort(STR1);
}
/*--------------------------------------------------------------*/
/* Report a Duplicate Identifier */
static void Duplicate(char *n)
{
char STR1[STRTMPSIZE];
sprintf(STR1, "Duplicate Identifier '%s'", n);
Abort(STR1);
}
/*--------------------------------------------------------------*/
/* Recognize an Alpha character */
static int IsAlpha(char c)
{
return isupper(toupper(c));
}
/*--------------------------------------------------------------*/
/* Recognize a Decimal Digit */
static int IsDigit(char c)
{
return isdigit(c);
}
/*--------------------------------------------------------------*/
/* Recognize a Hex Digit */
static int IsHex(char c)
{
return ( (c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F') );
}
/*--------------------------------------------------------------*/
/* Recognize an AlphaNumeric character (allow underscores) */
static int IsAlNum(char c)
{
return (IsAlpha(c) | IsDigit(c) | c=='_');
}
/*--------------------------------------------------------------*/
/* Recognize an Addop */
static int IsAddop(char c)
{
return (c == '-' || c == '+');
}
/*--------------------------------------------------------------*/
/* Recognize a Mulop */
static int IsMulop(char c)
{
return (c == '/' || c == '*');
}
/*--------------------------------------------------------------*/
/* Recognize a int Orop */
static int IsOrop(char c)
{
return (c == '~' || c == '|');
}
/*--------------------------------------------------------------*/
/* Recognize a Relop */
static int IsRelop(char c)
{
return (c == '>' || c == '<' || c == '=' || c == '!');
}
/*--------------------------------------------------------------*/
/* Recognize White Space */
static int IsWhite(char c)
{
if (c == LF) { linenumber[slevel]++; totallines++; }
return (c == LF || c == CR || c == TAB || c == ' '
|| c == TOK_BLOCK_COMMENT || c == TOK_LINE_COMMENT);
}
/*--------------------------------------------------------------*/
/* Skip A Block Comment */
static void SkipCommentBlock()
{
do {
do {
GetcharX();
if (Look == LF) { linenumber[slevel]++; totallines++; }
} while (Look != '*' && !endofallsource);
GetcharX();
if (Look == LF) { linenumber[slevel]++; totallines++; }
} while (Look != '/' && !endofallsource);
Getchar();
}
/*--------------------------------------------------------------*/
/* Skip A single-line Comment */
static void SkipCommentLine()
{
do GetcharX(); while (Look != LF && !endofallsource);
linenumber[slevel]++;
totallines++;
Getchar();
}
/*--------------------------------------------------------------*/
/* Skip Over Leading White Space */
static void SkipWhite()
{
while (IsWhite(Look)) {
switch (Look) {
case TOK_LINE_COMMENT: SkipCommentLine(); break;
case TOK_BLOCK_COMMENT: SkipCommentBlock(); break;
default: Getchar(); break;
}
}
}
/*--------------------------------------------------------------*/
/* Table Lookup */
static long Lookup(Symbol *T, char *s, long n)
{
long i;
int found;
found = FALSE;
i = n;
while (i > 0 && !found) {
if (!strcmp(s, T[i - 1]))
found = TRUE;
else
i--;
}
return i;
}
/*--------------------------------------------------------------*/
/* Locate a Symbol in the Global Table */
/* Returns the index of the entry. Zero if not present. */
static long Locate (char *N)
{
return (Lookup(GS_Name, N, NumGlobals));
}
/*--------------------------------------------------------------*/
/* Locate a Symbol in the Local Table */
/* Returns the index of the entry. Zero if not present. */
static long IsLocal (char *name)
{
return (Lookup(LS_Name, name, NumLocals));
}
/*--------------------------------------------------------------*/
/* Locate a Symbol in the Param Table */
/* Returns the index of the entry. Zero if not present. */
static int IsParam (char *name)
{
return (Lookup(PS_Name, name, NumParams));
}
/*--------------------------------------------------------------*/
/* Locate a Symbol in the Definition Table */
/* Returns the index of the entry. Zero if not present. */
static long IsDef (char *name)
{
return (Lookup(DS_Name, name, NumDefs));
}
/*--------------------------------------------------------------*/
/* Locate a Symbol in the Constants Table */
/* Returns the index of the entry. Zero if not present. */
int IsConst (char *name)
{
return (Lookup(CS_Name, name, NumConsts));
}
/*--------------------------------------------------------------*/
/* Test to see if 'name' is already known */
static int IsKnown (char *name)
{
return (Locate(name) || IsLocal(name) ||
IsParam(name) || IsConst(name));
}
/*--------------------------------------------------------------*/
/* Return the offset of a local within the stack frame */
static int LocalOffset (char *Name)
{
int offset = 0,i;
long element;
element = Lookup(LS_Name, Name, NumLocals);
for (i=0; i<element-1; i++)
offset += (LS_Size[i] * SizeOfType(LS_Type[i]));
return offset;
}
/*--------------------------------------------------------------*/
/* Return the offset of a param within the stack frame */
static int ParamOffset (char *Name)
{
int offset = 0,i;
long element;
element = Lookup(PS_Name, Name, NumParams);
for (i=NumParams-1; i>=element-1; i--)
offset += SizeOfType(PS_Type[i]);
return offset-1;
}
/*--------------------------------------------------------------*/
/* Look for Symbol in Table */
static int InTable(char *n)
{
return (Lookup(GS_Name, n, NumGlobals) != 0);
}
/*--------------------------------------------------------------*/
/* Check the Symbol Table for a Duplicate Identifier */
/* Report an error if identifier is already in table. */
static void CheckDup(char *N)
{
if (InTable(N)) Duplicate(N);
if (IsConst(N)) Duplicate(N);
}
/*--------------------------------------------------------------*/
/* Add a New Entry to Symbol Table */
static void AddEntry(char *N, int T)
{
trace ('+',"AddEntry",N,"","");
CheckDup(N);
if (NumGlobals == MAXGLOBALS) Abort("Symbol Table Full");
NumGlobals++;
strcpy(GS_Name[NumGlobals - 1], N);
GS_Type[NumGlobals - 1] = T;
trace ('-',"AddEntry","","","");
}
/*--------------------------------------------------------------*/
/* Add a New Entry to Definition Table */
static void AddDef(char *N, char *V)
{
trace ('+',"AddDef",N,V,"");
if (NumDefs == MAXDEFS) Abort("Definition Table Full");
NumDefs++;
strcpy(DS_Name[NumDefs - 1], N);
strcpy(DS_Value[NumDefs - 1], V);
trace ('-',"AddDef","","","");
}
/*--------------------------------------------------------------*/
/* Get an Identifier */
static void GetName()
{
trace ('+',"GetName","","","");
SkipWhite();
if (!IsAlpha(Look)) Expected("Identifier");
Token = TOK_IDENTIFIER;
*Value = '\0';
do {
sprintf(Value + strlen(Value), "%c", Look);
Getchar();
} while (IsAlNum(Look));
trace ('-',"GetName",Value,"","");
}
/*--------------------------------------------------------------*/
/* Get a Number */
static void GetNum()
{
trace ('+',"GetNum","","","");
SkipWhite();
if (!IsDigit(Look)) Expected("Number");
Token = TOK_NUM;
*Value = '\0';
do {
sprintf(Value + strlen(Value), "%c", Look);
Getchar();
} while (IsDigit(Look));
trace ('-',"GetNum",Value,"","");
}
/*--------------------------------------------------------------*/
/* Get a Hex Number */
static void GetHexNum()
{
trace ('+',"GetHexNum","","","");
SkipWhite();
Getchar(); // skip the $
if (!IsHex(Look)) Expected("Hex number");
Token = TOK_HEX;
*Value = '$';
*(Value+1) = '\0';
do {
sprintf(Value + strlen(Value), "%c", Look);
Getchar();
} while (IsHex(Look));
trace ('-',"GetHexNum",Value,"","");
}
/*--------------------------------------------------------------*/
/* Get a Character Literal */
static void GetCharLit()
{
trace ('+',"GetCharLit","","","");
SkipWhite();
Getchar(); // skip the '
Token = TOK_NUM;
sprintf(Value,"%d",Look);
Getchar(); // skip the '
if (Look != '\'') Expected ("Character literal");
Getchar();
trace ('-',"GetCharLit",Value,"","");
}
/*--------------------------------------------------------------*/
/* Get a Directive */
static void GetDirective()
{
int tracesave;
trace ('+',"GetDirective","","","");
if (PrevLook != LF) Expected("Directive at start of line");
SkipWhite();
Token = TOK_DIRECTIVE;
*Value = '\0';
do {
sprintf(Value + strlen(Value), "%c", Look);
Getchar();
} while (IsAlpha(Look));
Scan();
trace ('-',"GetDirective",Value,"","");
}
/*--------------------------------------------------------------*/
/* Get an Operator */
static void GetOp()
{
trace ('+',"GetOp","","","");
SkipWhite();
Token = Look;
sprintf(Value, "%c", Look);
Getchar();
trace ('-',"GetOp",Value,"","");
}
/*--------------------------------------------------------------*/
/* Process a #define directive */
static void DoDefine()
{
char STR1[STRTMPSIZE], STR2[STRTMPSIZE];
trace ('+',"DoDefine","","","");
GetName();
if (IsDef(Value)) Abort("Already defined");
strcpy(STR1,Value);
Next();
strcpy(STR2,Value);
AddDef(STR1,STR2);
Next();
Scan();
trace ('-',"DoDefine","","","");
}
/*--------------------------------------------------------------*/
/* Process a #inline directive */
static void DoInline()
{
SkipWhite();
if (Look != '\"') Expected(" \" ");
GetcharX();
*Value = '\0';
do {
sprintf(Value + strlen(Value), "%c", Look);
GetcharX();
} while (Look != '\"' && !endofallsource);
Stage (PC_INLINE,Value,"","",0,0);
trace (' ',"Inline",Value,"","");
Getchar();
Next();
Scan();
}
/*--------------------------------------------------------------*/
/* Translate to definition, if required */
static void translate_def ()
{
if (IsDef(Value)) {
trace (' ',"translate_def","","","");
strcpy(Value,DS_Value[IsDef(Value)-1]);
Token=Value[0];
if (IsAlpha(Token)) Token = TOK_IDENTIFIER;
if (IsDigit(Token)) Token = TOK_NUM;
if (Token == '$') Token = TOK_HEX;
if (Token == '\'') Token = TOK_NUM;
}
}
/*--------------------------------------------------------------*/
/* Get the Next Input Token */
static void Next()
{
trace ('+',"Next","","","");
SkipWhite();
if (Look == '#') { // a directive
GetDirective();
trace ('-',"Next#","","","");
return;
}
if (Look == '\'') { // a character literal
GetCharLit();
trace ('-',"NextC","","","");
return;
}
if (IsAlpha(Look)) { // a name
GetName();
translate_def();
trace ('-',"NextN","","","");
return;
}
if (IsDigit(Look)) // a number
GetNum();
else
if (Look == '$') // a hex number
GetHexNum();
else
GetOp(); // an operator
trace ('-',"Next","","","");
}
/*--------------------------------------------------------------*/
/* Scan the Current Identifier for Keywords */
static void Scan()
{
trace ('+',"Scan",Value,"","");
if (Token == TOK_IDENTIFIER || Token == TOK_DIRECTIVE)
Token = KWcode[Lookup(KWlist, Value, (long)NKW)];
trace ('-',"Scan","","","");
}
/*--------------------------------------------------------------*/
/* Match a Specific Input String */
static void MatchString(char *x)
{
char STR2[STRTMPSIZE];
if (strcmp(Value, x)) {
sprintf(STR2, "'%s'", x);
Expected(STR2);
}
Next();
}
/*--------------------------------------------------------------*/
/* Skip semicolons, if present */
static void Semi()
{
if (Token == ';') Next();
}
/*--------------------------------------------------------------*/
/* Output a Char */
void EmitChar(char s)
{
if (interactive) printf("%c", s);
if (op != NULL) fprintf(op,"%c", s);
}
/*--------------------------------------------------------------*/
/* Output a String with Tab */
static void Emit(char *s)
{
if (interactive) printf("%c%s", TAB, s);
if (op != NULL) fprintf(op,"%c%s", TAB, s);
}
/*--------------------------------------------------------------*/
/* Output a String without Tab */
static void Emit_notab(char *s)
{
if (interactive) printf("%s", s);
if (op != NULL) fprintf(op,"%s", s);
}
/*--------------------------------------------------------------*/
/* Output a String with Tab and CRLF */
void EmitLn(char *s)
{
Emit(s);
if (interactive) putchar('\n');
if (op != NULL) fprintf (op,"\n");
}
/*--------------------------------------------------------------*/
/* Output a String with CRLF, but no TAB */
void EmitLn_notab(char *s)
{
Emit_notab(s);
if (interactive) putchar('\n');
if (op != NULL) fprintf (op,"\n");
}
/*--------------------------------------------------------------*/
/* Generate a Unique Label */
static char *NewLabel(char *Result)
{
char S[STRTMPSIZE];
sprintf(S, "%ld", LCount);
sprintf(Result, "L%s", S);
LCount++;
return Result;
}
/*--------------------------------------------------------------*/
/* Post a Label To Output */
static void PostLabel(char *L)
{
Stage (PC_LABEL,L,"","",0,0);
}
/*---------------------------------------------------------------*/
/* Load a Constant Value to a Register */
static int LoadConst(char *n, int dt)
{
char cha[4], STR1[STRTMPSIZE];
int tmp, thisreg, datatype, newdt;
sprintf (STR1,"%s",DataTypeDesc(dt));
trace ('+',"LoadConst",n,STR1,"");
if (*n == '$') {
strcpy (STR1,"0x");
strcat (STR1,n+1);
tmp = strtol(STR1, (char **)NULL, 16);
} else {
tmp = atoi(n);
}
datatype = DT_INT;
if (tmp >= -32767 && tmp <= 32767) datatype = DT_INT;
if (tmp >= 0 && tmp < 256) datatype = DT_UCHAR;
if (tmp >= -127 && tmp <= 127) datatype = DT_CHAR;
newdt = datatype;
if (dt == DT_CPTR || dt == DT_UCPTR) newdt = DT_INT;
if ((newdt == DT_CHAR || newdt == DT_UCHAR) && dt == DT_INT) newdt = DT_INT;
if ((newdt == DT_CHAR || newdt == DT_UCHAR) && dt == DT_UINT) newdt = DT_UINT;
sprintf (STR1,"%s",DataTypeDesc(newdt));
trace (' ',"LoadConst",STR1,"","");
thisreg = GetReg(newdt);
sprintf (cha,"%d",thisreg);
Stage (PC_MOVE_CONST_REG,n,cha,"",0,RegDT(thisreg));
trace ('-',"LoadConst","","","");
return thisreg;
}
/*--------------------------------------------------------------*/
/* Initialize Parameter Table to Null */
static void ClearParams()
{
int i;
trace (' ',"ClearParams","","","");
for (i=0; i<MAXPARAMS; i++) *PS_Name[i] = 0;
NumParams = 0;
}
/*--------------------------------------------------------------*/
/* Add a Parameter to Table */
static void AddParam (char *name, int ptype)
{
trace (' ',"AddParam",name,"","");
if (IsParam(name)) Duplicate(name);
strcpy(PS_Name[NumParams],name);
PS_Type[NumParams] = ptype;
NumParams++;
}
/*---------------------------------------------------------------*/
/* Return the scope of a variable */
static int WhatIs(char *Name)
{
if (IsParam(Name)) return PARAM;
if (IsLocal(Name)) return LOCAL;
if (InTable(Name)) return GLOBAL;
return UNKNOWN;
}
/*---------------------------------------------------------------*/
/* Return the data type of a variable */
static int DataType(char *Name)
{
switch (WhatIs(Name)) {
case PARAM:
return PS_Type[IsParam(Name)-1];
break;
case LOCAL:
return LS_Type[IsLocal(Name)-1];
break;
case GLOBAL:
return GS_Type[Locate(Name)-1];
break;
case UNKNOWN:
Abort("Unknown data type");
}
}
/*---------------------------------------------------------------*/
/* Load a Variable to Register */
static int LoadVar(char *Name, int dt)
{
int offset, thisreg, newdt;
char STR1[STRTMPSIZE],STR2[STRTMPSIZE];
trace ('+',"LoadVar",Name,"","");
newdt = DataType(Name);
if (newdt == DT_PROCEDURE) Abort("Can not assign to/from a procedure");
if (newdt == DT_INTERRUPT) Abort("Can not assign to/from an interrupt");
if ((newdt == DT_CHAR || newdt == DT_UCHAR) && dt == DT_INT) newdt = DT_INT;
if ((newdt == DT_CHAR || newdt == DT_UCHAR) && dt == DT_UINT) newdt = DT_UINT;
switch (WhatIs(Name)) {
case PARAM:
offset = ParamOffset(Name);
sprintf(STR1,"%d",offset);
thisreg = GetReg(newdt);
sprintf(STR2,"%d",thisreg);
Stage (PC_MOVE_PVAR_REG,Name,STR1,STR2,DataType(Name),RegDT(thisreg));
break;
case LOCAL:
offset = LocalOffset(Name);
sprintf(STR1,"%d",offset);
thisreg = GetReg(newdt);
sprintf(STR2,"%d",thisreg);
Stage (PC_MOVE_LVAR_REG,Name,STR1,STR2,DataType(Name),RegDT(thisreg));
break;
case GLOBAL:
thisreg = GetReg(newdt);
sprintf(STR2,"%d",thisreg);
Stage (PC_MOVE_VAR_REG,Name,STR2,"",DataType(Name),RegDT(thisreg));
break;
case UNKNOWN:
Undefined(Name);
default:
Abort("Unsupported LoadVar mechanism");
}
trace ('-',"LoadVar","","","");
return thisreg;
}
/*---------------------------------------------------------------*/
/* Store Register to Variable */
static void Store(int thisreg, char *Name)
{
int offset;
char STR1[STRTMPSIZE],STR2[STRTMPSIZE];
trace ('+',"Store",Name,"","");
if (DataType(Name) == DT_PROCEDURE)
Abort("Can not assign to/from a procedure");
if (DataType(Name) == DT_INTERRUPT)
Abort("Can not assign to/from an interrupt");
sprintf(STR2,"%d",thisreg);
switch (WhatIs(Name)) {
case PARAM:
offset = ParamOffset(Name);
sprintf(STR1,"%d",offset);
Stage (PC_MOVE_REG_PVAR,STR2,Name,STR1,RegDT(thisreg),DataType(Name));
break;
case LOCAL:
offset = LocalOffset(Name);
sprintf(STR1,"%d",offset);
Stage (PC_MOVE_REG_LVAR,STR2,Name,STR1,RegDT(thisreg),DataType(Name));
break;
case GLOBAL:
Stage (PC_MOVE_REG_VAR,STR2,Name,"",RegDT(thisreg),DataType(Name));
break;
case UNKNOWN:
Undefined(Name);
default:
Abort("Unsupported Store mechanism");
}
FreeReg(thisreg);
trace ('-',"Store",Name,"","");
}
/*---------------------------------------------------------------*/
/* Branch Unconditional */
static void Branch(char *L)
{
trace (' ',"Branch",L,"","");
Stage (PC_BRANCH,L,"","",0,0);
}
/*---------------------------------------------------------------*/
/* Branch False */
static void BranchFalse(char *L, int thisreg)
{
char cha[4];
sprintf (cha,"%d",thisreg);
trace (' ',"BranchFalse",L,cha,"");
Stage (PC_BRANCH_FALSE,L,cha,"",RegDT(thisreg),0);
}
/*--------------------------------------------------------------*/
/* Write the Epilog */
static void Epilog(char *name, int isinterrupt)
{
char STR1[STRTMPSIZE];
sprintf (STR1,"%d",TotLocSize);
if (TotLocSize) Stage (PC_SHRINKSTACK,STR1,"Epilog - locals","",0,0);
if (isinterrupt) Stage (PC_POPFP,"","","",0,0);
if (isinterrupt)
Stage(PC_INTRET,"","","",0,0);
else
Stage(PC_CALLRET,"","","",0,0);
Stage (PC_EPILOG,name,"","",0,0);
}
/*--------------------------------------------------------------*/
/* Allocate Storage for a static Variable */
static void Allocate(char *Name, char *Val)
{
if (section != PC_DATASEC) {
section = PC_DATASEC;
Stage (PC_DATASEC,"","","",0,0);
}
Stage (PC_ALLOCATE,Name,Val,"",0,0);
}
/*--------------------------------------------------------------*/
/* Move address of var to Register */
static int LoadAVR (char *varname)
{
int thisreg;
char cha[4], coffset[6];
thisreg = GetReg(DT_INT);
sprintf (cha,"%d",thisreg);
switch (WhatIs(varname)) {
case PARAM:
sprintf(coffset,"%d",ParamOffset(varname));
Stage (PC_MOVE_AP_REG,varname,cha,coffset,DT_INT,RegDT(thisreg));
break;
case LOCAL:
sprintf(coffset,"%d",LocalOffset(varname));
Stage (PC_MOVE_AL_REG,varname,cha,coffset,DT_INT,RegDT(thisreg));
break;
case GLOBAL:
Stage (PC_MOVE_A_REG,varname,cha,"",DT_INT,RegDT(thisreg));
break;
case UNKNOWN:
Undefined(varname);
}
return thisreg;
}
/*--------------------------------------------------------------*/
/* Adjust Register according to variable's data type size */
static void AdjustReg(int thisreg, char *varname)
{
int dsize;
char STR1[STRTMPSIZE],STR2[STRTMPSIZE];
trace ('+',"AdjustReg",varname,"","");
switch (WhatIs(varname)) {
case PARAM:
dsize = SizeOfType(PS_Type[IsParam(varname)-1]);
break;
case LOCAL:
dsize = SizeOfType(LS_Type[IsLocal(varname)-1]);
break;
case GLOBAL:
dsize = SizeOfType(GS_Type[Locate(varname)-1]);
break;
case UNKNOWN:
Undefined(varname);
}
if (dsize != 1) {
sprintf(STR1,"%d",dsize);
sprintf(STR2,"%d",thisreg);
Stage (PC_ADJUST_REG,STR2,varname,STR1,RegDT(thisreg),0);
}
trace ('-',"AdjustReg","","","");
}
/*--------------------------------------------------------------*/
/* Parse and Translate a Math Factor */
static int Factor(int dt)
{
char SavedValue[STRTMPSIZE];
int SavedToken;
int thisreg, thatreg, dt2;
trace ('+',"Factor",Value,"","");
if (Token == '(') {
Next();
thisreg = BoolExpression(dt);
MatchString(")");
trace ('-',"Factor","","","");
return thisreg;
}
strcpy(SavedValue,Value);
SavedToken=Token;
Next();
switch (SavedToken) {
case TOK_IDENTIFIER:
if (Token == '[') { // an array element...
Next();
thisreg = Expression(DT_INT); // evaluate element
MatchString("]");
thatreg = LoadAVR(SavedValue); // load address of array
AdjustReg(thisreg,SavedValue); // adjust element by array's data type
AddReg(thatreg,thisreg); // add element to address
MoveIReg(thisreg,thatreg); // move [thisreg] to thatreg
FreeReg(thisreg);
trace ('-',"Factor[]","","","");
return thatreg;
}
else
thisreg = LoadVar(SavedValue,dt);
break;
case TOK_NUM:
case TOK_HEX:
thisreg = LoadConst(SavedValue,dt);
break;
case OP_PTR:
if (Token == TOK_IDENTIFIER) {
if (!IsPointer(DataType(Value))) Expected ("Pointer Data Type");
thatreg=LoadVar(Value,dt); // load var to thatreg
dt2 = DataType(Value);
if (dt2 == DT_CPTR) dt2 = DT_CHAR;
if (dt2 == DT_UCPTR) dt2 = DT_UCHAR;
if (dt2 == DT_IPTR) dt2 = DT_INT;
if (dt2 == DT_UIPTR) dt2 = DT_UINT;
thisreg=GetReg(dt2); // grab a register matching this datatype
}
else {
thatreg=LoadConst(Value,0); // load const to thatreg
thisreg=GetReg(DT_DEFAULT); // grab a register matching this datatype
}
MoveIReg(thatreg,thisreg); // move [thatreg] to thisreg
FreeReg(thatreg);
Next();
break;
case OP_ADDR: // address-of operator
switch (Token) {
case TOK_IDENTIFIER:
strcpy(SavedValue,Value);
SavedToken=Token;
Next();
if (Token == '[') { // an array element...
Next();
thisreg=Expression(DT_INT); // evaluate element
MatchString("]");
thatreg=LoadAVR(SavedValue); // load address of array
AdjustReg(thisreg,SavedValue); // adjust by array's data type
AddReg(thatreg,thisreg); // add address to adjusted element
FreeReg(thatreg);
trace ('-',"Factor&[]","","","");
return thisreg;
}
else
thisreg = LoadAVR(SavedValue);
trace ('-',"Factor&","","","");
return thisreg;
default:
Expected("Identifier after Address operator");
break;
}
default:
Expected("Math Factor");
break;
}
trace ('-',"Factor.","","","");
return thisreg;
}
/*---------------------------------------------------------------*/
/* Recognize and Translate a Multiply */
static int Multiply(int nextreg)
{
int thisreg, newdt;
trace ('+',"Multiply","","","");
Next();
if (OP_PTR == '*') { // C-style pointer op in use ?...
if (IsParam(Value) || InTable(Value) || IsLocal(Value)) {
if (IsPointer(DataType(Value)))
Warn ("Possible pointer misuse or missing ';'");
}
}
newdt = vreg[nextreg].datatype;
if (newdt == DT_CHAR) newdt = DT_INT;
if (newdt == DT_UCHAR) newdt = DT_UINT;
thisreg = Factor(newdt);
MulReg (nextreg,thisreg); // PopMul();
FreeReg (nextreg);
trace ('-',"Multiply","","","");
return thisreg;
}
/*---------------------------------------------------------------*/
/* Recognize and Translate a Divide */
static int Divide(int nextreg)
{
int thisreg;
trace ('+',"Divide","","","");
Next();
if (OP_PTR == '*') { // C-style pointer op in use ?...
if (IsParam(Value) || InTable(Value) || IsLocal(Value)) {
if (IsPointer(DataType(Value)))
Warn ("Possible pointer misuse");
}
}
thisreg = Factor(vreg[nextreg].datatype);
DivReg (nextreg,thisreg); // PopDiv();
FreeReg (nextreg);
trace ('-',"Divide","","","");
return thisreg;
}
/*---------------------------------------------------------------*/
/* Parse and Translate a Math Term */
static int Term(int dt)
{
int thisreg, nextreg = -1;
int savedtype;
trace ('+',"Term","","","");
thisreg = Factor(dt);
savedtype = vreg[thisreg].datatype;
while (IsMulop(Token)) {
if (nextreg = -1)
nextreg = thisreg;
else {
nextreg = GetReg(savedtype); // Push();
MoveReg (thisreg,nextreg);
FreeReg (thisreg);
}
switch (Token) {
case '*':
thisreg = Multiply(nextreg);
break;
case '/':
thisreg = Divide(nextreg);
break;
}
}
trace ('-',"Term","","","");
return thisreg;
}
/*--------------------------------------------------------------*/
/* Recognize and Translate an Add */
static int Add(int nextreg)
{
int thisreg,newdt;
trace ('+',"Add","","","");
Next();
newdt = vreg[nextreg].datatype;
if (newdt == DT_CHAR) newdt = DT_INT;
if (newdt == DT_UCHAR) newdt = DT_UINT;
thisreg = Term(newdt);
AddReg (nextreg,thisreg); // PopAdd();
FreeReg (nextreg);
trace ('-',"Add","","","");
return thisreg;
}
/*-------------------------------------------------------------*/
/* Recognize and Translate a Subtract */
static int Subtract(int nextreg)
{
int thisreg,newdt;
trace ('+',"Subtract","","","");
Next();
newdt = vreg[nextreg].datatype;
if (newdt == DT_CHAR) newdt = DT_INT;
if (newdt == DT_UCHAR) newdt = DT_UINT;
thisreg = Term(newdt);
SubReg (thisreg,nextreg); // PopSub();
FreeReg (thisreg);
trace ('-',"Subtract","","","");
return nextreg;
}
/*--------------------------------------------------------------*/
/* Parse and Translate an Expression */
static int Expression(int dt)
{
int thisreg,nextreg = -1;
int savedtype;
trace ('+',"Expression","","","");
if (IsAddop(Token)) {
thisreg = GetReg(dt);
ClearReg(thisreg); // Clear();
}
else
thisreg = Term(dt);
savedtype = vreg[thisreg].datatype;
trace (' ',"Expression","","","");
while (IsAddop(Token)) {
if (nextreg = -1)
nextreg = thisreg;
else {
nextreg = GetReg(savedtype); // Push();
MoveReg (thisreg,nextreg);
FreeReg (thisreg);
}
switch (Token) {
case '+':
thisreg = Add(nextreg);
break;
case '-':
thisreg = Subtract(nextreg);
break;
}
}
trace ('-',"Expression","","","");
return thisreg;
}
/*---------------------------------------------------------------*/
/* Get Another Expression and Compare */
static int CompareExpression(int nextreg)
{
int thisreg;
thisreg = Expression(0);
CompareReg (nextreg,thisreg); // PopCompare();
FreeReg (nextreg);
return thisreg;
}
/*---------------------------------------------------------------*/
/* Get The Next Expression and Compare */
static int NextExpression(int nextreg)
{
Next();
return CompareExpression(nextreg);
}
/*---------------------------------------------------------------*/
/* Recognize and Translate a Relational "Equals" */
static int Equal(int nextreg)
{
int thisreg;
thisreg = NextExpression(nextreg);
SetEqual(thisreg);
return thisreg;
}
/*---------------------------------------------------------------*/
/* Recognize and Translate a Relational "Less Than or Equal" */
static int LessOrEqual(int nextreg)
{
int thisreg;
thisreg = NextExpression(nextreg);
SetLessOrEqual(thisreg);
return thisreg;
}
/*---------------------------------------------------------------*/
/* Recognize and Translate a Relational "Not Equals" */
static int NotEqual(int nextreg)
{
int thisreg;
thisreg = NextExpression(nextreg);
SetNEqual(thisreg);
return thisreg;
}
/*---------------------------------------------------------------*/
/* Recognize and Translate a Relational "Less Than" */
static int Less(int nextreg)
{
int thisreg;
Next();
switch (Token) {
case '=':
thisreg = LessOrEqual(nextreg);
break;
case '>':
thisreg = NotEqual(nextreg);
break;
case '<':
Next();
thisreg = Expression(0);
TraceGenReg (PC_SHIFTLEFT,"ShiftLeft",nextreg,thisreg,0);
FreeReg(thisreg);
return nextreg;
default:
thisreg = CompareExpression(nextreg);
SetLess(thisreg);
break;
}
return thisreg;
}
/*---------------------------------------------------------------*/
/* Recognize and Translate a Relational "Greater Than" */
static int Greater(int nextreg)
{
int thisreg;
Next();
switch (Token) {
case '=':
thisreg = NextExpression(nextreg);
SetGreaterOrEqual(thisreg);
break;
case '>':
Next();
thisreg = Expression(0);
TraceGenReg (PC_SHIFTRIGHT,"ShiftRight",nextreg,thisreg,0);
FreeReg(thisreg);
return nextreg;
default:
thisreg = CompareExpression(nextreg);
SetGreater(thisreg);
break;
}
return thisreg;
}
/*---------------------------------------------------------------*/
/* Recognize and Translate a possible Relational "Not Equal" */
static int NEqual(int nextreg)
{
int thisreg;
Next();
if (Token == '=')
thisreg = NotEqual(nextreg);
else
Expected ("'!='");
return thisreg;
}
/*---------------------------------------------------------------*/
/* Parse and Translate a Relation */
static int Relation(int dt)
{
int thisreg, nextreg;
trace (' ',"Relation","","","");
thisreg = Expression(dt);
if (!IsRelop(Token)) return thisreg;
trace (' ',"Relation2","","","");
// Push();
switch (Token) {
case '=':
nextreg = Equal(thisreg);
break;
case '<':
nextreg = Less(thisreg);
break;
case '>':
nextreg = Greater(thisreg);
break;
case '!':
nextreg = NEqual(thisreg);
break;
}
trace (' ',"Relation3","","","");
return nextreg;
}
/*---------------------------------------------------------------*/
/* Parse and Translate a int Factor with Leading NOT */
static int NotFactor(int dt)
{
int thisreg;
trace ('+',"NotFactor","","","");
if (Token != '!') {
thisreg = Relation(dt);
trace ('-',"NotFactor","","","");
return thisreg;
}
Next();
thisreg = Relation(dt);
NotReg(thisreg);
trace ('-',"NotFactor.","","","");
return thisreg;
}
/*---------------------------------------------------------------*/
/* Parse and Translate a int Term */
static int BoolTerm(int dt)
{
int thisreg, nextreg = -1;
int savedtype;
trace ('+',"BoolTerm","","","");
thisreg = NotFactor(dt);
savedtype = vreg[thisreg].datatype;
while (Token == '&') {
if (nextreg == -1)
nextreg = thisreg;
else {
nextreg = GetReg(savedtype); // Push();
MoveReg (thisreg,nextreg);
FreeReg (thisreg);
}
Next();
thisreg = NotFactor(dt); // PopAnd();
AndReg (nextreg,thisreg);
FreeReg (nextreg);
}
trace ('-',"BoolTerm","","","");
return thisreg;
}
/*--------------------------------------------------------------*/
/* Recognize and Translate a int OR */
static int BoolOr(int nextreg)
{
int thisreg, newdt;
Next();
newdt = vreg[nextreg].datatype;
thisreg = BoolTerm(newdt); // PopOr();
OrReg (nextreg,thisreg);
FreeReg (nextreg);
return thisreg;
}
/*--------------------------------------------------------------*/
/* Recognize and Translate an Exclusive Or */
static int BoolXor(int nextreg)
{
int thisreg, newdt;
Next();
newdt = vreg[nextreg].datatype;
thisreg = BoolTerm(newdt); // PopXor();
XorReg (nextreg,thisreg);
FreeReg (nextreg);
return thisreg;
}
/*---------------------------------------------------------------*/
/* Parse and Translate a int Expression */
static int BoolExpression(int dt)
{
int thisreg, nextreg = -1;
int savedtype;
trace ('+',"BoolExpression","","","");
thisreg = BoolTerm(dt);
savedtype = vreg[thisreg].datatype;
while (IsOrop(Token)) {
if (nextreg = -1)
nextreg = thisreg;
else {
nextreg = GetReg(savedtype); // Push();
MoveReg (thisreg,nextreg);
FreeReg (thisreg);
}
switch (Token) {
case '|':
thisreg = BoolOr(nextreg);
break;
case '~':
thisreg = BoolXor(nextreg);
break;
}
}
trace ('-',"BoolExpression","","","");
return thisreg;
}
/*--------------------------------------------------------------*/
/* Push a Register */
static void PushReg (int regnum, int dt)
{
TraceGenReg (PC_PUSH_REG,"PushReg",regnum,dt,0);
}
/*--------------------------------------------------------------*/
/* Process a String Constant */
static int StringConst ()
{
char LitName[MAXSYMSIZE], LitVal[MAXCONSTSIZE], cha[4];
int thisreg, isnull = FALSE;
trace ('+',"StringConst","","","");
if (NumConsts >= MAXCONSTS) Abort ("Constants Table is full");
sprintf(LitName,"CS%d",CCount);
if (IsKnown(LitName)) Duplicate(LitName);
*Value = '\0';
if (Look == '"') // a null string?...
isnull = TRUE;
else {
do {
sprintf(Value + strlen(Value), "%c", Look);
GetcharX();
} while (Look != '"' && !endofallsource);
strcpy(CS_Value[NumConsts],Value);
}
strcpy(CS_Name[NumConsts],LitName);
if (isnull) {
CS_Type[NumConsts] = DT_INT;
strcpy(CS_Value[NumConsts],"0");
}
else {
CS_Type[NumConsts] = DT_CHAR;
}
Next(); // skip the end "
NumConsts++;
CCount++;
thisreg = GetReg(DT_INT);
sprintf(cha,"%d",thisreg);
Stage (PC_MOVE_A_REG,LitName,cha,"",0,RegDT(thisreg));
Next();
trace ('-',"StringConst","","","");
return thisreg;
}
/*--------------------------------------------------------------*/
/* Call a procedure */
static void DoCall(char *procname)
{
int protocount = 0, acount = 0, procpos, dt, resreg;
int pspace = 0;
char STR1[STRTMPSIZE];
trace ('+',"DoCall","","","");
procpos = Locate(procname)-1;
protocount = GS_ParamCount[procpos];
Next();
MatchString("(");
while (Token != ')') {
if (acount == protocount) Abort("Too many parameters");
dt = GS_ParamType[procpos][acount];
pspace += SizeOfType(dt);
if (Token == '"')
resreg = StringConst();
else
resreg = Expression(dt);
PushReg(resreg,dt);
FreeReg(resreg);
acount++;
Scan();
if (Token == ',') { Next(); Scan(); }
} // while (Token != ')')
if (protocount != acount) Abort("Too few parameters");
MatchString(")");
Stage (PC_PUSHFP,"","","",0,0);
Stage (PC_DOCALL,procname,"","",0,0);
Scan();
Stage (PC_POPFP,"","","",0,0);
if (pspace) {
sprintf (STR1,"%d",pspace);
Stage (PC_SHRINKSTACK,STR1,"remove params","",0,0);
}
trace ('-',"DoCall","","","");
}
/*--------------------------------------------------------------*/
/* Parse and Translate an Assignment Statement */
static void Assignment()
{
char Name[STRTMPSIZE];
int SavedToken;
int thisreg,thatreg = -1, dt;
trace ('+',"Assignment",Value,"","");
if (Token == OP_PTR) { // a pointer assignment...
dt=DT_DEFAULT;
Next();
SavedToken = Token;
switch (Token) {
case TOK_IDENTIFIER: // e.g. *name
dt=DataType(Value);
if (!IsParam(Value) && !InTable(Value) && !IsLocal(Value))
Undefined(Value);
if (!IsPointer(dt)) Expected ("Pointer Data Type");
case TOK_HEX: // e.g. *$FF00
strcpy(Name, Value);
Next();
MatchString("=");
if (SavedToken == TOK_IDENTIFIER) {
if (dt == DT_CPTR) dt = DT_CHAR;
if (dt == DT_UCPTR) dt = DT_UCHAR;
if (dt == DT_IPTR) dt = DT_INT;
if (dt == DT_UIPTR) dt = DT_UINT;
}
thisreg=BoolExpression(dt); // evaluate RHS
if (SavedToken == TOK_IDENTIFIER)
thatreg=LoadVar(Name,dt);
if (SavedToken == TOK_HEX)
thatreg=LoadConst(Name,dt);
MoveRegI(thisreg,thatreg,dt); // move RHS to [LHS]
FreeReg(thisreg);
FreeReg(thatreg);
trace ('-',"Assignment*","","","");
return;
default:
Abort("Unsupported pointer use");
}
}
if (!IsParam(Value) && !InTable(Value) && !IsLocal(Value))
Undefined(Value);
strcpy(Name, Value);
dt=DataType(Name);
if (dt == DT_INTERRUPT) Abort ("Invalid interrupt use");
if (dt == DT_PROCEDURE) // a procedure...
DoCall(Name);
else { // a non-pointer assignment...
Next();
if (Token == '[') { // an array element...
Next();
thisreg=Expression(DT_INT); // evaluate element
MatchString("]");
thatreg=LoadAVR(Name); // load address of array
AdjustReg(thisreg,Name); // adjust element by array's data type
AddReg(thatreg,thisreg); // sum
FreeReg(thatreg);
MatchString("=");
thatreg=BoolExpression(dt); // evaluate RHS
MoveRegI(thatreg,thisreg,dt); // move RHS to [sum]
FreeReg(thisreg);
FreeReg(thatreg);
}
else {
MatchString("=");
thisreg = BoolExpression(dt);
Store(thisreg,Name);
}
}
trace ('-',"Assignment","","","");
}
/*--------------------------------------------------------------*/
/* Recognize and Translate an IF Construct */
static void DoIf()
{
char L1[STRTMPSIZE], L2[STRTMPSIZE];
int thisreg;
trace ('+',"DoIf","","","");
Next();
MatchString("(");
thisreg = BoolExpression(0);
MatchString(")");
NewLabel(L1);
strcpy(L2, L1);
BranchFalse(L1,thisreg);
FreeReg(thisreg);
Block();
if (Token == TOK_ELSE) {
Next();
NewLabel(L2);
Branch(L2);
PostLabel(L1);
Block();
}
PostLabel(L2);
MatchString("endif");
trace ('-',"DoIf","","","");
}
/*--------------------------------------------------------------*/
/* Parse and Translate a WHILE Statement */
static void DoWhile()
{
char L1[STRTMPSIZE], L2[STRTMPSIZE];
int thisreg;
trace ('+',"DoWhile","","","");
Next();
MatchString("(");
NewLabel(L1);
NewLabel(L2);
PostLabel(L1);
thisreg = BoolExpression(0);
MatchString(")");
BranchFalse(L2,thisreg);
FreeReg(thisreg);
Block();
MatchString("endwhile");
Branch(L1);
PostLabel(L2);
trace ('-',"DoWhile","","","");
}
/*--------------------------------------------------------------*/
/* Parse and Translate a FOR Statement */
static void DoFor()
{
char L1[STRTMPSIZE], L2[STRTMPSIZE], L3[STRTMPSIZE], L4[STRTMPSIZE];
int thisreg;
trace ('+',"DoFor","","","");
Next();
MatchString("(");
NewLabel(L1);
NewLabel(L2);
NewLabel(L3);
NewLabel(L4);
Assignment(); // initial assignment
Semi();
PostLabel(L1);
thisreg = BoolExpression(0); // evaluate the condition
Semi();
BranchFalse(L2,thisreg); // skip out if condition false
FreeReg(thisreg);
Branch(L3); // jump to do the block
PostLabel(L4);
Assignment(); // end-of-block assignment
Semi();
MatchString(")");
Branch(L1); // jump to test the condition
PostLabel(L3);
Block(); // do the block
MatchString("endfor");
Branch(L4); // jump to do end-of-block assignment
PostLabel(L2);
FreeReg(thisreg);
trace ('-',"DoFor","","","");
}
/*--------------------------------------------------------------*/
/* Skip source until we have 1 less #endif */
static void IfDefSkip()
{
int newifdef;
newifdef = ifdeflevel - 1;
trace ('+',"IfDefSkip","","","");
while (ifdeflevel != newifdef && !endofallsource) {
do GetcharX(); while (Look != LF && !endofallsource);
linenumber[slevel]++; totallines++;
GetcharX();
if (Look == '#') {
*Value = '\0';
do {
sprintf(Value + strlen(Value), "%c", Look);
GetcharX();
} while (IsAlNum(Look));
Token = TOK_DIRECTIVE;
Scan();
if (Token == TOK_IFDEF) ifdeflevel++;
if (Token == TOK_ENDIFDEF) ifdeflevel--;
}
}
Next(); Scan();
trace ('-',"IfDefSkip","","","");
}
/*--------------------------------------------------------------*/
/* Process a #ifdef directive */
static void DoIfDef ()
{
trace ('+',"DoIfDef","","","");
ifdeflevel++;
SkipWhite();
if (IsAlpha(Look)) {
GetName();
if (IsDef(Value)) { // it's defined...
Next(); Scan();
}
else // it's not defined...
IfDefSkip();
}
else
Expected("Definition Name");
trace ('-',"DoIfDef","","","");
}
/*--------------------------------------------------------------*/
/* Process a #ifdef directive */
static void DoEndIfDef ()
{
if (ifdeflevel) {
ifdeflevel--;
Next(); Scan(); return;
}
else
Abort("#endif without #ifdef");
}
/*--------------------------------------------------------------*/
/* Parse and Translate a Block of Statements */
static void Block()
{
trace ('+',"Block","","","");
Scan();
while (Token != TOK_ELSE && Token != TOK_END && !endofallsource) {
switch (Token) {
case TOK_IF:
DoIf();
break;
case TOK_WHILE:
DoWhile();
break;
case TOK_FOR:
DoFor();
break;
case TOK_DEFINE:
DoDefine();
break;
case TOK_INLINE:
DoInline();
break;
case TOK_IDENTIFIER:
case OP_PTR:
Assignment();
break;
case TOK_IFDEF:
DoIfDef();
break;
case TOK_ENDIFDEF:
DoEndIfDef();
break;
default:
Expected("Valid language token");
break;
}
Semi();
Scan();
}
trace ('-',"Block","","","");
}
/*--------------------------------------------------------------*/
/* Calculate array size of a declaration */
static int ArraySize()
{
int asize = 1;
if (Token == '[') {
Next();
Scan();
if (Token != TOK_NUM) Expected ("Number");
asize = atoi(Value);
Next();
MatchString("]");
}
return asize;
}
/*--------------------------------------------------------------*/
/* Translate a declaration into a datatype */
static int TransDec (int isunsigned, int ispointer, int datatype)
{
int retcode;
if (isunsigned) {
if (datatype == TOK_CHARDEF) retcode = DT_UCHAR;
if (datatype == TOK_INTDEF) retcode = DT_UINT;
} else {
if (datatype == TOK_CHARDEF) retcode = DT_CHAR;
if (datatype == TOK_INTDEF) retcode = DT_INT;
}
if (ispointer) {
if (retcode == DT_CHAR) retcode = DT_CPTR;
if (retcode == DT_UCHAR) retcode = DT_UCPTR;
if (retcode == DT_INT ) retcode = DT_IPTR;
if (retcode == DT_UINT ) retcode = DT_UIPTR;
}
return retcode;
}
/*--------------------------------------------------------------*/
/* Allocate Storage for a Variable */
static void Alloc(int datatype, int isunsigned)
{
char STR1[STRTMPSIZE], name[MAXSYMSIZE+1];
int asize, ispointer = FALSE;
trace ('+',"Alloc","","","");
Next();
if (Token == OP_PTR) { ispointer=TRUE; Next(); }
if (Token != TOK_IDENTIFIER) Expected("Variable Name");
strcpy (name,Value);
CheckDup(name);
datatype = TransDec(isunsigned,ispointer,datatype);
AddEntry(name, datatype);
Next();
asize = ArraySize();
sprintf(STR1,"%d",SizeOfType(datatype)*asize);
GS_Size[NumGlobals-1] = asize;
if (ispointer && (asize!=1)) Abort("*name[] not allowed");
Allocate(name, STR1);
trace ('-',"Alloc","","","");
}
/*--------------------------------------------------------------*/
/* Get a file name */
static void GetFileName()
{
trace ('+',"GetFileName","","","");
SkipWhite();
// if (!IsAlpha(Look)) Expected("Identifier");
// Token = TOK_IDENTIFIER;
*Value = '\0';
do {
sprintf(Value + strlen(Value), "%c", Look);
Getchar();
} while (Look != '"');
trace ('-',"GetFileName",Value,"","");
}
/*--------------------------------------------------------------*/
/* Process a #include directive */
static void DoInclude()
{
trace ('+',"DoInclude","","","");
if (slevel+1 >= MAXINCL) Abort ("Maximum include depth exceeded");
Next();
if (Token != '"') Expected ("\"filename\"");
GetFileName();
trace (' ',"DoInclude",Value,"","");
if ((ip[slevel+1]=fopen(Value,"r"))==NULL)
Abort ("Include file not found");
slevel++;
strcpy (sname[slevel],Value);
Look = LF;
Next();
Scan();
trace ('-',"DoInclude","","","");
}
/*--------------------------------------------------------------*/
/* Parse and Translate Global Declarations */
static void TopDecls()
{
int datatoken;
int isunsigned = FALSE;
trace ('+',"TopDecls","","","");
Scan();
while (Token != TOK_PROGRAM && Token != TOK_PROCEDURE &&
Token != TOK_INTERRUPT && !endofallsource) {
switch (Token) {
case TOK_DEFINE:
DoDefine();
break;
case TOK_UNSIGNED:
Next(); Scan(); isunsigned = TRUE;
case TOK_CHARDEF:
case TOK_INTDEF:
datatoken = Token;
Alloc(datatoken,isunsigned);
while (Token == ',') Alloc(datatoken,isunsigned);
Semi();
Scan();
isunsigned = FALSE;
break;
case TOK_IFDEF:
DoIfDef();
break;
case TOK_ENDIFDEF:
DoEndIfDef();
break;
case TOK_INCLUDE:
DoInclude();
break;
default:
Expected("Valid Header Block Statement");
}
}
trace ('-',"TopDecls","","","");
}
/*--------------------------------------------------------------*/
/* Add a Local to Table */
static void AddLocal (char *name, char ltype)
{
trace ('+',"AddLocal","","","");
if (IsParam(name) || IsLocal(name)) Duplicate(name);
strcpy(LS_Name[NumLocals],name);
LS_Type[NumLocals]=ltype;
NumLocals++;
trace ('-',"AddLocal","","","");
}
/*--------------------------------------------------------------*/
/* Allocate Storage for a Local Variable */
static void AllocLocal(int vtype, int isunsigned)
{
char name[STRTMPSIZE], STR1[STRTMPSIZE], STR2[STRTMPSIZE], *sptr;
int asize, ispointer = FALSE;
trace ('+',"AllocLocal","","","");
Next();
if (Token == OP_PTR) { ispointer=TRUE; Next(); }
if (Token != TOK_IDENTIFIER) Expected("Variable Name");
vtype = TransDec(isunsigned,ispointer,vtype);
AddLocal(Value, vtype);
strcpy(name,Value);
Next();
asize = ArraySize();
LS_Size[NumLocals-1] = asize;
if (ispointer && (asize!=1)) Abort("*name[] not allowed");
sprintf (STR1,"%d",asize);
sptr = DataTypeDesc(vtype);
strcpy(STR2,sptr);
Stage (PC_GROWSTACK,name,STR1,STR2,0,0);
TotLocSize += (asize * SizeOfType(vtype));
trace ('-',"AllocLocal",name,"","");
}
/*--------------------------------------------------------------*/
/* Initialize Locals Table to Null */
static void ClearLocals()
{
int i;
trace ('+',"ClearLocals","","","");
for (i=0; i<MAXLOCALS; i++) {
*LS_Name[i] = 0; LS_Size[i] = 0; LS_Type[i] = 0;
}
NumLocals = 0;
trace ('-',"ClearLocals","","","");
TotLocSize = 0;
}
/*--------------------------------------------------------------*/
/* Process Local Variable Declarations */
static void DoLocals()
{
int datatoken;
int isunsigned = FALSE;
trace ('+',"DoLocals","","","");
ClearLocals();
Scan();
while ((Token == TOK_DEFINE || Token == TOK_UNSIGNED ||
Token == TOK_CHARDEF || Token == TOK_INTDEF ||
Token == TOK_IFDEF || Token == TOK_ENDIFDEF)
&& !endofallsource) {
switch (Token) {
case TOK_DEFINE:
DoDefine();
break;
case TOK_UNSIGNED:
Next(); Scan(); isunsigned = TRUE;
case TOK_CHARDEF:
case TOK_INTDEF:
datatoken = Token;
AllocLocal(datatoken,isunsigned);
while (Token == ',') AllocLocal(datatoken,isunsigned);
Semi();
Scan();
isunsigned = FALSE;
break;
case TOK_IFDEF:
DoIfDef();
break;
case TOK_ENDIFDEF:
DoEndIfDef();
break;
default:
Expected("Valid Program Block Statement");
}
}
trace ('-',"DoLocals","","","");
}
/*--------------------------------------------------------------*/
/* Write the Prolog */
static void Prolog(char *Name, int isinterrupt)
{
trace (' ',"Prolog","","","");
Stage(PC_PROLOG,Name,"","",0,0);
PostLabel(Name);
if (isinterrupt) Stage (PC_PUSHFP,"","","",0,0);
Stage (PC_SETFP,"","","",0,0);
}
/*--------------------------------------------------------------*/
/* Process the Formal Parameter List of a Procedure */
static int FormalList(int protoexists, char *procname)
{
int protocount = 0, ptype, isunsigned, pltype = 0;
int pcount = 0, procpos, ispointer;
char varnam[MAXSYMSIZE];
trace ('+',"FormalList","","","");
procpos = Locate(procname)-1;
if (protoexists) protocount = GS_ParamCount[procpos];
while (Token != ')') {
Scan();
if (Token == TOK_UNSIGNED) {
if (protoexists) Expected("Parameter Name or Blank");
isunsigned = TRUE; Next(); Scan(); pltype = 1;
}
else
isunsigned = FALSE;
if (Token == TOK_CHARDEF || Token == TOK_INTDEF) {
if (protoexists) Expected("Parameter List");
ptype = Token;
pltype = 1;
Next(); Scan();
if (Token == OP_PTR) {
if (protoexists) Expected("Parameter name or Blank");
ispointer = TRUE; Next(); Scan(); pltype = 1;
}
else {
if (Token != ',' && Token != ')' && Token != TOK_IDENTIFIER)
Abort("Unexpected character encountered");
ispointer = FALSE;
}
} else
if (isunsigned) Abort("Missing Data Type");
if (Token == TOK_IDENTIFIER) {
strcpy (varnam,Value);
Next(); Scan();
if (pltype == 1) pltype=3; else pltype = 2;
}
ptype = TransDec(isunsigned,ispointer,ptype);
switch (pltype) {
case 1: // datatype only
GS_ParamType[procpos][protocount] = ptype;
if (protocount >= MAXPARAMS) Abort("Max param count exceeded");
protocount++;
break;
case 2: // var name only
if (!protoexists) Expected ("Data type");
if (pcount >= MAXPARAMS) Abort("Max param count exceeded");
pcount++;
if (pcount > protocount) Abort ("Too many arguments");
AddParam(varnam,GS_ParamType[procpos][pcount-1]);
break;
case 3: // datatype and var
if (protoexists) Abort ("Data types already defined in prototype");
GS_ParamType[procpos][protocount] = ptype;
if (protocount >= MAXPARAMS) Abort("Max param count exceeded");
protocount++;
pcount++;
AddParam(varnam,ptype);
break;
}
while (Token == ',') {
Next(); Scan();
if (pltype == 1 || pltype == 3) { // datatype required
if (Token == TOK_UNSIGNED) {
isunsigned = TRUE; Next(); Scan();
}
else
isunsigned = FALSE;
if (Token == TOK_CHARDEF || Token == TOK_INTDEF) {
ptype = Token;
Next(); Scan();
if (Token == OP_PTR) {
ispointer = TRUE; Next(); Scan();
}
else
ispointer = FALSE;
} else
if (isunsigned) Abort("Missing Data Type");
ptype = TransDec(isunsigned,ispointer,ptype);
}
if (pltype == 2 || pltype == 3) { // var name required
if (Token == TOK_IDENTIFIER) {
strcpy (varnam,Value);
Next(); Scan();
} else
Expected ("Variable Name");
}
switch (pltype) {
case 1: // datatype only
GS_ParamType[procpos][protocount] = ptype;
if (protocount >= MAXPARAMS) Abort("Max param count exceeded");
protocount++;
break;
case 2: // var name only
if (pcount >= MAXPARAMS) Abort("Max param count exceeded");
pcount++;
if (pcount > protocount) Abort ("Too many arguments");
AddParam(varnam,GS_ParamType[procpos][pcount-1]);
break;
case 3: // datatype and var
GS_ParamType[procpos][protocount] = ptype;
if (protocount >= MAXPARAMS) Abort("Max param count exceeded");
protocount++;
pcount++;
AddParam(varnam,ptype);
break;
}
} // while (Token == ',')
} // while (Token != ')')
if (protoexists && (pcount != protocount)) Abort ("Too few arguments");
switch (pltype) {
case 0:
trace (' ',"FormalList PL0","","","");
break;
case 1:
trace (' ',"FormalList PL1","","","");
GS_ParamCount[procpos] = protocount;
break;
case 2:
trace (' ',"FormalList PL2","","","");
GS_ParamCount[procpos] = pcount;
break;
case 3:
trace (' ',"FormalList PL3","","","");
GS_ParamCount[procpos] = pcount;
break;
}
trace ('-',"FormalList","","","");
return pltype;
}
/*--------------------------------------------------------------*/
/* Parse and Translate procedure (and interrupt) blocks */
static void ProcedureBlock()
{
char Name[MAXSYMSIZE], STR1[STRTMPSIZE];
int protoexists, procexists, isinterrupt, pltype;
trace ('+',"ProcedureBlock","","","");
if (section != PC_PROGSEC) {
section = PC_PROGSEC;
Stage (PC_PROGSEC,"","","",0,0);
}
Branch(MAINNAME); // skip to "main"
while (Token == TOK_PROCEDURE || Token == TOK_INTERRUPT) {
isinterrupt = (Token == TOK_INTERRUPT);
Next(); // gets the procedure name
if (Token != TOK_IDENTIFIER) Expected ("Procedure Name");
strcpy(Name,Value);
procexists = Locate(Name);
protoexists = FALSE;
if (procexists) { // already exists...
if (isinterrupt && (GS_Type[procexists-1] != DT_INTERRUPT))
Duplicate(Name);
if ((!isinterrupt) && (GS_Type[procexists-1] != DT_PROCEDURE))
Duplicate(Name);
if (GS_Size[procexists-1] == 0) // as just a prototype?
protoexists = TRUE;
else
Duplicate(Name);
}
else { // a new procedure
trace (' ',"ProcedureBlockN","","","");
if (isinterrupt)
AddEntry(Name, DT_INTERRUPT);
else
AddEntry(Name, DT_PROCEDURE);
}
Next();
MatchString("(");
pltype = FormalList(protoexists, Name);
MatchString(")");
Scan();
if (Token == TOK_BEGIN) { // 'begin' found
trace (' ',"ProcedureBlockB","","","");
if (pltype == 1) Abort("Not valid for a prototype");
MatchString("begin");
if (protoexists)
GS_Size[procexists-1] = 1;
else
GS_Size[NumGlobals-1] = 1;
Prolog(Name,isinterrupt);
DoLocals();
Block();
MatchString("end");
Epilog(Name,isinterrupt);
Scan();
}
else { // no 'begin' - prototype
trace (' ',"ProcedureBlockP","","","");
if (protoexists) Expected("Prototype already defined - 'begin'");
Scan();
}
ClearParams();
}
trace ('-',"ProcedureBlock","","","");
}
/*--------------------------------------------------------------*/
/* Parse and Translate the main program block */
static void ProgramBlock()
{
trace (' ',"ProgramBlock","","","");
Next();
MatchString("begin");
if (section != PC_PROGSEC) {
section = PC_PROGSEC;
Stage (PC_PROGSEC,"","","",0,0);
}
Prolog(MAINNAME,FALSE);
DoLocals();
Block();
MatchString("end");
Epilog(MAINNAME,FALSE);
}
/*--------------------------------------------------------------*/
/* Initialize */
static void Init()
{
if (tracing) {
if ((tr=fopen("trace.txt","w"))==NULL)
Abort ("Can not open trace file");
fprintf (tr,COMPILER);
}
if (opfile1) {
if ((op1=fopen("out1.txt","w"))==NULL)
Abort ("Can not open output file 1");
fprintf (op1,"; "); fprintf (op1,COMPILER);
op = op1;
}
if (opfile2) {
if ((op2=fopen("out2.txt","w"))==NULL)
Abort ("Can not open output file 2");
fprintf (op2,"; "); fprintf (op2,COMPILER);
}
if (pcdump || pcdump2) {
if ((pcd=fopen("pcodes.txt","w"))==NULL)
Abort ("Can not open pcode dump file");
fprintf (pcd,COMPILER);
}
if ((sym=fopen("symbol.txt","w"))==NULL)
Abort ("Can not open symbol file");
fprintf (sym,COMPILER);
trace (' ',"Init","","","");
totallines = 1;
InitRegs();
ClearParams();
Getchar();
Next();
}
/*--------------------------------------------------------------*/
/* Main Program */
main(int argc, char *argv[])
{
printf ("\n"); printf (COMPILER);
if (argc < 2) {
interactive = TRUE;
EmitLn_notab ("Interactive Mode");
strcpy (sname[slevel],"STDIN");
}
else {
if ((ip[slevel]=fopen(argv[1],"r"))==NULL)
Abort ("File not found");
strcpy (sname[slevel],argv[1]);
}
Init();
Header();
TopDecls();
if (Token == TOK_PROCEDURE || Token == TOK_INTERRUPT) ProcedureBlock();
ProgramBlock();
Trailer();
if (ifdeflevel) Expected("#endif");
dump_symbol(); // dump the symbol tables to the trace file
if (pcdump) dump_pcodes(); // dump the unoptimized pcodes
Gen_Code(op1); // generate o/p from unopt pcodes to file 1
if (opfile2) {
Optimize();
if (pcdump2) dump_pcodes();
genreguse=genreguse2;
Gen_Code(op2); // generate output from optimized pcodes to file 2
}
printf ("\n%d source lines\n",totallines);
printf ("%d symbols used\n%d pcodes generated (%d after optimization)\n",
NumGlobals,sbufftop,sbufftop-sbuffopt);
printf ("%d warnings\n",wcount);
printf ("End of Compilation\n");
if (tracing) fclose (tr);
if (opfile1) fclose (op1);
if (opfile2) fclose (op2);
if (pcdump || pcdump2) fclose (pcd);
fclose (sym);
exit(EXIT_SUCCESS);
}
/*--------------------------------------------------------------*/