|
| |||||||||||||||||||||||||||||||||
|
|
| ||||||||||||||||||||||||||||||||
»ARexx-Kurs: Übersicht
1. Einführung in ARexx
»
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!
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.
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 |
Ergebnis=OPEN(Dateiname usw.) ECHO Ergebnis |
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 |
Ü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 |
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 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
|
/* 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
|
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") |
/*Sicherheitskopie für Hausarbeit*/
Address Command
Datum=DATE("Sorted")
makedir "Hausarbeit_BAK:"Datum
copy "Text:BT-III/Texte/(Hausarbeit|Literaturverzeichnis).TXT
Hausarbeit_BAK:"Datum
|
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)
|
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 |
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.
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)«