home *** CD-ROM | disk | FTP | other *** search
- (* ====================================================== *)
- (* NX.PAS *)
- (* 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+,E+,R-,S-,I-,A+}
-
- PROGRAM Naxos;
-
- 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 = $FFFE; { Inputfile Buffergröße }
- MaxName = 12; { Namensgröße }
-
- TYPE
- Memory = ARRAY[256..MaxProg] OF BYTE; { 62 KByte }
- PMemory = ^Memory;
- PSYMTAB = ^SYMTAB;
- SYMTAB = RECORD
- Name : STRING[12];
- Typ : BYTE;
- QFA : WORD;
- PAR0,
- PAR1,
- PAR2,
- PAR3 : WORD;
- QFAlen : WORD;
- 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 : BYTE ABSOLUTE $0040:$0049;
- 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 }
- Outfile : FILE; { compilierter Code }
- Zeile,
- LZ : ZeilenTyp; { Forth-Textzeile }
- LastTyp,
- WTyp : BYTE; { Worttyp }
- Wort, { Forth-Wort }
- VocName, { Vocabulary }
- Merker,
- Merker2 : WortTyp; { Merker }
- IFB : IfBTyp; { Input File Buffer }
- IFBP : WORD;
- IFBMax : WORD;
- Name : NameStr;
- Ext : ExtStr;
- Pfad,
- SysPfad : DirStr;
- DXName : STRING;
- DateiName: STRING[MaxZeile]; { 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, { Feldakkumulator }
- Macro, { Macrogrenze aktuell}
- MacroLim, { Vorgabe Grenze }
- SP, { Stackpointer }
- Nummer, { Zeilennummer }
- Anfang, { Anfang Dictionary }
- Ende, { Ende Dictionary }
- VocAnfang, { Start Vocabulary }
- OFCnt, { OF-Zähler }
- i, { Zählvariable }
- Mn, { Main-Adresse }
- RecLen : WORD; { Datenlänge }
- FZeiger, { Zeiger auf gefundenes Wort }
- Zeiger : pSymtab; { Zeiger auf aktuelles Definitionswort }
- M : pMemory; { Speicherbereich }
- S : 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 }
- Flagstack, { Bedingungsstack }
- Found, { für Wortsuche }
- NoCodeFlag, { speichern ein/aus }
- Includeflag, { Nur ein Incl.file }
- ShortFlag, { Short-Jump ein/aus }
- Comment, { Kommentar }
- MapFlag : BOOLEAN; { Zur Erzeugung von MAP-Files } { neu 2.1.92 }
- LineLen : WORD; { Zeilenlänge }
- Sif : FILE; { Globales Includefile }
- InDef : BOOLEAN; { In Definition Flag; }
- { True zwischen : oder PROC und ; }
- 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 }
- BEGIN
- Result.ErrorPos := IFBP;
- Result.ErrorWort:= Merker;
- Dispose(IFB);
- Dispose(M);
- Halt(100 + nr);
- END;
-
- PROCEDURE Hilfe;
- BEGIN
- WriteLn;
- WriteLn('NAXOS Compiler Version ', Version);
- WriteLn('(C) 1992 DMV-Verlag & Peper, Zissis, Tossounidis');
- WriteLn;
- WriteLn('Aufruf: NX Dateiname -m -n ');
- WriteLn;
- WriteLn(' (Parameter sind optional)');
- WriteLn;
- WriteLn(' -m MAP-Datei erzeugen');
- WriteLn(' -n Keine Code-Erzeugung');
- 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;
- MapFlag := FALSE; { ** neu 2.1.92 ** }
- 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;
- 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);
- IFBMax := 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;
- LineLen := 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^.RLink := NIL;
- Root^.LLink := NIL;
- Root^.Name := 'FFFFFFFFFFFF';
- Root^.Typ := 254;
- Root^.PAR0 := 0;
- Root^.PAR1 := 0;
- Root^.PAR2 := 0;
- Root^.PAR3 := 0;
- Assign(Sif, SysPfad + 'SYSTEM.DIC');
- {$I-} Reset(Sif, SizeOf(Root^) - 10); {$I+}
- IF IOResult <> 0 THEN Error(25);
- REPEAT
- New(x);
- BlockRead(Sif, x^, 1);
- x^.QFAlen := 0;
- 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 >= IFBMax 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[36] = '▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒';
- 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 / IFBMax) * 36));
- 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 [160..165, 177, 181, 191, 192]) THEN
- QFAs := Bffr;
- 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 := INTEGER(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;
-
- FUNCTION Suche(Name: STRING): BOOLEAN;
- { Namen in Dictionary suchen }
- LABEL
- Ok;
- VAR
- 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;
- REPEAT
- p2 := p1;
- IF Name > p1^.Name 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;
- 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^.QFA := QFAs;
- Zeiger^.RLink := NIL;
- Zeiger^.LLink := NIL;
- Main := Name = 'MAIN';
- END;
-
- PROCEDURE TueLink;
- VAR
- p1, p2 : PSYMTAB;
- BEGIN
- Zeiger^.QFAlen := IFBP - Zeiger^.QFA;
- p1 := Root;
- 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
- FZeiger^.Name := FZeiger^.Name+#0; { #0 an Name anhängen }
- 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;
- 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;
- 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 }
- RegFix := 0;
- END;
- 2: BEGIN { BX, ADR }
- Ob($BB); Ow(n); { mov bx,n }
- RegFix := 0;
- END;
- 3: BEGIN { DX, TO, ,, }
- Ob($BA); Ow(n); { mov dx,n }
- RegFix := 0;
- END;
- 4: BEGIN { SX }
- Ob($4E); Ob($4E); { dec si,dec si }
- Ob($C7); Ob($04); Ow(n); { mov [si],n }
- END;
- END;
- 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 }
- RegFix := 0;
- 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;
- 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 }
- VAR
- nn, Fehlern : INTEGER;
- z : CHAR;
- Len, Dis : BYTE;
- Disp, Fehler,
- Adr, Adr1,
- Adr2 : WORD;
- Zgr1, Zgr2 : pSymtab;
- Gefunden : BOOLEAN;
-
- BEGIN
- Sys := TRUE;
- IF WTyp > 127 THEN
- CASE WTyp OF
- { ; }
- 128: BEGIN
- Ob($C3); { ret }
- ShortFlag := TRUE;
- 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: PcMerker := Pc;
- { [PC] }
- 183: Ow(PcMerker);
- { IF }
- 132: 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;
- { 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: 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;
- { 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; { for }
- 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);
- TueLiteral(PAR0);
- END;
- { BEGIN }
- 145: Push(Pc, _BEGIN, 0);
- { UNTIL }
- 146: BEGIN
- Adr := Pop(_BEGIN, Len);
- Branch0(Adr);
- END;
- { WHILE }
- 147: 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;
- { 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;
- 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;
- 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;
- 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);
- 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;
- { (short) }
- 174 : ShortFlag := TRUE;
- { (long) }
- 175 : ShortFlag := FALSE;
- { 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);
- w := HoleWort;
- IF w = Empty THEN Error(2);
- IF NOT Found THEN Error(4);
- IF WTyp <> _PROC THEN Error(30);
- 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;
- BEGIN
- REPEAT
- w := HoleWort;
- IF (WTyp = 181) OR (WTyp = 161) THEN Error(44);
- IF w = Empty THEN Error(2);
- TueSystem(w);
- IF Sys THEN RegFix := 0;
- 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 = TRUE 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:
- UNTIL WTyp = 128;
- 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 }
- 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 }
- TueLink;
- InDef := FALSE;
- END;
-
- PROCEDURE TueVariable;
- { Baue Datenstruktur auf }
- LABEL
- Ok;
- 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 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;
- 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;
- TestSemi;
- TueLink;
- 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;
- TestSemi;
- TueLink;
- 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;
- TestSemi;
- TueLink;
- 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 }
- TestSemi;
- TueLink;
- END;
-
- PROCEDURE TueMake;
- VAR
- w : WortTyp;
- Adr1,
- Adr2,
- Typ : INTEGER;
- Gefunden : BOOLEAN;
- BEGIN
- w := HoleWort;
- IF w = Empty THEN Error(4);
- IF NOT Found THEN Error(4);
- Adr1 := PAR0;
- IF WTyp <> _VECTOR THEN Error(29);
- w := HoleWort;
- IF w = Empty THEN Error(4);
- IF NOT Found THEN Error(4);
- Adr2 := PAR0;
- IF WTyp <> _PROC THEN Error(30);
- Otb(Adr1, $E9); { jmp disp }
- Ot(Succ(Adr1), Pred(Near(Adr1, Adr2)));
- 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;
- { aktuelles Vocabulary sichern }
- VAR
- v : FILE;
- nam : WortTyp;
- gri : WORD;
-
- PROCEDURE SV(Ptr: PSYMTAB);
- BEGIN
- BlockWrite(v, Ptr^, gri);
- IF Ptr^.LLink <> NIL THEN SV(Ptr^.LLink);
- IF Ptr^.RLink <> NIL THEN SV(Ptr^.RLink);
- END;
-
- BEGIN
- gri := SizeOf(Root^) - 8;
- nam := Name + '.DIC';
- Assign(v, Pfad + nam);
- ReWrite(v, 1);
- BlockWrite(v, Pc, 2);
- SV(Root);
- Close(v);
- END;
-
- PROCEDURE TueInclude;
- { Vocabulary einbinden }
- VAR
- Name, nam : WortTyp;
- v : FILE;
- x, p1, p2 : PSYMTAB;
- gr, gri : WORD;
- BEGIN
- gri := SizeOf(Root^) - 8;
- 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);
- {$I-} 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;
- 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);
- Name := nam + '.COM';
- Assign(v, Pfad + Name);
- {$I-} Reset(v, 1); {$I+}
- IF IOResult <> 0 THEN Error(25);
- BlockRead(v, M^[$100], gr - $100);
- Pc := gr;
- Close(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(1);
- END; {case}
- 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^.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('Naxos-Compiler, Version 1.01 ß/1992 ');
- 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;
- 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 NX.PAS *)
-
-