home *** CD-ROM | disk | FTP | other *** search
/ Compendium Deluxe 1 / LSD Compendium Deluxe 1.iso / a / programming / assemblers / cas.lha / st.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-14  |  12.4 KB  |  385 lines

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #include <string.h>
  5. #include "io.h"
  6. #include "ex.h"
  7. #include "op.h"
  8. #include "res.h"
  9.  
  10. #define MAX_ST 20
  11. typedef enum { BotS, IfS, ElseS, GroupS } StTag;
  12. byte Active;
  13. int Phase;
  14.  
  15. StTag SStack[MAX_ST], *SP;
  16. byte IStack[MAX_ST], *IP;
  17.  
  18. void PUSH(StTag Tag) {
  19.    if (SP >= SStack + MAX_ST) FATAL("Statement too complex");
  20.    *SP++ = Tag;
  21. }
  22.  
  23. void SetColon(byte Glo, Symbol Sym) {
  24.    if (!Active) return;
  25.    if (Sym->Defined) {
  26.       if (*Sym->Name != '#') {
  27.          ERROR("Attempting to redefine %s.", Sym->Name); return;
  28.       } else if (Glo) {
  29.          ERROR("Attempting to make local label global."); return;
  30.       } else {
  31.          Sym->Address = 1, Sym->Global = 0, Sym->Variable = 1;
  32.       }
  33.    } else if (Sym->Global) {
  34.       if (!Glo) {
  35.          ERROR("Symbol %s already declared as external.", Sym->Name); return;
  36.       } else if (!Sym->Address) {
  37.          ERROR("Symbol %s already declared as number.", Sym->Name); return;
  38.       } else if (Sym->Seg->Type != SegP->Type) {
  39.          ERROR("Type mismatch: %s.", Sym->Name); return;
  40.       }
  41.    } else
  42.       Sym->Address = 1, Sym->Global = Glo, Sym->Variable = 0;
  43.    Sym->Defined = 1, Sym->Seg = SegP, Sym->Offset = LOC;
  44. }
  45.  
  46. void SetVar(byte Glo, Symbol Sym, Exp E) {
  47.    if (!Active) return;
  48.    if (Sym->Defined && !Sym->Variable)
  49.       ERROR("Symbol %s already defined as constant.", Sym->Name);
  50.    else if (Glo)
  51.       ERROR("Variables cannot be made global.");
  52.    else if (Sym->Global)
  53.       ERROR("Symbol %s already declared as external.", Sym->Name);
  54.    else if (!Sym->Defined) {
  55.       if (E->Tag == AddrX)
  56.          Sym->Address = 1, Sym->Seg = SEG(E), Sym->Offset = OFFSET(E);
  57.       else
  58.          Sym->Address = 0, Sym->Offset = VALUE(E);
  59.       Sym->Variable = 1, Sym->Defined = 1;
  60.    } else if (Sym->Address) {
  61.       if (E->Tag != AddrX)
  62.          Sym->Seg = SegTab + Sym->Seg->Type, Sym->Offset = VALUE(E);         
  63.       else if (SEG(E)->Type != Sym->Seg->Type)
  64.          ERROR("Type mismatch: %s.", Sym->Name);
  65.       else
  66.          Sym->Seg = SEG(E), Sym->Offset = OFFSET(E);
  67.    } else if (E->Tag == AddrX) {
  68.       if (SEG(E)->Rel)
  69.          ERROR("Symbol %s cannot be set to relative address.", Sym->Name);
  70.       else
  71.          Sym->Offset = SEG(E)->Base + OFFSET(E);
  72.    } else
  73.       Sym->Offset = VALUE(E);
  74. }
  75.  
  76. void SetConst(byte Glo, byte Addr, byte Type, Symbol Sym, Exp E) {
  77.    if (!Active) return;
  78.    if (Addr && E->Tag == AddrX && SEG(E)->Type != Type) {
  79.       ERROR("Expression type does not match."); return;
  80.    } else if (Sym->Defined) {
  81.       ERROR("Symbol %s already defined.", Sym->Name); return;
  82.    } else if (!Sym->Global)
  83.       Sym->Global = Glo, Sym->Variable = 0, Sym->Address = (E->Tag == AddrX);
  84.    else if (!Glo) {
  85.       ERROR("Symbol %s already declared as external.", Sym->Name); return;
  86.    } else if (Sym->Address) {
  87.       if (Addr && Sym->Seg->Type != Type) {
  88.          ERROR("Symbol %s's type does not match.", Sym->Name); return;
  89.       } else if (E->Tag != AddrX) {
  90.          Sym->Defined = 1, Sym->Offset = VALUE(E); return;
  91.       } else if (SEG(E)->Type != Sym->Seg->Type) {
  92.          ERROR("Type mismatch: %s.", Sym->Name); return;
  93.       }
  94.    } else if (Addr) {
  95.       ERROR("Symbol %s already declared as external number.", Sym->Name);
  96.       return;
  97.    } else if (E->Tag == AddrX) {
  98.       if (SEG(E)->Rel) {
  99.          ERROR("Symbol %s cannot be equated to relative address.", Sym->Name);
  100.          return;
  101.       } else {
  102.          Sym->Defined = 1, Sym->Offset = SEG(E)->Base + OFFSET(E); return;
  103.       }
  104.    }
  105.    Sym->Defined = 1;
  106.    if (E->Tag == AddrX)
  107.       Sym->Seg = SEG(E), Sym->Offset = OFFSET(E);
  108.    else
  109.       Sym->Offset = VALUE(E);
  110. }
  111.  
  112. FILE *OpenObj(char *Obj) {
  113.    FILE *FP; word MAGIC = 0x55aa;
  114.    unsigned long L = 0; int I;
  115.    FP = fopen(Obj, "wb");
  116.    if (FP == 0) return 0;
  117.    PutW(MAGIC, FP);
  118.    for (I = 0; I < 8; I++) PutL(L, FP); /* Empty the header */
  119.    fclose(FP);
  120.    FP = fopen(Obj, "rb+");
  121.    if (FP == 0) return 0;
  122.    fseek(FP, 34L, SEEK_SET); /* Skip the header */
  123.    return FP;
  124. }
  125.  
  126. void Assemble(char *Path) {
  127.    Lexical L; Exp E; byte Glo, Addr, Type; Symbol Label;
  128.    Phase = 0;
  129.    SymInit(), FileInit(), SegInit(), ExpInit(), ResInit();
  130.    IP = IStack, SP = SStack;
  131.    Active = 1; RegInit(); OpenF(Path); L = Scan();
  132. START:
  133.    if (L == 0) { EndSeg(); return; }
  134.    PUSH(BotS);
  135. STATEMENT:
  136.    StartLine = Line, StartF = CurF;
  137.    switch (L) {
  138.       case IF:
  139.          L = Scan();
  140.          if (L != LPAR) ERROR("Missing '(' in 'if (...)'"); else Scan();
  141.          E = Parse(0);
  142.          PUSH(IfS), *IP++ = Active;
  143.          if (Active) Active = VALUE(E);
  144.          L = OldL;
  145.          if (L != RPAR) ERROR("Missing ')' in 'if (...)'."); else L = Scan();
  146.       goto STATEMENT;
  147.       case LCURL:
  148.          L = Scan();
  149.          if (L == RCURL) { L = Scan(); goto END_ST; }
  150.          PUSH(GroupS);
  151.       goto STATEMENT;
  152.       case SEMI: L = Scan(); goto END_ST;
  153.       case RB:
  154.          Scan(), InSemi = 1, E = Parse(0);
  155.          Space(VALUE(E));
  156.       goto SEM;
  157.       case RW:
  158.          Scan(), InSemi = 1, E = Parse(0);
  159.          Space(2*VALUE(E));
  160.       goto SEM;
  161.       case SEG:
  162.          L = Scan();
  163.          if (L != TYPE) { ERROR("Expected segment type."); goto PURGE; }
  164.          if (Value != CODE && Value != XDATA && Value != DATA) {
  165.             ERROR("Only code, xdata, or data segments allowed."); goto PURGE;
  166.          }
  167.          Type = Value;
  168.          InSemi = 1, L = Scan();
  169.          if (L == ORG) { InSemi = 0; goto DoOrg; }
  170.          if (Active) EndSeg(), StartSeg(Type, 1, 0);
  171.       goto SEM;
  172.       case ORG:
  173.          Type = SegP->Type;
  174.       DoOrg:
  175.          Scan(), InSemi = 1, E = Parse(0);
  176.          if (Active) EndSeg(), StartSeg(Type, 0, VALUE(E));
  177.       goto SEM;
  178.       case INCLUDE: {
  179.          char *S;
  180.          L = Scan();
  181.          if (L != STRING) FATAL("Missing filename in 'include'.");
  182.          S = CopyS(Text);
  183.          InSemi = 1, L = Scan();
  184.          if (L != SEMI) FATAL("Missing ';' after include statement.");
  185.          OpenF(S), free(S);
  186.          InSemi = 0, L = Scan();
  187.       }
  188.       goto END_ST;
  189.       case GLOBAL:
  190.          Glo = 1;
  191.          L = Scan();
  192.          if (L != SYMBOL) {
  193.             ERROR("Expected symbol after 'global'"); goto PURGE;
  194.          }
  195.       goto DEFINE;
  196.       case SYMBOL:
  197.          Glo = 0;
  198.       DEFINE:
  199.          Label = Sym; L = Scan();
  200.          switch (L) {
  201.             case COLON:
  202.                SetColon(Glo, Label);
  203.                InSemi = 1, L = Scan(), InSemi = 0;
  204.             goto STATEMENT;
  205.             case SET:
  206.                Scan(), InSemi = 1, E = Parse(1), SetVar(Glo, Label, E);
  207.             goto SEM;
  208.             case TYPE: Type = Value, Addr = 1; goto DoEqu;
  209.             case EQU: Type = 0, Addr = 0;
  210.             DoEqu:
  211.                Scan(), InSemi = 1, E = Parse(1);
  212.                SetConst(Glo, Addr, Type, Label, E);
  213.             goto SEM;
  214.             default: ERROR("Undefined symbol: %s.", Label->Name); goto PURGE;
  215.          }
  216.       break;
  217.       case EXTERN:
  218.          L = Scan();
  219.          if (L == EQU) Addr = 0;
  220.          else if (L == TYPE) Addr = 1, Type = Value;
  221.          else {
  222.             ERROR("Expected type or 'equ' after 'extern'."); goto PURGE;
  223.          }
  224.          InSemi = 1;
  225.          do {
  226.             L = Scan();
  227.             if (L != SYMBOL) {
  228.                ERROR("Expected symbol in 'extern'"); goto PURGE;
  229.             }
  230.             if (Active) {
  231.                if (Sym->Global) {
  232.                   byte Addr1 = Sym->Address;
  233.                   if (!Addr && Addr1)
  234.                      ERROR("Redeclaring number %s as address.", Sym->Name);
  235.                   else if (Addr && !Addr1)
  236.                      ERROR("Redeclaring address %s as number.", Sym->Name);
  237.                   else if (Addr && Addr1 && Type != Sym->Seg->Type)
  238.                      ERROR("Type mismatch: %s.", Sym->Name);
  239.                } else if (Sym->Defined)
  240.                   ERROR("Redeclaring local symbol %s as external.", Sym->Name);
  241.                else {
  242.                   Sym->Global = 1;
  243.                   if (Addr) Sym->Address = 1, Sym->Seg = SegTab + Type;
  244.                }
  245.             }
  246.             Scan();
  247.          } while (OldL == COMMA);
  248.       goto SEM;
  249.       case DB:
  250.          InSemi = 1;
  251.          do {
  252.             L = Scan();
  253.             if (L == STRING) PString(Text), Scan();
  254.             else Reloc(0, 'b', Parse(2));
  255.          } while (OldL == COMMA);
  256.       goto SEM;
  257.       case DW:
  258.          InSemi = 1;
  259.          do
  260.             Scan(), Reloc(0, 'w', Parse(2));
  261.          while (OldL == COMMA);
  262.       goto SEM;
  263.       case END:
  264.          if (Active) { EndSeg(); return; }
  265.          InSemi = 1, Scan();
  266.       goto SEM;
  267.       case MNEMONIC: InSemi = 1, ParseArgs((byte)Value); goto SEM;
  268.       default: ERROR("Syntax error"); goto PURGE;
  269.    }
  270. PURGE:
  271.    InSemi = 1;
  272.    while (L != SEMI) {
  273.       if (L == 0) { InSemi = 0; goto END_ST; }
  274.       L = Scan();
  275.    }
  276. SEM:
  277.    InSemi = 0; L = OldL;
  278.    if (L != SEMI) ERROR("Missing ';'"); else L = Scan();
  279. END_ST:
  280.    switch (*--SP) {
  281.       case BotS: goto START;
  282.       case IfS:
  283.          if (L == ELSE) {
  284.             if (IP == IStack || IP[-1]) Active = !Active;
  285.             *SP++ = ElseS, L = Scan(); goto STATEMENT;
  286.          }
  287.       case ElseS: EndIf:
  288.          if (*--IP && !Active) {
  289.             Active = 1;
  290.             if (L == SYMBOL) Sym = LookUp(Text);
  291.          }
  292.       goto END_ST;
  293.       case GroupS:
  294.          if (L == RCURL) { L = Scan(); goto END_ST; }
  295.          if (L == 0) { ERROR("Missing '}'."); goto END_ST; }
  296.          *SP++ = GroupS;
  297.       goto STATEMENT;
  298.    }
  299. }
  300.  
  301. static void Purge(void) {
  302.    Symbol Sym, NextS; Exp E, NextE; char **F;
  303.    for (Sym = NIL->Next[0]; Sym != NIL; Sym = NextS)
  304.       NextS = Sym->Next[0], free(Sym->Name), free(Sym);
  305.    for (F = FileTab; F < FileTab + Files; F++) free(*F);
  306.    free(FileTab);
  307.    free(NIL);
  308.    for (E = ExpHead; E != 0; E = NextE) NextE = E->Next, free(E);
  309.    free(RTab);
  310. }
  311.  
  312. void Generate(void) {
  313.    Symbol S; Segment Seg; Exp E; Item IP; word /*Value,*/ File; Gap G;
  314.    unsigned long SegLoc, Segs, Gaps, Syms, Exps, Relocs, Sum;
  315.    Phase = 1;
  316.    SegLoc = ftell(OutF), Segs = SegP - SegTab, Gaps = GapP - GapTab;
  317.    for (IP = RTab; IP < RTab + RCur; IP++) Resolve(IP);
  318.    fseek(OutF, SegLoc, SEEK_SET); /* Skip the code image */
  319.    for (File = 0; File < Files; File++) {
  320.       word L = strlen(FileTab[File]);
  321.       PutW(L, OutF), fwrite(FileTab[File], 1, L, OutF);
  322.    }
  323.    for (Seg = SegTab + TYPES; Seg < SegP; Seg++) {
  324.       word U = (Seg->Rel&1) << 8 | Seg->Type&0xff;
  325.       PutW(Seg->Line, OutF), PutW(Seg->File, OutF),
  326.       PutW(U, OutF), PutW(Seg->Size, OutF),
  327.       PutW(Seg->Base, OutF), PutL(Seg->Loc, OutF);
  328.    }
  329.    for (G = GapTab; G < GapP; G++)
  330.       PutW(G->Seg - SegTab, OutF), PutW(G->Offset, OutF), PutW(G->Size, OutF);
  331.    for (Syms = 0, S = NIL->Next[0]; S != NIL; S = S->Next[0])
  332.    if (S->Map || S->Global && S->Defined) {
  333.       byte B = (S->Global&1) << 3  | (S->Defined&1) << 2 |
  334.                (S->Address&1) << 1 | (S->Variable&1);
  335.       word U = S->Seg - SegTab, L = strlen(S->Name);
  336.       if (!S->Global && !S->Defined)
  337.          ERROR("Undefined symbol: %s.", S->Name);
  338.       S->Index = Syms++;
  339.       PutB(B, OutF), PutW(U, OutF), PutW(S->Offset, OutF), PutW(L, OutF);
  340.       if (L > 0) fwrite(S->Name, 1, L, OutF);
  341.    }
  342.    for (Exps = 0, E = ExpHead; E != 0; E = E->Next)
  343.    if (E->Map) {
  344.       byte Tag = E->Tag, Op; /* word U;*/
  345.       E->Hash = Exps++;
  346.       PutW(E->Line, OutF), PutW(E->File, OutF), PutB(Tag, OutF);
  347.       switch (Tag) {
  348.          case NumX: PutW(VALUE(E), OutF); break;
  349.          case AddrX:
  350.             PutW(SEG(E) - SegTab, OutF), PutW(OFFSET(E), OutF);
  351.          break;
  352.          case SymX: PutW(SYM(E)->Index, OutF); break;
  353.          case UnX:
  354.             Op = OP(E);
  355.             PutB(Op, OutF), PutW(ARG1(E)->Hash, OutF);
  356.          break;
  357.          case BinX:
  358.             Op = OP(E);
  359.             PutB(Op, OutF), PutW(ARG1(E)->Hash, OutF),
  360.             PutW(ARG2(E)->Hash, OutF);
  361.          break;
  362.          case CondX:
  363.             PutW(ARG1(E)->Hash, OutF), PutW(ARG2(E)->Hash, OutF),
  364.             PutW(ARG3(E)->Hash, OutF);
  365.          break;
  366.       }
  367.    }
  368.    for (Relocs = 0, IP = RTab; IP < RTab + RCur; IP++)
  369.    if (IP->Map) {
  370.       word U = IP->Seg - SegTab;
  371.       Relocs++;
  372.       PutW(IP->Line, OutF), PutW(IP->File, OutF),
  373.       PutB(IP->Tag, OutF), PutW(IP->E->Hash, OutF),
  374.       PutW(U, OutF),
  375.       PutW(IP->Offset, OutF);
  376.    }
  377.    fseek(OutF, 2L, SEEK_SET); /* Do the header */
  378.    PutL(SegLoc, OutF), PutL(Files, OutF), PutL(Segs, OutF),
  379.    PutL(Gaps, OutF), PutL(Syms, OutF), PutL(Exps, OutF), PutL(Relocs, OutF);
  380.    Sum = SegLoc + Files + Segs + Gaps + Syms + Exps + Relocs;
  381.    PutL(Sum, OutF);
  382.    fclose(OutF);
  383.    Purge();
  384. }
  385.