/*--------------------------------------------------------------*/ /* 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); } /*--------------------------------------------------------------*/