30 KiB
Sprachreferenz Terminal Basic
Rekonstruierte Referenz des Dialekts (DOS-BASIC, Stand 1992: prozedurale BASIC-Familie mit Forms-Erweiterung). Dieses Dokument ist die verbindliche Grundlage für Frontend und Runtime. Offene Detailfragen sind ausgeräumt (Stand 2026-09-04); wo die Original-Dokumentation schweigt, steht an Ort und Stelle eine datierte Entscheidung mit Begründung.
Primärquellen: Original-Hilfedateien des Vorbilds als HTML unter
https://dos-help.soulsphere.org/ (qck.hlp Quick Reference, advr.hlp
Details, ener.hlp Fehlermeldungen; Vergleich PDS 7.1: bas7qck.hlp)
sowie das Original-README der Professional Edition. Aussagen ohne
ausgewiesene Entscheidung sind daraus belegt; die Themenlisten von
bas7advr.hlp und qb45advr.hlp bilden zusammen das
Vollständigkeits-Inventar (docs/inventar.md).
Guiding Principle: Die Original-Dokumentation führt. Jedes dort dokumentierte Sprachelement wird unterstützt oder — nur nach expliziter Non-Feature-Entscheidung des Projektinhabers — mit einer klaren Fehlermeldung abgewiesen. Bewusste Abweichungen und Non-Features stehen am Ende dieses Dokuments; nur diese Liste rechtfertigt Abweisungen.
1. Lexik
- Zeilenorientiert. Eine logische Zeile enthält eine oder mehrere
Anweisungen, getrennt durch
:. Zeilenfortsetzung:_als letztes Zeichen (mit vorangehendem Leerzeichen/Tab) setzt die Zeile fort — im Vorbild für extern erstellten Code gedacht (der IDE-Editor fügt fortgesetzte Zeilen beim Laden zusammen); Terminal Basic akzeptiert es überall. - Zeilennummern sind optional und wirken als Labels. Alphanumerische
Labels enden mit
:am Zeilenanfang (Fehler:). - Kommentare:
REM(ganze Anweisung) und'(bis Zeilenende).REM/'am Zeilenanfang mit$STATIC/$DYNAMIC/$INCLUDE: 'datei'sind Metabefehle. - Bezeichner: Buchstabe, dann Buchstaben/Ziffern/
./_, max. 40 Zeichen, case-insensitiv. Optionales Typ-Suffix als letztes Zeichen. (_in Bezeichnern ist eine dokumentierte Neuerung des Vorbilds.) - Typ-Suffixe:
%INTEGER ·&LONG ·!SINGLE ·#DOUBLE ·$STRING ·@CURRENCY.name,name%,name$sind verschiedene Variablen. - Keywords sind reserviert und case-insensitiv; die IDE normalisiert auf Großschreibung.
- Numerische Literale: dezimal (
123,1.5,1.5E3,1D3für DOUBLE), hexadezimal&HFF, oktal&O777; Suffixe erzwingen den Typ (10%,10&,1.5!,1.5#,2.5@). Ohne Suffix gilt: Ganzzahl im INTEGER-Bereich → INTEGER; Hex/Oktal ohne&-Suffix → 16 Bit (INTEGER), mit&→ LONG;E-Exponent → SINGLE,D-Exponent → DOUBLE; Dezimalpunkt-Wert: Entscheidung (2026-09-02): bis 7 signifikante Stellen → SINGLE, darüber → DOUBLE. (Die Original-Hilfe nennt widersprüchlich eine 15-Stellen-Schwelle, die SINGLE-Präzision verlöre; wir legen die Schwelle auf die SINGLE-Genauigkeit — präzisionserhaltende Auslegung.) Ganzzahl außerhalb des LONG-Bereichs wird Gleitkommawert (kein Fehler). - String-Literale:
"…"; doppeltes""ergibt ein Anführungszeichen.
2. Typsystem
| Typ | Suffix | Repräsentation | Wertebereich |
|---|---|---|---|
| INTEGER | % |
i16 | −32 768 … 32 767 |
| LONG | & |
i32 | −2 147 483 648 … 2 147 483 647 |
| SINGLE | ! |
f32 | ±3.4E38 |
| DOUBLE | # |
f64 | ±1.8E308 |
| STRING | $ |
dynamischer Unicode-String | Länge 0 … 32 767 Zeichen |
| STRING * n | — | fester String, n Zeichen | nur in TYPE/DIM |
| CURRENCY | @ |
i64, Festkomma ×10 000 | ±922 337 203 685 477.5807 |
- Benutzerdefinierte Typen:
TYPE name … END TYPEmit Elementen fester Größe (numerische Typen,STRING * n, verschachtelte TYPEs). Kein dynamischer STRING in TYPE. - Implizite Deklaration: Erstverwendung deklariert die Variable. Ohne
Suffix gilt der Standardtyp SINGLE, änderbar per
DEFINT/DEFLNG/DEFSNG/DEFDBL/DEFSTR/DEFCUR a–z(buchstabenbereichsweise, wirkt pro Modul/Prozedur ab Deklaration). OPTION EXPLICITexistiert (Neuerung des Vorbilds gegenüber der QB/PDS-Familie): erzwingt Deklaration aller Variablen (über COMMON, CONST, DEF FN, DIM, FUNCTION, REDIM, SHARED, STATIC oder SUB); gilt auch für das Direktfenster.- Arrays:
DIM a(10),DIM a(1 TO 10, 0 TO 5). Untergrenze standardmäßig 0, perOPTION BASE 1änderbar.$STATIC/$DYNAMICbzw. Kontext bestimmen statisch/dynamisch;REDIM(dynamisch, löscht Inhalt),ERASE(reinitialisiert statisch / gibt dynamisch frei). Max. 60 Dimensionen, Indizes −32 767 … 32 767 (mitTO).LBOUND/UBOUNDliefern Grenzen. (DOS-Speichergrenzen der Arrays — 64K/128K-Regeln — übernehmen wir nicht.) - Konvertierung: implizit zwischen numerischen Typen mit Rundung
(Banker's Rounding bei
CINT/CLNGund Zuweisung an Ganzzahl); Überlauf → Fehler 6. Keine implizite Konvertierung Zahl ↔ String (Fehler 13, Type mismatch). Die vollständige Konvertierungsmatrix (Ergebnistypen der Operatoren, Rundungs- und Überlaufregeln, Textdarstellung) steht in docs/tbvm-design.md und ist übertests/compat/konvertierung.basausführbar verankert (Phase 2, 2026-09-02).
3. Deklarationen und Sichtbarkeit
DIM [SHARED] var[(dims)] [AS typ]—AS-Klausel: INTEGER, LONG, SINGLE, DOUBLE, STRING, STRING * n, CURRENCY, benutzerdefinierter Typ.COMMON [SHARED] [/blockname/] liste— modulübergreifend (Kette CHAIN-kompatibel im Vorbild; ohneCHAINbleibtCOMMONdie Verknüpfung mehrerer Module eines Projekts — geklärt mit der Projektverwaltung in Phase 5).SHARED(in Prozedur): Zugriff auf Modulebene-Variablen.STATIC(in Prozedur): Variablen behalten Werte zwischen Aufrufen;STATIC-Attribut anSUB/FUNCTIONmacht alle lokalen Variablen statisch.CONST name = ausdruck— Konstanten (konstante Ausdrücke zur Compilezeit).DECLARE SUB/FUNCTION name (parameter)— Prototyp; die IDE erzeugt sie automatisch beim Speichern.
4. Operatoren (nach Priorität, hoch → niedrig)
^(Potenz)- unäres
- *,/(Fließkommadivision)\(Ganzzahldivision; Operanden werden gerundet auf INTEGER/LONG)MOD(Ganzzahlrest, Vorzeichen wie Dividend)+,-(+auch String-Verkettung)- Vergleiche
= <> < > <= >=(Zahlen und Strings; Strings codepoint-weise — Abweichung, s. u.) NOTANDORXOREQVIMP
Logische Operatoren sind bitweise auf Ganzzahlen; Vergleichsergebnis ist INTEGER −1 (wahr) / 0 (falsch).
5. Kontrollfluss
IF b THEN … [ELSE …](einzeilig) und Block-IF … THEN / ELSEIF / ELSE / END IFSELECT CASE ausdruckmitCASE wert,CASE a TO b,CASE IS >= x,CASE ELSEFOR i = a TO b [STEP s] … NEXT [i](Grenzen werden einmal ausgewertet; Schleifenvariable numerisch)DO [WHILE|UNTIL b] … LOOP [WHILE|UNTIL b],WHILE … WENDEXIT FOR / EXIT DO / EXIT SUB / EXIT FUNCTION / EXIT DEFGOTO ziel,GOSUB ziel/RETURN [ziel]ON n GOTO liste,ON n GOSUB liste(berechneter Sprung, 1-basiert; 0 oder > Anzahl: kein Sprung; negativ/>255: Fehler 5)END(Programmende),STOP(Unterbrechung → im IDE-Kontext Debugger),SYSTEM(Programmende, im Vorbild „zurück zu DOS"). Runner-Verhalten (Entscheidung 2026-09-02): außerhalb der IDE beendetSTOPdas Programm mit der MeldungSTOP in line nund Exit-Code ≠ 0;END/SYSTEM/Programmende liefern Exit-Code 0.CONTexistiert nur als Direktmodus-Befehl der IDE (Phase 5) und ist nicht kompilierbar.SLEEP [sekunden],DO EVENTS/DOEVENTS(Ereignisse verarbeiten — zentral für Forms)
6. Prozeduren
SUB name (p1 AS t, p2(), …) [STATIC] … END SUB; AufrufCALL name(args)odername args(ohne Klammern).FUNCTION name (…) [STATIC] … name = wert … END FUNCTION; Typ über Suffix oderDEF…-Regel.- Parameterübergabe standardmäßig BYREF. Klammern um ein Argument
(
CALL f((x))) erzwingen Wertübergabe.BYVALnur inDECLAREfür externe Routinen (entfällt bei uns;BYVALallgemein zu erlauben wäre eine Erweiterung über den Kernstandard hinaus → Stufe 2, PLAN.md). - Arrays werden mit
name()übergeben, TYPEs BYREF. - Rekursion erlaubt (außer bei
STATIC-Semantik-Konflikten). DEF FNname (args) = ausdruckund Block-DEF FN … END DEF(mitEXIT DEF); AufrufFNname(…). Nur auf Modulebene definier- und nutzbar, nicht rekursiv, Argumente by value, keine Arrays/Records/ Fixed-Strings als Argumente.
7. Fehlerbehandlung
- Vollständige Syntax:
ON [LOCAL] ERROR {GOTO zeile/label | RESUME NEXT | GOTO 0}.LOCALinstalliert einen prozedurlokalen Handler; ohneLOCALgilt der Handler modulweit.GOTO 0deaktiviert (in einem aktiven Handler: Fehler weiterreichen → Programmabbruch). - Im Handler:
RESUME(fehlerauslösende Anweisung wiederholen),RESUME NEXT,RESUME zeile/label. ERR(Code),ERL(Zeilennummer, nur numerische Zeilennummern!),ERROR n(Fehler auslösen). Fehlernummer 105 ist im Vorbild intern reserviert und sollte nicht viaERROR nverwendet werden.- Fehler im aktiven Handler → sofortiger Abbruch. Fehler ohne Handler → Abbruch mit Meldung „Fehlertext in Zeile n" bzw. Debugger in der IDE.
- Fehlerkatalog: klassische Codes 1–76, ISAM-Codes 80–89, Forms-Codes
260–480 — vollständig implementiert in
tb-runtime/src/errors.rs.
8. Ereignis-Traps (klassisch, ohne Forms)
Vorhanden im Vorbild: ON COM/KEY/PEN/PLAY/SIGNAL/STRIG/TIMER/UEVENT(…) GOSUB label mit Steueranweisungen … ON/OFF/STOP, dazu das
EVENT-Statement (auch für Forms-Ereignisse) und SetUEvent.
Timer-Events und Trapping sind ausgesetzt, solange ein Menü-Control den
Fokus hat. Für Terminal Basic relevant: TIMER, KEY, UEVENT,
SIGNAL; COM/PEN/PLAY/STRIG: Nicht-Ziel (Fehler 73).
Traps und Wertebereiche
| Anweisung | Wertebereich | Quelle |
|---|---|---|
ON TIMER(n&) GOSUB ziel |
n& = 1–86 400 Sekunden |
verstrichene Zeit |
ON KEY(n%) GOSUB ziel |
n% = 0 (alle), 1–10 (F1–F10), 11 ↑, 12 ←, 13 →, 14 ↓, 15–25 (benutzerdefiniert), 30–31 (F11–F12) |
Tastendruck |
ON UEVENT GOSUB ziel |
— | SetUEvent |
ON SIGNAL(n%) GOSUB ziel |
n% = 1 (SIGINT), 2 (SIGTERM) |
Betriebssystem |
GOSUB 0 schaltet den jeweiligen Trap ab. Ein Wert außerhalb des
Bereichs wird namentlich abgewiesen — zur Übersetzungszeit, wenn er
konstant ist, sonst mit Fehler 5.
Maskierung. Je Quelle ON (zustellen), OFF (verwerfen — auch ein
unter STOP bereits gemerktes Ereignis) und STOP (höchstens eines
merken und beim nächsten ON zustellen). EVENT ON/EVENT OFF
klammern einen Abschnitt, in dem keine Ereignisse erkannt werden müssen;
ein EVENT STOP gibt es nicht.
Zustellpunkte. Anweisungsgrenze, DOEVENTS, während SLEEP und vor
blockierender Eingabe — sonst nirgends. Ein zugestelltes Ereignis
beendet ein laufendes SLEEP.
Wiedereintritt. Der Eintritt in einen Handler führt selbsttätig
STOP seiner Quelle aus, das RETURN selbsttätig ON — außer im
Handler stand ein ausdrückliches OFF, dann bleibt die Quelle aus.
Benutzerdefinierte Trap-Tasten. KEY n, CHR$(flag) + CHR$(scancode)
erklärt für n = 15–25, welche Taste der zugehörige ON KEY(n)-Trap
fängt — anders als für 1–10 und 30–31, wo dieselbe Anweisung ein Makro
zuweist. flag ist das Tastaturflagbyte (1 rechte Umschalttaste, 2 linke,
4 Strg, 8 Alt), scancode der Scancode der Taste. Beispiel: KEY 15, CHR$(4) + CHR$(30) fängt Strg+A.
Festlegungen ohne Beleg im Vorbild (2026-09-04; die Original-Hilfe verweist dazu auf ein nicht vorliegendes Kapitel des Programmer's Guide):
- Eine Taste mit aktivem
ON KEY-Trap erscheint nicht zusätzlich beiINKEY$/INPUT; sonst sähe ein Programm dieselbe Taste zweimal. - Sind mehrere Ereignisse zugleich fällig, gilt die Reihenfolge
KEY(aufsteigend nachn),TIMER,UEVENT,SIGNAL; zugestellt wird eines je Zustellpunkt. - Zugestellt wird an jeder Anweisungsgrenze, auch innerhalb von
SUB/FUNCTION; das Sprungziel liegt im Modulrumpf — dieselbe Regel wie beim modulweitenON ERROR. - Die Bits des Tastaturflagbytes folgen der BIOS-Belegung. Linke und rechte Umschalttaste sind im Terminal nicht unterscheidbar; beide Bits gelten gleich. NumLock und CapsLock werden ignoriert.
- Zeichen ohne Eintrag in der Scancode-Tabelle des Vorbilds können keinen benutzerdefinierten Trap auslösen.
9. Konsolen-E/A
PRINT [#n,] liste— Trennzeichen;(direkt anschließend) und,(nächste 14-Zeichen-Druckzone). Zahlen: führendes Leerzeichen bzw.-, nachgestelltes Leerzeichen. Abschluss ohne;/,→ Zeilenumbruch.PRINT USING "format"; liste— Formatzeichen (offizielle Liste): numerisch#Ziffer,.Dezimalpunkt,,Tausendertrennung,+Vorzeichen- position,-nachgestelltes Minus,$$führendes $,**Füllsterne,**$kombiniert,^^^^Exponent; String&ganz,!erstes Zeichen,\ \n Zeichen (Leerzeichen + 2);_Literal-Escape; alle anderen Zeichen literal.- Feldüberlauf (geklärt 2026-09-04): Passt ein Wert nicht in sein
Feld, wird er vollständig ausgegeben und die Ausgabe mit
%eingeleitet (PRINT USING "##"; 12345→%12345). Die Original-Hilfe listet das nicht; wir übernehmen das Verhalten der QB-Familie, weil ein stilles Abschneiden Zahlen verfälschen würde. - Vorzeichenangaben (
+vorn,+/-hinten) belegen eine eigene Position neben den Ziffernstellen;$$und**bringen ihre Stellen dagegen mit. - Die Formatzeichenkette wird wiederholt, solange Werte übrig sind. Eine Zeichenkette ohne Feld bei vorhandenen Werten löst Fehler 5 aus.
SetFormatCC(ländercode)setzt das Zeichen für$$. Nur wenige Codes sind belegt (1 =$, 33 =F, 39 =L, 44 =£, 49 =DM, 81 =¥); alle übrigen behalten$— die Tabelle des Vorbilds ist nicht überliefert (dokumentierte Abweichung).
- Feldüberlauf (geklärt 2026-09-04): Passt ein Wert nicht in sein
Feld, wird er vollständig ausgegeben und die Ausgabe mit
INPUT ["prompt"{;|,}] var, …(mit;vor Prompt: kein „? ");LINE INPUT(ganze Zeile in String).INKEY$(nicht blockierend; "" wenn leer; erweiterte Tasten: 2-Zeichen-SequenzCHR$(0)+codeim Vorbild — Abweichung s. u.),INPUT$(n [,#f]).LOCATE [zeile][,spalte][,cursor an/aus][,start,ende],CSRLIN,POS(0)— arbeiten auf der tatsächlichen Bildschirmgröße (dynamisch, s. Abweichungen).COLOR [vg][,hg](vg 0–31: 16–31 = blinkend — bei uns als „hell" simuliert, Entscheidung 2026-09-02; hg 0–7),CLS,WIDTH(hebt den Puffer höchstens an, s. Abweichungen),VIEW PRINT oben TO unten(Scrollbereich).TAB(n),SPC(n)in PRINT-Listen.BEEP,SOUND freq, dauer(Terminal-Bell / Nicht-Ziel, s. Abweichungen),PLAY(Nicht-Ziel).- Funktionstasten-Makros (Umfang geklärt 2026-09-03 aus der
Original-Hilfe):
KEY n, text$belegt ein Makro.nist 1–10 für F1–F10 sowie 30 und 31 für F11/F12; andere Werte lösen Fehler 5 aus.text$wird nach 15 Zeichen abgeschnitten.KEY LISTgibt alle zwölf Makros untereinander aus.KEY ONblendet die Softkey-Zeile in der untersten Bildschirmzeile ein (Tastennummer plus die ersten sechs Zeichen des Makros),KEY OFFblendet sie aus. Solange sie sichtbar ist, endet der Scrollbereich darüber, damit die Ausgabe sie nicht überschreibt; ein danach gesetztesVIEW PRINThat Vorrang.KEY(n) ON|OFF|STOPmit Index ist Ereignissteuerung und kommt mit der Forms-Engine (Phase 4).- Abweichung: ein kompiliertes Programm startet mit leeren Makros; die Vorbelegung des Vorbilds gehörte zu dessen Interpreter-Oberfläche.
10. Datei-E/A
OPEN datei$ [FOR modus] [ACCESS zugriff] [lock] AS [#]n [LEN=reclen]Modi:INPUT,OUTPUT,APPEND(sequenziell),RANDOM(Standard),BINARY.CLOSE [#n, …],RESET(alle schließen).- Sequenziell:
PRINT #,PRINT # USING,WRITE #(CSV-artig, Strings in"…"),INPUT #,LINE INPUT #,EOF(n). - Random:
FIELD #n, breite AS var$…(klassisch) undGET/PUT #n [,satznr] [,var]mit TYPE-Variablen;LSET/RSETfür Feldpuffer. - Binary:
GET/PUT #n, [pos], var,SEEK #n, pos/SEEK(n),LOC(n),LOF(n). - Verwaltung:
NAME alt$ AS neu$,KILL datei$,FILES [muster$],CHDIR,MKDIR,RMDIR,FILEATTR,FREEFILE. - Pfade: plattformneutral;
/und\werden akzeptiert.
10a. ISAM (indizierter Satzzugriff)
ISAM der Professional-Edition des Vorbilds wird unterstützt (Entscheidung 2026-09-02). Das Dateiformat beschreibt dateiformate.md.
OPEN datenbank$ FOR ISAM typname tabellenname$ AS [#]nbindet eine Tabelle an eine Dateinummer; die Felder des benanntenTYPEsind ihre Spalten. Die Tabelle entsteht beim ersten Öffnen.CLOSElöst die Bindung; jede Operation außerhalb einer Transaktion ist für sich schon festgeschrieben. Eine laufende Transaktion lässtCLOSEunberührt — über ihr Ende entscheidenCOMMITTRANSundROLLBACK ALL; eine beim Programmende offene Transaktion bleibt wirkungslos.- Indizes:
CREATEINDEX [#]n, indexname$, eindeutig%, spalte$[, spalte$]…,DELETEINDEX [#]n, indexname$,SETINDEX [#]n[, indexname$],GETINDEX$(n).SETINDEXohne Namen wählt den NULL-Index (Einfügereihenfolge);GETINDEX$liefert dafür einen leeren String. - Sätze:
INSERT,RETRIEVE,UPDATE(je[#]n, satzvariable) undDELETE [#]nauf dem aktuellen Satz. - Cursor:
MOVEFIRST,MOVELAST,MOVENEXT,MOVEPREVIOUS(je[#]n) in der Ordnung des aktiven Index;EOF(n)undBOF(n)melden das Überlaufen am Ende bzw. am Anfang. - Suche:
SEEKEQ,SEEKGT,SEEKGE(je[#]n, schlüsselwert[, …]). Ein mehrspaltiger Index lässt sich mit einem Präfix seiner Spalten durchsuchen;SEEKEQmit unvollständigem Schlüssel schlägt dabei immer fehl (wie im Vorbild),SEEKGEundSEEKGTpositionieren auf dem ersten passenden Satz. Über den NULL-Index lässt sich nicht suchen (Fehler 87). - Tabellen:
DELETETABLE datenbank$, tabellenname$. - Transaktionen:
BEGINTRANS,COMMITTRANS,SAVEPOINT(Funktion, liefert die Kennung),ROLLBACK [kennung]undROLLBACK ALL. LOF(n)liefert für eine ISAM-Dateinummer die Satzzahl der Tabelle,LOC(n)die Kennung des aktuellen Satzes (0 = unpositioniert).- Cursorlage wie im Vorbild: nach
SETINDEXist der erste Satz der neuen Ordnung der aktuelle; nachDELETEder auf den gelöschten folgende, und war der gelöschte der letzte, steht der Cursor am Ende der Tabelle ohne aktuellen Satz. - Fehlercodes 81–89 (
ERR): 81 ungültiger Name, 82 Tabelle nicht gefunden, 83 Index nicht gefunden, 84 ungültige Spalte, 85 kein aktueller Satz, 86 Verstoß gegen einen eindeutigen Index, 87 unzulässige Operation auf dem NULL-Index (Suche), 88 Datenbank inkonsistent, 89 ISAM-Puffer zu klein.
Sortierordnung der Indizes. Textspalten ordnen nach
Unicode-Codepoints; Groß- und Kleinschreibung werden unterschieden.
Es ist dieselbe Ordnung, die der Vergleichsoperator des Dialekts auf
Strings anwendet — ein Programm kann die Satzreihenfolge damit
vorhersagen. Praktisch heißt das: alle Großbuchstaben A–Z stehen vor
allen Kleinbuchstaben a–z, und Zeichen jenseits von ASCII (Ä, ß,
€) stehen nach beiden, in der Reihenfolge ihrer Codepoints. Beispiel:
Apfel < Birne < apfel < birne < Äpfel.
Eine sprachabhängige (locale-abhängige) Sortierung gibt es bewusst nicht: sie machte die Reihenfolge plattformabhängig. Das Vorbild ordnete nach den Zeichencodes einer festen Codepage; Codepoints sind die direkte Entsprechung unter der Unicode-Entscheidung dieses Projekts.
Absteigende Indexspalten (Erweiterung). Die Original-Hilfe kennt bei
CREATEINDEX keine Sortierrichtung. Terminal Basic ordnet eine Spalte
absteigend, wenn ihrem Namen ein - vorangestellt ist:
CREATEINDEX #1, "NachPreis", 0, "Nachname", "-Preis"
Das ist kollisionsfrei, weil ein Feldname einer TYPE-Anweisung nie mit
- beginnen kann; Programme des Vorbilds bleiben unverändert gültig.
SETMEM und Fehler 89 (Abweichung). Im Vorbild veränderte
SETMEM(n&) den DOS-Fern-Heap um n Bytes. Ein DOS-Speichermodell gibt
es hier nicht; stattdessen ist SETMEM die Obergrenze des ISAM-Puffers:
sie wird um n Bytes verändert (negativ verkleinert, positiv vergrößert)
und die danach verfügbare Größe geliefert. Der Vorgabewert ist 65536
Bytes. Gegen die Grenze zählen die Satzbytes einer laufenden Operation
und das Rücknahmeprotokoll einer offenen Transaktion. Reicht der Puffer
für eine Operation nicht aus, tritt Laufzeitfehler 89 („ISAM -
Insufficient ISAM buffers") auf — nicht ein generischer Fehler und kein
stiller Abbruch.
11. Eingebaute Funktionen (Katalog)
Strings: LEN, LEFT$, RIGHT$, MID$ (Funktion und Anweisung),
INSTR([start,] s$, such$), UCASE$, LCASE$, LTRIM$, RTRIM$,
SPACE$, STRING$(n, zeichen|code), ASC, CHR$, STR$, VAL,
HEX$, OCT$, LSET/RSET (Anweisungen).
Mathematik: ABS, SGN, INT (abrunden), FIX (Richtung 0), SQR,
EXP, LOG, SIN, COS, TAN, ATN, RND[(n)], RANDOMIZE [saat],
CINT, CLNG, CSNG, CDBL, CCUR.
Zufallszahlen. Der Generator ist der lineare Kongruenzgenerator des
Vorbilds auf 24 Bit:
zustand = (zustand · &H FD43FD + &H C39EC3) MOD 2^24, Ergebnis
zustand / 2^24 als SINGLE im Bereich [0, 1).
RND und RND(n) mit n > 0 liefern die nächste Zahl, RND(0)
wiederholt die zuletzt gelieferte, RND(n) mit n < 0 setzt den Zustand
aus dem Argument. RANDOMIZE saat bildet aus der Saat 16 Bit, die die
Bits 8–23 des Zustands besetzen; das niederwertige Byte ist fest — damit
liefert dieselbe Saat stets dieselbe Folge, unabhängig von vorherigen
RND-Aufrufen. RANDOMIZE ohne Argument fragt den Startwert mit
Random Number Seed (-32768 to 32767)? ab.
Datum/Zeit: DATE$ (Funktion und Anweisung — Setzen: Nicht-Ziel),
TIME$, TIMER (Sekunden seit Mitternacht, SINGLE); dazu die nativen
Schlüsselwörter des Vorbilds (Neuerung ggü. QB/PDS): NOW, DATESERIAL,
DATEVALUE, TIMESERIAL, TIMEVALUE, DAY, MONTH, YEAR, WEEKDAY,
HOUR, MINUTE, SECOND (serielle Datumswerte als DOUBLE) sowie
FORMAT$ (Zahlen-, Datums-/Zeitformatierung).
Sonstiges: LBOUND, UBOUND, FRE(…) (freier Speicher — liefert bei
uns Pseudowerte), VARPTR/VARSEG/SADD/PEEK/POKE → Nicht-Ziel
(Fehler 73), ENVIRON$, COMMAND$, SHELL [cmd$].
DATA: DATA konstanten, READ var, …, RESTORE [label].
12. Forms-Anbindung (Details in forms-referenz.md)
form.eigenschaft = wert, form!steuerelement.eigenschaft,
Ereignisprozeduren SUB name_Ereignis (…), LOAD/UNLOAD form,
form.SHOW [style%] (0 = modeless, Standard; 1 = modal), form.HIDE,
DOEVENTS(), SCREEN-Objekt, Datentypen FORM/CONTROL, IF TYPEOF,
$FORM-Metabefehl, Include-Dateien (Konstanten-.BI).
Dialoge:
MSGBOX msg$ [,type% [,title$]](Anweisung) bzw. Funktion → INTEGER.type%= Buttons (0 OK · 1 OK/Cancel · 2 Abort/Retry/Ignore · 3 Yes/No/Cancel · 4 Yes/No · 5 Retry/Cancel) + Default-Button (0/256/512). Rückgabe 1 OK · 2 Cancel/Esc · 3 Abort · 4 Retry · 5 Ignore · 6 Yes · 7 No. Keine Icon-Flags (Textmodus). msg$ max. 1024 Zeichen, modal.INPUTBOX$(prompt$ [,title$ [,default$ [,xpos%, ypos%]]])→ STRING; Cancel liefert""; Position in Zeichen, sonst zentriert; Dialog fest 46×16 Zeichen; prompt$ max. 255 Zeichen.
Abweichungen vom Vorbild (beschlossen)
-
UTF-8/Unicode statt CP437 (2026-09-01). Konsequenzen:
- STRING ist eine Folge von Unicode-Zeichen (Codepoints);
LENzählt Zeichen, nicht Bytes.ASC/CHR$arbeiten auf Codepoints (CHR$(9731)= „☃").ASC("")bleibt Fehler 5. - String-Vergleich codepoint-weise (keine CP437-Sortierung).
- Der Bildschirmpuffer speichert Unicode-Zeichen; Rahmen werden mit Unicode-Box-Drawing gezeichnet.
- Zeichen mit Darstellungsbreite 2 (Emoji, CJK) belegen zwei Zellen
(Entscheidung 2026-09-02, umgesetzt): der Cursor rückt um zwei Spalten
vor,
POSnennt die Anfangsspalte,LOCATEauf die zweite Hälfte wirkt auf den Zeichenanfang. Passt ein breites Zeichen nicht mehr in die Zeile, wandert es als Ganzes in die nächste und die letzte Spalte bleibt leer. Wird eine Hälfte überschrieben, verschwindet die andere. Zeichen der Breite 0 (kombinierende Zeichen) belegen vorerst eine eigene Zelle. GET/PUT-Records: feste Strings (STRING * n) werden als UTF-32 gespeichert (4 Bytes/Zeichen, feste Record-Länge) — Binärdateien sind dadurch bewusst inkompatibel zum Vorbild (Entscheidung 2026-09-02).
- STRING ist eine Folge von Unicode-Zeichen (Codepoints);
-
Keine Hardware-Nähe (bestätigt 2026-09-02):
PEEK/POKE/INP/OUT/WAIT/BLOAD/BSAVE/VARPTR/VARSEG/SADD/CALL ABSOLUTE/CALL INTERRUPT/IOCTLwerden bereits zur Compile-Zeit mit der Meldung „Feature unavailable" abgewiesen (kein Laufzeitfehler). Ebenso abgewiesen: die Interlanguage-Schnittstelle (CALLS,SSEG,SSEGADD,StringAddress/StringAssign/StringLength/StringRelease), die EingabegerätePEN,STRIG,STICKund die serielle Schnittstelle (COM,ON COM,OPEN "COMn:"). -
INKEY$für erweiterte Tasten liefertCHR$(0) + code-Sequenzen mit den klassischen Scancodes, damit bestehender Code funktioniert (festgelegt 2026-09-04): F1–F10 = 59–68, Pos1 = 71, ↑ = 72, Bild↑ = 73, ← = 75, → = 77, Ende = 79, ↓ = 80, Bild↓ = 81, Einfg = 82, Entf = 83. Zeichentasten liefern ein Zeichen, EingabeCHR$(13), RückschrittCHR$(8), EscCHR$(27), TabulatorCHR$(9). Strg+C und Strg+Untbr sind Abbruch und erscheinen nicht inINKEY$. Tasten heutiger Tastaturen ohne Entsprechung im Vorbild (etwa F11/F12 oder Meta- Kombinationen) liefern nichts — eine eigene Kodierung dafür wäre eine Erweiterung und gehört in Stufe 2. -
Kein
CHAIN/Overlay-Mechanismus;SHELLstartet die System-Shell. -
Grafik-Anweisungen (
SCREEN n>0,PSET,PRESET,LINE,CIRCLE,PAINT,DRAW, Grafik-GET/PUT,PALETTE,WINDOW,VIEW,PMAP,PCOPY,POINT) sind Nicht-Ziel und werden zur Compile-Zeit mit „Feature unavailable" abgewiesen. Die Formen, die sich ein Schlüsselwort mit einer unterstützten Anweisung teilen, erkennt der Compiler an ihrer Syntax:LINEohneINPUT,GET/PUTmit(,VIEWohnePRINT. Hinweis: das Vorbild hatte die Grafikmodi 0–13, aber nicht gleichzeitig mit Forms (dort Fehler 272 „Invalid when forms are showing") — wir übernehmen nur den Forms-/Textmodus-Zweig. -
PLAY/SOUND:BEEP= Terminal-Bell; Rest Nicht-Ziel (Fehler 73). 5a.LPRINTschreibt in eine Datei (2026-09-03): einen plattformübergreifenden Druckerkanal gibt es nicht. Der Druckerpuffer geht am Programmende inLPT1.TXTim aktuellen Verzeichnis;LPOSnennt die Spalte in diesem Puffer. 5b. Satzsperren (LOCK/UNLOCK) prüfen nur, ob die Datei offen ist; eine echte Sperre bietet die Plattform nicht einheitlich.FILEATTRliefert nur die Modus-Kennzahl (Argument 1); das Betriebssystem-Handle bildet der Dialekt nicht ab und liefert 0. 5c.CHDRIVEist außerhalb von Windows folgenlos — Laufwerksbuchstaben gibt es dort nicht. 6a. Uhr in Ortszeit, mit Rückfall auf UTC (2026-09-04):DATE$,TIME$,TIMERundNOWrechnen in der Zeitzone des Rechners;TIMERzählt ab der lokalen Mitternacht. Der Versatz wird für den jeweils abgefragten Zeitpunkt bestimmt, nicht einmal beim Start — ein Programm, das über eine Zeitumstellung hinweg läuft, folgt ihr. Lässt sich die Zone des Rechners nicht ermitteln, gilt UTC; das Programm läuft weiter, und der Runner meldet es einmal beim Start auf der Fehlerausgabe („Zeitzone nicht ermittelbar …").DATE$ = …undTIME$ = …stellen nicht die Systemuhr, sondern einen programmeigenen Versatz auf die Ortszeit; alle Zeitfunktionen rechnen ihn mit ein. 6b. Serielle Datumswerte zählen Tage ab dem 30.12.1899 (Serie 2 = 1.1.1900), der Nachkommaanteil ist die Tageszeit.WEEKDAYliefert 1 für Sonntag. Zweistellige Jahre gelten inDATESERIALals 19xx, inDATEVALUEals 20xx unter 80 und sonst als 19xx. -
Dynamische Bildschirmgröße (2026-09-02): kein festes 80×25 — der Bildschirm folgt der Terminalgröße (Mindestgröße 80×25, darunter nur ein Hinweis).
CSRLIN/POS/LOCATE/VIEW PRINTund dasSCREEN-Objekt arbeiten auf der tatsächlichen Größe.WIDTH 40/80wird akzeptiert, ändert aber nichts (die Größe bestimmt das Terminal). 80×25 ist überall nur die untere Schranke der Darstellung, nie eine Bildschirmgröße im Verhalten des Programms. Ändert sich die Größe während der Ausführung, wird das zugestellt: der Inhalt bleibt oben links erhalten, der Cursor wird in die neuen Grenzen geklemmt, und einVIEW PRINT-Bereich wird am unteren Rand geklemmt bzw. — wenn er ganz vom Schirm fällt — auf den vollen Bildschirm zurückgesetzt. -
SIGNALliegt auf Betriebssystemsignalen (2026-09-04): Im Vorbild trappteON SIGNAL(n%)OS/2-Signale — Prozessflags A/B/C, ausgelöst überDOSFLAGPROCESSaus einem anderen Prozess; einen Wertebereich fürn%dokumentierte die Hilfe nicht. Diese Quelle existiert auf keiner Zielplattform. Abgebildet wird deshalb die minimale Menge, die auf allen dreien besteht:SIGNAL(1)=SIGINT,SIGNAL(2)=SIGTERM. Die vier übrigen Signale des C-Standards (SIGABRT,SIGFPE,SIGILL,SIGSEGV) entstehen aus dem eigenen Programmzustand und sind nach einemRETURNnicht fortsetzbar; sie werden nicht abgebildet. Unter Windows istSIGTERMvon außen nicht zustellbar —SIGNAL(2)bleibt dort wirkungslos. TrifftSIGINTohne aktiven Trap ein, bleibt es beim bisherigen Abbruch.