====== Tokiwa-Basic-Compiler ======
Der Tokiwa-Basic-Compiler (TBC) ist eigentlich nicht neu, stammt aber aus Japan und hatte lange Zeit nur eine
japanische Dokumentation, so dass er außerhalb Japans relativ wenig Verbreitung fand.
Der Compiler wurde - vermutlich Anfang der 1990er Jahre - von Dr. Genji Okada entwickelt.
Die bislang letzte Version (5.55e) stammt vom Dezember 2000 und bekam vom Autor eine, wenn auch sehr knappe,
englischsprachige Beschreibung spendiert, was den Einsatz natürlich erleichtert,
Neben der Freeware-Version, die man z.B. unter http://www.franksteinberg.de/psprach.htm#TokiwaBas herunterladen
kann, gab es wohl noch eine kommerzielle Variante, die aber nirgends mehr auffindbar zu sein scheint.
Inzwischen existiert auch eine deutschsprachige Version des Handbuchs, die eine Übersetzung der englischen Version
mit einer Reihe von Ergänzungen und erklärenden Anmerkungen darstellt. Sie ist [[http://www.kiezsoft.de/download/tbc_de.pdf|HIER]] abrufbar.
===== Besonderheiten von Tokiwa-Basic =====
Tokiwa-Basic nimmt sich (so der Autor) Standard-Basic als Ausgangspunkt und erweitert es um nützliche Eigenschaften:
* keine Angabe von Zeilennummern notwendig
* explizit festlegbare Datentypen für Variablen (integer, real, character)
* erweiterte Arrays (mit DIMX definierbar)
* benutzerdefinierte benannte Unterprogramme und Funktionen mit formalen Parameterlisten
* lokale Variablen in Unterprogrammen und Funktionen
* integrierte Gleitpunkt-Arithmetik
* integrierter Assembler für maschinennahe Routinen
Der Tokiwa-Basic-Cpmpiler ist tatsächlich ein "echter" Compiler. Es wird also direkt Maschinencode erzeugt
und folglich kein Runtime-Modul benötigt. Der Overhead ist dabei recht klein - er liegt bei etwa 400 Bytes, die
für die Initialisierung benötigt werden. Werden Real-Zahlen verwendet und somit die Gleitpunkt-Arithmetik benötigt, kommen noch einmal ca. 3 KB dazu, was im Vergleich zu den 20KB, die z.B. die Gleitpunkt-Emulation von Turbo-C braucht, sehr sparsam ist.
Der Compiler kann wahlweise Programme im EXE- oder COM-Format erzeugen, wobei sich beide Varianten in ihrem
Aufbau praktisch nicht unterscheiden. Die EXE-Dateien verwenden initial das Tiny-Speichermodell und belegen,
wie die COM-Dateien, den gesamten freien Speicher. Die Initialisierung der Segmentregister erfolgt in
beiden Varianten auf gleiche Weise zur Laufzeit.
Tokiwa-Basic erlaubt das Anlegen von Bibliotheken (Quelltext), die in Programme per MERGE-Anweisung
integriert werden können. Dies ermöglicht die einfache Wiederverwendung benutzerdefinierter Funktionen
und Unterprogramme.
===== Tokiwa-Basic auf dem Portfolio =====
Der Compiler ist nur etwa 36KB groß und passt damit bequem auf eine CCM-Karte. Weder der Compiler noch
die von ihm erzeugten Programme benötigen Funktionen, die auf dem Portfolio nicht verfügbar sind. Bei der Übersetzung werden außerdem keine temporären Dateien erzeugt, die bei wenig Platz zu Problemen führen könnten.
Allerdings gibt es ein anderes Problem, das den Einsatz des Compilers auf einem Standard-Pofo
verhindert: Er gönnt sich zu seinem Code zwei Datensegmente von jeweils 64K sowie einen
Stack von 18K und benötigt damit mindestens ca. 180K RAM, was also eine Speichererweiterung erfordert.
Auch die erzeugten Programme gehen - für Portfolio-Verhältnisse - recht großzügig mit dem Speicher um.
Sie verlangen normalerweise mindestens 69K RAM, was darauf zurückzuführen ist, dass standardmäßig
ein Datensegment von 64K und ein Stack von 4K angelegt werden. Mit Hilfe von Compiler-Optionen
und einem kleinen Patch-Programm lässt sich der Bedarf aber bis auf etwa 10K reduzieren.
Damit sind mit dem TBC erzeugte Programme dann bestens für den Einsatz auf dem Portfolio geeignet. Der
integrierte Assembler ermöglicht sehr einfach den direkten Zugriff auf Systemfunktionen.
Für die Pofo-Programmierung mit Tokiwa-Basic gibt es [[http://www.kiezsoft.de/download/tbc555fe.zip | HIER]] eine erweiterte Distribution des Compilers,
die folgende zusätzliche Dateien enthält:
* tbc_de.pdf: die deutschprachige Dokumentation
* tbcptch.com: Binary des Patch-Programms
* tbcptch.bas: Quellcode des Patch-Programms (ja, in Tokiwa-Basic geschrieben :-D )
* mshrink.ltb: Bibliothek zur Verkleinerung des verwendeten Speicherblocks
* alloc.ltb: Bibliothek zur Verwaltung von dynamischen Speicherbereichen
* strings.ltb: Bibliothek mit zusätzlichen String-Funktionen
* files.ltb: Bibliothek mit erweiterten Funktionen zum Umgang mit Binärdateien
* dirs.ltb: Bibliothek mit Verzeichnisfunktionen
* test31.bas: Testprogramm für mshrink.ltb und alloc.ltb
* strings.bas: Testprogramm für strings.ltb
===== Verwenden von TBCPTCH =====
Der Zweck von TBCPTCH besteht darin, den beim Programmstart benötigten Speicherplatz eines mit TBC
übersetzten Programms zu reduzieren. Voraussetzung dafür ist es, die Maximalgröße des Datenbereichs
zu reduzieren. Dies erfolgt mit Hilfe der Compiler-Optionen /wl (Obergrenze des Offsets im Datensegment),
/wp (Maximalwert des Stack-Pointers) und /ws (Stack-Größe in Bytes).
Dabei gelten folgende Standardeinstellungen: /wl=&fff8 /wp=&fffe /ws=4096
Allerdings kann man diese Werte nicht beliebig verkleinern - folgendes ist zu beachten:
Das Datensegment braucht eine Mindestgröße, die sich etwa wie folgt abschätzen lässt:
Anzahl aller globalen Integer-Variablen * 2
+ Anzahl aller globalen Real-Variablen * 5
+ Anzahl aller globalen String (Character)-Variablen * 2
+ Summe der Längen aller globalen String-Variablen
+ Summe der Längen aller mit DIM definierten Felder Länge = Anzahl Elemente * Elementgröße)
+ Anzahl der mit DINX definierten Felder * 2
+ Summe der Puffergrößen (Optionen /wt, /wi und /wb; Standard: 514 Bytes)
+ mindestens 1K für Stringoperationen und sonstigen Verwaltungs-Kleinkram
= Minimalwert für /wl
Das Stacksegment liegt um die durch /ws gegebene Anzahl von Bytes oberhalb des Beginns des Datensegments.
Damit sich Stack und Datenbereich nicht gegenseitig überschreiben können, darf der Wert von /wp
nicht kleiner als der von /wl sein.
Die benötigte Stackgröße ergibt sich vor allem aus der Anzahl der in Unterprogrammen und
Funktionen verwendeten Argumente und lokalen Variablen sowie der maximalen Tiefe rekursiver Aufrufe.
Jedes Argument benötigt 2 Bytes auf dem Stäck, zusätzlich werden für jeden Unterprogramm-/Funktionsaufruf
2 Bytes für die Return-Adresse benötigt. Darüber hinaus fallen für jede lokale Integer-Variable 2 bytes an.
Lokale Real- und String-Variablen werden dagegen im Datensegment angelegt und sind für dessen
Größe zu berücksichtigen.
Für die Einstellung der Optionen bietet es sich an, in der ersten Zeile des Programm-Quelltextes
die options-Anweisung zu verwenden.
z.B. options /wl=&1ff8 /wp=&1ffe /ws=1024
Nach dem Übersetzen mit TBC.COM kann nun TBCPTCH.COM mit folgender Syntax aufgerufen werden:
TBCPTCH file[.COM] [file2]
Dabei ist file der Name (ggf. mit Pfad) des zu patchenden Programms. Fehlt die Extension,
so wird als Standard COM angenommen.
Das optionale Argument file2 bezeichnet den Namen der Ausgabedatei. Ist das Argument angegeben,
so wird eine Kopie von file angelegt und der Patch darauf ausgeführt; fehlt es, wird
file selbst modifiziert.
TBCPTCH erkennt den Dateityp an der Extension. Lautet sie "EXE", wird eine EXE-Datei angenommen,
andernfalls eine Datei im COM-Format.
//Achtung:// Der Patch bewirkt, dass man Programme auch bei weniger als 69K freiem Speicher starten kann.
Falls in einem Programm mit DIMX definierte (erweiterte) Arrays verwendet werden, ist dies allerdings
keine Garantie dafür, dass es auch läuft. Der Grund: Solche Felder werden oberhalb des Stacks angelegt
und bei der Prüfung des freien Speichers beim Programmstart nicht berücksichtigt. Auf der sicheren Seite
ist man also nur, wenn man keine DIMX-Felder verwendet oder weiß, dass der Speicher trotzdem reicht ;-).
===== Speicherbereich zur Laufzeit verkleinern =====
Sowohl die EXE- als auch die COM-Versionen (die sowieso) der mit TBC erzeugten Programme belegen
beim Start den größtmöglichen Speicherblock (was oft dem gesamten freien Speicher entspricht).
Die Folge davon ist, dass man weder die Möglichkeit hat, vom System weiteren Speicher dynamisch
anzufordern noch weitere Programme als Kindprozesse zu starten. Weil im Normalfall aber nicht der
gesamte Speicher benötigt wird, kann man den Speicherblock des Programms zur Laufzeit verkleinern.
Dabei ist der Ablauf folgender:
- ermittle die Adresse des eigenen PSP (= Startadresse des Speicherblocks)
- ermittle die höchstmögliche verwendete Adresse (Ende des als letztes definierten DIMX-Feldes)
- rechne die Gesamtgröße in Paragraphen aus
- verkleinere den Speicherbereich mit der DOS-Funktion 4AH (Set Block)
Da die Größe von Arrays leider nirgends abfragbar ist, bietet es sich an, zum Bestimmen der Endadresse mit
DIMX ein Dummy-Feld anzulegen, das hinter allen anderen Feldern definiert wird. Seine Startadresse
entspricht damit der Adresse des ersten freien Segments hinter dem Programm und die Blockgröße
in Paragraphen ist einfach diese Adresse, vermindert um die PSP-Segmentadresse.
Weil der beschriebene Ablauf eigentlich immer gleich ist, gibt es in der erweiterten Distribution
eine kleine Bibliothek, die man einfach mit MERGE hinter der letzten Felddefinition ins
Programm einfügt und die dann die Verkleinerung automatisch erledigt.
Ein Beispiel für die Verwendung findet sich im schon erwähnten Testprogramm test31.bas.
===== Bibliotheken =====
Tokiwa-Basic unterstützt mit der MERGE-Anweisung das Einbinden von Quelltextbibliotheken in ein Programm. Das erlaubt es grundsätzlich, wiederverwendbare Programmteile (typischerweise Unterprogramme und Funktionen) zu erstellen und bei Bedarf darauf zurückzugreifen.\\
Mit Hilfe von Bibliotheken lassen sich vor allem auch wichtige Funktionen "nachrüsten", für die keine Standardfunktionen vorhanden sind.
Eine wesentliche Einschränkung ergibt sich allerdings daraus, dass die MERGE-Anweisung keine verschachtelten Bibliotheken zulässt (MERGE darf nicht in einer Bibliothek verwendet werden), was es z.B. unmöglich macht, an zentraler Stelle Konstantendefinitionen zusammenzufassen. Wenn Bibliotheken voneinander abhängen, lässt sich dies nicht im Quellcode ausdrücken - vielmehr muss man es wissen bzw. entsprechend dokumentieren.
Wenn - wie bei unserem Pofo - der Platz recht knapp ist, kann es außerdem ein Problem darstellen, dass mit dem Einbinden einer Bibliothek deren gesamter Inhalt mit ins Programm aufgenommen wird - auch wenn man womöglich nur eine einzige Funktion aufruft. Deshalb kann es in manchen Fällen von Vorteil sein, nur einzelne Abschnitte aus einer Bibliothek direkt ins Programm hinein zu kopieren, anstatt die Bibliothek mit MERGE einzubinden.
Nachfolgend wird - ohne Anspruch auf Vollständigkeit - der Inhalt der einzelnen Bibliotheken als Kurzreferenz dargestellt. Diese Referenz soll bei der Verwendung helfen, ist aber keine umfassende Dokumentation. Es empfiehlt sich also in jedem Fall, auch die Kommentare in den Bibliotheken selbst und ggf. deren Quellen zu lesen.
Weil bei Tokiwa-Basic benutzerdefinierte Funktionen, die einen Integer-Wert zurückliefern, über das Schlüsselwort SUBROUTINE beschrieben werden, ist die Unterscheidung zwischen Unterprogrammen und Funktionen etwas verwirrend. Nachfolgend wird die Unterscheidung so vorgenommen, dass //Unterprogramme keinen Rückgabewert// haben (entsprechend etwa Prozeduren in Pascal), während //Funktionen einen Wert zurückgeben//.
==== Bibliothek CONTIME.LIB ====
Diese Bibliothek gehört zur Original-Distribution von Tokiwa-Basic und beinhaltet eine etwas eigenartige Mischung von Funktionen zur Konsoleneingabe, Lesen von Datum und Uhrzeit sowie Zeichenkettenbehandlung.
**Enthaltene Unterprogramme/Funktionen:**
=== conin ===
Die Funktion liest ein einzelnes Zeichen von der Konsole. Ein Bildschirmecho erfolgt dabei nicht. Ist kein Zeichen im Tastaturpuffer, so wird auf die Eingabe eines Zeichens gewartet.
Argumente: keine\\
Rückgabewert: ASCII-Code des gelesenen Zeichens
=== up_conin ===
Fie Funktion verhält sich wie ''conin'', eingegebene Buchstaben werden jedoch in Großbuchstaben umgewandelt.
Argumente: keine\\
Rückgabewert: ASCII-Code des gelesenen Zeichens
=== to_upper(str) ===
Das Unterprogramm wandelt alle Kleinbuchstaben der übergebenen Zeichenkette in Großbuchstaben um.
Argument: zu modifizierende Zeichenkette\\
Rückgabewert: keiner
=== time ===
Das Unterprogramm trägt in die globale Variable time$ die aktuelle Uhrzeit in der Form ''hh:mm:ss'' ein.
Argumente: keine\\
Rückgabewert: keiner
Nach dem Aufruf steht die Uhrzeit in der Variablen time$.\\
**Achtung:** Ein Programm, das das Unterprogramm verwendet, sollte selbst keine Variable time$ zu einem anderen Zweck anlegen.
=== date ===
Das Unterprogramm trägt in die globale Variable date$ die aktuelle Uhrzeit in der Form ''yy-mm-dd'' ein.
Argumente: keine\\
Rückgabewert: keiner
Nach dem Aufruf steht das Datum in der Variablen date$.\\
**Achtung:** Ein Programm, das das Unterprogramm verwendet, sollte selbt keine Variable date$ zu einem anderen Zweck anlegen.
==== Bibliothek MSHRINK.LTB ====
Diese Bibliothek stellt keine Funktionen im eigentlichen Sinne bereit. Ihre Aufgabe besteht darin, den vom aktuellen Programm belegten Speicher auf die tatsächlich benötigte Größe zu beschränken, um so die dynamische Anforderung von Speicher zu ermöglichen.
Dazu muss MSHRINK.LTB hinter dem letzten mit ''dimx'' definierten erweiterten Feld (oder am Programmstart, falls es kein solches Feld gibt, eingebunden werden.
Mit dem Einbinden von MSHRINK.LTB sind außerdem folgende globale Variablen definiert:
* integer psp__seg : Segmentadresse des eigenen PSP
* integer nxt__mcb : Segmentadresse des MCB für den nächsten Speicherbereich hinter dem Programm
* integer my__size : Größe des vom Programm belegten Speicherblocks in Paragraphen
==== Bibliothek ALLOC.LTB ====
Die Bibliothek stellt Funktionen zur dynamischen Speicheranforderung über DOS-Systemaufrufe bereit.
Da Tokiwa-Basic-Programme standardmäßig den gesamten verfügbaren Speicher belegen, ist die Verwendung dynamischen Speichers nur dann möglich, wenn der belegte Speicher vorher (mit Hilfe der Bibliothek MSHRING.LTB) redutiert wurde.
Alle Funktionen dieser Bibliothek legen im Falle eines Ausführungsfehlers den DOS-Fehlercode in der globalen (Integer-) Variablen ''**ALLOC_ERROR**'' ab.
Darüber hinaus werden folgende Konstanten definiert:
* DOS-Funktionen
* _dos_malloc &48 (allocate memory block)
* _dos_mfree &49 (free memory block)
* _dos_mresize &4A (resize memory block)
* _dos_setmstrat &5801 (set memory strategy)
* _dos_getmstrat &5800 (get memory strategy)
* Strategie-Konstanten für _dos_setmstrat
* _mstrat_first 0 (allocate first block available)
* _mstrat_best 1 (allocate best sized menory block)
* _mstrat_last 2 (allocate last block available)
**Enthaltene Unterprogramme/Funktionen:**
=== allocMem(parSize) ===
Die Funktion fordert einen Speicherbereich der angegebenen Größe vom System an.
Argument: Größe des Speicherbereichs in Paragraphen\\
Rückgabewert: Segmentadresse des Bereichs bei Erfolg, sonst 0
Hinweis: Ein mit ''allocMem'' angelegter Speicherbereich sollte stets mit ''freeMem'' wieder freigegeben werden.
=== freeMem(handle) ===
Die Funktion gibt einen mit ''allocMem'' angeforderten Speicherbereich wieder frei.
Argument: Handle (Segmentadresse) des freizugebenden Speicherbereichs\\
Rückgabewert: 0 bei Erfolg, sonst Fehlernummer
=== resizeMem(handle, parSize) ===
Die Funktion ändert die Größe eines mit ''allocMem'' angelegten Speicherbereichs.
Argumente:
* handle: Handle (Segmentadresse) des Speicherbereichs
* parSize: neue Größe in Paragraphen
Rückgabewert: 0 bei Erfolg, sonst Fehlernummer
=== getMemAvail ===
Die Funktion ermittelt die Größe des größten noch freien Speicherbereichs.
Argumente: keine
Rückgabewert: Größe des größten freien Speicherblocks in Paragraphen
=== getAllocStrategy ===
Die Funktion gibt die aktuelle Einstellung für die Strategie der Speichervergabe zurück.
Argumente: keine
Rückgabewert: Speichervergabe-Strategie (''_mstrat_first'', ''_mstrat_best'' oder ''_mstrat_last'')
=== setAllocStrategy(strategy) ===
Das Unterprogramm legt die Einstellung für die Strategie der Speichervergabe fest.
Argument: Speichervergabe-Strategie (''_mstrat_first'', ''_mstrat_best'' oder ''_mstrat_last'')
Rückgabewert: keiner
==== Bibliothek STRINGS.LTB ====
Die Bibliothek enthält eine Reihe von Funktionen zur erweiterten und schnelleren Verarbeitung von Zeichenketten.
**Enthaltene Unterprogramme/Funktionen:**
=== getCmdLine(resloc) ===
Die Funktion speichert die Kommandozeile (Programmpfad mit übergebenen Argumenten) in einer String-Variablen.
Argument: Adresse der Puffervariablen, in der die Kommandozeile abgelegt werden soll.
Rückgabewert: Offset-Adresse des ersten Zeichens in der Puffervariablen
Hinweise:
* Der Ergebnispuffer (adressiert durch resloc) muss eine String-Variable im Datensegment sein, deren Adresse sich mit Hilfe der LOC-Funktion bestimmen lässt.
* Der Rückgabewert kann direkt an die ''strTok''-Funktion als Argument ''str'' übergeben werden.
=== memCpy(dest,src,nbytes) ===
Die Funktion kopiert einen Datenbereich im Speicher unter Nutzung von NEAR-Adressen.
Argumente:
* dest: Adresse des Zielpuffers
* osrc: Adresse der Datenquelle
* nbytes: Länge des zu kopierenden Speicherbereichs in Bytes
Rückgabewert: Adresse des Zielpuffers
Hinweise:
* Sowohl der Zielpuffer als auch die Datenquelle müssen vollständig im Datensegment liegen.
* Der Zielpuffer muss mindestens eine Kapazität von ''nbytes'' Bytes haben.
* Ein Überlappen der Bereiche von Quelle und Zielpuffer ist zulässig, wenn die Zieladresse unterhalb der Quelladresse liegt - nicht umgekehrt!
* Das ''nbytes''-Argument wird als vorzeichenloser Integer-Wert interpretiert.
* Achtung: Es wird keine Überprüfung auf Offset-Überlauf durchgeführt!
=== memCpyFar(odest,sdest,osrc,ssrc,nbytes) ===
Die Funktion kopiert einen Datenbereich im Speicher unter Nutzung von FAR-Adressen.
Argumente:
* odest: Offset-Adresse des Zielpuffers
* sdest: Segment-Adresse des Zielpuffers
* osrc: Offset-Adresse der Datenquelle
* ssrc: Segment-Adresse der Datenquelle
* nbytes: Länge des zu kopierenden Speicherbereichs in Bytes
Rückgabewert: Offset-Adresse des Zielpuffers; die Segment-Adresse wird im Register DX abgelegt
Hinweise:
* Der Zielpuffer muss mindestens eine Kapazität von ''nbytes'' Bytes haben.
* Ein Überlappen der Bereiche von Quelle und Zielpuffer ist zulässig, wenn die Zieladresse unterhalb der Quelladresse liegt - nicht umgekehrt!
* Das ''nbytes''-Argument wird als vorzeichenloser Integer-Wert interpretiert, es können also theoretisch bis zu 64 KBytes auf einmal kopiert werden.
* Achtung: Es wird weder eine Normalisierung der Zeiger noch eine Überprüfung auf Offset-Überlauf durchgeführt!
=== strChrPos(str, c) ===
Die Funktion ermittelt die Position eines Zeichens innerhalb einer Zeichenkette.
Argumente:
* str: Zeichenkette, in der nach einem Zeichen gesucht werden soll
* c: Zeichen, nach dem gesucht werden soll
Rückgabewert: Position des ersten Auftretens des Zeichens in str; -1, wenn das Zeichen nicht gefunden wurde
=== strCmp(str1,str2) ===
Die Funktion führt einen byteweisen Vergleich zweier Zeichenketten durch.
Argumente:
* str1: linker Operand
* str2: rechter Operand
Rückgabewert: -1 für ''str1 < str2'', 1 für ''str1 > str2'', 0 für ''str1 = str2''
=== strDelete(str, pos, length) ===
Die Funktion löscht Zeichen aus einer Zeichenkette.
Argumente:
* str: Zeichenkette, aus der Zeichen gelöscht werden sollen
* pos: Indexposition des ersten zu löschenden Zeichens
* length: maximale Anzahl zu löschender Zeichen
Rückgabewert: Anzahl tatsächlich gelöschter Zeichen
Hinweise:
* Bei einem negativen Wert von ''length'' werden alle Zeichen ab ''pos'' bis zum Ende gelöscht.
* Das Löschen erfolgt "in place", d.h. es wird kein neuer String erzeugt, sondern die übergebene Zeichenkette selbst modifiziert.
=== strDeleteChr(str, chr, pos, length) ===
Die Funktion löscht alle Vorkommen des angegebenen Zeichens aus einer Zeichenkette oder Teilzeichenkette.
Argumente:
* str: Zeichenkette, aus der Zeichen gelöscht werden sollen
* chr: Zeichencode (integer) des Zeichens, das gelöscht werden soll
* pos: Start-Indexposition des Bereichs, in dem das Zeichen gelöscht werden soll
* length: Maximallänge des Bereichs, in dem das Zeichen gelöscht werden soll
Rückgabewert: Anzahl tatsächlich gelöschter Zeichen
Hinweise:
* Bei einem negativen Wert von ''length'' reicht der Löschbereich von ''pos'' bis zum Ende der Zeichenkette.
* Das Löschen erfolgt "in place", d.h. es wird kein neuer String erzeugt, sondern die übergebene Zeichenkette selbst modifiziert.
=== strInsert(str,pos,insertion) ===
Die Funktion fügt eine Zeichenkette an der angegebenen Position in eine andere Zeichenkette ein.
Argumente:
* str: Adresse der String-Variablen, die als Ziel der Einfügeoperation dient
* pos: Indexposition, an der die Einfügung vorgenommen werden soll
* insertion: einzufügende Zeichenkette
Rückgabewert: Adresse des ersten Zeichens der Ziel-Zeichenkette nach dem Einfügen
Hinweise:
* Die Adresse der Ziel-Zeichenkette (Argument ''str'') kann mit der ''LOC''-Funktion ermittelt werden.
* Wenn der Wert von ''pos'' kleiner als Null ist oder die Länge von ''str'' übersteigt, wird ''insertion'' an das Ende von ''str'' angehängt.
=== strLen(str) ===
Die Funktion bestimmt die Länge der übergebenen Zeichenkette.
Argument: Zeichenkette, deren Länge werden soll
Rückgabewert: Anzahl der Zeichen in ''str''
Hinweis: Die Funktion verhält sich wie die Standardfunktion LEN, akzeptiert jedoch als Argument statt einer Stringvariablen oder -konstanten auch einen Integer-Wert, der den Offset des ersten Zeichens eines Strings im Datensegment angibt.
=== strLower(str) ===
Das Unterprogramm wandelt alle Großbuchstaben (A-Z) der übergebenen Zeichenkette in Kleinbuchstaben um.
Argument: Zeichenkette, die modifiziert werden soll.
Rückgabewert: keiner
Hinweis: Die Umwandlung erfolgt "in place", d.h. es wird kein neuer String erzeugt, sondern die übergebene Zeichenkette selbst modifiziert.
=== strReplace(strloc,search,rep) ===
Die Funktion ersetzt alle Vorkommen einer Teilzeichenkette durch eine andere Zeichenkette.
Argumente:
* strloc: Adresse der String-Variablen, die als Ziel der Operation dient
* search: zu ersetzende Teilzeichenkette
* rep: Ersatzzeichenkette
Rückgabewert: Anzahl der durchgeführten Ersetzungen
Hinweise:
* Die Adresse der Ziel-Zeichenkette (Argument ''strloc'') kann mit der ''LOC''-Funktion ermittelt werden.
* Wenn die Länge von ''rep'' nicht größer ist als die von ''search'', so wird die Ersetzung "in place" durchgeführt.
=== strReplaceChr(str,search,rep) ===
Die Funktion ersetzt alle Vorkommen eines Zeichens innerhalb einer Zeichenkette durch ein anderes Zeichen.
Argumente:
* str: Zeichenkette, die modifiziert werden soll
* search: Zeichencode des zu ersetzenden Zeichens (integer)
* rep: Zeichencode des Ersatzzeichens (integer)
Rückgabewert: Anzahl der durchgeführten Ersetzungen
Hinweis: Das Ersetzen erfolgt "in place", d.h. es wird kein neuer String erzeugt, sondern die übergebene Zeichenkette selbst modifiziert.
=== strStrPos(str, search) ===
Die Funktion sucht innerhalb einer Zeichenkette nach einer Teilzeichenkette.
Argumente:
* str: Zeichenkette, in der gesucht werden soll
* search: zu suchende Teilzeichenkette
Rückgabewert: Position von ''search'' in ''str'' bei Erfolg, sonst -1
=== strTok(str,resloc,delimit) ===
Die Funktion erlaubt das schrittweise Zerlegen einer Zeichenkette in Token.
Dazu wird die Zeichenkette nach dem ersten Vorkommen eines Trennzeichens durchsucht. Enthält sie ein Trennzeichen, wird die Teilzeichenkette vor dem Trennzeichen im Ergebnispuffer abgelegt; ist kein Trennzeichen enthalten, wird als Ergebnis
die ganze Zeichenkette (als einzelnes Token gespeichert.
Argumente:
* str: Zeichenkette, die zerlegt werden soll
* resloc: Adresse der Puffervariablen, in der das Ergebnis-Token abgelegt werden soll
* delimit: Liste der zum Zerlegen verwendeten Trennzeichen (als Zeichenkette)
Rückgabewert:\\
Startadresse des hinter dem gefundenen Trennzeichen verleibenden Restes der Zeichen, falls ein Trennzeichen gefunden
wurde; andernfalls 0.
Hinweise:
* Der Ergebnispuffer (adressiert durch resloc) muss eine String-Variable im Datensegment sein.
* Wenn der Rückgabewert der Funktion nicht 0 ist, so kann dieser Wert als Argument str für einen nachfolgenden Aufruf der Funktion verwendet werden, um ein weiters Token abzuspalten.
Beispiel:
txt$ = "This text consists of multiple words."
buf$ = ""
delimit$ = " ."
integer s, bloc
bloc = loc(buf$);
s = call_StrTok(txt$,bloc,delimit$)
while s <> 0
print buf$
s = call_StrTok(s,bloc,delimit$)
wend
end
=== strUpper(str) ===
Das Unterprogramm wandelt alle Kleinbuchstaben (a-z) der übergebenen Zeichenkette in Großbuchstaben um.
Argument: Zeichenkette, die modifiziert werden soll.
Rückgabewert: keiner
Hinweis: Die Umwandlung erfolgt "in place", d.h. es wird kein neuer String erzeugt, sondern die übergebene Zeichenkette selbst modifiziert.
==== Bibliothek FILES.LTB ====
Diese Bibliothek stellt zusätzliche Funktionen zum Umgang mit Binärdateien bereit, wobei Handle-basierte DOS-Aufrufe verwendet werden.
Alle Funktionen dieser Bibliothek legen im Falle eines Ausführungsfehlers den DOS-Fehlercode in der globalen (Integer-) Variablen FILE_ERROR ab.
Die Funktionen [[#fseek(fhandle,smode,offset)|fseek]] und [[#fseek_f(fhandle,smode,offslow,offshigh)|fseek_f]] belegen außerdem eine globale Variable ''seek_pos'' mit der Dateiposition. Diese Position ist 32 Bit breit und wird auf ein zweielementiges Integer-Feld abgebildet. Dabei beinhaltet ''seek_pos(0)'' den niederwertigen und ''seek_pos(1)'' den höherwertigen Teil des Wertes.
Darüber hinaus werden folgende Konstanten definiert:
* Dateiattribute (Bitflags, OR-kombinierbar)
* _fattr_r 1 (read only)
* _fattr_h 2 (hidden)
* _fattr_s 4 (system)
* _fattr_l 8 (volume label)
* _fattr_a 16 (archive flag)
* Datei-Fehlercodes
* _fsuccess 0
* _ferr_invalid_func 1
* _ferr_no_file 2
* _ferr_no_path 3
* _ferr_no_handle 4
* _ferr_acc_denied 5
* _ferr_inv_handle 6
* Modi zum Öffnen einer Datei
* _fopen_r 0 (open for read)
* _fopen_w 1 (open for write)
* _fopen_rw 2 (open for read and write)
*_ fopen_a 3 (open for append)
* Modi für Seek-Funktionen
* _fseek_start 0 (seek from start)
* _fseek_rel 1 (seek relative to current position)
* _fseek_end 2 (seek from end)
* DOS-Funktionsnummern
* _dos_fcreate &3c (create file)
* _dos_fopen &3d (open file or device)
* _dos_fclose &3e (close file)
* _dos_fread &3f (read from file/device)
* _dos_fwrite &40 (write to file/device)
* _dos_fseek &42 (file seek)
**Enthaltene Unterprogramme/Funktionen**
=== fopen(fileName, mode) ===
Die Funktion öffnet eine Datei oder ein Gerät (Zeichentreiber).
Argumente:
* fileName: Name (ggf. mit Pfad) der zu öffnenden Datei
* mode: Modus, in dem die Datei geöffnet werden soll (_fopen_r, _fopen_rw, _fopen_w oder _fopen_a)
Rückgabewert: Bei Erfolg Datei-Handle (Kanalnummer), sonst -1.
Hinweis: Eine mit ''fopen'' geöffnete Datei sollte stets mit ''fclose'' explizit geschlossen werden.
=== fcreate(fileName, attributes) ===
Die Funktion legt eine neue Datei an oder schneidet eine bereits existierende auf die Länge Null ab.
Argumente:
* fileName: Name (ggf. mit Pfad) der anzulegenden Datei
* attributes: Bitmaske als OR-Verknüpfung der Dateiattribute (_fattr_?)
Rückgabewert: 0 bei Erfolg, sonst Fehlercode
Hinweise:
* Die Funktion kann nicht mit dem Attribut _fattr_l (Volume Label) verwendet werden.
* Die Anwendung auf eine existierende schreibgeschützte Datei führt zu einem Fehler.
* Nach erfolgreicher Ausführung ist die angelegte Datei geschlossen und muss mit ''fopen'' für den Zugriff explizit geöffnet werden.
=== fclose(fhandle) ===
Die Funktion schließt eine zuvor mit ''fopen'' geöffnete Datei.
Argument: Handle (Kanalnummer) der zu schließenden Datei.
Rückgabewert: 0 bei Erfolg, sonst Fehlercode
=== fread_f(fhandle, nbytes, bufoffs, bufseg) ===
Die Funktion liest Daten aus einer geöffneten (Binär-)Datei in einen per FAR-Zeiger adressierten Puffer.
Argumente:
* fhandle: Handle (Kanalnummer) einer geöffneten Datei oder eines Geräts
* nbytes: maximale Anzahl der zu lesenden Bytes
* bufoffs: Offset-Adresse des Datenpuffers
* bufseg: Segment-Adresse des Datenpuffers
Rückgabewert: Anzahl der gelesenen Bytes (0 bei Fehler)
Hinweise:
* ''nbytes'' wird als vorzeichenloser Integer-Wert repräsentiert. Somit können theoretisch Datenblöcke bis zu 64 KBytes gelesen werden.
* Auch der Rückgabewert ist streng genommen vorzeichenlos. Bei Blockgrößen über 32 KBytes sollte er deshalb nicht als negativer Wert fehlinterpretiert werden.
* Das aufrufende Programm ist dafür verantwortlich, einen hinreichend großen Datenpuffer bereitzustellen. Die Funktion selbst kann dessen tatsächliche Größe nicht überprüfen und überschreibt schlimmstenfalls andere Speicherbereiche.
* Die Funktion schließt die Datei nach Ausführung nicht, sondern verschiebt lediglich deren internen Datenzeiger um die Anzahl der gelesenen Bytes. Sie kann also mehrfach hintereinander aufgerufen werden, um den Inhalt einer Datei stückweise zu lesen. Das Dateiende ist erreicht (die Datei vollständig gelesen), wenn der Rückgabewert kleiner als ''nbytes'' ist.
=== fread(fhandle, nbytes, buf) ===
Die Funktion liest Daten aus einer geöffneten (Binär-)Datei in einen per NEAR-Zeiger adressierten Puffer innerhalb des Datensegments.
Argumente:
* fhandle: Handle (Kanalnummer) einer geöffneten Datei oder eines Geräts
* nbytes: maximale Anzahl der zu lesenden Bytes
* buf: Adresse des Datenpuffers
Rückgabewert: Anzahl der gelesenen Bytes (0 bei Fehler)
Hinweise:
* ''nbytes'' wird als vorzeichenloser Integer-Wert repräsentiert. Somit können theoretisch Datenblöcke von mehr als 32 KBytes gelesen werden.
* Auch der Rückgabewert ist streng genommen vorzeichenlos. Bei Blockgrößen über 32 KBytes sollte er deshalb nicht als negativer Wert fehlinterpretiert werden.
* Das aufrufende Programm ist dafür verantwortlich, einen hinreichend großen Datenpuffer bereitzustellen. Die Funktion selbst kann dessen tatsächliche Größe nicht überprüfen und überschreibt schlimmstenfalls andere Speicherbereiche.
* Die Funktion schließt die Datei nach Ausführung nicht, sondern verschiebt lediglich deren internen Datenzeiger um die Anzahl der gelesenen Bytes. Sie kann also mehrfach hintereinander aufgerufen werden, um den Inhalt einer Datei stückweise zu lesen. Das Dateiende ist erreicht (die Datei vollständig gelesen), wenn der Rückgabewert kleiner als ''nbytes'' ist.
=== fwrite_f(fhandle,nbytes,bufoffs,bufseg) ===
Die Funktion schreibt Daten aus einem per FAR-Zeiger adressierten Puffer in eine geöffnete (Binär-)Datei.
Argumente:
* fhandle: Handle (Kanalnummer) einer geöffneten Datei oder eines Geräts
* nbytes: maximale Anzahl der zu schreibenden Bytes
* bufoffs: Offset-Adresse des Datenpuffers
* bufseg: Segment-Adresse des Datenpuffers
Rückgabewert: Anzahl der geschriebenen Bytes (0 bei Fehler)
Hinweise:
* ''nbytes'' wird als vorzeichenloser Integer-Wert repräsentiert. Somit können theoretisch Datenblöcke bis zu 64 KBytes geschrieben werden.
* Auch der Rückgabewert ist streng genommen vorzeichenlos. Bei Blockgrößen über 32 KBytes sollte er deshalb nicht als negativer Wert fehlinterpretiert werden.
* Die Funktion schließt die Datei nach Ausführung nicht, sondern verschiebt lediglich deren internen Datenzeiger um die Anzahl der geschriebenen Bytes. Sie kann also mehrfach hintereinander aufgerufen werden, um den Inhalt einer Datei stückweise zu schreiben.
=== fwrite(fhandle,nbytes,buf) ===
Die Funktion schreibt Daten aus einem per NEAR-Zeiger adressierten Puffer in eine geöffnete (Binär-)Datei.
Argumente:
* fhandle: Handle (Kanalnummer) einer geöffneten Datei oder eines Geräts
* nbytes: maximale Anzahl der zu schreibenden Bytes
* buf: Adresse des Datenpuffers (Offset im Datensegment)
Rückgabewert: Anzahl der geschriebenen Bytes (0 bei Fehler)
Hinweise:
* ''nbytes'' wird als vorzeichenloser Integer-Wert repräsentiert. Somit können theoretisch Datenblöcke von mehr als 32 KBytes geschrieben werden.
* Auch der Rückgabewert ist streng genommen vorzeichenlos. Bei Blockgrößen über 32 KBytes sollte er deshalb nicht als negativer Wert fehlinterpretiert werden.
* Die Funktion schließt die Datei nach Ausführung nicht, sondern verschiebt lediglich deren internen Datenzeiger um die Anzahl der geschriebenen Bytes. Sie kann also mehrfach hintereinander aufgerufen werden, um den Inhalt einer Datei stückweise zu schreiben.
=== fseek(fhandle,smode,offset) ===
Die Funktion ändert die Lese- bzw. Schreibposition in einer göffneten Datei.
Argumente:
* fhandle: Handle (Kanalnummer) einer geöffneten Datei
* smode: Modus
* _fseek_start - Positionierung relativ zum Dateianfang
* _fseek_rel - Positionierung relativ zur aktuellen Position
* _fseek_end - Positionierung relativ zum Dateiende
* offset: Anzahl von Bytes, um die die Position geändert werden soll
Rückgebewert: 0 bei Erfolg, sonst Fehlercode
Hinweise:
* Der Wert von ''offset'' ist ein vorzeichenbehafteter Integer. Somit kann man die Position um maximal 32K ändern.
* Im Modus ''_fseek_end'' wird die Position vom Dateiende um ''offset'' Bytes in Richtung Dateianfang verschoben. In den anderen Modi erfolgt die Verschiebung in Richtung Dateiende (bei einem positiven Offset, sonst umgekehrt).
* Es erfolgt keine Prüfung, ob die Position über die Dateigrenze hinaus verschoben wird. Bei einer Verschiebung vor den Dateianfang können bei nachfolgenden Schreibzugriffen Fehler in der Dateistruktur entstehen. Bei einer Verschiebung hinter das Dateiende wird die Datei vergrößert und es entsteht ein Bereich, der mit zufälligem Inhalt gefüllt ist.
* Wird ''offset=0'' angegeben, so bewirkt
* ''smode=_fseek_st''art eine Positionierung auf den Dateianfang,
* ''smode=_fseek_end'' eine Positionierung auf das Dateiende und
* ''smode=_fseek_rel'' keine Positionsänderung.
* Bei erfolgreicher Ausführung wird die aktuelle Dateiposition in der globalen Variablen ''seek_pos'' abgelegt, wobei ''seek_pos(0)'' den niederwertigen und ''seek_pos(1)'' den höherwertigen Teil enthält (die Dateiposition ist ein 32-Bit-Integer). Somit kann man die Angabe von ''offset=0'' auch nutzen, um die aktuelle Position (mit ''smode=_fseek_rel'') bzw. die Dateilänge (mit ''smode=_fseek_end'') zu ermitteln.
=== fseek_f(fhandle,smode,offslow,offshigh) ===
Die Funktion ändert die Lese- bzw. Schreibposition in einer göffneten Datei, wobei ein 32-Bit-Offset verwendet wird.
Argumente:
* fhandle: Handle (Kanalnummer) einer geöffneten Datei
* smode: Modus
* _fseek_start - Positionierung relativ zum Dateianfang
* _fseek_rel - Positionierung relativ zur aktuellen Position
* _fseek_end - Positionierung relativ zum Dateiende
* offslow: Anzahl von Bytes, um die die Position geändert werden soll (niederwertiger Teil)
* offshigh: Anzahl von Bytes, um die die Position geändert werden soll (höherwertiger Teil)
Rückgebewert: 0 bei Erfolg, sonst Fehlercode
Hinweise:
* Die Offset-Wert ist ein vorzeichenbehafteter 32-Bit-Integer. Somit kann man die Positionsverschiebunf theoretisch maximal +/-2^31 betragen. Weil Tokiwa-Basic keinen integralen 32-Bit-Integer kennt, ist eine Aufteilung auf zwei Argumente nötig.
* Bis auf den größeren möglichen Offset entspricht das Verhalten der Funktion dem für ''[[#fseek(fhandle,smode,offset)|fseek]]'' beschriebenen.
==== Bibliothek DIRS.LTB ====
Diese Bibliothek stellt Unterprogramme und Funktionen für DOS-basierte Dateisystem- und Verzeichnisoperationen zur Verfügung.
Für die Datei-Suchfunktionen wird eine globale Puffervariable ''dos_s_rec'' von 44 Bytes Länge angelegt.\\
Außerdem definiert die Bibliothek folgende globale Konstanten:
* DOS-Funktionsnummern
* _dos_set_drive &e (set current drive)
* _dos_get_drive &19 (get current drive)
* _dos_set_dta &1a (set DTA address)
* _dos_get_dta &2f (get DTA address)
* _dos_mkdir &39 (make directory)
* _dos_rmdir &3a (remove directory)
* _dos_chdir &3b (change directory)
* _dos_del_file &41 (delete file)
* _dos_get_dir &47 (get current directory)
* _dos_find_first &4e (find first)
* _dos_find_next &4f (find next)
* _dos_get_attr &4300 (get file attributes)
* _dos_set_attr &4301 (set file attributes)
* _dos_rename_fd &56 (rename file or directory)
* Fehlercodes (als Rückgebewerte von Funktionen)
* _dsuccess 0 (kein Fehler)
* _derr_no_file 2
* _derr_no_path 3
* _derr_acc_denied 5
* _derr_inv_drive 15
* _derr_cant_delete 16
* _derr_cant_move 17
* _derr_no_entries 18
* Dateiattribute (Bitflags, OR-verknüpfbar)
* _dfattr_r 1 (read only)
* _dfattr_h 2 (hidden)
* _dfattr_s 4 (system)
* _dfattr_l 8 (volume label)
* _dfattr_a 16 (archive flag)
* Byte-Offsets der Elemente in ''dos_s_rec''
* _dos_srec_attr 21
* _dos_srec_time 22
* _dos_srec_date 24
* _dos_srec_sizelo 26
* _dos_srec_sizehi 28
* _dos_srec_name 30
* Dateiattribut-Flags zur Verwendung mit [[#findFirst(pattern,attr,resloc)|findFirst]]
* _sattr_hidden 2
* _sattr_system 4
* _sattr_vlabel 8
* _sattr_dir &10
* _sattr_all &3f
**Unterprogramme und Funktionen**
=== setCurrentDrive(drv) ===
Die Funktion legt das aktive Laufwerk fest.
Argument: Laufwerk, das aktiv gesetzt werden soll (angegeben als Index oder Laufwerksbuchstabe)
Rückgabewert: aktives Laufwerk
Hinweise:
* Der Argumenrwert ist eine Zahl (Laufwerksindex, wobei 0 für Laufwerk A, 1 für B usw. steht) oder ein Groß- bzw. Kleinbuchstabe (Laufwerksbuchstabe)
* Der Rückgabewert ist eine Zahl, wenn als Argument ein Index (also ein Wert zwischen 0 und 25) angegeben wurde, oder ein Groß- bzw. Kleinbuchstabe, wenn das Argument als Buchstabe angegeben wurde.
* Der Aufrufer kann den Erfolg der Operation prüfen, indem er den Rückgabewert mit dem übergebenen Argumentwert vergleicht.
=== getCurrentDrive ===
Die Funktion ermittelt das aktuell aktive Laufwerk.
Argumente: keine
Rückgabewert: aktives Laufwerk (als Großbuchstabe)
=== mkDir(path) ===
Die Funktion legt ein Verzeichnis entsprechend dem angegebenen Pfad an.
Argument: Name des anzulegenden Verzeichnisses (relativer oder absoluter Pfad)
Rückgabewert: 0 bei Erfolg, sonst Fehlercode
Hinweise:
* Der als Argument übergebene Pfad kann absolut oder relativ zum aktuellen Verzeichnis angegeben werden.
* Eine absolute Pfadangebe kann eine Laufwerksangabe enthalten, die nicht mit dem aktuellen (aktiven) Laufwerk übereinstimmen muss.
* Es lässt sich (wie beim mkdir-Befehl von DOS) nur ein einzelnes Verzeichnis anlegen, d.h. alle übergeordneten Verzeichnisse müssen bereits existieren.
=== rmDir(path) ===
Die Funktion löscht ein (leeres) Verzeichnis.
Argument: Name des zu löschenden Verzeichnisses (relativer oder absoluter Pfad)
Rückgabewert: 0 bei Erfolg, sonst Fehlercode
Hinweise:
* Der als Argument übergebene Pfad kann absolut oder relativ zum aktuellen Verzeichnis angegeben werden.
* Eine absolute Pfadangebe kann eine Laufwerksangabe enthalten, die nicht mit dem aktuellen (aktiven) Laufwerk übereinstimmen muss.
* Die Funktion kann (wie der rmdir-Befehl von DOS) nur einzelne Verzeichnisse, keine vollständigen Pfade löschen.
* Das zu löschende Verzeichnis muss leer sein und darf nicht schreibgeschützt sein.
=== delFile(fpath) ===
Die Funktion löscht die angegebene Datei.
Argument: Name der zu löschenden Datei (relativer oder absoluter Pfad)
Rückgabewert: 0 bei Erfolg, sonst Fehlercode
Hinweise:
* Der als Argument übergebene Pfad kann absolut oder relativ zum aktuellen Verzeichnis angegeben werden.
* Eine absolute Pfadangebe kann eine Laufwerksangabe enthalten, die nicht mit dem aktuellen (aktiven) Laufwerk übereinstimmen muss.
* Im Unterschied zum DOS-Befehl del kann nur eine einzelne Datei gelöscht wwrden; Wildchards (* oder ?) in der Pfadangabe sind nicht zulässig.
* Die zu löschende Datei darf nicht schreibgeschützt und nicht geöffnet sein.
=== setCwd(path) ===
Die Funktion setzt das aktuelle Arbeitsverzeichnis.
Argument: Name des Verzeichnisses, das als Arbeitsverzeichnis gesetzt werden soll (relativer oder absoluter Verzeichnispfad)
Rückgabewert: 0 bei Erfolg, sonst Fehlercode
Hinweise:
* Der als Argument übergebene Pfad kann absolut oder relativ zum aktuellen Verzeichnis angegeben werden.
* Falls der Verzeichnispfad eine Laufwerksangabe enthält, wird auch das aktive Laufwerk entsprechend gesetzt.
=== getCwd(pathloc) ===
Die Funktion bestimmt das aktuelle Arbeitsverzeichnis.
Argument: Adresse der Puffervariablen (String), in der das aktuelle Arbeitsverzeichnis abgelegt werden soll.
Rückgabewert: 0 bei Erfolg, sonst Fehlercode
Hinweise:
* Bei erfolgreicher Ausführung wird der vollständige Pfad des aktuellen Arbeitsverzeichnisses in der Puffervariablen abgelegt.
* Als Parameter muss die Adresse (bestimmbar mit der LOC-Funktion) des Puffers angegeben werden.
=== setDTA(offs, seg) ===
Das Unterprogramm verlegt das DTA auf die angegebene Adresse.
Argumente:
* offs: Offset-Adresse des DTA
* seg: Segment-Adresse des DTA
Rückgabewert: keiner
Hinweis:\\
Das DTA (Disk Transfer Area) ist ein Pufferbereich, der von den "altem" (CP/M-kompatiblen) DOS-Dateifunktionen sowie
von den Suchfunktionen (find first / find next) verwendet wird. Standardmäßig befindet sich dieser Bereich ab Offset
80H im PSP und teilt sich damit den Speicherbereich mit den auf der Kommandozeile übergebenen Parametern. Das temporäre Verlegen
dieses Bereichs kann sinnvoll sein, um beim Verwenden der genannten Funktionen die Parameter nicht zu überschreiben.\\
Die Funktionen [[#findFirst(pattern,attr,resloc)|findFirst]] und [[#findNext(resloc)|findNext]] dieser Bibliothek verlegen das DTA
temporär und beeinträchtigen so die Kommandozeilenparameter nicht.
=== getDTA(locoffs, locseg) ===
Das Unterprogramm bestimmt die aktuell gesetzte DTA-Adresse.
Argumente:
* locoffs: Adresse der Puffervariablen (Integer) für die Offset-Adresse des DTA
* locseg: Adresse der Puffervariablen (Integer) für die Segment-Adresse des DTA
=== findFirst(pattern,attr,resloc) ===
Die Funktion sucht den ersten Verzeichniseintrag, der dem angegebenen Suchmuster entspricht.
Argumente:
* pattern: Suchmuster (Zeichenkette); das Suchmuster kann eine relative oder absolute Pfadangabe (ggf. auch mit
Laufwerk) sowie im Dateinamens- und Erweiterungsteil die unter DOS üblichen Wildcards (* byw. ?) enthalten.
* attr: Attribute für die Suche; OR-Kombination der ''_sattr_xx''-Flags (siehe oben). Standardmäßig werden "normale" Dateien gefunden, mit Hilfe der Flags lassen sich zusätzlich Verzeichnisse, Volume-Labels und versteckte Dateien in die Suche einbeziehen.
* resloc: Adresse des Ergebnispuffers (Zeichenkettenvariable)
Rückgabewert: 0 bei Erfolg, sonst Fehlercode
Hinweise:
* Der Ergebnispuffer (''resloc'') muss im Datensegment liegen, die Adresse kann mit der LOC-Funktion bestimmt werden.
* Bei Erfolg (Rückgabewert 0, d.h. ein passender Eintrag wurde gefunden) wird der Eintragsname mit ggf. vorhandener Erweiterung, jedoch ohne Verzeichnispfad, in der durch ''resloc'' adressierten Variablen abgelegt.
=== findNext(resloc) ===
Die Funktion sucht den nächsten Verzeichniseintrag, der dem beim vorangegangenen Aufruf
von [[#findFirst(pattern,attr,resloc)|findFirst]] angegebenen Suchmuster entspricht.
Argument: Adresse des Ergebnispuffers (Zeichenkettenvariable)
Rückgabewert: 0 bei Erfolg, sonst Fehlercode
Hinweise:
* Der Ergebnispuffer (''resloc'') muss im Datensegment liegen, die Adresse kann mit der LOC-Funktion bestimmt werden.
* Bei Erfolg (Rückgabewert 0, d.h. ein passender Eintrag wurde gefunden) wird der Eintragsname mit ggf. vorhandener Erweiterung,
jedoch ohne Verzeichnispfad, in der durch ''resloc'' adressierten Variablen abgelegt.
=== getFileSize ===
Die Funktion bestimmt die Größe der zuletzt mit ''findFirst'' bzw ''findNext'' gefundenen Datei.
Argumente: keine
Rückgabewert: Größe der Datei in Bytes
Hinweise:
* Die Dateigröße wird aus der Pseudo-Struktur ''_dos_s_rec'' ausgelesen. Deshalb muss vor dem Aufruf der Funktion ein Aufruf von ''findFirst'' bzw. ''findNext'' erfolgt sein.
* Weil der Rückgabewert vom Real-Typ ist, kann er wegen der begrenzten Genauigkeit der Zahldarstellung mit einem Fehler behaftet sein, falls die Dateigröße 1 GB überschreitet.
=== getFileAttr(fname) ===
Die Funktion bestimmt die Attribute einer Datei oder eines anderen Verzeichniseintrags.
Argument:\\
Name der Datei- bzw. des Eintrags, für die/den die Attribute bestimmt werden sollen. Der
Name kann eine absolute oder relative Pfadangabe beinhalten.
Rückgabewert: Bitset der Attribute (OR-Kombination aus ''_sattr_xx''-Flags)
Hinweis:\\
Im Falle eines Fehlers (z.B. wenn die Datei nicht existiert) ist der Rückgabewert
größer als 255. Der um 256 verminderte Rückgabewert entspricht dann dem Fehlercode.
=== setFileAttr(fname,fattr) ===
Die Funktion legt die Attribute des angegebenen Verzeichniseintrags fest.
Argumente:
* fname: Name der Datei- bzw. des Eintrags, für die/den die Attribute festgelegt werden sollen. Der Name kann eine absolute oder relative Pfadangabe beinhalten.
* fattr: Bitset der Attribute (OR-Kombination aus ''_sattr_xx''-Flags)
Rückgabewert: 0 bei Erfolg, sonst Fehlercode
Hinweise:
* Das Setzen von Attributen ist nicht beliebig möglich. Welche Attribute gesetzt werden können, ist vom Typ des Verzeichniseintrags abhängig.
* Vorsicht: Es ist mit dieser Funktion grundsätzlich möglich, Dateieinträge in Vezeichniseinträge umzuwandeln (und umgekehrt). Ein Anwendungsprogramm sollte dies abfangen, um Fehler im Dateisystem zu verhindern.
=== renDirEntry(name,newname) ===
Die Funktion benennt einen Verzeichniseintrag um.
Argumente:
* name: Bisheriger Name des Verzeichniseintrags (ggf. einschließlich Pfadangabe)
* newname: Neuer Name des Verzeichniseintrags (ggf. einschließlich Pfadangabe)
Rückgabewert: 0 bei Erfolg, sonst Fehlercode
Hinweis:\\
Die Funktion führt nur das Umbenennen eines Eintrags in der Verzeichnisstruktur durch, kein "echtes"
Kopieren oder Verschieben einer Datei. Deshalb dürfen ''name'' und ''newname'' nicht auf unterschiedliche Laufwerke verweisen.