home *** CD-ROM | disk | FTP | other *** search
- {$M 16384,0,655360}
- (* ====================================================== *)
- (* NXO.PAS *)
- (* optimierender Naxos-Compiler Vers. 1.01 BETA *)
- (* (C) 1992 DMV-Verlag & K.Peper, A.Zissis, I.Tossounidis *)
- (* Compiler: Turbo Pascal 6.0 *)
- (* ------------------------------------------------------ *)
- (* Naxos basiert in seinen Grundlagen auf dem Software- *)
- (* Projekt SForth von DOS International *)
- (* (C) 1987 Volker Everts und DOS International *)
- (* sowie den Vorgängerprojekten FCC u. MCC *)
- (* (C) 1989 bis 1992 K.Peper, I.Tossounidis & A.Zissis *)
- (* ====================================================== *)
- {$M 65520,0,655350}
- {$N+,R-,S-,I-,A+,V+,X-,O-,G-,E+,D-,F-,L-}
-
- PROGRAM NaxosOpt;
- USES
- Crt, Dos;
-
- LABEL OkMCC;
-
- CONST
- Version = '1.01 BETA'; { Versionsnummer }
- MaxStack = 100; { Stack-Ebenen }
- Empty = ''; { leerer String }
- Space = #32; { Leerzeichen }
- NUL = #0; { Null-Zeichen }
- BEL = #7; { akust. Signal }
- CR = #13; { Wagenrücklauf }
- Apost = #39; { Hochkomma }
-
- { Typ-Bezeichner im Wörterbuch }
-
- _VAR = 1; { Datenvariable }
- _ARR = 2; { Datenarray }
- _REC = 3; { Datenrecord }
- _FLD = 4; { Datenfeld }
- _STRING = 5; { String }
- _DCONST = 15; { Double-Konstante}
- _FCONST = 16; { Real-Konst }
- _CONST = 10; { Konstante }
- _KOLON = 12; { Kolon-Def. }
- _PROC = 13; { Prozedur }
- _VECTOR = 14; { Vektor }
- _IF = 1; { IF-Flag }
- _BEGIN = 2; { BEGIN-Flag }
- _WHILE = 3; { WHILE-Flag }
- _DO = 4; { DO-Flag }
- _CASE = 5; { CASE-Flag }
-
- MaxZeile = 127; { max. Zeilenlänge}
- MaxProg = $F7FF; { Programmgröße }
- MaxIFB = $FEFF; { Inputfile Buffergröße }
- MaxName = 12; { Namensgröße }
-
-
- TYPE
- Memory = ARRAY[256..MaxProg] OF BYTE; { 62 KByte }
- pMemory = ^Memory;
- pDEPS = POINTER;
- pSymtab = ^Symtab;
- Symtab = RECORD
- Name : STRING[12];
- Typ : BYTE;
- QFA : WORD;
- Par0,
- Par1,
- Par2,
- Par3 : WORD;
- QFALen : WORD;
- Used : BOOLEAN;
- RLink,
- LLink : pSymtab;
- END;
- InfileBuf = ARRAY[0..MaxIFB] OF BYTE;
- IFBTyp = ^InfileBuf;
- WortTyp = STRING[16];
- ZeilenTyp = STRING[MaxZeile];
- HexStr = STRING[4];
-
- StackEintrag = RECORD
- Wert : INTEGER;
- Typ : BYTE;
- Size : BYTE;
- END;
-
- StackTyp = ARRAY[0..MaxStack] OF StackEintrag;
-
-
-
- VAR
- CRTReg : WORD ABSOLUTE $0040 : $0063;
- Result : RECORD
- CASE BOOLEAN OF
- TRUE : (ErrorPos : WORD;
- ErrorWort : STRING[16]);
- FALSE : (Main, Here,
- s0, r0, Zeilen, Bytes : WORD);
- END;
- r0, s0 : WORD;
- XFSize : LONGINT; { Inputfilegröße }
- ef : TEXT; { LOG.FILE im Shellmodus }
- QFAs : WORD; { QuellFileAdresse }
- Debug, { Intermediär-Quelltext }
- InFile : TEXT; { Forth-Quelltext }
- IncF : FILE; { includefile }
- OutFile : FILE; { compilierter Code }
- Zeile,
- LZ : ZeilenTyp; { Forth-Textzeile }
- LastTyp,
- WTyp : BYTE; { Worttyp }
- Wort, { Forth-Wort }
- VocName, { Vocabulary }
- Merker,
- Merker2 : WortTyp; { Merker }
- IFB : IFBTyp; { Inputfilebuffer }
- IFBp : WORD;
- IFBTop : WORD;
- Name : NameStr;
- Ext : ExtStr;
- Pfad,
- SysPfad : DirStr;
- DXName : STRING;
- DateiName : STRING; { Zugriffspfad }
- DMerker : pSymtab;
- pc, { Programmzähler }
- AdrMerker, { Merkt Adresse }
- PCMerker, { Merkt pc }
- QFA, { Quellfileptradr }
- Par0, { Parameter 0 }
- Par1, { Parameter 1 = LEN }
- Par2, { Parameter 2 }
- Par3,
- Felder, { Feldaccumulator }
- Macro, { Macrogrenze aktuell}
- MacroLim, { Vorgabegrenze }
- Sp, { Stackpointer }
- SPBuf,
- Nummer, { Zeilennummer }
- Anfang, { Anfang Dictionary }
- Ende, { Ende Dictionary }
- VocAnfang, { Start Vocabulary }
- OFCnt, { OF-Zähler }
- OFCntBuf,
- i, { Zählvariable }
- mn, { Main-Adresse }
- RecLen : WORD; { Datenlänge }
- FZeiger, { Zeiger auf gefundenes Wort }
- Zeiger : pSymtab; { Zeiger auf aktuelles wort }
- DicNo : WORD; { Dictionary Nummer }
- m : pMemory; { Speicherbereich }
- s,
- SBuf : StackTyp; { Kontroll-Stack }
- Root,
- d : pSymtab; { Wörterbuch }
-
- RegFix, { RegisterPräfix }
- CaseLit: INTEGER; { Literal vor OF }
-
- Sys, { System-Befehl }
- Main, { Hauptprogramm }
- CaseFlag, { für Case-Anweisung }
- CLitflag, { CaseLiteralflag }
- CaseFlagBuf,
- CLitFlagBuf,
- ExtSys,
- FlagStack, { Bedingungsstack }
- Found, { für Wortsuche }
- NoCodeFlag, { speichern ein/aus }
- IncludeFlag, { Nur ein Incl.file }
- ShortFlag, { Short-Jump ein/aus }
- XDBFlag, { Intermediärlisting ein/aus }
- Comment, { Kommentar }
- MapFlag : BOOLEAN; { Zur Erzeugung von MAP-Files }
- sif : FILE; { Globales Includefile }
- InDef : BOOLEAN; { In Definition Flag; True zwischen : oder PROC und ; }
- Extrn : BOOLEAN; { Externe Definition }
- Cv : RECORD
- CASE BOOLEAN OF
- TRUE : (l : LONGINT);
- FALSE : (Lo, Hi : WORD);
- END;
-
- FUNCTION BackPos(ch: CHAR; Str: STRING): BYTE;
- { Ermittelt Position des letzten Auftretens von ch in str }
- VAR
- i : BYTE;
- BEGIN
- i := Length(Str);
- WHILE (i > 0) AND (Str[i] <> ch) DO Dec(i);
- BackPos := i;
- END;
-
- FUNCTION LongLo(x: LONGINT): WORD;
- BEGIN
- Cv.l := x;
- LongLo := Cv.Lo;
- END;
-
- FUNCTION LongHi(x: LONGINT): WORD;
- BEGIN
- Cv.l := x;
- LongHi := Cv.Hi;
- END;
-
- FUNCTION Hex(n, l: INTEGER): HexStr;
- { n in l-stellige Hexzahl wandeln }
- VAR
- i, z : INTEGER;
- s : HexStr;
- BEGIN
- s := Empty;
- FOR i := 1 TO l DO BEGIN
- z := n AND 15; { Ziffer bilden }
- IF z > 9 THEN z := z + 7;
- s := Chr(z + 48) + s;
- n := n SHR 4; { Division durch 16 }
- END;
- Hex := s;
- END;
-
- PROCEDURE Error(Nr : BYTE);
- { Fehlerbehandlung }
- VAR
- i : WORD;
- BEGIN
- IF XDBFlag THEN BEGIN
- Assign(Debug, Pfad + Name + '.XDB');
- ReWrite(Debug);
- FOR i := 0 TO IFBTop DO BEGIN
- IF i = IFBp THEN WriteLn(Debug, ' <-- ERROR !!! ');
- Write(Debug, Chr(IFB^[i]));
- END;
- Close(Debug);
- END;
- IF IFBp > XFSize THEN Result.ErrorPos := 0
- ELSE Result.ErrorPos := IFBp;
- Result.ErrorWort := Merker;
- Dispose(IFB);
- Dispose(m);
- Halt(100 + Nr);
- END;
-
- PROCEDURE Hilfe;
- BEGIN
- WriteLn;
- WriteLn('NAXOS Optimierender Compiler Version ', Version);
- WriteLn('(C) 1992 DMV-Verlag & Peper, Zissis, Tossounidis');
- WriteLn;
- WriteLn('Aufruf: NXO Dateiname -m -n -d ');
- WriteLn;
- WriteLn(' (Parameter sind optional)');
- WriteLn;
- WriteLn(' -m MAP-Datei erzeugen');
- WriteLn(' -n Keine Code-Erzeugung');
- WriteLn(' -d Intermediär-Source erzeugen');
- WriteLn;
- WriteLn(' (statt "-" ist auch "/" gültig)');
- WriteLn;
- Halt(0);
- END;
-
- PROCEDURE Init;
- { Compiler initialisieren }
- VAR
- p, i : BYTE;
- Option : STRING[2];
- ch : CHAR;
- f : FILE;
- OkL, OkR : BOOLEAN;
- x, p1, p2: pSymtab;
- BEGIN
- LZ := Empty;
- { Dateinamen holen }
- DateiName := ParamStr(1);
- IF (DateiName = '?') OR (ParamCount = 0) THEN Hilfe;
- FSplit(DateiName, Pfad, Name, Ext);
- IF Ext = '' THEN Ext := '.FTH';
- { Options-Voreinstellungen }
- SysPfad := GetEnv('NAXOS');
- IF SysPfad <> '' THEN SysPfad := SysPfad + '\';
- NoCodeFlag := FALSE;
- InDef := FALSE;
- Comment := FALSE;
- ShortFlag := TRUE;
- XDBFlag := FALSE;
- MapFlag := FALSE;
- Main := FALSE;
- Merker := '';
- Nummer := 0;
- { Optionen auswerten }
-
- IF ParamCount > 1 THEN
- FOR i := 2 TO ParamCount DO BEGIN
- Option := ParamStr(i);
- IF Option[1] IN ['/', '-'] THEN BEGIN
- ch := UpCase(Option[2]);
- CASE ch OF
- 'N' : NoCodeFlag := TRUE;
- 'M' : MapFlag := TRUE;
- 'D' : XDBFlag := TRUE;
- ELSE Error(18);
- END;
- END ELSE IF Option[1] <> '>' THEN Error(18);
- END;
-
- { Quelltextdatei öffnen }
- Assign(f, Pfad + Name + Ext);
- {$I-} Reset(f, 1); {$I+}
- IF IOResult <> 0 THEN Error(19);
- XFSize := FileSize(f);
- BlockRead(f, IFB^, XFSize);
- Close(f);
- IFBTop := XFSize;
- IFBp := 0;
- { verschiedene Einstellungen }
- Zeile := Empty;
- Merker := Empty;
- Wort := Space;
- IncludeFlag := TRUE;
- CLitflag := FALSE;
- FlagStack := FALSE;
- r0 := $FFFF;
- s0 := $FFFF;
- Sp := 0;
- Nummer := 0;
- pc := 256;
- MacroLim := 9;
- RegFix := 0;
- Macro := MacroLim;
- VocName := Empty;
- OFCnt := 0;
- CaseFlag := FALSE;
- VocAnfang := 0;
- QFAs := 0;
- FillChar(m^, SizeOf(m^), NUL);
- TextAttr := $70;
- GotoXY(35, 11);
- Write(Name, '.FTH');
- GotoXY(23, 14);
- Write('└─────────────────┴────────────────┘');
- GotoXY(23, 15);
- Write('0% 50% 100%');
- GotoXY(22, 16);
- TextAttr := $1F;
- Write(' Abbruch mit Strg-Untbr ');
- TextAttr := $70;
- New(Root);
- Root^.Name := 'FFFFFFFFFFFF';
- Root^.Typ := 254;
- Root^.Par0 := 0;
- Root^.Par1 := 0;
- Root^.Par2 := 0;
- Root^.Par3 := 0;
- Root^.Used := FALSE;
- Root^.QFALen := 0;
- Root^.RLink := NIL;
- Root^.LLink := NIL;
- Assign(sif, SysPfad + 'SYSTEM.DIC');
- {$I-} Reset(sif, SizeOf(Root^) - 11); {$I+}
- IF IOResult <> 0 THEN Error(25);
- REPEAT
- New(x);
- BlockRead(sif, x^, 1);
- x^.QFALen := 0;
- x^.Used := FALSE;
- x^.RLink := NIL;
- x^.LLink := NIL;
- p1 := Root;
- REPEAT
- p2 := p1;
- IF x^.Name > p1^.Name THEN p1 := p1^.RLink
- ELSE p1 := p1^.LLink;
- UNTIL p1 = NIL;
- IF x^.Name > p2^.Name THEN p2^.RLink := x
- ELSE p2^.LLink := x;
- UNTIL EoF(sif);
- Close(sif);
- END;
-
- FUNCTION IneOf: BOOLEAN;
- BEGIN
- IF IFBp >= IFBTop THEN IneOf := TRUE
- ELSE IneOf := FALSE;
- END;
-
- PROCEDURE InReadLn(VAR s: ZeilenTyp);
- BEGIN
- s := '';
- IF NOT(IneOf) THEN BEGIN
- WHILE IFB^[IFBp] = 13 DO Inc(IFBp, 2);
- REPEAT
- s := s + Chr(IFB^[IFBp]);
- Inc(IFBp);
- UNTIL (IFB^[IFBp] = 13) OR(IneOf);
- Inc(IFBp, 2);
- END;
- END;
-
- FUNCTION Suche(Name : STRING) : BOOLEAN; FORWARD;
-
- FUNCTION Hw1 : WortTyp;
- { Ein Wort aus Quelltext holen }
- CONST
- Balken : STRING = '▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒';
- BlkEmp : STRING = ' ';
- VAR
- p : BYTE;
- w : STRING;
- Mist : BOOLEAN;
- Bffr : WORD;
-
- BEGIN
- REPEAT
- IF IneOf THEN BEGIN
- Hw1 := Empty;
- Exit;
- END ELSE BEGIN
- w := '';
- WHILE IFB^[IFBp] = 13 DO BEGIN
- IF Comment THEN Error(46);
- Inc(IFBp, 2);
- Inc(Nummer);
- END;
- Bffr := IFBp;
- WHILE (IFB^[IFBp] <> $20) AND (IFB^[IFBp] <> $0D) AND
- (NOT(IneOf)) DO BEGIN
- w := w + Chr(IFB^[IFBp]);
- Inc(IFBp);
- END;
- Inc(IFBp);
- END;
- UNTIL w <> '';
- IF IFB^[IFBp] = $0A THEN BEGIN
- Inc(IFBp);
- Inc(Nummer);
- Balken[0] := Chr(Round((IFBp / IFBTop) * 36));
- GotoXY(23, 13);
- Write(BlkEmp);
- GotoXY(23, 13);
- Write(Balken);
- END;
- IF w[1] <> Apost THEN
- FOR p := 1 TO Length(w) DO w[p] := UpCase(w[p]);
- Merker2 := w;
- Merker := w;
- Hw1 := w;
- IF (w = '(') THEN WTyp := 178 ELSE
- IF (w = ')') THEN WTyp := 179 ELSE
- IF NOT Comment THEN Mist := Suche(w);
- IF (WTyp IN [161..165, 181, 191, 192]) THEN BEGIN
- QFAs := Bffr;
- SPBuf := Sp;
- SBuf := s;
- OFCntBuf := OFCnt;
- CLitFlagBuf := CLitflag;
- CaseFlagBuf := CaseFlag;
- END;
- END;
-
-
- FUNCTION HoleWort : WortTyp;
- VAR
- wx : WortTyp;
- BEGIN
- wx := Hw1;
- WHILE (WTyp = 178) DO BEGIN
- Comment := TRUE;
- REPEAT
- wx := Hw1;
- UNTIL (WTyp = 179);
- Comment := FALSE;
- wx := Hw1;
- END;
- HoleWort := wx;
- END;
-
- FUNCTION HoleZeichen : CHAR;
- { Ein einzelnes Zeichen aus Quelltext holen }
- BEGIN
- HoleZeichen := Chr(IFB^[IFBp]);
- Inc(IFBp);
- END;
-
-
-
- PROCEDURE Ob(b : BYTE);
- { Ein Byte im Code ablegen }
- BEGIN
- m^[pc] := b;
- Inc(pc);
- IF pc > MaxProg THEN Error(3);
- END;
-
-
- PROCEDURE Ow(w : WORD);
- { Ein Wort im Code ablegen }
- BEGIN
- Move(w, m^[pc], 2);
- Inc(pc, 2);
- IF pc > MaxProg THEN Error(3);
- END;
-
-
- PROCEDURE Ot(Adr : WORD; w : INTEGER);
- { Ein Wort an spezifizierter CodeAdresse ablegen }
- BEGIN
- Move(w, m^[Adr], 2);
- END;
-
-
- PROCEDURE Otb(Adr : WORD; b : BYTE);
- { Ein Byte an spezifizierter CodeAdresse ablegen }
- BEGIN
- Move(b, m^[Adr], 1);
- END;
-
-
- PROCEDURE Os(s : ZeilenTyp);
- { String im Code ablegen }
- BEGIN
- FOR i := 0 TO Length(s) DO Ob(Ord(s[i]));
- END;
-
-
- PROCEDURE TueCode;
- { Inline-Code auswerten }
- VAR
- w : WortTyp;
- Disp : WORD;
- Fehler : INTEGER;
- BEGIN
- REPEAT
- w := HoleWort;
- IF w = Empty THEN Error(7);
- IF w <> ']' THEN BEGIN
- Val(w, Disp, Fehler);
- IF Fehler <> 0 THEN Error(7);
- IF Disp > 255 THEN Ow(Disp) ELSE Ob(Disp);
- END;
- UNTIL w = ']';
- END;
-
- PROCEDURE Push(p: WORD; Flag, Short: BYTE);
- { Adresse und Flag auf Stack ablegen }
- BEGIN
- WITH s[Sp] DO BEGIN
- Wert := p;
- Typ := Flag;
- Size := Short;
- END;
- Inc(Sp);
- IF Sp > MaxStack THEN Error(8);
- END;
-
- FUNCTION Pop(Flag : BYTE; VAR Short : BYTE) : INTEGER;
- { Adresse vom Stack holen, Flag prüfen }
- BEGIN
- IF Sp = 0 THEN Error(9);
- Dec(Sp);
- WITH s[Sp] DO BEGIN
- Short := Size;
- IF Typ = Flag THEN Pop := Wert
- ELSE CASE Flag OF
- _IF : Error(10);
- _BEGIN : Error(13);
- _WHILE : Error(14);
- _DO : Error(15);
- ELSE Error(0);
- END;
- END;
- END;
-
- FUNCTION Near(Quelle, Ziel: WORD): INTEGER;
- { Near-Sprungdistanz berechnen }
- BEGIN
- Near := Ziel - Quelle - 2;
- END;
-
-
-
- FUNCTION Short(Quelle, Ziel : WORD) : BYTE;
- { Short-Sprungdistanz berechnen }
- VAR
- Disp : INTEGER;
- BEGIN
- Disp := Ziel - Quelle - 1;
- IF Abs(Disp) > 127 THEN Error(11);
- Short := Lo(Disp);
- END;
-
- PROCEDURE Patch;
- BEGIN
- IFBp := Zeiger^.QFA;
- Sp := SPBuf;
- OFCnt := OFCntBuf;
- s := SBuf;
- CaseFlag := CaseFlagBuf;
- CLitflag := CLitFlagBuf;
- pc := Zeiger^.Par0;
- Move(IFB^[IFBp], IFB^[IFBp + FZeiger^.QFALen],
- IFBTop - IFBp);
- Seek(IncF, FZeiger^.QFA);
- BlockRead(IncF, IFB^[IFBp], FZeiger^.QFALen);
- IFBTop := IFBTop + FZeiger^.QFALen;
- FZeiger^.Par0 := pc;
- FZeiger^.Used := FALSE;
- Main := FALSE;
- InDef := FALSE;
- FZeiger^.Name := FZeiger^.Name + #0;
- Dispose(Zeiger);
- Zeiger := NIL;
- END;
-
- FUNCTION Suche(Name : STRING) : BOOLEAN;
- { Namen in Dictionary suchen }
- LABEL Ok;
- VAR
- NMBuf : STRING[12];
- va, er : INTEGER;
- vd : LONGINT;
- vf : RECORD
- CASE BOOLEAN OF
- TRUE : (r : DOUBLE);
- FALSE : (p0, p1, p2, p3 : WORD);
- END;
- p1, p2 : pSymtab;
- n : WortTyp;
- Num : STRING;
- Su : BOOLEAN;
- BEGIN
- n := Empty;
- Num := Name;
- Name := Copy(Name, 1, MaxName);
- Su := FALSE;
- p1 := Root;
- Extrn := FALSE;
- REPEAT
- NMBuf := p1^.Name;
- NMBuf[0] := Chr(BYTE(NMBuf[0]) AND $7F);
- p2 := p1;
- IF Name > NMBuf THEN p1 := p1^.RLink
- ELSE p1 := p1^.LLink;
- UNTIL (Name = p2^.Name) OR(p1 = NIL);
- IF Name = p2^.Name THEN BEGIN
- Su := TRUE;
- FZeiger := p2;
- END ELSE Su := FALSE;
- IF Su THEN BEGIN
- QFA := p2^.QFA;
- LastTyp := WTyp;
- WTyp := p2^.Typ;
- Par0 := p2^.Par0;
- Par1 := p2^.Par1;
- Par2 := p2^.Par2;
- Par3 := p2^.Par3;
- IF p2^.Used THEN Extrn := TRUE;
- END ELSE BEGIN
- LastTyp := WTyp;
- IF (Name[1] = '''') AND (Name[0] = #3) AND
- (Name[3] = '''') THEN BEGIN
- er := 0;
- vd := Ord(Name[2]);
- END ELSE Val(Name, vd, er);
- WTyp := _CONST;
- IF (er <> 0) AND(Name[1] = '&') THEN BEGIN
- Delete(Name, 1, 1);
- Val(Name, vd, er);
- WTyp := _DCONST;
- END;
- IF er = 0 THEN BEGIN
- Par0 := LongLo(vd);
- Par1 := LongHi(vd);
- Su := TRUE;
- END ELSE BEGIN
- IF Num[1] = '%' THEN BEGIN
- Delete(Num, 1, 1);
- Val(Num, vf.r, er);
- IF er = 0 THEN BEGIN
- WTyp := _FCONST;
- Par0 := vf.p0;
- Par1 := vf.p1;
- Par2 := vf.p2;
- Par3 := vf.p3;
- Su := TRUE;
- END ELSE Su := FALSE;
- END;
- END;
- END;
- Ok:
- IF NOT(Su) THEN BEGIN
- LastTyp := WTyp;
- WTyp := 255; { unbekannter Bezeichner }
- END;
- Found := Su;
- Suche := Su;
- END;
-
- PROCEDURE TueName;
- { Name holen und überprüfen, Header bauen }
- VAR
- Name : WortTyp;
- p1, p2 : pSymtab;
- BEGIN
- Name := HoleWort;
- IF Name[0] > Chr(MaxName) THEN Name[0] := Chr(MaxName);
- IF Name = Empty THEN Error(2);
- IF Found THEN Error(40);
- New(Zeiger);
- Zeiger^.Name := Name;
- Zeiger^.Used := FALSE;
- Zeiger^.QFA := QFAs;
- Zeiger^.Par0 := pc;
- Zeiger^.RLink := NIL;
- Zeiger^.LLink := NIL;
- Main := Name = 'MAIN';
- END;
-
- PROCEDURE TueLink;
- VAR
- p1, p2: pSymtab;
- BEGIN
- p1 := Root;
- Zeiger^.QFALen := QFAs - Zeiger^.QFA;
- REPEAT
- p2 := p1;
- IF Zeiger^.Name > p1^.Name THEN p1 := p1^.RLink
- ELSE p1 := p1^.LLink;
- UNTIL p1 = NIL;
- IF Zeiger^.Name > p2^.Name THEN p2^.RLink := Zeiger
- ELSE p2^.LLink := Zeiger;
- END;
-
- PROCEDURE TueSeal;
- { Name verstecken }
- VAR
- Name : WortTyp;
- BEGIN
- Name := HoleWort;
- IF Name = Empty THEN Error(2);
- IF Found THEN BEGIN
- { #0 an Name anhängen: }
- FZeiger^.Name := Zeiger^.Name + #0;
- END ELSE Error(4);
- END;
-
- PROCEDURE Branch0(Adr: WORD);
- { compiliert bedingten Short- oder Near-Jump rückwärts }
- VAR
- Len : INTEGER;
- BEGIN
- Len := Near(pc, Adr);
- IF Abs(Len) < 128 THEN BEGIN
- Ob($73); Ob(Len); { jnc disp }
- END ELSE BEGIN
- Ob($72); Ob(03); { jc +3 }
- Ob($E9); Ow(Len - 3); { jmp disp }
- END; { if }
- END;
-
- PROCEDURE Branch(Adr: WORD);
- { compiliert Rückwärtssprung }
- VAR
- Len : INTEGER;
- BEGIN
- Len := Near(pc, Adr);
- IF Abs(Len) < 128 THEN BEGIN
- Ob($EB); Ob(Len); { jmp disp }
- END ELSE BEGIN
- Ob($E9); Ow(Len); { jmp disp }
- END; { if }
- END;
-
-
- PROCEDURE TueLiteral(n: INTEGER);
- { Literalhandler mit Präfix }
- BEGIN
- IF CLitflag THEN CaseLit := n
- ELSE CASE RegFix OF
- 1 : BEGIN { AX }
- Ob($B8); Ow(n); { mov ax,n }
- END;
- 2 : BEGIN { BX, ADR }
- Ob($BB); Ow(n); { mov bx,n }
- END;
- 3 : BEGIN { DX, TO, ,, }
- Ob($BA); Ow(n); { mov dx,n }
- END;
- 4 : BEGIN { SX }
- Ob($4E); Ob($4E); { dec si,dec si }
- Ob($C7); Ob($04); Ow(n); { mov [si],n }
- END;
- END;
- RegFix := 0;
- END;
-
- PROCEDURE TueDLiteral(n0, n1: WORD);
- { Literalhandler mit Präfix }
- BEGIN
- CASE RegFix OF
- 1 : BEGIN { AX }
- Ob($B8); Ow(n0); { mov ax,n1 }
- Ob($BA); Ow(n1); { mov dx,n2 }
- END;
- 4 : BEGIN { SX }
- Ob($4E); Ob($4E); { dec si,dec si }
- Ob($C7); Ob($04); Ow(n1); { mov [si],n }
- Ob($4E); Ob($4E); { dec si,dec si }
- Ob($C7); Ob($04); Ow(n0); { mov [si],n }
- END;
- ELSE Error(45);
- END;
- RegFix := 0;
- END;
-
- PROCEDURE TueFLiteral(n0, n1, n2, n3: WORD);
- VAR
- Merk : WORD;
- BEGIN
- Ob($EB); Ob($08); { JMP SHORT +8 }
- Merk := pc;
- Ow(n0); Ow(n1); Ow(n2); Ow(n3); { DATENFELD }
- Ob($DD); Ob($06); Ow(Merk); { FLD DATENFELD }
- END;
-
-
- PROCEDURE TestSemi;
- { Semikolonabschluss }
- VAR
- w : WortTyp;
- BEGIN
- w := HoleWort;
- IF WTyp <> 128 THEN Error(41); { Semikolon erwartet }
- END;
-
-
- PROCEDURE TueStringLiteral;
- VAR
- z : CHAR;
- Adr : WORD;
- BEGIN
- Ob($E8); Ow(0); { call disp }
- Adr := pc;
- Ob(0); { countbyte }
- z := HoleZeichen;
- WHILE (z <> '"') AND(z <> Empty) DO BEGIN
- Ob(Ord(z)); z := HoleZeichen;
- Inc(m^[Adr]);
- END;
- Ob(0); { Nullbyte }
- m^[Adr - 2] := m^[Adr] + 2; { disp setzen }
- Ob($5B); { pop bx }
- END;
-
-
- PROCEDURE Tue_ZIf;
- { Leite If über Zeroflag ein }
- BEGIN
- IF ShortFlag THEN BEGIN
- Ob($74); { jz disp }
- Push(pc, _IF, 1);
- Ob(0);
- END ELSE BEGIN
- Ob($75); Ob(03); { jnz +3 }
- Ob($E9); { jmp disp }
- Push(pc, _IF, 2);
- Ow(0);
- END;
- END;
-
- PROCEDURE TueSystem(w : WortTyp);
- { SYSTEM-Worte compilieren }
- LABEL
- Ext;
- VAR
- nn, Fehlern : INTEGER;
- z : CHAR;
- Len, Dis : BYTE;
- Disp, Fehler,
- Adr, Adr1,
- Adr2 : WORD;
- Zgr1, Zgr2 : pSymtab;
- Gefunden : BOOLEAN;
-
- BEGIN
- Sys := TRUE;
- ExtSys := FALSE;
- IF WTyp > 127 THEN CASE WTyp OF
- { ; }
- 128 : BEGIN
- Ob($C3); { ret }
- IF Sp > 0 THEN CASE s[Sp - 1].Typ OF
- _IF : Error(20);
- _BEGIN : Error(21);
- _WHILE : Error(22);
- _DO : Error(23);
- ELSE Error(0);
- END;
- END;
-
- { [ }
- 129 : TueCode;
-
- { PC? }
- 182 : BEGIN
- PCMerker := pc;
- END;
-
- { [PC] }
- 183 : BEGIN
- Ow(PCMerker);
- END;
-
- { IF }
- 132 : BEGIN
- IF ShortFlag THEN BEGIN
- Ob($73); { jnc disp }
- Push(pc, _IF, 1);
- Ob(0);
- END ELSE BEGIN
- Ob($72); Ob(03); { jc +3 }
- Ob($E9); { jmp disp }
- Push(pc, _IF, 2);
- Ow(0);
- END;
- END;
-
- { C@IF }
- 133 : BEGIN
- Ob($8A); Ob($1F); { move bl,[bx] }
- Ob($84); Ob($DB); { test bl,bl }
- Tue_ZIf;
- END;
-
- { @IF }
- 188 : BEGIN
- Ob($8B); Ob($1F); { mov bx,[bx] }
- Ob($85); Ob($DB); { test bx,bx }
- Tue_ZIf;
- END;
-
- { 0=IF }
- 189 : BEGIN
- Ob($85); Ob($C0); { test ax,ax }
- Tue_ZIf;
- END;
-
- { ENDIF, THEN }
- 134 : BEGIN
- Adr := Pop(_IF, Len);
- IF Len = 1 THEN
- m^[Adr] := Short(Adr, pc)
- ELSE
- Ot(Adr, Near(Adr, pc));
- END;
-
- { ELSE }
- 135 : BEGIN
- IF CLitflag THEN CLitflag := FALSE ELSE BEGIN
- Adr := Pop(_IF, Len);
- IF Len = 1 THEN BEGIN
- m^[Adr] := Short(Adr, pc + 2);
- Ob($EB); { jmp disp }
- Push(pc, _IF, 1);
- Ob(0);
- END ELSE BEGIN
- Ot(Adr, Near(Adr, pc + 3));
- Ob($E9); { jmp disp }
- Push(pc, _IF, 2);
- Ow(0);
- END;
- END;
- END;
-
- { CASE }
- 136 : BEGIN
- IF CaseFlag THEN Error(28);
- CaseFlag := TRUE;
- CLitflag := TRUE;
- END;
-
- { OF }
- 137 : BEGIN
- CLitflag := FALSE;
- Inc(OFCnt);
- Ob($3D); Ow(CaseLit); { cmp ax,n }
- IF ShortFlag THEN BEGIN
- Ob($75); { jnz disp }
- Push(pc, _CASE, 1);
- Ob(0);
- END ELSE BEGIN
- Ob($74); Ob(3); { jz +3 }
- Ob($E9); { jmp disp }
- Push(pc, _CASE, 2);
- Ow(0);
- END;
- END;
-
-
- { >OF }
- 138 : BEGIN
- CLitflag := FALSE;
- Inc(OFCnt);
- Ob($3D); Ow(CaseLit); { cmp ax,n }
- IF ShortFlag THEN BEGIN
- Ob($7E); { jng disp }
- Push(pc, _CASE, 1);
- Ob(0);
- END ELSE BEGIN
- Ob($7F); Ob(3); { jg +3 }
- Ob($E9); { jmp disp }
- Push(pc, _CASE, 2);
- Ow(0);
- END;
- END;
-
-
- { <OF }
- 139 : BEGIN
- CLitflag := FALSE;
- Inc(OFCnt);
- Ob($3D); Ow(CaseLit); { cmp ax,n }
- IF ShortFlag THEN BEGIN
- Ob($7D); { jnl disp }
- Push(pc, _CASE, 1);
- Ob(0);
- END ELSE BEGIN
- Ob($7C); Ob(3); { jl +3 }
- Ob($E9); { jmp disp }
- Push(pc, _CASE, 2);
- Ow(0);
- END;
- END;
-
- { ENDOF, ;; }
- 140 : BEGIN
- Adr := Pop(_CASE, Len);
- IF Len = 1 THEN BEGIN
- m^[Adr] := Short(Adr, pc + 2);
- Ob($EB); { jmp disp }
- Push(pc, _CASE, 1);
- Ob(0);
- END ELSE BEGIN
- Ot(Adr, Near(Adr, pc + 3));
- Ob($E9); { jmp disp }
- Push(pc, _CASE, 2);
- Ow(0);
- END;
- CLitflag := TRUE;
- END;
-
- { ENDCASE }
- 141 : BEGIN
- FOR i := 1 TO OFCnt DO BEGIN
- Adr := Pop(_CASE, Len);
- IF Len = 1 THEN m^[Adr] := Short(Adr, pc)
- ELSE Ot(Adr, Near(Adr, pc));
- END;
- OFCnt := 0;
- CaseFlag := FALSE;
- CLitflag := FALSE;
- END;
-
- { MACRO }
- 142 : Macro := 64;
-
- { -MACRO }
- 143 : Macro := MacroLim;
-
- { FIND }
- 144 : BEGIN
- w := HoleWort;
- IF NOT Found THEN Error(4);
- IF Extrn THEN BEGIN
- ExtSys := TRUE;
- Exit;
- END;
- TueLiteral(Par0);
- END;
-
- { BEGIN }
- 145 : BEGIN
- Push(pc, _BEGIN, 0);
- END;
-
- { UNTIL }
- 146 : BEGIN
- Adr := Pop(_BEGIN, Len);
- Branch0(Adr);
- END;
-
- { WHILE }
- 147 : BEGIN
- IF ShortFlag THEN BEGIN
- Ob($73); { jnc disp }
- Push(pc, _WHILE, 1);
- Ob(0);
- END ELSE BEGIN
- Ob($72); Ob(03); { jc +3 }
- Ob($E9); { jmp disp }
- Push(pc, _WHILE, 2);
- Ow(0);
- END;
- END;
-
- { REPEAT }
- 148 : BEGIN
- Adr1 := Pop(_WHILE, Len);
- Adr := Pop(_BEGIN, Dis);
- Branch(Adr);
- IF Len = 1 THEN m^[Adr1] := Short(Adr1, pc)
- ELSE Ot(Adr1, Near(Adr1, pc));
- END;
-
- { AGAIN }
- 149 : BEGIN
- Adr := Pop(_BEGIN, Dis);
- Branch(Adr);
- END;
-
-
- { DO }
- 150 : BEGIN
- Ob($55); { push bp }
- Ob($51); { push cx }
- Ob($89); Ob($C5); { mov bp,ax }
- Ob($89); Ob($D1); { mov cx,dx }
- Push(pc, _DO, 0);
- END;
-
- { LOOP }
- 151 : BEGIN
- Ob($41); { inc cx }
- Ob($39); Ob($E9); { cmp cx,bp }
- Adr := Pop(_DO, Len);
- nn := Near(pc, Adr);
- IF Abs(nn) < 128 THEN BEGIN
- Ob($7E); Ob(nn); { jle adr }
- END ELSE BEGIN
- Ob($7F); Ob(03); { jg +3 }
- Ob($E9); Ow(nn - 3); { jmp adr }
- END; { if }
- Ob($59); { pop cx }
- Ob($5D); { pop BP }
- END;
-
- { +LOOP }
- 152 : BEGIN
- Ob($03); Ob($C8); { add cx,ax }
- Ob($39); Ob($E9); { cmp cx,bp }
- Adr := Pop(_DO, Len);
- nn := Near(pc, Adr);
- IF Abs(nn) < 128 THEN BEGIN
- Ob($7E); Ob(nn); { jle adr }
- END ELSE BEGIN
- Ob($7F); Ob(03); { jg +3 }
- Ob($E9); Ow(nn - 3); { jmp adr }
- END; { if }
- Ob($59); { pop cx }
- Ob($5D); { pop bp }
- END;
-
- { -LOOP }
- 153 : BEGIN
- Ob($29); Ob($C1); { sub cx,ax }
- Ob($39); Ob($E9); { cmp cx,BP }
- Adr := Pop(_DO, Len);
- nn := Near(pc, Adr);
- IF Abs(nn) < 128 THEN BEGIN { ** geändert 3.6.89 ** }
- Ob($7D); Ob(nn); { jge adr }
- END ELSE BEGIN
- Ob($7C); Ob(03); { jl +3 }
- Ob($E9); Ow(nn - 3); { jmp adr } { KP 12.5.91 }
- END; { if }
- Ob($59); { pop cx }
- Ob($5D); { pop BP }
- END;
-
- { /LOOP }
- 154 : BEGIN
- Adr := Pop(_DO, Len);
- Ob($03); Ob($C8); { add cx,ax }
- Ob($85); Ob($C0); { test ax,ax }
- Ob($79); Ob($07); { jns disp }
- Ob($39); Ob($E9); { cmp cx,bp }
- Ob($7C); Ob($0A); { jl +10 }
- Ob($E9); Ow(Near(pc, Adr)); { jmp adr }
- Ob($39); Ob($E9); { cmp cx,bp }
- Ob($7F); Ob(03); { jg +3 }
- Ob($E9); Ow(Near(pc, Adr)); { jmp adr }
- Ob($59); { pop cx }
- Ob($5D); { pop bp }
- END;
-
- { " }
- 155 : TueStringLiteral;
-
- { ." }
- 156 : BEGIN
- TueStringLiteral;
- w := 'TYPE';
- IF NOT Suche(w) THEN Error(4);
- IF Extrn THEN BEGIN
- ExtSys := TRUE;
- Exit;
- END;
- Ob($8A); Ob($07); { mov al,[bx] }
- Ob($B4); Ob($00); { mov ah,00 }
- Ob($43); { inc bx }
- Ob($BF); Ow(Par0); { mov di,[pfa] }
- Ob($FF); Ob($D7); { call di }
- END;
-
- { RECLEN }
- 157 : BEGIN
- Ob($B8); Ow(RecLen);
- END;
-
- { OFFSET }
- 158 : BEGIN
- w := HoleWort;
- IF w = Empty THEN Error(7);
- Val(w, nn, Fehlern);
- IF Fehlern <> 0 THEN Error(7);
- Ob($81); Ob($C3); Ow(nn); { add bx,nn }
- END;
-
- { (LONG) }
- 175 : ShortFlag := FALSE;
-
- { (SHORT) }
- 176 : ShortFlag := TRUE;
-
- { Schweifklammer auf }
- 184 : BEGIN
- FlagStack := TRUE;
- Ob($55); { push bp }
- END;
-
- { Schweifklammer zu }
- 185 : BEGIN
- FlagStack := FALSE;
- Ob($5D); { pop bx }
- END;
-
- { PUSHF }
- 187 : BEGIN
- IF FlagStack = TRUE THEN BEGIN
- Ob($D1); Ob($D5); { rcl bp,1 }
- END;
- END;
-
- { MAKE }
- 160 : BEGIN
- w := HoleWort;
- IF w = Empty THEN Error(2);
- IF NOT Found THEN Error(4);
- Adr1 := Par0;
- IF WTyp <> _VECTOR THEN Error(29);
- IF Extrn THEN BEGIN
- ExtSys := TRUE;
- Exit;
- END;
- w := HoleWort;
- IF w = Empty THEN Error(2);
- IF NOT Found THEN Error(4);
- IF WTyp <> _PROC THEN Error(30);
- IF Extrn THEN BEGIN
- ExtSys := TRUE;
- Exit;
- END;
- Adr2 := Par0;
- Ob($BB); Ow(Adr1); { mov bx,adr1 }
- Ob($C6); Ob($07); Ob($E9); { mov [bx],$E9 }
- Ob($43); { inc bx }
- Ob($C7); Ob($07); { mov [bx],cfa }
- Ow(Near(Adr1, Adr2) - 1);
- END;
- ELSE Sys := FALSE;
- END ELSE Sys := FALSE;
- END;
-
- PROCEDURE CopyMacro(Strt, Len : WORD);
- { Kopiere Len Bytes von Cfa nach Pc }
- VAR
- i : WORD;
- BEGIN
- i := 0;
- WHILE i < Len DO BEGIN
- Ob(m^[Strt]);
- Inc(Strt);
- i := i + 1;
- END;
- END;
-
-
- PROCEDURE DoCompile;
- { Compiliere bis Semikolon }
- VAR
- Len, Adr : WORD;
- Disp, Fehler : INTEGER;
- w : WortTyp;
- sxx : BOOLEAN;
- LABEL
- Ok, ExOk;
- BEGIN
- REPEAT
- w := HoleWort;
- IF NOT Extrn THEN BEGIN
- IF (WTyp = 181) OR(WTyp = 161) THEN Error(44);
- IF w = Empty THEN Error(2);
- TueSystem(w);
- IF WTyp = 128 THEN RegFix := 0;
- IF ExtSys THEN BEGIN Patch; GOTO ExOk; END;
-
- IF WTyp = 130 THEN BEGIN
- RegFix := 2;
- GOTO Ok;
- END;
- IF WTyp = 131 THEN BEGIN
- RegFix := 3;
- GOTO Ok;
- END;
- IF WTyp = 170 THEN BEGIN
- RegFix := 1;
- GOTO Ok;
- END;
- IF WTyp = 186 THEN BEGIN
- RegFix := 4;
- GOTO Ok;
- END;
- IF Sys THEN GOTO Ok;
-
- { in Dictionary suchen }
- IF NOT Found THEN Error(4);
-
- IF RegFix <> 0 THEN BEGIN
- sxx := TRUE;
- CASE WTyp OF
- _CONST : TueLiteral(Par0);
- _DCONST : TueDLiteral(Par0, Par1);
- _FCONST : TueFLiteral(Par0, Par1, Par2, Par3);
- ELSE IF RegFix <> 4 THEN TueLiteral(Par0)
- ELSE BEGIN
- RegFix := 0;
- sxx := FALSE;
- END;
- END;
- IF sxx THEN GOTO Ok;
- END;
-
- { Konstante? }
- IF WTyp = _CONST THEN BEGIN
- RegFix := 1;
- TueLiteral(Par0);
- GOTO Ok;
- END;
-
- IF WTyp = _DCONST THEN BEGIN
- RegFix := 1;
- TueDLiteral(Par0, Par1);
- GOTO Ok;
- END;
-
- IF WTyp = _FCONST THEN BEGIN
- TueFLiteral(Par0, Par1, Par2, Par3);
- GOTO Ok;
- END;
-
- RegFix := 0;
-
- { KOLON ? }
- IF (WTyp = _KOLON) AND (Par1 < Macro) THEN BEGIN
- CopyMacro(Par0, Par1 - 1);
- GOTO Ok;
- END;
-
- { DATENSTRUKTUR? }
- IF WTyp < 10 THEN BEGIN
- RecLen := Par1;
- Ob($BB); Ow(Par0); { mov bx,adr }
- IF WTyp > 4 THEN GOTO Ok;
- IF Par2 = 0 THEN GOTO Ok;
- CopyMacro(Par2, Par3 - 1);
- GOTO Ok;
- END;
-
- { sonst Vector oder Prozedur }
- Ob($BF); Ow(Par0); { mov di,cfa }
- Ob($FF); Ob($D7); { call di }
- Ok:
- END ELSE BEGIN
- Patch;
- GOTO ExOk;
- END;
- UNTIL WTyp = 128;
- ExOk: ;
- END;
-
-
- PROCEDURE TueKolon;
- { Colon-Definition compilieren }
- VAR
- w : WortTyp;
- Fehler : INTEGER;
- Cfa1 : WORD;
- Merker : pSymtab;
- BEGIN
- TueName; { Header bauen }
- InDef := TRUE;
- Zeiger^.Typ := _KOLON;
- Merker := Zeiger;
- IF Main THEN BEGIN
- Ot($0102, pc);
- mn := pc;
- END;
-
- PCMerker := pc;
- DoCompile;
-
- Merker^.Par0 := PCMerker; { cfa }
- Merker^.Par1 := pc - PCMerker; { LEN eintragen }
- IF Zeiger <> NIL THEN TueLink;
- InDef := FALSE;
- END;
-
- PROCEDURE TueProc;
- { Prozedur compilieren }
- VAR
- w : WortTyp;
- Fehler : INTEGER;
- Cfa1 : WORD;
- Merker : pSymtab;
- BEGIN
- TueName; { Header bauen }
- InDef := TRUE;
- Zeiger^.Typ := _PROC;
- Merker := Zeiger;
- IF Main THEN BEGIN
- Ot($100, $E9);
- Ot($0101, pc);
- mn := pc;
- END;
-
- PCMerker := pc;
- DoCompile;
- Merker^.Par0 := PCMerker; { CFA-eintragen }
- Merker^.Par1 := pc - PCMerker; { LEN eintragen }
- IF Zeiger <> NIL THEN TueLink;
- InDef := FALSE;
- END;
-
- PROCEDURE TueVariable;
- { Baue Datenstruktur auf }
- LABEL
- Ok, Ex;
- VAR
- w : WortTyp;
- n, Fehler,
- Opa0, Opa1,
- Opa2 : INTEGER;
- DMerker : pSymtab;
-
- PROCEDURE TueString;
- { String-Definition compilieren }
- VAR
- z : CHAR;
- n, Fehler : INTEGER;
- w : WortTyp;
- BEGIN
- Zeiger^.Typ := _STRING;
- DMerker := Zeiger;
- { in Codebereich: }
- PCMerker := pc;
- Ob(0); { maxcount }
- Ob(0); { Countinit 0 }
- DMerker^.Par0 := PCMerker + 1; { par0 }
- IF Merker = 'STRING' THEN BEGIN
- w := HoleWort;
- IF WTyp <> 10 THEN Error(7); { Zahl erwartet }
- IF Par0 > 255 THEN Error(35); { String zu groß }
- pc := pc + Par0 + 1;
- END ELSE BEGIN { Stringliteral }
- z := HoleZeichen;
- IF z = Empty THEN Error(43); { Stringende fehlt }
- n := 0;
- WHILE (z <> '"') AND(z <> Empty) DO BEGIN
- Ob(Ord(z));
- z := HoleZeichen;
- IF n > 255 THEN Error(43); { Stringende fehlt }
- Inc(n);
- END;
- Ob(0); { Abschlussbyte }
- Otb(PCMerker + 1, Lo(n)); { count }
- END;
- Otb(PCMerker, Lo(n)); { maxcount }
- DMerker^.Par1 := n;
- END;
-
- PROCEDURE TueVarInit;
- { Initialisiere Datenstruktur }
- VAR
- w : WortTyp;
- n, Fehler, Count : WORD;
-
- FUNCTION Eval(wo : WortTyp) : WORD;
- VAR
- t : WORD;
- BEGIN
- IF Suche(wo) THEN Eval := Par0
- ELSE Error(7);
- END;
-
- BEGIN
- DMerker^.Par2 := 0; { cfa }
- DMerker^.Par3 := 0; { codlen }
-
- IF Odd(pc) THEN pc := pc + 1;
- DMerker^.Par0 := pc;
- w := HoleWort;
- IF w = Empty THEN Error(7);
- Count := 0;
- REPEAT
- n := Eval(w);
- Inc(Count);
- w := HoleWort;
- IF NOT((w = ',') OR(w = 'C,')) THEN Error(43);
- IF w = ',' THEN BEGIN
- Inc(Count);
- Ow(n);
- END ELSE Ob(Lo(n));
- w := HoleWort;
- UNTIL w = ']';
- DMerker^.Par1 := Count;
- END;
-
- PROCEDURE TueVarDo;
- { Compiliere DO: code in VAR }
- BEGIN
- PCMerker := pc;
- DMerker^.Par2 := pc; { cfa }
- IF Opa2 <> 0 THEN BEGIN
- Ob($BF); Ow(Opa2); { mov di,cfa }
- Ob($FF); Ob($D7); { call di }
- END;
- DoCompile;
- DMerker^.Par3 := pc - PCMerker; { codlen }
- END;
-
- BEGIN (* TueVariable *)
- TueName;
- Zeiger^.Typ := _VAR;
- DMerker := Zeiger;
- w := HoleWort;
- IF Extrn THEN GOTO Ex;
- IF w = Empty THEN Error(7);
- IF (WTyp = 155) OR(WTyp = 164) THEN BEGIN
- Merker := w;
- TueString;
- TestSemi;
- GOTO Ok;
- END;
- IF WTyp = 129 THEN BEGIN
- TueVarInit;
- TestSemi;
- GOTO Ok;
- END;
- IF NOT(WTyp = _VAR) THEN Error(36);
- DMerker^.Par0 := 0;
- DMerker^.Par1 := Par1;
- DMerker^.Par2 := Par2;
- DMerker^.Par3 := Par3;
-
- IF Odd(pc) THEN pc := pc + 1;
- Opa0 := Par0;
- Opa1 := Par1;
- Opa2 := Par2;
- w := HoleWort;
- DMerker^.Par0 := pc;
- IF (w = ';') OR(w = 'DO:') THEN BEGIN
- CopyMacro(Opa0, Opa1); { Datenzellen übertragen }
- END ELSE BEGIN
- Val(w, n, Fehler);
- IF Fehler <> 0 THEN Error(7); { Zahl erwartet }
- DMerker^.Par1 := Opa1 * n;
- pc := pc + Opa1 * n;
- w := HoleWort;
- END;
- IF w = 'DO:' THEN BEGIN
- TueVarDo;
- GOTO Ok;
- END;
- IF WTyp <> 128 THEN Error(41);
- Ok:
- TueLink;
- Exit;
- Ex:
- Patch;
- END;
-
- PROCEDURE TueKonstante;
- { Konstanten-Definition compilieren }
- VAR
- w : WortTyp;
- BEGIN
- TueName; { Header bauen }
- Zeiger^.Typ := _CONST;
- w := HoleWort;
- IF WTyp <> _CONST THEN Error(7);
- Zeiger^.Par0 := Par0;
- TueLink;
- TestSemi;
- END;
-
- PROCEDURE TueDKonstante;
- { Konstanten-Definition compilieren }
- VAR
- w : WortTyp;
- BEGIN
- TueName; { Header bauen }
- Zeiger^.Typ := _DCONST;
- w := HoleWort;
- IF (WTyp <> _DCONST) AND (WTyp <> _CONST) THEN Error(7);
- Zeiger^.Par0 := Par0;
- Zeiger^.Par1 := Par1;
- TueLink;
- TestSemi;
- END;
-
- PROCEDURE TueFKonstante;
- { Konstanten-Definition compilieren }
- VAR
- w : WortTyp;
- BEGIN
- TueName; { Header bauen }
- Zeiger^.Typ := _FCONST;
- w := HoleWort;
- IF WTyp <> _FCONST THEN Error(7);
- Zeiger^.Par0 := Par0;
- Zeiger^.Par1 := Par1;
- Zeiger^.Par2 := Par2;
- Zeiger^.Par3 := Par3;
- TueLink;
- TestSemi;
- END;
-
- PROCEDURE TueVektor;
- { Vector-Definition compilieren }
- VAR
- w : WortTyp;
- BEGIN
- TueName; { Header bauen }
- Zeiger^.Typ := _VECTOR;
- Zeiger^.Par0 := pc; { cfa }
- Zeiger^.Par1 := 5; { len }
- Ob($C3); { ret , Initialwert für Dummy Wort }
- Ow($00); { Dummy für Jump-Adresse }
- TueLink;
- TestSemi;
- END;
-
-
- PROCEDURE TueMake;
- LABEL
- Ext;
- VAR
- w : WortTyp;
- Adr1,
- Adr2,
- Typ : INTEGER;
- Gefunden : BOOLEAN;
- Buf : WORD;
-
- PROCEDURE Pat;
- BEGIN
- IFBp := Buf;
- Move(IFB^[IFBp], IFB^[IFBp + FZeiger^.QFALen], IFBTop - IFBp);
- Seek(IncF, FZeiger^.QFA);
- BlockRead(IncF, IFB^[IFBp], FZeiger^.QFALen);
- IFBTop := IFBTop + FZeiger^.QFALen;
- FZeiger^.Par0 := pc;
- FZeiger^.Used := FALSE;
- FZeiger^.Name := FZeiger^.Name + #0;
- END;
-
- BEGIN
- Buf := QFAs;
- w := HoleWort;
- IF w = Empty THEN Error(4);
- IF NOT Found THEN Error(4);
- Adr1 := Par0;
- IF WTyp <> _VECTOR THEN Error(29);
- IF Extrn THEN GOTO Ext;
- w := HoleWort;
- IF w = Empty THEN Error(4);
- IF NOT Found THEN Error(4);
- Adr2 := Par0;
- IF WTyp <> _PROC THEN Error(30);
- IF Extrn THEN GOTO Ext;
- Otb(Adr1, $E9); { jmp disp }
- Ot(Succ(Adr1), Pred(Near(Adr1, Adr2)));
- Exit;
- Ext:
- Pat;
- END;
-
- PROCEDURE TueLabel;
- VAR
- w : WortTyp;
- Adr1,
- Adr2,
- Typ : INTEGER;
- Gefunden : BOOLEAN;
- Pfa : WORD;
- BEGIN
- TueName;
- Zeiger^.Typ := _VECTOR;
- w := HoleWort;
- IF w = Empty THEN Error(4);
- IF WTyp <> _PROC THEN Error(30);
- w := HoleWort;
- IF WTyp <> 10 THEN Error(7);
- Pfa := Zeiger^.Par0 + Par0;
- Ob($E9); { jump }
- Ow(Pfa - pc - 2); { disp }
- TueLink;
- END;
-
- PROCEDURE TueMlimit;
- VAR
- w : WortTyp;
- BEGIN
- w := HoleWort;
- IF WTyp <> 10 THEN Error(7);
- IF Par0 < 7 THEN Par0 := 7;
- IF Par0 > 64 THEN Par0 := 64;
- MacroLim := Par0;
- Macro := Par0;
- END;
-
- PROCEDURE SichereVoc;
- BEGIN
- Error(47);
- END;
-
- PROCEDURE TueInclude;
- { Vocabulary einbinden }
- VAR
- Name, Nam : WortTyp;
- v : FILE;
- x, p1, p2 : pSymtab;
- Gr, Gri : WORD;
-
- BEGIN
- Gri := SizeOf(Root^) - 9;
- IF IncludeFlag = FALSE THEN Error(38); { nur ein include }
- IncludeFlag := FALSE;
- Nam := HoleWort;
- IF Nam = Empty THEN Error(2);
- Name := Nam + '.DIC';
- Assign(v, Pfad + Name);
- Assign(IncF, Pfad + Nam + '.FTH');
- {$I-}
- Reset(IncF, 1);
- IF IOResult <> 0 THEN Error(25);
- Reset(v, 1);
- {$I+}
- IF IOResult <> 0 THEN Error(25);
- BlockRead(v, Gr, 2);
- REPEAT
- New(x);
- BlockRead(v, x^, Gri);
- x^.RLink := NIL;
- x^.LLink := NIL;
- x^.Used := TRUE;
- p1 := Root;
- REPEAT
- p2 := p1;
- IF x^.Name > p1^.Name THEN p1 := p1^.RLink
- ELSE p1 := p1^.LLink;
- UNTIL p1 = NIL;
- IF x^.Name > p2^.Name THEN p2^.RLink := x
- ELSE p2^.LLink := x;
- UNTIL EoF(v);
- END;
-
-
- PROCEDURE MemSizes;
- VAR
- w : WortTyp;
- BEGIN
- w := HoleWort;
- IF WTyp <> 10 THEN Error(7);
- r0 := Par0;
- w := HoleWort;
- IF WTyp <> 10 THEN Error(7);
- s0 := Par0;
- IF s0 < 80 THEN s0 := 80;
- w := HoleWort;
- IF WTyp <> 179 THEN Error(1);
- END;
-
- PROCEDURE Compile(w : WortTyp);
-
- BEGIN
- CASE WTyp OF
- 181 : TueKolon;
- 161 : TueProc;
- 162 : TueKonstante;
- 191 : TueDKonstante;
- 192 : TueFKonstante;
- 163 : TueVariable;
- 165 : TueVektor;
- 166 : TueLabel;
- 167 : TueInclude;
- 168 : TueSeal;
- 169 : TueMlimit;
- 160 : TueMake;
- 173 : SichereVoc;
- 174 : ShortFlag := TRUE;
- 175 : ShortFlag := FALSE;
- 190 : MemSizes;
- ELSE Error(4);
- END;
- END;
-
- PROCEDURE DoMap(Ptr : pSymtab);
- VAR
- p1 : pSymtab;
- n : STRING;
- Typ : BYTE;
- Adr : WORD;
- Used : BYTE;
- BEGIN
- IF Ptr^.LLink <> NIL THEN DoMap(Ptr^.LLink);
- IF (Ptr^.Typ < 15) AND (Ptr^.Typ <> 10) THEN
- IF (NOT Ptr^.Used) AND
- (NOT(Ptr^.Name[BYTE(Ptr^.Name[0])] = #0)) THEN
- WriteLn(ef, ' 0000:',
- Hex(Ptr^.Par0, 4), ' ', Ptr^.Name);
- IF Ptr^.RLink <> NIL THEN DoMap(Ptr^.RLink);
- END;
-
-
- BEGIN (* Hauptprogramm *)
- New(m);
- New(IFB);
- Init;
-
- { Startcode }
- Ob($EB); Ob($3E); { jmp 140 }
-
- { Compiler-Bereich }
- Ow($0000); { adr $102: MAIN }
- Ow($0000); { adr $104: r0 }
- Ow($FE00); { adr $106: s0 }
- Ow($0000); { adr $108: dp }
- Ow($0000); { adr $10A: frei }
- Ow($0000); { adr $10C: frei }
- Ow($0000); { adr $10E: frei }
-
- { Copyright-Notiz }
- Ob(13); Ob(10);
- Os('NX-Optimiernder Compiler v1.01ß/''92 ');
- Ob(13); Ob(10); Ob(26);
- Ot($134, 0); { Video+MouseByte init }
- pc := $13D; { Codeanfang }
-
- { Debug- und Overlay-Einsprung }
- Ob($FF); Ob($D7); { call di }
- Ob($CB); { retf }
-
- { pc = $140: Register retten }
- Ob($2E); Ob($8C); Ob($1E); Ow($0122); { mov cs:[122],ds }
- Ob($2E); Ob($A3); Ow($0110); { mov cs:[110],ax }
- Ob($8C); Ob($C8); { mov ax,cs }
- Ob($8E); Ob($D8); { mov ds,ax }
- Ob($FA); { cli }
- Ob($8C); Ob($16); Ow($0126); { mov [126],ss }
- Ob($89); Ob($26); Ow($0118); { mov [118],sp }
- Ob($8C); Ob($06); Ow($0124); { mov [124],es }
- Ob($89); Ob($1E); Ow($0116); { mov [116],bx }
- Ob($5B); { pop bx }
- Ob($58); { pop ax }
- Ob($50); { push ax }
- Ob($53); { push bx }
- Ob($A3); Ow($0120); { mov [110],ax }
- Ob($89); Ob($0E); Ow($0112); { mov [112],cx }
- Ob($89); Ob($16); Ow($0114); { mov [114],dx }
- Ob($89); Ob($2E); Ow($011A); { mov [11A],bp }
- Ob($89); Ob($36); Ow($011C); { mov [11C],si }
- Ob($89); Ob($3E); Ow($011E); { mov [11E],di }
- Ob($9C); { pushf }
- Ob($58); { pop ax }
- Ob($A3); Ow($0128); { mov [128],ax }
- Ob($FB); { sti }
-
- { INT0 retten }
- Ob($B8); Ow($3500); { mov ax,3500 }
- Ob($CD); Ob($21); { int 21 }
- Ob($89); Ob($1E); Ow($0130); { mov [130],bx }
- Ob($8C); Ob($06); Ow($0132); { mov [132],es }
-
- { Videomode retten }
- Ob($B4); Ob($0F); { mov ah,0F }
- Ob($CD); Ob($10); { int 10 }
- Ob($2E); Ob($A2); Ow($0134); { mov cs:[134],al }
-
- { Stackmaschine bauen }
- Ob($FA); { cli }
- Ob($8C); Ob($C8); { mov ax,cs }
- Ob($8E); Ob($D8); { mov ds,ax }
- Ob($8E); Ob($D0); { mov ss,ax }
- Ob($31); Ob($DB); { xor bx,bx }
- Ob($FC); { cld }
- Ob($8B); Ob($26); Ow($0104); { mov sp,[104] }
- Ob($8B); Ob($36); Ow($0106); { mov si,[106] }
- Ob($FB); { sti }
-
- { MAIN aufrufen }
- Ob($8B); Ob($3E); Ow($0102); { mov di,[102] }
- Ob($FF); Ob($D7); { call di }
-
- { EXIT-Code: }
-
- { Videomode restaurieren }
- Ob($A0); Ow($0134); { mov al,[134] }
- Ob($B4); Ob($00); { mov ah,00 }
- Ob($CD); Ob($10); { int 10 }
-
- Ot($102, pc); { IF NO MAIN }
-
- { INT0 restaurieren }
- Ob($B8); Ow($2500); { mov ax,2500 }
- Ob($8B); Ob($1E); Ow($0130); { mov bx,[130] }
- Ob($8E); Ob($06); Ow($0132); { mov es,[132] }
- Ob($CD); Ob($21); { int 21 }
-
- { Exit }
- Ob($B4); Ob($4C); { mov ah,4C }
- Ob($A0); Ow($0135); { mov al,[135] }
- Ob($CD); Ob($21); { int 21 }
-
- { ... Haupt-Programm verabschiedet }
-
- { Compilieren: }
-
- Wort := HoleWort;
- IF Wort = Empty THEN GOTO OkMCC;
- WHILE (Wort <> Empty) DO BEGIN
- Compile(Wort);
- Wort := HoleWort;
- END;
-
- OkMCC:
- { Compiler-Variablen setzen }
-
- Ot($108, pc); { Dictionary-Pointer }
- IF (r0 <> $FFFF) OR(s0 <> $FFFF) THEN BEGIN
- IF Odd(pc) THEN Inc(pc);
- s0 := pc + s0 + 2;
- r0 := s0 + r0 + 2;
- Ot($104, r0);
- Ot($106, s0);
- END;
- { COM-File erzeugen }
-
- IF NoCodeFlag = FALSE THEN BEGIN
- Assign(OutFile, Pfad + Name + '.com');
- ReWrite(OutFile, pc - 256);
- BlockWrite(OutFile, m^[256], 1);
- Close(OutFile);
- END;
-
- IF MapFlag THEN BEGIN
- DXName := Name;
- Assign(ef, Pfad + Name + '.MAP');
- ReWrite(ef);
- WHILE (Length(DXName) < 19) DO DXName := DXName + ' ';
- WriteLn(ef, ' Start Stop Length Name'
- + ' Class');
- WriteLn(ef);
- WriteLn(ef, ' 00100H 0', Hex(pc, 4), 'H 0',
- Hex(pc - $FF, 4), 'H ', DXName, 'CODE');
- WriteLn(ef);
- WriteLn(ef, ' Address Publics by Value');
- WriteLn(ef);
- DoMap(Root);
- WriteLn(ef);
- WriteLn(ef, 'Program entry point at 0000:0100');
- Close(ef);
- END;
- IF NOT IncludeFlag THEN Close(IncF);
-
- IF XDBFlag THEN BEGIN
- Assign(Debug, Pfad + Name + '.XDB');
- ReWrite(Debug);
- FOR i := 0 TO IFBTop DO Write(Debug, Chr(IFB^[i]));
- Close(Debug);
- END;
- Result.Main := WORD(m^[$102] + 256 * m^[$103]);
- Result.Here := WORD(pc);
- Result.s0 := WORD(m^[$106] + 256 * m^[$107]);
- Result.r0 := WORD(m^[$104] + 256 * m^[$105]);
- Result.Bytes := WORD(pc - $100);
- Result.Zeilen := WORD(Nummer);
- Dispose(IFB);
- Dispose(m);
- END.
-
- (* ====================================================== *)
- (* Ende von NXO.PAS *)
-
-