Workshops / Hintergrundberichte

1. ARexx-Kurs - Teil 4 (von Heiko Kuschel)

»ARexx-Kurs: Übersicht

1. Einführung in ARexx

2. Programmstruktur und Ansteuerung von anderen Programmen 3. Ein- und Ausgabe; Funktionen 4. komplexere Programmstrukturen 5. Beispiele für die Vernetzung von Programmen Änderungen vorbehalten. Spezielle Wünsche werden, wenn möglich, gerne aufgenommen.«

»

4. Programmstrukturen und Systemfunktionen

4.0. Vorbemerkungen

Hier wiederhole ich für Quereinsteiger noch einmal einen Teil der Vorbemerkungen, die ich zum ganzen Kurs gemacht habe.

Der Kurs wird als reine Text-Datei angefertigt, da auch Amiga aktuell u.a. in ASCII-Form verschickt wird. Um den Text etwas zu gliedern, habe ich daher ein paar "Textmarker" eingefügt.

********** unterteilt einzelne Abschnitte
__________ bezeichnet Beginn und Ende eines ARexx-Programms. Die Striche gehören nicht zum Programm!
Hinweis: In der HTML-Version verzichten wir auf diese Kennzeichnung und benutzen übersichtlichere Formatierungen

ARexx-Befehle werden in diesem Kurs immer GROSS geschrieben, obwohl das eigentlich nicht nötig ist. Auf diese Weise kann man sie aber leichter erkennen.

Ich hoffe, daß diese Regelung den Kurs etwas leserlicher macht.

Wenn Ihr spezielle Fragen habt, etwas nicht verstanden habt oder Anregungen und Ideen für weitere Kursteile habt, könnt Ihr euch gerne an mich wenden. Ich selbst benutze folgende ARexx-fähige Programme und kann daher auf deren Programmierung kurz eingehen, wenn das gewünscht wird: Wordworth, GoldEd, Database Professional, YAM, Miami, Voyager, TurboCalc.

Hier meine Kontaktadresse:

Heiko Kuschel
Lehmgrubenweg 13
97280 Remlingen
E-Mail: hk0006@wuerzburg.baynet.de

Und jetzt... viel Spaß mit ARexx!

4.1. Operatoren

Ein schwierig klingendes Wort für eine Sache, die wir zum Teil schon ganz selbstverständlich angewendet haben. Operatoren sind einfach die Zeichen, die zwei Variablen oder sonstige Ausdrücke auf irgendeine Art verknüpfen. Also z.B. ein simples +. Das Problem ist nur: Wie sollen diese Operatoren abgearbeitet werden, wenn mehrere in einem Ausdruck vorhanden sind? Aus Mathe kennst Du sicher noch "Punkt vor Strich": Erst mal und geteilt durch, dann plus und minus. In ARexx gibt es eine ganze Prioritätenliste der Operatoren, und auch hier gibt es welche, die wie Plus und Minus die gleiche Priorität haben. Diese Liste sieht folgendermaßen aus:

Operator    Pri.    Beschreibung
~           8       logisches "nicht"
+           8       als Präfix zur Konvertierung
-           8       Präfix
**          7       Potenzierung 2**6 meint "2 hoch 6"
*           6       Multiplikation
%           6       ganzzahlige Division
/           6       Division
//          6       Rest der Division
-           5       Subtraktion
+           5       Addition
Leerz.      4       Verkettung mit Leerzeichen
||          4       direkte Verkettung
~==         3       absolut ungleich
==          3       absolut gleich
~=          3       ungleich
=           3       gleich
>=          3       größer/gleich
>           3       größer
<=          3       kleiner/gleich
<           3       kleiner
&           2       logisches UND
|           1       logisches ODER
&&          1       logisches exklusiv ODER

Ich denke, es sollte kein Problem sein, diese Liste anzuwenden. Besonders interessant finde ich, daß es gleich extra Operatoren für eine ganzzahlige Division gibt, ebenso wie für den Rest bei einer solchen Operation.

4.2. Programmstruktur

Bis jetzt haben wir nur Programme geschrieben, die mehr oder weniger von oben nach unten abgearbeitet wurden. Je komplexer Programme werden, desto wichtiger ist es aber, auch noch Überblick zu behalten. Deshalb gibt es in so gut wie allen Programmiersprachen die Möglichkeit, ein Programm in Unterabschnitte aufzuteilen, die dann (z.B. über einen aussagekräftigen Namen) aufgerufen werden. Das Hauptprogramm ist dann oft nur noch dazu da, die Unterprogramme in der richtigen Reihenfolge aufzurufen.

Der erste dafür notwendige Befehl lautet CALL. CALL kann auf verschiedene Arten verwendet werden:

1. Aufruf einer ARexx-Funktion. Das Ergebnis wird in RESULT abgelegt

CALL OPEN(Dateiname usw.)
ECHO RESULT
ist gleichbedeutend mit
Ergebnis=OPEN(Dateiname usw.)
ECHO Ergebnis
2. Aufruf externer ARexx-Programme

Andere ARexx-Programme können mit CALL "rexx:MeinProg.rexx" gestartet werden.

3. Mit CALL kann in ein Unterprogramm verzweigt werden.

Das ist jetzt der Punkt, der für uns im Moment am interessantesten ist. Die Unterprogramme werden alle mit Namen versehen. Dieser Name wird einfach in die erste Zeile einer Unterroutine geschrieben und ein Doppelpunkt angehängt. Die letzte Zeile der Unterroutine enthält dann ein RETURN (Kehre zurück). Nochmal ein Beispiel mit "HelloWorld" gefällig?
/* Hello World Version 1.6.*/

CALL Fensteroeffnen
CALL FrageundAntwort
EXIT

Fensteroeffnen:
Erfolg=OPEN(Fenster,'CON:20/20/620/100/Hello World 1.6./CLOSE',R)
IF ~Erfolg THEN ECHO "Fehler!"
RETURN

FrageundAntwort:
DO WHILE Eingabe~="Ende"
Erfolg=WRITELN(Fenster,"Gib was ein!")
Eingabe=READLN(Fenster)
Erfolg=WRITELN(Fenster,"Du hast "||Eingabe||" eingegeben.")
END
RETURN
Beachte, wieviel kürzer und damit übersichtlicher selbst bei diesem Mini- Programm das Hauptprogramm geworden ist!

Übrigens: So ganz nebenbei habe ich hier den Befehl EXIT eingefügt. Er beendet das ARexx-Skript. Soll das Skript an das aufrufende Programm einen Wert zurückgeben, kann man den auch definieren, z.B. EXIT 10. Wenn ein Skript einfach irgendwo aufhört und kein Befehl mehr nachfolgt, sieht der Interpreter das als EXIT 0 an. Der Rückgabewert, der normalerweise für Fehlermeldungen benutzt wird, ist dann 0.

Jetzt wäre es natürlich noch schön, wenn man sich bei der Erstellung der Unterprogramme nicht immer darum kümmern müßte, welche Variablen im Hauptprogramm oder in anderen Unterprogrammen bereits verwendet wurden. Dann ist es z.B. sehr leicht möglich, einzelne Programmteile in anderen Skripten wiederzuverwerten, ohne irgend etwas daran verändern zu müssen. Und natürlich ist auch das möglich. Neben der einfachen Form von Unterprogrammen, wie wir sie gerade eingeführt haben, gibt es auch noch sogenannte Procedures, die völlig unabhängig vom Hauptprogramm arbeiten. Variablen im Hauptprogramm werden nicht verändert, außer man sagt es ausdrücklich. So eine Procedure wird durch den Befehl PROCEDURE definiert. Sie endet mit dem Befehl RETURN, bei dem noch angegeben werden kann, ob der Wert einer Variable in RESULT abgelegt werden soll.

/* Hello World Version 1.7.*/

CALL Fensteroeffnen
CALL FrageundAntwort
EXIT

Fensteroeffnen:
Erfolg=OPEN(Fenster,'CON:20/20/620/100/Hello World 1.6./CLOSE',R)
IF ~Erfolg THEN ECHO "Fehler!"
RETURN

FrageundAntwort:
DO WHILE Result~="Ende"
CALL Eingabefrage
CALL Ausgabe
END
RETURN

Eingabefrage:
Erfolg=WRITELN(Fenster,"Gib was ein!")
RETURN

Ausgabe: PROCEDURE
Eingabe=READLN(Fenster)
Erfolg=WRITELN(Fenster,"Du hast "||Eingabe||" eingegeben.")
RETURN Eingabe
Die Variable Eingabe existiert nur noch in der Prozedur Ausgabe! Versuche einmal herauszufinden, was diese Variable innerhalb des Hauptprogramms für einen Wert enthält! (Noch nicht benutzte Variablen enthalten ihren eigenen Namen in Großschrift... nur so als kleiner Hinweis.) Hinter PROCEDURE kann man nun auch noch angeben, welche Variablen aus dem Hauptprogramm im Unterprogramm doch bekannt sein sollen. Das sieht dann z.B. so aus: Unterprogramm: PROCEDURE EXPOSE Variable Nocheine Unddiedritte Undsoweiter

An dieser Stelle möchte ich nun noch einen Befehl nachtragen, der eigentlich schon ein wenig früher sinnvoll gewesen wäre. Aber auch hier kann er gute Dienste leisten. Wenn nun abhängig von dem, was der Benutzer eingeben will, verschiedene Dinge ausgeführt werden sollen, dann kann man dafür natürlich lauter einzelne IF...THEN-Abfragen machen. Aber was tun, wenn ich 20 solcher Abfragen habe, und als letztes will ich eine Aktion für alles, was noch nicht extra abgefragt wurde?

Also z.B.: Wenn der Benutzer "ich" eingegeben hat, schreibe "Hallo Heiko!". Wenn der Benutzer "Schafkopf" eingegeben hat, schreibe "Wenz", usw. Und wenn er gar nichts von den Sachen eingibt, sondern was ganz anderes, dann schreibe "Wie kreativ! :-)"

Dafür gibt es den Befehl SELECT...END. Das schaut dann folgendermaßen aus:
SELECT
WHEN Eingabe="ich" THEN DO
Erfolg=WRITELN(Fenster,"Hallo Heiko!")
END
WHEN Eingabe="Schafkopf" THEN DO
Erfolg=WRITELN(Fenster,"Wenz!")
END
OTHERWISE DO
Erfolg=WRITELN(Fenster,"Wie kreativ!")
END
END
Die Angabe von OTHERWISE ist notwendig, sonst gibt's eine Fehlermeldung!

4.3. Systemfunktionen

Die Systemfunktionen geben weitgehende Kontrolle über computerinterne Dinge. Sie werden wie alle Funktionen in ARexx entweder aufgerufen mit Ergebnis=Funktion(), oder aber, wie wir in diesem Kursteil gesehen haben, mit CALL Funktion(). Vorsicht! Manche sind schon sehr speziell, Du solltest wissen, was Du damit anstellst.

ADDLIB(Name,Priorität[,Offset,Version])
Hiermit lassen sich externe Bibliotheken (Libraries) in ARexx einbinden, die weitere Befehle zur Verfügung stellen. Solche Bibliotheken befinden sich normalerweise im Verzeichnis LIBS: und haben die Endung .library. Für ARexx sind leider meistens spezielle Abwandlungen dieser Libraries nötig. Im Aminet gibt es aber eine ganze Reihe sehr guter Libraries, z.B. rexxtricks.library, rexxsupport.library, rexxreqtools.library und andere. Wie diese im einzelnen arbeiten, kann ich hier kaum erklären, das würde zu weit führen. Die Befehle, die die Libraries zur Verfügung stellen, sind normalerweise gut dokumentiert. ARexx schaut dann bei Befehlen, die unbekannt sind, zunächst einmal in den angemeldeten Bibliotheken nach, ob dort der entsprechende Befehl zu finden ist. Erst dann wird versucht, über den ARexx-Port ein Programm zu finden, das diesen Befehl versteht. Die Priorität gibt an, in welcher Reihenfolge in den Bibliotheken gesucht werden soll. Hoher Wert meint zuerst suchen. Gültig sind Werte zwischen 100 und -100. Offset ist die Einsprungadresse für die QUERY-Funktion der Bibliothek. Ist normalerweise -30 und muß angegeben werden, damit alles funktioniert. Mit Version kann noch eine Versionsnummer der Bibliothek angegeben werden. Ist die Version der gefundenen Bibliothek kleiner, wird sie nicht akzeptiert. Ein Beispiel, für das Du natürlich die rexxreqtools.library installiert haben mußt:

IF ~SHOW("L",rexxreqtools.library) THEN DO
CALL ADDLIB("rexxreqtools.library", 0, -30, 0)
END
gadtxt= "_Weiter|_Cancel"
Eingabe = rtgetstring(" ","Bitte einen Text eingeben:","Hello World 1.8.",gadtxt)
KnopfGedrückt=rtresult
... oder in unser Hello World eingebaut, das mittlerweile gigantische Ausmaße annimmt:

/* Hello World Version 1.8.*/
IF ~SHOW("L",rexxreqtools.library) THEN DO
CALL ADDLIB("rexxreqtools.library", 0, -30, 0)
END
gadtxt= "_Weiter|_Cancel"
CALL Fensteroeffnen
CALL FrageundAntwort
EXIT

Fensteroeffnen: Erfolg=OPEN(Fenster,'CON:20/20/620/100/Hello World 1.8./CLOSE',R) IF ~Erfolg THEN ECHO "Fehler!" RETURN

FrageundAntwort: DO WHILE (Eingabe~="Ende")&(KnopfGedrueckt~="0") Eingabe = rtgetstring("","Bitte einen Text eingeben:","Hello World 1.8.",gadtxt) KnopfGedrueckt=rtresult Erfolg=WRITELN(Fenster,"Du hast "||Eingabe||" eingegeben.") END RETURN

Ich möchte hier darauf verzichten, rexxreqtools zu erklären. Schau Dir dieses kleine Beispiel und die zu rexxreqtools gehörige Anleitung an und probiere ein wenig herum damit.

Jetzt geht's erst mal weiter mit den Systemfunktionen: ADDRESS()
ergibt den Namen des ARexx-Ports, an den im Moment die externen Befehle geschickt werden. Oft sinnvoll am Anfang eines Programms. Die einzige Möglichkeit, um z.B. bei einem aus Wordworth gestarteten Programm zu erfahren, wie denn nun der ARexx-Port tatsächlich heißt (Wordworth.1, Wordworth.2 usw.).

DATE(Option[,Datum,I|S])
Gibt die aktuelle Zeit als Zeichenkette zurück. Diese kann weitgehend durch Optionen verändert werden (auf I|S komme ich gleich zu sprechen). Diese Möglichkeiten gibt es, wobei T für Tag, M für Monat und J für Jahr steht:

Century      Tage seit Beginn des Jahrhunderts
Days         Tage seit Beginn des Jahres
European     TT/MM/JJ
Internal     Systemtage (seit dem 1.1.1978)
Julian       JJTTT (Tage seit Beginn des Jahres)
Month        englischer Monatsname
Normal       TT MMM JJJJ
Ordered      JJ/MM/TT
Sorted       JJJJMMTT
USA          MM/TT/JJ
Weekday      der Wochentag

Es reicht jeweils der erste Buchstabe als Angabe.

Durch Angabe des I oder S kann ein Datum, das im Internal- oder Sorted- Format vorliegt, in jedes beliebige andere umgewandelt werden:
SAY DATE("E",19960428,"S")
Ein winziges Beispiel: Ein kleines Programm, das ich einmal täglich automatisch aufrufen ließ und das mir den aktuellen Stand meiner Hausarbeit auf die Diskette Hausarbeit_BAK: kopierte, und zwar jedesmal in ein neues Verzeichnis, das als Namen das aktuelle Datum hatte:
/*Sicherheitskopie für Hausarbeit*/
Address Command
Datum=DATE("Sorted")
makedir "Hausarbeit_BAK:"Datum
copy "Text:BT-III/Texte/(Hausarbeit|Literaturverzeichnis).TXT
Hausarbeit_BAK:"Datum
ERRORTEXT()
Gibt eine kurze Beschreibung zu jeder Fehlernummer aus, die in ARexx auftreten kann.

EXPORT(Addresse[,String,Länge,Füllzeichen])
Hiermit kann der Inhalt eines String an eine 4-Byte-Adresse geschrieben werden. Der Speicher muß vorher reserviert werden! (Siehe GETSPACE)

FREESPACE([Addresse,Länge])
Gibt die mit GETSPACE reservierten Speicherbereiche wieder frei. Bei Verwendung der Argumente arbeitet die Funktion nicht ganz fehlerfrei. Sie wird am Ende des Programms sowieso ausgeführt, also vielleicht einfach weglassen, wenn Du nicht gerade 180 MB Speicher reserviert hast. Und wenn, dann besser ohne die Argumente, denn FREESPACE weiß, welcher Speicher ihm gehört.

GETCLIP(Name)
Liest eine Zeichenkette aus dem Clipboard.

GETSPACE(Länge)
Gibt einen Zeiger auf einen freien Speicherbereich zurück.

HASH(String)
Gibt den Hashwert des übergebenen Strings zurück. Das ist so eine Art Prüfsumme: Alle ASCII-Werte werden addiert, und das unterste Byte der Summe zurückgegeben.

IMPORT(Adresse[,Länge])
Liest Daten aus einem Speicherbereich. Ohne Angabe einer Länge wird bis zum nächsten "00"x gelesen.

PRAGMA(Option[,Wert])
Damit kann man einige Einstellungen des Programms verändern bzw. abfragen. Folgende Optionen sind möglich (es reicht wieder die Angabe des ersten Buchstabens):

Directory  gibt das aktuelle Verzeichnis des Programms zurück.
ID         Zeiger auf die TaskControlBlock-Struktur
Priority   Damit kann dem Prozeß eine andere TaskPriority gegeben werden.
Vorsicht: REXXMAST hat 4! Nicht höher gehen!
Werte zwischen -128 und 127 sind theoretisch möglich, normal
ist der Bereich von etwa -5 bis +3.
Window     Damit kann der WindowPointer des Tasks verändert werden. Für
"Wert" können die Schlüsselworte "Null" oder "Workbench" stehen. Der in Wert angegebene logische Name wird als aktueller Console-Handler eingestellt.

REMLIB()
Entfernt eine Library wieder.

SETCLIP(Name[,Wert])
Setzt einen Eintrag in der Clipliste. Ohne Angabe eines Wertes wird der Eintrag gelöscht. Der Rückgabewert ist boolsch (0 oder 1).

SHOW(Option[,Name,Trennzeichen])
Option muß angegeben werden. Es gibt die folgenden Möglichkeiten:

Clip      : alle Einträge in der Clip-Liste
Files     : eine Liste der offenen logischen Dateinamen
Internal  : die interne Port-Liste
Libraries : die geöffneten Bibliotheken
Ports     : die allgemeinen PublicMessagePorts, zu denen auch die
            ARexx-Ports gehören.
Es reicht jeweils die Angabe des ersten Buchstaben.

Wird ein Name angegeben, dann ändert SHOW() seine Funktion. Es gibt 1 zurück, wenn der unter Name angegebene Port gefunden wurde, und 0, wenn er nicht gefunden wurde. Beispiele im zweiten Kursteil unter 2.3.2

SOURCELINE([Zeile])
Liefert ohne Wertangabe die Zahl aller Zeilen im aktuellen Skript. Mit Angabe einer Nummer liefert es einen String, in dem die Zeile mit der entsprechenden Nummer steht.

STORAGE(Addresse[,String,Länge,Füllzeichen])
Schreibt den angegebenen String direkt in den Speicher. Ganz ohne Parameter übergibt die Funktion den freien Systemspeicher.

SYMBOL(Name)
Damit kann getestet werden, ob es sich bei Name um ein gültiges ARexx- Symbol (z.B. eine Variable) handelt. Folgende Rückgabewerte sind möglich: BAD war nichts: kein ARexx-Symbol. LIT es handelt sich um ein uninitialisiertes Symbol (eine Variable, der noch kein Wert zugewiesen wurde). VAR Eine Variable, der ein Wert zugewiesen wurde.

TIME([Option])
Ähnlich wie DATE(), nur für die Uhrzeit. Folgende Optionen gibt es:

Civil     [h]h:mmxx (xx meint am oder pm)
Elapsed   Sekunden und Hundertstelsekunden seit der letzten Abfrage
Hours     Stunden seit Mitternacht
Minutes   Minuten seit Mitternacht
Normal    hh:mm:ss
Reset     wie Elapsed, löscht aber danach den Timer.
Seconds   Sekunden seit Mitternacht

TRACE(Option)
Gibt die aktuelle Trace-Einstellung zurück oder ändert je nach Option diese Einstellung.

VALUE(Name)
Gibt den Inhalt einer Variablen zurück. Das ist dann nötig, wenn der Variablenname selbst eine Variable ist:
a="Hoppla, ist das kompliziert"
b="a"
SAY VALUE(a)
SAY VALUE("a")
SAY VALUE(b)

4.4. Ein paar Tips am Rande

Hier möchte ich noch schnell ein paar Tips loswerden, die dem einen oder der anderen von Euch vielleicht helfen können.

4.4.1. Start mit Piktogramm
Ein Piktogramm für ein ARexx-Skript ist mit den entsprechenden Programmen schnell erstellt. Es sollte vom Typ "Projekt" sein und als Standardprogramm einfach RX eingetragen haben. Dann steht einem Start per Doppelklick nicht mehr viel im Weg (außer vielleicht Programmfehlern...)

4.4.2. Start aus AmigaGuide
@{"hier" rx hier.rexx} gibt einen Link mit dem Wort "hier". Ein Klick darauf startet das Skript "hier.rexx". Allerdings mußt Du für Ausgabe von Daten selber sorgen. ECHO funktioniert nicht so einfach. Aber Du hast ja inzwischen gelernt, wie man Fenster öffnet usw.

4.4.3. Anführungszeichen
Anführungszeichen sind eine heikle Geschichte in ARexx. Es gibt die zwei Arten ' (Alt-ä) und ". Beide sind völlig gleichbedeutend. Bei der Interpretation wird immer das äußerste Paar weggenommen. Aus "'" wird ' und umgekehrt. Und aus "Name" wird Name, was für ARexx ein gültiges Symbol (eine Variable!) ist! Im Endeffekt hilft hier nur 'rumprobieren und vor allem Tracen. Wenn was nicht funktioniert, mach mal noch ein paar Anführungszeichen außenherum. Beachte außerdem Groß- und Kleinschreibung! Außerhalb von Anführungszeichen macht ARexx so ziemlich alles GROSS.

4.4.4. MUIRexx
MUIRexx ist ein Programm, das eine Schnittstelle zwischen ARexx und MUI (Magic User Interface) bildet. Es ist sehr leistungsfähig. Ich bin selber im Moment noch dabei, es zu verstehen, und hoffe, daß ich nächsten Monat ein kleines Programm damit präsentieren kann. Probiert's mal aus! Ebenfalls im Aminet erhältlich, genauso wie MUI.

4.4.5. Wordworth finden
Das ist gar nicht so einfach, denn jedes Fenster öffnet einen eigenen Port! Es gibt zwar auch noch den Port mit dem Namen WordworthLives, was wahrscheinlich bedeuten soll: Wenn dieser Port existiert, dann ist auch Wordworth aktiv. Aber sicher bin ich mir da nicht. Meine Lösung ist nicht sehr elegant, das muß ich zugeben. Aber sie funktioniert:

DO Num = 1 to 20
WwPort = "WORDWORTH." || Num
IF SHOW(PORTS, WwPort) THEN DO
Address Value WwPort
leave Num
end
end
if num=21 then do
echo "Wordworth nicht gefunden! Programm endet."
exit
end
So, das waren nun fast alle ARexx-Befehle, die es gibt. Im nächsten und letzten Kursteil werde ich einige wenige Befehle noch nachtragen und vor allem ein paar kleine Beispiele dafür geben, was mit ARexx alles möglich ist. Wer dafür Ideen oder fertige Skripte hat: Ich bin für Vorschläge und Unterstützung offen!

Ein kurzes persönliches Wort an diejenigen, die im Lauf des letzten Monats an mich geschrieben haben: Leider war ich im April sehr wenig zu Hause und hatte dann sehr viel zu tun, so daß ich noch nicht dazu gekommen bin, auf alles zu antworten. Ich werde aber alles noch beantworten! Vielen Dank für Eure Geduld.

4.5. Zusammenfassung der neuen Befehle

ADDLIB(Name,Priorität[,Offset,Version])
ADDRESS()
CALL
DATE(Option[,Datum,I|S])
ERRORTEXT()
EXIT
EXPORT(Addresse[,String,Länge,Füllzeichen])
FREESPACE([Addresse,Länge])
GETCLIP(Name)
GETSPACE(Länge)
HASH(String)
IMPORT(Adresse[,Länge])
PRAGMA(Option[,Wert])
PROCEDURE (EXPOSE)
REMLIB()
RETURN
SETCLIP(Name[,Wert])
SHOW(Option[,Name,Trennzeichen])
SOURCELINE([Zeile])
STORAGE(Addresse[,String,Länge,Füllzeichen])
SYMBOL(Name)
TIME([Option])
TRACE(Option)
VALUE(Name)
«