 F6 nderungen, Ergnzungen, Korrekturen und ein paar Tips in loser Folge,
 ergnzend zur Dokumentation "forth_gls" in der Version vom 4.8.1993,
 Reihenfolge mit den jngsten nderungen zuerst.
 Beschreibung der Funktion des Hilfs-Jobs s. Vers. 7.15
        7.23     1.2.95   jngste hier behandelte Version, damit hat
 dieser Text neben den allgemeinen Beispielen nurmehr "historischen" Wert.
        8.08    20.8.96   jngste in "F6WORDS_txt" beschriebene Version,
 auf die hier nicht gesondert eingegangen wird.

 Neben dem F6 steht (kostenlos) noch ein fig-Standardsystem zur Verfgung,
 das mit weniger als 6K Bytes fr den Kern extrem kompakt ist.
 Autor ist Laurence Reeves, der die f.i.g.-Standard-Installation fr den QL
 zurechtgemacht hat. Das System wurde an einigen wenigen Stellen von Fehlern
 befreit und ergnzt, soda es nun auch ber bis zu 64K Adressbereich verfgt.

 Wer geneigt ist, die F6-Beschreibungen in eine andere Sprache zu bersetzen,
 wird gebeten, dies zu tun, und sich mit dem Autor in Verbindung zu setzen.

 Kennzeichnung:
 disp    displacement, Abstand z.B. von einer Adresse
 {namen} zwischen "{" und "}" ohne Kennzeichnung gehren dem Forth-Vocabular an
 (a)     assembler-Vocabular asm68
 (D)     deferred
 (h)     hidden-vocabular
 (I)     immediate
 (r)     root-Vocabular
 (S)     vom Screenfile "forth_scr" zu compilieren

 * ++ 1994 ++ ab Version 7.15 +++++++

 Copyright (C) 1996 by
        H.-Peter Recktenwald, D-12159 Berlin, Albestr. 21
        Tel.: 030 8520413  -  inet  phpr@berlin.snafu.de

 * ++ Praeliminarien ++++++++++++++++

 Nach dem Muster des (ziemlich vollgestpften) F-PC zum ibm-PC zuerst mal eine
 Liste, wie sich das System am effizientesten zum ZUSAMMENBRUCH bringen lt,
 und wie NICHT, wo aber andere Systeme sich blicherweise verabschieden. Zuerst
 die problematischen Operationen, die dort mit groer Sicherheit zum Desaster
 fhren, die aber im F6 erlaubt sind, oder abgefangen werden:
        -1 @            ungerade Adressen sind im F6 erlaubt,
        -1 !            kann Probleme verursachen, wenn dort compilierte
                        Worte stehen (-1 ist etwa die Mitte des Dictionary).
        -1 >r           endet in einer ausfhrlichen Fehlermeldung, ausgelst
                        normalerweise durch die trap-redirection des QDOS, die
                        das F6-System schtzt, oder wird durch den zustzlichen
                        berwachungsjob des F6 abgefangen (Super-GC/qxl);
        perform         bei (versehentlich) ungeraden Adressen gleichermaen.
        >r              wird fast immer abgefangen (fter Fehler bei SMSQ).
        r>              was fr alle Returnstack-Operationen gilt.
        0 0 DO          kehrt nach einmaliger Ausfhrung der Schleife zurck.
        multitasking    mit mehreren F6-Jobs ist dank QDOS vllig problemlos,
                        mit einzelnen 4th-Worten durch die Tasker-Erweiterung
                        gibt es nur selten Schwierigkeiten.
        forget          des Ziels von {deferred}-Worten wird abgefangen, das
                        Wort kehrt dann mit Fehlermeldung nach {quit} zurck.
                        Anwenderdefinitionen knnen denselben Schutz mittels
                        einer Aufrufverkettung ber das deferred-Wort {doforget}
                        erreichen (s. u.a. ARRAY und HEAPMEM aus "forth_scr").
        BEGIN .. AGAIN  neben allen anderen Schleifen, auch direkt in Assembler-
                        Code (versehentlich) programmierten, kann unterbrochen
                        werden, solange {break} nicht auf -1 gesetzt wurde.
                        UND sofern nicht irgendwer das Multitasking des QL
                        "verbesert" hat...

 Hier kann auch im F6 nichts mehr helfen:
        !               irgendwohin in das Dictionary ist (meist) tdlich,
        !l              an falsche absolute Adresse erst recht.


 * ++ Verzeichnis der wichtigsten Zusatzdefinitionen
 aus "forth_scr" mit den vorrangig zur Auswahl durch {l-load} zu verwendenden
 Namen - {l-load} ist im Kern nur als Rumpf vorhanden, der beim erstmaligen
 Aufruf den Versuch startet, die volle Definition aus "flp1_forth_scr" zu laden.
 Ist diese Datei nicht vorhanden, ldt man z.B.
        1 s-load {dirname}_forth_scr
 oder legt vorher einen Filenamen nach {(boot)}, z.B. mit
        " n1_flp2_forth_utl_forth_scr" (boot) over @ f/n min 2+ cmove

array   Variablenfelder auerhalb des Dictionary (im Speicher-Heap)
backup  Dateien copieren
#chan   standardisierte Kanaldefiniton
c-load  laden bereits compilierter Worte
c-save  sichern eines Blockes 4th-Worte fr {c-load}, ldt auch {c-load}
debugger debug-Aktionen zur Ausfhrung/Compilation bei {is-debug} =/= 0
dir     Directory und Filedaten anzeigen
dump    Inhalt des 4th-Speichers anzeigen
label   Hilfsdefinitionen fr Assembler-Labels
ldump   dto., Inhalt beliebiger Speicherbereiche
enter   besonderer Schleifeneinsprung
heapmem abgesicherte Speicherzuweisung und Adressenspeicherung
history macht die command-line-history von "Oktagon" fr F6 aufrufbar
.jobs   alle QDOS-Jobs und ihre Basisdaten anzeigen
minerva erzeugt ein paar nur in Minerva aufrufbare f.p.-Rechenoperatoren
printer Worte zum Drucken, ggf. zusammen mit der Bildausgabe
q.      vierfachgenaue Zahlen in Strings umwandeln/ausgeben
.s      Stack-Dump (ab 7.22 nicht mehr im Kern), auch mit {debugger} geladen.
sort    "tag-sort" Sortierverfahren fr 4th-Pointer
sort-l  oder beliebige Speicher- und Fileadressen
turtle  Worte zur Krten- (Krabbel- oder  auch "turtle"-) Graphik
.vocs   Anzeige der aktuellen Vocabularstruktur
where   Hilfe bei Fehlerabbruch in den {load}-Varianten
words   alphabetisch sortierte und durch Auswahl einschrnkbare Wortliste


 * ++ SYSTEMSPERRUNG fr SICHERUNG und WEITERGABE eigener F6-PROGRAMME

 Eine recht sichere Sperrung des Systems wird erreicht mit:
        ' quit also hidden is [cpl]
 Diese Programm-Versiegelung macht den Compiler unwirksam. Direkte Eingabe ist
 weiter mglich. Soll das Programm selbst gegen "Spionageversuche" geschtzt
 werden, aber z.B. auch gegen (versehentliche) Fehleingaben, sind darum weitere
 Manahmen erforderlich.

        ' {wort} also hidden is [interpret]
 Dann werden nur noch Zahlen in direkter Eingabe erkannt, jede andere Eingabe
 ruft das o.g. {wort} auf. Da aber das Eingabeende, das ja auch durch <enter>
 signalisiert wird, stets das <nul>-Wort aufruft und interpretiert, lst auch
 eine direkte Zahleneingabe sogleich wieder das vorgegeben {wort} aus. Nur die
 Text- oder Zahleneingabe innerhalb eines Programms bleibt weiter mglich.
 Diese letzte Umstellung kann darum nicht vor dem Sichern als Job-File erfolgen,
 sondern mu in das Programm selbst eingebaut werden, mglichst an einer Stelle,
 bis zu der nach dem Start Unterbrechungen nicht mglich sind.

 Eine weitere Variante zeigt der kleine Beispiel-Job "f6hnoi", der die "Trme
 von Hanoi" einmal mehr zum Programmtest strapaziert. Durch Umstellen des
 <nul>-Wortes wird hier eine einzelne Eingabezeile ordentlich interpretiert,
 dann aber sofort das Wort {hanoi} aufgerufen. Vorteil dabei ist, da so der
 Programmstart auch interaktiv mit Parameterbergabe erfolgen kann, und kleine
 Sequenzen, wie z.B. { 0 wmov } noch aufrufbar bleiben. Wurde, wie im Beispiel,
 zustzlich {[cpl]} gendert, ist ein solches Programm sehr sicher geschtzt:
        ' {wort} cfa    also hidden also assembler
                     dup dup dup ' [cpl] 2! [nul-pfa] 2!

Natrlich gibt es auch hier Mglichkeiten, den Schutz aufzubrechen. Doch ist
das mit soviel Mhe verbunden, da der Preis vielleicht gerechtfertigt ist.
So soll also dem siegreichen "Knacker" sein Lohn dann gegnnt sein, er wird
lediglich gebeten, sein Ergebnis nicht excessiv unter die Leute zu bringen.


 * ++ NICHT KORRIGIERTE FEHLER ++++++

headr   mu die Angabe der zu lesenden Anzahl Bytes separat erhalten:
                ( ptr -- len flg )  14 d2w! headr
        Die lt. Beschreibung fest vorgegebene Zahl 14, und darum wurde dies
        nicht im Code korrigiert, kann somit auch gendert werden, wodurch
        sich ggf. noch Filename und Datumsangaben lesen lassen.
        Ein der Dokumentation entsprechender Ersatz kann definiert werden:
                qdos definitions
        : headr 14 literal -compile d2w! -compile headr ; immediate


 * ++ VERSIONEN +++++++++++++++++++++

 * ++ 20. 8.96 ++ v8.08 +++++++++++++

 NEU: ist die Umstellung von QUERY auf eine deferred-Definition, ebenso
 (EXPER), das die Fehlerbehandlung in EXPECT und QUERY besorgt, um die
 Erweiterung auf die File-Worte des ANS-Standard zu erleichtern. Weiter
 wurden einige Fehler korrigiert, andere nderungen gibt es nicht.

 * ++  1. 2.95 ++ v7.24 +++++++++++++

$8000   Inhalt dieser Adresse auf $8000 gendert.
-0      als Constante mit dem Wert $8000 eingefhrt und als Null-Referenz
        der Adressierung benutzt. Sonderfall:  $8000 ABS liefert 0.

 NEU: U.a. ein universeller Stackoperator und Locale Variable.

stack   (I)( n1...nn -- nx...ny )       stack abcDEf..|abcdeFABc
           ( d1...dn -- dx...dy )       stack ABCDEF..|abCDefAbC
        Ein universell anstelle von Stackmanipulationen in einer Stacktiefe von
        bis zu 26 Quellen-Posten anwendbarer Aufruf. So, wie irgendeine Folge
        von Buchstaben hingschrieben wird, wird die Reihenfolge von Datenposten
        aus dem Buchstabenwert entsprechenden Positionen im Stack neu angeord-
        net. Gro- und Kleinschreibung sind gleichwertig, mit der Ausnahme, da
        doppelte Posten transportiert werden, wenn der Quellenteil nur(!) groe
        Buchstaben enthlt. "a" gilt fr den Quellenposten 0, "z" fr 25. Diese
        werden mit der nach dem "|" notierten Indizierung entnommen und in den
        Datenstack copiert. Quellen- und Zielangabe zusammen knnen bis zu 62
        Zeichen umfassen. Ohne "|" Strich bleibt der Aufruf wirkungslos.
        Ein paar Beispiele mit Standard-Entsprechung:
                stack a|aa                      dup
                stack abc|bca                   rot
                stack abcd|abcdaabb             over >r dup dup r r>
                stack abcdefghij|abcdefghijab   9 pick 9 pick
                stack abcdefghij|cdefghijab     9 roll 9 roll
        1 2 3 4 stack abcd|abcdac (    -->   )  1 2 3 4 1 3
        1 2 3 4 stack abcd|aacc   (    -->   )  1 1 3 3
                stack abc|                      2drop drop
        Die Angabe entspricht also genau der Form, wie bei der Beschreibung
        von Forth-Worten blicherweise die Stackvernderungen notiert werden.

        Die Ausfhrungszeit entspricht bei kleineren Listen ungefhr der von
        zwei {roll}-Aufrufen, bietet, da im gefdelten (interpretive) Forth-
        Compiler hier nur wenig optimierbar ist, also nichts Sensationelles:
                2rot 8 ndup             braucht nur ein Drittel der Zeit von
                stack abcdefgh|cdefghabcdefhgab
        Dagegen ist die Schreibweise so viel bersichtlicher, da bei kompli-
        zierten Anordnungen und bei groer Anzahl Daten im Stack Prorammier-
        fehler sehr sicher zu vermeiden und evtl. ungnstige Einzeloperatoren
        dann doch recht effizient zu ersetzen sind. Auf jeden Fall aber hilft
        {stack} beim Ausprobieren von Worten mit umfangreichen und komplizierten
        Parameterstrukturen und dem Herantasten an die gnstigste bergabe, bis
        dann ggf. mit den Standardoperatoren Compatibilitt geschaffen und die
        Ausfhrungsgeschwindigkeit optimiert werden kann.
        Die Anordnung der Indices hat keinen Einflu auf die Ausfhrungszeit.

        Damit sind die zusammengesetzten Stackoperatoren berflssig, wie z.B.
        {sdup}, {sover}, aber auch alle anderen nicht-trivialen Aufrufe, etwa
        {2rot} u.dgl., die aber der geringeren Ausfhrungszeit wegen beibehalten
        wurden. Zur bersetzung kann leicht die Darstellung der Datenanordnung
        vor und nach dem jeweiligen Aufruf herangezogen werden, die, bertragen
        in buchstabenweise Bezeichnung, direkt als Operatorenstring dient:
                stack ab|baa    folgt fr {sdup} aus ( n1 n2 -- n2 n1 n1 )
                stack ab|bab              {sover}    ( n1 n2 -- n2 n1 n2 )

        Compiliert wird nach der Runtime-cfa die in Indices und "|"-Markierung
        umgewandelte Zeichenfolge samt Countbyte, am Ende ggf. fr gerade Folge-
        adresse mit einem Byte aufgefllt. Als Indices ausgewertet werden die 5
        niederwertigen Bits jedes Zeichens mit Ausnahme des Quellen- und Zielan-
        ordnung trennenden Striches "|". Gesetztes hchstwertiges Bit im Count-
        byte markiert doppelte Postengre. Der "|" wird durch ein negatives
        Byte ersetzt, das den bergang von Ablage- zu Lese-Indices markiert.

        Diese Ablageform ist angeregt durch ein FIFTH-System zum IBM-PC ent-
        standen, dessen Programme damit sehr leicht in einen F6-Aufbau ber-
        tragbar waren: Das Beispiel der "Trme von Hanoi" lie sich mit dem
        neuen Stack-Wort ohne nderung bernehmen!

local   (I)  entry:  LOCAL abc..|       compiling: ( ptr 9 -- ) resolved by {;}
             call:   LOCAL b
        Nun (endlich?) steht eine mit dem f.i.g.-Standard VLLIG KONFLIKTFREI
        verwendbare Installation von Localen Variablen zur Verfgung:

        Die Operationen in beiden Stacks bleiben von Localen Variablen gnzlich
        unbeeinflut. Einzig der Datenstack-Ursprungspointer {s0} darf nicht
        verndert werden - was mit wenigen hchst speziellen Ausnahmen bedeu-
        tungslos ist. Die betr. Worte sind zudem unbedingt regulr zu beenden,
        sie drfen also nicht mit {;s} oder {-exit} vorzeitig verlassen werden.
        Die Localen Variablen sind recursiv aufrufbar; sie eignen sich auch fr
        tasker-Definitionen (Ausfhrung von Forth-Worten als selbstndige Jobs).

        Von anderswo beschriebenen Installationen unterscheiden sich die Localen
        Variablen des F6 insbesondere z.B. dadurch, da sie unverndert und ohne
        Einflu auf die Schleifenindices innerhalb von DO..LOOPs aufrufbar sind.
        Smtliche Returnstack-Manipulationen bleiben weiterhin einsetzbar, ein-
        schlielich so schlimmer Sachen, wie {rdrop} zur Rckkehr "vor" das auf-
        rufende Wort. Der Datenstack bleibt unverndert zugnglich und wird in
        den regulren Grenzen berwacht, d.h. der Local-Bereich ist geschtzt.

        Bei {warm} und {cold} werden die Localen Variablen aufgegeben, nicht
        aber bei {abort} und {error} mit allen Varianten, solange ihre Basis-
        Definitionen mit Rckkehr nach {quit} erhalten bleiben.

        hnlich den mit {constant} definierten Zahlen sind die einzelnen Posten
        durch ihren Namen (hier aus nur einem Buchstaben bestehend) abrufbar.
        Sie werden zu Beginn einer Hi-Level-Definition eingerichtet und mit den
        im Stack vorhandenen Posten initiiert. Die Namen sind zugleich Index in
        den Bereich, der auch die Localen Variablen aufrufender Worte enthlt.
        Eine Grenzenkontrolle wurde nicht eingebaut, und so sind uere Locale
        Variable mit Indices erreichbar, die ber die der eigenen Definition
        hinausweisen. {tib} kann zusammen mit der Local-Adresse aus {-loc} zur
        Prfung auf die absolute Obergrenze herangezogen werden, da der Stack-
        ursprung ohne Locale Variable mit dem Anfang des t.i.b. identisch ist
        (solange dessen Lage nicht verndert wurde).

        Die Benennung bezeichnet in alphabetischer Reihenfolge, beginnend mit
        "A" oder "a", die einzelnen Variablen, die vom unteren (jngsten) Stack-
        posten angefangen in den localen Bereich bertragen wurden.
        Es lassen sich in jedem Wort maximal 26 Locale Variable definieren, die
        Liste kann insgesamt bis zu 62 Datenposten (lang oder kurz) indizieren.
        Die Werte knnen wie Variable mit Hilfe ihrer Adressen verndert werden.

        HINWEIS: In Laufzeit-kritischen Sequenzen sollte die Einrichtung Localer
        Variabler mglichst vermieden werden, da dies mit zunehmender Stacktiefe
        einen u.U. recht erheblichen Zeitaufwand fordert.

local abc..|                            sys: --  stringptr 9
local ABC..|    ( nX.. nC nB nA -- nX ) loc: ..nn  -- ..nn nC nB nA
        Wenn seit dem Definitionsanfang noch keine Compilerdaten im Systemstack
        (identisch dem Datenstack) abgelegt sind, erwartet der erste Aufruf von
        {local} in einem Hi-Level-Wort eine Buchstabenfolge wie fr {stack},
        jedoch nur bis zum Strich "|". Wie dort bestimmt deren Schreibweise die
        Ablage als einfache oder doppelte Integer. Die der Anzahl an Localen
        Variablen entsprechende Anzahl Stackposten wird bei der Ausfhrung mit
        bernahme in die locale Ablage zugleich vom Datenstack abgehoben.
local | Gibt man nur den Strich an, werden keine eigenen Posten eingerichtet.
        Der Compiler empfngt hierdurch lediglich das Signal, fortan {local}
        als Lese-Aufruf zu compilieren. In einem solchen Wort indizieren die
        Localen Variablen die Posten des bergeordneten Aufrufs mit denselben
        Namen, die sie fr entsprechende Stellen im eigenen Bereich htten.
IF .. local .. ELSE                     sys: nn -- nn
        Innerhalb von Compiler-Strukturen ist die Deklaration einer Local-Gruppe
        nicht mglich. Die {local}-Aufrufe werden nur als Lese-Variante (s.u.)
        compiliert, da die einfache Signalisierungsmethode das Vorhandensein der
        Initiierung vortuscht: Sobald seit dem Wortanfang irgendwelche Daten
        in den Stack gebracht worden sind, gilt dies als Signal, nur noch Lese-
        aufrufe zu compilieren.
local a                                 sys: nn  -- nn  ( nn beliebig )
local A Jeder weitere Aufruf von {local} wertet den ersten folgenden Buchstaben
        als Bezeichnung (Index) einer Localen Variablen aus und holt die Zahl
        zum Datenstack. Auch hier bestimmt die Schreibweise, ob einfache oder
        doppelte Integer gelesen werden. f.p.-Zahlen werden nicht verarbeitet.
-loc A  (I)( -- ptr )                   sys: nn -- nn   ( nn beliebig )
-loc a  liefert den ptr auf die Speicherstelle einer Localen Variablen, die
        damit wie die gewhnlichen Forth-Variablen nicht nur gelesen, sondern
        auch verndert werden kann.
;       (I)( -- ) ergnzt               sys: -- | stringptr 9 --
        Wenn der Systemstack (noch) nicht leer ist, und die  Markierung passt,
        wird am Ende der Definition durch {;} automatisch ein zustzliches Wort
        compiliert, das bei der Ausfhrung die Localen Variablen lscht.

        Compiliert werden bei der Deklaration:
                lv! count.b+chars[+fllbyte]    Deklaration, oder
                (nichts)                        bei { local | }
        zum Lesen des Wertes:
                lv@ disp                        disp aus dem Index ermittelt als
                                                Abstand von s0 zum Datenposten.
        zurm Holen des Variablen-Pointers:
                lv  disp                        4th-Adresse, mit Abstand wie lv@
        zur Freigabe bei Wortende:
                lvr count                       count als Anzahl freizugebender
                                                Bytes im Local-Speicher, oder
                (nichts)                        wenn keine eigenen Localen
                                                Variablen eingerichtet wurden.

        Die Namen {lv!}, {lv@}, {lvr} und {lv} sind nicht aufrufbar. Dennoch
        lt sich mit dem Runtime-Wort zum Auflsen des Local-Bereichs eine
        Compileranweisung definieren,
                : end-loc [ ' -loc nfa even 6-  ] literal , , ; immediate
        die dann auch unstrukturiertes Verlassen von Worten erlaubt, in denen
        Locale Variale deklariert  wurden:
                : probe local ABC| ...
                        ... IF ... [ 12 ] end-loc ;s ENDIF ... ;

        Notfalls kann der gesamte Local-Bereich freigegeben werden durch:
                tib @ s0 !

        Ein kleines Beispiel, das belegt, da die Localen Variablen auch zu
        recursivem Einsatz taugen:
                : fak local A|
                  local A -1 m+ 2dup -2 m+ d0< 0= IF recurse ENDIF local A d* ;
        Damit z.B.
                12. fak d.
        liefert 479001600.

n>r     ( nn n(n0).. n1 n0 -- nn ) bringt n0 Zellen zum Returnstack;
nr>     ( n0 -- n(n0).. n1)        holt sie zurck.

m>r     ( ptr n0 -- )   RP: ( nn -- nn n(n0)..n1 )
        bringt n0 Zellen aus dem 4th-Adressenbereich ab ptr in den Returnstack;
r>m     ( ptr n0 -- )   RP: ( nn n(n0)..n1 -- nn )
        legt n0 Zellen aus dem Returnstack an ptr+ im 4th-Adressenbereich ab.

dataspace (h) Variable
        Wenn hier ein Wert eingetragen wurde, der kleiner als der grtmgliche
        Datenbereich fr einen mit {w-save} oder {save} zu erzeugenden F6-Job
        ist, wird dieser fr die entspr. Angabe im Fileheader und spter zur
        Einrichtung des Jobs benutzt. Damit lassen sich, insbes. bei kleinen
        Programmen, Jobs erzeugen, die nur das fr sie ntige Minimum an Platz
        im Speicher belegen.
        {dataspace} wird vorzeichenlos ausgewertet, der Wert ist mit 65536
        vorgegeben, und bewirkt zunchst immer Eintragung des Maximalwertes.
        Jenen ermittelt das System mit
                here minus 72 $8000 or -
        Keinesfalls sollten weniger als 2000 Bytes vorgesehen werden.

ch-num  ( d.chan.id -- chan.no | -1 )
        liefert die F6-Kanalnummer zu einer bergebenen Kanal-id. Findet diese
        sich nur in {work}, oder gehrt sie zu keinem F6-Kanal, kommt -1 zurck.
work-num ( -- chan.no | -1 )
        liefert die F6-Kanalnummer des Kanals, der gerade {work}-Kanal ist.

 OPTIMIERUNG:
 Dazu sind die u.g. Operatoren "immediate", sie drfen darum nicht in den Listen
 von {case:} etc. aufgerufen werden. {lit} kommt dafr ohnehin nicht in Betracht
 und die anderen sollten darin ebensowenig Verwendung finden, da sie den jeweils
 ersten Returnstack-Posten betreffen, wo bei den Listenaufrufen sinnvolle Werte
 nicht zu erwarten sind.

lit     zwei aufeinanderfolgende einfache Integer-Literale werden durch Compi-
        lieren von {dlit} und den beiden Zahlenwerten zusamengefat.
>r      Ablage im Returnstack,
r>      bertrag vom Returnstack,
i r     beide funktional identisch, liefern in DO..LOOPs den Laufindex.


 GENDERT:

(find)  (h) als ursprngliche Vorgabe fr [find] ersetzt dessen Definition, und
        stellt so die Benennung nach dem f.i.g.-Modell wieder her. Es dient der
        Wortsuche innerhalb eines einzelnen Vocabulars.
[find]  (D)(h) bleibt als leeres deferred Wort erhalten, das in allen Varianten
        von {find} zuerst ausgefhrt wird, und damit Gelegenheit zu besonderen
        Aktionen einer Anwenderderfinition noch vor dem Systemaufruf bietet.
        Hier knnte z.B. die Wortsuche auf ein Menu-Vocabular beschrnkt und so
        eine besonders hohe Sicherheit gegen Fehlbedienung erreicht werden.
        Im Urzustand ist eine ungerade Adresse eingetragen, wodurch [find] bei
        minimal mglichem Zeitaufwand als inaktiv erkannt und bersprungen wird.

(update) auf 0 gesetzt sperrt {r/w} fr Schreiboperationen.
        {ernum} liefert dann ggf. auch den Fehlercode err.ef (-10).

w-save  (I) nun "immediate".

        N.b.: Der "immediate"-Status eines jeden Wortes lt sich umschalten:
                ' {name} nfa $40 toggle
        oder, z.B. mit Bitmuster-Flag, definiert setzen:
                :  >imm [compile] ' nfa
                   dup c@ $40 and rot = IF drop ELSE $40 toggle ENDIF ;
        daraus:
                : set-imm $40 >imm ;    ( use: SET-IMM {name} --
                : not-imm   0 >imm ;

l<i     ( -- dn )
        damit kann unmittelbar nach den folgenden Operationen fr weiterfhrende
        Berechnungen das berlauf-Flag als Wert =/= 0 gelesen werden:.
                * d2*
                + d+ q+ qm+
                - d- d+- q- q+-
                abs +- over-
                f>q f>d

[donext] (assembler) (-- ptr)
        ist die 4th-Adresse des Inneren Interpreters, 2 Bytes danach ist der
        Einsprung zum Ausfhren einer im [w]-Register befindlichen cfa (z.B.
        fr execute), weitere 2 Bytes danach wird auf den 16-Bit-Inhalt der
        cfa zugegriffen, und es folgt der Sprung an die mit diesem vorzeichen-
        behaftet zur Basisadresse [bp] addierten Ort in den auszufhrenden Code.
        Es gibt (nunmehr) im gesamten F6-Kern keinen direkten Sprung dorthin,
        die Adressierung erfolgt stets durch [nx] und ggf. den genannten Offset.
        Solange also diese Abstnde erhalten bleiben, kann der next-Einsprung
        an beliebiger Adresse stehen, d.h. fr Jobs z.B. auch umgesetzt werden.
        [bp] wird durch A6 reprsentiert, [nx] durch A3 und [w] ist A2, der
        Datenstack [sp] ist A5, [ip] ist A4, und der Returnstack [rp] bleibt A7.
        Diese Register, bedingt auch [up] in D7, mssen (normalerweise) unver-
        ndert erhalten bleiben: Sie drfen nur fr neue Tasks rsp. QDOS-Jobs
        neu besetzt werden. Mehr hierzu s. "f6asm_scr" und "f6task_scr".


 ENTFERNT

0drop   wurde mangels sinnvoller Anwendung gestrichen; je einmal in "fig_scr"
        und "forth_scr" aufgerufen, und gelegentlich ntzlich fr z.B.
                ernum 0drop IF message ENDIF
        Man kann es leicht ersetzen:
                -dup drop

 Da mit o.a. neuen Worten wieder einmal das Fassungsvermgen des GST-Assemblers
 an Labels berschritten wurde, muten weitere weniger nutzbringende Worte aus
 dem Kern entfernt werden:

(-ffind) Der Wortheader dieses Vorgabeaufrufs fr {-find} wurde entfernt.
        Seine cfa kann, z.B. zur Restituierung von {-find}, ermittelt werden:
                ' -find 4+ ' -find !
(#boot) ist fr selbststartende Programme nicht mehr erforderlich.
(fop)   (D) ersatzlos entfernt.
0in!    kann ersetzt werden durch
                in off
local   als Variablentyp und
loc:    deren Fehlen kaum ein schmerzlicher Verlust sein wird, da die Pseudo-
        {local}-Variablen sich nicht als sonderlich wertvoll erwiesen haben,
        dies umsomehr, nachdem neben o.a. Stackoperator nun auch "echte" und
        gnzlich problemlose Locale Variable zur Verfgung stehen.
local   auch das Vocabular wurde entfernt. Die vorrangige Suche nach einem
        Vocabular kann z.B. in {[find]} untergebracht werden.
2forth+ Gleichwertig ist
                ( d.memadr )   0 base+ d-   ( d.forthadr )
        oder, da headerlos vorhanden, notfalls nachzusetzen:
                create 2forth+ -2 allot ' 2base+ nfa even 2- @ ,
?found  ist in {if-found} und {if-nfound} enthalten. Diese reichen zusammen mit
        {+continue}, {ftest}, {-find} und {if-true} zum bedingten Compilieren
        oder fr sonstige Prfungen vollkommen aus.
<i      mu ggf. ersetzt werden durch
                l<i drop
        wie z.B. fr den Editor in "fig_scr" bei {JL}.
-drop   ersatzlos gestrichen
chk     Der zugrundeliegende Processorbefehl mag in speziellen Fllen bentigt
        werden, hat sich hier aber als vllig nutzlos und ineffizient erwiesen.
t-regs  (h) Auf die Registerablage der QDOS-Trap-Redirection wird nur selten
        zuzugreifen sein. Der ptr kann hilfsweise gelesen werden:
                ' open nfa even 2- @
<move   Die Varianten sind
move>   berflssig, und selbst
move    hat nur unwesentlich an Ausfhrungszeit eingespart.
cmove>  {cmove} arbeitet nicht-berschreibend, und {fill} dient dem Eintragen
        von Bitmustern. Die {cmove}-Varianten sind also berflssig. {<cmove}
        wurde dennoch beibehalten, da es nun einmal im Standard existiert...
save    wegen {w-save} berflssig.


 FEHLER korrigiert bei:

*/      (f) (f1 f2 f3 -- f4) f4:=f1*f2/f3
call    (q) (dA4..dD0 d.calladr -- dA4..dD0) Datenanordnung.
cmove   Transportrichtung bei 4th-Adressen ungleicher Vorzeichen.
(find)  (Sehr seltener Fehler im) Abbruchkriterium bei Vocabularende.
expect  und
query   bei Abbruch durch i/o-Fehler oder Erreichen der Eingabepuffergrenze
        trat ein Adressierungsfehler beim Restaurieren der i/o-Kanalnummern
        auf. Voller Eingabepuffer gilt nicht mehr als Fehler.


 SCREENFILE: U.a. mit einer Definition fr beliebig dimensionierbare Arrays.

 In "forth_scr" korrigiert rsp. neu:

heapmem ( dn -- ) gendert
        erwartet als doppelte Integer die wirklich geforderte Bereichsgre.
        Da der Speicher vom QDOS ohnehin nur in Achtergruppen zugeteilt wird,
        ist die Stufung nun 8, wonach maximal 512K reserviert werden knnen.

o-prt   enthielt das o.a. {0drop}, welches entsprechend ersetzt wurde.

turtle  bis zu 16 Krten knnen auf eigenen Bahnen bewegt werden.
#turtle (turtle) (-- nn) cons, enthlt die Krten-Nummer
penup
pendown berwachen beide (als einzige der turtle-Aufrufe) den Nummernbereich
        und justieren die Nummer ggf. auf einen Wert im Bereich 0 bis 15.
move    (turtle) (f1 --) hatte Fehler.
deg     (turtle) (f1 -- f2)
        neu: Umrechnung Bogenma nach Grad.
rad     (turtle) (f1 -- f2)
        neu: Umrechnung Grad nach Bogenma.

l-load  ohne Namen nach vollstndiger Aktivierung zeigt alle Kopfzeilen des
        library-file an, die eine mit l-load auffindbare Eintragung enthalten.
        Wird die Anzeige nicht mit ESC abgebrochen, mu der {screen}-Kanal
        u.u. durch gesonderten Aufruf geschlossen werden.

stack:  define: STACK: {name} abc...|abc...
        use:    n1...nn {name} nx...ny
        Definitionswort fr Stackoperatoren nach dem Verfahren von {stak}.

array   define:             n.dims size ARRAY {name}
        initiate: dim.n ... dim.2 dim.1   DIM {name}
        use:      dim.1 dim.2 ... dim.n       {name} -- d.memaddr
        Allgemeine Definition fr im freien Ram angeordnete Datenfelder:
                        2 32768  array  Bilder
                    6 1          dim    Bilder          ( 12 * Bildschirminhalt
                        3     4  array  doubles
                99 99 1          dim    doubles         ( 20000 doppelte integer

        Mit {dim} wird im Rahmen der festgelegten Anzahl und der Postengre
        jedes Array (neu) dimensioniert. War es bereits eingerichtet, werden
        seine Daten vorher aus dem Speicher entfernt. Der Speicherblock wird
        dem Array erst mit einem Aufruf des definierten {namen} zugewiesen.
        Als Schutzmanahme erhlt ein noch un-{dim}ensioniertes Array beim
        Aufruf einen Speicherblock von 16 Bytes zuzglich dem Produkt aus
        Dimensionenanzahl und Postengre, Indices =/= 0 werden abgewiesen.
        Fr das Produkt aller Dimensionen gilt als Maximum 65535, das Format
        der einzelnen Posten ist auf 65536 Bytes begrenzt (in welch letzterem
        Fall der Wert 0 anzugeben ist) und das Produkt aus Postengre und
        Dimensionen mu kleiner als 512K Bytes sein.
        Die Dimensionsgre zhlt ab Null.
        Die Anzahl Dimensionen und die Postengre zhlen ab Eins.
a'      (I) use: A' {name}      ( -- array-pfa )
        liefert den Datenptr in eine Array-Definition oder bricht mit dem Text
        "?not an array" ab; compiliert ggf. den ptr als Literal.
-array  ( dn -- array-pfa | 0 )
        ermittelt den Datenptr der mit einer Speicheradresse korrespondierenden
        Array-Definition. Gibt es diese nicht, kommt Null zurck.
dim     (I) use: ( dim.n ... dim.2 dim.1 )  DIM {name}  ( -- )
        dimensioniert ein Array und gibt zuvor ggf. einen schon bestehenden
        Speicherblock frei; in derselben Schreibweise auch compilierbar.
a'clr   (I) use: A'CLR {name}   ( -- )
        erwartet einen Array-Namen und lst den zugehrigen Speicherblock auf;
        er wird mit dem nchsten Aufruf von {name} leer wieder eingerichtet.
?arrays zeigt Namen und Dimensionierung aller Arrays an.

        Weitere Hinweise zu Definition und Anwendung in "forth_scr".


 * ++  1. 1.95 ++ v7.22 +++++++++++++

 SCREENFILE:
 U.a. mit TURTLE-Graphik im Stil des QL-Basic, und zwei Aufrufen zum Sichern und
 Laden assemblierter Blcke (auch fr einige Vorgngerversionen geeignet):

 Die turtle-Kommandos und -Variablen sind in "forth_scr" beschrieben:
penup pendown move moveto turn turnto arc-t x-cor y-cor angle pen

 Sichern und Laden compilierter 4th-Sequenzen:
c-save {file} {wort1} {wort2}
        Aufruf: C-SAVE {filename} anfang ende
        Sichert den compilierten Code ab {anfang} bis vor {ende}.
c-load {file}
        AUFRUF: C-LOAD {filename}
        Ldt den compilierten Code aus {filename}, fgt die gefundenen und im
        Bildschirm angezeigten Worte dem {current}-Vocabular hinzu.

                l-load c-load flp1_forth_scr
        spart Speicher und ldt nur C-LOAD, beide Worte werden geladen mit:
                l-load c-save flp1_forth_scr

 Auer der Zeitersparnis beim Compilieren scheint der Nutzen dieser Aufrufe zu-
 nchst ausgesprochen begrenzt, ist doch normalerweise die einzige Folge der
 zustzliche Speicherbedarf hierfr (520 Bytes). Ganz anders sieht es aber aus,
 wenn ein Hilfsprogramm einen Code erzeugt, in den es selbst nicht eingebaut
 ist, und dieser Code dann mit C-SAVE zum Nachladen separiert werden kann. Das
 wichtigste Beispiel hierzu bildet der Assembler. Zu beachten ist:
        1. Das erste und das letzte Wort dieses Blocks mssen zum selben Voca-
           bular gehren; ebenso das dem letzten zu sichernden folgende, da aus
           diesem das Ende des wirklichen letzten Wortes ermittelt wird. Dazu
           sind Kopf- und Schludresse erforderlich, die spteren {latest} und
           {here}, welche nur aus den Daten eines unmittelbar danach definierten
           Wortes zuverlssig und bei geringstem Platzbedarf zu gewinnen sind.
        2. Das Vocabular kann beliebig gewhlt werden, es mu zum Zeitpunkt des
           Sicherns rsp. Ladens lediglich zugleich auch {context} sein.
           Die Worte werden beim Laden dem {current}-Vocabular hinzugefgt.
           Das Vocabular mu dabei nicht dasselbe sein, wie beim Sichern.
        3. Alle Worte, auf die bei der Ausfhrung zugegriffen wird, mssen beim
           Laden an derselben Stelle stehen. Die Blcke knnen nur in ein System
           geholt werden, das ber exakt dieselben dort aufgerufenen Ausgangs-
           definitionen verfgt, wie beim Sichern. Blcke, die jeweils einzeln
           zum Kern hinzucompiliert wurden, lassen sich in beliebiger Reihenfol-
           ge einfgen. Auch die F6-Version mu dieselbe sein, da Unterschiede
           der Adressenlage im Kern von Version zu Version sehr wahrscheinlich
           sind. In der vorliegenden Form bricht {c-load} bei unterschiedlichen
           Versionsnummern mit der Fehlermeldung "? F6-Version" ab.
        4. Worte im Block, die in fremde Vocabulare hineincompiliert wurden,
           sind nach dem Laden von auerhalb des Blocks nicht mehr aufrufbar,
           sie erscheinen nicht in den Wortlisten der betr. Vocabulare.
        5. Innerhalb des Blocks drfen nur Worte aufgerufen werden, die schon
           vorher definiert wurden. Einzige Ausnahme sind Definitionen mittels
           im Block formulierter Definitionsworte, die einen {does>}-Teil ent-
           halten. C-LOAD ist dadurch im wesentlichen auf die Anwendung zusammen
           mit dem Assembler beschrnkt. {interpret} verfgt jedoch ber zwei
           vectorisierte (deferred) Aufrufe als Verankerung fr Ergnzungen,
           soda hier evtl. eine entsprechende Erweiterung mglich ist (s.u.).
        6. Zur mglichst vielseitigen Verwendung sind beide Worte "immediate".
           Sie lassen sich mit bereits vorgegebenen Namen compilieren, in Worte
           einbauen, die dann ihrerseits beim Aufruf die Namen erwarten, oder
           mit direkter Tastatureingabe aufrufen.
                : {name} ... [compile] c-save ..worte.. ;
           {name} empfngt dann die zugehrigen Namen aus dem Eingabestrom.
           Dagegen mit vorgegebenen Namen:
                : {name} ... c-save erstes letztes filename ..worte.. ;
        8. Der Header des erzeugten File darf auf keinen Fall verndert werden:
           Wo bei Job-Files die Zahl fr den Datenbereich steht, sind die Adres-
           sen fr die Vocabularverkettung, danach ggf. die F6-Versionsnummer,
           eingetragen. Manipulation dieser Angaben macht das File unbrauchbar!
           Solch ein File wird mit der Typen-Kennung 3 markiert.

 Zu 5.: Dies ist die hi-level-Definition von {interpret} aus dem Kern, wo an
        entsprechender Stelle die Sonderbehandlung eingesetzt werden kann:
        : interpret
           BEGIN -find
            IF [interpret] state@ 0= IF db-on IF [debug] ENDIF ENDIF
             state@ uc< IF [cpl] cfa , ELSE cfa execute ENDIF
            ELSE here [convert] ENDIF
            ?stack
           AGAIN ;
        {[interpret]} z.B. knnte bei erneutem Compilieren des zu sichernden
        Teils die Referenzen auf intern aufgerufene Worte des Blocks einsammeln.
        {c-save} htte sie dann zustzlich zum Code mitzusichern, und {c-load}
        diese dann beim Laden auf die genderte Adressenlage umzustellen. Was
        aber bei der Struktur des F6-Systems etliche Probleme aufwirft, weshalb
        eine solche Mglichkeit des Aufwandes wegen nicht vorgesehen wurde.

[interpret] (h)(D)(pfa countbyte -- pfa countbyte)
        Das Countbyte enthlt auerdem smudge- und precedence-Bit, letzteres
        ist die "immediate"-Makierung. Das hchstwerige Bit ist immer gesetzt.
[cpl]       (h)(D)(pfa -- pfa)
        Beide mssen die empfangenen Daten in gleichwertiger Form weitergeben.

 Ein Beispiel:
 Die Assemblerroutinen aus "f6task_scr" fr den F6-Tasker knnen mit {c-load}
 geladen werden, wodurch dann der Assembler nicht mehr vorhanden sein mu:
        c-save flp1_tasker_4th tasker tcb
 sichert zunchst aus einem regulr compilierten F6-Job die betr. Aufrufe.
    e$='l-load l-load c-load c-load flp1_tasker_4th l-load tcb flp1_f6task_scr'
    EX flp1_qf;e$
 ruft nun ein neues F6-System auf und ldt den gesamten Tasker ohne Assembler,
 wodurch an die 14K Bytes mehr an Platz fr andere Programmteile frei bleiben.


 * ++ 31.12.94 ++ v7.21 +++++++++++++

nderungen:

l-load  Mit Hilfe der weiter unten angegebenen neuen Aufrufe zum Datentransport
        wird bei auch der Vorgnger-Suchname im Returnstack gesichert, soda
        er bei geschachtelten Aufrufen erhalten bleibt. Damit erhht sich der
        Platzbdarf mit jeder Schachtelungsstufe um die jeweilige Namenslnge
        zuzglich 2 Bytes fr die Lngenangabe, ggf. geradzahlig aufgerundet.
        Bei durchschnittlicher Lnge von 20 Bytes fr Filenamen und 10 Bytes
        fr Suchnamen sowie 10 Bytes Daten fr den Aufruf selbst bietet der
        Returnstack damit noch Platz fr 25 Schachtelungsstufen; bei Maximal-
        lnge fr beide Namen bleiben es noch immer mindestens 12. Hinzuzurech-
        nen ist ggf. die Datenanzahl, die andere Ladeaufrufe zwischenspeichern:
        LOAD beansprucht 6 Bytes, S-LOAD 10 und Platz fr den Filenamen.

db-on   ist zunchst wirkungslos. Da der Speicher fr rein produktive Zwecke
        bentigt wurde, sind die (ca. 200 Bytes umfassenden ) Debugger-Routi-
        nen nach "forth_scr" ausgelagert worden, von wo sie unter dem Namen
        {debugger} geladen und in den Interpreter eingebaut werden knnen.
        An der Debugging-Ausfhrung hat sich nichts gendert, sie ist nun
        jedoch in weiten Grenzen auch vom Anwender modifizierbar.

(debug) (D)(h) (--)                     (neu)
        Zunchst inaktiv definierte Runtime zum Debugging. Wird vor das aus-
        zufhrende Wort compiliert und kann auch auf vllig andere Aktionen
        vectorisiert werden, als das in "forth_scr" angegebene Debugging.
        Die 'deferred'-Definition wurde vor allem deshalb gewhlt, weil sie ein
        zuverlssiges Hilfmittel zur Kontrolle des bergebenen Aufrufs auf die
        mgliche Ausfhrbarkeit ist, und auch Sicherheit gegen {forget} bietet,
        falls der eigentliche Aufruf damit gelscht worden sein sollte.

[debug] (D)(h) (--)                     (neu)
        Anweisung zum Einbau der Debugging-Runtime. Wird vom Interpreter vor
        dem Compileraufruf ausgefhrt, wenn {db-on} und {state} nicht Null
        sind. Ist ebenfalls auf beliebige andere Aktionen vectorisierbar.

$8000   ist die erste (niedrigste) Forth-Adresse. Sie wird von der 'deferred'-
        Runtime und anderen Code-ausfhrenden Teilen abgewiesen. An dieser
        Stelle steht ein 'no op'-Sprung, soda sie auch gegen versehentlichen
        Aufruf, z.B. nach Einbau durch den Compiler, abgesichert ist.

where   wurde zur Platzersparnis aus dem Standard-Aufbau fr den Editor her-
        ausgenommen. Es kann aus "forth_scr" nachgeladen werden. Ersatzweise:
                b/scr /mod . . .        <enter>
        womit unmittelbar nach Fehlerabbruch die {scr}-Nummer sowie Zeile und
        Spalte darin (alles ab 0 zhlend) der Fehlerstelle ausgegeben werden.
                edif drop -print
        oder nach {l-load} und {s-load}
                (dir) -print
        gibt den zugehrigen Screenfile-Namen an.

safety  (r) wurde durch den Hilfs-Job zur Adressierungsberwachung entbehrlich,
        da dieser nun die gesamte (ergnzend zur 'address error exception trap'
        des Processors) programmierte Kontrolle bernimmt, und ist darum nicht
        mehr vorhanden.

basic   arbeitet unabhngig vom MEM-Device aus "dvs_byt". Es mu dafr nicht
        mehr geladen werden. Dasselbe gilt fr die vordefinierten Worte, die
        im Basic resident definierte Aufrufe aktivieren:
                lngbad  cache-on  cache-off
        "dvs_byt" ist nur noch fr {>fount} erforderlich, und die vier Zeichen-
        stze, die sich damit den Fensterkanlen zuweisen lassen.

basic   (h)(ptr -- flg)
        Liefert nur einen Fehlercode, falls der betr. Name unbekannt ist. Wenn
        er eine parameterlos im (ersten) Basic aufrufbare residente Procedur
        bezeichnet, wird diese ausgefhrt, sonst bleibt {basic} ohne Aktion.
        Der Anwender mu darauf achten, da die Aufrufe bei gesperrten Inter-
        rupts ausfhrbar sind, da programmierte Kontrolle nicht mglich ist.
        flg:=0 wird angegeben, wenn der betr. Name existiert.
        Damit lassen sich, entsprechende Sachkenntnis vorausgesetzt, z.B. Vari-
        able aus dem Basic lesen und (in Grenzen) auch ndern, was weitreichende
        Kommunikationsmglichkeiten zwischen Basic und F6-Jobs sowie diesen un-
        tereinander erffnet. Mit den folgenden {qdos}-Worten sind dann die
        Daten (aus) der zugehrigen 'name table' lesbar:
d1l@    Aufrufadresse, Variablenptr oder Basic-Zeile.
        Z.B. den Inhalt einer im Basic definierten Variablen 'adr' gibt aus:
                forth hidden qdos also forth
                " adr" basic dup ?error d1l@ 2dup 2 m+ 2@l 2swap @l \.
        und ein neuer fp-Wert aus dem Stack wird an sie bergeben:
                ( fp-zahl ) " adr" basic dup ?error d1l@ 2>rr !l 2r> 2 m+ 2!
a1w@    im niederwertigen Byte die Verwendungscodierung
a2w@    im hherwertigen Byte die Typencodierng.
a1l@    Ptr zur 'name table', wo die beschreibenden Daten verzeichnet sind.
a2l@    disp vom Forth-Basisptr. zur Basic-Datenreferenz.
        Die wirkliche Referenzadresse erhlt man dann mit { a2l@ 2base+ }.


 Optimierung:

 Compiler:
 Durch nderungen bei {find} konnte die Compilezeit um ca 25% verringert werden.

 Programmausfhrung:

 Die Datenanordnung im Stack ist von entscheidender Bedeutung fr die Ausfh-
 rungszeit. Darum lohnt es sich immer, deren bergabe besondere Sorgfalt zu
 widmen, ebenso, wie dann der Wahl der bestgeeigeten Stackoperatoren.
 Obwohl eine groe Zahl Logik-Operatoren angegeben ist, sind diese nicht immer
 die beste Wahl, da ihre Realisierung zusammen mit der Flagerzeugung umstnd-
 licher ausfallen mute, als die zugrundeliegende elementare Rechenoperation.
 Der Datenvergleich mit {=} oder {=/=} ist solch ein Fall. Die Subtraktion ist
 stets schneller und kann, insbes. zusammen mit der optimierenden Funktion von
 {IF}, vorteilhaft stattdessen benutzt werden. Weil {IF} jeden Wert =/= 0 als
 'true'-Flag auswertet, gengt das {-} immer dann, wenn ein {IF}-Teil bei Un-
 gleichheit durchlaufen werden soll. {0=} im Anschlu wird von {IF} optimiert,
 soda im F6 auch Gleichheit auf diese Weise erfat werden kann.

 Grundstzlich reichen {u<}, {0<} und {0=} zur Vergleichsauswertung aus; wren
 aber nur diese drei vorhanden, ginge das zulasten der Ausfhrungszeit. Doch es
 ist unntz, fr jeden Einzelfall einen eigenen Operator vorzusehen. Da in sehr
 vielen Fllen ein bedingter Sprung folgt, bietet sich ergnzend die Variation
 der Sprungbedingungen an, was im F6 mit den verschiedenen Sprung-Worten aus dem
 {hidden}-Vocabular verwirklicht wurde. Damit die Texte standardkonform hinge-
 schrieben und dennoch die zustzlichen bedingten Sprnge des F6 genutzt werden
 knnen, wurde die Optimierung von {IF} bei vorangestellten Flagoperatoren {0<},
 {0>} und {0=} eingefhrt. Die modifizierten Sprnge werden hiermit in derselben
 Zeit ausgefhrt und mit demselben Speicherbedarf compiliert, wie {IF} allein.
 Dasselbe gilt fr {UNTIL} und {WHILE}.

 {+IF} und {0IF} sind nun berflssig und nicht mehr im Kern enthalten.
0IF wird getrennt als { 0= IF } hingeschrieben, und
+IF ersetzt man durch { 0< 0= IF }.

 Die Worte     compilieren kompakt als Sprung hinter ELSE (oder ENDIF)
 0= IF           -branch                  =/= Null
 0> IF           0-branch                 kleiner oder gleich Null
 0< 0= IF        0<branch                 kleiner Null
 0< IF           +branch                  grer oder gleich Null
 0> 0= IF        0>branch                 grer Null
    und entsprechend:
 {bedingung} UNTIL                               und
 {bedingung} WHILE ..            REPEAT          sowie
 {bedingung} WHILE .. {bedingung} UNTIL          als F6-spezifische Ergnzung.

 Mitunter kann es erforderlich werden, die IF-Optimierung stillzulegen. Das
 betrifft z.B. unstrukturierte Einsprnge in den Code an Stellen innerhalb der
 normalerweise durch Optimierung zusammengefaten Worte. Fr ENDIF und CASE:,
 RANGE:, ASSOCIATIVE: werden entsprechende Vorkehrungen automatisch getroffen,
 die anderen Strukturworte compilieren eigene Codes und trennen sich dadurch
 selbst; "handgestrickte" Strukturen kann der Compiler aber nicht schtzen.
 Dafr ist ein Wort vorhanden, das ggf. vor ein IF oder UNTIL zu schreiben ist,
 oder in eine Compiler-Anweisung einzubauen, wie z.B. bei ENTRY in "forth_scr":

if-off  (I)(--)
        Schaltet die Optimierung fr das nchste IF, UNTIL oder WHILE ab.
          .. 0branch [ here 0 , ] BEGIN .. 0< [ rot >resolve ] if-off 0= IF ..
        In diesem Beispiel wird {0=} mit {IF} zusammengefat, das {0<} davor
        bleibt stehen. Ohne {if-off} wrde auch dieses Wort in den Code fr
        {IF} eingearbeitet und {0branch} direkt in den Code nach IF fhren.

 Neu:

 'Trickprogrammiererei' drfte zumeist nur ein Symptom der Dummheit sein, und,
 wo eine Aufgabe sich angeblich strukturiert nicht lsen lt, ist der Ansatz
 falsch, oder die Aufgabenstellung wurde nicht begriffene. Was nicht heien
 soll, da sie unbedingt und in sturem Purismus stets in strukturierter Form
 bewltigt werden mu. Gerade z.B. das bedingte Verlassen eines Aufrufs, eine
 im Sinne strenger Strukturiertheit verwerfliche Tat, erlaubt es nicht nur,
 Proceduren bersichtlich hinzuschreiben, sie werden automatisch dabei auch
 kurz und effizient programmiert. Drum:

-exit   (flg --)                entspricht: .. ( flg ) IF ;s ENDIF ..
        fr durch flg =/= 0 bedingten vorzeitigen Abbruch eines Wortes.
 IF .. ;S ENDIF ..   ;
        anstelle von
 IF .. ELSE .. ENDIF ;
        spart ebenfalls etwas Speicherplatz und Ausfhrungszeit. Wie auch bei
        {-exit} lohnt sich diese Abkrzung insbs. bei kurzen Aufrufen, oder
        wenn sich damit verwickelte Schachtelungen auflsen lassen.

#case   (-- nn) liefert den Index, mit dem das Wort, das {#case} enthlt, in
        einer {case:}-Liste ermittelt und aufgerufen wurde, wenn es das erste
        Wort in dieser Definition ist. Ansonsten ist der Wert (nn) ungewi.

edif    (e) (-- ptr cn)
        liefert abhngig von {offset} Kanalnummer ( cn ) und 4th-Adresse ( ptr )
        des Namen zum gerade editierten File, rsp. die Daten zu {screen}, wenn
        kein File editiert wird und (offset) Null ist. {screen} und {(screen)}
        gelten auch nach Aufruf von {dr0}, {file} und {(file)} nach {dr1}.

dr?     ( -- f)
        liefert 0 wenn {offset} < 16384 ist (z.B. nach {dr0}), sonst 1

 Datentransport zwischen Speicher und Returnstack:
        Die geradzahlig aufgerundete Anzahl Bytes wird geholt, die genaue Anzahl
        abgelegt. Bei berschreiten der Maximalzahl von 512 Bytes oder negativer
        Zahl brechen die Aufrufe ohne Aktion oder Fehlermeldung ab.

m>r     (ptr cn --)
        holt von 4th-Adresse ( ptr ) die Anzahl ( cn ) Bytes zum Returnstack.
r>m     (ptr cn --)
        legt die Anzahl ( cn ) Bytes vom Returnstack an 4th-Adresse ( ptr ) ab.


 * ++ 28.11.94 ++ v7.15 +++++++++++++

 Ab dieser Version bernimmt ein Secundr-Job die <break>-Abfrage, die nun vom
 Programmverlauf vllig unabhngig und immer aktiv ist, selbst, wenn sich das
 Programm irgendwo in einer Endlos-Schleife aufhlt, auf die normalerweise kein
 Zugriff mehr mglich ist. Auerdem lie sich ein Teil der zustzlichen Adressie-
 rungs-Sicherheit dorthin verlagern. Erfolg ist die um bis zu 45% gesteigerte
 Ausfhrungsgeschwindigkeit trotz gegenber den Vorgngerversionen erheblich er-
 weiterter Absicherung und stndiger Abbruch-Abfrage. Die bisher sehr vorsichtig
 eingeschtzte Geschwindigkeit liegt nun bei etwa dem Vierfachen des C1-Forth.
 So kann sich das F6 mittlerweile auch mit den schnelleren Systemen messen, ist
 dabei aber von ungleich hherer Betriebssicherheit, vom entschieden greren
 Leistungsumfang ganz abgesehen.

 Alle F6-Jobs werden unabhngig voneinander berwacht und der Abbruch ist mit
 jeweils frei whlbarer Testencodierung gesondert auslsbar.
 Weil die berwachung durch einen Job stattfindet, zudem, um das Gesamtsystem
 mglichst wenig zu belasten, mit geringster Prioritt, kann es einen Moment
 dauern, bis die <break>-Anforderung erkannt und die Aktion ausgelst wird.

 Erste Versuche in Gestalt Compilierens einiger grerer Programme haben neben
 den Standardsystemen die Verwendbarkeit selbst mit den qxl-Produkten (Version
 2.16 und 2.31) besttigt, doch ist dies mit endgltiger Sicherheit noch nicht
 zugrundezulegen.

 nderungen:

 Die F6 Versionsnummer allein kann als ASCII-String gelesen werden
                2 code+ 2@l
 oder ausgegeben
                2 code+ 4 type-l

 Bislang namenlos und nicht programmiert nutzbar waren die user-Variablen, die
 das befristete Compilieren mittels {|} aus direkter Eingabe untersttzen:

tail    (-- ptr)
                erhlt durch den ersten {|} den Wert aus {last}, welches mit dem
                abschlieenden {|} hieraus restauriert wird.
head    (-- ptr)        und     head 2-  (-- ptr) fr den Langwort-Wert
                erhlt durch den ersten {|} den Wert aus {dp}, der abschlieende
                {|} restauriert {dp} hieraus.

|       (--)    wurde bereits beschrieben, hier noch der Hinweis, da {state}
                dann der besondere Wert $ffc0 zugewiesen wird. Dadurch werden
                besondere Aktionen ausgelst, die den Eingabe- vom regulren
                Compile-Zustand unterscheiden, und den gemischten Gebrauch mit
                den Compile- rsp. Interpret-Klammern, {]} und {[}, unterbinden.
                Genaueres ist dem Assemblertext zu entnehmen; die Versionen sind
                unverndert - abweichend wird {head} mit <uword> adressiert.

 Neue Worte sind:

btst    (dn1 n2 -- f)           tf wenn Bit n2 in dn1 gesetzt ist.
bset    (dn1 n2 --)             Bit n2 in dn1 setzen.
bclr    (dn1 n2 --)             Bit n2 in dn1 lschen.

f>q     (fn1     -- qn2)        Fliekommazahl in quad Integer umwandeln.

        Fr quad Integer zur Datenablage/-Gewinnung:
4@      (ptr -- qn1)            vier Zellen von (auch ungerader) 4th-Adresse
4@l     (dadr -- qn1)           vier Zellen von wirklicher Adresse lesen
4!      (qn1 ptr --)            vier Zellen an (auch ungerade) 4th-Adresse
4!l     (qn1 dadr --)           vier Zellen an wirklicher Adresse ablegen

abort"  wurde gendert. Dieses Wort steht nun auf derselben Reinitiierungsstufe
        wie {quit}, das von {(abort")} aufgerufen wird; im Gegensatz zu {abort},
        das den Datenstack erneuert und dann {(abort)} ausfhrt, vordefiniert
        mit weitgehender Reinitiierung des Systems.

,       as Compile-Komma kann auch an ungerader Adresse angesetzt werden.

perform (ptr -- (action)        79-Standard-Wort, fhrt aus: @ cfa execute
        zur Erleichterung bei der bernahme anderer Programme eingerichtet.
        Kann zusammen mit einer einfachen Variablen auch die {deferred} Worte
        ersetzen, wenn deren ausfhrliche Sicherheitsmanahmen unntig sind.
        Die Ausfhrung ist dann u.U. wesentlich schneller.

 Runtime-Executives fr bedingte Sprnge:
0+branch (h)(flg --)    Sprung bei positivem Flagwert oder Null.
0>branch (h)(flg --)    Sprung bei Flagwert grer Null.
0-branch (h)(flg --)    Sprung bei negativem Flagwert oder Null.


 ENTER BEGIN .. ENTRY .. { .. WHILE .. } .. 0= UNTIL  oder .. UNTIL
enter   und
entry   knnen von "forth_scr" dazugeladen werden. Sie bieten eine Alternative
        zur blichen begin..while..until-Konstruktion, die mit einem gewissen
        Ausfhrungszeit-Gewinn verbunden ist, weil der immere bedingte Sprung
        entfllt: Bei genauerem Hinsehen fllt auf, da nur beim Einsprung in
        die standardmige Schleife der unbedingte Teil zuerst ausgefhrt werden
        mu, und da danach eine Struktur durchlaufen wird, die der Schleife
        BEGIN .. 0= UNTIL entspricht. Genau dies ermglicht die Kombination von
        ENTER BEGIN und ENTRY:
                BEGIN ..unbedingt.. WHILE ..bedingt.. REPEAT
        wird bei identischer Programmausfhrung ersetzt durch
                ENTER BEGIN ..bedingt.. ENTRY ..unbedingt.. 0= UNTIL

?1branch (h)(n1 n2 -- | n1)
        Runtime-Wort fr eine weitere IF-Variante:
case?   (n1 n2 -- | n1)
        Zustzlich zu den Listen-Konstrukten {case:} etc. ein Hilfsmittel fr
        einfache Fallunterscheidungen, das nach Art der {if}-Varianten anzu-
        wenden ist: {case?} compiliert den Vergleich zweier Zahlen miteinander,
        der bei Gleichheit beide vom Stack nimmt und in die unmittelbar folgen-
        den Worte bis zum nchsten ELSE oder ENDIF fhrt. Bei fehlgeschlagenem
        Vergleich bleibt die (als erste bergebene) Vergeichszahl im Stack und
        nach einem ELSE oder ENDIF knnen weitere {case?}-s folgen. Jedes ein-
        zelne {case?} mu mit einem ENDIF abgeschlossen werden; Schachtelung
        und ELSE-Teile sind in derselben Weise zulssig, wie bei {if}. Fr den
        Fall, da kein Vergleich Erfolg hatte, kann in einer geschachtelten
        Folge dem letzten ELSE noch eine abschlieende Aktion folgen. Auf jeden
        Fall ist am Schlu die verbliebene Vergleichszahl vom Stack zu nehmen:
                n1  n2.erste.auswahl  CASE? ..1st-case.. ELSE ..
                    n2.zweite.auswahl CASE? ..2nd-case.. ELSE ..
                                ...
                    n2.letzte.auswahl CASE? ..nth-case.. ELSE ..
                    ausfallaktion drop ENDIF .. ENDIF .. ENDIF


l-load  aus "forth_scr" wird in seinen Suchfunktionen mit Hilfe dreier Text-
        variabler (variable Byte-Datenfelder) gesteuert:
(boot)  liefert bei fehlender oder unbrauchbarer Angabe fr den Filenamen den
        Text fr einen erneuten Leseversuch. Danach bricht der Aufruf ggf. ab.
(dir)   erhlt den erfolgreich zum ffnen benutzten Filenamen zugewiesen.
l-word  nimmt den jeweils jngsten Suchnamen auf.

-lword  {name}
        liefert tf, wenn der angegebene gleich dem jngsten Suchnamen ist.


 Da der GST-Assembler mit dem F6-Quelltext an der Grenze seiner Kapzitt ange-
 langt ist und aufgrund zuvieler Labels Fehler produziert, wurden zugunsten der
 o.a. nicht so einfach als Hi-Level-Worte nachsetzbaren Definitionen folgende
 Namen aus dem {hidden}-Vocabular gestrichen, die nur runtimes bezeichnen und
 auer der Namensausgabe beim debugging keine weitere Verwendung haben:
        (save)  (d.r)   (is)
        (cfa@)  (cfa,)  (csel)  (case)
        (asv@)  (asv,)  (asvl)  (asvr)  (range)
 sowie die inzwischen berflssigen
        is-in   is-out  is-work is-io   is-screen is-file  move>  <move
 und das in spteren Standards enthaltene Wort
        exit
 welches zur Ausfhrung ohne Laufzeitverlust nachgetragen werden kann
        : exit compile ;s ;   immediate
 und nur ein geschwtziger Ersatz fr das direkt hingeschriebene {;s} ist.

 Sowie die (nicht standardmigen) Forth-Worte
        #chan   report  in><out  0if  +if  move
 die vor allem des relativ seltenen Gebrauchs wegen aus dem Kern nach "forth_scr"
 ausgelagert wurden. Und schlielich das f.i.g.-Editor-Wort {-text}, das mit iden-
 tischer Aktion als Forth-Wort {w=} vorhanden ist. Wird es fr fremde Quelltexte
 bentigt, lt es sich mit gleicher Ausfhrungsgeschwindigkeit leicht nachsetzen:
        editor definitions forth
        create -text -2 allot ' w= 2- count-w , 2@ , , smudge

 Die Alternative der Aufteilung in mehrere Teiltexte, der reine Codeteil am
 Anfang bte sich dafr an, wurde wegen der vielen bergreifenden Labels und
 der lstigen Procedur zum Erzeugen des vollstndigen Programms verworfen.


 * ++ 18.11.94 ++ v7.14 +++++++++++++

 Auer der Reihe hier ein ganz simpler kleiner De-Compiler:
        : nxid. count-w dup $. 2+ nfa id. space ;
        : see [compile] ' BEGIN nxid. key 27 = UNTIL drop ;
 der aufgerufen wird
        see {wortname}
 und mit jeder Tastenbettigung einen Wortnamen der untersuchten Definition
 hinschreibt, und den eigentlichen Inhalt der gelesenen Zelle. Verlassen wird
 das Wort nur durch die Escape-Taste.
 Dabei gibt es allerdings noch keine Erkennung der besonderen 4th-Worte wie
 {literal}, wo z.B. die folgende Zelle einen Zahlenwert enthlt, nicht eine
 cfa; oder {branch}, wo die folgende Zelle die relative Sprungdistanz angibt.
 Entsprechende Erweiterungen sind leicht mglich, bleiben aber dem Anwender
 berlassen.

 Die in dem nicht ber 4th-Adressen erreichbaren Teil liegenden Primitive-
 Aufrufe umfassen mittlerweile gut 8K, wodurch trotz zahlreicher Ergnzungen
 der fr Programme und Daten nutzbare Bereich auf rund 45K angewachsen ist.
 Am Rande hat sich dadurch auch eine Steigerung der Ausfhrungsgeschwindigkeit
 ergeben, die abhngig vom Systemzustand bis zu 45% betrgt. Nur in extrem un-
 gnstigen Fllem und bei zugleich aktiver Abbruchtasten-Abfrage fllt sie
 in etwa auf das bei Qliberator-Programmen Erreichbare ab. Das Compilieren geht
 sehr viel schneller vonstatten, als das Laden gleichwertiger Basic-Programme.

 Neben geringfgigen Anpassungen an die Weichware zur QXL-Karte gibt es ein
 paar weitere nderungen/Ergnzungen:

message { 16 message } gibt einen Text mit der F6-Version aus.

break   ist eine Variable, an die der Code einer Taste bergeben werden kann,
        bei deren Bettigung ein evtl. gerade in Ausfhrung begriffenes Wort
        abgebrochen wird. Zusammen mit ALT wird der Warmstart ausglst, sonst
        bergang nach {quit}. Das System fhrt die Abfrage immer nach der Rck-
        kehr aus einem 4th-Wort durch. Endlosschleifen, die in reinen Codeteilen
        entstanden sind, knnen darum also nicht unterbrochen werden.
        Soll die {break}-Abfrage stillgelegt werden, bergibt man den Wert -1
        an die Variable. Zur Untersttzung ist eine Constante definiert:
never   (-- wf)
        wf, im F6-Slang als "wrong flag" bezeichnet, hat den Wert -1.
                break never
        legt z.B. die {break}-Abfrage still - und beschleunigt den Programm-
        ablauf erheblich. Vorgabe ist die Taste  CTR/a, einstellbar mit
                break on

safety  ist eine weitere Variable zum Programmablauf. Ist sie positiv und nicht
        Null, so werden nach jeden 4th-Wort die Register des virtuellen 4th-
        Processors auf Geradzahligkeit geprft und ggf. der Warmstart ausgelst.
        Ein hierdurch abgefangener Fehler ist daran Erkennbar, da das System
        nur die Fehlermeldung gibt, nicht aber die Registerwerte anzeigt, wie
        das beim Abbruch durch die Exception-Trap des Processors geschieht.

        Diese Kontrolle kostet etwa 1/8 der Zeit der {break}-Abfrage. Sie wurde
        vor allem fr die qxl-Systeme eingerichtet, da der Processor dort nur
        beim Sprung auf eine ungerade Code-Adresse die entsprechende Trap aus-
        lst, und so nicht mehr alle im F6 als solche geltenden Adressierungs-
        fehler erkannt werden. In den Standard-QL-Systemen ist diese zustzliche
        Sicherung von untergeordnetem Nutzen, soda es sich dort empfiehlt, sie
        stillzulegen:
                safety off
        wonach die {break}-Abfrage noch einstellbar bleibt, oder
                safety never
        welches auch die {break}-Abfrage stillegt, unabhngig von der Codierung
        in {break}. Der Zustand {off} ist Vorgabe beim Programmstart.
        Der Unterschied in der Ausfhrungszeit liegt im Extremfall (alles frei-
        gegeben und aktiv oder alles gesperrt) bei 1:9 (!).

t-regs  (-- disp)  (im hidden-Vocabular)
        ist eine Constante, die auf die Adresse weist, an der der Inhalt der
        Processorregister abgelegt wird, wenn ein Adressierungsfehler erkannt
        wurde. Der Ablagebereich liegt auerhalb der 4th-Adressen und kann
        mit seiner wirklichen Speicheradresse z.B. ermittelt werden:
                t-regs code+
        {ldump} aus "forth_scr" ist dann eine Mglichkeit, die Daten anzuzeigen.

empty   lscht alle Worte, die nach der in {fence} stehenden Adresse
        compiliert wurden (danach ist nun auch der Aufruf von {cold} sicher).

forget  Ausfhrung allgemein sicherer und im Zusammenhang mit {safe!} treten
        die Fehler von {cold} nicht mehr auf (Verlust des Dictionary).

safe!   sichert den aktuellen Wortschatz gegen {forget} und bereitet das System
        fr die Aufrufe {empty} und {cold} mit den entsprechenden Grenzen vor.
        Um die durch das f.i.g.-Modell bedingte Unsicherheit des {cold}-Aufrufs
        in Fllen unvollstndig vorbereiteter Systemdaten zu vermeiden, insbes.
        nach Umstellung des mittels {fence} geschtzten Bereichs, ruft man auf:
                ' {wort} lfa fence ! empty
        oder unmittelbar nach Compilieren des letzten zu schtzenden Wortes nur
                safe!

!a @a   Daten an gerade Adresse ablegen/Lesen von gerader Adresse
2!a 2@a dasselbe fr doppelte Posten (32-Bit, Langworte)
+!a     Addition in den Speicher (auch fr f.p.-Zahlen)
        Die Aufrufe sind immer dann vorteilhaft, wenn die jeweilige Adresse
        mit Sicherheit nicht ungerade sein kann, und auch Fehler bei der
        Tastatureingabe diesbezglich auszuschlieen sind. Z.B.
                #36 base !a
        oder
                out @a
        Da hier der Datentransport in Wort- rsp. Langwortposten erfolgt, ergibt
        sich ein Laufzeitvorteil von ca. 20% (bis 60%) gegenber den byteweise
        organisierten Standard-Aufrufen des Systems.

.(r)    (n1 n2 -- n1)
        Hiermit kann auch Text formatiert ausgegeben werden (s. "forth_txt").
        n1 ist Zhler z.B. einer Stringausgabe, die rechtsbndig ins Bild (oder
        zu Papier) gebracht werden soll, und n2 die verfgbare Feldbreite. Dann
        fllt der Aufruf eine Zeile von links an mit den in (r) als ASCII-Code
        angegebenen Zeichen, die z.B. auch fr {.r} benutzt werden, so auf, da
        ein String der Lnge n1 rechtsbndig in das Feld der Breite n2 gesetzt
        wird:
           | cr date$ 30 .(r) type cr \1000,01 f>$ 27 .(r) type space ." DM" |
        schreibt am 1.12.1994 abends um Acht Uhr:
                  1994 Dec 01 20:00:00
                            1000.01 DM

a>h     (c1 -- c2) Umwandlung ASCII-Zeichen nach sedecimaler Ziffer.
h>a     (c1 -- c2) Umwandlung sedecimaler Ziffer anch ASCII-Zeichen.

skip    (ptr1 n1 c1 -- ptr2 n2)
        liefert ptr2 auf den n2 Zeichen langen String, der ab der ersten im
        Code von c1 abweichenden Position verbleibt. Bis dahin im String ent-
        haltene (Steuer-)Codes < 32 werden bersprungen.

scan    (ptr1 n1 c1 -- ptr2 n2)
        liefert ptr2 auf den n2 Zeichen langen String ab der ersten Position,
        an der der Zeichencode c1 gefunden wurde.

 * Vierfachgenaue Integer-Arithmetik:
        Eine Gruppe Operatoren fr vorzeichenbehaftete 64-Bit-Zahlen, hier mit
        "quad" abgekrzt, ist hinzugekommen (doppeltgenaue mit "double"). Dies
        ermglicht schnelle Rechenoperationen im Bereich ca +/- 10^18.

q+      (qn1 qn2 -- qn3)        Addition
q-      (qn1 qn2 -- qn3)        Subtraktion
qminus  (qn1     -- qn2)        Negation
qabs    (qn1     -- +qn2)       positiver Betrag einer quad Integer
qm+     (qn1 n2  -- qn3)        vorzeichen-richtige Addition
                                einer einfachen zu einer quad Integer.
q+-     (qn1 n2 -- qn3)         qn3:=qn1*sgn(n2) : Vorzeichen einer einfachen
                                auf die darunterliegende quad Integer anwenden.
qm/mod  (qn1 dn2 -- qrm dqt)    Division quad durch double mit quad Rest
                                und double Quotienten.
uq/mod  (+qn1 dn2 -- drm dqt)   quad durch double nach double Rest und Quotient.

q>f     (qn1     -- fn2)        quad Integer in Fliekomma-Zahl umwandeln.
d>q     (dn1     -- qn2)        double vorzeichenerweitert in quad umwandeln.

        Mit vierfachgenauem Zwischenergebnis rechnet der Scalierungsoperator
udm/mod (dn1 dn2 dn3 -- drm dqt) Multiplikation dn1 mit dn2 und Division des
                                quad Produkts durch dn2 nach double Rest & Quot.

        Ein "Abfallprodukt" der quad-Division ist
d/      (dn1 dn2 -- dqt)        Division zweier doubles mit double Quotient

        Zur Ausgabe der quad-Zahlen knnen die notwendigen Operatoren aus
        "forth_scr" dazugeladen werden:
 <q# q# q#s q#> q. uq.           entsprechend den Standardoperationen.
 uq# q#                          stellen einen zu {type} passenden String bereit.

 Die zugehrigen Speicheroperationen lassen sich z.B. mit den doppeltgenauen
 Operatoren definieren:
        : 4@l  2dup 4 m+ 2@l 2swap 2@l ;        : 4!l  2>rr 2!l 2r> 4 m+ 2!l ;
        : 4@   2base+ 4@l ;                     : 4!   2base+ 4!l ;


        Fr die Adressierbarkeit aus mit dem f6-Tasker gebildeten 4th-tasks,
        die einzelne 4th-Worte unabhngig als QDOS-Jobs ausfhren, wurden
        einige Systemadressen auf 32-Bit-Format umgestellt:
u0
s0
r0
dp
hld
        lassen sich mit Abstand -2 als doppeltgenaue Werte lesen:
                dp 2- 2@
pad
hold
<#
#
#>
        arbeiten intern mit doppeltgenauen Adressen


[dojump] (a) ist die cfa fr auerhalb des 4th-Adressenbereichs liegende
        primitives. Damit kann fr Synonym-Definitionen kontrolliert werden,
        ob der direkte Sprung in eine ausfhrbare Routine mglich ist. Die
        Codeadresse eines lang adressierten Primitive-Aufrufs erhlt man mit
                ' {name} 2@ 2base+
        Die unten angegebene Sequenz hinterlt tf (1), wenn das untersuchte
        Wort eine solche Definition ist. Dann enthlt die auf die cfa folgende
        doppelte Speicherzelle die zur 4th-Basisadresse relative Adresse
        der betr. Routine und kann zur Bildung eines Synonyms ohne Verlust
        an Ausfhrungszeit benutzt werden.
        Dazu ist aber u.U. immernoch genaue Kenntnis des Worttyps erforderlich.
        Denn nur, falls der Vergleich mit [dojump] oder des cfa-Inhalts mit der
        pfa desselben Wortes Gleichheit ergibt, ist das untersuchte Wort mit
        Sicherheit eine primitive-Definition.

            : alias:            ( use: ALIAS: {neuername} {altername}
              ?exec             ( Abbruch, wenn im Compile-Betrieb aufgerufen
              create            ( wortheader anlegen
              -2 allot          ( primitive standard-cfa entfernen
              [compile] '       ( pfa des zu ersetzenden wortes holen
              dup cfa @ also assembler [dojump] = ( cfa-typenvergleich
              IF [dojump] ,  previous 2@ ,        ( worttyp und langen sprung
              ELSE              ( NUR wenn der Worttyp bekannt ist, oder
               dup              ( zustzliche Prfung vorbereiten
               cfa @            ( sprung auf standard primitive
               dup rot - 3 ?error ( unbekannten Worttypen abfangen
              ENDIF ,           ( compilieren
              smudge ;          ( und aufrufbar machen.

        Damit definiert man z.B.:
              also forth definitions fp also
              alias: fswap swap
              previous previous
        und kann nun mit {fswap} im forth-vocabular auf das fp-wort swap
        zugreifen, welches zwei dreiergruppen datenposten im stack vertauscht.

error
warm
cold
        kehren auch aus Aufrufen richtig zurck, bei denen der Fehler im
        supervisor-Mode des Processors ausgelst wurde.

fopen   Um Konflikte mit dem Pointer-IF zu vermeiden, rufen alle Worte dieser
        Gruppe bei erfolgreich geffnetem Kanal auch noch { 0 paper } auf.
        Ein dabei evtl. erzeugter Fehler ndert den Rckgabecode nicht, bei
        Filekanlen wird aber {ernum} nicht mehr null sein. Zuverlssige Aus-
        wertung erlaubt also nur der vom Aufruf zum Stack gelieferte Code.

fop-over lscht zuerst eine ggf. existierende Datei des angegebenen Namens
        und legt sie dann neu an. Dadurch wird der Aufruf von Minerva oder
        TK2 unabhngig, auch scheint die Anordung der Dateien auf Disketten
        damit gnstiger und weniger fehleranfllig verwaltet zu werden.

 In "forth_scr" sind einige Definitionen hinzugekommen, insbesondere eine
 vollstndige Gruppe von Worten zum (Simultan-)Drucken der Eingabe und von
 beliebigen anderen Texten. Diese wird z.B. geladen mit
                L-LOAD printer flp2_forth_scr

l-load
s-load
        wurden so modifiziert, da sie auch ohne Dateiangabe arbeiten. Es
        gilt dann die jngste Datei, die bei einem Aufruf von s-load oder
        l-load benutzt wurde. Damit lassen sich nun Quelltexte zusammen-
        stellen, die unabhngig vom jeweiligen Laufwerk/Gert arbeiten.

        Der Filename wird mit (boot) adressiert und kann gendert werden:
                (boot) fname" n1_flp2_forth_scr"
        Sind also s-load oder l-load einmal aufgerufen worden, und ist die
        4th-Datei dieselbe, so gengt fr o.a. Beispiel dann:
                L-LOAD printer
        oder etwa einen dem JOBS des TK2 hnlichen (erweiterten) Aufruf:
                L-LOAD .jobs

        Dadurch, da jeder nicht als zugngliches File erkannte Name nun als
        4th-Wort behandelt wird, brechen L-/S-LOAD ab, wenn es solch ein Wort
        (noch) nicht gibt. Definiert man aber den Filenamen selbst als 4th-Wort,
        so kann er dann aktiv werden, und alle mglichen Aktionen einleiten,
        die in diesen Falle sinnvoll sein mgen; im einfachsten Falle z.B die
        Suche nach einem alternativen screenfile:
                : flp1_probe_scr
                  [compile] \
                  [ latest ] literal cr id. ."  nicht gefunden" cr
                  [ latest pfa ] literal w-forget ;
                1 s-load flp1_probe_scr       .( Probe geladen ) ;s

                : flp2_alternative_scr
                  bell screen close
                  cr (screen) -print ."  => "
                  [ latest ] literal id. ."  War nix! "
                  [ latest pfa ] literal w-forget
                  quit ;
                1 s-load flp2_alternative_scr .(  Alternative geladen )
                                ;s
        Wonach nur, wenn eines der Files gefunden wurde, das betr. Wort noch
        weiterbesteht, alle evtl. Vorgnger lschen sich selbsttig aus dem
        Dictionary, sobald sie ihre "Notfall-Aktion" erledigt haben.

c-load  (n.i.)
        zum Einbau fertig compilierter Segmente ist in Vorbereitung, weshalb
        gebeten wird, diesen Namen nicht fr Anwenderdefinitionen zu werwenden.

words   wurde um eine Anzahl Auswahlmglichkeiten erweitert. Damit lassen sich
        nun bestimmte Wort- oder Definitionstypen oder alphabetisch ausgewhlte
        Listen zusammenstellen. Neben dem Folgenden mehr dazu in "forth_txt":
selected
        kann vor {words} aufgerufen werden, um die Ausgabe auf bestimmte Gruppen
        zu beschrnken. Es beeinflut {words} nur fr diesen einen Aufruf.
        Grundstzlich gelten die nach {selected} folgenden max. 7 Zeichen bis
        zum nchsten Leerzeichen als alphabetisches Auswahlkriterium fr den
        Wortanfang der Ausgabe. Daneben gibt es Sondergruppen mit:
                selected imed           fr die "immediate"-Worte;
                selected prim           die Standard- und die mit Langwort-Ptr
                                        aufgerufenen Primitives;
                selected defn {name}    fat die Worte zusammen, deren pfa den-
                                        selben Inhalt wie {name} hat, z.B. also
                                        die Worte aus demselben Definitionswort;
                selected wtyp {name}    die Worte vom selben Typen wie {name}.


 Speziell fr den Betrieb im System der QXL-Karte:

sysflg  (-- dn) hat bei qxl-Systemen in den hherwertigen 16-Bit die Zahl -2.

cache   (-- f)
        gibt 1 zurck bei aktiver Cache, sonst 0, auch in Standard-QLs.
cache-on  (-- ernum)
cache-off (-- ernum)
        entsprechend den Basic-Aufrufen zum Ein- oder Ausschalten der
        Cache-Speicherung - wirkungslos in Standard-QL-Systemen, oder
        wenn das MEM-Device aus IO2 rsp. "dvs_byt" fehlt. In diesen
        Fllen geht in ernum der entsprechende QDOS-Fehlercode zurck.
-cache    (f -- ernum)
        stellt den Zustend entsprechend der z.B. aus {cache} erhaltenen
        Flag ein. Dabei gilt jeder Wert =/= 0 als tf zum Einschalten.

forget  und sein Varianten schalten ggf. vorbergehend die Caches ab. Da hier
        deren einziger kritischer Punkt liegt, kann das F6-System ohne beson-
        dere Manahmen mit aktiven Caches betrieben werden.


 * ++  8. 8.94 ++ v6.14 +++++++++++++

 Ein paar Fehler wurden korrigiert:
s#      empfngt auch negative Zahlen,
        fhrende Leerzeichen knnen die Zahlen nicht mehr verflschen.
s@      schliet den Text in {pad} mit dem Begrenzungszeichen ab.
\.      und {.} im fp-Vocabular sind gegen unbrauchbare Daten abgesichert durch
        Lschen der oberen 4 Bits des Exponenten, wo der qdos-Vector sonst in
        eine Endlos-Schleife geraten kann. {fp-err} wird dann -17.


 * ++ 15. 1.93 ++ v6.12 +++++++++++++

w-forget und forget
        gehen durch ALLE Vocabulare unabhngig von der aktuellen Suchfolge.
-forget bercksichtigt allein das context-Vocabular.

trap1a  (da1 dd3 dd2 dd1 op -- dd1)
        Im qdos-Vocabular; Trap#1-Aufruf mit bergabe auch von A1.

vlist   Ausgabe nach {out-cons}; hlt an, wenn eine Tate bettigt wurde, nach
        erneutem Tastendruck wird die Ausgabe fortgesetzt. Abbruch mit <esc>.
words   (S) gibt die Wortliste alphabetisch sortiert aus.
        Die Ordnung kann mit {(upper)} so modifiziert werden, da sie nur nach
        der Lnge erfolgt (0), nach Lnge getrennt fr Gro- und Kleinschrei-
        bung (32), strikt alphabetisch und zweitrangig nach der Lnge (-33),
        schlielich alphabetisch mit Lnge, getrennt nach Schreibweise (-1).

.s      Ausgabe geht nach {in-cons}

[number] ( ptr -- nn|dn|fn tf | ff )
        Hilfsaufruf fr den headerlosen Standardaufruf in {number}. Bricht bei
        Fehlern nicht mit abort ab, sondern liefert Flag 0, rsp. die Zahl mit 1.
        - {number} darf nur mit {default-is} restauriert werden -

        Smtliche Primitive-Routinen liegen nun, soweit sinnvoll, auerhalb des
        4th-Adressenbereichs. Damit sind dort weitere ca. 2K freigeworden.
        Vom Kern liegen jetzt ca. 17K im 4th-Adressenbereich und 7K 'darunter'.

 $8000   ist die NIEDRIGSTE Forth-Adresse, $7fff die hchste.
 $8000 @ liefert den Abstand von der Job-Basis zur niedrigsten Forth-Adresse,
 $8000 base+ $8000 @ s->d d-
         liefert die wirkliche Speicheradresse der Job-Basis.
 $8000 base+ $8000 @ 0 d- 2 m+ @l $8000 @ = .
        als Kontrolle mu 1 ausgeben.

 * ++ 26.12.93 ++ v6.08 +++++++++++++

 Gegenber der Vorgngerversion unterscheidet diese sich darin, da einige Code-
 teile nach auerhalb der 4th-Adressen verlegt wurden. Damit wurde der nutzbare
 Bereich des 4th-Dictionary um ca. 5K grer. Ein 4th-Wort mute gendert werden:

disp+   ( nn -- dn )
        Der Aufruf zum Umrechnen eines Forth-Pointers in den wirklichen Abstand
        zur Job-Basis liefert nun eine doppelt genaue Zahl, denn, da er 64K
        berschreiten kann, wre er mit 16 Bit ggf. nicht mehr darstellbar.

 Als Effekt nebenbei hat sich gezeigt, da das System nun auch mit dem Kommando
        EXEP
 aus der Hotkey-Erweiterung aufgerufen werden kann. Ausfhrlich wurde das nicht
 untersucht, jedoch verliefen Aufrufe mit Angabe eines neuen Jobnamen fehlerlos:
        EXEP'flp2_f6ed','editor'
 erzeugt den F6-Job aus dem File flp2_f6ed und gibt ihm den Namen 'editor'.

 Da aber der Codebereich des Jobs selber erweiterbar ist, und dort auch Variable
 angelegt werden, sind Kommandos wie HOT_CHP und HOT_RES ohne besondere Manahmen
 ungegeignet. HOT_LOAD ist brauchbar.
 Mehrfachnutzung des F6-Kerns ist durch die 16-Bit-Forth-Struktur nicht mglich.
 Die Hotkey-Aufrufe sind nur von begrenztem Nutzen:
 Fr eine Job-Copie im aktuellen Zustand ist {clone-4th} besser geeignet, und
 den nicht erweiterten Job startet man mit EX o.dgl.

 Die Speichereinteilung ist:

 -----------------------
 vom forth aus adressierbarer bereich
 4th-obergrenze  -------    obergrenze kanal-id-tabelle
                        16 langwort-tabellenpltze
           limit                obergrenze blockpuffer, anfang kanal-id-tabelle
                        16 blcke zu 2+64+2 bytes
           first                anfang des blockpuffers
                        256 bytes 'user-area'
           (u0) und (r0)
                        1088 bytes returnstack. 'abwrts' bauend,
                         170 bytes 'aufwrts' fr den terminal input buffer
           (s0) und (tib)
           .............
                        freier dictionarybereich und datenstack
                        im F6-Kern stehen hier ca 43K bytes zur verfgung
           .............
           pad          hilfsadresse fr einen zwischenpuffer 80 bytes ber here
           here         erste freie stelle im dictionary
           .............
                        von forth-definitionen besetzter bereich
                        der kern beansprucht hier ca. 19K bytes
           .............
 4th-untergrenze ------- ab hier 'aufwrts' 64K 4th-adressenbereich
           .............
            codebereich ca 5K fr processorcode-routinen benutzt, die aus dem
                        system direkt angesprungen werden, standardmig von
                        neu compilierten forth-worten nicht adressierbar.
           .............
 jobanfang - qdos-header mit sprung in das 4th-system
 -----------------------

 * ++ 26.12.93 ++ v6.07 +++++++++++++

 Ein paar Worte sind, u.a. angeregt durch f83 und das aktuelle ans-4th-Dokument,
 entstanden:

source  ( -- ptr nn )   wird z.B. von {word} ausgefhrt,
                        gibt Adresse und Puffergre fr die aktuelle Eingabe an
blk+    ( -- f )        wird von <nul> am Zeilenende ausgefhrt,
                        mit f= -1:tib 0:neues screenfile +ve:nchste blocknummer
#tib    ( -- nn )       Anzahl der gerade aufgenommenen Eingabezeichen ein-
                        schlielich ggf. eines abschlieenden <cr>.
baud    ( -- nn )       Constante fr die aktuelle Baudrate (Vorgabe ist 19200).

 Bei den fp-Worten {lit}, {literal} und {@} wurde die Exponenten-Absicherung
 entfernt, soda diese auch auf beliebige Datengruppierungen zu drei Zellen
 anwendbar sind. Zum Ausgleich wird diese Kontrolle nun bei {constant}, und
 unverndert bei {$>f}, durchgefhrt - sie begrenzt den Exponenten auf 12 Bits.

dpl     wird durch die fp-Worte {$>f}, {2*}, {2/} und {constant} wie bei der
        direkten Zahleneingabe auf -2 gesetzt.

2nd-voc ( -- ptr )
        Da fehleranfllig, und durch die neue Vocabular-Suchfolge berflssig,
        wurde eine Mglichkeit geschaffen, das den Vocabularen direkt, ggf.
        mit {search}, eingeprgte zweite Such-Vocabular unwirksam zu machen.
                2nd-voc off
        stellt diesen Zustand ein, der beim Programmstart auch vorgegeben ist.
        Dabei wird es aber nun wichtig, immer wirklich alle erforderlichen
        Vocabulare anzugeben und sie zum Schlu mit einen weiteren {also} in
        eine sichere Position zu schieben. Der Grund wird aus den ausfhrliche-
        ren Bemerkungen zu v6.01 ersichtlich.
        Der bisherige Zustand kann mit jedem Wert =/= 0 in der Variablen
        {2nd-voc} wiederhergestellt werden.

vocabulary
        Der zweite 'freie' Posten in der Vocabulardefinition (pfa+10) wird von
        den find-Varianten markiert, nachdem das betr. Vocabular erstmals durch-
        sucht wurde. Dadurch ist sichergestellt, da dies bei jedem Vocabular
        immer nur einmal geschieht, unabhngig davon, wie oft es mit {also} in
        den Vocabularstack gebracht wurde, oder ob es in der fixierten secun-
        dren Suchfolge der einzelnen Vocabulare mehrfach vorkommt (s. v6.01).
        Dies hatte ebensooft das Durchsuchen desselben Vocabulars zur Folge,
        und demgem erheblichen berflssigen Zeitaufwand, da dann immer das
        gesamte (weil gerade darin das Wort ja nicht vohanden sein konnte)
        jeweilige Vocabular mehrmals abgesucht wurde.
        Da die Compilezeit aber ganz wesentlich von der Anzahl zu prfender
        Wortnamen abhngt, erspart die nderung einen damit und mit der in
        diesen enthaltenen Anzahl Worte zunehmenden betrchtlichen Zeitanteil,
        erfahrungsgem oft weit mehr als 10% der Zeit, die beim Suchlauf durch
        allein das Forth-Vocabular erfordert.
        Damit knnen nun bedenkenlos beliebig viele Vocabulare beliebig oft
        genannt werden, ohne da das die Compilezeit beeintrchtigt.


 * ++  2.12.93 ++ v6.04 +++++++++++++

id.     hebt immediate-Worte mit vertauschten ink- und strip-Farben hervor.
vlist   ruft id. auf, stellt die worte darum in derselben weise dar.

(find)  wurde an einer Fehlerstelle korrigiert,
        wo die Suche sich vorher in einer Endlosschleife fangen konnte.

shift   (n1 n2 -- n3 n4) liefert n3 als den um +n2 bits nach links geschobenen
        wert von n1, berlauf wird in n4 aufgefangen. -n2 schiebt nach rechts.
        Als einfache Schiebeoperatoren mit Fehlerabbruch bei berlauf knnen
        damit z.B. definiert werden:
                : << abs shift -18 ?error ;
                : >> abs minus shift -18 ?error ;
        Und zur Untersuchung einzelner Bits:
                : BIT minus shift sdrop ;


 * ++ 16.10.93 ++ v6.01 +++++++++++++

 Wichtigste Ergnzungen: Vocabularstack und Compilieren aus Bibliothek-Files.

 Ab Version 6.01 existiert ein Vocabularstack nach f-83-Vorbild, der bis zu
 15 Vocabulare aufnehmen kann, und den Context der Suchordnung erweitert.
 "forth_scr" wurde ergnzt. Es kann nun auch mit Namensangabe des zu compi-
 lierenden Wortes anstelle der Screen-Nummer aus einer Quelltext-Bibliothek
 (in Gestalt eines Screenfile) compiliert werden.

 Zustzliche Worte sind:

also        (r)(I) reiht das ltere Context-Vocabular in die Suchfolge ein.
previous    (r)(I) nimmt das jngste Vocabular aus der Suchfolge heraus.
only        (r)(I) belt nur das Vocabular root in der Suchfolge.
#vocs              liefert als Constante die maximale Anzahl Vocabulare, die
                   in die Suchfolge aufgenommen werden knnen. Der Wert (16)
                   kann, solange noch keine neuen {user}-Variablen definiert
                   worden sind, erhht werden. {up} mu dann fr jeden Posten
                   um 2 Bytes weitergezhlt werden, wobei die absolute Grenze
#user          (h) mit der Maximalgre des {user}-Bereichs zu beachten ist.
                   Vor {w-save} kann {#user} mit IS verndert werden, mu
                   danach aber sicherheitshalber restauriert werden. Die
                   neue Bereichsgre gilt dann fr den damit erzeugten Job.

 Diese Ergnzung ndert darber hinaus nichts an der bewhrten Vocabularbehand-
 lung des f.i.g.-Modells; die jngeren Standards haben nur wenig beigetragen,
 was diese Konzept in irgendeiner Form bereichern oder verbessern knnte.
 Im Unterschied zu jenen unbeholfenen Versuchen der Zusammenfassung gngiger
 Praxis gibt es z.B. keinerlei Probleme bei {forget}, das durch alle Vocabulare
 geht, und auch die gerade nicht im Vocabularstack greifbaren bercksichtigt.

 Das Wort {postpone} ist z.B. so eine Stilblte der Nachfolgestandards, die
 nicht in das F6 nicht bernommen wird. Sie ist sinnlos und irrefhrend.
        compile [compile] forth
 zeigt z.B. entschieden klarer, da und wie ein Wort aufgebaut wird, welches
 den Aufruf eines immediate-Wortes in ein anderes Wort einbauen soll, als
        postpone postpone postpone forth
 - das erste {postpone} compiliert das zweite, da {postpone} immediate sein mu.

 Die im Kern enthaltenen Vocabulare sind weiterhin smtlich "immediate", und es
 empfiehlt sich, dies konventionell auch bei neuen Vocabularen so zu handhaben.
 Das erspart viel Schreiberei bei hufigem Context-Wechsel:
        ..worte.. {vocname} ..worte.. {vocname} ..worte..
 statt der lstigen Schreibweise mit Compile-Klammern z.B. im f83:
        ..worte.. [ {vocname} ] ..worte.. [ {vocname} ] ..worte..

 Der im allgemeinen seltene Fall, wo das neue Vocabular erst beim Aufruf des
 gerade definierten Wortes Context wird, wird im f.i.g.-Forth so abgehandelt:
        ..worte.. [compile] {vocname} ..worte..

 {-find} durchsucht nun der Reihe nach zuerst {context} und dann die ggf. mit
 {also} zuvor auf den Vocabularstack geschobenen Vocabulare. Im Compile-Betrieb
 wird wie bisher zuerst das {local}-Vocabular durchsucht. Die alte Suchordnung
 mit der vocabularspezifischen Nachfolge und der automatischen Bildung eines
 neuen Vocabulars als Untervocabular des gerade {current} vereinbarten bleiben
 erhalten. Ebenso die bertragung des Current-Vocabulars in den Context bei
 Colon-Definitionen, wodurch dieses Vocabular dann zuerst durchsucht wird.

 Bei Erreichen der Maximalzahl durch den Aufruf {also} berlaufende Vocabulare
 fallen aus der Suchordnung heraus. Dies wird nicht als Fehlersituation behan-
 delt, kann aber anhand der Constanten {#vocs} gesondert berwacht werden.

 Bestehende Quelltexte bedrfen darum nur geringer nderungen. Zustzlich gibt
 es noch die Mglichkeit, die besondere Nachfolge-Suche zu unterbinden:

no-search       (I) lscht eine mit search bergebene Eintragung im Context-Voc.

 Weil das ansich sehr einfache Verfahren der Ordnung nach Vocabularen vielleicht
 zunchst etwas unbersichtlich scheint, mag dies die Vernderungen der Suchord-
 nung veranschaulichen:
 Anordnung im Speicher   Verwendung

        ocurrent        Ablage des vor {definitions} gltigen {current}-Voc.
      current         aktuelles Definitionsvocabular
 ocurrent @ current !   restauriert ggf. das vorherige Definitionsvocabular

 vocabularstack, vom 'unteren' Posten an:
      context         aktuelles Lexikon-Vocabular (Wortsuche nach current)
       ocontext        Ablage des alten bei Nennung eines neuen Vocablulars
       [ ...           max. 14 weitere Posten werden ab {context} mit
            ...]        Aufruf von {also} 'hoch'geschoben.
 ende voc.stack ('oben')

        {definitions}   sichert das alte Definitionsvocabular in {ocurrent}
                        und trgt das Context-Vocabular in {current} ein.
        vocabular       Nennung des Namen trgt {current} in {ocurrent} ein,
                        danach wird das eben genannte Vocabular {current}.
        {also}          trgt alle Vocabulare einen Posten 'hher' ein, dabei
                        bleibt {context} erhalten und wird zugleich {ocontext}.
        {rvoc}          copiert {ocurrent} nach {current}.
        {previous}      wie {rvoc}, schiebt auerdem alle weiteren Vocabulare
                        einen Posten zurck. Die 'obere' Stelle wird gelscht.

 Solange noch keine neuen {user}-Variablen definiert wurden, kann der Vocabular-
 Stack erweitert werden. Z.b:
        8                       \ anzahl weiterer vocabulare der suchfolge
        dup #vocs + IS #vocs    \ neues maximum festlegen
        dup + up +!             \ datenbereich dafr reservieren
        w-save flp1_f6          \ gendertes system sichern

 {search} und {no-search} wirken sich direkt auf das Context-Vocabular aus, mit
 dem sie ein unmittelbares Nachfolge-Vocabular fest verknpfen rsp es abkoppeln.
 Die allgemeine Suchordnung aus {also} und {previous} bleibt davon unberhrt.

 Die Vocabulareinstellung sieht nun also etwas so aus:

        only            \ suchfolge gelscht, nur {root} gilt noch
        forth           \ suchfolge nun: 1. {forth} 2. {root}
        definitions     \ {forth} wird current
        editor          \ root verschwindet, es gilt:{editor}{forth}
                        \ da abschlieend aber immer auch {root}
                        \ durchsucht wird, bleiben dessen worte
                        \ stets auffindbar.
        also            \ alle vocs eins 'hoch'schieben
                        \ nun gilt: {editor} {forth} {forth}
                        \ und innerhalb einer {:}-Definition entsteht:
                        \           {forth} {editor forth}
                        \ was danach erhalten bleibt!

        only forth fp editor also forth also also definitions
 erzeugt
        forth forth forth editor fp
 womit auch bei beliebig hufigem Vocabularwechsel, z.B. durch {:} bei abwei-
 chendem {current} und durch einfache Namensnennung, die Suchfolge ab dem
 dritten Namen erhalten bleibt:
                                forth   forth   forth  editor fp
        qdos            =>      qdos    forth   forth  editor fp
        pif             =>      pif     qdos    forth  editor fp
        minerva         =>      minerva pif     forth  editor fp
 und:
        rvoc            =>      pif     pif     forth  editor fp
        rvoc            =>      pif     pif     forth  editor fp
 dagegen:
        previous        =>      pif     forth   editor fp
        previous        =>      forth   editor  fp

 Soll einmal fr einen begrenzten Zeitraum genau nur ein Vocabular gelten, und
 anschlieend die ursprngliche Ordnung wiederhergestellt werden, die aber selbst
 (in Compileraufrufen eines Programms z.B.) nicht bekannt ist, gibt man ein:
        also {name} also context 2+ off
 Damit wird die Suche allein auf das Vocabular {name} begrenzt.
 Die alte Ordnung stellt man dann wieder her mit:
        previous previous
 Und wenn auch das Vocabular aus der Suche ausgeschlossen sein soll, in dem das
 Context-Vocabular definiert wurde, ruft man auch noch {no-search} auf. So lt
 sich nun die Suchordnung in jeder Weise beeinflussen. Sicherheitshalber kann
 aber das {root}-Vocabular keinesfalls von der Suchfolge ausgenommen werden.

 Da hierzu Eingriffe ins System erforderlich waren, wren diese nderungen nur
 mit groem Aufwand von auen nachsetzbar, sie sind darum nicht in "forth_scr"
 enthalten. Fr mglicherweise erneute nderungen sind nun die wichtigsten
 Stellen vectorisiert oder deferrred eingerichtet.

[interpret]     (h)(D) Vorspann im Wort interpret
[find]          (h)(D) ( stg nfa -- pfa chr f | 0 ) in -find, Vorgabe (find)
[convert]       (h)(D) ( ptr -- ) Zahlenermittlung im Wort interpret.
                Aufruf immer, wenn ein Wort ab ptr nicht gefunden wurde.
number          (D) mit Vorgabe [number], Abbruch bei milungener Wandlung
[number]        (h) ( ptr -- dn | err) Standardaufruf in {number}.
buffer          (D)
block           (D)

 Wieder aktiviert wurden:

assembler       (r)(I)(D) fr Assembler-Vocabular (vormals code-voc)
asm68           (r)(I) als Assemblervocabular (a)
[donext]        (a) assembler-label zum next-Einsprung.
[doexec]        (a) dto, Ausfhrungs-Ptr. im W-Register (A2.w)
doforget        (h)(D) ( n1 n2 -- n1 n2 )
                Erhlt die jngste Vocabular-Verkettung in n1 und in n2 die nfa
                des mit einer der {forget}-Varianten freizugebenden Wortes und
                mu diese unverndert (oder in gleichwertiger Form) weitergeben.
                In diesem {forget}-Vorspann knnen vorbereitende Aktionen aus-
                gefhrt werden; Verwendung z.B. bei {heapmem} in "forth_scr".
forget-lk       (-- ptr) vorbereitet zur Verkettung optionaler forget-Aktionen.

w-find          (D) und
-find           (D) in deferred Worte umgewandelt.

 Das Compilieren aus einer Bibliothek wird durch den aus s-load modifizierten
 Aufruf L-LOAD um die Mglichkeit der namentlichen Suche ergnzt. Die dafr
 geeigneten Screenfiles mssen das gesuchte Wort in der Seite, wo das Compi-
 lieren beginnen soll, in der ersten Zeile enthalten, weiter markiert durch
 vorangestellten Doppelpunkt und jenem folgendes Leerzeichen. In dieser Form
 darf das Wort bis dahin in keiner anderen Kopfzeile auftreten.
 Viele Beispiele dazu finden sich in "forth_scr".

 Fr heikle Flle sind {s-load} und {l-load} so eingerichtet, da sie im Un-
 terschied zu {load} auch mit schreibgeschtzten Disketten arbeiten knnen.

 In "forth_scr" ist definiert:

l-load {wortname} {screenfilename}
        (S) Im angegebenen Screenfile wird eine Kopfzeile (erste Zeile
        einer Seite) gesucht, in der das gesuchte Wort mit fhrendem
        Doppelpunkt und Space verzeichnet ist. Die so ermittelte
        (ganze) Seite wird compiliert.
        Dazu geht sie als Screen-Nummer an den schon bekannten Aufruf
        s-load, fr den der hier genannte Filename weitergilt.

 1 s-load flp1_forth_scr
        ldt L-LOAD,
        und hiermit wird nun z.B. der Aufruf ?imm compilert:
  l-load ?imm flp1_forth_scr

 Da dies eine allzuhufige Fehlerquelle scheint, wurde 'h' als Zahlenpraefix
 gestrichen. Es gelten
 Zeichen         temp. Zahlenbasis
   {             256     nur das erste Zeichen wird bewertet (statt ascii)
   $             16
   #             10
   &             8
   %             2
   \             erzeugt eine qdos-Fliekommazahl

 Der Wert dieser Kennzeichen mu sich noch erweisen:
                12     erleichtert das Rechnen ohne Bruchzahlen (dagegen er-
                        weist sich der Gebrauch des Dezimalsystems schon fast
                        als epochaler Schwachsinn).
   '             5
   "             6
   !             4

 * ++ 24.9.93 +++++++++++++++++++++++

 In "forth_scr" finden sich alle Definitionen, die zur ursprnglichen Version
 hinzugekommen sind, als Hi-Level-Worte zur Anpassung nach Bedarf. Die jngste
 Original-Version ist dann u.U. entbehrlich. Dazu noch einige weitere Worte, die
 von Fall zu Fall gebraucht werden knnen - nhere Erluterungen im Quelltext:
        EX und EW       fremde Jobs aufrufen, ohne Parameterbergabe an den Job
        (clone-jdt)     ( d.job.id -- d.job.id)
                        wird innerhalb des Aufrufs unmittelbar vor dem Aktivie-
                        ren des Jobs durchlaufen - auch bei {clone-4th}.
                        {a2@l} liefert dann die Speicherbasis des Jobs, soda
                        hieraus auch die Startwerte der Register des Jobs be-
                        einflut werden knnen. Damit wird auch die bergabe
                        von Parametern nach qdos-Standard mglich.
        DATAD$ DATA_USE etc. - die vom Basic mit TK2 bekannten Device-Vorgaben
        DIR             wie im Glossar beschrieben
        BACKUP          dto.
        HEAPMEM         und untersttzende Worte zum Einrichten eines Speicher-
                        bereichs im Heap. Das Wort ist gegen Mehrfachaufruf und
                        {forget} abgesichert und erneuert ggf. auch einen zuvor
                        aufgegebenen Speicherbereich einer bekannten Definition.
        .VIEW           Erweiterung fr die VIEW-Felder nach f-83-Muster.
        DUMP LDUMP      Speicherauszug darstellen.


 Damit Programme mit automatischer Anpassung an verschiedene Systemkonstella-
 tionen versehen werden knnen, liefert das neue Wort {sysflg} als 32-bit-Wert
 byteweise gepackt:
     hi    -1  bei 68010+, sonst 0
          -1  emu, 1 JM und lter, 0 sonst
         char qdos Nationen-Markierung
     lo    -1  Minerva (ver. > 1.50, fr ri-exec), 0 sonst

         sysflg drop >< emit
 gibt z.b. das Kennzeichen fr die nationale Rom-Version aus.


 Blockfile-Adressierung:

 Das File-System holt nun auch in den Kerndefinitionen alle Daten zu den Blocks
 und der Screen-Gre aus den zugehrigen Constanten {b/buf} und {b/scr}. Es gibt
 damit keine Festwerte im System mehr, die 'gewut' werden mssen. Bei konsequen-
 ter Unterscheidung dieser Daten und der Hilfsvariablen/-Constanten {c/l}, {scr}
 und {blk} sollten damit unterschiedliche Formate und beliebige Verhltnisse zwi-
 schen Block-Gre, Zeilenlnge und Editor-Screens verwaltet werden knnen.
 "Sollten" deshalb, weil diese Dinge nicht untersucht wurden.

 Kanle:
        Eine dem Basic hnliche Kanalwahl ist vorbereitet durch das
        DefinitionsWort {#chan}:

#chan   use: ( d.ernum -- )  #CHAN {name}  ( -- | abort)
        erwartet die Fehlernumer aus einem vorangegangenen Aufruf der fopen-
        Gruppe, wertet diese ggf. durch Abbruch und Fehlermeldung aus, und
        bildet ein Wort, bei dessen Aufruf {in-cons}, {out-cons} und {work}
        auf den Kanal gestellt werden, der zum Zeitpunkt der Definition der
        {work}-Kanal war - welches nach einem der fopen-Aufrufe der gerade
        geffnete Kanal ist. Der Aufruf von hiermit gebildeten Worten bricht
        ab, wenn der bergebene Kanal nicht (mehr) zugnglich ist. Die betr.
        Fehleraktion lt sich in {error} nach Bedarf re-vectorisieren.

                fopen con_100x50a40x30 #chan w#1
        oder
                fop-over flp2_ein_34_zeichen_langer_name... #chan kanal#2
        und nun gehen nach z.B.
                kanal#2 <enter>
        alle Operationen der i/o- und work-Aufrufe, insbes. also auch die des
        qdos-Vocabulars, an den dem neuen Wort {kanal#2} zugewiesenen Kanal.
        Irgendein bereits offener Kanal kann mit einem Platzhalter fr den
        Fehlercode an die #chan-Definition folgendermaen bergeben werden:
                ( kanalnummer )  to-work
        oder    ( d.kanal-id  ) set-work
        dann                    0. #chan {name}

        Sollen fr {in-cons}, {out-cons} und {work} verschiedene Kanle gelten,
        so bergibt man nach der Ur-Definition deren id-Zahlen an das mit #chan
        gebildete Wort. Ein Beispiel mit den jeweils gerade gltigen Kanlen:
                0. #chan {name}                 zuerst das Wortgerippe erzeugen
                ' {name}                        seine pfa ermitteln und erstmal
                2+                              das [dodoes] berspringen,
                   dup in-cons  ch-id rot 2!    aktuellen input-Kanal eintragen
                4+ dup out-cons ch-id rot 2!    desgl. System-Ausgabe (Prompts)
                4+     work     ch-id rot 2!    und aktuellen {work}-Kanal.
        Beim Aufruf werden die drei Kanle gesondert auf Zugnglichkeit geprft.

        Ein weiteres Beispiel steht in "forth_scr" bei der Definition von {w#0}.


 * ++++++++++++++++++++++++++++++++++

 Sichere Speicherzuweisungen und automatische Freigabe bei {forget}:

 {heapmem} und zugehrige Worte werden in "forth_scr" definiert und besorgen
 Speicherreservierung und geordnete Freigabe im Heap. Das Definitionswort legt
 zunchst nur ein Variablenfeld an, wo ggf. die Basisadresse der Heap-Zuweisung
 und ein Verkettungspointer eingetragen wird. Sooft das damit definierte Wort
 nun aufgerufen wird, liefert es stets eine gltige (absolute) Speicheradresse
 zum Stack, die zu einem bereits vorhandenen Bereich gehrt oder zu einer durch
 diesen Aufruf veranlaten neuen Zuweisung. {heap-rmv} nimmt eine Reservierung
 zurck. Erneuter Aufruf des Speicherwortes nach vorheriger Freigabe legt den
 zugehrigen Speicherbereich sofort wieder neu an. Ob eine Adresse tatschlich
 auf einen zum Job gehrenden Speicherbereich zeigt, lt sich mit {4th-heap}
 berprfen. {clchp} nimmt smtliche Zuweisungen zurck, und {heap?} zeigt die
 Adressen aller mit {heap-mem} eingerichteten Speicherblcke an.

 Auerdem wird {forget} samt seinen Varianten so erweitert, da Bereiche, deren
 definierende Aufrufe zu den zu entfernenden Worten gehren, gleichzeitig frei-
 gegeben werden. Spter ist dies ohne besondere Vorkehrungen nicht mehr mglich,
 weil nach {forget} die Basisadresse der Heap-Reservierung 'vergessen' ist.
 Auch {empty}, in scr# 8 als {forget}-Variante fr alle Worte 'oberhalb' von
 {fence} definiert, lst die Freigabe solcher Heap-Bereiche aus.

 Beispiele:
                        1024 heapmem speicher   ( gre/4 HEAPMEM {name}
 definiert eine 'aktive' Variable, die zunchst nur die angegebene Zahl enthlt.
 Beim Aufruf veranlat sie die Zuweisung eines Heap-Blocks von vierfacher Gre
 der Zahl, mit der sie definiert wurde, und gibt die Speicheradresse des reser-
 vierten Bereiches zum Stack. Solange dieser Block nicht aufgegeben wird, kommt
 von nun an immer dieselbe Adresse zurck:

                        speicher                ( -- d.adresse
 liefert dann also die Basisadresse eines 4K Bytes groen Speicherblocks.
 Bedingt durch die Grenangabe als 16-Bit-Zahl knnen mit {heapmem} Speicher-
 blcke von 4 bis 262140 Bytes definiert werden.

 Sollen anderweitig definierte Speicherzuweisungen in o.g. Automatik zur Heap-
 freigabe aufgenommen werden, sind sie ber {heap-lk} zu verketten:
        ( d.adresse -- ) here 1 and allot       ( geradzahlige 4th-adresse
                         here 6 allot 2!        ( speicheradresse, 16-bit-dummy
                         here heap-lk dup @ , ! ( verketten
 Diese Verkettung gengt, Wortheader o.a. Referenzen sind nicht erforderlich.

 Einzel-Freigabe mittels {heap-rmv} bercksichtigt diese Liste nicht, kann also
 beliebig fr jeden Speicherbereich aufgerufen werden, den der augenblickliche
 4th-Job besitzt. Die 'Automatik' wiederum prft, ob die ihr bergebene Adresse
 zu einem noch existierenden eigenen Speicherblock gehrt. Widrigenfalls sucht
 sie einfach nur weiter nach der nchsten Adresse. 'Fremde' Bereiche lst auch
 {heap-rmv} darum nicht auf, dazu ist das QDOS-Wort {rechp} geeignet, wobei aber
 im QDOS nicht geprft wird, ob die bergebene Adresse (noch) gltig ist. Dadurch
 bedingt kann es zu schwerwiegenden Fehlern kommen, die auch vor File-Daten nicht
 halt machen! Gesonderte Prfung ist darum unbedingt ratsam, etwa mittels der vom
 System gefhrten Listen aus beispielsweise sv.cheap { 4 qsys+ 2@l }.


 Gru von mir, .hpr

  .hpr'12/93  eof 
