
 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.

 Ad Version 3.01a:                                             ... 2.4.94, RS
 ----------------------------------------------------------------------------

 Frherer Linker oder der von MS empfohlen, da der neue ab 1200 Prozeduren
  streikt, obwohl das Handbuch 1500 als Grenze angibt.

 Der Compiler verarbeitet SET-Konstanten in DEF-Moduln fehlerhaft;
  Abhilfe: In .DEFs SET-Variable statt -Konstanten verwenden.
  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).

 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.
  hilft nur uerste Sorgfalt, 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.

 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 (10000000H);
 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)).
 SHORT akzeptiert keine LONGCARD-Konstanten (Umgehung: SHORT (KONST -0)).

 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, leider aber im Code- statt im Data- oder im
  Bss-Segment! Da solche St.-K. (sinnvollerweise!) auch in Prozedur-Parameter
  eingesetzt werden drfen, die als referenzierte offene Felder (VAR ARRAY OF
  CHAR) deklariert sind, 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-Var. an
  geeigneter Stelle einfgen & 0 setzen).

 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!

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

 Es gibt primitive Programmier-Fehler, deren Verarbeitung frhere Versionen
  des Compilers saftig abstrzen lieen: Z.B., wenn an geeigneter Stelle im
  Quell-Text vergessen wurde, eine Kommentar-Klammer zu schlieen.

 Der TDI-originale System-Modul "GEMX" besitzt so viele wunderschne Bugs ...
  Da der Compiler selbst sowie M2Desk, die Utilities etc. offenbar auch 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. Jedoch
  sollten Anwendungs-Programme ein korrigiertes GEMX einbinden.

     