REXX (Abk. f. Restructured Extended Executor)
ist eine von Michael Cowlishaw bei IBM entwickelte Skriptsprache.
Herkunft
REXX stammt aus dem Großrechnerbereich (TSO, VM/CMS (bzw. später VM/ESA)), wurde aber auch in anderen Produktlinien wie OS/2 verwendet. Eine angepasste Version erfreute sich auch auf dem Amiga großer Beliebheit, da beinahe jedes wichtige Proramm damit "fernsteuerbar" wurde. Mittlerweile sind auch Interpreter für fast alle Umgebungen bis hin zum PalmOS erhältlich. 1996 wurde REXX zum ANSI-Standard (ANSI X3.274-1996 "Information Technology - Programming Language REXX").
REXX kann besonders leicht erweitert werden, indem DLLs zum eigentlichen Interpreter hinzugeladen werden. Insbesondere unter OS/2 ist eine Vielfalt solcher Bibliotheken mit mathematischen, Datenbank-, Socket- und System-Funktionen verfügbar, die wie normale REXX Funktionen angesprochen werden können. REXX ist in der Regel eine interpretierte Sprache, aber auf IBM Großrechnern sind auch REXX-Compiler verfügbar.
Array ähnlich
REXX ist sehr flexibel. REXX kennt keine expliziten Variablendeklarationen, und auch keine Arrays. Dennoch lässt sich eine Array ähnliche Struktur leicht dadurch erzeugen, indem Variablen indiziert werden:
do i = 1 to 10 zahl.i = 10 - i end
Danach existieren folgende Variablen mit folgender Zuordnung: zahl.1 = 9, zahl.2 = 8, zahl.3 = 7, ...
Mit einem drop zahl. können dann alle zehn Variablen der Form zahl.i mit einem Schlag entfernt werden.
flexible Variablen
So kann auch eine Variable, die vorher ohne Zuweisung als Wort verwendet wurde, nach der Zuweisung mit diesem Wert benutzt werden:
do say hallo => HALLO hallo = 25 say hallo => 25 hallo = "say 5 + 3" say hallo => say 5 + 3 interpret hallo => 8 drop hallo say hallo => HALLO end
In der ersten Zeile versucht REXX, den Inhalt der bisher noch nicht definierte Variable 'HALLO' auszugeben, da diese jedoch noch unbesetzt ist, gibt REXX den an "say" übergebenen Text als Großbuchstaben aus. In der zweiten Zeile wird durch die Anführungszeichen ein String definiert und dementsprechend ausgegeben.
Das negative Beispiel
Auch REXX hat eine zum GOTO äquivalente Anweisung: SIGNAL. Richtig angewendet ein sehr nützlicher Befehl, zum Beispiel dann wenn man Fehler oder andere Ausnahmesituationen abfangen will. Aber man kann damit auch unleserliche, schlecht bis gar nicht nachzuvollziehende Source-Codes erzeugen:
/* Ein Rexx-Programm */ signal definieren; ausgabe: say a signal ende; definieren: a = "hello world" signal ausgabe; ende: exit
Übersicht der REXX-Anweisungen (unvollständig)
REXX-Anweisungen | ||
adress umgebung ausdruck | zum Ausführen von Anweisungen außerhalb der REXX-Umgebung | adress DOS 'DIR *.*' |
call prozedur | Aufruf einer prozedur | call binkoeff n k |
call load 'bibliothek' | Eine externe Bibliothek laden | call load 'mathe.r' |
cls | löscht den Bildschirm | |
do | Alle möglichen Arten von Schleifen | |
drop variable | variable löschen | drop a |
exit | veranlasst das Programm sich zu beenden | |
if | ||
interpret ausdruck | ausdruck wird wie eine REXX-Anweisung behandelt | interpret "a=5*(4+b)" |
leave | Verlassen einer Schleife | |
pull variable | liest eine Zeichenkette von der Tastatur ein | pull eingabe |
say ausdruck | ausdruck wird auf dem Bildschirm ausgegeben | say "Hallo Welt!" |
signal label | Äquivalent zu goto label |
Übersicht der REXX-Funktionen (unvollständig)
REXX-Funktionen | ||
arg(1) | Enthält die Eingabe aus der Kommandozeile | console = arg(1) |
charin() | holt ein Zeichen aus dem Eingabestrom | zeichen = charin("semmel.txt") |
charout() | schreibt ein Zeichen in den Ausgabestrom | |
chars() | gibt die Anzahl der noch verfügbaren Zeichen im Eingabestrom aus | |
linein("dateiname") | Liest eine ganze Zeile aus einer Datei ein | zeile = linein("semmel.txt") |
lineout("dateiname",ausdruck) | ausdruck wird in Datei geschrieben | linout("semmel.txt",eumel) |
lines() | gibt die Anzahl der noch vollständigen Zeilen im Eingabestrom aus | |
Stringfunktionen | ||
length(string) | liefert die Länge eines Strings zurück | |
substr(string,position,zeichenzahl) | Ein Teilstring aus string | |
word(string,wert) | gibt das n.te Wort des String aus | a = word("polyglotte Katze",2) |
words(string) | gibt die Anzahl der Wörter des Strings aus | a = words("Hallo Leute") |
mathematische Funktionen | ||
abs(zahl) | liefert den vorzeichenlosen Teil einer Zahl zurück | |
bitand() | Bitweises UND | |
bitor() | Bitweises ODER | |
bitxor() | Bitweises XOR | |
random(u,o,s) | liefert eine zufällige Zahl in den Grenzen von u und o zurück. u,o und s sind optional | |
C2D() | Wandelt Zeichen in ASCII-Code (dezimal) um | |
C2X() | Wandelt Zeichen in ASCII-Code (hexadezimal) um | |
D2C() | Wandelt Dezimalzahlen in Zeichen um | |
D2X() | Wandelt Dezimalzahlen in Hexadezimalzahlen um |
Übersicht der REXX-Operatoren (unvollständig)
REXX-Operatoren | ||
% | ganzzahlige Division | 11%3 = 3 |
// | Rest-Operator (Modulo) | 11//3 = 2 |
|| | Stringverkettung (Konkatenation) | "bär"||"tiger" = "bärtiger" |
Fehler- und Ausnahmebehandlung in REXX
Es gibt in REXX die Möglichkeit mit SIGNAL Fehler abzufangen und mit Ausnahmezuständen umzugehen. Es gibt dazu die fünf System-Labels: ERROR, FAILURE, HALT, NOVALUE und SYNTAX. Sie können im Quellcode während des Ablaufs an und ausgeschaltet werden.
SIGNAL
Beispiel:
signal on halt; a = 1 do a = (a + 1) // 10000 say a end halt: say "Das Programm wurde vom Benutzer abgebrochen" exit
error | |
failure | |
halt | Programmabbruch |
novalue | |
syntax |
Wenn ein Abbruch durch Fehler oder Benutzer mittels signal on Bedingung umgeleitet wurde, kann mittels der Systemvariablen RC und SIGL der Fehler analysiert werden. RC beinhaltet den Fehlercode von REXX und SIGL die Zeile, in der dieser Fehler aufgetreten ist.
TRACE
TRACE bestimmt die Ablaufverfolgung des Programms. TRACE kennt die folgenden Schalter: A, C, E, F, I, L, N, O, R und S.
Fehlercodes
RC - Code: | Bedeutung: | RC - Code: | Bedeutung: |
4 | Programmunterbrechung | 26 | Ungültige ganze Zahl |
5 | Ressourcen erschöpft | 27 | Ungültige DO Syntax |
6 | Unpaarige Zeichen "/*" | 28 | Ungültiges LEAVE oder ITERATE |
7 | WHEN oder OTHERWISE erwartet | 29 | Umgebungsname zu lang |
8 | Unerwartetes THEN oder ELSE | 30 | Name oder Kette zu lang |
9 | Unerwartetes WHEN oder OTHERWISE | 31 | Name beginnt mit Nummer oder . |
10 | Unerwartetes oder unpassendes END | 33 | Ungültiges Ausdrucksergebnis |
11 | Steuerstapel voll | 34 | Logischer Wert nicht 0 oder 1 |
12 | Klausel zu lang | 35 | Ungültiger Ausdruck |
13 | Ungültige Zeichen im Programm | 36 | Unpaariges ")" |
14 | Unvollständiges DO/SELECT/IF | 37 | Unpaariges "(" oder unerwartetes "," |
15 | Ungültige hexadezimale Konstante | 38 | Ungültige Schablone oder Muster |
16 | Marke nicht gefunden | 39 | Auswertungsstapel-Überlauf |
17 | Unerwartete PROCEDURE | 40 | Inkorrekter Routinenaufruf |
18 | THEN erwartet | 41 | Schlechte Arithmetik-Umformung |
19 | Kette oder Symbol erwartet | 42 | Arithmetischer Überlauf/Unterlauf |
20 | Symbol erwartet | 43 | Routine nicht gefunden |
21 | Ungültige Daten am Ende der Klausel | 44 | Die Funktion gab keine Daten zurück |
22 | Ungültige Zeichenkette | 45 | Bei der Funktion Return sind keine Daten angegeben |
24 | Ungültige TRACE-Anforderung | 48 | Ausfall im Systemservice |
25 | Ungültiges Unter-Schlüsselwort gefunden | 49 | Interpretationsfehler |
Literatur
- The Rexx Language: A Practical Approach to Programming, von Michael Cowlishaw, ISBN 0137806515