
 Ad TDI Modula-2 (3.01a)                                   ... 22.3.95 by RS
 -----------------------

 VORWORT:  Diese Wanzen-Sammlung soll keineswegs irgendjemandem das bewhrte
  TDI-Modula mies machen; ganz im Gegenteil wird (zusammen mit den Ptsches)
  aufgezeigt, da man es auch heute noch (sogar auf dem TT) einsetzen kann.
  Viele der hier aufgefhrten Macken lassen sich ohne groe Probleme umgehen.
  Mit einem entsprechenden GEMX lassen sich sogar Applikationen erstellen,
  die sowohl als .ACC wie auch als .PRG laufen und MultiTOS vertragen!

 Der Compiler verarbeitet SET-Konstanten in DEF-Moduln fehlerhaft;
  Abhilfe: In .DEFs SET-Variable statt -Konst. verwenden & in .MODs setzen.
  Fr den Vergleich von SET-Variablen wird manchmal falscher Code erzeugt;
  Abhilfe: Mit anderem Typ rechnen (evtl. per Cast).

 Der Compiler hat einige Bugs in der Prozedur-Verarbeitung:
 Fr lok. Var. >32KB wird ein fehlerhafter LINK-Code erzeugt:
   2F0EH, 2F0FH, 0DFFCH ~ MOVE.L A6,-(A7); MOVE.L A7,-(A7); ADD.L #..,A7
  statt 4E56H,0, 0DFFCH ~ LINK A6,#0; ADD.L #..,A7 o..
  (Die fehlerhafte Stelle befindet sich wahrscheinlich bei Adr. 20A48H ff).
  Abhilfe: Lok. Var. auf 32K beschrnken, grere Mengen global machen.
 Gewisse Unterbereichs-Typen (z.B. TYPE U1to50 = INTEGER [1..50]) produzieren
  als Paramter die Meldung "compiler error in assert" sowie falschen Code.
  Abhilfe: U-Typen als Par. vermeiden (gibt's in Oberon sowieso nicht mehr).
 Die Buchhaltung fr VALUE-Feld-Parameter vergit offenbar, den A6-Offset fr
  den Stack mitzufhren; wird er gebraucht, resultiert ein Adress-Fehler.
  Abhilfe: Felder als VAR deklarieren oder den erz. Code mit DECLNK checken.
 Da als tag-Feld offenbar nur ein Wort auf den Stack gelegt wird, werden
  'groe' Felder als open-array-Parameter falsch verarbeitet.
  Abhilfe: Groe Felder ber Ptr.-Arith. verarbeiten (geht auch schneller).
 Der Compiler setzt die Indizierung !smtlicher! open-array-parameter in
  Register-relative Addressierung von !Wort!-Lnge um - das bedeutet, da
  open arrays nur indiziert werden knnen, solange sie < 32KB sind (also open
  Strings < 32K, open LONGCARDs < 8K, open LONGREALs < 4K etc.). Der Bug ist
  schwer zu erkennen, da die Symptome denen eines 'dangling pointers' hneln.
  Fazit: Man benutze Pointer-Arithmetik (die ist sowieso viel schneller!).
 Die Anzahl lokaler Prozedur-Aufrufe ist auf ca. 250 beschrnkt.

 Beim Aufruf indizierter Funktionen (d.h. Elementen eines Feldes von Proz.-
  Variablen mit Rckgabe-Wert) glaubt der Compiler manchmal, Register retten
  und wiederherstellen zu mssen und macht dabei einen Fehler, der gerade den
  Rckgabe-Wert zerstrt. Abhilfe: Die indizierte zunchst an eine nicht-
  indizierte Variable zuweisen und dann letztere aufrufen.

 Manche Arithmetik mit REAL-Konstanten (z.B. r := - 123.0 - 0.123) quittiert
  der Compiler zur bersetzungszeit (!) mit Fehler 14 (Arithm. Overflow).
  Abhilfe: Konstanten 'zu Fu' ausrechnen (z.B. r := - 123.123).
 Zuweisungen von REAL nach LONGREAL sind zwar ausdrcklich erlaubt, nicht
  aber entsprechende Einsetzungen in Prozedur-Parameter! Die werden vom
  Compiler zwar nicht bemeckert, aber das Compilat strzt bel ab. Abhilfe:
  Statt REAL-Par. kann man LONGWORDs deklarieren; bei LONGREAL-Par. knnte
  man im ref. Fall VAR ARRAY OF LONGWORD auf HIGH = 1 abprfen, aber fr
  Value-Par. hilft nur, sorgfltig eine Einsetzung von REALs zu vermeiden.
 Etwas sonderbare Werte produziert TDI fr MAX (REAL) = 1.701412E38 und
  MIN (REAL) = -6.805647E38 (die beide von +-3.402823E38 nach IEEE abweichen)
  und MAX (LONGREAL) & MIN (LONGREAL) strzen sogar ab. Abhilfe:
  Ersetzt man im Compiler (v3.01a, 157562 B.) an den Stellen 27620 & 44010
  die Bytes-Folgen 7EFFFFFF durch 7F7FFFFF, vertrgt der Compiler auch
  r := 3.4E38 und erzeugt das richtige MAX (REAL); leider lie sich keine
  entsprechende Stelle fr MIN (REAL) finden, daher " - MAX(REAL)" benutzen;
  fr die langen Werte kann man Quasi-Konstante deklarieren, z.B.
    MAXLORE ~ (7FEFFFFFH, 0FFFFFFFFH).

 CONSTante Adressen lassen sich nicht an Pointer zuweisen;
  Abhilfe: Variable zwischenschalten.
 CONSTante neg. LONGINTs werden als Prozedur-Parameter kurz & klein gehackt;
  Abhilfe: Expliziter Cast mit LONGINT.
 MIN (LONGINT) hlt der Compiler fr einen LONGCARD-Wert (soda also bei der
  Weiterverarbeitung - etwa in MIN (LONGINT) DIV 10 - das Vorzeichen fehlt).
  Der Ausdruck LONGINT (MIN (LONGINT)) + 1 produziert zur bersetzungzeit
  einen "arithmetic error in evaluation of constant expression", @$%&*#!
  Abhilfe: CONST MINLI = LONGINT (80000000H);
 Die Typ-Wandlung (Cast) durch LONGCARD erzeugt fr neg. INTEGER falsche
  Werte (z.B. LONGCARD (INTEGER (0B8E8H)) = 0FFFFB8E8H).
  Abhilfe: Andersherum casten (z.B. LONG (CARDINAL (-3)).
 Zwar ist die Typ-Wandlung per VAL prinzipiell vorhanden, aber offenbar hat
  TDI ein paar Updates vergessen, soda z.B. li := VAL (LONGINT, 13) nicht
  funktioniert; Abhilfe durch z.B. li := 13.
 SHORT akzeptiert keine LONGCARD-Konstanten (Umgehung: SHORT (KONST -0)).
 SHORT & LONG knnen nicht auf (LONG-) BITSETs angewendet werden;
  Abhilfe: Mit (LONG-) BITSET casten.

 Wie die folgenden Beispiele zeigen, hat der Compiler Schwierigkeiten bei
  der Zuweisung von Byte-Arrays:
    VAR qB,zB: ARRAY [0..32000+1] OF CHAR;
    PROCEDURE BAss1;    (* Produziert Code MOVE.W statt MOVE.B => Absturz! *)
     VAR   q,z: POINTER TO ARRAY [0..32000] OF CHAR;
     BEGIN q := ADR (qB[1]); z := ADR (zB[0]); z^ := q^ END BAss1;
    PROCEDURE BAss2;    (* Produziert Code MOVE.L statt MOVE.B => Absturz! *)
     VAR   q,z: POINTER TO ARRAY [0..32000-1] OF CHAR;
     BEGIN q := ADR (qB[1]); z := ADR (zB[0]); z^ := q^ END BAss2;
    PROCEDURE BAss3;    (* Produziert Fehlermeldung "Type incompatibility".*)
     PROCEDURE DoIt (VAR qB, zB: ARRAY OF CHAR); BEGIN zB := qB END DoIt;
     BEGIN DoIt (qB, zB) END BAss3;
  Abhilfe: Eigene Copy-Routinen fr Byte-Arrays, wie vielfach verffentlicht.

 String-'Konstanten' sind in Wahrheit vorbelegte Variablen: Sie werden nicht
  wie sonstige K. zur Kompilier-Zeit verwurstet, sondern es wird Speicher mit
  dem Original-Text reserviert, mit den Original-Linkern aber leider im Code-
  statt im Data- oder Bss-Segment! Da solche St.-K. (sinnvollerweise!) auch
  in referenzierte offene Felder (Prozedur-Parameter VAR ARRAY OF CHAR) ein-
  gesetzt werden drfen, kann ber eine kleine Prozedur legal ihre Adresse
  erfragt werden; das ist zuweilen ntzlich, um Speicherplatz zu sparen,
  jedoch liegt es in der Verantwortung des Programmierers, die St.-K. ber
  diesen Zugang nicht etwa zu verndern: Sonst wird 'selbstmodifizierender
  Code' erzeugt! An String-Konstanten hngt der Compiler selbstndig ein 0c
  an; obwohl nicht von der M2-Sprach-Definition gefordert, gewhrt dies
  Kompatibilitt zu C-Strings, also zum Betriebssystem TOS; insbesondere bei
  Zuweisungen wird die angehngte 0 auch bercksichtigt - aber leider nicht
  bei Parameter-bergabe in offenen Feldern: Der tag-Wert ist um 1 zu klein!
  Schade, man knnte sonst viele Sonderflle im Modul Strings vermeiden.
  (Will man dennoch den Modul beschleunigen, mu man entweder fr akt. Par.
  immer Variable verwenden & die C-Konvention einhalten (abschlie. 0c) oder
  bei Konstanten auf ungerade Lnge achten oder lokal eine Dummy-Variable an
  geeigneter Stelle einfgen & 0 setzen).
 Character-Konstante als akt. String-Parameter passen nur fr Referenzen!
  (Also nicht fr Value-String-Parameter).

 Die Compiler-Option "$T-" fr 'Pointer-Arithmetik' (INC/DEC...) funktioniert
  bei Vergleichen von Pointern mit Adressen nicht fr Bool:= (Adr < Ptr) etc.
  Abhilfe: Bool := (Ptr > Adr) etc.
 Warnung: Die Compiler-Option "$P-" wirkt normalerweise nur auf diejenige
  Prozedur, vor der sie steht; manchmal aber 'verschluckt' sich der Compiler
  und schaltet erst nach der bernchsten Prozedur zurck... Daher besser
  selbst mit "$P+" zurckschalten!
 Die Compiler-Option "$V+" erzeugt fr INTEGERs falsche overflow-checks
  (nmlich BCC statt BVC) und in Folge falsche Meldungen. Abhilfe: "$V-".
 Hinweis: Die Standardfunktionen INC & DEC werden auch mit V+ nicht getestet!

 Undokumentierte SYSTEM-Features:
  Aus dem Pseudo-Modul knnen auch 'ASH' und 'SUPERVISOR' importiert werden.
  Syntax: ASH (VAR a: T; d: INTEGER): T, wobei T einer der 'Zhl-Typen' ist
  (fr (LONG-) INTEGERs resultiert ASL/ASR, sonst LSL/LSR).
  Der Aufruf von SUPERVISOR ist derzeit immer noch unbekannt.
  Im Gegensatz zur Doku kann SYSCALL nicht aus SYSTEM importiert werden!

 Es gibt primitive Programmier-Fehler, deren Verarbeitung den Compiler saftig
  abstrzen lt. (In frheren Versionen z.B., wenn an geeigneter Stelle im
  Quell-Text vergessen wurde, eine Kommentar-Klammer zu schlieen - was zwar
  jetzt immer noch nicht gemeldet wird, aber eine *.ERM-Datei produziert).
 Eine falsch gestellte System-Uhr kann u.U. bei allen Modula-Systemen die
  Versions-Prfung (Modul-Key) aushebeln; das kann zu Endlos-Schleifen beim
  Kompilieren oder zu mysterisen Abstrzen des fertigen Programms fhren;
  Abhilfe gibt's meist nur durch Neu-Kompilation aller betroffenen Moduln!

 Weder der Compiler noch der TDI-Texteditor vertragen Zeichen < 40c (Blank)
  oder > 277c (TradeMark), auch nicht in Kommentaren! (Interne Steuerung!)

 Batch-Processing bzw. die Verwendung einer anderen Shell sind mglich, wenn
  sie dem Compiler (oder Editor oder..) die CommandLine mundgerecht serviert:
  Per ShellWrite entweder 'nen leeren CmdTail (& dann den normalen via PExec)
  oder aber im Spezial-Format: Ohne fhrenden Count, aber abgeschlossen durch
  CR,0c,0c. Dies bedeutet, da kein Start als MODULA.TTP vom Desktop und kein
  Drag & Drop auf MODULA.PRG mglich sind! Abhilfe: Durch Patch.
 Hinweis: Der normale .PRG Aufruf geht (also ohne Shell, via FileSelektor!).
 Das Environment bleibt unbeachtet.

 Frherer bzw. anderer Linker empfohlen, da der neue ab 1200 Prozeduren
  streikt, obwohl das Handbuch 1500 als Grenze angibt.
 Auerdem binden die TDI-Linker das Run-Time-System GEMX u.U. doppelt ein,
  und sie knnen keine Importe in GEMX verarbeiten.

 Hinweis: Der Post-Mortem-Debugger von TDI funktioniert besser, wenn man die
  Gre der erzeugten Dumps im Modul GEMError korrigiert.
 Davon unabhngig, fhrt die in der PMD-Beschreibung aufgefhrte angebliche
  Mglichkeit, strukturierte Variable ber 'right arrow' zu ffnen, leider
  manchmal auf ein HALT (= Error #9); ergo: Cursor-Taste nicht berhren!
 LONGREALs kennt der Debugger nicht.

 Hinweis an Multi-Tasker: Das orig. M2OPTION.ACC liefert seine Informationen
  immer nur an dasjenige Programm zurck, das die 0 als Appl.-ID hat!
  Abhilfe: Ptsch aus ST-Comp 2/95 S.98: 4 mal 33C8 durch 33C6 ersetzen!
 Das Acc. macht einen Fehler beim Aufruf von ObjChange (der aber nur beim
  Nachladen auffllt, z.B. per Chamleon). Abhilfe durch folgenden Ptsch:
  In der Byte-Folge 03E7 3F2E 0008 3F3C 0001 die letzte 1 durch 0 ersetzen!
 8ung, im Acc. lt sich zwar ein Wert >= 64K fr den CompilerHeap einstelln,
  aber tatschlich an den Compiler abgeschickt wird der Wert modulo 64K! Aber
  das scheint den Compiler gar nicht zu kmmern, er alloziert immer 48K.
 Mit dem Prg.-Stack verhlt sich's genau umgekehrt: Der Linker kann sehr wohl
  mehr als 99999 Bytes einstellen (aber dafr gibt's ja das STACKSIZ.PRG).
 Format von M2PATHS.TXT (ist rein ASCII!):
  Zunchst 6 Zeilen (<=37 Zeichen) mit GEM-Pfaden (Leerpfade => Leerzeilen,
  die Ordner drfen keine Extensions haben!), dann 1 Zeile Parameter:
  Vorn 8 Bytes Schalter (d.h. ASCII '0' oder '1'), dann ohne Zwischenraum
  die Gre des Stacks, dann abgetrennt durch '|' die Gre des Heaps.
  Die Schalter haben folgende Bedeutung (von links nach rechts):
   1: Dump, 2: Query, 3: xFer, 4: Map, 5: Debug, 6: Opt, 7: Refs, 8: Listing.
  Als Abschlu einer jeden Zeile gilt CR+LF.
  Folgen noch weitere Zeilen, so handelt es sich um durch nderungen ('Save')
  entstandenen Schrott, der nicht weiter beachtet wird; Files unter GEMDOS
  kann man ja nur per Kopie krzen...

 Der TDI-originale System-Modul "GEMX" besitzt so viele wunderschne Bugs...
  (Z.B. Stacktest & Error-Handling fehlerhaft, Bugs in LFCMP, LENGTHEN etc.).
  Da der Compiler selbst sowie M2Desk, die Utilities etc. offenbar ebenfalls
  damit gelinkt wurden, wirken manche davon natrlich auch dort; z.B. hat die
  M2-TDI-typische Vektor-Verbiegerei Konzept-Fehler, die bei Multi-Tasking
  lstig werden (& XBRA fehlt sowieso), und long stack frames (fr >=MC68020)
  gab's zu TDIs Zeiten auch noch nicht - aber damit lt sich's leben (denn
  Abstrze des Compilers sind ja selten, die Traps werden also kaum benutzt).
  Jedoch sollten Anwendungs-Programme ein korrigiertes GEMX einbinden!
