411 REFERENCE · Wikibooks
Aros/Developer/Docs/Rexx
Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.
Introduction
Is REXXC = "AREXX". AROS includes REXXMAST where the program register the arexx ports, that can be used from any scripting language that supports it, not just AREXX. AREXX is not compatible integrated, there were improvements in certain areas but it includes regina, that is implementing a relative updated REXX version. But AREXX is not only older but includes extensions and changes not in the original REXX. So yes but not 100%
For example, in SYS:Extras/Rexx/Progs rx <prg>.r runs the script
Arexx
A scripting language for processing text and files.
A script is just a plain text file.
rx script.rexx
Copyrighted (William S. Hawes) extension to Rexx from IBM
ARexx is a scripting language and although you can use it to launch applications, you're better off using a regular DOS script for that, if it's required.
ARexx is far more powerful than DOS, but isn't really intended as a replacement. ARexx's principal strength is that it allows you to write scripts that can talk to "hosts"; that is, any application that has an ARexx port. This allows ARexx to control the application (within the limits of what features it exposes to ARexx). As a single script can communicate with multiple hosts, it can coordinate activity between applications. Any command it doesn't understand, it forwards to the currently selected host. By default, the host is the shell itself.
You invoke CALL searching for a function from a library (according to the documentation in this search order):
1) Internal functions
2) Built-in functions
3) Function libraries and Function Hosts
4) External AREXX programs - forward the Msg to the AREXX process itself and scan for files loaded
There are three different 'modes':
- ARexx command host
- function host
- function library
Tutorial
/* A simple program */
say 'Hello World'
Looping
The DO control structure always begins with a DO and ends with an END.
DO UNTIL:
DO UNTIL [condition]
[instructions]
END
DO WHILE:
DO WHILE [condition is true]
[instructions]
END
Stepping through a variable:
DO i = x TO y BY z
[instructions]
END
Looping forever until exiting with LEAVE - BREAK has other possibilities, but you probably want LEAVE:
DO FOREVER
IF [condition] THEN LEAVE
END
Looping a fixed number of times
DO i = x TO y BY z FOR a
[instructions]
END
Conditionals
IF [condition] THEN
[instruction]
ELSE
[instruction]
Testing for multiple conditions
SELECT
WHEN [condition] THEN
DO
[instruction]
END
OTHERWISE
DO
[instruction] or NOP
END
NOP indicates no instruction is to be executed.
Variables
There is a command that looks if a var is a integer or not... DATATYPE(WHOLE)
Command and Function
Rexx makes difference between commands and functions. With ADDRESS you indicate a place to send a command to. Commands are always one line. Functions have to be in a library with ARexx support and be added with addlib. You seem to want function syntax but are using command port.
Changes the way that arguments passed on the command line are made available to the called Rexx program. With this switch each parameter on the command line is available as a separate argument, rather then the normal behaviour of only making the combined command line arguments available as one internal argument.
It seems indeed that 'command'-mode is not to receive more than 1 argument (arg[0]).
PARSE
The PARSE instruction is particularly powerful; it combines some useful string-handling functions
parse [upper] origin template
where origin specifies the source:
arg (command line variable)
linein (keyboard)
pull (REXX data queue)
value (a literal or a function) with required to indicate where the literal ends
var (a variable)
version (version/release number)
and template can be:
list of variables
column number delimiters
literal delimiters
upper is optional; it you specify it, data will be converted to upper case.
use 'PARSE PULL var' if you don't want the input to be uppercased. 'PULL var' is the same as 'PARSE UPPER PULL var'
Examples:
Using a list of variables as template
myVar = "John Smith"
parse var MyVar firstName lastName
say "First name is:" firstName
say "Last name is:" lastName
displays the following
First name is: John
Last name is: Smith
Using a delimiter as template:
myVar = "Smith, John"
parse var MyVar LastName "," FirstName
say "First name is:" firstName
say "Last name is:" lastName
also displays the following
First name is: John
Last name is: Smith
Using column number delimiters:
myVar = "(202) 123-1234"
parse var MyVar 2 AreaCode 5 7 SubNumber
say "Area code is:" AreaCode
say "Subscriber number is:" SubNumber
displays the following
Area code is: 202
Subscriber number is: 123-1234
A template can use a combination of variables, literal delimiters, and column number delimiters.
Advanced Data Structures
array(var, var)
record.field1
record.field2
/* check if a library function is available */
SHOW (L, 'rexxsupport.library')
/* if function not available - add library*/
ADDLIB ('rexxsupport.library',0,-30,0)
/* SHOWDIR (directory, {mode), [pad]) */
SHOWDIR ('sys:')
/* if function - remove library*/
REMLIB ('rexxsupport.library')
parse arg height, width, depth
PROCEDURE EXPOSE WORD
You can pass a whole stem to a function declared in THE SAME script via the "PROCEDURE EXPOSE" statement, e.g.
...
test: procedure expose stem.
say stem.1 stem.a stem.a.ciao
...
(take care to put the '.' or just the stem var will be visible to the function 'test', not the all stem.
Any modificiation to 'stem.' will be global. There is no way to pass a stem to an external function
ARexx will also search for the function in a file with the same name as it and as <name>.rexx), both in current dir and REXX:. Don't put .rexx on my files, as ~(*:*) matches functions, *.rexx ordinary scripts, *.ced ...
File Manipulation
/* Create a file */
if open('file', 'ram:test', 'w') then
call writeln('file' 'data')
call close('file')
else
say 'unable to open'
/* Read a file */
if open('file', 'ram:test', 'r') then
call readch('file' var) /* read first var characters */
do while ~eof('file')
say line
line=readln('file') /* read next line */
end
call close('file')
/* Read a file */
if open('file', 'ram:test', 'a') then
say 'it is here'
else
say 'it is not here'
position = seek ('file', var, string) /* var is +/- bytes from start and string can be b, c or e */
IBM EOL (end of line) = <CR><LF> or (^M^J)
Amiga/UNIX EOL = <LF> or (^J)
Macintosh EOL = <CR> or (^M)
IBM EOF = <EOL><CTRL-Z> or (^M^J^Z)
Amiga EOF = <NULL> or (), optionally <LF> or (^J)
Null, of course, is the absence of any data.
IBM text editors do a <CR><LF> at each <RETURN>. Most Amiga software, AFAIK, only does <LF> and the end of the file is simply indicated when there are no more bytes to be read.
The ARexx EOF() indicates when you've run out of stuff to read from a file. It does not (to my knowledge) look around for whatever the IBM thinks signifies the end of a file on top of simply noticing when the file has reached its end of capacity (say you have a 1024-byte file, after reading 1024 bytes you will have reached the end of the file, or EOF).
do UNTILEF("FILE")
/* Do some reading here or something */
end
Change "call readch('rfile',1)" into "say c2d(readch('rfile',1))" to display the "ascii" code. (Note that only charcodes < 127 is ASCII)
Debugging
Syntax, loop errors, etc.
Trace
Signal
Program IPC
rx "address command Dir"
Talking to DOS,
address "program-name"
You can get the ARexx commands of any MUI program with the HELP command. Here is an example for IBrowse.
/* CheckIB.rexx*/
address IBrowse
'HELP vd0:IB.txt'
The drive specification after the HELP command is the drive and file name for the output. Of course, the program you are checking must be running so the port is available. The output will show the standard ARexx commands that every MUI program has followed by the commands specific to the particular program being checked.
Hooks
Normally you would provide a commandlist with your application and those command would 'automatically' be processed by the hooks installed.
It's when you use commands that does not get 'processed automatically' (because they are not in the commandlist) you need to make use of the functionality you presented (like MUIA_Application_RexxHook).
Since those attributes does not seem to be in place, you would need to fallback to the ordinairy way of doing things, meaning you would somehow 'invent' how to 'sync' your normal commands with the arexx commands
References
ARexx guide (last updated jun-1995)
Beginning ARexx
Loops and Conditionals
Aminet Guides
Arexx references (in AmigaGuide)
Regina 3.00
Instructions
CALL {symbol | string} [expression] [,expression,...]
DO [var=exp] [To exp] [BY exp]] [FOR exp] [FOREVER] [WHILE exp | UNTIL exp]
DROP variable [variable...]
ELSE [;] [conditional statement]
END [variable]
EXIT [expression]
IF expression [THEN] [;] [conditional statement]
INTERPRET expression
ITERATE [variable]
LEAVE [variable]
NOP
NUMERIC {DIGITS | FUZZ} expression or: NUMERIC FORM {SCIENTIFIC | ENGINEERING}
OPTIONS [FAILAT expression] or: OPTIONS [PROMPT expression] or: OPTIONS [RESULTS]
OTHERWISE [;] [conditional statement]
PARSE [UPPER] inputsorce [template] [,template...]
PROCEDURE [EXPOSE variable [variable...]]
PULL [template] [,template...]
PUSH [expression]
QUEUE [expression]
RETURN
SAY [expression]
SELECT
SHELL [symbol | string] [expression]
SIGNAL {ON |OFF} condition or: SIGNAL [VALUE] expression
THEN[;] [conditional statement]
TRACE [symbol|string|[[VALUE] expression]]
UPPER variable [variable...]
WHEN expression [THEN [;] [conditional statement]]
Functions
ABBREV
ABS
ADDLIB
ADDRESS [Symbol|string|VALUE] [expression]]
ALLOCATED
ARG [template] [,template...]
B2C
B2X
BEEP
BITAND
BITCHG
BITCLR
BITCOMP
BITOR
BITSET
BITTST
BITXOR
BUFTYPE
C2B
C2D
C2X
CD
CENTER
CENTRE
CHANGESTR
CHARIN
CHAROUT
CHARS
CHDIR
CLOSE
COMPARE
COMPRESS
CONDITION
COPIES
COUNTSTR
CRYPT
D2C
D2X
DATATYPE
DATE
DELSTR
DELWORD
DESBUF
DIGITS
DIRECTORY
DROPBUF
DUMPFILES
DUMPTREE
DUMPVARS
EOF
ERRORTEXT
EXISTS
EXPORT
FREELISTS
FREESPACE
FUZZ
GETCLIP
GETENV
GETPATH
GETPID
GETSPACE
GETTID
HASH
IMPORT
INDEX
INSERT
JUSTIFY
LASTPOS
LEFT
LENGTH
LINEIN
LINEOUT
LINES
LISTLEAKED
MAKEBUF
MAX
MEMORYSTATS
MIN
OPEN
OVERLAY
POPEN
POS
PRAGMA
QUALIFY
QUEUED
RANDOM
RANDU
READCH
READLN
REMLIB
REVERSE
RIGHT
RXFUNCADD
RXFUNCDROP
RXFUNCERRMSG
RXFUNCQUERY
RXQUEUE
SEEK
SETCLIP
SHOW
SIGN
SLEEP
SOURCELINE
SPACE
STATE
STREAM
STRIP
STORAGE
SUBSTR
SUBWORD
SYMBOL
TIME
TRACE
TRIM
TRACEBACK
TRANSLATE
TRUNC
UNAME
UNIXERROR
UPPER
USERID
VALUE
VERIFY
WORD
WORDINDEX
WORDLENGTH
WORDPOS
WORDS
WRITECH
WRITELN
X2B
X2C
X2D
XRANGE
Operators
OPERATOR PRIORITY OPERATOR DEFINITION
~ 8 Logical NOT
+ 8 Prefix Conversion
- 8 Prefix Negation
** 7 Exponentiation
* 6 Multiplication
/ 6 Division
% 6 Integer Division
// 6 Remainder
+ 5 Addition
- 5 Subtraction
|| 4 Concatenation
(blank) 4 Blank Concatenation
== 3 Exact Equality
~== 3 Exact Inequality
= 3 Equality
~= 3 Inequality
> 3 Greater Than
>=,~< 3 Greater Than or Equal To
< 3 Less Than
<=,~> 3 Less Than or Equal To
& 2 Logical AND
| 1 Logical Inclusive OR
^,&& 1 Logical Exclusive OR
RexxSupport
LONG rxsupp_allocmem(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_baddr(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_closeport(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_delay(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_delete(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_forbid(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_freemem(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_getarg(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_getpkt(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_makedir(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_next(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_null(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_offset(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_openport(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_permit(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_rename(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_reply(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_showdir(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_showlist(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_statef(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_typepkt(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_waitpkt(struct Library *, struct RexxMsg *, UBYTE **);
RexxSyslib
UBYTE *CreateArgstring(UBYTE *string, ULONG length) (A0, D0)
void DeleteArgstring(UBYTE *argstring) (A0)
ULONG LengthArgstring(UBYTE *argstring) (A0)
struct RexxMsg *CreateRexxMsg(struct MsgPort *port, UBYTE *extension, UBYTE *host) (A0, A1, D0)
void DeleteRexxMsg(struct RexxMsg *packet) (A0)
void ClearRexxMsg(struct RexxMsg *msgptr, ULONG count) (A0, D0)
BOOL FillRexxMsg(struct RexxMsg *msgptr, ULONG count, ULONG mask) (A0, D0, D1)
BOOL IsRexxMsg(struct RexxMsg *msgptr) (A0)
void LockRexxBase(ULONG resource) (D0)
void UnlockRexxBase(ULONG resource) (D0)
Adding Regina/Rexx to Programs
http://aminet.net/search?query=Minrexx
http://www.pcguru.plus.com/tutorial/introduction.html
It's really easy to set up your own Rexx port. It's just a standard MsgPort. If you are just going to exit on any message and not parse commands sent to the port then you don't even need to open rexxsyslib.library...
struct MsgPort *CreatePubPort (UBYTE *name, LONG pri)
/* create a port if port name is not already used */
{
struct MsgPort *pubport;
port = NULL;
Forbid ();
if (FindPort (name) == NULL)
pubport = CreateMsgPort (name, pri);
Permit ();
return (pubport);
}
Now that the port is created we just need to wait for a message.
static void PubPortWait (struct MsgPort *pubport)
/* wait for a message or signal on our pubport */
{
ULONG port_mask, signals;
struct RexxMsg *msg;
port_mask = (1L << RexxPort->mp_SigBit);
while (1)
{
signals = Wait (port_mask | SIGBREAKF_CTRL_C);
if (signals & SIGBREAKF_CTRL_C)
Quit("Aborting");
if (signals & port_mask)
{
while ((msg = (struct RexxMsg *) GetMsg (pubport)) != NULL)
{
ProcessRexxMsg (msg); /* routine parses the REXX message */
ReplyMsg ((struct Message *) msg);
}
}
}
}
ProcessRexxMsg() can print your message and exit but remember to ReplyMsg(). If you want to parse the Arexx commands, it's not much more work. The above is pulled from a longer printed code example and uses some REXX includes from "arexx.h" and "arexxsyslib.h" but it should NOT be necessary to open rexxsyslib.library if you will exit on any message received at your port.
http://utilitybase.com/forum/index.php?action=vthread&forum=15&topic=1915
/*
#include <proto/exec.h>
#include <proto/alib.h>
#include <proto/rexxsyslib.h>
#include <exec/ports.h>
#include <rexx/errors.h>
#include <rexx/storage.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
struct MsgPort *port;
struct RexxMsg *msg;
struct Library *RexxSysBase;
char *value;
RexxSysBase = OpenLibrary("rexxsyslib.library", 0);
if (RexxSysBase == NULL)
{
puts("Error opening rexxsyslib.library");
return 20;
}
port = CreatePort("VARTEST", 1);
if (port == NULL)
{
puts("Error creating port");
CloseLibrary(RexxSysBase);
return 20;
}
printf("Port created %x, waiting for message\n", port);
WaitPort(port);
msg = (struct RexxMsg *)GetMsg(port);
puts("Got a message");
if (!IsRexxMsg(msg))
{
puts("Message is not a rexxmsg");
ReplyMsg((struct Message *)msg);
DeletePort(port);
CloseLibrary(RexxSysBase);
return 20;
}
puts("Is a rexx message");
if (!CheckRexxMsg(msg))
{
puts("Message is not from rexx interpreter");
msg->rm_Result1 = RC_ERROR;
ReplyMsg((struct Message *)msg);
DeletePort(port);
CloseLibrary(RexxSysBase);
return 20;
}
puts("Message is from the rexx interpreter");
if (!GetRexxVar(msg, "A", &value))
{
puts("Error during retrieval of value");
return 20;
}
printf("Length string: %d\n", strlen(value));
printf("Value of A: %s\n", value);
SetRexxVar(msg, "A", "2", 1);
msg->rm_Result1 = RC_OK;
msg->rm_Result2 = NULL;
ReplyMsg((struct Message *)msg);
DeletePort(port);
CloseLibrary(RexxSysBase);
return 0;
}
You can now send a message to this little program with the following script:
/* Testing the variable interface */
a = 1
say 'a before call' a
ADDRESS 'VARTEST' test
say 'a after call' a
Save it as (example) 'vartest.rexx' and run it with:
rx vartest.rexx
Example script
For More Examples
/* Calculate some squares and cubes */
do i = 1 to 10 /* 10 interations */
say i i**2 i**3 /* calculations */
end
say ' all done '
/* Even or odd? */
do i = 1 to 10
if i//2 = 0 then type = 'even'
else type = 'odd'
say i 'is' type
end
/* Defining and calling a function */
do i = 1 to 5
say i square(i) /* call square */
end
exit /* all done */
square: /* function name */
arg x /* get the "argument" */
return x**2 /* square it and return*/
/* Demonstrate "results" tracing */
trace results
sum=0;sumsq=0;
do i = 1 to 5
sum = sum + i
sumsq = sumsq + i**2
end
say 'sum=' sum 'sumsq=' sumsq
/* Calculate age in days */
say 'Please enter your age'
pull age
say 'You are about' age*365 'days old'
DO .... ; you have the code already
line = READLN(textfile)
IF line = marker line THEN DO
target = READLN(textfile)
END
END
/* File to read */
IF ~OPEN("in", "Path:yourTextFile", "READ") THEN DO
SAY "Can't open 'Path:yourTextFile' for reading."
CALL CLOSE('in')
EXIT
END
/* File to write */
IF ~OPEN("out", "Ram:filename", "WRITE") THEN DO
SAY "Can't open 'Ram:filename' for writing."
CALL CLOSE('out')
EXIT
END
/* Write lines that start with "(" to Ram:filename */
DO UNTIL EOF('in')
line = READLN('in')
temp = STRIP(line, 'L')
IF LEFT(temp, 1) = '(' THEN CALL WRITELN('out', line)
END
/* */
options results
arg sourcefile
if open(input, sourcefile, R) then do
if ~open(output, "ram:output", W) then call error
Do until eof(input)
line=readln(input)
if pos('(',line)=1 then writeln(output,line) /* line begins with '(' at POS 1 */
end
close(input)
close(output)
end
EXIT
/* function */
ERROR:
SAY "ERROR"
EXIT
/*Bin2AHex*/
/* Convert a binary file to a ASCII representation of Hex.*/
if ~open('bufbin', 'RAM:buffer.bin', 'READ') then do
say "Can't open 'RAM:buffer.bin' for reading."
exit
end
if ~open('buftxt', 'RAM:buffer.txt','WRITE') then do
say "Can't open 'RAM:buffer.txt' for writing."
exit
end
/* 500 seems do be the max for c2x() */
max = 500
in = readch('bufbin', max)
DO until eof('bufbin')
call writech('buftxt',c2x(in))
in = readch('bufbin', max)
END
call close('bufbin')
call close('buftxt')
/* That's All Folks! */
/* Here's a more visible way to enter the control codes */
CSI='9b'x /* control sequence introducer */
boldOn=CSI'1m'
boldOff=CSI'22m'
IF OPEN("Env", "Env:File", "R") THEN DO
filename = READLN("Env")
CALL CLOSE("Env")
END
/* OPEN alone will pop up a filerequester */
OPEN NAME <filename>
/* Displays the data in the source string */
parse source source /* type results called resolved extension host */
words=words(source)
shell command 'RequestChoice >Nil: Source',
'"Invocation type:' word(source,1)'*n',
||'Result requested:' word(source,2)'*n',
||'Called name:' word(source,3)'*n',
||'Resolved name:' DelWord(trim(DelWord(source,words-1)),1,3)'*n',
||'Search extension:' word(source,words-1)'*n',
||'Initial command host:' word(source,words)'"',
'OK'
/* Grabs the Users Hz thus the tick rate per second of the persons machine
(either 50 or 60 generally) amd pouts it into variable 'f' */
PARSE UPPER VERSION f
f=SUBSTR(WORD(f,6),1,2)
DO UNTIL <expression is valid> | i=<value ya want>
/* Call a delay and do nothing for value times(*) variable 'f' */
Call Delay(1*f)
i=i+1
End
You can do it so it makes a value true or tries indefinitely. otherwise you can make it leave the loop using a 'Leave' command at any stage of the DO UNTIL part.
So the below loading libs works well...
libs = "rexxreqtools.library rexxdossupport.library rexxkuang11.library
rexxsupport.library rexxtricks.library"
DO UNTIL libs='';PARSE VAR libs lib libs
IF EXISTS('libs:'lib)|EXISTS('Libs/'lib)|EXISTS(lib) THEN DO
IF ~show('L',lib) THEN call addlib(lib,0,-30,0);END;ELSE DO
/* error output line whether say or echo or defined */
cECHO('Cannot load 'lib);END;END
find what number every key has, this can be in ARexx...
rx <RAW: "
do while 1;
z=readch(stdin,1);
c=c2d(z);
if c2d(bitand('7f'x,z)) < 33 then
z='<'c'>';
call writech(stdout,z);
end
(All on one line)
CTRL-C will stop this thing. Note here that the above and RAW-KEY Intui-messages (OpenWindow()/intuition,
IDCMP flags) are about the only easy and *system legal* way to obtain information about keys pressed.
This will extract the filename extension (such as .lha or .8svx) along with its length. It can be useful, when renaming files. Used it in a conversion script, that can convert different file- types, so archive.lha gets archive.lzx and pic.gif gets pic.png.
STRING = ExtPart(filename)
PARSE VAR string extlen ext
/* ExtPart(filename)
** Returns filename extension and length of extension
** freely usable, freely distributable, intellectual property:
** Andreas Mixich <humpty@...>
*/
PARSE ARG filename
posi = LastPos('.',filename)
ext = SubStr(filename,(posi+1))
extlen = Length(SubStr(filename,posi))-1
extpartinfo = extlen||' '||ext
RETURN(extpartinfo)
This one makes a valid path, which is better to use. No more RAM:Envfilename mistake, but RAM:Env/filename
Additional it makes RAM: out of Ram Disk:
Nothing special, though, you can achieve the same result (except for RAM:<-Ram Disk:) by using rexxdossupport.library/AddPart(pathname,"") - Do not forget the "".
STRING = ValPath("sys:Tools")
/* ValPath()
** make a vaild path out of path (in case it lacks '/')
** Concentrates "Ram Disk:" to "Ram:", so we get rid of this annoying space
** Freely usabel, freely distributable, intellectual property of
** Andreas Mixich <humpty@...>
*/
valpath:
PARSE ARG path
IF (LastPos('/',path) ~= Length(path) & Pos('/',path) ~= 0) THEN
path = path||'/'
ELSE
IF (LastPos(':',path) ~= Length(path) & Pos('/',path) = 0) THEN
path = path||'/'
IF Left(path,9) = "Ram Disk:" THEN
path = Insert("Ram",DelStr(path,1,8))
RETURN(path)
this little sub-routine used in all my ARexx scripts, that need external ports to be available. (WaitForPort)
Since not liking to write the same lines in any script, just select this routine from a GoldED list requester and it is appended to my source. The function is simple:
BOOL = IfPort(portname, prog, mode)
portname is the ARexx-port name of the application,
prog is the full path to the application, in case it needs to be launched mode can be either empty or WB. If WB is used it will be started with WBRun. Sometimes this is quite useful.
The function results in a BOOL (either TRUE or FALSE) so it is easy to handle flow control.
In this routine you will find another function I use:
myERR()
You can replace it by anything you want or just take it away. Use such general routines, because they are more powerful, so could have some logging in myERR() or WB requesters or whatever.
/*///------------------------------ "IfPort(portname,prog,mode)" ------------------------------ */
/*
** IfPort(portname, prog, mode)
** Shows if portname is available, attempts to launch program if not
** Freely usable, freely distributable, intellectual properties:
** Andreas Mixich <humpty@...>
*/
ifport:
PARSE ARG portname, prog, mode
IF ~Show(P,portname) THEN
DO
IF mode = WB THEN
ADDRESS COMMAND wbrun||' >NIL: '||prog
ELSE
ADDRESS COMMAND 'run >NIL: '||prog
ADDRESS COMMAND 'WaitForPort '||portname
IF RC ~= 0 THEN
DO
Call myERR('Error: Could not start '||prog)
RETURN(FALSE)
END
ELSE
RETURN(TRUE)
END
RETURN(TRUE)
/*\\\*/
Here ya go, the fastest SQRT function in Rexx I have seen yet, found in c.l.rexx
/* */
parse arg N
if N <= 0 then exit
s = time('e')
call MethodB(N)
say time('e') - s
exit
MethodB:
x1 = 1
x0 = N
if N ~= 0 then
do until x1 = x0
x0 = x1
x1 = ((x0 * x0) + N) / (2 * x0)
end
else x1 = 0
say x1
return
a very simple one, seldomly used, but given as some example of the Translate() function to newbies and to make the function set a bit more complete. (Since there is an Upper() why shouldn't be there also a Lower())
/*
** Lower()
** Like Upper(), but this one makes a string lowercase.
** Considers german unmlauts and some accents.
** TODO: Add more national characters. Do you know of any missing
** (and where to find them on the keyboard) ?
*/
Lower: PROCEDURE
PARSE ARG string
res =
Translate(string,'abcdefghijklmnopqrstuvwxyzäöüáéíóú','ABCDEFGHIJKLMNOPQRSTUVWXY\
ZÄÖÜÁÉÍÓÚ')
RETURN(res)
/* convert a file into sentences */
arg fileid .
input=''
do until LINES(fileid)=0
in=LINEIN(fileid)
input=input in
end
t=LINEOUT("sentence.txt","--- "fileid" ---")
out=''
do i=1 to LENGTH(input)
char=SUBSTR(input,i,1)
out=out||char
if char="." then do
out=STRIP(SPACE(out))
t=LINEOUT("sentence.txt",out)
out=''
end
end
out=STRIP(SPACE(out))
t=LINEOUT("sentence.txt",out)
exit
Suggest that when you open files you do something more like this to check that it was opened successfully:
if open(tempfile,'t:ms_scenes',w) then do
call writeln(tempfile,'SCENE1')
/* blah, blah... */
call close(file)
end
else do
say 'Unable to open temp file!'
exit
end
Get the file size
/* */
parse arg file
if file="" then do
say "no file given"
exit
end
s=statef(file)
if s="" then do
say "can't find file '"file"'"
exit
end
parse var s type size d d d d d comment
if type~="FILE" then do
say "'"file"' is not a valid file name"
exit
end
say "file '"file"':" size
Scripting languages