Phase 4: Ereignisschleife und klassische Traps

This commit is contained in:
2026-09-04 15:56:47 +02:00
parent 060674b466
commit 5cf5a6582c
40 changed files with 4024 additions and 176 deletions

View File

@@ -0,0 +1,261 @@
# Umfang und Form der Ereignis-Elemente (Aufgaben 1.1, 1.2)
**Quelle.** `bas7advr.hlp` (BASIC 7 Advisor), Einzelseiten unter
https://dos-help.soulsphere.org/bas7advr.hlp/ (abgerufen 2026-09-04);
Gegenprobe `qb45advr.hlp` unter derselben Domain. Zitate wörtlich aus den
Einzelseiten, Übersetzung nur in den Kommentarzeilen.
## 1.1 Einzelseiten
| Element | Seite |
|---|---|
| `ON TIMER` | `x_dot_ontimerrr.html` |
| `ON KEY` | `x_dot_onkeyr.html` |
| `ON UEVENT` | `x_dot_onur.html` |
| `ON SIGNAL` | `x_dot_onsigbar.html` |
| `TIMER` (Anweisung) | `x_dot_timersr.html` |
| `KEY(n)` (Ereignis) | `x_dot_ketvr.html` |
| `UEVENT` | `x_dot_uevvvr.html` |
| `SIGNAL` | `x_dot_signalr.html` |
| `EVENT` | `x_dot_evntonr.html` |
| `SetUEvent` | `x_dot_SETUEVr.html` |
### ON TIMER
> `ON TIMER(n&) GOSUB {linenumber | linelabel}`
>
> „The maximum number of seconds that can be specified for the time
> interval, n&, is the number of seconds in a 24-hour day (86,400)."
>
> „A linenumber value of 0 disables event trapping and does not specify
> line 0 as the start of the routine."
Der Zeitwert ist **LONG** (`n&`), Bereich 186 400 Sekunden.
`GOSUB 0` schaltet den Trap ab.
### TIMER ON/OFF/STOP
> „TIMER ON enables timer-event trapping."
>
> „TIMER OFF disables timer-event trapping. … Events occurring while
> trapping is off are ignored."
>
> „TIMER STOP suspends timer-event trapping. … Events occurring while
> trapping is off are remembered and processed when the next TIMER ON
> statement is executed."
**Wiedereintritt — wörtlich belegt:**
> „an automatic TIMER STOP is executed so that recursive traps cannot
> take place."
>
> „The RETURN from the trapping routine automatically performs a TIMER ON
> statement unless an explicit TIMER OFF was performed inside the
> routine."
Das ist genauer als „die Quelle gilt während des Handlers als gestoppt":
`RETURN` schaltet die Quelle **auf ON**, außer im Handler stand ein
ausdrückliches `OFF`.
### KEY(n) — Wertebereich
> ```
> KEY(n%) ON
> KEY(n%) OFF
> KEY(n%) STOP
> ```
| n% | Taste |
|---|---|
| 0 | alle Tasten dieser Tabelle |
| 110 | F1F10 |
| 11 | Pfeil hoch |
| 12 | Pfeil links |
| 13 | Pfeil rechts |
| 14 | Pfeil runter |
| 1525 | benutzerdefinierte Tasten |
| 3031 | F11F12 (101-Tasten-Tastatur) |
`ON KEY` selbst: `ON KEY(n%) GOSUB {linenumber | linelabel}`. Zur Frage,
ob eine getrappte Taste im Eingabestrom bleibt, sagt die Einzelseite nur:
> „After a key is trapped, the information on which key was trapped is no
> longer available."
Die Gegenprobe in `qb45advr.hlp` (`x_dot_onkeyba.html`, `x_dot_ketv.html`)
enthält dazu **nichts**. → Festlegung nötig, siehe 1.2.
### Benutzerdefinierte Tasten 1525
Die Einzelseite zu `KEY n, zeichenkette$` (`x_dot_setfkr.html`) behandelt
**nur** die Makrozuweisung für 110 und 3031; die Erklärungsform für
1525 steht in keiner der beiden Hilfen, ebenso wenig die Bedeutung der
Bits des Tastaturflagbytes. Belegt ist dagegen die **Scancode-Tabelle**
(`qb45advr.hlp`, `x_dot_kbsct.html`), aus der die Zuordnung Zeichen →
Scancode stammt:
> ESC 01 · „! or 1" 02 … „) or 0" 0B · „_ or -" 0C · „+ or =" 0D ·
> TAB 0F · Q 10 … P 19 · ENTER 1C · A 1E … L 26 · Z 2C … M 32 ·
> SPACEBAR 39 · F1 3B … F10 44 · HOME 47 · UP 48 · LEFT 4B · RIGHT 4D ·
> END 4F · DOWN 50 · INS 52 · DEL 53
→ Festlegung nötig für das Flagbyte, siehe 1.2.
### UEVENT und SetUEvent
> `ON UEVENT GOSUB {linenumber | linelabel}`
>
> „This event typically originates from a hardware interrupt but can also
> be triggered by software."
>
> „SetUEvent … sets a flag that BASIC checks before executing the next
> statement."
Bestätigt die Zustellung **an der Anweisungsgrenze**.
> ```
> UEVENT ON
> UEVENT OFF
> UEVENT STOP
> ```
>
> UEVENT STOP „preserves events in memory for processing once UEVENT ON
> resumes, though executing UEVENT OFF afterward will discard these queued
> events."
`OFF` verwirft also auch ein unter `STOP` gemerktes Ereignis.
`SetUEvent` ist eine **Routine** ohne dokumentierte Argumentliste und ohne
dokumentierten Rückgabewert:
> „It sets the BASIC entry point that causes a user-defined event."
### SIGNAL
> ```
> SIGNAL(n%) ON
> SIGNAL(n%) OFF
> SIGNAL(n%) STOP
> ```
>
> `ON SIGNAL(n%) GOSUB {linenumber | linelabel}`
>
> „A linenumber value of 0 disables event trapping."
Quelle der Signale — wörtlich:
> „OS/2 protected-mode signal"
>
> „Process flags A, B, and C are used for communicating between
> processes."
>
> aktiviert durch die OS/2-Funktion `DOSFLAGPROCESS` aus einem anderen
> Prozess.
Ein **Wertebereich für `n%` ist nicht dokumentiert**; die Einzelseite
verweist auf „Chapter 9, Event Handling'" des Programmer's Guide, der
nicht vorliegt.
### EVENT
> ```
> EVENT ON
> EVENT OFF
> ```
>
> „EVENT OFF … equivalent to compiling a program from the BC command line
> without using /V or /W."
>
> „EVENT OFF and EVENT ON can be used to bracket sections of code where
> events do not need to be detected and trapped, and fast performance is
> required."
**`EVENT STOP` ist nicht dokumentiert.** `EVENT` ist im Vorbild kein
Laufzeit-Hauptschalter mit drei Zuständen, sondern eine Klammer, die die
Erzeugung der Ereignisprüfungen im Kompilat ein- und ausschaltet.
### Reihenfolge und Trapping in Prozeduren
Zu beidem geben die Einzelseiten **nichts** her; sie verweisen auf
Kapitel 9 des Programmer's Guide. → Festlegung nötig, siehe 1.2.
## 1.2 Abweichungen der Delta-Spec vom Beleg
Nach der Leitplanke „Referenzverhalten schlägt Eleganz … das gilt auch
gegenüber den eigenen Spezifikationen" ist bei jeder Abweichung die
**Spec** anzugleichen.
| Nr. | Delta-Spec sagt | Beleg sagt | Folge |
|---|---|---|---|
| A | `EVENT` hat `ON`/`OFF`/`STOP` und überlagert die Einzelzustände | nur `ON`/`OFF`; Klammer um die Erzeugung der Prüfungen | Spec angleichen; `EVENT STOP` wird namentlich abgewiesen |
| B | „während des Handlers gilt die Quelle als gestoppt; mit `RETURN` gilt wieder ihr Zustand" | Eintritt = automatisches `STOP`; `RETURN` = automatisches `ON`, außer im Handler stand ein ausdrückliches `OFF` | Spec präzisieren |
| C | `OFF` verwirft künftige Ereignisse | `OFF` verwirft **auch** ein unter `STOP` gemerktes | Spec ergänzen |
| D | `ON KEY(n)` mit Wertebereich | 0, 125, 3031 mit fester Tastenzuordnung | Spec unverändert, Bereich jetzt belegt |
| E | `ON TIMER(n)` | `n&` ist LONG, 186 400; `GOSUB 0` schaltet ab | Spec unverändert, Form jetzt belegt |
**Ohne Beleg — unsere Festlegungen (gehören nach `sprachreferenz.md`
unter „Abweichungen"):**
1. **Getrappte Tasten verlassen den Eingabestrom.** Von keiner der beiden
Hilfen belegt. Wir legen fest: eine Taste mit aktivem Trap erscheint
nicht zusätzlich bei `INKEY$`/`INPUT`. Begründung: andernfalls sähe ein
Programm dieselbe Taste zweimal, und `KEY(n) OFF` wäre die einzige Art,
eine Taste überhaupt normal zu lesen.
2. **Reihenfolge gleichzeitig fälliger Ereignisse.** Unbelegt. Wir legen
fest: `KEY` (aufsteigend nach `n`), dann `TIMER`, dann `UEVENT`, dann
`SIGNAL` — Tasten zuerst, weil sie an einer Benutzereingabe hängen.
3. **Trapping in Prozeduren.** Unbelegt. Wir legen fest: die Zustellung
erfolgt an jeder Anweisungsgrenze, auch innerhalb von `SUB`/`FUNCTION`;
das Ziel liegt im Modulrumpf. Das entspricht dem bereits umgesetzten
Verhalten des modulweiten `ON ERROR`.
4. **Bits des Tastaturflagbytes** in `KEY n, CHR$(flag)+CHR$(scan)`.
Unbelegt. Wir legen die Belegung des BIOS-Flagbytes zugrunde:
1 rechte Umschalttaste, 2 linke Umschalttaste, 4 Strg, 8 Alt. Im
Terminal sind linke und rechte Umschalttaste nicht unterscheidbar,
beide Bits gelten deshalb gleich; NumLock und CapsLock spielen für
einen Trap keine Rolle und werden ignoriert.
5. **`SIGNAL`-Quelle.** Die belegte Quelle ist OS/2-gebunden
(`DOSFLAGPROCESS`, Prozessflags A/B/C) und existiert auf keiner
Zielplattform; ein Wertebereich ist nicht dokumentiert. → **Entscheidung
des Projektinhabers ausstehend**, siehe unten.
## Entscheidung zu `SIGNAL` (Projektinhaber, 2026-09-04)
`SIGNAL` wird auf **Betriebssystemsignale** abgebildet, und zwar nur auf
die minimale Menge, die auf allen Zielplattformen existiert.
Der C-Standard garantiert überall — Linux, macOS **und** Windows —
`SIGABRT`, `SIGFPE`, `SIGILL`, `SIGINT`, `SIGSEGV`, `SIGTERM`. Von diesen
sind nur zwei asynchron, von außen ausgelöst und fortsetzbar; die vier
Fault-Signale entstehen aus dem eigenen Programmzustand, und ein
`RETURN` aus ihrem Handler führte in denselben Fehler zurück. Abgebildet
werden deshalb:
| `n%` | Signal | Bedeutung |
|---|---|---|
| 1 | `SIGINT` | Unterbrechungswunsch von außen |
| 2 | `SIGTERM` | Beendigungswunsch von außen |
Ein anderer Wert als 1 oder 2 wird namentlich abgewiesen — zur
Übersetzungszeit, wenn er konstant ist, sonst mit Laufzeitfehler 5.
**Zustellung.** Signale erreichen die Laufzeit wie die Zeit über den
Host; nur er berührt das Betriebssystem. Ein Signal wird nicht im
Signalkontext verarbeitet, sondern setzt eine Marke, die der Host beim
nächsten Abholen in ein Ereignis übersetzt.
**Verhältnis zum Abbruch.** Im Rohmodus liefert das Terminal Strg+C als
Taste, nicht als Signal; daran ändert sich nichts. Trifft `SIGINT`
dagegen von außen ein (`kill -INT`), gilt: mit aktivem Trap läuft der
Handler, ohne aktiven Trap bleibt es beim bisherigen Abbruch. Dieselbe
Regel wie bei getrappten Tasten.
**Abweichungen, die zu dokumentieren sind:**
1. Die belegte Quelle des Vorbilds (OS/2-Prozessflags A/B/C über
`DOSFLAGPROCESS`) existiert nicht; `n%` bedeutet bei uns etwas
anderes als im Vorbild. Ein Wertebereich war im Vorbild ohnehin nicht
dokumentiert.
2. `SIGTERM` ist unter Windows von außen nicht zustellbar (es gibt kein
`kill`); `SIGNAL(2)` bleibt dort wirkungslos. `SIGNAL(1)` wird dort
über den Konsolen-Steuerhandler (`CTRL_C_EVENT`) bedient.