# Programmeren in REXX/RexxUtil

Vrijwel de meeste implementaties van REXX hebben naast de basistaal nog één of meer externe functiepakketten die de mogelijkheden van REXX vergroten. In het geval van OORexx waarop we ons hier baseren zijn er de volgende pakketten
* RexxUtil met vooral functies om het besturingssysteem te benaderen (Windows of Unix).
* RxMath met trigonometrische en logaritmische functies.
maar ook
* RxSock, een Rexx functiepakket dat toegang verleent tot de TCP/IP socket API's zoals men ze in C programmeertaal kan vinden.
* RxFtp, een Object Rexx Class library die toegang verleent tot de TCP/IP FTP interface.
Met de functie RxFuncAdd kunnen we een functie uit een extern pakket laden, of beter gezegd, registreren voor ons programma.
Willen we bijvoorbeeld de functie SysIni uit het RexxUtil pakket laden, dan gebruiken we het statement:
Met de RxFuncQuery kunnen we controleren of de functie geladen is (rc=0) of niet (rc=1). Met de functie RxFuncDrop kunnen we een functie terug uitschrijven.
Maar vrijwel de meeste pakketten voorzien in een speciale functie die dan in één beweging alle andere functies laadt. Dit is wat we dan schrijven:
De "SysLoadFuncs" functie uit het RexxUtil pakket dient dus om alle RexxUtil functies te registreren. In het RxMath pakket zorgt de functie "MathLoadFuncs" daarvoor.
* Het is niet nodig dit in elk programma te schrijven. Het is voldoende om deze functiepakketten eenmalig te registreren tijdens het opstarten van het systeem. Maak daarom een start.rex programma met bovenstaande statements en plaats het programma in de startup-folder van Windows.
We gaan nu de meest interessante functies van het RexxUtil pakket van nabij bekijken. Voor de volledige lijst verwijzen we naar de documentatie (C:\Program Files\ooRexx\doc\RexxRef.pdf).

# Functies voor het systeem

We veronderstellen hier een Windows systeem, maar veel van deze functies werken ook op een Unix systeem, al zullen ze dan soms anders reageren.

## SysBootDrive - Vanaf welk station is het systeem opgestart ?

geeft de stationsletter van waaruit Windows is opgestart (bv. C:).

## SysCls - het scherm uitvagen

Met deze functie kan men het scherm van de opdrachtprompt uitblanken tijdens uitvoering van het programma (clear screen).

## SysDriveInfo - informatie over diskstation

Geeft de driveletter, de vrije ruimte, de totale ruimte en het label van het opgegeven station. Bijvoorbeeld:
Pas op, het zijn decimale getallen. Om digitale gigabytes, of gibibytes te bekomen moeten we delen door 1024**2. Windows zal daarom bij de taartverdeling voor dit station 87,6GB vrije ruimte tonen.

## SysDriveMap - lijst van de stationsletters

Geeft een lijst van de stationsletters op het systeem, te beginnen bij station. Men kan de lijst beperken door een optie op te geven. Deze kan zijn:
* USED - Geeft de stationsletters die toegankelijk zijn, zowel locale als remote;
* FREE - geeft enkel de vrije stations;
* LOCAL - geeft enkel de locale stations;
* REMOTE - geeft enkel de remote stations (bv. een NAS schijf);
* REMOVABLE - de stations die verwijderbaar zijn (bv. USB stick of kaartlezer);
* CDROM - geeft de CD-ROM stations;
* RAMDISK - virtuele stations die in RAM geheugen zijn gesimuleerd.
Bijvoorbeeld:

## SysFileSystemType - organisatie van een station

Geeft de bestandsorganisatie van het opgegeven station (nullstring als het station niet gereed is, of niet bestaat).

## RxWinExec - programma uitvoeren (alleen Windows)

Deze functie voert het opgegeven Windows commando uit. Het commando bevat alles wat men anders op de opdrachtprompt zou invoeren, parameters incluis.
Als geen expliciet pad is meegegeven in de naam van het commando, dan zoekt REXX achtereenvolgens:
* de huidige map (current directory);
* de map van waaruit OORexx is opgeroepen;
* de Windows systeemmap;
* de Windows map;
* de mappen die in de systeemvariabele "Path" zijn opgegeven.
De optie schermvorm bepaalt hoe het venster van de toepassing er moet uitzien. Dit kan volgende waarde aannemen:
* ShowNormal: toont een normaal opdrachtvenster;
* ShowNoActivate: toont een opdrachtvenster, doch behoudt het huidig als actief;
* ShowMinNoActive: opent een geminimaliseerd scherm en behoudt het huidig venster als actief;
* ShowMinimized: opent een geminimaliseerd venster;
* ShowMaximized: opent een venster dat het hele scherm beslaat;
* Hide: stopt het huidig venster weg en opent een nieuw venster;
* Minimize: minimaliseert het venster en activeert het venster met hogere rang.
Het resultaat van deze functie is het Process ID (PID) van de toepassing die gestart is. Indien het starten niet is gelukt krijgen we één van volgende cijfers als resultaat
* 2, het bestand was niet gevonden;
* 3, het opgegeven pad bestaat niet;
* 11, het EXE bestand is ongeldig;
* -53, het netwerk-pad is ongeldig.
We hebben hier dus een andere manier om een host-commando uit te voeren. Indien we zijn opgeroepen door een programmapakket, dan kunnen we via deze methode toch nog rechtstreeks een Windows commando uitvoeren zonder via het oproepend programma te moeten rondgaan.

## SysIni - Windows INI bestanden benaderen

Deze functie laat een beperkte toegang toe tot INI bestanden. Variabelen worden verzameld onder hun applicatie-naam en geassocieerde sleutels. Het kan gebruikt worden om gegevens uit te wisselen tussen toepassingen die niet gelijktijdig actief zijn. Wees bijzonder voorzichtig bij het veranderen van bestaande sleutels. Het Windows register kan slechts beperkt met deze functie worden benaderd.
We kunnen een waarde opvragen, zetten of elimineren. Het antwoord van de functie is de opgevraagde waarde, of een nullstring indien het zetten of uitvagen van de waarde is gelukt.
Bij fouten wordt een foutbericht terug gegeven.
Indien geen inifile is meegegeven wordt het bestand "WIN.INI" gebruikt. De functie heeft 6 mogelijke vormen:
* SysIni([inifile],applicatie,sleutel,waarde) om één enkele waarde de zetten;
* SysIni([inifile],applicatie,sleutel) om de waarde van één enkele sleutel op te vragen;
* SysIni([inifile],applicatie,sleutel,"DELETE:") om één enkele sleutel te elimineren;
* SysIni([inifile],applicatie,"DELETE:") om een applicatie en al zijn sleutels te elimineren;
* SysIni([inifile],applicatie,"ALL:","stem") om alle sleutels van een applicatie op te vragen. Het resultaat gaat naar de opgegeven stem;
* SysIni([inifile],"ALL:","stem") om de namen van alle applicaties op te vragen. Het resultaat gaat naar de stem.

## SysShutdownSystem - het Windows systeem stoppen

Dank zij deze functie kan het Windows systeem worden gestopt. De parameters zijn:
* Computer = de naam van het systeem op afstand. Zonder computernaam wordt het lokaal systeem gestopt;
* Bericht = een bericht naar de gebruiker;
* Wachttijd = de tijd dat het bericht blijft staan;
* Appsluiten = als op "1" gezet, toont het niet het bericht "Save unsaved data ?"
* Herstart = het systeem wordt herstart als hier 1 wordt opgegeven.

## SysSleep - het programma pauzeren

Het programma pauzeert gedurende het opgegeven aantal seconden.
Het aantal seconden mag een getal zijn met maximaal 7 cijfers.
En eigenlijk hoort het volgende paar standaardfuncties hier ook logisch bij...

## USERID - naam van gebruiker

Geeft de naam van de actieve user.

## DIRECTORY - de huidige actieve map

Deze functie geeft de naam van de huidige actieve map en zet de nieuwe_map als nieuwe actieve map. Bij het opstarten van een REXX programma is de actieve map gelijk aan de map van waaruit het programma is opgestart. Dit is niet noodzakelijk de map waar de broncode van het programma staat ! Als we het programma als volgt oproepen,
dan zal «C:\» als actieve map worden aangeven.

# Bestanden beheren

Voornamelijk voor Windows voorziet het RexxUtil pakket in een reeks functies waarmee we bestanden kunnen beheren. Het gebruik van deze functies is te verkiezen boven het oproepen van het rechtstreeks commando, omdat:
* we een meer sprekende returncode terugkrijgen;
* de Windows foutberichten niet meer op het scherm verschijnen. Desgevallend kunnen we er dan zelf één produceren dat duidelijker is voor de gebruiker.
We maken deze verschillen duidelijk bij de bespreking van de eerste functie SysFileDelete hieronder.
Maar eerst nog even dit: vermits het hier om functies gaat, en niet om host-commando's, zal de variabele rc niet ingevuld worden, maar wel de variabele result. Toch spreekt men vaak over returncode voor deze functies, maar dan kunnen we als volgt de verwarring wegnemen:

## SysFileDelete - een bestand uitvagen

We mogen geen "wildcards" gebruiken, dus geen *.jpg bijvoorbeeld.
Dit zijn de mogelijke "returncodes" die we kunnen krijgen:
* 0 Alles OK, bestand is verwijderd;
* 2 Bestand is niet gevonden;
* 3 Het pad van de bestandsnaam bestaat niet;
* 5 Toegang geweigerd, of bestand is in gebruik;
* 26 Niet een DOS disk;
* 32 Sharing violation, bestand op andere computer mag alleen gelezen worden;
* 36 Sharing buffer overloop;
Laten we het gebruik van deze functie nu eens vergelijken met het rechtstreeks oproepen van het "ERASE" commando van Windows:
We krijgen het volgende op het scherm:
De eerste zin is het antwoord van Windows op het eerste 'ERASE' commando. Hier kunnen we nog met dat bericht leven. Maar voor een nietsvermoedende gebruiker is zo'n bericht, midden in de uitvoering van een programma niet duidelijk en ook niet leuk om zien. Erger nog, zelfs al mislukte dit commando omdat het bestand er niet is, toch geeft Windows een returncode 0 terug. Ons programma kan het foutbericht niet intercepteren en heeft er dus het raden naar of de operatie lukte of niet.
Bij de daaropvolgende SysFileDelete functie krijgen we een rare boodschap. Dit is het gevolg van een typische beginnersfout. We kijken nu terug naar de instructielijn met de SysFileDelete. REXX vervangt de functie door het resultaat dat ze produceerde, t.t.z. 2 want het bestand is niet gevonden. Het statement is nu erg kort geworden en maakt geen deel uit van een assignatie of een conditionele instructie (bv. when 2=0 then) of zo. REXX geeft dat resultaat dus door als host commando. Tot nader order heeft Windows geen commando dat "2" noemt, tenzij er een 2.BAT of 2.REX in het "path" te vinden is.
De tweede 'ERASE' geeft ons helemaal geen tekst te zien (alles verliep OK, maar we zien dat niet) en ook hier is de returncode=0.
De daaropvolgende 'SysFileDelete' heeft hetzelfde probleem als bij de eerste. We moeten dit dus anders schrijven:
We krijgen we:
En we zien dat de SysFileDelete functie ons wel degelijk meer zinvolle "returncodes" geeft. Het afschrikkend foutbericht krijgen we ook niet meer, maar ons programma kan aan de hand van de returncode de gebruiker op een vriendelijke manier inlichten als dat nodig zou blijken.

## SysFileCopy - een bestand kopiëren

Er mogen geen "wildcards" gebruikt worden (bv. *.jpg). Als alles goed gaat hebben we een returncode 0, bij een fout geeft de functie een returncode 2. Bijvoorbeeld:
Noteer dat een bestaand bestand zonder verwittiging wordt overschreven.

## SysFileMove - een bestand verplaatsen

Zoals SysFileCopy, maar nu wordt het bestand van de oorspronkelijke plaats weggenomen nadat het kopiëren naar de nieuwe plaats is gelukt. Als het bestand in het doelpad al bestaat, dan krijgen we een resultaat 183.

## SysIsFile - bestaat een bestand ?

Deze functie geeft 0 als het bestand niet bestaat, en 1 als het wel bestaat. De bestandsnaam mag geen "wildcards" ofte jokers bevatten.
Vermits we de binaire waarde 0 (onwaar) of 1 (waar) terugkrijgen kunnen we eenvoudig dit schrijven:

## SysIsFileDirectory - bestaat een map ?

Is vergelijkbaar met SysIsFile, en antwoord dus 0 als de map niet bestaat, 1 als ze wel bestaat. Jokers zijn ook niet toegelaten.

## SysFileTree - bestanden zoeken

Deze functie is equivalent aan het DIR commando, maar we krijgen het resultaat rechtstreeks terug in een REXX stem !
De zoekterm is zoals we met het DIR commando gebruiken, bijvoorbeeld "D:\Fotos\*.jpg". Dus jokers zijn nu wel toegelaten.
De lijst van de gevonden bestanden wordt in de opgegeven stem. geplaatst, waarbij de dimensie van de stem, dus het aantal gevonden bestanden, in element 0 wordt gezet.
Als opties kan men een combinatie van één of meer van volgende letters opgeven:
* F enkel naar bestanden zoeken (Files);
* D enkel naar (sub)mappen zoeken (Directories);
* B zowel bestanden als mappen zoeken (Both). Dit is de standaardoptie.
* S recursief zoeken, dus ook in Submappen;
* T geeft Tijd en datum van de bestanden in de vorm JJ/MM/DD/UU/MM i.p.v. normaal iets als «13/11/05 2:12pm»;
* L geeft de tijd en datum in Lang formaat JJJJ-MM-DD UU:MM:SS. (Nuttig voor een sort);
* O geeft enkel de naam van het bestand. Zonder deze optie worden standaard de datum, tijd, grootte, attributen en naam van de bestanden teruggegeven.
Voorbeeld:
geeft mogelijks:
De datum en tijdsweergave in het voorbeeld hierboven is niet om naar huis te schrijven, en we zitten mogelijk ook al met een jaar-2000 probleemje. Daarom gebruiken we dus best de optie L, zoals in ons volgend voorbeeld. Ook hier geldt weer dat de naam van de stem waarin het resultaat moet komen als een constante moet worden geschreven. Doen we dat niet dan loopt alles in het honderd als iemand bestand.="Hello" zou gaan toevoegen...
Zattribuut bepaalt welke attributen de gezochte bestanden moeten hebben. Het masker is standaard "*****", waarmee alle bestanden worden teruggegeven. Elke positie in het masker kan echter vervangen worden door een + of - om aan te duiden dat het bestand het desbetreffend attribuut verplicht wel of niet moet hebben. De volgorde van de attributen ligt vast en is gelijk aan ADHRS, namelijk Archive, Directory, Hidden, Read-only en System. Dus, "*-+**" zou alle verborgen bestanden zoeken maar geen mappen.
Nattribuut bepaalt de nieuwe attributen die aan de bestanden moeten worden toegekend. Men kan dus met deze functie attributen van bestanden veranderen. De volgorde van de attributen is weer ADHRS en als er een + gezet wordt dan wordt het attribuut aangezet. Met een - wordt het afgezet en met een * blijft het attribuut onveranderd. Dus, een Nattribuut gelijk aan "-**+*" zal het Archive attribuut afzetten en de Read-only aanzetten voor alle bestanden die aan de zoekopdracht voldeden. Een map maken van een bestand, ja dat lukt natuurlijk niet. De nieuwe attributen zijn onmiddellijk in het antwoord van de functie te zien.
Voorbeeld:
geeft misschien iets in de aard van:
Wij vonden SysFileTree geweldig nuttig omdat ze de bestandsinformatie mooier teruggeeft dan het DIR commando van Windows, maar ook omdat men zeer eenvoudig kan kiezen welke bestanden met specifieke attributen men wil zien. Daarom hebben we een FileTree.rex programma gemaakt dat SysFileTree gebruikt en het resultaat op het scherm toont. We voegen nog de mogelijkheid om het resultaat te sorteren aan toe. Met piping kan men de output afleiden naar een bestand. Het programma is te vinden in het hoofdstuk met voorbeeldprogramma's.

## SysGetFileDateTime - datum en tijd van bestand opvragen

Met deze functie kunnen we - indien het bestandssysteem het toelaat - de verschillende tijden van een bestand (of map) opvragen. Het bestand moet toegankelijk zijn en mag niet in gebruik zijn.
De verschillende tijden die we kunnen opvragen zijn:
* Create - de creatiedatum en -tijd van het bestand;
* Access - de laatste maal dat het bestand benaderd werd. Dit is de standaardoptie;
* Write - de laatste maal dat er naar het bestand is geschreven.
Vergelijk dit met bijvoorbeeld "SysFileTree" waar we enkel de Access tijd terugkrijgen.

## SysSetFileDateTime - een nieuwe datum en/of tijd aan een bestand toekennen

SysSetFileDateTime(bestandsnaam[,nieuwe_datum][,nieuwe_tijd]) Met deze functie kunnen we datum en/of tijd van een bestand aanpassen. Het gaat enkel om de "Laatste Modificatie-datum". Indien datum noch tijd worden opgegeven, dan wordt de huidige systeemtijd toegewezen. Indien slechts één van deze twee parameters wordt opgegeven verandert uiteraard enkel dat gegeven. Ook de datum/tijd van een map kan zo worden aangepast. Het bestand of map moet toegankelijk zijn voor schrijven en niet in gebruik zijn door een ander proces of gebruiker.
De nieuwe datum moet verplicht voldoen aan volgende formaat: JJJJ-MM-DD. De nieuwe tijd moet opgegeven worden in het formaat UU:MM:SS (24-uursformaat).
Een returncode -1 geeft aan dat de aanpassing is mislukt. Dit zijn voorbeelden:

## SysFileSearch - tekst in een bestand zoeken

Met deze functie zoeken we in een bestand naar alle lijnen waar de zoekstring in voorkomt. Het resultaat ervan is terug te vinden in de opgegeven stem.. Element 0 bevat dan het aantal gevonden lijnen.
Als opties kan men meegeven:
* C hoofdletter gevoelige opzoeking (case-sensitieve)
* N lijnnummers bij het resultaat zetten.
Bijvoorbeeld:
geeft misschien volgende uitslag:

## SysSearchPath - zoeken naar een bestand in een pad

Deze functie gaat na of het bestand in het opgegeven pad aanwezig is. Indien wel, dan wordt de volledige naam van het eerste bestand dat voldoet teruggegeven, en wordt er niet meer verder gezocht. Indien geen bestand is gevonden, dan krijgen we een nullstring terug. Het pad verwijst hier naar een "omgevingsvariabele" die een lijst van mappen bevat. De typische omgevingsvariabelen hiervoor zijn "PATH" en "DPATH".
De optie geeft aan waar het zoeken moet beginnen:
* C beginnen van in de huidige map (Current directory) en vervolgens het opgegeven pad.
* N niet in de huidige map beginnen.
Bijvoorbeeld:
Hopelijk krijgen we als antwoord:
want anders moeten we steeds expliciet het volledig pad opgeven om de REXX interpreter op te starten.

# Mappen beheren
## SysMkDir - een map aanmaken

Mogelijke returncodes zijn:
* 0 alles verliep naar wens;
* 3 pad waar map moet gemaakt worden is niet gevonden;
* 5 toegang geweigerd;
* 26 geen DOS disk;
* 87 ongeldige parameter (mapnaam ongeldig);
* 108 schijf gelocked;
* 183 map bestaat al;
Het MKDIR commando van Windows geeft altijd returncode=0.

## SysRmDir - een map wegnemen

De returncodes kunnen nu zijn:
* 0 alles verliep naar wens;
* 2 map niet gevonden;
* 3 pad naar map is niet gevonden;
* 5 toegang geweigerd;
* 16 De map is de huidige map (we kunnen de tak waarop we zitten niet afzagen);
* 26 geen DOS disk;
* 32 map is niet gedeeld, of veranderingen niet toegestaan;
* 108 schijf gelocked;
* 123 ongeldige mapnaam;
* 145 map is niet leeg;
* 146 er is een substitutie op de map;
* 147 de map is gelinkt aan een andere;

# Werken met stems
## SysStemCopy - een (deel van een) stem kopiëren

Deze functie kopieert elementen van één stem, de bronstem, naar een andere, de doelstem.
Het kopiëren begint bij element bstart van de bronstem. Dit eerste element gaat naar element met index dstart van de doelstem. Een aantal elementen kan opgegeven worden, anders worden alle resterende elementen van de bronstem gekopieerd.
Een laatste parameter bepaalt of de elementen van de bronstem als nieuwe elementen moeten worden Ingevoegd, dan wel of de elementen in de doelstem moeten worden Overschreven.
Deze functie kan enkel werken met stems waarvan de staart een continue getallenreeks is en waarvan element nul het aantal bevat. Dit is een conventie die we al lang kennen.
Een resultaat -1 betekent dat er problemen zijn opgetreden.
Voorbeeld:
In het eerste geval wordt de doel-stem gelijkgemaakt aan de bron-stem.
In het tweede geval voegen we de eerste twee elementen van de bron tussen na het vierde element van het doel. In dit concrete voorbeeld is dat dus aan het einde van de stem. Als we nu de elementen van de doelstem lijsten, dan bekomen we:

## SysStemDelete - elementen uit een stem nemen

Deze functie elimineert een aantal elementen van de stem, beginnend aan het element met index start.
Ook deze bewerking kan alleen op stems met numerieke indexen worden uitgevoerd. Na het elimineren van de elementen wordt de stem gecompacteerd, t.t.z. de indexen worden terug opeenvolgend gemaakt.

## SysStemInsert - elementen aan een stem toevoegen

Deze functie voegt een nieuw element met index toe aan de stem en geeft het een waarde. De volgende elementen worden opgeschoven, dus hun indexnummers worden met één verhoogd.

## SysStemSort - een stem sorteren

De elementen van de stem (met numerieke indexen) worden geordend. Dit kan in oplopende of aflopende volgorde gebeuren (Ascending of Descending).
Het sorteren kan wel of niet hoofdlettergevoelig zijn (Case sensitive of case Insensitive). Het sorteren begint bij het element met index start en eindigt bij het element met index einde. Het sorteren gebeurt tussen de beginkolom en de eindkolom (of volledige breedte).

# Andere nuttige functies
## RxMessageBox - Een bericht in een kadertje

Met deze functie kunnen we op een eenvoudige wijze een popup-schermpje maken waarin we een bericht kunnen tonen. Dit is vooral nuttig indien ons programma niet vanuit de opdrachtprompt is opgeroepen, maar door een link in het startmenu of een icoon op de desktop. Een say werkt dan niet omdat er geen scherm is om het te tonen.
Naast de tekst kunnen we ook zorgen voor een titel en kiezen welke knoppen en icoontje moeten voorzien worden. De mogelijke knoppen zijn:
* NONE (geen knop voorzien):
* OK - een knop met de tekst "OK" voorzien.
* OKCANCEL - twee knoppen, een met "OK" en een met "CANCEL";
* RETRYCANCEL - de knoppen "RETRY" en "CANCEL";
* ABORTRETRYIGNORE - drie knoppen: "ABORT", "RETRY" en "IGNORE";
* YESNO - de knoppen "YES" en "NO";
* YESNOCANCEL - drie knoppen, "YES", "NO" en "CANCEL";
Een tekst op de knoppen kan niet vertaald worden. OORexx biedt hier andere mogelijkheden, we bespreken die in het hoofdstuk Een beetje OORexx.
We kunnen kiezen uit volgende icoontjes:
* HAND - een handje;
* QUESTION - een vraagteken;
* EXCLAMATION - een uitroepteken;
* ASTERISK - een ster;
* INFORMATION - een Informatie-icoontje;
* STOP - een stopteken;
* QUERY - een vraagteken;
* WARNING - een waarschuwingsteken;
* ERROR - een foutteken.
Dit zijn de codes die we terugkrijgen als de gebruiker een knop heeft gekozen:
* 1 OK knop;
* 2 CANCEL knop (of Esc-toets);
* 3 ABORT knop;
* 4 RETRY knop;
* 5 IGNORE knop;
* 6 YES knop;
* 7 NO knop;
Voorbeeld:

## SysDumpVariables - programmavariabelen lijsten

Deze functie schrijft alle variabelen en hun waarde naar STDOUT, of het bestand dat als doel is opgegeven. Het bestand wordt aangevuld (append). Per variabele krijgen we een lijn in de vorm:
Handig om te debuggen natuurlijk.
Hiermee beëindigen we de beschrijving van de functies uit het RexxUtil pakket. Er zijn minstens nog eens zoveel functies in dit pakket. We raden aan van er de documentatie eens op na te slaan om de andere functies te leren kennen. Deze opmerking geldt natuurlijk ook voor functiepakketten die bij andere implementaties van REXX zijn meegeleverd.