home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / stjo2122 / doc / oberon.doc < prev    next >
Encoding:
Text File  |  1993-11-30  |  111.7 KB  |  3,084 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.                               *STJ-OBERON-2 *
  16.  
  17.  
  18.                       *Eine Oberon-2 Implementation
  19.                           für Atari ST/STe/TT *
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.                                      von
  29.                               Stephan Junker
  30.  
  31.  
  32.  
  33.  
  34.  
  35.                              28. November 1993
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44. Inhaltsverzeichnis
  45. ==================
  46.  
  47. 1) Einleitung
  48.   1.1) Stand der Entwicklung
  49.   1.2) Geplante Entwicklung
  50.   1.3) Benutzungsbedingungen
  51.   1.4) Fehlermeldungen
  52.   1.5) Kontakt
  53. 2) Von Modula-2 nach Oberon-2
  54.   2.1) Streichungen
  55.     2.1.1) Datentypen
  56.     2.1.2) Module und Import-/Exportregeln
  57.     2.1.3) Anweisungen
  58.     2.1.4) Low-Level Anweisungen
  59.   2.2) Neue Features
  60.     2.2.1) Typerweiterung
  61.     2.2.2) Typgebundene Prozeduren
  62.     2.2.3) Typinklusion
  63.   2.3) Sonstige Unterschiede
  64. 3) Allgemeine Erläuterungen
  65.   3.1) Suchpfade
  66.   3.2) Dateien
  67.   3.3) Einstellung der Shell
  68. 4) Installation
  69.   4.1) Start
  70. 5) Der Compiler
  71.   5.1) Aufruf, Parameter
  72.   5.2) Environmentvariablen
  73.   5.3) Optionen im Quelltext
  74.   5.4) Ausgabe
  75.   5.5) Vordefinierte Prozeduren
  76.   5.6) Unterschiede zum Standard-Oberon-2
  77.   5.7) Bekannte Fehler
  78. 6) Der Assembler
  79.   6.1) Symbolkonventionen
  80.     6.1.1) Formelausdrücke
  81.   6.2) Pseudobefehle
  82.     6.2.1) SET und EQU
  83.     6.2.2) CHARSET
  84.     6.2.3) CPU
  85.     6.2.4) SUPMODE
  86.     6.2.5) SEGMENT
  87.     6.2.6) DC,DS
  88.     6.2.7) ALIGN
  89.     6.2.8) MACRO
  90.     6.2.9) IRP
  91.     6.2.10) REPT
  92.     6.2.11) Bedingte Assemblierung
  93.     6.2.12) Lokale Label
  94.   6.3) Hochsprachenelemente
  95.     6.3.1) IF cond THEN ... ELSIF ... ELSE ... END
  96.     6.3.2) REPEAT ... UNTIL cond
  97.     6.3.3) LOOP ... END
  98.     6.3.4) EXIT [(Zahl)]
  99.   6.4) Diverses
  100.     6.4.1) INCLUDE
  101.     6.4.2) MESSAGE, WARNING, ERROR und FATAL
  102.   6.5) Zugriff auf Oberon-Bezeichner
  103. 7) Der Linker
  104.   7.1) Aufruf, Parameter
  105.   7.2) Environmentvariablen
  106. 8) Die Lader
  107.   8.1) Aufruf, Parameter
  108.   8.2) Ausgabe
  109. 9) Das Make-Utility
  110.   9.1) Aufruf, Parameter
  111.   9.2) Environmentvariablen
  112.   9.3) Hinweise
  113. 10) Der Scanner
  114.   10.1) Aufruf, Parameter
  115.   10.2) Environmentvariablen
  116. 11) Debugging
  117.   11.1) DB
  118.   11.2) Bugaboo
  119.   11.3) Tips
  120. 12) Utilities
  121.   12.1) Der Browser
  122.   12.2) Inline-Zeilen erzeugen
  123. 13) Speicherverwaltung
  124.   13.1) Benutzung in Programmen
  125.   13.2) Implementierung
  126. 14) Die Bibliotheken
  127.   14.1) Betriebssystem
  128.     14.1.1) BIOS
  129.     14.1.2) GEMDOS
  130.     14.1.3) MiNT
  131.     14.1.4) XBIOS
  132.   14.2) Abstrakte Datenstrukturen
  133.     14.2.1) BinTree
  134.     14.2.2) CDCL
  135.     14.2.3) DCL
  136.     14.2.4) FIFO
  137.     14.2.5) LRU
  138.     14.2.6) Stack
  139.   14.3) Standardmodule
  140.     14.3.1) Buffers
  141.     14.3.2) CommandLine
  142.     14.3.3) Cookie
  143.     14.3.4) Datum
  144.     14.3.5) Environment
  145.     14.3.6) Error
  146.     14.3.7) Exceptions
  147.     14.3.8) Execute
  148.     14.3.9) File
  149.     14.3.10) FileBuffer
  150.     14.3.11) Filename
  151.     14.3.12) IO
  152.     14.3.13) Kernel
  153.     14.3.14) Key
  154.     14.3.15) MathCom
  155.     14.3.16) MathLib0
  156.     14.3.17) Memory
  157.     14.3.18) Modules
  158.     14.3.19) MVC
  159.     14.3.20) NumStr
  160.     14.3.21) Paths
  161.     14.3.22) Strings
  162.     14.3.23) Supervisor
  163.     14.3.24) Sys
  164.     14.3.25) Task
  165.     14.3.26) VA
  166.   14.4) VDI-Module
  167.     14.4.1) VDI
  168.     14.4.2) VDIAttributes
  169.     14.4.3) VDIControl
  170.     14.4.4) VDIExcapes
  171.     14.4.5) VDIInput
  172.     14.4.6) VDIInquiry
  173.     14.4.7) VDIOutput
  174.     14.4.8) VDIRaster
  175.   14.5) AES-Module
  176.     14.5.1) AES
  177.     14.5.2) Appl
  178.     14.5.3) Evnt
  179.     14.5.4) Form
  180.     14.5.5) Fsel
  181.     14.5.6) Graf
  182.     14.5.7) Menu
  183.     14.5.8) Objc
  184.     14.5.9) Rsrc
  185.     14.5.10) Wind
  186.   14.6) Erweiterte AES-Module
  187.     14.6.1) Dialogs
  188.     14.6.2) FontSelect
  189.     14.6.3) GemApp
  190.     14.6.4) GEMIO
  191.     14.6.5) Menus
  192.     14.6.6) TermWin
  193.     14.6.7) WindowDialog
  194.     14.6.8) WinView
  195. 15) Tutorial
  196.   15.1) Die Resourcedatei
  197.   15.2) Der Rumpf
  198.   15.3) Resourcedatei laden
  199.   15.4) Die Menüzeile
  200.   15.5) Ein Fenster öffnen
  201.   15.6) Einen Dialog darstellen
  202.   15.7) Das fertige Programm
  203.   15.8) Zusammenfassung
  204. 16) Anhang
  205.   16.1) Literatur
  206.   16.2) Danksagungen
  207.  
  208.  
  209. 1) Einleitung
  210. =============
  211.  
  212. Die Entstehung dieses Oberon-Systems begann kurz vor Weihnachten  '92,  als
  213. Frank Storm mir die Quelltexte zum Oberon-1 Compiler von Niklaus  Wirth  in
  214. die Hand drückte.  Zunächst mußte ich den in Oberon geschriebenen  Compiler
  215. in Modula umschreiben und den Codegenerator auf 68000 ändern.  Der  nächste
  216. Schritt war dann natürlich,  das ganze wieder in Oberon umzuschreiben. Dies
  217. war bis März '93 geschafft,  seitdem programmiere ich nur noch  in  Oberon.
  218. Inzwischen sind etliche Monate vergangen, in denen ich fleißig Fehler beho-
  219. ben und Erweiterungen eingebaut habe. Trotzdem wird noch einige Zeit verge-
  220. hen, bis diese Software den Betateststatus verliert.
  221.  
  222. 1.1) Stand der Entwicklung
  223. --------------------------
  224.  
  225. Der Kern einer Programmiersprache ist natürlich der Compiler.  Dieser  wird
  226. ergänzt durch Linker,  Lader, Make und Scanner. Zusätzlich gibt es noch ei-
  227. nige Utilities.  Alles wird als Objektmodule ausgeliefert und vom Installa-
  228. tionsprogramm zu ausführbaren Programmen gelinkt.   Aber erst durch umfang-
  229. reiche Libraries wird eine Programmiersprache benutzbar. Die meisten Module
  230. sind von mir im Laufe von mehreren Jahren programmiert worden.  Einige sind
  231. auch von anderen Autoren,  und weitere Implementationen sind natürlich  er-
  232. wünscht.
  233.  
  234.   Der Compiler hat bereits starke Erweiterungen gegenüber dem von Wirth er-
  235. fahren.  Dies ist zwar unschön,  weil dadurch wieder Inkompatibilitäten  zu
  236. anderen Compilern entstehen,  aber sie erleichtern die Programmierung. Wenn
  237. man portable Programme schreiben möchte,  muß man auf  diese  Erweiterungen
  238. verzichten.
  239.  
  240. 1.2) Geplante Entwicklung
  241. -------------------------
  242.  
  243. Zunächst steht die Entwicklung einer Load-Time-Linking Entwicklungsumgebung
  244. mit Chatwin auf dem Plan.  Dann fehlt noch  ein  Source-Level-Debugger.  Da
  245. werde ich mich irgenwann mal drangeben.  Die Codequalität könnte auch  noch
  246. verbessert werden, dazu gehört auch 68030- und FPU-Unterstützung. Ansonsten
  247. werden natürlich ständig noch Fehler  behoben  und  Bibliotheksmodule  ver-
  248. bessert.
  249.  
  250. 1.3) Benutzungsbedingungen
  251. --------------------------
  252.  
  253. STJ-Oberon-2 ist Shareware. Die öffentliche Version darf in Mailboxen hoch-
  254. geladen und auf PD-Disketten bis 5 DM pro Diskette vertrieben werden.  Wenn
  255. man dauerhaft damit arbeiten möchte, muß man den Sharewarebeitrag von 50 DM
  256. entrichten.  Dafür bekommt man die neueste Version auf Diskette zugeschickt
  257. (also Adresse nicht vergessen!).  Diese enthält eine private  Version,  die
  258. nicht weitergegeben werden darf.  Darauf ist zusätzlich diese Anleitung als
  259. DVI-File sowie der fehlende optimierende Linker.  Auf Wunsch kann  ich  die
  260. Anleitung auch in eine Postscriptdatei umwandeln.  Möchte jemand  eine  ge-
  261. druckte Anleitung (Laserdrucker) mit Ringbindung, kostet dies 20 DM extra.
  262.  
  263.   Wer am System mitarbeitet oder mitgearbeitet hat,  kann einen individuel-
  264. len Rabatt erhalten. Einfach mal anfragen.
  265.  
  266. 1.4) Fehlermeldungen
  267. --------------------
  268.  
  269. Das ganze System ist noch in der Entwicklungs- und Betatestphase. Ich weiß,
  270. daß es noch einige Macken hat. Ich bemühe mich, sie noch alle zu entfernen.
  271. Ich übernehme keine Garantie für die  Funktionsfähigkeit  dieses  Programms
  272. und hafte nicht für Schäden,  die dieses Programm verursacht.  Falls Fehler
  273. entdeckt werden, sollte man mich möglichst genau darüber informieren.
  274.  
  275. 1.5) Kontakt
  276. ------------
  277.  
  278.   Stephan Junker
  279.   Heuvel 1A
  280.   NL-6291 CP Vaals
  281.  
  282.   E-Mail, MausNet : Stephan Junker @ AC2
  283.  
  284.     Sparkasse Aachen
  285.   Kontonummer : 16013351
  286.   Bankleitzahl: 390 500 00
  287.  
  288.  
  289. 2) Von Modula-2 nach Oberon-2
  290. =============================
  291.  
  292. Für diejenigen,  die Modula kennen und evtl.  umsteigen möchten,  werde ich
  293. hier kurz die Unterschiede zwischen Modula-2  und  Oberon-2  auflisten.  Es
  294. soll keineswegs eine Sprachbeschreibung ersetzen,  sondern nur  einen  Ein-
  295. druck von den neuen Möglilchkeiten vermitteln, um das Interesse zu wecken.
  296.  
  297. 2.1) Streichungen
  298. -----------------
  299.  
  300. Niklaus Wirth hatte den Mut,  einige Features  von  Modula-2  ersatzlos  zu
  301. streichen.  Dahinter stand das Konzept, die Sprache Oberon auf das Wichtig-
  302. ste zu konzentrieren und damit einen kleinen,  schnellen Compiler zu reali-
  303. sieren.  Diese Streichungen sind nicht bei allen  Modula-Programmieren  auf
  304. Gegenliebe gestoßen, aber man kann damit leben.
  305.  
  306. 2.1.1) Datentypen
  307. .................
  308.  
  309. _Variante Records_ wurden eliminiert, da sie die Implementation einer Spei-
  310. cherverwaltung mit Garbage Collector im  Wege  stand.  Ihre  Funktionalität
  311. wurde durch erweiterbare Typen erhalten[1].
  312. _Opake Typen_ wurden überflüssig,  da man Records nicht mehr  komplett  ex-
  313. portieren muß. Die Auswahl einzelner Feldelemente ist wesentlich flexibler.
  314. _Aufzählungstypen_ standen der  Erweiterung  über  Modulgrenzen  hinweg  im
  315. Wege.  Außerdem führte ein Import des Typbezeichners zum impliziten  Import
  316. aller assoziierten Konstantenbezeichner.
  317. _Unterbereichstypen_ hatten nicht den Nutzen,  der die dafür nötige zusätz-
  318. liche Komplexität des Compilers rechtfertigt.
  319. _Mengen_ wurden zu einem einzigen  Typ  reduziert:  SET.  Diese  Menge  be-
  320. inhaltet alle Zahlen von 0 bis  zu  einem  implementationsabhängigen  Maxi-
  321. mum[2]. Dies resultiert aus der Elimination von Aufzählungs- und Unterbereichstypen.
  322. Der Typ _CARDINAL_ wurde eliminiert,  da die Benutzung  von  32-Bit  Werten
  323. dies unnötig macht[3].
  324. _Zeigertypen_ können nur noch auf Records und Arrays zeigen. Dies hängt da-
  325. mit zusammen, das der Zeigeroperator '^' nicht mehr benutzt werden muß.
  326. _Indextypen_ können nicht mehr angegeben werden.  Stattdessen gibt man  nur
  327. noch die Anzahl Elemente des Arrays an.
  328.  
  329. ---------------
  330.  
  331.  [1]  nicht ganz, wie ich meine
  332.  
  333.  [2]  bei STJ-Oberon-2 ist das Maximum 31
  334.  
  335.  [3]  man beachte, daß damit keine vorzeichenlosen Vergleiche möglich sind
  336.  
  337.  
  338. 2.1.2) Module und Import-/Exportregeln
  339. ......................................
  340.  
  341. _Lokale Module_ wurden eliminiert, da sie nur selten benutzt wurden und den
  342. Compiler unnötig schwierig machten.
  343. _Unqualifizierter Export_ ist nicht mehr möglich,  d.h.  man gibt nur  noch
  344. den Namen eines Moduls in der Importliste an und  muß  immer  mit  vorange-
  345. stelltem Modulbezeichner auf die exportierten Bezeichner zugreifen.  Um die
  346. Tipparbeit ein wenig zu reduzieren,  ist es  möglich,  den  Import  umzube-
  347. nennen. Dafür schreibt man beim Import 'Abk:=Abkuerzung', z.B. 'WDial:=WindowDialog'.
  348. Das _Hauptmodul_ als solches gibt es nicht mehr. Alle Module sind gleichbe-
  349. rechtigt, d.h. daß auch alle Module linkfähig sind.
  350. _Definitionsmodule_ sind für den Compiler nicht mehr nötig, aber man sollte
  351. sie natürlich für den Programmierer erzeugen.  Dafür ist der Browser vorge-
  352. sehen.  Der Export geschieht jetzt, indem man hinter einem Bezeichner einen
  353. Stern für normalen oder ein Minuszeichen (bei Variablen und  Feldelementen)
  354. für Read-Only Export angibt.
  355.  
  356. 2.1.3) Anweisungen
  357. ..................
  358.  
  359. Die _WITH-Anweisung_ wurde eliminiert,  da der qualifizierte Zugriff zu be-
  360. vorzugen ist. Diese Anweisung hat in Oberon jetzt eine andere Funktion.
  361.  
  362. 2.1.4) Low-Level Anweisungen
  363. ............................
  364.  
  365. _ADDRESS_ und _WORD_ wurden durch BYTE ersetzt.  _Typumwandlungsfunktionen_
  366. mit vorangestelltem Typbezeichner und _absolute Addressierung_ wurden  eli-
  367. miniert.
  368.  
  369. 2.2) Neue Features
  370. ------------------
  371.  
  372. 2.2.1) Typerweiterung
  373. .....................
  374.  
  375. Es ist möglich, einen bestehenden Recordtyp zu erweitern.
  376. Beispiel: Wenn Typ Point so
  377.  
  378. Point = RECORD x,y : INTEGER END
  379.  
  380. definiert ist, kann man ihn so
  381.  
  382. Rect = RECORD(Point)  w,h : INTEGER END
  383.  
  384. erweitern.  Typ Rect hat dann die Elemente x,y,w,h.  Dann ist  es  möglich,
  385. Prozeduren zu definieren,  die einen Typ Point als Parameter erwarten,  und
  386. diesen einen Typ Rect zu übergeben.  Analog gilt dies für Zeiger auf solche
  387. Typen.  Mit einem Typeguard der Form var(typ) kann man zur Compilezeit  den
  388. Typen festlegen. Zur Laufzeit wird dann überprüft, ob die Variable var tat-
  389. sächlich den Typ typ hat. Wenn nicht, wird das Programm abgebrochen. Es ist
  390. auch möglich, den Typ einer Variablen abzufragen. Der Ausdruck
  391.  
  392. var IS typ
  393.  
  394. liefert TRUE, wenn var vom (dynamischen) Typ typ ist.
  395.  
  396.   Diese Abfrage inklusive eines regionalen  Typeguards  leistet  das  WITH-
  397. Statement:
  398.  
  399. WITH var : Point DO (* wenn var vom typ Point ist *)
  400.        var.x := 0      (* dann x löschen *)
  401.    | var : Rect DO     (* ist es ein Rect *)
  402.        var.w := 0      (* dann w löschen *)
  403.    ELSE                (* sonst *)
  404.    END;                (* nichts *)
  405.  
  406. 2.2.2) Typgebundene Prozeduren
  407. ..............................
  408.  
  409. Es ist möglich, Prozeduren an einen Recordtyp zu binden. In der Sprache des
  410. OOP sind dies dann Methoden,  die auf dem Typ arbeiten, an den sie gebunden
  411. sind.  Im Gegensatz zu anderen Ansätzen werden bei Oberon jedoch keine  Be-
  412. zeichner implizit übergeben, sondern explizit angegeben. Eine solche Proze-
  413. dur wird so
  414.  
  415. PROCEDURE (VAR p : Point) Clear;
  416.  BEGIN
  417.   p.x := 0; p.y := 0;
  418.  END;
  419.  
  420. definiert und mit
  421.  
  422. point.Clear
  423.  
  424. aufgerufen. Statt VAR Point könnte man auch einen Zeiger auf Point ohne VAR
  425. angeben.  Man kann jetzt hingehen und eine Prozedur Clear an  Rect  binden.
  426. Der Name ist nicht etwa schon benutzt,  denn er ist ja nur innerhalb  eines
  427. Typs Point sichtbar.
  428.  
  429. PROCEDURE (VAR r : Rect) Clear;
  430.  BEGIN
  431.   r.w := 0; r.h := 0;
  432.   r.Clear^;
  433.  END;
  434.  
  435. Dieses Clear löscht erst w und h,  um dann mit r.Clear^die geerbte Prozedur
  436. Clear aufzurufen, die x und y löscht.
  437.  
  438. 2.2.3) Typinklusion
  439. ...................
  440.  
  441. Die Integer- und Realtypen sind jeweils Teilmengen des nächst größeren  Be-
  442. reichs. Daher ergibt sich folgende Hierarchie:
  443. LONGREAL > REAL > LONGINT > INTEGER > SHORTINT
  444. Das bedeutet,  daß ein Wert eines untergeordneten Typs  einem
  445. höheren zugewiesen werden kann.
  446.  
  447. 2.3) Sonstige Unterschiede
  448. --------------------------
  449.  
  450. _Prozedurtypen_ werden mit Dummynamen für die Parameter angegeben.
  451. _Globale Variablendeklarationen_ müssen immer vor der ersten Prozedur erfolgen.
  452.  
  453.  
  454. 3) Allgemeine Erläuterungen
  455. ===========================
  456.  
  457. 3.1) Suchpfade
  458. --------------
  459.  
  460.  Suchpfade sind solche Pfade, in denen nach Dateien gesucht wird. Viele der
  461. Systemprogramme benötigen Suchpfade, aber alle bauen auf einem Modul namens
  462. Paths  auf.   Daher  verlangen  alle  Programme  den  gleichen  Aufbau  der
  463. Suchpfade.  Definiert werden sie mit  einer  Environmentvariablen.  Mehrere
  464. Suchpfade müssen mit Komma oder Semikolon getrennt werden. Ein Backslash am
  465. Ende ist möglich,  aber nicht nötig.  Eine kleine Möglichkeit für Wildcards
  466. ist vorgesehen:  Der letzte Order einer  Suchpfaddefinition  darf  ein  '*'
  467. sein,  so daß alle Ordner in diesem Directory durchsucht werden.  Die Suche
  468. beginnt immer mit dem zuletzt angegebenen Pfad.
  469. Beispiel: MODPATH=E:\OBERON\GEM,E:\OBERON\STD\
  470. Damit  können  alle  Dateien  gefunden  werden,  die  den  Mustern  E:\OBE-
  471. RON\GEM\*.*und E:\OBERON\STD\*.*genügen.
  472. Beispiel: MODPATH=E:\OBERON\LIB\*
  473. Damit können alle Dateien gefunden werden, die den Mustern E:\OBERON\LIB\*\*.*genügen.
  474. Wenn im folgenden also von 'Suchpfaden' die Rede ist,  sind  Environmentva-
  475. riable mit obigem Inhalt gemeint.
  476.  
  477.   Eine Besonderheit der Suchpfade möchte  ich  hier  schon  erwähnen:  Eine
  478. sinnvolle Einstellung ist es,  nur MODPATH zu definieren.  Dann wird  immer
  479. dort gesucht und Ausgaben des Compilers werden bei den Sourcen gespeichert.
  480. In dieser Form werden die Dateien auch veröffentlicht. Es ist aber möglich,
  481. die verschiedenen Dateitypen in getrennten Ordnern zu  bewahren.  Dazu  muß
  482. man für jeden Dateityp einen Suchpfad definieren und die Ausgaben des  Com-
  483. pilers werden in den letzten Suchpfad geschrieben.  Diese Suchpfade  heißen
  484. OBJPATH, SYMPATH und INFPATH.
  485.  
  486. 3.2) Dateien
  487. ------------
  488.  
  489. Das System unterscheidet vier verschiedene Dateien:
  490.  
  491.   1) Die Quelltexte mit der Extension MOD.
  492.  
  493.   2) Die Objektmodule mit der Extension OBJ.  Diese nehmen den  Code  eines
  494.      Moduls auf.
  495.  
  496.   3) Die Symboldateien mit der Extension SYM. Diese enthalten Informationen
  497.      über exportierte Bezeichner.
  498.  
  499.   4) Die Infodateien mit der Extension INF. Diese enthalten zusätzliche In-
  500.      formationen zu Modulen.  Momentan sind das zum Beispiel ein  Programm-
  501.      name und Optimierungsinformationen. Später sollen die Infodateien dann
  502.      auch Informationen für den Source Level Debugger aufnehmen.
  503.  
  504.   5) Die Fehlerdateien mit der Extension ERR.  Darin werden Fehler, die der
  505.      Compiler findet, in einem frei wählbaren Format notiert.
  506.  
  507. 3.3) Einstellung der Shell
  508. --------------------------
  509.  
  510. DIe Shell,  mit der man arbeitet, sollte man mittels Batchfile beim Starten
  511. schon vernünftig konfigurieren. Dies ist ein Beispiel-Setup für Chatwin:
  512.  
  513. alias make e:\oberon\Make.TTP $*
  514.     alias opt e:\oberon\OPTIMIZE.TTP $*
  515.     alias scan e:\oberon\SCAN.TTP $*
  516.     alias lt e:\oberon\LOAD.TTP $*
  517.     alias lg e:\oberon\LOAD.PRG $*
  518.     alias browse e:\oberon\browse.ttp $*
  519.     env OC=e:\oberon\compile.ttp
  520.     env MODPATH=E:\OBERON\LIB\*
  521.     env LINKALSO=Exceptio
  522.  
  523.   Desweiteren empfiehlt es sich,  für jedes Projekt  eine  Batchdatei  ein-
  524. zurichten,  in der Pfade,  Namen, Extension etc. definiert werden. Hier ist
  525. mal ein Beispiel, daß ich für das Installationsprogramm verwende:
  526.  
  527. env MODPATH=E:\OBERON\LIB\*,E:\OBERON\INSTALL\
  528.     env PRGEXT=PRG
  529.     env PRGPATH=E:\OBERON\
  530.     env LINKALSO=Exceptio
  531.     dellist *
  532.     addlist e:/oberon/install/install.mod
  533.     addlist e:/oberon/install/linker.mod
  534.     addlist e:/oberon/install/syminld.mod
  535.  
  536.  
  537. 4) Installation
  538. ===============
  539.  
  540.  Das Installationsprogramm INSTALL.PRG ist das einzig  lauffähige  Programm
  541. in der Distribution. Es erzeugt alle Programme, die für die Arbeit mit STJ-
  542. Oberon-2 benötigt werden.
  543.  
  544. 4.1) Start
  545. ----------
  546.  
  547. Beim Start von Install erscheint eine Dialogbox.  Dort sieht  man  zunächst
  548. neun Buttons mit jeweils einem Namen dran.  Selektiert sind alle  Programme
  549. außer Oberon[4]. Wählen sie die Programme, die sie haben wollen.
  550.  
  551.   Stellen sie nun ein, ob die Programme eine Symboltabelle haben oder opti-
  552. miert[5] werden sollen.  Die Symboltabelle kostet nur unnötig  Platz,  also
  553. verzichten sie lieber darauf.
  554.  
  555.   Als letztes können sie einen Zielpfad für die Programme  angeben.  Dieser
  556. wird anfangs auf den Pfad gesetzt,  in dem auch  das  Installationsprogramm
  557. steht.
  558.  
  559.   Wenn sie nun den Knopf 'Installieren' anwählen,  verschwindet die Dialog-
  560. box und ein Terminalfenster wird geöffnet. Dort erscheinen die Ausgaben des
  561. Linkers, der alle selektierten Programme linkt. Dabei sind die Suchpfade so
  562. eingestellt, wie sie in der Distribution sind, also LIB\*\,SYS\ und TOOLS\,
  563. jeweils vom Directory ausgehend,  in dem das  Installationsprogramm  steht.
  564. Wenn sie also gerade erst das Archiv ausgepackt haben und dabei die Ordner-
  565. struktur nicht verloren ging, müssen die Module auch gefunden werden.
  566.  
  567.   Hinweis:  Im Prinzip ist der Linker auch in der Lage,  die Tätigkeit  des
  568. Installationsprogramms durchzuführen. Lediglich die Lader und Oberon können
  569. nicht vom normalen Linker gelinkt werden.
  570.  
  571. ---------------
  572.  
  573.  [4]  denn Oberon gibt's noch nicht
  574.  
  575.  [5]  Die Optimierung funktioniert leider noch nicht
  576.  
  577.  
  578.  
  579. 5) Der Compiler
  580. ===============
  581.  
  582.   Der Compiler des Oberon-Systems (COMPILE.OBJ/TTP) entstand aus  dem  Obe-
  583. ron-1 Compiler von Niklaus Wirth.  Er wurde unter anderem um einen Makroas-
  584. sembler erweitert und ist jetzt weitgehend auf Oberon-2-Standard.
  585.  
  586. 5.1) Aufruf, Parameter
  587. ----------------------
  588.  
  589.   Der Compiler sollte von einer Shell aus benutzt werden,  die zumindest in
  590. der Lage ist,  Environmentvariablen zu setzen, denn der Compiler liest dort
  591. seine Optionen.  Beim Aufruf kann man als Kommando  einige  Optionen  sowie
  592. eine Liste von Namen,  getrennt mit Leerzeichen,  übergeben.  Diese  Module
  593. werden nacheinander übersetzt. Die Syntax sieht also so aus:
  594.  
  595. compile {<Option>} <Name> {<Name>}
  596.  
  597. Das Format des Namens wird flexibel gehandhabt.  Ein  Name  mit  Pfadangabe
  598. wird dort zuerst gesucht.  Danach wird er wie ein Name  ohne  Pfad  in  den
  599. Suchpfaden gesucht.  Wird keine Datei gefunden,  wird der  Compiler  wieder
  600. verlassen. In jedem Fall wird der Name mit der Extension MOD versehen.
  601. Die Optionen haben die allgemeine Syntax:
  602.  
  603. -<Option><Parameter>
  604.  
  605. Die Art der Option wird mit einem Buchstaben (groß oder  klein)  angegeben,
  606. eventuelle Parameter folgen ohne Leerzeichen.  Einige Optionen sind  sowohl
  607. über Environmentvariablen als auch über Kommandozeile setzbar.  Dabei gilt:
  608. Die Option in der Kommadozeile hat höhere Priorität.
  609. Folgende Optionen sind implementiert:
  610.  
  611. -e: Weist den Compiler an,  bei dem ersten gefundenen Fehler den  Programm-
  612.     lauf abzubrechen.  Normalerweise wird die Datei komplett übersetzt  und
  613.     die Fehler in einer Datei gespeichert.
  614.  
  615. -w: Schaltet die Ausgabe von Warnungen ein.  Warnungen werden erzeugt, wenn
  616.     ein Fehler des Programmierers vorliegen könnte,  die der Compiler  aber
  617.     übersetzen kann.  Dies wird zum Beispiel bei Schreibzugriffen auf  glo-
  618.     bale Variable eines anderen Moduls getan.  Warnungen  werden  normaler-
  619.     weise unterdrückt.
  620.  
  621. -i: Schaltet den Indexcheck aus,  da er defaultmäßig eingeschaltet ist. In-
  622.     dexcheck bewirkt eine Überprüfung  der  Arraygrenzen  von  Indizes  zur
  623.     Laufzeit und ist mit einer geringfügigen Verlängerung  des  Codes  ver-
  624.     bunden. Ein falscher Index bewirkt eine CHK-Exception.
  625.  
  626. -t: Schaltet den Typcheck aus,  der ebenfalls  normalerweise  eingeschaltet
  627.     ist. Wenn er eingeschaltet ist, wird bei jedem Typeguard geprüft, ob es
  628.     sich auch um den korrekten Recordtyp handelt.  Ein falscher Typ bewirkt
  629.     die Ausgabe einer Fehlermeldung und anschließenden Programmabbruch.
  630.  
  631. -a: Schaltet den Arithmetikcheck aus,  der defaultmäßig eingeschaltet  ist.
  632.     Dieser Check soll Über- und Unterlauf von  Realzahlen  überprüfen,  ist
  633.     aber noch nicht implementiert.
  634.  
  635. -s|<pos>|: Diese Option bewirkt,  daß der Compiler bei Erreichen der  Posi-
  636.     tion pos im erzeugten Code den Programmlauf mit einer Meldung abbricht.
  637.     Mit dieser Funktion läßt der Scanner  die  Absturzstelle  im  Quelltext
  638.     finden.
  639.  
  640. -o: Wenn die Option -s benutzt wird und der Compiler bricht ab,  so gibt er
  641.     einige Zeilen vor und nach dem Abbruchpunkt aus, falls diese Option ge-
  642.     setzt wird.
  643.  
  644. 5.2) Environmentvariablen
  645. -------------------------
  646.  
  647. Der Compiler wertet auch einige Environmentvariablen aus.  Sie müssen immer
  648. großgeschrieben und von einem = gefolgt sein.  Gesetzt werden  sie  in  der
  649. Shell und jedem Programm übergeben, daß von dieser Shell aufgerufen wird.
  650.  
  651. Es werden folgende Variablen ausgewertet:
  652.  
  653. MODPATH: Gibt die Suchpfade (Kap.??) an, in denen nach dem zu übersetzenden
  654.     Modul gesucht wird.
  655.  
  656. SYMPATH: Gibt die Suchpfade an,  in denen nach den Symboldateien der impor-
  657.     tierten Module gesucht wird.  Ist SYMPATH definiert, wird ein evtl. er-
  658.     zeugtes SYM-File in den letzten Pfad geschrieben, der bei SYMPATH ange-
  659.     geben ist.  Ist SYMPATH nicht definiert,  werden die Suchpfade von MOD-
  660.     PATH übernommen und das SYM-File wird in denselben Ordner  geschrieben,
  661.     in dem die Source war.
  662.  
  663.       Anmerkung:  Eine Symboldatei wird nur erzeugt,  wenn sie  noch  nicht
  664.     existiert oder sich geändert hat.
  665.  
  666. OBJPATH: Die erzeugte Objektdatei wird in den letzten Pfad geschrieben, der
  667.     mit dieser Variablen definiert wird.  Ist OBJPATH nicht definiert, wer-
  668.     den die Suchpfade von MODPATH übernommen und das OBJ-File wird in  den-
  669.     selben Ordner geschrieben, in dem die Source war.
  670.  
  671. INFPATH: Die erzeugte Infodatei wird in den letzten Pfad  geschrieben,  der
  672.     mit dieser Variablen definiert wird.  Ist INFPATH nicht definiert, wer-
  673.     den die Suchpfade von MODPATH übernommen und das INF-File wird in  den-
  674.     selben Ordner geschrieben, in dem die Source war.
  675.  
  676.     Anmerkung: Ein Info-File wird nur erzeugt, wenn es nötig ist.
  677.  
  678. INXCHK: Der Inhalt der Variablen darf die Werte ON oder  OFF  haben.  Damit
  679.     wird der Indexcheck ein- oder ausgeschaltet,  der normalerweise  einge-
  680.     schaltet ist.
  681.  
  682. TYPCHK: Wie INXCHK, jedoch für den Typcheck.
  683.  
  684. ARICHK: Wie INXCHK, jedoch für den Arithmetikcheck.
  685.  
  686. ERRDIST: Der Inhalt der Variablen muß eine Dezimalzahl sein,  die  den  Ab-
  687.     stand zwischen zwei Fehlermeldungen in Zeichen angibt.  Dieser  Abstand
  688.     bewirkt,  daß weniger Folgefehler eines Fehlers ausgegeben werden.  Der
  689.     Standardwert ist 20, das bedeutet: Wenn nach einem erkannten Fehler in-
  690.     nerhalb der nächsten 20 Zeichen nochmal ein Fehler  auftritt,  wird  er
  691.     nicht ausgegeben.
  692.  
  693. MAXERR: Der Inhalt ist wieder eine Dezimalzahl,  die angibt, nach wievielen
  694.     ausgegebenen Fehlern keine weiteren Fehler mehr ausgegeben werden  sol-
  695.     len. Normalerweise sind dies 100 Fehler.
  696.  
  697. ERRFORM: Der Inhalt dieser Variablen ist ein String.  Damit ist es möglich,
  698.     das Format einer Fehlermeldung einzustellen.  Prinzipiell kann man sich
  699.     den Dateinamen mit \d,  die Zeilennummer mit  \z,  die  Spalte  mit  \s
  700.     (beide zählend ab 1),  die absolute Position mit \p und  natürlich  die
  701.     Fehlermeldung selbst mit \f ausgeben lassen. Diese Teile werden dort in
  702.     der Zeile eingefügt,  wo die Kürzel mit '\' stehen.  Der  standardmäßig
  703.     gesetzte String lautet:
  704.  
  705.     "Error \d \z : \s \f"
  706.  
  707.     Damit sieht eine Fehlermeldung so aus:
  708.  
  709.       Error DATEI ZEILE : SPALTE FEHLERMELDUNG
  710.  
  711. WARNOUT: Werte ON/OFF sind erlaubt.  Schaltet die Ausgabe von Warnungen ein
  712.     oder aus. Normalerweise werden keine Warnungen ausgegeben.
  713.  
  714. 5.3) Optionen im Quelltext
  715. --------------------------
  716.  
  717.   Für die Angabe von Optionen in Quelltexten ist die  übliche  Konstruktion
  718. (*$...*) reserviert.  Solche Optionen haben die höchste Priorität.  Es kann
  719. immer nur eine Option angegeben werden.  Zwischen $ und dem  Kennbuchstaben
  720. darf kein Leerzeichen sein. Hinter den Parametern darf noch beliebiger Kom-
  721. mentar folgen.
  722.  
  723. (*$I?*): Damit kann der Indexcheck bestimmt werden.  Das Fragezeichen  darf
  724.     '+',  '-' oder '=' sein.  Hinter dem I darf kein Leerzeichen sein.  Ein
  725.     '+' schaltet den Indexcheck ein, '-' aus und '=' stellt den vorigen Zu-
  726.     stand wieder her.
  727.  
  728.     Diese Option ist nur im Oberon-Teil verfügbar.
  729.  
  730. (*$T?*): Wie I für den Typcheck.  Eingeschalteter Typcheck bewirkt eine Ty-
  731.     püberprüfung bei jedem Zugriff auf den gesamten  Record.  Diese  Option
  732.     ist nur im Oberon-Teil verfügbar.
  733.  
  734. (*$A?*): Wie I für den Arithmetikcheck.  Wird im Moment noch  nicht  unter-
  735.     stützt. Die Routinen im Modul System (Grundrechenarten) melden arithme-
  736.     tische Fehler, auch ohne diesen Check.
  737.  
  738.     Diese Option ist nur im Oberon-Teil verfügbar.
  739.  
  740. (*$N?*) Diesmal gibt das Fragezeichen einen Dateinamen an. Unter diesem Na-
  741.     men wird später das gelinkte Programm gespeichert. Vor dem Namen dürfen
  742.     ausnahmsweise auch Leerzeichen stehen.  Wird der Name mit Pfad  angege-
  743.     ben, wird das Programm dort gespeichert, ansonsten im Pfad PRGPATH oder
  744.     beim Modul. Der Name wird dem Linker über die Infodatei mitgeteilt.
  745.  
  746.     Diese Option ist nur im Oberon-Teil verfügbar.
  747.  
  748. (*$O?*) Wenn ein '-' angegeben wird,  wird der folgende Code bei der  Opti-
  749.     mierung nicht angerührt. Bei O+ wird die Optimierung wieder zugelassen.
  750.     Es darf keine Verschachtelung stattfinden.
  751.  
  752.     Diese Option ist auch im Assembler verfügbar.
  753.  
  754. (*$V+?*) Das Fragezeichen muß den Namen einer Environmentvariablen  angege-
  755.     ben.  Es bedeutet:  Der nun folgende Code soll bei der Optimierung  nur
  756.     dann im Programm gelassen  werden,  wenn  die  Environmentvariable  zum
  757.     Zeitpunkt der Optimierung definiert ist.  Der Wert ist dabei  beliebig.
  758.     Der Compiler kümmert sich nicht weiter darum und  übersetzt  alles,  es
  759.     ist also keine bedingte Compilierung.  Es ist nämlich  wesentlich  fle-
  760.     xibler: Wenn man die Form des Codes (z.B. für verschiedene Zielrechner)
  761.     ändern möchte, muß man nicht irgendwo einen Wert ändern und alle Module
  762.     neu übersetzen  und  linken.  Stattdessen  braucht  man  nur  die  ent-
  763.     sprechenden Variablen zu setzen oder zu löschen und die Optimierung  zu
  764.     starten. Der Linker erzeugt dann das gewünschte Programm.
  765.  
  766.     Diese Option ist auch im Assembler verfügbar.
  767.  
  768.     Beispiel:
  769.  
  770.     (*V+ DEBUG *) (* drinlassen wenn Debugversion *)
  771.       IO.WriteString(...)
  772.     (*V=*)
  773.  
  774.     Wenn die Environmentvariable DEBUG definiert ist,  wird beim Optimieren
  775.     die zusätzliche Ausgabe dringelassen.
  776.  
  777. (*$V-?*) Wie oben,  jedoch wird der folgende Code nur dann  entfernt,  wenn
  778.     die Variable definiert ist.
  779.  
  780.     Diese Option ist auch im Assembler verfügbar.
  781.  
  782. (*$V+?=...*) und (*$V-?=...*) Wie oben, jedoch wird auch der Inhalt der Va-
  783.     riablen angegeben.  Die Bedingung ist also erfüllt,  wenn die  Variable
  784.     definiert ist und den angegebenen  Wert  hat  (beliebiger  String  ohne
  785.     Leerzeichen).
  786.  
  787.     Diese Option ist auch im Assembler verfügbar.
  788.  
  789. (*$V=*) Damit wird die Abhängigkeit von allen vorher angegebenen  Variablen
  790.     ausgeschaltet.
  791.  
  792.     Diese Option ist auch im Assembler verfügbar.
  793.  
  794. 5.4) Ausgabe
  795. ------------
  796.  
  797. Der Compiler erzeugt eine neue Objektdatei, wenn die Übersetzung fehlerfrei
  798. war.  Ist die dabei erzeugte Symboldatei anders als die bisherige oder exi-
  799. stierte bisher Keine,  so wird die neue Symboldatei abgespeichert.  War die
  800. Übersetzung fehlerhaft,  wird die Fehlerdatei abgespeichert.  Die Symbolda-
  801. teien benötigt der Compiler,  um beim Import die dort exportierten Bezeich-
  802. ner zu lesen.  Die Objektdateien benötigt der Linker,  wenn er ein Programm
  803. zusammensetzt.  Evtl.  wird auch eine Infodatei erzeugt,  die unter anderem
  804. einen Programmnamen aufnimmt.
  805.  
  806.   Das Format der Objektdateien enspricht fast dem eines normalen Programms.
  807. Es hat einen 28 Byte langen Programmheader,  es folgen der Code, die Daten,
  808. die Symboltabelle und die Reloziertabelle. Die Symboltabelle entspricht dem
  809. erweiterten GST-Format.  Durch dieses Format der Objektdateien ist es  mög-
  810. lich,  sowohl komplette Module mit einem beliebigen Assembler zu schreiben,
  811. als auch vom Compiler erzeugte  Objektdateien  zu  disassemblieren  und  zu
  812. überarbeiten.  Letzteres kann für die Geschwindigkeitsoptimierung hilfreich
  813. sein,  denn es ist einfacher, einen bestehenden Assemblertext zu verbessern
  814. als etwas direkt in Assembler zu schreiben.  Das Format des  Symboltabellen
  815. ist nicht mehr kompatibel zu dem von N. Wirth, da einige zusätzliche Infor-
  816. mationen benötigt wurden.
  817.  
  818. 5.5) Vordefinierte Prozeduren
  819. -----------------------------
  820.  
  821. Die folgenden Tabellen zeigen die vordefinierten Funktionen und  Prozeduren
  822. von Oberon-2 inklusive der Erweiterungen bei STJ-Oberon-2.  Diese sind  mit
  823. einem Stern markiert und sind nicht portabel.  v steht für eine Variable, x
  824. und n für Ausdrücke,  a für Adresse und T für einen Typ.  Integer  bedeutet
  825. einen der Integertypen SHORTINT, INTEGER oder LONGINT.
  826.  
  827.   _Funktionen:_
  828.  
  829. +-------------+--------------+-------------+-----------------------+
  830. | Name        | Argumenttyp  | Ergebnistyp | Funktion              |
  831. +-------------+--------------+-------------+-----------------------+
  832. | ABS(x)      | Numerische   | Typ von x   | Absolutwert           |
  833. |             | Typen        |             |                       |
  834. | ASH(x,n)    | x,n: Integer | Typ von x   | x * 2^n               |
  835. | CAP(x)      | CHAR         | CHAR        | Großbuchstabe         |
  836. | CHR(x)      | Integer      | CHAR        | Zahl in CHAR          |
  837. |             |              |             | umwandeln             |
  838. | ENTIER(x)   | Realtyp      | LONGINT     | Größtes Integer nicht |
  839. |             |              |             | größer als x          |
  840. | TRUNC(x) *  | Realtyp      | LONGINT     | Integeranteil         |
  841. | LEN(v,n)    | v: Array;    | INTEGER     | Länge von v in        |
  842. |             | n: Integer-  |             | Dimension n           |
  843. |             | konstante    |             | (0 = erste Dim.)      |
  844. | LEN(v)      | v: Array     | INTEGER     | entspricht LEN(v,0)   |
  845. | LONG(x)     | SHORTINT     | INTEGER     | erweitern             |
  846. |             | INTEGER      | LONGINT     |                       |
  847. |             | REAL         | LONGREAL    |                       |
  848. | MAX(T)      | T = Basistyp | T           | Maximalwert von T     |
  849. |             | T = SET      | INTEGER     | Maximales             |
  850. |             |              |             | Mengenelement         |
  851. | MIN(T)      | T = Basistyp | T           | Minimalwert von T     |
  852. |             | T = SET      | INTEGER     | 0                     |
  853. | ODD(x)      | Integer      | BOOLEAN     | x MOD 2 = 1           |
  854. | ORD(x)      | CHAR         | INTEGER     | Ordinalzahl von x     |
  855. | SHORT(x)    | LONGINT      | INTEGER     | nächst kleinerer Typ  |
  856. |             | INTEGER      | SHORTINT    |                       |
  857. |             | LONGREAL     | REAL        |                       |
  858. | SIZE(T)     | jeder Typ    | Integer     | Anzahl Bytes,         |
  859. |             |              |             | die T belegt          |
  860. +-------------+--------------+-------------+-----------------------+
  861.  
  862. _Prozeduren:_
  863.  
  864. +--------------------+-------------------------------+---------------------+
  865. | Name               | Argumenttyp                   | Funktion            |
  866. +--------------------+-------------------------------+---------------------+
  867. | COPY(x,v)          | x: Char. Array, String;       | v := x              |
  868. |                    | v: Char. Array                |                     |
  869. | DEC(v)             | Integer                       | v := v-1            |
  870. | DEC(v,n)           | v,n: Integer                  | v := v-n            |
  871. | EXCL(v,x)          | v: SET; x: Integer            | v := v - {x}        |
  872. | HALT(x)            | Integerkonstante              | Programm beenden    |
  873. | INC(v)             | Integer                       | v := v+1            |
  874. | INC(v,n)           | v,n: Integer                  | v := v+n            |
  875. | INCL(v,x)          | v: SET; x: Integer            | v := v + {x}        |
  876. | NEW(v)             | Zeiger                        | v^   allozieren     |
  877. | NEW(v,x_0,...,x_n) | v : Zeiger auf offenes Array; | v^   mit Längen     |
  878. |                    | x_i: Integer                  | x_0..x_n allozieren |
  879. +--------------------+-------------------------------+---------------------+
  880.  
  881.  
  882.   _Funktionen in SYSTEM:_
  883.  
  884. +-------------+------------------+-------------+-------------------------+
  885. | Name        | Argumenttyp      | Ergebnistyp | Funktion                |
  886. +-------------+------------------+-------------+-------------------------+
  887. | ADR(v)      | alle             | LONGINT     | Adresse von v           |
  888. | ANL(a,b) *  | a,b: Integer     | wie a,b     | bitweise Und            |
  889. | BIT(a,n)    | a: LONGINT       | BOOLEAN     | Bit n von Mem[a]        |
  890. |             | n: Integer       |             |                         |
  891. | CC(n)       | Integerkonstante | BOOLEAN     | Bedingung n (0≤n≤15)    |
  892. | LONG(a) *   | SHORTINT         | INTEGER     | vorzeichenlos erweitern |
  893. |             | INTEGER          | LONGINT     |                         |
  894. | LSH(x,n)    | x: Integer,      | Typ von x   | logischer Shift         |
  895. |             | CHAR,BYTE        |             |                         |
  896. |             | n: Integer       |             |                         |
  897. | NTL(a) *    | a: Integer       | wie a       | bitweise invertieren    |
  898. | ORL(a,b) *  | a,b: Integer     | wie a,b     | bitweise Oder           |
  899. | ROT(x,n)    | x: Integer       | Typ von x   | Rotation                |
  900. |             | CHAR,BYTE        |             |                         |
  901. |             | n: Integer       |             |                         |
  902. | VAL(T,x)    | T,x: alle Typen  | T           | x als Typ T auffassen   |
  903. | XOL(a,b) *  | a,b: Integer     | wie a,b     | bitweise Exklusiv Oder  |
  904. +-------------+------------------+-------------+-------------------------+
  905.  
  906. _Prozeduren in SYSTEM:_
  907.  
  908. +----------------+---------------------+------------------------+
  909. | Name           | Argumenttyp         | Funktion               |
  910. +----------------+---------------------+------------------------+
  911. | DISPOSE(p)     | Zeiger              | gibt den Speicher frei |
  912. | GET(a,v)       | a: LONGINT          | v := Mem[a]            |
  913. |                | v: einfache Typen   |                        |
  914. | GETREG(n,v)    | n: Integerkonstante | v := Register n        |
  915. |                | v: einfache Typen   | (0≤n≤15)               |
  916. | INLINE(...) *  | Wortkonstanten      | fügt die Konstanten    |
  917. |                |                     | in den Code ein        |
  918. | MOVE(a0,a1,n)  | a0,a1: LONGINT      | n Bytes bei a0         |
  919. |                | n: Integer          | nach a1 kopieren       |
  920. | NEW(v,n)       | v: Zeiger, LONGINT  | n Bytes allozieren     |
  921. |                | n: Integer          | und Adresse nach v     |
  922. | PUT(a,v)       | a: LONGINT          | Mem[a] := v            |
  923. |                | v: einfache Typen   |                        |
  924. | PUTREG(n,v)    | n: Integerkonstante | Register n := v        |
  925. |                | v: einfache Typen   | (0≤n≤15)               |
  926. +----------------+---------------------+------------------------+
  927.  
  928. 5.6) Unterschiede zum Standard-Oberon-2
  929. ---------------------------------------
  930.  
  931.  - Der Compiler wurde erweitert um AND und NOT,  die identisch  mit  &  und
  932.    ~sind.
  933.  
  934.  - SYSTEM.ADR kann auch die Adressen von Prozeduren und konstanten  Strings
  935.    zurückgeben.
  936.  
  937.  - Es gibt eine Abart von Prozeduren, die für Betriebssystemaufrufe benutzt
  938.    werden. Bei Wirth wurden sie anders benutzt.
  939.    Beispiel :
  940.  
  941.    PROCEDURE- Fclose(Handle : INTEGER) : INTEGER 62,1;
  942.  
  943.    Bei Benutzung dieser Prozedur wird das Handle und die Funktionsnummer 62
  944.    auf den Stack geschrieben,  TRAP #1 aufgerufen und der Stack korrigiert.
  945.    Da das Betriebssystem genau wie normale Prozeduren den Returnwert in Re-
  946.    gister D0 zurückgeben,  funktioniert dies also auch.  Lediglich die Rei-
  947.    henfolge der Parameter müssen vertauscht werden.
  948.  
  949.  - Bei Wirth müssen Prozeduren, die einer Prozedurvariablen zugewiesen wer-
  950.    den,  eine Funktionsnummer haben.  Prozeduren bekommen Funktionsnummern,
  951.    wenn sie einen Stern hinter dem Namen haben (dann sind sie  exportiert),
  952.    wenn sie einen Stern hinter 'PROCEDURE' stehen haben  (soll  wohl  einen
  953.    Far-Aufruf erzwingen) oder wenn sie forward deklariert werden  (ein  '^'
  954.    hinter 'PROCEDURE'). Bei STJ-O2 ist keine Funktionsnummer mehr nötig für
  955.    die Zuweisung an eine Prozedurvariable.
  956.  
  957.  - Laut Wirth waren Strings nur in Gänsefüßchen zulässig.  Dabei  wird  ein
  958.    Zeichen als CHAR,  mehr oder weniger Zeichen als ARRAY OF CHAR  erkannt.
  959.    Um nun auch einzelne Zeichen als Strings zu deklarieren, kann man sie in
  960.    Hochkommata einschließen.
  961.  
  962. 5.7) Bekannte Fehler
  963. --------------------
  964.  
  965.  - Nicht für alle Fehlermeldungen  ist  eine  Klartextmeldung  gespeichert.
  966.    Dann erscheint nur  eine  Fehlernummer.  Einige  Fehlermeldungen  passen
  967.    nicht immer ganz zu dem bemerkten Fehler. Man möge mir das verzeihen.
  968.  
  969.  - Zeiger auf offene Arrays in komplexen Strukturen (Arrays,  Records)  ma-
  970.    chen Probleme. Besonders der Indexcheck funktioniert dann nicht.
  971.  
  972.  - Die Anzahl Prozeduren,  die an einen Typ und dessen Erweiterungen gebun-
  973.    den werden, ist noch auf 100 begrenzt.
  974.  
  975.  - Zeiger auf mehrdimensional offene Arrays sind noch nicht möglich.
  976.  
  977.  - LEN liefert nur INTEGER zurück statt LONGINT, da die Indizes auf 32K be-
  978.    grenzt sind.
  979.  
  980.  - Wenn schon eine Infodatei existiert,  deren Inhalt aber Unsinn ist  oder
  981.    deren Format veraltet ist oder die 0 Bytes lang ist, stürzt der Compiler
  982.    nach der Übersetzung ab.
  983.  
  984.  
  985.  
  986.  
  987. 6) Der Assembler
  988. ================
  989.  
  990. Im Compiler ist ein Makroassembler integriert.  Dieser ist ursprünglich als
  991. eigenständiges Programm zur Assemblerprogrammierung gedacht gewesen und da-
  992. her sehr viel leistungsfähiger als nötig.  Daher ist er auch nur gering mit
  993. dem Oberon-Teil des Compilers verbunden.  Er hat einen eigenen  Parser  und
  994. arbeitet im Gegensatz zum Compiler mit 2  Passes.  Bei  der  Programmierung
  995. habe ich mich an AS orientiert,  ein PD-Assembler für PC's, so daß hier ei-
  996. nige Ähnlichkeiten bestehen. Mit dem Befehl
  997.  
  998. ASSEMBLER
  999.      ...
  1000.    END;
  1001.  
  1002. wird der Assembler aktiviert.  Alles zwischen ASSEMBLER und END  wird  dann
  1003. nicht mehr vom Compiler, sondern vom Assembler bearbeitet. Dabei können die
  1004. meisten Symbole des Oberon-Teils verwendet werden,  jedoch kann der Oberon-
  1005. Teil nicht auf im Assembler definierte  Symbole  zugreifen.  Der  Assembler
  1006. kann soweit mit Oberon-Strukturen arbeiten, solange kein Code dabei erzeugt
  1007. werden muß.
  1008.  
  1009.   Für A7 kann alternativ auch SP verwendet werden.  Alle Befehle sind  auch
  1010. ohne Längenangabe definiert.  Wenn der Befehl in Wortgröße existiert,  wird
  1011. dies als Größe angenommen.
  1012.  
  1013.   Der Assembler ist genau wie der Compiler streng Case-Sensitiv.  Alle  Ma-
  1014. schinenbefehle und Pseudobefehle müssen groß geschrieben werden. Bei Labeln
  1015. wird zwischen Groß- und Kleinschreibung unterschieden.
  1016.  
  1017.   Achtung :  Es sind längst nicht alle Maschinenbefehle  getestet  und  bei
  1018. Problemen sollte ein Disassembler prüfen, ob der Assembler nicht vielleicht
  1019. Unsinn kodiert hat.
  1020.  
  1021. 6.1) Symbolkonventionen
  1022. -----------------------
  1023.  
  1024. Symbole werden mit einer Länge von 22 Byte gespeichert,  alle weiteren Zei-
  1025. chen werden ignoriert.  Wenn ein Label definiert werden soll, muß es in der
  1026. ersten Spalte beginnen,  darf kein vordefinierter Bezeichner sein  und  muß
  1027. mit einem Buchstaben beginnen.  Alle weiteren  Zeichen  können  Buchstaben,
  1028. Ziffern und Unterstrich sein.  Ein Doppelpunkt hinter einem Label  ist  er-
  1029. laubt,  aber nicht erforderlich. Alle vordefinierten Bezeichner dürfen auch
  1030. in der ersten Spalte anfangen.  Die Parameterliste eines Makros muß mit ei-
  1031. nem Zeilenende oder Kommentar beendet werden. Außer diesen beiden Forderun-
  1032. gen ist in einem Quelltext alles erlaubt,  auch mehrere  Befehle  in  einer
  1033. Zeile. Sicherheitshalber sollten sie mit ';;' getrennt werden, auch wenn es
  1034. nicht immer nötig ist.  Ein Semikolon leitet Kommentar ein,  zwei  hingegen
  1035. trennen Befehle.  Die Spalte hinter dem zweiten Semikolon wird  wieder  als
  1036. erste Spalte einer neuen Zeile interpretiert,  so daß dort auch  ein  Label
  1037. definiert werden kann.
  1038.  
  1039.   Neben dem üblichen Kommentar mit einem Semikolon bis zum Zeilenende  kann
  1040. man auch mehrere Zeilen mit der in Oberon üblichen  Konstruktion  (*  ...*)
  1041. Kommentar definieren.
  1042.  
  1043.   Bei Labels und Befehlen wird immer zwischen Groß- und Kleinschreibung un-
  1044. terschieden.  Alle Maschinenbefehle,  Register und Pseudooperationen müssen
  1045. groß geschrieben werden.
  1046. Folgende Symbole definiert der Assembler vor:
  1047.  
  1048.  
  1049.  
  1050.  
  1051. +------+------------------------+
  1052. | Name | Bedeutung              |
  1053. +------+------------------------+
  1054. | *    | mom. Programmzähler    |
  1055. | CPU  | der gewählte Prozessor |
  1056. +------+------------------------+
  1057.  
  1058.  
  1059.   Desweiteren einige Pseudobefehle,  deren  Parameter  und  natürlich  alle
  1060. 68000 Befehle.  Befehle der anderen 680X0 Prozessoren sind  z.T.  implemen-
  1061. tiert.
  1062.  
  1063. 6.1.1) Formelausdrücke
  1064. ......................
  1065.  
  1066. An den meisten Stellen, an denen der Assembler Zahlenangaben erwartet, kön-
  1067. nen nicht nur einfache Symbole oder Konstanten  angegeben  werden,  sondern
  1068. ganze Formelausdrücke. Bei den Komponenten der Formelausdrücke kann es sich
  1069. sowohl um ein einzelnes Symbol als auch  um  eine  Konstante  handeln.  Die
  1070. Schreibweise von Integerkonstanten kann in verschiedenen Zahlensystemen er-
  1071. folgen:
  1072.  
  1073.  
  1074.  
  1075.  
  1076. +-------------+-------------------------------------+
  1077. | dezimal     | direkt                              |
  1078. | hexadezimal | nachgestelltes H, vorangestelltes $ |
  1079. | binär       | nachgestelltes B, vorangestelltes % |
  1080. | oktal       | nachgestelltes O, vorangestelltes @ |
  1081. +-------------+-------------------------------------+
  1082.  
  1083.  
  1084.   Damit hexadezimale Kostanten im Intel-Modus nicht als  Symbolnamen  fehl-
  1085. interpretiert werden können,  müssen sie immer mit einer  Ziffer  beginnen;
  1086. anstelle z.B.  F0H muβ also 0F0H geschrieben werden.  Die Werte A-F  müssen
  1087. großgeschrieben  werden,   ebenso  die  nachgestellten   Buchstaben.   Beim
  1088. Motorola-Modus entfällt dies. Integerkonstanten können auch als ASCII-Werte
  1089. geschrieben werden, so entsprechen
  1090.  
  1091. 'A'    == $00000041
  1092.   'AB'   == $00004142
  1093.   'ABC'  == $00414243
  1094.   'ABCD' == $41414244
  1095.  
  1096. Dabei müssen die Zeichen in Hochkommata eingeschlossen  sein,  um  sie  von
  1097. Strings zu unterscheiden.  Ihre Länge darf maximal 4 Zeichen  betragen.  Um
  1098. nun aber auch Gänsefüβchen und Sonderzeichen ohne Verrenkungen  in  Strings
  1099. (und als Ascii-Werte geschriebene Integerkonstanten) schreiben  zu  können,
  1100. wurde ein "Escape-Mechanismus" eingebaut,  der  C-Programmierer(inne)n  be-
  1101. kannt vorkommen dürfte:  Schreibt man einen Backslash (\) mit einer maximal
  1102. dreiziffrigen Zahl im String,  so versteht der Assembler dies  als  Zeichen
  1103. mit dem entsprechenden dezimalen ASCII-Wert.  So kann man  mit  \0ein  NUL-
  1104. Zeichen definieren.
  1105.  
  1106.   Einige besonders häufig gebrauchte Steuerzeichen kann man auch  mit  fol-
  1107. genden Abkürzungen erreichen:
  1108.  
  1109. \b : Backspace    \a : Klingel         \e : Escape
  1110.  \t : Tabulator    \n : Zeilenvorschub  \r : Wagenrücklauf
  1111.  \\ : Backslash    \' : Hochkomma       \" : Gänsefüβchen
  1112.  
  1113. Die Kennbuchstaben dürfen sowohl groβ als auch klein geschrieben werden.
  1114.  
  1115.   Über dieses Escape-Zeichen können sogar  Formelausdrücke  in  den  String
  1116. eingebaut werden,  wenn sie in geschweifte Klammern eingefaβt werden:  z.B.
  1117. bewirkt
  1118.  
  1119. Wert1   equ 1
  1120.   Wert2   equ 2
  1121.   message "Wert = \{Wert1+Wert2}"
  1122.  
  1123. die Ausgabe von 'Wert = 3'.
  1124. Der Assembler stellt zur Verknüpfung folgende Operanden zur Verfügung:
  1125.  
  1126.  
  1127.  
  1128.  
  1129. +--------------------------------------------------+
  1130. | Operand Funktion            #Operanden    Rang   |
  1131. +--------------------------------------------------+
  1132. | ~       log. NOT                 1        hoch   |
  1133. | ~~      binäres NOT              1          ^    |
  1134. +--------------------------------------------------+
  1135. | *       Produkt                  2          |    |
  1136. | /       Quotient                 2          |    |
  1137. | #       Modulodivision           2          |    |
  1138. | ^       Potenz                   2          |    |
  1139. | !,!!    binäres XOR              2          |    |
  1140. | &,&&    binäres AND              2          |    |
  1141. +--------------------------------------------------+
  1142. | -       Differenz                2          |    |
  1143. | +       Summe                    2          |    |
  1144. | |,||    binäres OR               2          |    |
  1145. +--------------------------------------------------+
  1146. | <>      Ungleichheit             2          |    |
  1147. | >=      gröβer oder gleich       2          |    |
  1148. | <=      kleiner oder gleich      2          |    |
  1149. | <       echt kleiner             2          |    |
  1150. | >       echt gröβer              2          v    |
  1151. | =       Gleichheit               2       niedrig |
  1152. +--------------------------------------------------+
  1153.  
  1154.  
  1155.   Die angedeuteten Gruppen haben jeweils gleichen Rang. Die Reihenfolge der
  1156. Evaluierung läβt sich durch Klammerung neu festlegen.
  1157.  
  1158.   Die Vergleichsoperatoren liefern TRUE,  falls die Bedingung zutrifft, und
  1159. FALSE falls nicht.  Für die logischen Operatoren  ist  ein  Ausdruck  TRUE,
  1160. falls er ungleich 0 ist,  ansonsten FALSE.  Deshalb ist auch ein  separater
  1161. "logisch Nicht" Operator nötig,  denn eine Zahl ungleich 0 kann  binär  in-
  1162. vertiert immer noch ungleich 0 sein.  Beim "logisch Nicht" wird eine 0  zur
  1163. 1,  eine Zahl ungleich 0 zur 0. Alle anderen logischen Operationen sind mit
  1164. den Binären identisch.
  1165.  
  1166.   Für Strings sind alle Vergleichsoperatoren sowie die Summe definiert. Die
  1167. Summe zweier Strings ergibt einen String,  der die beiden aneinandergehängt
  1168. erhält. Vergleiche von Strings liefern 0 (FALSE) oder 1 (TRUE). Überall, wo
  1169. Zahlen erwartet werden, dürfen also auch Stringvergleiche benutzt werden.
  1170.  
  1171.   Als einzige Funktion,  die ein Stringargument zuläβt,  ist  die  Funktion
  1172. UPSTRING definiert.  Sie wandelt alle Zeichen in Groβbuchstaben  um.  Dabei
  1173. werden auch Umlaute in Großbuchstaben gewandelt,  aber Änderungen des  Zei-
  1174. chensatzes mit CHARSET werden nicht korrekt  berücksichtigt.  Wer  nur  ein
  1175. einzelnes Zeichen (als Integer gespeichert) umwandeln will,  kann dies  mit
  1176. der Funktion TOUPPER tun.
  1177.  
  1178. 6.2) Pseudobefehle
  1179. ------------------
  1180.  
  1181. 6.2.1) SET und EQU
  1182. ..................
  1183.  
  1184. SET und EQU erlauben die Definition typenloser Konstanten,  d.h. sie werden
  1185. keinem Segment zugeordnet und ihre Verwendung erzeugt in keinem  Fall  eine
  1186. Warnung wegen Segmentverquickung.  Während EQU  Konstanten  definiert,  die
  1187. nicht wieder (mit EQU) geändert werden können,  erlaubt SET die  Definition
  1188. von Variablen,  die sich während des Assemblerlaufes verändern lassen.  In-
  1189. tern werden Konstanten und Variablen identisch gespeichert, der einzige Un-
  1190. terschied ist, daβ sie mit SET umdefiniert werden können und mit EQU nicht.
  1191. Es ist daher möglich,  ein Symbol mit EQU zu definieren und es mit  SET  zu
  1192. ändern (auch wenn das nicht der Sinn der Sache ist).
  1193.  
  1194. 6.2.2) CHARSET
  1195. ..............
  1196.  
  1197. Einplatinensysteme,  zumal wenn sie LCDs ansteuern,  benutzen häufig  einen
  1198. anderen Zeichensatz als ASCII,  und daβ die Umlautkodierung mit der im  Be-
  1199. fehl übereinstimmt,  dürfte wohl reiner Zufall sein. Um nun aber keine feh-
  1200. lerträchtigen Handumkodierungen vornehmen zu müssen,  enthält der Assembler
  1201. eine Umsetzungstabelle für Zeichen, die jedem Quellcode ein Zielzeichen zu-
  1202. ordnet.  Zur Modifikation dieser Tabelle (die initial 1:1 übersetzt), dient
  1203. der Befehl CHARSET.  Der Befehl erwartet eine  Bereichsangabe  für  die  zu
  1204. übersetzenden Zeichen als ersten  bzw.  ersten/zweiten  Parameter  und  als
  1205. letzten Parameter den Bereich,  in den die Zeichen umgemappt werden sollen.
  1206. Zur Klarstel- lung zwei Beispiele:
  1207.  
  1208.   CHARSET 'ä',128
  1209.  
  1210. bedeutet,  daβ das Zielsystem das ä mit der Zahl  128  kodiert.  Falls  das
  1211. Zielsystem keine Kleinbuchstaben unterstützt, können mit
  1212.  
  1213.   CHARSET 'a','z','A'
  1214.  
  1215. alle Kleinbuchstaben auf die passenden Groβbuchtaben automatisch  umgemappt
  1216. werden.
  1217.  
  1218.   ACHTUNG! CHARSET beeinfluβt nicht nur im  Speicher  abgelegte  Stringkon-
  1219. stanten,  sondern auch als 'ASCII' formulierte Integerkonstanten.  Dies be-
  1220. deutet, daβ eine evtl. bereits modifizierte Umsetzungstabelle in den obigen
  1221. Beispielen zu anderen Ergebnissen führt!
  1222.  
  1223. 6.2.3) CPU
  1224. ..........
  1225.  
  1226. Speichert die nachfolgende Zahl als Bezeichnung für eine CPU.  Kann wie je-
  1227. der andere Bezeichner in Ausdrücken verwendet werden und ist  bei  der  be-
  1228. dingten Assemblierung verwendbar.  Der Assembler prüft, ob ein Maschinenbe-
  1229. fehl auf der gewählten CPU verfügbar ist und verweigert sie wenn nicht. De-
  1230. faultwert ist 68000.
  1231.  
  1232. 6.2.4) SUPMODE
  1233. ..............
  1234.  
  1235. Diese Variable kann nur ein- oder ausgeschaltet werden.  Sie teilt dem  As-
  1236. sembler mit,  ob der Supervisormode gerade eingeschaltet ist oder nicht. Am
  1237. Anfang ist die Variable ausgeschaltet.
  1238.  
  1239. Beispiel :
  1240.  
  1241. SUPMODE ON
  1242.      MOVE    #0,SR    ; nur im Supervisormode zulässig
  1243.      SUPMODE OFF
  1244.      MOVE    #0,SR    ; führt zu einer Warnung des Assemblers
  1245.  
  1246. 6.2.5) SEGMENT
  1247. ..............
  1248.  
  1249. Der Atari unterscheidet verschiedene Adreβbereiche,  die nicht  miteinander
  1250. mischbar sind und jeweils auch verschiedene Befehle zur  Ansprache  benöti-
  1251. gen.  Um auch diese verwalten zu können,  stellt der Assembler mehrere Pro-
  1252. grammzähler zur Verfügung,  zwischen denen mit dem SEGMENT-Befehl hin-  und
  1253. hergeschaltet werden kann. Dies erlaubt es, sowohl in mit INCLUDE eingebun-
  1254. denen Unterprogrammen als auch im  Hauptprogramm  benötigte  Daten  an  der
  1255. Stelle zu definieren, an denen sie benutzt werden. Im einzelnen werden fol-
  1256. gende Segmente mit folgenden Namen verwaltet:
  1257.  
  1258. CODE: Programmcode
  1259.  
  1260. DATA: Datenbereich
  1261.  
  1262. BSS: Block storage segment,  zu 0 initialisierte Daten,  die nicht im  Pro-
  1263.     grammcode auftauchen, sondern vom TOS angehängt werden.
  1264.  
  1265. Labels, die in einem Segment eines bestimmten Typs definiert werden, erhal-
  1266. ten diesen Typ als Attribut. Damit hat der Assembler eine begrenzte Prüfmö-
  1267. glichkeit,  ob mit den falschen Befehlen auf Symbole in einem Segment zuge-
  1268. griffen wird. In solchen Fällen sollte der Assembler eine Warnung ausgeben.
  1269.  
  1270.   Achtung : Die Segmente werden natürlich auseinandergezogen und vom Linker
  1271. richtig zusammengesetzt,  daher darf man natürlich keine PC-relative Adres-
  1272. sierung über Segmentgrenzen anwenden.
  1273.  
  1274. 6.2.6) DC,DS
  1275. ............
  1276.  
  1277. Damit werden Konstanten im Code oder im Datensegment abgelegt oder Speicher
  1278. reserviert.  Als Längen sind .B,  .W und .L möglich,  keine Angabe wird als
  1279. Wortlänge interpretiert.
  1280.  
  1281.   Bei allen dreien sind Strings erlaubt,  evtl.  wird ein String mit Nullen
  1282. verlängert, um auf ein Vielfaches der Bytezahl zu kommen. Eine Reservierung
  1283. von Speicher wird durch DS gemacht:
  1284.  
  1285. DS.B    10      ; reserviert 10 Bytes
  1286.         DS.W    1       ; reserviert ein Wort
  1287.         DS.L    2,$FF   ; reserviert 2 Langworte
  1288.                         ; mit Inhalt $FF
  1289.  
  1290. Speicherreservierung ohne Inhaltsangabe ist in allen Segmenten erlaubt. Der
  1291. Inhalt ist dann jeweils 0. Eine Inhaltsangabe ist natürlich nur im Code und
  1292. im Datensegment erlaubt.
  1293.  
  1294. 6.2.7) ALIGN
  1295. ............
  1296.  
  1297. ALIGN mit einem dahinterstehenden Integerausdruck erlaubt es, den Programm-
  1298. zähler auf eine bestimmte Adresse  auszurichten.  Die  Ausrichtung  erfolgt
  1299. dergestalt, daβ der Programmzähler so weit erhöht wird, daβ er ein ganzzah-
  1300. liges vielfaches des Arguments wird :
  1301.  
  1302.   align 2
  1303.  
  1304. macht den Programmzähler gerade. Der Freiraum wird mit 0 gefüllt. Stattdes-
  1305. sen kann man auch EVEN ohne Wert benutzen.
  1306.  
  1307. 6.2.8) MACRO
  1308. ............
  1309.  
  1310. Dies ist der wohl wichtigste Befehl zur Makroprogrammierung.  Mit  der  Be-
  1311. fehlsfolge
  1312.  
  1313. <Name>    MACRO    [Parameterliste]
  1314.         <Befehle>
  1315.         ENDM
  1316.  
  1317. wird das Makro <Name>als die eingeschlossene Befehlsfolge definiert.  Diese
  1318. Definition alleine erzeugt noch keinen Code! Dafür kann fortan die Befehls-
  1319. folge einfach durch den Namen abgerufen werden,  das ganze stellt also eine
  1320. Schreiberleichterung dar.  Um die ganze Sache etwas nützlicher  zu  machen,
  1321. kann man bei der Makrodefinition eine Parameterliste mitgeben.  Die Parame-
  1322. ternamen werden wie üblich durch Kommas getrennt und müssen - wie  der  Ma-
  1323. kroname selber - den Konventionen für Symbolnamen genügen.
  1324.  
  1325.   Beim Aufruf eines Makros werden die beim Aufruf angegebenen  Parameterna-
  1326. men überall textuell im Befehlsblock eingesetzt und der sich  so  ergebende
  1327. Assemblercode wird normal assembliert.  Sollten beim Aufruf zu wenige Para-
  1328. meter angegeben werden,  werden sie als leere Strings übergeben.  Soll mit-
  1329. tendrin ein Parameter weggelassen werden, kann man zwei aufeinanderfolgende
  1330. Kommas schreiben.
  1331.  
  1332.   Für die übergebenen Parameter gelten besondere Regeln : Eine zusammenhän-
  1333. gende Kette von Zeichen ohne Komma gilt als ein Parameter,  egal um  welche
  1334. Zeichen es sich handelt.  Es können also auch spezielle  Adressierungsarten
  1335. wie (A0)+ übergeben werden.  Wenn bewußt Strings übergeben  werden  sollen,
  1336. müssen sie in Hochkommata eingeschlossen werden, der Parameter besteht dann
  1337. aus dem String mit Hochkommata.  Wird ein  String  in  Gänsefüßchen  einge-
  1338. schlossen,  besteht der Parameter nur aus dem String ohne Gänsefüßchen.  So
  1339. ist es auch möglich, Kommas und Leerzeichen in einem Parameter unterzubrin-
  1340. gen.
  1341. Beispiele :
  1342.  
  1343. mac1   MACRO   par1
  1344.         MOVE    D0,par1
  1345.         ENDM
  1346.         mac1    A0             ; entspricht "MOVE D0,A0"
  1347.  mac2   MACRO   par2,par3
  1348.         par2    par3
  1349.         ENDM
  1350.         mac2    MOVE,"D0,A0"  ; entspricht wiederum
  1351.                               ; "MOVE D0,A0"
  1352.  
  1353. Es kann also praktisch alles durch Makroparameter ersetzt werden,  auch Be-
  1354. fehle !
  1355.  
  1356.   In Makrorümpfen definierte Labels werden immer als lokal betrachtet,  ein
  1357. expliziter LOCAL-Befehl ist also nicht erforderlich.  Sollen  Label  global
  1358. bekannt sein,  müssen sie mit einem Stern gekennzeichnet sein. Da auf diese
  1359. Weise das Label mit jedem Makroaufruf neu definiert wird,  darf es sich nur
  1360. um Definitionen mit 'SET' handeln,  damit keine Fehlermeldungen wie  'Label
  1361. schon definiert' kommen. Aus technischen Gründen ist es momentan nötig, ein
  1362. Makro vor der ersten Benutzung zu deklarieren.  Wenn ein Makroparameter  in
  1363. Gänsefüßchen eingeschlossen wird,  wird er ebenfalls ersetzt,  so  daß  das
  1364. Aussehen des Parameters überprüft werden kann.
  1365. Beispiel :
  1366.  
  1367. Test   MACRO Par
  1368.         IF "Par" = "A"
  1369.         ...
  1370.  
  1371. Wenn als Parameter 'a' oder 'A' übergeben wurde, ergibt der Vergleich true.
  1372. Es wird aber nicht generell in Strings ersetzt,  sondern nur,  wenn der ge-
  1373. samte String gleich einem Makroparameter ist. Der Parameter wird *immer* in
  1374. Großbuchstaben umgewandelt.
  1375.  
  1376. 6.2.9) IRP
  1377. ..........
  1378.  
  1379. Dies ist die eine vereinfachte Form von Makrodefinitionen für den Fall, daβ
  1380. eine Befehlsfolge einmal auf mehrere Operanden angewendet werden  soll  und
  1381. danach nicht mehr gebraucht wird.  IRP benötigt als  ersten  Parameter  ein
  1382. Symbol für den Operanden,  und danach eine (fast) beliebige Menge von Para-
  1383. metern,  die nacheinander in den Befehlsblock eingesetzt  werden.  Um  eine
  1384. Menge von Registern auf den Stack zu schieben, kann man z.B. schreiben
  1385.  
  1386. IRP     op, D0,D1,D3
  1387.         MOVE    op,-(SP)
  1388.         ENDM
  1389.  
  1390. was in folgendem resultiert:
  1391.  
  1392. MOVE    D0,-(SP)
  1393.         MOVE    D1,-(SP)
  1394.         MOVE    D3,-(SP)
  1395.  
  1396. Benutzte Labels sind wieder für jeden Durchgang automatisch lokal.
  1397.  
  1398.   Soll ein Label global sichtbar sein,  muß es einen Stern hinter dem Namen
  1399. haben.  Dies geht nur bei Labels, die mit SET definiert werden, denn andere
  1400. würden eine Fehlermeldung erzeugen, daß das Label schon definiert ist.
  1401.  
  1402. 6.2.10) REPT
  1403. ............
  1404.  
  1405. Dies ist die einfachste Form der Makrobenutzung.  Der im  Rumpf  angegebene
  1406. Code wird einfach sooft assembliert,  wie der Integerparameter von REPT an-
  1407. gibt.  Dieser Befehl wird häufig in kleinen Schleifen anstelle  einer  pro-
  1408. grammierten Schleife verwendet, um den Schleifenoverhead zu sparen.
  1409.  
  1410. Der Vollständigkeit halber ein Beispiel:
  1411.         REPT    3
  1412.         ROR     #1,(A0)
  1413.         ENDM
  1414.  rotiert den Wert um 3 Stellen nach rechts.
  1415.  
  1416. Symbole sind wiederum für jede einzelne Repetition lokal.
  1417.  
  1418. 6.2.11) Bedingte Assemblierung
  1419. ..............................
  1420.  
  1421. Der Assembler unterstützt die bedingte Assemblierung mit Hilfe der  Befehle
  1422. IFC..  / ELSIFC / ENDC. Diese Befehle wirken zur Assemblierzeit, indem ent-
  1423. sprechend der Bedingung Teile übersetzt oder übersprungen werden. Diese Be-
  1424. fehle sind also nicht mit den IF-Statements höherer Programmiersprachen zu vergleichen.
  1425. Die allgemeine Form eines IF-Befehles ist folgendermaβen:
  1426.  
  1427. IFC <Ausdruck> THEN
  1428.          .
  1429.          .
  1430.          <Block 1>
  1431.          .
  1432.          .
  1433.         ELSIFC
  1434.          .
  1435.          .
  1436.          <Block 2>
  1437.          .
  1438.          .
  1439.         ELSEC
  1440.          .
  1441.          .
  1442.          <Block 3>
  1443.          .
  1444.          .
  1445.         ENDC
  1446.  
  1447. Falls der hinter IFC angegebene Ausdruck wahr (d.h.  ungleich 0) ist,  wird
  1448. Block 1 assembliert. Es können dann beliebig viele ELSIFC folgen, mit denen
  1449. genauso verfahren wird.  Falls keine Bedingung zutrifft,  wird  der  ELSEC-
  1450. Zweig assembliert, falls er vorhanden ist.
  1451.  
  1452.   IF-Anweisungen dürfen beliebig verschachtelt werden,  ein  ELSEC  bezieht
  1453. sich immer auf das letzte vorangegangene, noch nicht abgeschlossene IFC.
  1454.  
  1455.   Wenn in der Bedingung Symbole auftauchen,  müssen diese unbedingt  vorher
  1456. definiert worden sein, damit im Pass 1 der richtige Block übersetzt wird.
  1457.  
  1458.   Für den Test,  ob ein Symbol definiert ist, wurde die Funktion DEF einge-
  1459. führt.  Sie gibt TRUE (=1), wenn das angegebene Symbol definiert ist, sonst
  1460. FALSE (=0).
  1461. Dies ist nützlich für Include Dateien :
  1462.  
  1463. IFC NOT DEF(thisfile) THEN; wenn nicht definiert
  1464.  thisfile       EQU 1             ; dann definieren
  1465.         ...                       ; und übersetzen
  1466.         ENDC
  1467.  
  1468. 6.2.12) Lokale Label
  1469. ....................
  1470.  
  1471. Die bedeutendste Erweiterung zu AS sind  lokale  Label.  Damit  können  in-
  1472. nerhalb eines Bereichs alle Label eingekapselt werden,  so daß sie  in  der
  1473. Umgebung nicht mehr sichtbar sind.
  1474.  
  1475. Beispiel :
  1476.         LOCAL
  1477.  Proc1*: ...
  1478.  Loop:   ...
  1479.         END
  1480.         LOCAL
  1481.  Proc2*: ...
  1482.  Loop:     ...
  1483.         END
  1484.  
  1485. können so in derselben Datei stehen. Loop ist jeweils nur innerhalb von LO-
  1486. CAL und END sichtbar.  Ein * hinter einem Label (vor dem Doppelpunkt  falls
  1487. einer gesetzt wird) bedeutet, daß das Label global sein soll. Egal auf wel-
  1488. cher Verschachtelungsebene von LOCAL man sich befindet,  ein solches  Label
  1489. ist überall sichtbar.  Includedateien sollten alle Label lokal  machen  und
  1490. nur diese Label global definieren, die auch von anderen benutzt werden sol-
  1491. len.  Damit vermeidet man die Doppelbenutzung von Labels, die unwissentlich
  1492. in einer Includedatei definiert sind.
  1493.  
  1494.   Alle Label ohne Stern sind außerhalb der ASSEMBLER ... END Struktur nicht
  1495. bekannt, d.h. sie sind automatisch lokal.
  1496.  
  1497.   Durch die Lokalisierung innerhalb von ASSEMBLER bis END ist dieser Befehl
  1498. nicht nötig, aber für reine Assemblerprojekte ist er wichtig.
  1499.  
  1500. 6.3) Hochsprachenelemente
  1501. -------------------------
  1502.  
  1503. Der Assembler beherrscht auch einige der Oberon-Strukturen,  wenn auch  we-
  1504. sentlich primitiver.  Trotzdem kann man mit ihnen ein wenig Struktur in ein
  1505. Assemblerprogramm bringen und auch Labeldefinitionen wie Loop o.ä. sparen.
  1506.  
  1507. 6.3.1) IF cond THEN ... ELSIF ... ELSE ... END
  1508. ..............................................
  1509.  
  1510. Die übliche If-Abfrage darf natürlich nicht fehlen.  Als  Bedingungen  sind
  1511. aber lediglich die üblichen Condition Codes HI, LS, CC, HS, CS, LO, NE, EQ,
  1512. VC, VS, PL, MI, GE, LT, GT und LE zugelassen.
  1513. Beispiel :
  1514.  
  1515. CMP D0,D1
  1516.         IF EQ THEN      ; wenn D0 = D1
  1517.           ...           ; tu dies
  1518.         ELSIF LO THEN   ; wenn D1 < D0
  1519.           ...           ; tu dies
  1520.         ELSE
  1521.           ...           ; sonst dies
  1522.         END
  1523.  
  1524. 6.3.2) REPEAT ... UNTIL cond
  1525. ............................
  1526.  
  1527. Entspricht einer Repeat-Schleife in Oberon. Bedingungen wie bei IF.
  1528.  
  1529. Beispiel :
  1530.         REPEAT
  1531.           SUBQ #1,D0
  1532.         UNTIL EQ        ; zählt D0 bis auf 0 runter
  1533.  
  1534. 6.3.3) LOOP ... END
  1535. ...................
  1536.  
  1537. Entspricht LOOP in Oberon.
  1538.  
  1539. 6.3.4) EXIT [(Zahl)]
  1540. ....................
  1541.  
  1542. Mit Hilfe der Exit-Anweisung kann man REPEAT-Schleifen und LOOP-  Schleifen
  1543. mittendrin verlassen.  Es wird ein Branch an das Ende der  Struktur  einge-
  1544. fügt. Wenn man eine Zahl in Klammern angibt, kann man gleich mehrere Struk-
  1545. turen verlassen. Dabei einspricht EXIT einem EXIT(0).
  1546. Beispiel :
  1547.  
  1548. LOOP
  1549.           REPEAT
  1550.             TST D0
  1551.             IF EQ THEN EXIT END   ; verläßt die
  1552.                                   ; REPEAT-Schleife
  1553.             IF MI THEN EXIT(1) END; verläßt die
  1554.                                   ; LOOP-Schleife
  1555.           UNTIL PL
  1556.         END
  1557.  
  1558. 6.4) Diverses
  1559. -------------
  1560.  
  1561. 6.4.1) INCLUDE
  1562. ..............
  1563.  
  1564. Dieser Befehl fügt die im Parameter angegebene Datei so im Text ein, als ob
  1565. sie dort stehen würde.  Dieser Befehl ist sinnvoll,  um Quelldateien aufzu-
  1566. spalten,  die alleine nicht in den Speicher  passen  würden  oder  um  sich
  1567. "Toolboxen" zu erzeugen.
  1568.  
  1569.   Aus Kompatibilitätsgründen ist  es  erlaubt,  den  Dateinamen  in  Gänse-
  1570. füβchen zu schreiben,
  1571.  
  1572. include stddef51.asm
  1573.  
  1574. und
  1575.  
  1576. include "stddef51.asm"
  1577.  
  1578. sind also äquivalent.
  1579.  
  1580. 6.4.2) MESSAGE, WARNING, ERROR und FATAL
  1581. ........................................
  1582.  
  1583. Der Assembler prüft zwar die Quelltexte so streng wie möglich  und  liefert
  1584. diffenzierte Fehlermeldungen, je nach Anwendung kann es aber sinnvoll sein,
  1585. unter bestimmten Bedingungen zusätzliche  Fehlermeldungen  auszugeben,  mit
  1586. denen sich logische Fehler automatisch prüfen lassen.  Der Assembler unter-
  1587. scheidet drei Typen von Fehlermeldungen,  die über drei  Befehle  auch  dem
  1588. Programmierer zugänglich sind:
  1589.  
  1590.  - WARNING :  Fehler,  die auf möglicherweise falschen  oder  ineffizienten
  1591.    Code hinweisen.  Die Assemblierung läuft weiter, eine Codedatei wird er-
  1592.    zeugt.
  1593.  
  1594.  - ERROR : Echte Fehler im Programm. Die Assemblierung läuft weiter, um mö-
  1595.    gliche weitere Fehler in einem Durchgang entdecken  und  korrigieren  zu
  1596.    können. Eine Codedatei wird nicht erzeugt.
  1597.  
  1598.  - FATAL :  Schwerwiegende Fehler,  die einen sofortigen Abbruch des Assem-
  1599.    blers bedingen.  Eine Codedatei kann möglicherweise entstehen,  ist aber
  1600.    unvollständig.
  1601.  
  1602. Alle Befehle erwarten eine String als Argument.
  1603.  
  1604.   Diese Anweisungen ergeben nur in Zusammenhang mit bedingter Assemblierung
  1605. Sinn.  So kann man fehlerhafte Bedingungen abtesten und mit  einer  Fehler-
  1606. meldung abbrechen. Der String einer Fehlermeldung wird anstatt einer Assem-
  1607. blermeldung in die Fehlerdatei geschrieben und mit Zeile und Spalte  verse-
  1608. hen, in der der Befehl steht.
  1609.  
  1610.   Der Befehl MESSAGE gibt den angegebenen String lediglich aus und  erzeugt
  1611. einen Zeilenvorschub.
  1612.  
  1613. 6.5) Zugriff auf Oberon-Bezeichner
  1614. ----------------------------------
  1615.  
  1616. Der Assembler hat eine begrenzte Zugriffsmöglichkeit auf Bezeichner, die in
  1617. Oberon definiert wurden.  Dabei gilt allgemein, daß nur solche Zugriffe un-
  1618. terstützt werden, die keinen zusätzlichen Code erfordern.
  1619. Beispiel :
  1620.  
  1621. CONST con = 10;
  1622.  TYPE rec = RECORD
  1623.               var1 : INTEGER;
  1624.               var2 : ARRAY 10 OF CHAR;
  1625.             END;
  1626.       arr = ARRAY 10 OF LONGINT;
  1627.  VAR a : rec;
  1628.      b : POINTER TO rec;
  1629.      c : arr;
  1630.  PROCEDURE proc1;
  1631.   ...
  1632.  PROCEDURE proc2*;
  1633.   ...
  1634. Dann sind folgende Zugriffe möglich:
  1635.         MOVE    #con,D0         ; lädt D0 mit 10
  1636.         MOVE.L  a,A0            ; lädt Adresse von a in A0
  1637.                                 ; (geht auch mit Prozeduren
  1638.                                 ; und Stringkonstanten)
  1639.         MOVE    a.var1,D0       ; geht weil a globale
  1640.                                 ; Variable ist
  1641.         MOVE.B  a.var2[5],D1    ; dito
  1642.         MOVE.L  c[8],D2         ; dito
  1643.         BSR     proc            ; innerhalb eines Moduls
  1644.         JSR     proc2           ; bei importierten und
  1645.                                 ; exportierten Prozeduren
  1646. Dagegen geht dies nicht:
  1647.         MOVE    b.var1,D0       ; b ist ein Zeiger und muß erst
  1648.                                 ; geladen werden
  1649. Dies kann so gelöst werden:
  1650.         MOVE.L  b,A0            ; Inhalt von b = Zeiger auf rec
  1651.         MOVE    rec.var1(A0),D0 ; typ.var ergibt Offset von var
  1652.         MOVE.B  rec.var2[5](A0),D0; genauso
  1653.         MOVE.L  arr[2](A1),D0   ; geht genauso mit Arrays
  1654.  
  1655. Man kann also mit dem Typbezeichner die Offsets der Variablen innerhalb des
  1656. Records bekommen. Dies sollte immer der direkten Angabe von Zahlen vorgezo-
  1657. gen werden,  damit bei einer Änderung der Datenstruktur nicht  alle  Zahlen
  1658. geändert werden müssen.
  1659.  
  1660.  
  1661. 7) Der Linker
  1662. =============
  1663.  
  1664.   Der Oberon-Linker (LINK.OBJ/TTP) dient dazu,  vom Compiler  erzeugte  Ob-
  1665. jektmodule zu einem lauffähigen Programm zusammenzubinden.  Dafür  benötigt
  1666. er nur die Objektmodule, die Symboldateien nicht.
  1667.  
  1668. 7.1) Aufruf, Parameter
  1669. ----------------------
  1670.  
  1671. Der Linker sollte von einer Shell aus benutzt werden,  die zumindest in der
  1672. Lage ist,  Environmentvariablen zu setzen, denn der Linker liest dort seine
  1673. Optionen. Beim Aufruf kann man als Kommando einige Optionen sowie einen Na-
  1674. men eines Objektmoduls übergeben.  Dieses Modul wird mit den von ihm impor-
  1675. tierten Modulen zusammengelinkt und unter seinem Namen mit passender Exten-
  1676. sion gespeichert. Die Syntax sieht also so aus:
  1677.  
  1678. link {<Option>} <Name>
  1679.  
  1680. Es wird nur der Name ohne Extension beachtet, ein eventueller Pfad wird ab-
  1681. geschnitten.  Dieser Name wird mit der Extension OBJ in den Suchpfaden  ge-
  1682. sucht. Wird keine Datei gefunden, wird der Linker wieder verlassen.
  1683. Die Optionen haben die allgemeine Syntax:
  1684.  
  1685. -<Option><Parameter>
  1686.  
  1687. Die Art der Option wird mit einem Buchstaben (groß oder  klein)  angegeben,
  1688. eventuelle Parameter folgen ohne Leerzeichen.  Einige Optionen sind  sowohl
  1689. über Environmentvariablen als auch über Kommandozeile setzbar.  Dabei gilt:
  1690. Die Optionen in der Kommadozeile haben höhere Priorität.
  1691. Folgende Optionen sind implementiert:
  1692.  
  1693. -t: Schaltet die Erzeugung einer Symboltabelle aus, die normalerweise immer
  1694.     an das Programm angehängt wird.  Eine Symboltabelle ist  wichtig,  wenn
  1695.     man ein Programm debuggen muß. Sowohl Bugaboo als auch DB verstehen das
  1696.     Format der Symboltabelle.
  1697.  
  1698. -e: Schaltet die Erzeugung einer erweiterten  Symboltabelle  ab.  Normaler-
  1699.     weise wird eine Symboltabelle im erweiterten  GST-Format  erzeugt,  die
  1700.     eine Symbollänge von 22 Zeichen zuläßt,  während das Standardformat nur
  1701.     8 Zeichen hat.  Diese Option stellt also nur das Format ein, die Option
  1702.     -t schaltet die Symboltabelle ganz aus.
  1703.  
  1704. -s|<size>|: Normalerweise erhält ein Programm einen Stack  von  32K  Größe.
  1705.     Mit dieser Option kann man den Stack beliebig einstellen.
  1706.  
  1707. -x|<ext>|: Damit kann die Extension eingestellt werden,  die  das  Programm
  1708.     erhalten soll.  Normalerweise ist das PRG, aber bei TOS-Programmen kann
  1709.     man TOS oder TTP angeben.
  1710.  
  1711. Ist von einem Modul eine Infodatei vorhanden und darin ist ein Programmname
  1712. definiert, wird dieser beim Speichern des Programmes benutzt. Wenn ein Pfad
  1713. angegeben ist, wird dort gespeichert, sonst in PRGPATH bzw. beim Modul. Der
  1714. Name kann im Quelltext mit (*$N ...*) gesetzt werden, siehe Kap. ??.
  1715.  
  1716. 7.2) Environmentvariablen
  1717. -------------------------
  1718.  
  1719. Der Linker wertet auch einige Environmentvariablen aus.  Sie  müssen  immer
  1720. großgeschrieben sein und von einem '=' gefolgt sein.  Gesetzt werden sie in
  1721. der Shell und werden jedem Programm übergeben,  daß von dieser Shell aufge-
  1722. rufen wird.
  1723. Es werden folgende Variablen ausgewertet:
  1724.  
  1725. OBJPATH: Gibt die Suchpfade an,  in denen nach importierten Modulen gesucht
  1726.     wird. Zum Linken werden nur die Objektdateien benötigt.
  1727.     Wenn OBJPATH nicht definiert ist, wird MODPATH genommen.
  1728.  
  1729. INFPATH: Gibt die Suchpfade an, in denen nach Infodateien gesucht wird.
  1730.     Wenn INFPATH nicht definiert ist, wird MODPATH genommen.
  1731.  
  1732. TOSPATH: Gibt ebenfalls Suchpfade an,  in denen Module stehen,  die in TOS-
  1733.     Programmen benutzt werden dürfen.  Diese Pfade werden vor denen in  OB-
  1734.     JPATH durchsucht.  Die Unterscheidung erfolgt anhand der Extension, die
  1735.     das zu erzeugende Programm erhält. Fängt sie mit 'T' an, werden die Mo-
  1736.     dule aus TOSPATH und OBJPATH gelinkt. Ist TOSPATH nicht definiert, wird
  1737.     wie bisher nur OBJPATH bzw. MODPATH genommen.
  1738.  
  1739. GEMPATH: Gibt ebenfalls Suchpfade an,  in denen Module stehen,  die in GEM-
  1740.     Programmen benutzt werden dürfen.  Diese Pfade werden vor denen in  OB-
  1741.     JPATH durchsucht.  Die Unterscheidung erfolgt anhand der Extension, die
  1742.     das zu erzeugende Programm erhält.  Fängt sie nicht mit 'T' an,  werden
  1743.     die Module aus GEMPATH und OBJPATH gelinkt.  Ist  GEMPATH  nicht  defi-
  1744.     niert, wird wie bisher nur OBJPATH bzw. MODPATH genommen.
  1745.  
  1746. PRGPATH: Gibt einen mit Backslash beendeten Pfad an,  in den  das  erzeugte
  1747.     Programm geschrieben werden soll.  Wenn die Variable  nicht  existiert,
  1748.     wird das Programm in denselben Pfad geschrieben, in dem das Objektmodul
  1749.     stand.
  1750.  
  1751. SYMTAB: Darf als Werte ON und OFF annehmen.  Damit wird die  Ausgabe  einer
  1752.     Symboltabelle ein- oder ausgeschaltet.  Normalerweise wird eine Symbol-
  1753.     tabelle erzeugt.
  1754.  
  1755. EXTSYM: Wieder Werte ON/OFF. Schaltet das erweiterte GST-Format der Symbol-
  1756.     tabelle ein oder aus. Ist normalerweise eingeschaltet.
  1757.  
  1758. PRGEXT: Gibt die Extension an,  die das gelinkte  Programm  erhalten  soll.
  1759.     Beispiel :  'PRGEXT=TOS' erzeugt ein TOS-Programm (der Code  muß  dafür
  1760.     natürlich geeignet sein). Standardmäßig wird die Extension PRG benutzt.
  1761.  
  1762. STACKSIZE: Der Inhalt dieser Variablen muß eine Dezimalzahl sein,  die  die
  1763.     Größe des Stacks angibt. Normalerweise ist dies 32K.
  1764.  
  1765. LINKALSO: Diese Variable darf eine Liste von Dateinamen,  getrennt mit Kom-
  1766.     mata,  enthalten. Diese Objektmodule werden dann auch gelinkt, wenn sie
  1767.     nicht importiert werden.  Damit ist es z.B.  möglich, während der Test-
  1768.     phase ein Debugmodul mitzulinken, daß sich in Exceptions einklinkt oder
  1769.     ähnliches.  Ein Name sollte immer nur 8 Zeichen lang  sein,  Extensions
  1770.     sind nicht nötig.  Es sind nur maximal 5 Module möglich. Müssen es mehr
  1771.     sein, so muß man ein Leermodul definieren, daß diese Module importiert,
  1772.     und dieses kann man bei LINKALSO angeben.
  1773.  
  1774. LINK_ ...: Alle Variablen,  die mit LINK_ anfangen,  dienen zum  Umbenennen
  1775.     von importierten Modulen.  Wird z.B.  LINK_IO=GEMIO definiert, wird bei
  1776.     jedem Import von IO stattdessen GEMIO gelinkt.  Diese Module müssen na-
  1777.     türlich gleiche Schnittstellen haben.
  1778.  
  1779.  
  1780. 8) Die Lader
  1781. ============
  1782.  
  1783.  Die Lader wurden zu einer Zeit entwickelt,  als es noch  keine  Shell  für
  1784. Load-Time-Linking gab.  Sie sind daher in der Lage,  Objektmodule direkt zu
  1785. linken und zu starten.  Es gibt zwei  Lader,  einen  für  GEM-Applikationen
  1786. (LOAD.PRG) und einen für TOS-Applikationen (LOAD.TTP).  Inzwischen gibt  es
  1787. allerdings keinen Unterschied mehr.  Man braucht nur jeweils  die  richtige
  1788. Extension, damit beim Start die richtige Umgebung gewählt wird.
  1789.  
  1790. 8.1) Aufruf, Parameter
  1791. ----------------------
  1792.  
  1793. Die Lader erhalten mindestens den Namen eines Moduls als  Argument.  Dieses
  1794. Modul darf keine Extension haben,  also nur der Name. Das Modul wird zuerst
  1795. im Lader selbst gesucht,  dann in den Suchpfaden, die in der Environmentva-
  1796. riablen OBJPATH definiert sind.  Ist sie nicht definiert,  wird MODPATH ge-
  1797. nommen. Wenn ein Modul nicht gefunden wird, wird mit einer Meldung abgebro-
  1798. chen.  Sind alle Module geladen und gelinkt, wird das Hauptmodul gestartet.
  1799. Dabei ist die Variable Sys.Loader TRUE,  so daß man erkennen kann, wenn man
  1800. unter dem Lader läuft.  Folgt auf den Namen des Moduls ein  Punkt  und  ein
  1801. weiterer Name, so wird dieser Name in der Liste der exportierten Prozeduren
  1802. gesucht und eine gefundene Prozedur wird gestartet. Dies realisiert die un-
  1803. ter Wirths Oberon übliche Art des  Load-Time-Linking.  Das  geladene  Modul
  1804. kann dies erkennen, denn die Variable Sys.ModuleCall wird auf TRUE gesetzt,
  1805. wenn nur das Modul gestartet wurde. In so einem Fall muß der Modulrumpf die
  1806. Aktion auslösen.  Sie wird auf FALSE gesetzt,  wenn eine Prozedur angegeben
  1807. wurde.  Dann dient der Modulrumpf nur zur Initalisierung.  Alles was hinter
  1808. dem Modul- bzw. Prozedurnamen folgt, wird als Kommando an das Modul weiter-
  1809. gegeben.  Man findet dies wie immer in Sys.Basepage.Command,  genau so  als
  1810. wäre das Modul als Programm gestartet worden.
  1811.  
  1812. 8.2) Ausgabe
  1813. ------------
  1814.  
  1815. Die Lader machen keine Ausgaben, solange keine Fehler auftreten.
  1816.  
  1817.   Eine mögliche Fehlermeldung lautet:  'Objectmodule defect'.  Dies  deutet
  1818. auf einen Versionskonflikt hin.
  1819.  
  1820.   Wird ein Modul mit Extension übergeben (z.B. Icon auf Loader gezogen), so
  1821. wird das Modul normal gestartet mit Sys.ModuleCall FALSE.  Nach  Beendigung
  1822. des Moduls erscheint dann die Meldung 'Procedure OBJ not found',  falls die
  1823. Extension OBJ war. Dies ist nicht weiter schädlich.
  1824.  
  1825.   Die Lader haben ein angepaßtes Modul für  die  Exceptionbehandlung  inte-
  1826. griert.  Es gibt die Art des Fehlers,  die Adresse, das Modul, die Prozedur
  1827. mit Offset und die Parameter aus,  mit denen der Compiler aufgerufen werden
  1828. muß.
  1829. Beispiel:
  1830.  
  1831.   Bus error
  1832.   Address: 1ABEA0
  1833.   Module: Test
  1834.   Procedure: test + 8
  1835.   Call Compiler with '-e-o-s64'
  1836.  
  1837. Der Absturz fand also in der Prozedur Test.test statt,  8 Bytes vom  Anfang
  1838. der Prozedur entfernt. Wenn man jetzt den Compiler mit '-e-o-s64 Test' auf-
  1839. ruft, sucht er im Modul Test die Position 64 (64 Bytes vom Anfang entfernt,
  1840. hexadezimal!) und gibt ein paar Zeilen rund um die Position aus. Die Bedeu-
  1841. tung der Optionen ist in Kap. ?? erklärt.
  1842.  
  1843.  
  1844. 9) Das Make-Utility
  1845. ===================
  1846.  
  1847.   Der Begriff Make dürfte von C her bekannt sein.  Hier ist es jedoch nicht
  1848. nötig, ein Makefile zu erzeugen. Make (MAKE.OBJ/TTP) liest die importierten
  1849. Module aus dem Quelltext und übersetzt alle Dateien,  bei denen dies  nötig
  1850. ist.
  1851.  
  1852. 9.1) Aufruf, Parameter
  1853. ----------------------
  1854.  
  1855. Make kann ohne Parameter oder mit einem Modulnamen gestartet  werden.  Wird
  1856. Make ohne Parameter gestartet, so werden alle Suchpfade nach zu übersetzen-
  1857. den Modulen durchsucht.  Wird ein Modul genannt,  werden nur solche  Module
  1858. überprüft,  die in den Suchpfaden stehen und für das Linken des angegebenen
  1859. Moduls benötigt werden.
  1860.  
  1861. 9.2) Environmentvariablen
  1862. -------------------------
  1863.  
  1864. Mit der Environmentvariablen OC kann man den Compiler angeben.
  1865. Beispiel: OC=E:\OBERON\SYS\COMPILE.TTP
  1866. Ist OC nicht definiert,  wird 'COMPILE.TTP' im  aktuellen  Verzeichnis  ge-
  1867. sucht. Die Suchpfade für Sourcen, Objekt- und Symboldateien werden über die
  1868. Environmentvariable 'MAKEPATH' definiert.
  1869.  
  1870. 9.3) Hinweise
  1871. -------------
  1872.  
  1873. Wenn Module sich gegenseitig importieren,  bleibt  Make  in  einer  Endlos-
  1874. schleife hängen.  Man erkennt dies daran,  daß ständig dieselben Dateinamen
  1875. ausgegeben werden. Mit Control-C kann man die Ausführung abbrechen.
  1876.  
  1877.  
  1878. 10) Der Scanner
  1879. ===============
  1880.  
  1881.   Der Scanner (SCAN.OBJ/TTP) dient dazu,  von einer Position in einem  Pro-
  1882. gramm die Stelle im richtigen Quelltext zu finden.  Dies erfordert eine er-
  1883. weiterte Symboltabelle am Programm. Diese erzeugt der Linker normalerweise,
  1884. wenn nichts anderes verlangt wird.
  1885.  
  1886. 10.1) Aufruf, Parameter
  1887. -----------------------
  1888.  
  1889. Scan erwartet zwei Parameter in der Kommandozeile,  die mit Leerzeichen ge-
  1890. trennt sind:
  1891.  
  1892.  65) Der Name des Programms. Der Name muß so angegeben werden, daß Scan das
  1893.      Programm auch findet.
  1894.  
  1895.  66) Die Position im Programm. Sie wird hexadezimal ohne Zusätze wie $ oder
  1896.      H angegeben.  Mit Position ist der Abstand von dem Codeanfang gemeint.
  1897.      Diese wird zum Beispiel von Exceptions ausgegeben.
  1898.  
  1899. Scan liest das Programm, bestimmt mit Hilfe der Symboltabelle das Modul und
  1900. die Position relativ zum Modulanfang und ruft den Compiler auf.  Als Optio-
  1901. nen werden -e,  -o und -s<pos>angegeben.  Der Compiler  übersetzt  das  be-
  1902. stimmte Modul,  bis er an die Position gelangt,  an der der Absturz  statt-
  1903. fand.  Es werden einige Zeilen davor und dahinter sowie eine  Kennzeichnung
  1904. der Stelle ausgegeben.  Diese Stelle wird auch als Fehlermeldung ausgegeben
  1905. und kann in der Fehlerdatei nachgelesen werden.  Dann beenden sich Compiler
  1906. und Scan.
  1907.  
  1908.   Falls das Programm keine Symboltabelle hat,  macht Scan eine Meldung  und
  1909. terminiert.
  1910.  
  1911. 10.2) Environmentvariablen
  1912. --------------------------
  1913.  
  1914. Mit der Environmentvariablen OC kann man den Compiler angeben.
  1915. Beispiel: OC=E:\OBERON\SYS\COMPILE.TTP
  1916. Ist OC nicht definiert,  wird 'COMPILE.TTP' im  aktuellen  Verzeichnis  ge-
  1917. sucht.
  1918.  
  1919.  
  1920. 11) Debugging
  1921. =============
  1922.  
  1923. Bis jetzt gibt es leider keinen Source  Level  Debugger  für  STJ-Oberon-2.
  1924. Dies ist aber geplant und wird irgendwann kommen.  Bis dahin muß  man  sich
  1925. mit Low Level Debuggern herumplagen.
  1926.  
  1927. 11.1) DB
  1928. --------
  1929.  
  1930. Der Debugger DB von Atari eignet sich einigermaßen zum Debuggen. Ich möchte
  1931. hier besonders auf den Befehl 'stack'  hinweisen:  Dieser  Befehl  versucht
  1932. über den Stack die Aufrufkette von Subroutinen zurückzuverfolgen. Dies geht
  1933. auch mit Oberon-Programmen,  da diese genau wie C-Programme mit Register A6
  1934. lokale Stacks aufbauen.
  1935.  
  1936. 11.2) Bugaboo
  1937. -------------
  1938.  
  1939. Bugaboo (aus dem TurboAss-Paket) eignet sich  ebenfalls  zum  Debuggen.  Er
  1940. kennt leider den Befehl 'stack' nicht,  ist dafür aber wesentlich komforta-
  1941. bler. Leider arbeitet er nicht auf dem TT mit Großbildschirm.
  1942.  
  1943. 11.3) Tips
  1944. ----------
  1945.  
  1946. Zum Debuggen wird immer eine Symboltabelle benötigt.
  1947.  
  1948.   Eine globale Variable kann man über den Namen ansprechen, lokale Variable
  1949. einer Prozedur findet man bei Adressen ab (A6) abwärts,  deren Parameter ab
  1950. 8(A6) aufwärts.
  1951.  
  1952.   Die Namen der Symboltabelle sind nicht immer eindeutig. Wenn man also ein
  1953. Symbol ansprechen will, muß man erst prüfen, ob es das Gewünschte ist. Bei-
  1954. spielsweise findet man die Prozedur 'Read' in File und in Paths.
  1955.  
  1956.   Einen Befehl sollte man immer im Hinterkopf haben:  Wenn nämlich ein Pro-
  1957. gramm abgestürzt ist und man aus dem Debugger raus möchte,  sollte man noch
  1958. die Exitprozedur aufrufen,  damit alle Betriebsmittel  freigegeben  werden.
  1959. Dazu muß man den PC auf das Symbol 'Exit' stellen und die Ausführung  star-
  1960. ten. Wenn der Exit nicht abstürzt, müßte eine Meldung über die Terminierung
  1961. des Programms kommen.  Bei DB lautet der Befehl 'x pc .Exit',  bei  Bugaboo
  1962. 'let pc=.Exit'.
  1963.  
  1964.  
  1965. 12) Utilities
  1966. =============
  1967.  
  1968. 12.1) Der Browser
  1969. -----------------
  1970.  
  1971. Ein Browser ist ein Programm,  daß aus der Symboldatei und der Source  eine
  1972. Definitionsdatei erzeugt.  Die vorliegende Version ist noch in der Entwick-
  1973. lung.  Sie wertet lediglich die Symboldatei aus, so daß keine Kommentare in
  1974. der Definitionosdatei sind.
  1975. Der Browser wurde von Dirk Theisen geschrieben.
  1976.  
  1977. 12.2) Inline-Zeilen erzeugen
  1978. ----------------------------
  1979.  
  1980. Für den Fall,  daß jemand eine Datei als INLINE-Zeilen in eine Source inte-
  1981. grieren will (z.B.  eine Resourcedatei),  kann man dies mit Inline tun. In-
  1982. line fragt nach der zu konvertierenden Datei und speichert die erzeugte Da-
  1983. tei mit der Extension INL ab.  Im Editor muß man dann noch  den  Modulnamen
  1984. SYSTEM bzw.  eine Abkürzung davon mittels Suchen und  Ersetzen  vor  INLINE
  1985. setzen.
  1986.  
  1987.  
  1988. 13) Speicherverwaltung
  1989. ======================
  1990.  
  1991. Die Speicherverwaltung implementiert Funktionen zum Allozieren und  Freige-
  1992. ben dynamischen Speichers. Solcher Speicher ist grundsätzlich nicht initia-
  1993. lisiert[6].
  1994.  
  1995. ---------------
  1996.  
  1997.  [6]  wie auch lokale Variable,  lediglich globale Variable werden zu 0 in-
  1998.       itialisiert
  1999.  
  2000.  
  2001. 13.1) Benutzung in Programmen
  2002. -----------------------------
  2003.  
  2004. Für die dynamische Speicherverwaltung stehen mehrere Funktionen zur  Verfü-
  2005. gung:
  2006.  
  2007. |NEW(<pointer>)|: Wenn als Argument ein Zeiger auf einen  Record  oder  ein
  2008.     konstantes Array übergeben wird, wird diese Struktur alloziert. Bei Re-
  2009.     cords werden 4 Bytes zusätzlich alloziert,  die den Typdeskriptor  auf-
  2010.     nehmen.  Dieser steht immer _vor_ dem Record, d.h. der Zeiger zeigt im-
  2011.     mer auf das erste Element des Records, wohingegen er bei anderen Compi-
  2012.     lern auf den Deskriptor zeigt.
  2013.  
  2014. |NEW(<pointer>,<len>)|: Eine Länge kann nur angegeben werden,  wenn es sich
  2015.     bei dem Zeiger um einen Zeiger auf ein offenes Array handelt. Dabei ist
  2016.     len die Anzahl Indizes.
  2017.  
  2018. |SYSTEM.NEW(<pointer>,<len>)|: SYSTEM.NEW kümmert sich nicht um den Typ des
  2019.     Zeigers. Es wird soviel Speicher alloziert, wie len in Bytes angibt. So
  2020.     allozierter Speicher wird niemals am Garbage Collect teilnehmen.
  2021.  
  2022. |SYSTEM.DISPOSE(<pointer>)|: Gibt den Speicher, auf den der übergebene Zei-
  2023.     ger zeigt, wieder frei.
  2024.  
  2025.   Der Garbage Collector wird mit Kernel.GC  aufgerufen.  Dies  führt  einen
  2026. kompletten Collect durch.  Es gibt auch eine Möglichkeit,  den  Collect  in
  2027. kleine Teile zerhackt nebenher  laufen  zu  lassen.  Dies  würde  mit  Obe-
  2028. ron.Collect unter Chatwin gehen.  Dort sehe ich auch die einzige  sinnvolle
  2029. Anwendung. Im Moment kann ich von beidem nur abraten, da es noch nicht aus-
  2030. gereift ist.
  2031.  
  2032.   Hinweis:  Am Ende eines Programms oder Modulstarts wird automatisch aller
  2033. Speicher freigegeben.
  2034.  
  2035. 13.2) Implementierung
  2036. ---------------------
  2037.  
  2038. Die Implementierung versucht den  Kompromiß  zwischen  Geschwindigkeit  und
  2039. Overhead zu finden.  Der Overhead wird minimal,  wenn bei  jeder  Speicher-
  2040. anforderung genau der angeforderte Speicher alloziert wird (plus  ein  Ein-
  2041. trag in einer Liste).  Die Verwaltung der Liste hat aber so viel Zeit benö-
  2042. tigt, daß der Compiler merklich langsamer wurde. Effizienter wird das, wenn
  2043. man den benötigten Speicher ein wenig aufrundet und in einem  Array  unter-
  2044. bringt.  Das kostet natürlich Speicher.  Um diesen Overhead nicht  zu  groß
  2045. werden zu lassen,  habe ich  Speicheranforderungen  in  16  Klassen  unter-
  2046. teilt[7].  Größere Objekte ab 256 Byte werden in einer Liste verwaltet. Ob-
  2047. jekte zwischen 2 und 256 Byte  werden  in  Arrays  verwaltet,  deren  Elem-
  2048. entgröße zwischen 16 und 256 Byte in 15 Stufen unterteilt ist.
  2049.  
  2050.   Gegenüber GEMDOS stellt sich die Speicherverwaltung anders dar. Dort wird
  2051. immer mindestens 32K alloziert, so daß die Anzahl GEMDOS-Blöcke nicht allzu
  2052. groß wird und damit die Geschwindigkeit abnimmt. Es kann auch nicht passie-
  2053. ren, daß die Speicherverwaltung des GEMDOS keine Einträge mehr hat.
  2054.  
  2055. ---------------
  2056.  
  2057.  [7]  Mombergs Oberon verwendet nur 5 Klassen und hat damit mehr Overhead
  2058.  
  2059.  
  2060.  
  2061. 14) Die Bibliotheken
  2062. ====================
  2063.  
  2064. Die Bibliotheken ermöglichen eigentlich erst ein vernünftiges Programmieren
  2065. mit einer Programmiersprache.  Hier soll eine Übersicht der vorhandenen Mo-
  2066. dule gegeben werden,  nähere Informationen  müssen  den  Definitionsdateien
  2067. entnommen werden.
  2068.  
  2069. 14.1) Betriebssystem
  2070. --------------------
  2071.  
  2072. Alle Betriebssystemmodule implementieren die Aufrufe als Makros,  d.h.  der
  2073. Code für den Trap wird beim Aufruf in den Code integriert.  Es erfolgt kein
  2074. Prozeduraufruf.  Der Nachteil dieser Methode ist, daß alle Parameter in der
  2075. Reihenfolge vertauscht sind.  Der Oberon-Compiler legt den ersten Parameter
  2076. auch als ersten auf den Stack, während C-Compiler den letzten Parameter als
  2077. erstes auf den Stack legen.
  2078.  
  2079. 14.1.1) BIOS
  2080. ............
  2081.  
  2082. Die üblichen BIOS-Funktionen.
  2083.  
  2084. 14.1.2) GEMDOS
  2085. ..............
  2086.  
  2087. Die üblichen GEMDOS-Funktionen.
  2088.  
  2089. 14.1.3) MiNT
  2090. ............
  2091.  
  2092. Die neuen Funktionen unter MiNT sind eigentlich  auch  GEMDOS-Aufrufe.  Sie
  2093. sind aber hier separat verfügbar.  Sys.MiNT gibt an,  ob  MiNT  installiert
  2094. ist.
  2095.  
  2096. 14.1.4) XBIOS
  2097. .............
  2098.  
  2099. Die üblichen XBIOS-Funktionen.  Es fehlen Erweiterungen von TT und  Falcon,
  2100. über die ich keine Informationen habe.
  2101.  
  2102. 14.2) Abstrakte Datenstrukturen
  2103. -------------------------------
  2104.  
  2105. 14.2.1) BinTree
  2106. ...............
  2107.  
  2108. BinTree implementiert einen binären Baum.
  2109. BinTree wurde von H. Mössenböck und Dirk Theisen geschrieben.
  2110.  
  2111. 14.2.2) CDCL
  2112. ............
  2113.  
  2114. CDCL steht für Circular Double Chained List.  Es handelt sich also um  eine
  2115. doppelt verkettete Liste, deren erstes und letztes Element aufeinander zei-
  2116. gen.
  2117.  
  2118. 14.2.3) DCL
  2119. ...........
  2120.  
  2121. DCL steht für Double Chained List.  Es handelt sich also  um  eine  doppelt
  2122. verkettete Liste.
  2123.  
  2124. 14.2.4) FIFO
  2125. ............
  2126.  
  2127. FIFO (First in first out) implementiert eine Liste,  an deren  Anfang  Ele-
  2128. mente eingefügt und an deren Ende sie wieder entnommen werden können.
  2129. FIFO wurde von Dirk Theisen geschrieben.
  2130.  
  2131. 14.2.5) LRU
  2132. ...........
  2133.  
  2134. LRU (Least recently used)  implementiert  eine  Prioritätenliste  nach  dem
  2135. Prinzip 'am längsten nicht mehr benutzt zuerst'.
  2136. LRU wurde von Dirk Theisen geschrieben.
  2137.  
  2138. 14.2.6) Stack
  2139. .............
  2140.  
  2141. Stack implementiert eine Liste, an deren Anfang Elemente eingefügt und wie-
  2142. der entnommen werden können.
  2143. Stack wurde von Dirk Theisen geschrieben.
  2144.  
  2145. 14.3) Standardmodule
  2146. --------------------
  2147.  
  2148. Unter diesem Abschnitt werden alle Module zusammengefaßt, die in beliebigen
  2149. Applikationen (TOS oder GEM) benutzt werden können.
  2150.  
  2151. 14.3.1) Buffers
  2152. ...............
  2153.  
  2154. Buffers implementiert einen einfachen flexiblen Puffer,  der als  Grundlage
  2155. für gepufferte Ausgabe dienen soll.
  2156.  
  2157. 14.3.2) CommandLine
  2158. ...................
  2159.  
  2160. CommandLine implementiert die Auswertung eines per  ARGV  übergebenen  Kom-
  2161. mandos, kann aber auch mit der normalen Commandline arbeiten.
  2162. CommandLine wurde von Dirk Theisen geschrieben.
  2163.  
  2164. 14.3.3) Cookie
  2165. ..............
  2166.  
  2167. Suchen, Setzen und Löschen von Einträgen im Cookie Jar.
  2168.  
  2169. 14.3.4) Datum
  2170. .............
  2171.  
  2172. Das Modul Datum arbeitet mit Daten.
  2173. Datum wurde von Wolfgang Radtke geschrieben.
  2174.  
  2175. 14.3.5) Environment
  2176. ...................
  2177.  
  2178. Suchen von Einträgen im Environment.
  2179.  
  2180. 14.3.6) Error
  2181. .............
  2182.  
  2183. Standardisierte  Ausgabe  von   Fehlermeldungen,   insbesondere   des   Be-
  2184. triebssystems, über eine Alertbox.
  2185.  
  2186. 14.3.7) Exceptions
  2187. ..................
  2188.  
  2189. Exceptions fängt Softwarefehler wie Bus Error etc.  ab und gibt  eine  pas-
  2190. sende Meldung aus.  Es genügt,  Exceptions zu importieren oder mit LINKALSO
  2191. hinzuzulinken.
  2192.  
  2193. 14.3.8) Execute
  2194. ...............
  2195.  
  2196. Execute ist immer dann zu verwenden,  wenn man nicht genau weiß, in welcher
  2197. Form (Modul oder Programm) etwas gestartet werden soll.  Daher gibt es  ein
  2198. Execute im Lader,  das Module startet,  und ein kompatibles zum Linken, das
  2199. Programme startet.
  2200.  
  2201. 14.3.9) File
  2202. ............
  2203.  
  2204. Hoffnungslos veraltetes Modul zur Dateibehandlung.
  2205.  
  2206. 14.3.10) FileBuffer
  2207. ...................
  2208.  
  2209. Ebenfalls veraltetes Modul  zur  Dateibehandlung  mit  zwischengeschaltetem
  2210. Puffer.
  2211.  
  2212. 14.3.11) Filename
  2213. .................
  2214.  
  2215. Zusammensetzen und Aufteilen von Dateinamen.
  2216.  
  2217. 14.3.12) IO
  2218. ...........
  2219.  
  2220. IO implementiert Standardprozeduren zur Ein- und Ausgabe auf dem  TOS-Bild-
  2221. schirm.  Die Benutzung in GEM-Programmen sollte vermieden werden,  da  dann
  2222. unschön auf den Bildschirm geschrieben wird.  Im Lader ist ein  kompatibles
  2223. Modul mit anderer Implementierung integriert,  daß die Ausgabe in das  CLI-
  2224. Fenster von Chatwin umlenkt.
  2225.  
  2226. 14.3.13) Kernel
  2227. ...............
  2228.  
  2229. Kernel  stellt  hauptsächlich  die  Speicherverwaltung,  aber  auch  einige
  2230. Hilfsprozeduren zur Verfügung.
  2231.  
  2232. 14.3.14) Key
  2233. ............
  2234.  
  2235. War mal die Grundlage für die  Zuweisung  von  Prozeduren  zu  Tastenkombi-
  2236. nationen. Wird im Moment nicht benutzt.
  2237.  
  2238. 14.3.15) MathCom
  2239. ................
  2240.  
  2241. Grundlegende Prozeduren für mathematische Funktionen. Entstammt LPR-Modula.
  2242.  
  2243. 14.3.16) MathLib0
  2244. .................
  2245.  
  2246. Übliche mathematische Funktionen. Entstammt LPR-Modula.
  2247.  
  2248. 14.3.17) Memory
  2249. ...............
  2250.  
  2251. Sehr schnelle Prozeduren zum Kopieren und Füllen von Speicher.
  2252.  
  2253. 14.3.18) Modules
  2254. ................
  2255.  
  2256. Modules ist für das Nachladen von Modulen in den Ladern zuständig.
  2257.  
  2258. 14.3.19) MVC
  2259. ............
  2260.  
  2261. MVC steht für Model View Controller. Es implementiert Viewer, deren Ausgabe
  2262. vom Inhalt eines Models abhängen.  WinView baut darauf auf. Theoretisch ist
  2263. es aber nicht an Fenster gebunden,  man könnte auch Pseudofenster auf einem
  2264. TOS-Bildschirm darauf aufbauen.
  2265.  
  2266. 14.3.20) NumStr
  2267. ...............
  2268.  
  2269. Umwandlung von Zahlen in Strings und umgekehrt.
  2270.  
  2271. 14.3.21) Paths
  2272. ..............
  2273.  
  2274. Suchpfadverwaltung.
  2275.  
  2276. 14.3.22) Strings
  2277. ................
  2278.  
  2279. Was man so braucht um mit Strings umzugehen.
  2280.  
  2281. 14.3.23) Supervisor
  2282. ...................
  2283.  
  2284. Ein- und Ausschalten des Supervisormodus.
  2285.  
  2286. 14.3.24) Sys
  2287. ............
  2288.  
  2289. Die Grundlage aller Programme.  Enthält alle Standardfunktionen des  Compi-
  2290. lers sowie die Programminitialisierung.
  2291.  
  2292. 14.3.25) Task
  2293. .............
  2294.  
  2295. Enthält den Mechanismus zur sauberen Terminierung von Programmen oder  Pro-
  2296. grammteilen. Normalerweise uninteressant für Anwender.
  2297.  
  2298. 14.3.26) VA
  2299. ...........
  2300.  
  2301. VA enthält die Konstanten,  die für das AV-Protokoll (Accessory <->  Venus)
  2302. benötigt werden.
  2303.  
  2304. 14.4) VDI-Module
  2305. ----------------
  2306.  
  2307. Das VDI implementiert alles zur Ausgabe auf beliebigen Geräten.  Es ist mir
  2308. nicht bekannt, ob es auch in TOS-Programmen benutzt werden darf.
  2309.  
  2310. 14.4.1) VDI
  2311. ...........
  2312.  
  2313. Die grundlegenden Strukturen und Variablen zur Arbeit mit dem VDI.
  2314.  
  2315. 14.4.2) VDIAttributes
  2316. .....................
  2317.  
  2318. Einstellen von Attributen für die Ausgabe.
  2319.  
  2320. 14.4.3) VDIControl
  2321. ..................
  2322.  
  2323. Kontrollfunktionen des VDI.  Es existiert  eine  zusätzliche  Funktion  zum
  2324. Test, ob GDOS installiert ist.
  2325.  
  2326. 14.4.4) VDIExcapes
  2327. ..................
  2328.  
  2329. Escaperoutinen des VDI.
  2330.  
  2331. 14.4.5) VDIInput
  2332. ................
  2333.  
  2334. Eingaberoutinen des VDI.
  2335.  
  2336. 14.4.6) VDIInquiry
  2337. ..................
  2338.  
  2339. Abfrageroutinen des VDI.
  2340.  
  2341. 14.4.7) VDIOutput
  2342. .................
  2343.  
  2344. Ausgaberoutinen des VDI.
  2345.  
  2346. 14.4.8) VDIRaster
  2347. .................
  2348.  
  2349. Rasterfunktionen des VDI.  Zusätzlich gibt es hier ein paar  Kopierroutinen
  2350. zum Scrollen von Bildschirmausschnitten.
  2351.  
  2352. 14.5) AES-Module
  2353. ----------------
  2354.  
  2355. Das AES implementiert das,  was man so liebgewonnen hat auf dem Atari:  Me-
  2356. nüs, Fenster und und und. Bis auf Form.Alert führen diese Prozeduren in ei-
  2357. nem TOS-Programm zum Absturz.
  2358.  
  2359. 14.5.1) AES
  2360. ...........
  2361.  
  2362. Die grundlegenden Strukturen und Variablen zur Arbeit mit dem AES.
  2363.  
  2364. 14.5.2) Appl
  2365. ............
  2366.  
  2367. Die Funktionen der Application Library.
  2368.  
  2369. 14.5.3) Evnt
  2370. ............
  2371.  
  2372. Die Funktionen der Event Library.
  2373.  
  2374. 14.5.4) Form
  2375. ............
  2376.  
  2377. Die Funktionen der Form Library.  Form.Alert darf  auch  in  TOS-Programmen
  2378. verwendet werden.
  2379.  
  2380. 14.5.5) Fsel
  2381. ............
  2382.  
  2383. Fileselectbox darstellen. Die neue Funktion mit Titel ist auch vorhanden.
  2384.  
  2385. 14.5.6) Graf
  2386. ............
  2387.  
  2388. Die Funktionen der Graphics Library.  Graf.Mouse wurde auf vier  Prozeduren
  2389. verteilt und Graf.Mkstate in Evnt verlegt.
  2390.  
  2391. 14.5.7) Menu
  2392. ............
  2393.  
  2394. Die Funktionen der Menu Library.
  2395.  
  2396. 14.5.8) Objc
  2397. ............
  2398.  
  2399. Die Funktionen der Object Library, stark erweitert um Funktionen zum Umgang
  2400. mit den Objekten.
  2401.  
  2402. 14.5.9) Rsrc
  2403. ............
  2404.  
  2405. Die Funktionen der Resource  Library.  Rsrc.Load  ist  auch  in  der  Lage,
  2406. selbständig zu suchen, wenn ein Resourcefile nicht gefunden wurde.
  2407.  
  2408. 14.5.10) Wind
  2409. .............
  2410.  
  2411. Die Funktionen der Window Library.
  2412.  
  2413. 14.6) Erweiterte AES-Module
  2414. ---------------------------
  2415.  
  2416. Zum einfacheren Umgang mit dem AES wurden folgende Module entwickelt:
  2417.  
  2418. 14.6.1) Dialogs
  2419. ...............
  2420.  
  2421. Dialogs enthält alle Prozeduren,  um ganz  einfach  eine  Dialogbox  darzu-
  2422. stellen und den Dialog mit dem Anwender zu führen.
  2423.  
  2424. 14.6.2) FontSelect
  2425. ..................
  2426.  
  2427. FontSelect bietet eine einfache Möglichkeit, mit einer Dialogbox den Benut-
  2428. zer einen Font auswählen zu lassen.
  2429.  
  2430. 14.6.3) GemApp
  2431. ..............
  2432.  
  2433. GemApp bildet die Grundlage zur Programmierung  von  GEM-Applikationen.  Es
  2434. muß unbedingt benutzt werden,  wenn die  erweiterten  AES-Module  verwendet
  2435. werden.
  2436.  
  2437. 14.6.4) GEMIO
  2438. .............
  2439.  
  2440. GEMIO ist das Pendant zu IO für TOS.  Die Schnittstellen sind identisch, so
  2441. daß man statt IO auch GEMIO linken kann.
  2442.  
  2443. 14.6.5) Menus
  2444. .............
  2445.  
  2446. Menus automatisiert den Aufruf von Prozeduren über Menüpunkte oder  Tasten-
  2447. kombinationen. Die Tastenkombinationen werden aus dem Eintrag des Menüs ge-
  2448. lesen und können dadurch von Benutzern individuell geändert werden!
  2449.  
  2450. 14.6.6) TermWin
  2451. ...............
  2452.  
  2453. TermWin erweitert WinView derart,  daß mit üblichen Schreibbefehlen (Write-
  2454. String...) Text in einem Fenster ausgegeben werden kann.  Desweiteren  wird
  2455. ein Event STRING eingeführt.
  2456.  
  2457. 14.6.7) WindowDialog
  2458. ....................
  2459.  
  2460. WindowDialog verlegt einen Dialog in ein Fenster.
  2461.  
  2462. 14.6.8) WinView
  2463. ...............
  2464.  
  2465. WinView ist die Grundlage für Fensterapplikationen.  Fast das gesamte Hand-
  2466. ling von Fensters ist automatisiert.  Im einfachsten Fall muß man nur  noch
  2467. eine Redrawprozedur implementieren.
  2468.  
  2469.  
  2470. 15) Tutorial
  2471. ============
  2472.  
  2473. Im nun folgenden Kapitel soll ein GEM-Programm entwickelt werden,  daß eine
  2474. Menüleiste hat,  über einen Dialog in einem Fenster Eingaben ermöglicht und
  2475. diese Eingaben graphisch in beliebig vielen Fenstern  ausgeben  kann.  Eine
  2476. neue Eingabe muß dann natürlich in allen Fenstern gezeichnet werden.
  2477.  
  2478. 15.1) Die Resourcedatei
  2479. -----------------------
  2480.  
  2481. Die Resourcedatei wird mit einem Resource Construction  Set  erstellt.  Die
  2482. Resourcedatei für unser Projekt heißt GEMDEMO.RSC.  Wer noch nie  eine  Re-
  2483. sourcedatei erzeugt hat,  sollte sich erstmal mit einem RCS  GEMDEMO.RSCan-
  2484. gucken und mal etwas damit spielen.  Aber bitte nicht verändert abspeichern
  2485. und mir dann eine Mail schicken, das Demo würde nicht funktionieren!
  2486.  
  2487. 15.2) Der Rumpf
  2488. ---------------
  2489.  
  2490. [hbpt]
  2491.  
  2492. MODULE Tutor1;
  2493.  
  2494. IMPORT GemApp;
  2495.  
  2496. VAR
  2497.   myApp : GemApp.Application;
  2498.  
  2499. BEGIN
  2500.   NEW( myApp);
  2501.   myApp.Init; myApp.Run; myApp.Exit
  2502. END Tutor1.
  2503.  
  2504.  
  2505.  
  2506.   Abb. ?? zeigt den prinzipiellen Aufbau einer Applikation:  Definition ei-
  2507. ner Variablen vom Typ Application,  deren Initialisierung  und  Aufruf  der
  2508. daran gebundenen Prozeduren Init, Run und Exit. Init initialisiert das Pro-
  2509. gramm.  Dazu gehört z.B.  die Anmeldung beim  AES.  Run  implementiert  die
  2510. Event-Schleife,  also warten auf Events vom AES und Aufruf von HandleEvent,
  2511. das ebenfalls an Application gebunden ist. Exit meldet die Applikation dann
  2512. wieder ab und sorgt auch für  eine  saubere  Terminierung,  z.B.  Schließen
  2513. evtl. offen gebliebener Fenster etc. Sollte jemand dieses Programm starten,
  2514. wird er in die Eventschleife gelangen.  Diese kann  mit  Control-Qverlassen
  2515. werden, diese Taste wird immer ausgewertet.
  2516.  
  2517. 15.3) Resourcedatei laden
  2518. -------------------------
  2519.  
  2520. Als nächstes müssen wir die Resourcedatei laden. Abb. ?? zeigt die Erweite-
  2521. rungen.
  2522.  
  2523. [hbpt]
  2524.  
  2525. TYPE
  2526.   Application = POINTER TO ApplDesc;
  2527.   ApplDesc    = RECORD(GemApp.ApplDesc)
  2528.                 END;
  2529.  
  2530. VAR
  2531.   myApp : Application;
  2532.  
  2533. PROCEDURE (app : Application) Init;
  2534.  BEGIN
  2535.   app.Init^;
  2536.   Graf.ChangeMouse( Graf.ARROW);
  2537.   IF NOT Rsrc.Load("GEMDEMO.RSC") THEN
  2538.     app.Exit
  2539.   END;
  2540.  END Init;
  2541.  
  2542.  
  2543.  
  2544.   Zunächst wurde eine Erweiterung von GemApp.ApplDesc definiert, damit eine
  2545. neue Prozedur Init daran gebunden werden kann.  Diese muß unbedingt als er-
  2546. stes die geerbte Prozedur Init aufrufen.  Als nächstes wird der  Mauszeiger
  2547. als Pfeil dargstellt, da er beim Programmstart immer auf 'Biene' steht. Der
  2548. Aufruf von Rsrc.Load bewirkt das Laden und evtl.  auch Suchen der Resource-
  2549. datei.  Wenn der Benutzer in der  Fileselectbox  'Abbruch'  anklickt,  gibt
  2550. Rsrc.Load FALSE zurück und die Applikation wird terminiert.  app.Exit  wird
  2551. nicht mehr verlassen, deshalb geht das. Wenn man das Programm startet, ver-
  2552. hält es sich wie Tutor1, nur daß die Maus auf Pfeil umgeschaltet wird.
  2553.  
  2554. 15.4) Die Menüzeile
  2555. -------------------
  2556.  
  2557. Nun wollen wir die Menüzeile anzeigen.  Abb. ?? zeigt die  Erweiterung  von
  2558. Init.
  2559.  
  2560. [hbpt]
  2561.  
  2562. TYPE
  2563.   Application = POINTER TO ApplDesc;
  2564.   ApplDesc    = RECORD(GemApp.ApplDesc)
  2565.                 END;
  2566.  
  2567. PROCEDURE ShowInfo;
  2568.   VAR d : INTEGER;
  2569.  BEGIN
  2570.   d := Form.Alert(1, "[1][Tutor3 by Stephan Junker][Ok]");
  2571.  END ShowInfo;
  2572.  
  2573. PROCEDURE Exit;
  2574.  BEGIN
  2575.   GemApp.exit := TRUE;
  2576.  END Exit;
  2577.  
  2578. PROCEDURE (app : Application) Init;
  2579.   VAR menu : Menus.Menu;
  2580.  BEGIN
  2581.   [...]
  2582.   NEW(menu); menu.Init( Rsrc.GetAddr(MENU) );
  2583.   menu.Set( FILE, QUIT, Exit );
  2584.   menu.Set( DESK, INFO, ShowInfo );
  2585.   menu.Show;
  2586.  END Init;
  2587.  
  2588.  
  2589.  
  2590.   Zunächst alloziert man das Objekt menu und initialisiert es.  Sodann emp-
  2591. fiehlt es sich,  eine Prozedur für den Menüpunkt QUIT anzumelden, damit man
  2592. das Programm auch wieder verlassen kann.  Dann kann man mit  menu.Show  die
  2593. Menüzeile darstellen.
  2594.  
  2595.   Beim Start werden sie feststellen,  daß sowohl beim Anklicken von  'Quit'
  2596. als auch bei Drücken von Control-Qdas Programm verlassen wird. Wie funktio-
  2597. niert das? Ganz einfach: Menus hat mit GemApp.StoreEventHandler eine Proze-
  2598. dur angemeldet,  die Events verarbeitet.  Diese wird immer aufgerufen, wenn
  2599. ein Ereignis vom AES gemeldet wird,  und filtert die Ereignisse heraus, die
  2600. für das Menü benötigt werden.
  2601.  
  2602. 15.5) Ein Fenster öffnen
  2603. ------------------------
  2604.  
  2605. Beim Aufruf des Menüpunktes 'Ausgabefenster' soll nun ein Fenster  geöffnet
  2606. werden.  Der Einfachheit halber wird es nur eine weiße  Fläche  darstellen.
  2607. Abb. ?? zeigt die Änderungen.
  2608.  
  2609.  
  2610.  
  2611.  
  2612. TYPE
  2613.   Viewer    = POINTER TO ViewDesc;
  2614.   ViewDesc  = RECORD(WinView.ViewDesc)
  2615.               END;
  2616.   MyModel   = POINTER TO ModelDesc;
  2617.   ModelDesc = RECORD(MVC.ModelDesc)
  2618.               END;
  2619.  
  2620. VAR
  2621.   myModel : MyModel;
  2622.   Station : INTEGER;
  2623.   Workout : VC.workout;
  2624.  
  2625. PROCEDURE(v : Viewer) Redraw(x,y,w,h : INTEGER);
  2626.   VAR x2, y2 : INTEGER;
  2627.  BEGIN
  2628.   x2 := x+w-1; y2 := y+h-1;
  2629.   VC.VsClip( Station, TRUE, x, y, x2, y2);
  2630.   VO.VBar( Station, x, y, x2, y2 );
  2631.  END Redraw;
  2632.  
  2633. PROCEDURE OpenOutput;
  2634.   VAR outWin  : Viewer;
  2635.  BEGIN
  2636.   NEW( outWin); outWin.Init;
  2637.   outWin.model := myModel;
  2638.   outWin.SetTitle("Objektfenster");
  2639.   outWin.SetFullSize( 0, 19, Workout.MaxX - 1,
  2640.                       Workout.MaxY - 20);
  2641.   outWin.Open;
  2642.  END OpenOutput;
  2643.  
  2644. PROCEDURE (app : Application) Init;
  2645.   VAR Workin : VC.workin;
  2646.       menu : Menus.Menu;
  2647.  BEGIN
  2648.   [...]
  2649.   NEW( menu); menu.Init( Rsrc.GetAddr(MENU) );
  2650.   menu.Set( FILE, QUIT, Exit );
  2651.   menu.Set( DESK, INFO, ShowInfo );
  2652.   menu.Set( WORK, OUTPUT2, OpenOutput );
  2653.   menu.Show;
  2654.   Station := 1;
  2655.   Workin.Id := 1; Workin.LineType := 1;
  2656.   Workin.LineColor := 1; Workin.MarkType := 1;
  2657.   Workin.MarkColor := 1; Workin.Font := 1;
  2658.   Workin.TextColor := 1; Workin.FillStyle := 0;
  2659.   Workin.FillPat := 0; Workin.FillColor := 1;
  2660.   Workin.KoorType := 2;
  2661.   VC.VOpnvwk(Workin,Station,Workout);
  2662.   VA.VswrMode(Station,VA.REPLACE);
  2663.   VA.VsfPerimeter(Station,FALSE);
  2664.   NEW( myModel); myModel.Init;
  2665.  END Init;
  2666.  
  2667. [hbpt]
  2668.  
  2669.  
  2670.   Zunächst wird die Prozedur OpenOutput für den  Menüpunkt  angemeldet.  Es
  2671. folgt die Öffnung einer virtuellen Workstation,  die zum Zeichnen des  Fen-
  2672. sterinhaltes benötigt wird.  Als letztes wird noch ein Model initialisiert,
  2673. das später die Daten für die Ausgabefenster aufnimmt.  OpenOutput  muß  ein
  2674. Fenster initialisieren, das Model, Titel und maximale Größe festlegen. Dann
  2675. kann es geöffnet werden.  outWin ist tatsächlich eine lokale Variable!  Wie
  2676. das gehen soll? Ganz einfach, die Verwaltung der Fenster übernimmt WinView!
  2677. Das einzige,  was wir noch machen müssen,  ist den Inhalt neuzeichnen. Dies
  2678. übernimmt die Prozedur Redraw, die an einen Typ Viewer gebunden werden muß.
  2679. Diese wird von WinView immer automatisch aufgerufen,  wenn das AES eine Re-
  2680. draw-Message verschickt. Die Ereignisse, die Fenster betreffen, werden wie-
  2681. der durch einen EventHandler bearbeitet,  der bei GemApp angemeldet  wurde.
  2682. Deshalb funktionieren auch Mover,  Closer,  Fuller etc.  ohne das  wir  uns
  2683. darum gekümmert haben!
  2684.  
  2685. 15.6) Einen Dialog darstellen
  2686. -----------------------------
  2687.  
  2688. Nun wollen wir einen Dialog mit dem Benutzer in einem Fenster  führen.  Die
  2689. Änderungen sind in Abb. ?? skizziert.
  2690.  
  2691. [hbpt]
  2692.  
  2693. VAR
  2694.   infoDial : WDial.Viewer;
  2695.  
  2696. PROCEDURE ShowInfo;
  2697.  BEGIN
  2698.   infoDial.Open;
  2699.  END ShowInfo;
  2700.  
  2701. PROCEDURE (app : Application) Init;
  2702.  BEGIN
  2703.   [...]
  2704.   NEW( infoDial);
  2705.   infoDial.InitDialog( Rsrc.GetAddr(BOX) , 0, TRUE);
  2706.   infoDial.SetWork(OK, NIL, { WDial.DESELECT,
  2707.                               WDial.EXITONLY } );
  2708.   infoDial.SetWork(OUTPUT1, OpenOutput,
  2709.              { WDial.DESELECT, WDial.REDRAWOBJ } );
  2710.   infoDial.SetTitle("Information");
  2711.  END Init;
  2712.  
  2713.  
  2714.  
  2715.   Die Initialisierung eines Dialog erfolgt wieder in Init.  Mit  InitDialog
  2716. wird der Viewer initialialisiert.  Dabei wird ihm auch der  zugehörige  Ob-
  2717. jektbaum mitgeteilt. Mit SetWork werden den Buttons im Dialog, die den Sta-
  2718. tus Exit haben, Prozeduren zugewiesen, die beim Anklicken aufgerufen werden
  2719. sollen. An dieser Stelle ist auch schon eine zweite Möglichkeit vorgesehen,
  2720. ein Ausgabefenster zu öffnen.  Geöffnet wird der Dialog  über  den  Eintrag
  2721. 'Information'.
  2722.  
  2723. 15.7) Das fertige Programm
  2724. --------------------------
  2725.  
  2726. Was noch fehlt,  ist eine Dialogbox zur Eingabe von Objekten und der Redraw
  2727. dieser Objekte. Abb. ?? zeigt das komplette Programm.
  2728.  
  2729.  
  2730.  
  2731. MODULE GemDemo;
  2732.  
  2733.  
  2734. IMPORT S:=SYSTEM, GemApp, MVC, WinView, Evnt,
  2735.        Graf, VC:=VDIControl, VA:=VDIAttributes,
  2736.        VO:=VDIOutput, Menus, Rsrc, Form, Objc,
  2737.        WDial:=WindowDialog, NumStr;
  2738.  
  2739.  
  2740. CONST
  2741.     BOX        = 0; (* form/dialog *)
  2742.     OK         = 4; (* BUTTON in tree BOX *)
  2743.     INPUT1     = 5; (* BUTTON in tree BOX *)
  2744.     OUTPUT1    = 6; (* BUTTON in tree BOX *)
  2745.  
  2746.     MENU       = 1; (* menu *)
  2747.     DESK       = 3; (* TITLE in tree MENU *)
  2748.     FILE       = 4; (* TITLE in tree MENU *)
  2749.     WORK       = 5; (* TITLE in tree MENU *)
  2750.     INFO       = 8; (* STRING in tree MENU *)
  2751.     QUIT       = 17; (* STRING in tree MENU *)
  2752.     INPUT2     = 19; (* STRING in tree MENU *)
  2753.     OUTPUT2    = 20; (* STRING in tree MENU *)
  2754.  
  2755.     INPUTBOX   = 2; (* form/dialog *)
  2756.     CIRCLE     = 2; (* BUTTON in tree INPUTBOX *)
  2757.     RECT       = 3; (* BUTTON in tree INPUTBOX *)
  2758.     XPOS       = 4; (* FTEXT in tree INPUTBOX *)
  2759.     YPOS       = 5; (* FTEXT in tree INPUTBOX *)
  2760.     RADIUS     = 6; (* FTEXT in tree INPUTBOX *)
  2761.     WIDTH      = 7; (* FTEXT in tree INPUTBOX *)
  2762.     HEIGHT     = 8; (* FTEXT in tree INPUTBOX *)
  2763.     DRAW       = 9; (* BUTTON in tree INPUTBOX *)
  2764.  
  2765.  
  2766.  
  2767. TYPE
  2768.   Viewer    = POINTER TO ViewDesc;
  2769.   ViewDesc  = RECORD(WinView.ViewDesc)
  2770.               END;
  2771.   Application = POINTER TO ApplDesc;
  2772.   ApplDesc  = RECORD(GemApp.ApplDesc)
  2773.               END;
  2774.   Object    = POINTER TO ObjDesc;
  2775.   ObjDesc   = RECORD
  2776.                 next : Object;
  2777.                 x,y  : INTEGER;
  2778.               END;
  2779.   Circle    = POINTER TO CircleDesc;
  2780.   CircleDesc= RECORD(ObjDesc)
  2781.                 r : INTEGER;
  2782.               END;
  2783.   Rect      = POINTER TO RectDesc;
  2784.   RectDesc  = RECORD(ObjDesc)
  2785.                 w,h  : INTEGER;
  2786.               END;
  2787.   MyModel   = POINTER TO ModelDesc;
  2788.   ModelDesc = RECORD(MVC.ModelDesc)
  2789.                 objects : Object;
  2790.               END;
  2791.  
  2792.  
  2793. VAR myApp : Application;
  2794.     infoDial,inputDial : WDial.Dialog;
  2795.     myModel : MyModel;
  2796.     Station : INTEGER;
  2797.     Workout : VC.workout;
  2798.  
  2799.  
  2800. PROCEDURE(o : Object) Draw(v : Viewer);
  2801.  BEGIN
  2802.  END Draw;
  2803.  
  2804.  
  2805. PROCEDURE(c : Circle) Draw(v : Viewer);
  2806.  BEGIN
  2807.   VO.VArc( Station, v.x - SHORT( v.xOff) + c.x,
  2808.          v.y - SHORT( v.yOff) + c.y, c.r, 0, 3600 );
  2809.  END Draw;
  2810.  
  2811.  
  2812. PROCEDURE(r : Rect) Draw(v : Viewer);
  2813.   VAR Edges : ARRAY 10 OF INTEGER;
  2814.  BEGIN
  2815.   Edges[0] := v.x - SHORT( v.xOff) + r.x;
  2816.   Edges[1] := v.y - SHORT( v.yOff) + r.y;
  2817.   Edges[2] := Edges[0];
  2818.   Edges[3] := Edges[1] + r.h - 1;
  2819.   Edges[4] := Edges[0] + r.w - 1;
  2820.   Edges[5] := Edges[3];
  2821.   Edges[6] := Edges[4];
  2822.   Edges[7] := Edges[1];
  2823.   Edges[8] := Edges[0];
  2824.   Edges[9] := Edges[1];
  2825.   VO.VPline( Station, 5, Edges);
  2826.  END Draw;
  2827.  
  2828.  
  2829. PROCEDURE(v : Viewer) Redraw(x,y,w,h : INTEGER);
  2830.   VAR x2, y2 : INTEGER;
  2831.       obj : Object;
  2832.  BEGIN
  2833.   x2 := x+w-1; y2 := y+h-1;
  2834.   VC.VsClip( Station, TRUE, x, y, x2, y2);
  2835.   VO.VBar( Station, x, y, x2, y2 );
  2836.   obj := myModel.objects;
  2837.   WHILE obj # NIL DO
  2838.     obj.Draw(v); obj := obj.next;
  2839.   END;
  2840.  END Redraw;
  2841.  
  2842.  
  2843. PROCEDURE(m : MyModel) Init;
  2844.  BEGIN
  2845.   m.objects := NIL; m.Init^;
  2846.  END Init;
  2847.  
  2848.  
  2849. PROCEDURE ShowInfo;
  2850.  BEGIN
  2851.   infoDial.Open;
  2852.  END ShowInfo;
  2853.  
  2854.  
  2855. PROCEDURE Exit;
  2856.  BEGIN
  2857.   GemApp.exit := TRUE; (* die saubere Methode *)
  2858.  END Exit;
  2859.  
  2860.  
  2861. PROCEDURE OpenInput;
  2862.  BEGIN
  2863.   inputDial.Open;
  2864.  END OpenInput;
  2865.  
  2866.  
  2867. PROCEDURE SetDWH(v : Viewer);
  2868.   VAR obj : Object; maxX, maxY, dw, dh : INTEGER;
  2869.  BEGIN
  2870.   obj := myModel.objects;
  2871.   dw := SHORT(v.dw); dh := SHORT(v.dh);
  2872.   WHILE obj # NIL DO
  2873.     IF obj IS Rect THEN
  2874.       maxX := obj.x + obj(Rect).w;
  2875.       maxY := obj.y + obj(Rect).h;
  2876.     ELSE
  2877.       maxX := obj.x + obj(Circle).r;
  2878.       maxY := obj.y + obj(Circle).r;
  2879.     END;
  2880.     IF maxX > dw THEN dw := maxX END;
  2881.     IF maxY > dh THEN dh := maxY END;
  2882.     obj := obj.next;
  2883.   END;
  2884.   IF dw # v.dw THEN v.dw := dw; v.HSlider END;
  2885.   IF dh # v.dh THEN v.dh := dh; v.VSlider END;
  2886.  END SetDWH;
  2887.  
  2888.  
  2889. PROCEDURE OpenOutput;
  2890.   VAR outWin  : Viewer;
  2891.  BEGIN
  2892.   NEW( outWin); outWin.Init;
  2893.   outWin.model := myModel; SetDWH(outWin);
  2894.   outWin.SetTitle("Objektfenster");
  2895.   outWin.SetFullSize( 0, 19, Workout.MaxX - 1,
  2896.                       Workout.MaxY - 20);
  2897.   outWin.Open;
  2898.  END OpenOutput;
  2899.  
  2900.  
  2901. PROCEDURE(v : Viewer) Update( aspect : LONGINT);
  2902.  BEGIN
  2903.   v.Update^( aspect); SetDWH(v);
  2904.  END Update;
  2905.  
  2906. (*$T- wegen NEW( obj(Rect) ) bzw. NEW( obj(Circle) ),
  2907.       denn Typcheck geht nur wenn das Objekt schon
  2908.       alloziert ist ... *)
  2909.  
  2910. PROCEDURE EnterNewObject;
  2911.   VAR x,y : INTEGER; obj : Object;
  2912.       tep : Objc.tedinfoptr;
  2913.  BEGIN
  2914.   IF Objc.SELECTED IN
  2915.      Objc.GetState( inputDial.objTree, RECT) THEN
  2916.     NEW( obj(Rect) );
  2917.     tep := Objc.GetSpec( inputDial.objTree, WIDTH);
  2918.     obj(Rect).w := NumStr.ToInt( 10, tep.Text^);
  2919.     tep := Objc.GetSpec( inputDial.objTree, HEIGHT);
  2920.     obj(Rect).h := NumStr.ToInt( 10, tep.Text^);
  2921.   ELSE
  2922.     NEW( obj(Circle) );
  2923.     tep := Objc.GetSpec( inputDial.objTree, RADIUS);
  2924.     obj(Circle).r := NumStr.ToInt( 10, tep.Text^);
  2925.   END;
  2926.   tep := Objc.GetSpec( inputDial.objTree, XPOS);
  2927.   obj.x := NumStr.ToInt( 10, tep.Text^);
  2928.   tep := Objc.GetSpec( inputDial.objTree, YPOS);
  2929.   obj.y := NumStr.ToInt( 10, tep.Text^);
  2930.   obj.next := myModel.objects;
  2931.   myModel.objects := obj;
  2932.   myModel.Changed( 0);
  2933.  END EnterNewObject;
  2934.  
  2935. (*$T= *)
  2936.  
  2937. PROCEDURE EnableCircle;
  2938.  BEGIN
  2939.   inputDial.SetCursor( XPOS);
  2940.   Objc.SetFlags( inputDial.objTree, WIDTH,
  2941.                  {Objc.EDITABLE, Objc.HIDDEN} );
  2942.   inputDial.RedrawObj( WIDTH);
  2943.   Objc.SetFlags( inputDial.objTree, HEIGHT,
  2944.                  {Objc.EDITABLE, Objc.HIDDEN} );
  2945.   inputDial.RedrawObj( HEIGHT);
  2946.   Objc.SetFlags( inputDial.objTree, RADIUS,
  2947.                  {Objc.EDITABLE} );
  2948.   inputDial.RedrawObj( RADIUS);
  2949.  END EnableCircle;
  2950.  
  2951.  
  2952. PROCEDURE EnableRect;
  2953.  BEGIN
  2954.   inputDial.SetCursor( XPOS);
  2955.   Objc.SetFlags( inputDial.objTree, RADIUS,
  2956.                 {Objc.EDITABLE, Objc.HIDDEN} );
  2957.   inputDial.RedrawObj( RADIUS);
  2958.   Objc.SetFlags( inputDial.objTree, WIDTH,
  2959.                 {Objc.EDITABLE} );
  2960.   inputDial.RedrawObj( WIDTH);
  2961.   Objc.SetFlags( inputDial.objTree, HEIGHT,
  2962.                 {Objc.EDITABLE} );
  2963.   inputDial.RedrawObj( HEIGHT);
  2964.  END EnableRect;
  2965.  
  2966.  
  2967. PROCEDURE(app: Application) Init;
  2968.   VAR menu : Menus.Menu;
  2969.       Workin  : VC.workin;
  2970.  BEGIN
  2971.   app.Init^; (* must come first! *)
  2972.   Graf.ChangeMouse( Graf.ARROW);
  2973.   IF NOT Rsrc.Load("GEMDEMO.RSC") THEN
  2974.     app.Exit
  2975.   END;
  2976.   NEW(menu); menu.Init( Rsrc.GetAddr(MENU) );
  2977.   menu.Set( FILE, QUIT, Exit );
  2978.   menu.Set( DESK, INFO, ShowInfo );
  2979.   menu.Set( WORK, OUTPUT2, OpenOutput );
  2980.   menu.Set( WORK, INPUT2, OpenInput );
  2981.   menu.Show;
  2982.   Station := 1;
  2983.   Workin.Id := 1; Workin.LineType := 1;
  2984.   Workin.LineColor := 1; Workin.MarkType := 1;
  2985.   Workin.MarkColor := 1; Workin.Font := 1;
  2986.   Workin.TextColor := 1; Workin.FillStyle := 0;
  2987.   Workin.FillPat := 0; Workin.FillColor := 1;
  2988.   Workin.KoorType := 2;
  2989.   VC.VOpnvwk(Workin,Station,Workout);
  2990.   VA.VswrMode(Station,VA.REPLACE);
  2991.   VA.VsfPerimeter(Station,FALSE);
  2992.   NEW( myModel); myModel.Init;
  2993.   NEW( infoDial);
  2994.   infoDial.InitDialog( Rsrc.GetAddr(BOX) , 0, TRUE);
  2995.   infoDial.SetWork(OK, NIL, { WDial.DESELECT,
  2996.                               WDial.EXITONLY } );
  2997.   infoDial.SetWork(INPUT1, OpenInput,
  2998.              { WDial.DESELECT, WDial.REDRAWOBJ } );
  2999.   infoDial.SetWork(OUTPUT1, OpenOutput,
  3000.              { WDial.DESELECT, WDial.REDRAWOBJ } );
  3001.   infoDial.SetTitle("Information");
  3002.   NEW( inputDial);
  3003.   inputDial.InitDialog( Rsrc.GetAddr(INPUTBOX),
  3004.                        XPOS, TRUE);
  3005.   inputDial.SetWork(DRAW, EnterNewObject,
  3006.              { WDial.DESELECT, WDial.REDRAWOBJ } );
  3007.   inputDial.SetWork(CIRCLE, EnableCircle, {} );
  3008.   inputDial.SetWork(RECT, EnableRect, {} );
  3009.   inputDial.SetTitle("Neues Objekt");
  3010.   inputDial.SetText( XPOS, "");
  3011.   inputDial.SetText( YPOS, "");
  3012.   inputDial.SetText( WIDTH, "");
  3013.   inputDial.SetText( HEIGHT, "");
  3014.   inputDial.SetText( RADIUS, "");
  3015.   Objc.SetState( inputDial.objTree, RECT,
  3016.                  {Objc.SELECTED} );
  3017.  END Init;
  3018.  
  3019.  
  3020. BEGIN
  3021.   NEW(myApp);
  3022.   myApp.Init; myApp.Run; myApp.Exit
  3023. END GemDemo.
  3024.  
  3025.  
  3026. [hbpt]
  3027.  
  3028.  
  3029.   Was hat sich getan? Nun,  der Typ ModelDesc nimmt jetzt die Objekte  auf,
  3030. die dargestellt werden sollen. Redraw wurde erweitert, damit es die Objekte
  3031. zeichnen kann.  Eine weitere Dialogbox,  mit der die Objekte  vom  Anwender
  3032. eingegeben werden,  wurde erzeugt.  EnterNewObject liest die  Eingaben  aus
  3033. dieser Box und erzeugt daraus ein neues Objekt.  Mit EnableCircle bzw. Ena-
  3034. bleRect wird die Darstellung der Box geändert,  je nachdem ob der  Benutzer
  3035. Kreis oder Rechteck verlangt.  SetDWH paßt die Größe  der  Zeichnung  (also
  3036. dessen was insgesamt dargestellt werden soll) immer an die Größe der einge-
  3037. gebenen Objekte an. So kann man auch Zeichnungen darstellen, die größer als
  3038. ein Fenster sind.  Die Slider,  Pfeile etc.  werden alle automatisch  durch
  3039. WinView bedient.  Man kann praktisch unbegrenzt Fenster  öffnen  (zumindest
  3040. wenn man Winx oder MultiTOS installiert hat),  und bei Eingabe eines  neuen
  3041. Objektes werden alle auf den neuesten Stand gebracht.  Aber  jedes  Fenster
  3042. kann natürlich einen anderen Ausschnitt darstellen.
  3043.  
  3044. 15.8) Zusammenfassung
  3045. ---------------------
  3046.  
  3047. Dieses Kapitel sollte einige Möglichkeiten von Oberon  und  der  GEM-Module
  3048. zeigen.  Das Ergebnis war ein 300 Zeilen langes Programm,  daß  hoffentlich
  3049. einen guten Eindruck hinterlassen hat.
  3050.  
  3051.  
  3052. 16) Anhang
  3053. ==========
  3054.  
  3055. 16.1) Literatur
  3056. ---------------
  3057.  
  3058. N.  Wirth, J. Gutknecht: <Project Oberon: The design of an Operating System
  3059. and Compiler,> Addison-Wesley (1992), ISBN 0-201-54428-8.
  3060.  
  3061. M.  Reiser:  <The Oberon System: Usesr Guide and Programmer's Manual> Addi-
  3062. son-Wesley (1991), ISBN 0-201-54422-9.
  3063.  
  3064. M.  Reiser,  N.  Wirth:  <Programming in Oberon:  Steps beyond  Pascal  and
  3065. Modula>, Addison-Wesley (1992)
  3066.  
  3067. 16.2) Danksagungen
  3068. ------------------
  3069.  
  3070. Dank an Frank Storm,  der mich darauf gebracht hat, statt einem Modula- ei-
  3071. nen Oberon-Compiler zu schreiben und anfangs auch die E-Mail erledigt hat.
  3072.  
  3073. Dank an den Chefbetatester Dirk Theisen für den Browser und sonstige Unter-
  3074. stützung.
  3075.  
  3076. Dank an alle, die über Fehler berichten und neue Module implementieren.
  3077.  
  3078. Dank an Christian Strunk für seine TeX-Implementierung.
  3079.  
  3080. Dank an Roman Hodek für TeX2TXT, mit dem diese Anleitung in einen ganz pas-
  3081. sablen Asciitext konvertiert werden konnte.
  3082.  
  3083. Ach ja,  dann sollte ich wohl auch noch Niklaus Wirth und seinem Team  dan-
  3084. ken, daß er Oberon erdacht hat und die Sourcen frei weitergibt.