home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turbo Toolbox
/
Turbo_Toolbox.iso
/
dtx9203
/
naxos
/
source
/
nxo.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1992-02-08
|
53KB
|
2,015 lines
{$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 *)