![]() |
||
Powered by GoldED |
ARexx-Kurs - Teil 2 (von Heiko Kuschel)»ARexx-Kurs: Übersicht1. Einführung in ARexx.
» 2. Programmstrukturen und Ansteuerung von externen Programmen2.0. VorbemerkungenHier 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! Ich hoffe, daß diese Regelung den Kurs etwas leserlicher macht. Wenn Ihr spezielle Fragen habt, etwas nicht verstanden oder Anregungen und Ideen für weitere Kursteile habt, könnt Ihr Euch gern 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 E-Mail: hk0006@wuerzburg.baynet.de Und jetzt... viel Spaß mit ARexx! ****************************************************
-------------------------------- /* Hello World Version 1.3.*/ DO UNTIL Eingabe="Ende" ECHO "Gib was ein!" PARSE PULL Eingabe ECHO "Du hast "||Eingabe||" eingegeben." END -------------------------------- -------------------------------- /* Hello World Version 1.4.*/ DO WHILE Eingabe~="Ende" ECHO "Gib was ein!" PARSE PULL Eingabe ECHO "Du hast "||Eingabe||" eingegeben." END --------------------------------Die Tilde ~ ist das Negationszeichen in ARexx. ~= heißt soviel wie "ist nicht gleich". Die zwei senkrechten Striche verknüpfen Zeichenfolgen miteinander. Die Einrückungen sind zwar nicht nötig, erhöhen aber die Übersichtlichkeit.
Wozu nun diese zwei verschiedenen Möglichkeiten, das offenbar gleiche
auszudrücken (DO WHILE, DO UNTIL)?
DO WHILE überprüft die Bedingung am Anfang der Schleife, Kapiert? Wenn nicht, probiere einmal, in beiden Versionen als erste Zeile nach dem Kommentar einzufügen: -------------------------------- Eingabe="Ende" --------------------------------In Hello World 1.4. wird gar nichts passieren! Die Schleife wird übersprungen, denn die Bedingung ist schon erfüllt. Hello World 1.3. dagegen geht brav in die Schleife rein... und bis zum END hat sich der Wert von Eingabe schon wieder verändert.
Jetzt fehlt uns allerdings noch die dritte Möglichkeit, Schleifen zu
programmieren: DO FOREVER.
--------------------------------
/**/
DO FOREVER
ECHO "Gib Ende für Quit ein"
PARSE PULL Eingabe
IF Eingabe="Ende" THEN
ECHO "Die eingabe war richtig "||Eingabe
LEAVE
IF Eingabe ~="Ende" THEN
ECHO "Die eingabe war falsch "||Eingabe
END
--------------------------------
Das ist schon eine ganze Menge, aber es fehlt
DO... END, um funktionieren zu können. Also:
--------------------------------
/**/
DO FOREVER
ECHO "Gib Ende für Quit ein"
PARSE PULL Eingabe
IF Eingabe="Ende" THEN DO
ECHO "Die Eingabe war richtig "||Eingabe
LEAVE
END
IF Eingabe ~="Ende" THEN DO
ECHO "Die Eingabe war falsch "||Eingabe
END
END
--------------------------------
Übrigens: IF...THEN kann auch noch mit ELSE
(ansonsten) weitergeführt werden. Eine kleine
Änderung des obigen Skripts:
--------------------------------
/**/
DO FOREVER
ECHO "Gib Ende für Quit ein"
PARSE PULL Eingabe
IF Eingabe="Ende" THEN DO
ECHO "Die Eingabe war richtig "||Eingabe
LEAVE
END
ELSE DO
ECHO "Die Eingabe war falsch "||Eingabe
END
END
--------------------------------
****************************************************
-------------------------------- /*Interpreter V1.0.*/ DO FOREVER PARSE PULL Eingabe IF Eingabe="Ende" THEN LEAVE INTERPRET Eingabe END --------------------------------Tip: Speichere dieses Programm irgendwo auf Festplatte, und nimm "rx (Name des Programms)" in Deine HotKey-Liste auf, falls Du ein Programm hast, das andere Programme auf Tastendruck startet! ****************************************************
Wir haben zwar noch lange nicht alle Möglichkeiten von ARexx selbst ausgeschöpft. Trotzdem möchte ich schon jetzt darauf eingehen, wie Programme angesteuert werden können, die einen ARexx-Port zur Verfügung stellen. Denn einfache Skripte kannst Du jetzt schon selbst schreiben, und am meisten lernt man meiner Erfahrung nach, wenn man selber was ausprobiert. Und wenn's Probleme gibt... Meine Adresse steht am Anfang des Kurses. Um ARexx mitzuteilen, welches Programm angesteuert werden soll, benötigen wir den Befehl ADDRESS. Die ARexx-Adresse (ARexx-Port), die dann folgen muß, entnimmst Du der Dokumentation des jeweiligen Programms. Z.B.: ADDRESS YAM ADDRESS Wordworth.1 ADDRESS TCALC ADDRESS GOLDED.1Eine Liste der vorhandenen Ports erhältst Du mit ECHO SHOW("PORTS") Gib das mal in der ARexx-Shell ein! Der Befehl wird weiter unten genauer erklärt. Nach dem Befehl ADDRESS YAM werden alle Anweisungen, die ARexx nicht versteht, an die YAM-Schnittstelle weitergeleitet. Wenn nun YAM zufällig einen Befehl haben sollte, der auch als ARexx-Befehl existiert, mußt Du ihn in Anführungszeichen setzen, damit er nicht von ARexx selbst interpretiert wird. ADDRESS COMMAND hat eine besondere Bedeutung: Damit können Shell-Befehle aufgerufen werden. -------------------------------- ADDRESS COMMAND DIR --------------------------------listet das aktuelle Verzeichnis auf. -------------------------------- ADDRESS COMMAND DIR --------------------------------hat prinzipiell die gleiche Bedeutung. Im ersten Fall wird aber nur eben schnell der Befehl DIR an COMMAND übergeben, im zweiten Fall wird die Schnittstelle als COMMAND definiert und alle weiteren Befehle an COMMAND geschickt. Also: Ich habe ein Programm, mit dem ich z.B. YAM steuere. Zwischendurch benötige ich einen einzigen COMMAND-Befehl. Dann schreibe ich ihn direkt hinter ADDRESS COMMAND, und alle folgenden Befehle gehen wieder an YAM.
------------------------ ------------------------
ADDRESS YAM ADDRESS YAM
(Befehle gehen an YAM) (Befehle gehen an YAM)
ADDRESS COMMAND DIR ADDRESS COMMAND
DIR
(Befehle gehen an YAM) (Befehle gehen an COMMAND)
------------------------ ------------------------
(Wenn Du einen proportionalen Zeichensatz installiert hast, wirst Du diesen
Vergleich nicht ganz so gut betrachten können. Sorry!)ADDRESS kann auch noch ein paar Parameter mit auf den Weg bekommen: ADDRESS VALUE Variable interpretiert Variable als solche und nimmt den Inhalt der Variablen als neuen ARexx-Port. Z.B.: -------------------------------- Var="YAM" ADDRESS VALUE Var --------------------------------Alle Befehle gehen an YAM.P> ADDRESS ohne weitere Angaben schaltet auf den vorhergehenden ARexx-Port zurück.
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 Buchstabens.
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.
--------------------------------
YAM-Existiert=SHOW("P",YAM)
--------------------------------
Die dritte Möglichkeit ist die, ein beliebiges Trennzeichen für die Liste
anzugeben. Am sinnvollsten ist ein "Wagenrücklauf", was der Return-Taste
entspricht. Er hat den ASCII-Code 10 und wird angegeben als D2C(10) (Warum,
erkläre ich im nächsten Kursteil.)
--------------------------------
ECHO SHOW("P",,D2C(10))
--------------------------------
****************************************************
ADDRESS COMMAND sys:rexxc/WaitforPort YAM
Jetzt brauchen wir noch die Möglichkeit, Werte aus Programmen in ARexx zu übernehmen. Das geschieht auf folgende Weise:
a)
b)
c)
Der Befehl ist so definiert, daß er sein Ergebnis (einen Zahlenwert) in
RC ablegt. Das ist meines Erachtens zwar nicht ganz korrekt, aber
durchaus nicht unüblich.
Achtung: Diese Variablen funktionieren nur, wenn vorher die entsprechende
Option eingeschaltet wurde! Das geschieht mit: Die anderen Optionen liefere ich am Ende des Kursteils nach. Sie sind jetzt gerade weniger interessant.
(Ich habe die Nummern der einzelnen Schritte in Kommentarzeilen mit ### eingefügt.)
--------------------------------
/* Post abholen mit Miami und YAM */
/* Version 1.0. 9.7.97 Heiko Kuschel */
OPTIONS RESULTS
YAMON=1
MIAMION=1
MIAMIONLINE=0
/*Bis hierher werden nur die Variablen so gesetzt, daß*/
/*YAMON=1: angenommen wird, daß YAM gestartet ist */
/*MIAMION=1: das gleiche für Miami */
/*MIAMIONLINE=0: Miami ist offline */
/* ############ Teil 1 ############ */
if ~show(PORTS, YAM) then do
address command
"run Comm:YAM/YAM"
/*Diese Zeile mußt Du ändern!*/
"sys:rexxc/waitforport YAM"
YAMON=0
end
/* Wenn YAM nicht bereits gestartet ist, dann*/
/* starte es */
/* warte auf den ARexx-Port von YAM */
/* merke dir, daß YAM nicht gestartet war */
/* Natürlich mußt Du den Pfad entsprechend */
/* anpassen. */
/* ############ Teil 2 ############ */
if ~show(PORTS, MIAMI.1) then do
Address command
"run Comm:miami11a/miami"
"sys:rexxc/waitforport MIAMI.1"
MIAMION=0
end
/* Genau wie bei YAM. */
/* ############ Teil 3 ############ */
address Miami.1
isonline
if RC=1 then do
MIAMIONLINE=1
end
else do
ONLINE
end
/*Hier sind zwei Befehle drin, die zum Befehlsschatz */
/*von Miami gehören: */
/*ISONLINE gibt RC=0 oder 1 zurück */
/*ONLINE geht online. */
/*Die Zeile MIAMIONLINE=1 merkt sich, daß Miami schon*/
/*online war. Sonst wird am Ende des Programms u.U. */
/*eine Verbindung unterbrochen, wo doch Dein Browser */
/*gerade 98% einer 3-Megabyte-Datei geladen hatte... */
/* ############ Teil 4 ############ */
address YAM
Mailsendall
/* ############ Teil 5 ############ */
Mailcheck
if RESULT>0 then YAMON=1
/* ############ Teil 6 ############ */
Mailcheck
if RESULT>0 then YAMON=1
/* ############ Teil 7 ############ */
if YAMON=0 then quit
/*Das ist der Teil, in dem eigentlich was passiert. */
/*Mailsendall ist ein YAM-Befehl, der alle anstehenden*/
/*Mails sendet. */
/*Mailcheck holt Post ab und gibt in RESULT die Anzahl*/
/*der Mails zurück. */
/*Wenn mehr als 0 Mails abgeholt wurden, dann wird die*/
/*Variable YAMON auf 1 gesetzt. YAM wird dann am Ende */
/*nicht geschlossen, damit Du die neuen Mails auch */
/*lesen kannst. */
/* ############ Teil 8 ############ */
Address MIAMI.1
if MIAMIONLINE=0 then do
offline
end
/*Wenn Miami vorher nicht online war, */
/*geht es jetzt auch wieder offline. */
/* ############ Teil 9 ############ */
if MIAMION=0 then do
quit
end
/*Und wenn Miami gar nicht gestartet war, */
/*wird es jetzt wieder beendet. */
--------------------------------
Das Ganze funktioniert leider noch nicht mit YAM 2.0., da dort ARexx noch
nicht vollständig implementiert ist.
Wenn Du das Skript nutzen willst, mußt Du es mit YAM 1.3.x tun.
Achtung: Lasse das Skript nicht unbeaufsichtigt laufen!
Name.1="Meyer" Kapiert? An den Namen der Variablen wird ein Punkt angehängt, danach kommt eine Zahl. Jeder Name in Verbindung mit jeder Zahl ist eine eigene Variable mit einem eigenen Wert! Das Schöne in ARexx, im Gegensatz zu den meisten anderen Sprachen, die ich kenne:
Du mußt ARexx nicht von vornherein sagen, welches die höchste Zahl ist. Und
man kann auch dem "Stamm" (so heißt der Teil der Variable, den ich als
"Name" bezeichnet habe) einen Wert zuweisen, der dann für alle
Untervariablen gilt. -------------------------------- PLZ.=97280 /*Beachte den Punkt!*/ Zahl=12 echo PLZ.1 echo PLZ.10 echo PLZ.Zahl echo PLZ.PLZ --------------------------------Im letzten Fall wird der Wert der Variablen PLZ.97280 ausgegeben... und der ist auch 97280! Auch mehrdimensionale Variablen sind möglich: Variable.Zahl.Zahl2 Und nun zu dem Programm. Es ist übrigens mit Dokumentation auch im Aminet zu haben, unter util/rexx/WW-Print.lha Außerdem sind noch zwei String-Funktionen drin, die eigentlich erst nächstes Mal behandelt werden sollen. Es sind: LASTPOS(Buchstabe,Zeichenkette) gibt die Position des Buchstabens an, an der er zum letzten Mal in einer Zeichenkette auftritt.
--------------------------------
Position=LASTPOS("e","Heiko Kuschel")
ECHO Position
--------------------------------
ergibt 11
LEFT(Zeichenkette,Zahl)
ergibt den linken Teil einer Zeichenkette, bis zum xten Zeichen.
--------------------------------
ECHO LEFT("Heiko Kuschel",6)
--------------------------------
ergibt "Heiko"
--------------------------------
/* Wordworth 5 ARexx-Skript zum
Drucken beliebig vieler Dateien */
/* Heiko Kuschel 27. Juni 1996 */
/* basierend auf WW5-Skript von
MJ (Digita) */
/* FREEWARE, falls Digita kein Copyright
beansprucht. */
OPTIONS RESULTS
Nummer=0
Pfad =""
DO forever
Nummer=Nummer+1
RequestFile TITLE "Zu druckendes Dokument wählen..." PATH Pfad
File.Nummer = Result
/*RequestFile ist ein Wordworth-Befehl. Mit der Option PATH kann
wahlweise angegeben werden, welcher Pfad im Requester voreingestellt
sein soll.*/
/*Das Resultat der Abfrage steht in RESULT. RC ist größer 0,
wenn Abbruch */
/*gewählt wurde.*/
/*Dieses Skript geht davon aus, daß es
direkt aus Wordworth gestartet */
/*wurde. Dann ist ADDRESS überflüssig, die Adresse
ist bereits richtig */
/*gesetzt. Da Wordworth für jedes Textfenster einen eigenen
ARexx-Port*/
/*aufmacht, ist es auch ziemlich schwierig herauszufinden,
welchen man */
/*adressieren kann. Wenn ich in WW das erste Fenster schließe,
geht der */
/*ARexx-Port mit dem Namen Wordworth.1 mit flöten.
Dann kann ich natürlich*/
/*nicht einfach ADDRESS Wordworth.1 schreiben.
Ziemlich kompliziert, wie */
/*gesagt. :-( */
Strich=Lastpos("/",File.Nummer)
Pfad=""
if (Strich>0) then Pfad=Left(File.Nummer,(Strich-1))
/*Hier "extrahiere" ich den Pfad des zuletzt
gewählten Dokuments, damit */
/*der Benutzer sich nicht jedesmal durch alle Verzeichnisse und */
/*Unterverzeichnisse durchwühlen muß. Er findet sich
im nächsten*/
/*Requester (wenn weitere Dokumente ausgewählt werden)
wieder im */
/*gleichen Verzeichnis, in dem er bereits war. */
if (RC > 0) THEN Exit
/*Wenn im File-Requester "Abbruch" geklickt wurde, wird
das Programm mit */
/*EXIT vollständig abgebrochen.*/
RequestResponse PROMPT "Möchten Sie ein weiteres Dokument drucken?"
if (RC > 0) THEN leave
/*Frage danach, ob ein weiteres Dokument gedruckt werden
soll. Wenn nein, */
/*wird die DO FOREVER-Schleife mit LEAVE verlassen, wenn
doch, geht's */
/*oben wieder weiter... mit dem Pfad des zuletzt
gewählten Dokuments */
/*als Vorgabe. */
END
New
Address Value Result
/*NEW öffnet ein neues Fenster in Wordworth und
gibt in Result den */
/*ARexx-Port zurück. Jedes Wordworth-Fenster hat
einen eigenen Port: */
/*Wordworth.1, Wordworth.2 usw. */
Do Zaehler=1 to Nummer
Open FILENAME File.Zaehler
Print
end
/*In File.1 steht der Name des ersten zu druckenden
Dokuments, */
/*in File.2 der des zweiten usw. */
Close FORCE
--------------------------------
****************************************************
Wichtig zu wissen ist die Behandlung von Anführungszeichen in ARexx-
Skripten.
--------------------------------
ADDRESS TCALC /*Das ist TurboCalcs Adresse*/
variable="Hallo"
Put Variable /* Fügt den Wert von Variable in die aktuelle Zeile ein*/
"NACHUNTEN()" /* Setzt den Cursor eine Zeile tiefer */
'Put Variable' /* Da Variable mit in Anführungszeichen steht, wird */
/* es als Text interpretiert, nicht als der Name einer*/
/* Variablen. In TurboCalc steht in dieser Zeile VARIABLE */
"NACHUNTEN()"
Put '"Hallo Du da"'
"NACHUNTEN()"
Put '"Ich sage mal '||Variable||' zu dir"'
'NACHUNTEN()'
'Put "Ich sage mal '||Variable||' zu dir"'
--------------------------------
Schau Dir mal mit Trace (vgl. u.) an, was ARexx aus den einzelnen Zeilen
macht!
TCO Trace Console Open
Öffnet ein eigenes Trace-Fenster
TCC Trace Console Close
schließt das Fenster wieder
TS Trace Start
Ab sofort werden alle Befehle in der Form,
wie sie ARexx interpretiert, ausgegeben. Ergebnisse werden
angezeigt. Der nächste Befehl wird erst nach
Drücken von Return ausgeführt.
TE Trace End
Tracing wird wieder beendet. Für den momentan
ausgeführten Befehl muß im Trace-Fenster
noch einmal Return gedrückt werden.
In der Trace-Console können auch Befehle eingegeben werden, die als Teil
des Programms betrachtet werden.= wiederholt die Ausführung der letzten Zeile -x überspringt die nächsten x Befehle In der Trace-Console werden vor der Auflistung der abgearbeiteten Befehle folgende Codes vorangestellt: +++ Befehls- oder Syntaxfehler >C> erweiterter zusammengesetzter Name >F> Ergebnis eines Funktionsaufrufs >L> Sprungmarkenklausel >O> Ergebnis einer zweistelligen Operation >P> Ergebnis einer Präfix-Operation >U> nicht initialisierte Variablen >V> Wert einer Variablen >>> Ergebnis eines Ausdrucks >.> Wert eines "Platzhalter"-TokensEs gibt allerdings auch einen Befehl, der innerhalb eines ARexx-Programms angewendet werden kann. Er heißt sinnvollerweise TRACE und hat eine Menge Optionen:
ALL Zeigt alles an.
BACKGROUND Es findet keine Ablaufverfolgung statt.
Was immer das auch heißt.
COMMANDS Zeigt alles an, was an ein externes
Programm geschickt wird.
ERRORS Zeigt alle Fehler an. (Befehle,
die RC~=0 liefern.)
INTERMEDIATES Zeigt alle Zwischenwerte an.
LABELS Zeigt alle Sprunganweisungen an (
die hatten wir noch nicht).
NORMAL Zeigt alle Befehle an, die den
voreingestellten Schweregrad
(OPTIONS FAILAT x) überschreiten
(RC>=x).
RESULTS Zeigt alle Ergebnisse an.
SCAN Prüft das Skript auf Fehler, ohne
es auszuführen
OFF Aus.
! Schaltet das Versenden von Befehlen
an externe Programme
ab, beim zweiten Aufruf wieder an.
? Entspricht TS in DOS. Nach jedem Befehl
wird gewartet. Nochmal schaltet den
Modus wieder aus.
Es reicht jeweils die Angabe des ersten Buchstabens: TRACE R
? kann auch in Verbindung mit den anderen Optionen verwendet werden: TRACE
R?Außerdem gibt es die Funktion TRACE()
ECHO TRACE()
IF...THEN...ELSE
INTERPRET Ausdruck
ADDRESS (VALUE|COMMAND)
Ergebnis=SHOW("C|F|I|L|P",Name,Trennzeichen)
TRACE Optionen
Ergebnis=TRACE()
Ergebnis=LASTPOS(Zeichen,Zeichenkette)
Ergebnis=LEFT(Zeichenkette,Zahl)
OPTIONS [NO] RESULTS die unten genannten Systemvariablen werden
(de-)aktiviert
FAILAT x RC>=x wird als Fehler interpretiert
PROMPT Ausdr.Bei PULL und PARSE PULL wird Ausdr. vorangestellt
[NO] CACHE: Der interne Befehlscache, der die Ausführung von
Schleifen beschleunigt, wird ab- bzw. angestellt.
Normalerweise an.
ohne Parameter werden die Einstellungen wieder zurückgesetzt.
DOS-Befehle:
TCO
TCC
TS
TE
WaitForPort
Systemvariablen:
RESULT
RC
So, das war's für diesmal. Ich hoffe, es ist mir gelungen, Dich ein wenig
in die Materie einzuführen. Probiere einfach mal aus, Deine eigenen Skripte
zu schreiben! Und im Aminet gibt es ein eigenes Verzeichnis util/rexx, in
dem auch viele Skripte darauf warten, von Dir erforscht zu werden. Bitte
schreibe mir, wenn Du etwas nicht verstanden hast oder bestimmte Probleme
hast. Auch, welche Programme Du programmieren willst, und zu welchem Zweck.
Wenn möglich, werde ich darauf eingehen.«
|
Ausgabe 03/98 |