/*--------------------------------------------------------------*/ /* TinC - Tiny, in C tinc10.c Dec 2004, 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 "tinc.h" #include FILE *ip = NULL; // input (source) file FILE *op = NULL; // output file FILE *op1 = NULL; // output file 1 FILE *op2 = NULL; // output file 2 FILE *tr = NULL; // trace file int tracing = TRUE; // tracing flag int opfile1 = TRUE; // output file flag 1 int opfile2 = FALSE; // output file flag 2 int interactive = 0; // interactive flag int trindent = 0; // trace indent level int linenumber = 0; // current source line number static void BoolExpression(); static void Block(); /*--------------------------------------------------------------*/ /* Symbol Tables etc */ static Symbol GS_Name[MAXGLOBALS]; // global symbol table (name) static char GS_Type[MAXGLOBALS]; // data type static int GS_Size[MAXGLOBALS]; // size (in 'data type' units) static Symbol LS_Name[MAXLOCALS]; // local symbol table (name) static char 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 long LCount = 0; // Label Count /*--------------------------------------------------------------*/ /* Definition of Keywords, etc */ static char Look; // Lookahead character static char Token; // Encoded Token static char Value[STRTMPSIZE]; // Unencoded Token /*--------------------------------------------------------------*/ /* Staging Buffer */ struct sbuff_struct { int pcode; char s1[MAXSYMSIZE]; char s2[MAXSYMSIZE]; char s3[MAXSYMSIZE]; } sbuff[MAXSTAGE]; long int sbufftop = 0; /*--------------------------------------------------------------*/ /* Dump the symbol table */ static void dump_symbol() { int tmp; char STR1[STRTMPSIZE]; if (!tracing) return; sprintf (STR1,"%%3d %%%ds %%c %%d\n",MAXSYMSIZE); fprintf (tr,"\nSymbol Table\n\n"); for (tmp=0; tmp0) { fprintf (tr,"\nLocal Table\n\n"); for (tmp=0; tmp0) { sprintf (STR1,"%%5d %%3d %%%ds %%%ds %%%ds\n",MAXSYMSIZE,MAXSYMSIZE,MAXSYMSIZE); fprintf (tr,"\nPCODES\n\n"); for (tmp=0; tmp' || c == '<' || c == '='); } /*--------------------------------------------------------------*/ /* Recognize White Space */ static int IsWhite(char c) { return (c == LF || c == CR || c == TAB || c == ' '); } /*--------------------------------------------------------------*/ /* Skip Over Leading White Space */ static void SkipWhite() { while (IsWhite(Look)) Getchar(); } /*--------------------------------------------------------------*/ /* 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)); } /*---------------------------------------------------------------*/ /* 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 */ static void SetGreater() { Stage (PC_SET_PRIMARY_GT,"","",""); } /*---------------------------------------------------------------*/ /* Set primary If Compare was < */ static void SetLess() { Stage (PC_SET_PRIMARY_LT,"","",""); } /*---------------------------------------------------------------*/ /* Set primary If Compare was <= */ static void SetLessOrEqual() { Stage (PC_SET_PRIMARY_LE,"","",""); } /*---------------------------------------------------------------*/ /* Set primary If Compare was >= */ static void SetGreaterOrEqual() { Stage (PC_SET_PRIMARY_GE,"","",""); } /*---------------------------------------------------------------*/ /* Branch Unconditional */ static void Branch(char *L) { Stage (PC_BRANCH,L,"",""); } /*---------------------------------------------------------------*/ /* Branch False */ static void BranchFalse(char *L) { Stage (PC_BRANCH_FALSE,L,"",""); } /*--------------------------------------------------------------*/ /* Write Header Info */ static void Header() { Stage (PC_HEADER,"","",""); } /*--------------------------------------------------------------*/ /* Write the Prolog */ static void Prolog() { Stage (PC_PROLOG,"","",""); } /*--------------------------------------------------------------*/ /* Write the Epilog */ static void Epilog() { char STR1[STRTMPSIZE]; sprintf (STR1,"%d",TotLocSize); if (TotLocSize) Stage (PC_SHRINKSTACK,STR1,"",""); Stage (PC_EPILOG,"","",""); } /*--------------------------------------------------------------*/ /* Allocate Storage for a static Variable */ static void Allocate(char *Name, char *Val) { Stage (PC_ALLOCATE,Name,Val,""); } /*--------------------------------------------------------------*/ /* Move address of var to Primary */ static void LoadAddrVar (char *varname) { switch (WhatIs(varname)) { case UNKNOWN: Undefined(varname); case GLOBAL: Stage (PC_MOVE_A_PRIMARY,varname,"",""); break; case LOCAL: Stage (PC_MOVE_AL_PRIMARY,varname,"",""); break; } } /*--------------------------------------------------------------*/ /* Pop to Secondary */ static void PopSec() { Stage (PC_POP_SECONDARY,"","",""); } /*--------------------------------------------------------------*/ /* Adjust Secondary according to variable's data type size */ static void AdjustSec(char *varname) { int dsize; char STR1[STRTMPSIZE]; switch (WhatIs(varname)) { case UNKNOWN: Undefined(varname); case GLOBAL: dsize = SizeOfType(GS_Type[Locate(varname)-1]); break; case LOCAL: dsize = SizeOfType(LS_Type[IsLocal(varname)-1]); break; } if (dsize != 1) { sprintf(STR1,"%d",dsize); Stage (PC_ADJUST_SECONDARY,varname,STR1,""); } } /*--------------------------------------------------------------*/ /* Add Primary to Secondary */ static void AddPrimSec() { Stage (PC_ADD_PRIMARY_SEC,"","",""); } /*--------------------------------------------------------------*/ /* Move [Secondary] to Primary */ static void MoveSecIPrim() { Stage (PC_MOVE_SI_PRIMARY,"","",""); } /*--------------------------------------------------------------*/ /* Move Primary to [Secondary] */ static void MovePrimSecI() { Stage (PC_MOVE_PRIMARY_SI,"","",""); } /*--------------------------------------------------------------*/ /* Parse and Translate a Math Factor */ static void Factor() { char SavedValue[STRTMPSIZE], SavedToken; trace ('+',"Factor",Value,"",0,0); if (Token == '(') { Next(); BoolExpression(); MatchString(")"); trace ('-',"Factor","","",0,0); return; } strcpy(SavedValue,Value); SavedToken=Token; Next(); if (SavedToken == TOK_IDENTIFIER) { if (Token == '[') { // an array element... Next(); BoolExpression(); // evaluate element MovePrimSec(); // save element to secondary MatchString("]"); LoadAddrVar(SavedValue); // load address of array to Primary AdjustSec(SavedValue); // adjust secondary by array's data type AddPrimSec(); // add primary to secondary MoveSecIPrim(); // move [secondary] to primary trace ('-',"Factor[]","","",0,0); return; } else LoadVar(SavedValue); } else if (SavedToken == TOK_NUM) LoadConst(SavedValue); else Expected("Math Factor"); trace ('-',"Factor.","","",0,0); } /*---------------------------------------------------------------*/ /* Recognize and Translate a Multiply */ static void Multiply() { Next(); Factor(); PopMul(); } /*---------------------------------------------------------------*/ /* Recognize and Translate a Divide */ static void Divide() { Next(); Factor(); PopDiv(); } /*---------------------------------------------------------------*/ /* Parse and Translate a Math Term */ static void Term() { trace ('+',"Term","","",0,0); Factor(); while (IsMulop(Token)) { Push(); switch (Token) { case '*': Multiply(); break; case '/': Divide(); break; } } trace ('-',"Term","","",0,0); } /*--------------------------------------------------------------*/ /* Recognize and Translate an Add */ static void Add() { Next(); Term(); PopAdd(); } /*-------------------------------------------------------------*/ /* Recognize and Translate a Subtract */ static void Subtract() { Next(); Term(); PopSub(); } /*---------------------------------------------------------------*/ /* Parse and Translate an Expression */ static void Expression() { trace ('+',"Expression","","",0,0); if (IsAddop(Token)) Clear(); else Term(); while (IsAddop(Token)) { Push(); switch (Token) { case '+': Add(); break; case '-': Subtract(); break; } } trace ('-',"Expression","","",0,0); } /*---------------------------------------------------------------*/ /* Get Another Expression and Compare */ static void CompareExpression() { Expression(); PopCompare(); } /*---------------------------------------------------------------*/ /* Get The Next Expression and Compare */ static void NextExpression() { Next(); CompareExpression(); } /*---------------------------------------------------------------*/ /* Recognize and Translate a Relational "Equals" */ static void Equal() { NextExpression(); SetEqual(); } /*---------------------------------------------------------------*/ /* Recognize and Translate a Relational "Less Than or Equal" */ static void LessOrEqual() { NextExpression(); SetLessOrEqual(); } /*---------------------------------------------------------------*/ /* Recognize and Translate a Relational "Not Equals" */ static void NotEqual() { NextExpression(); SetNEqual(); } /*---------------------------------------------------------------*/ /* Recognize and Translate a Relational "Less Than" */ static void Less() { Next(); switch (Token) { case '=': LessOrEqual(); break; case '>': NotEqual(); break; default: CompareExpression(); SetLess(); break; } } /*---------------------------------------------------------------*/ /* Recognize and Translate a Relational "Greater Than" */ static void Greater() { Next(); if (Token == '=') { NextExpression(); SetGreaterOrEqual(); } else { CompareExpression(); SetGreater(); } } /*---------------------------------------------------------------*/ /* Parse and Translate a Relation */ static void Relation() { Expression(); if (!IsRelop(Token)) return; Push(); switch (Token) { case '=': Equal(); break; case '<': Less(); break; case '>': Greater(); break; } } /*---------------------------------------------------------------*/ /* Parse and Translate a int Factor with Leading NOT */ static void NotFactor() { trace ('+',"NotFactor","","",0,0); if (Token != '!') { Relation(); trace ('-',"NotFactor","","",0,0); return; } Next(); Relation(); NotIt(); trace ('-',"NotFactor.","","",0,0); } /*---------------------------------------------------------------*/ /* Parse and Translate a int Term */ static void BoolTerm() { trace ('+',"BoolTerm","","",0,0); NotFactor(); while (Token == '&') { Push(); Next(); NotFactor(); PopAnd(); } trace ('-',"BoolTerm","","",0,0); } /*--------------------------------------------------------------*/ /* Recognize and Translate a int OR */ static void BoolOr() { Next(); BoolTerm(); PopOr(); } /*--------------------------------------------------------------*/ /* Recognize and Translate an Exclusive Or */ static void BoolXor() { Next(); BoolTerm(); PopXor(); } /*---------------------------------------------------------------*/ /* Parse and Translate a int Expression */ static void BoolExpression() { trace ('+',"BoolExpression","","",0,0); BoolTerm(); while (IsOrop(Token)) { Push(); switch (Token) { case '|': BoolOr(); break; case '~': BoolXor(); break; } } trace ('-',"BoolExpression","","",0,0); } /*--------------------------------------------------------------*/ /* Parse and Translate an Assignment Statement */ static void Assignment() { char Name[STRTMPSIZE]; trace ('+',"Assignment",Value,"",0,0); if (!InTable(Value) && !IsLocal(Value)) Undefined(Value); strcpy(Name, Value); Next(); if (Token == '[') { // an array element... Next(); BoolExpression(); // evaluate element MovePrimSec(); // save element to secondary MatchString("]"); LoadAddrVar(Name); // load address of array to primary AdjustSec(Name); // adjust element by array's data type AddPrimSec(); // add primary to secondary MatchString("="); PushSec(); // push LHS (an address) BoolExpression(); // process RHS PopSec(); // pop LHS (an address) to secondary MovePrimSecI(); // move primary to [secondary] } else { MatchString("="); BoolExpression(); Store(Name); } trace ('-',"Assignment","","",0,0); } /*---------------------------------------------------------------*/ /* Recognize and Translate an IF Construct */ static void DoIf() { char L1[STRTMPSIZE], L2[STRTMPSIZE]; trace ('+',"DoIf","","",0,0); Next(); BoolExpression(); NewLabel(L1); strcpy(L2, L1); BranchFalse(L1); Block(); if (Token == TOK_ELSE) { Next(); NewLabel(L2); Branch(L2); PostLabel(L1); Block(); } PostLabel(L2); MatchString("endif"); trace ('-',"DoIf","","",0,0); } /*--------------------------------------------------------------*/ /* Parse and Translate a WHILE Statement */ static void DoWhile() { char L1[STRTMPSIZE], L2[STRTMPSIZE]; trace ('+',"DoWhile","","",0,0); Next(); NewLabel(L1); NewLabel(L2); PostLabel(L1); BoolExpression(); BranchFalse(L2); Block(); MatchString("endwhile"); Branch(L1); PostLabel(L2); trace ('-',"DoWhile","","",0,0); } /*--------------------------------------------------------------*/ /* Parse and Translate a Block of Statements */ static void Block() { trace ('+',"Block","","",0,0); Scan(); while (Token != TOK_ELSE && Token != TOK_END) { switch (Token) { case TOK_IF: DoIf(); break; case TOK_WHILE: DoWhile(); break; default: Assignment(); break; } Scan(); } trace ('-',"Block","","",0,0); } /*--------------------------------------------------------------*/ /* Calculate array size of a declaration */ static int ArraySize() { int asize = 1; if (Token == '[') { Next(); Scan(); if (Token != TOK_NUM) Abort ("Number Expected"); asize = atoi(Value); Next(); MatchString("]"); } return asize; } /*--------------------------------------------------------------*/ /* Allocate Storage for a Variable */ static void Alloc(char datatype) { char STR1[STRTMPSIZE]; char name[MAXSYMSIZE+1]; int asize; trace ('+',"Alloc","","",0,0); Next(); if (Token != TOK_IDENTIFIER) Expected("Variable Name"); strcpy (name,Value); CheckDup(name); AddEntry(name, datatype); Next(); asize = ArraySize(); sprintf(STR1,"%d",SizeOfType(datatype)*asize); GS_Size[NumGlobals-1] = asize; Allocate(name, STR1); trace ('-',"Alloc","","",0,0); } /*--------------------------------------------------------------*/ /* Parse and Translate Global Declarations */ static void TopDecls() { char datatoken; linenumber = 1; trace ('+',"TopDecls","","",0,0); Scan(); while (Token == TOK_CHARDEF || Token == TOK_INTDEF) { datatoken = Token; Alloc(datatoken); while (Token == ',') Alloc(datatoken); Scan(); } trace ('-',"TopDecls","","",0,0); } /*--------------------------------------------------------------*/ /* Add a Local to Table */ static void AddLocal (char *name, char ltype) { trace ('+',"AddLocal","","",0,0); if (IsLocal(name)) Duplicate(name); strcpy(LS_Name[NumLocals],name); LS_Type[NumLocals]=ltype; NumLocals++; trace ('-',"AddLocal","","",0,0); } /*--------------------------------------------------------------*/ /* Allocate Storage for a Local Variable */ static void AllocLocal(char vtype) { char name[STRTMPSIZE]; int asize; trace ('+',"AllocLocal","","",0,0); Next(); if (Token != TOK_IDENTIFIER) Expected("Variable Name"); AddLocal(Value, vtype); strcpy(name,Value); Next(); asize = ArraySize(); LS_Size[NumLocals-1] = asize; TotLocSize += (asize * SizeOfType(vtype)); trace ('-',"AllocLocal",name,"",0,0); } /*--------------------------------------------------------------*/ /* Initialize Locals Table to Null */ static void ClearLocals() { int i; trace ('+',"ClearLocals","","",0,0); for (i=0; i