Home Page
        Orders     Downloads     Support     Contact     Deutsch
ZOC Terminal is a professional SSH Client and Terminal Emulator for Windows and macOS.
ZOC Online Help Topic:

Programming ZOC (REXX/DDE) → REXX Language Elements

 

Overview
This topic offers an overview of the most commonly used parts of the native REXX language (a more basic introduction to ZOC programming can be found in REXX Programming).

The REXX language in combination with ZOC basically consists of three parts:
1. Basic REXX instructions (CALL, IF, END, etc.)
2. REXX built in functions. (TIME(), SUBSTR(), STRIP(), etc.)
3. ZOC Extensions (ZocSend, ZocDownload, ZocWait, etc.)

This topic covers the essential parts of points 1. and 2.

ZOC specific extension (3.) are listed in ZOC-REXX Commands/Functions.

 

If you look at the My Documents→ZOC Files→REXX folder on your computer, you will find a link to ZOC REXX Reference (PDF), document, which will cover all three points above in great depth. A link to other REXX resources. can also be found there.

Last but not least, there is a ZIP archive with Zoc scripting samples (ZocScriptingSamples.zip) in the folder mentioned above. Most of the topics which are presented here, are also demonstrated in the those samples.

 

 

Essential REXX Language Elements
       
Command Placement
 

In REXX comments can span multiple lines when they are placed between /* and */. REXX also knows single line comments, which start with a -- sequence and which automatically end when the line ends.

More than one command can be placed in one line by separating them by semicolons.

A command can be continued in the next line by placing an extra comma at the end of the line.
 

/* REXX
   Placement Sample */
    
SAY "Hello "; SAY "World"
    
CALL zoc "REQUEST", "What do you think?", ,
     "Do not know", "Do not care"
    
answer= ZOCRESULT()
    
-- now we're done
EXIT

Numbers and Arithmetics
 

Numbers can be used for calculation, counting etc. REXX uses numbers and the arithmetic in a pretty straightforward way:
 

/* REXX */
SAY 4*5+3*5 /* Output: 35 */
SAY 10/3 /* Output: 3.333333 */
SAY 10%3 /* Output: 3 (integral division) */
SAY 10//3 /* Output: 1 (division remainder) */
N= 4
SAY N /* Output: 4 */
N= N+1
SAY N*3 /* Output: 15 */

Strings
 

REXX programs often process text in one way or another. While REXX inherently knows no types (values are treated as numbers or strings depending on the context), it is generally better to put all text strings in single or double quotes:
 

/* REXX */
SAY "Hello World!"
SAY "Joe's Bar"
SAY 'He suggested: "Use ZOC!"'
SAY 'She replied: "That''s my program!"'

You can assign strings to variables. Strings in quotes and string variables can simply be concatenated by writing them after one another, although sometimes the string concatenation operator || can be used for clarity or to resolve ambiguities.:
 

/* REXX */
w= "World"
ex= "!"
w2= w||ex /* the || operator is actually required here: w||ex vs. wex */
hwe= "Hello "w2
    
-- say five times "Hello World!"
SAY hwe
SAY "Hello" w2
SAY "Hello "w2
SAY "Hello "||w2
SAY "Hello "||w||ex

Tracing
 

To find errors in your REXX program (or to watch the program execution) you can insert a TRACE A command into your REXX program (usually after the initial comment). With that, the REXX interpreter will display each instruction in the program as it executes it.

TRACE I will show very detailed tracing and TRACE O turns tracing off.

Conditionals
 

To express conditions in REXX programs, the following conditional operators are used:

Operator Function Example
= equal (numbers) IF ret=640 THEN …
== exactly equal (strings) IF input=="ZOC" THEN …
<> not equal IF rc<>640 THEN …
\= not equal (same as <>) IF rc\=640 THEN …
< less IF val<10 THEN …
> greater IF val>50 THEN …
<= less or equal IF val<=100 THEN …
>= greater or equal IF val>=100 THEN …
& AND IF (i>=0) & (i<10) THEN …
| OR IF (k=0) | (k=1) THEN …
\ NOT IF \(k=0) THEN …

Decisions
 

Decisions are made using the IF <condition> THEN DO <commands> END ELSE DO <commands> END sequence (see above for conditionals).
A typical program part using an IF command looks like this:
 

/* REXX */
IF rc=0 | rc=1 THEN DO /* rc 0 oder rc 1 */
    SAY "ok"
END
ELSE DO
    SAY "failed"
END

The ELSE-part can be omitted if it is not needed. The keywords DO and END can be omitted if only one command is to be executed conditionally.:
 

/* REXX */
IF rc=0 | rc=1 THEN SAY "ok"
ELSE SAY "failed"

Loops
 

Loops are expressed in the following form:

DO <count> <commands> END
DO WHILE <condition> <commands> END
DO UNTIL <condition> <commands> END
DO <variable>=<start> TO <end> <commands> END


 
Example:

/* REXX */
DO 5
    SAY "Hello"
END
    
N= 100
DO WHILE n>0
    SAY n
    n= n-1
END
    
DO i=1 TO 10
    SAY i
END

Loops can be aborted from within using the LEAVE command. The ITERATE command will skip the rest of the loop body for the current iteration and will continue with the next loop iteration.

Jumps and Procedures (Subroutines)
 

Jump targets (labels) and subroutines are marked with a name and a colon. To jump to a label, use the SIGNAL command.

The CALL command is used to call a subroutine (which will return to the place it was called from via RETURN).

The following example demonstrates a jump and a call to a subroutine with argument passing:
 

/* REXX */
    
PULL n
    
IF n=0 THEN SIGNAL get_out
    
teny= 10/n
SAY "10/"n "is" teny
CALL square n
    
get_out:
    
EXIT
    
square:
    value= ARG(1)
    sqr= value*value
    SAY "Square of "||value||" is "||sqr
    RETURN
    

Function Calls
 

Functions are marked and called like procedures. The difference is that the can return a value to the calling command:
 

/* REXX */
    
SAY "Enter base"
PULL b
SAY "Enter power"
PULL p
    
result= power(b,p)
SAY "The " p "th power of " b " is " result
    
EXIT
    
power:
    base= ARG(1)
    pow= ARG(2)
    res= 1
    DO I=1 TO pow
     res= res*base
    END
    RETURN res

External Calls
 

It is also possible to call an external script file as a subroutine and pick up a possible result. To do this, the name of the external script files needs to be placed in quotes. The called script then needs to be placed either in the ZOC program folder, in the ZOC Files folder, in the ZOC script files folder or in a folder which is listed in the PATH or REGINA_MACROS variable in the system environment (e.g. C:\1).

Alternately you can specify a full folder and file name for the file. Parameters are passed as usual (separated by commas).

If you have a scriptname or path in a REXX variable the regular call Syntax will not work though, but you can build a string which contains the complete command and pass it through the INTERPRET command (see the sample below).
 

/* REXX:test.zrx */
    
/* call external script in one of the ZOC folders */
CALL "sub.zrx" "Hello", "World"
    
/* call external script in an external folder */
CALL "C:\rexxlib\sub.zrx" "Hello", "World"
    
/* call external script as function */
x= "sub.zrx"(12,2)
SAY x
    
/* call external script via INTERPRET */
scriptfile= "Z:\test\zzz.zrx"
cmd= 'CALL "'||scriptfile||'"'
INTERPRET cmd
    
/* call external script as function via INTERPRET */
scriptfile= "sub.zrx"
cmd= 'x= "'||scriptfile'"(12,2)'
INTERPRET cmd
SAY x

The called script can pick up parameters through the built-in ARG(n). function and return results via the RETURN command:
 
/* REXX:sub.zrx */
a= ARG(1)
b= ARG(2)
SAY a
SAY b
mult= a*b
RETURN mult

The PARSE command
 

PARSE is a powerful REXX command which can be used to split formatted strings in parts and assign the parts to variables. The syntax is PARSE VALUE <string> WITH <variable>"<delimiter>" …

For example, if you have a string coordinate in the form <index>: <pos-x>/<pos-y> you can easily break it into parts via

PARSE VALUE coord WITH index": "posx"/"posy
 
Example:

/* REXX SAMPLE TO GET VALUES FROM A COMMA SEPARATED LIST */
x= "1, 2, 3, 4"
    
DO FOREVER
    IF x=="" THEN LEAVE
    
    PARSE VALUE x WITH val", "rest
    
    SAY val
    
    x= rest
END

Issuing ZOC Commands
 

ZOC commands are extensions to the REXX language which are implemented as procedures and functions (see ZOC-REXX Commands for a list).

ZOC commands that do not return a value (or if you are not interested in the return value) are called with the procedure call syntax:
CALL <zoc-command> <argument(s)>

ZOC-commands that do return a value are called with the function call syntax:
<result-var>= <zoc-command>(<argument(s)>)

Issuing Windows or macOS Shell Commands
 

Commands which are intended to be executed by the operating system (like deleting or renaming files), must be addressed to the operating system directly. This can either be done through REXX's ADDRESS CMD command or through ZOC's ZocShell command.
 

/* REXX */
ADDRESS CMD "cmd.exe /c DEL UPLOAD.TMP"
ZocShell "DEL UPLOAD.TMP"

Built-In Functions
 

The functions below can be used in assignments or in other commands that expect values, e.g. b= ABS(a) or IF ABS(n)>10 THEN ….

 
Note: Only the essential functions and arguments are listed here, for a complete description please see The ZOC REXX Reference (PDF) in your My Documents→ZOC Files→REXX folder.

ABS(<value>)
 

Absolute value (remove sign), e.g. n=ABS(t)

ARG(<n>)
 

The n-th argument of a procedure/function.

COPIES(<str>,<repeat>)
 

Return <repeat> copies of <string>, e.g. x=COPIES("-more- ", 10)

C2D(<char>)
 

Obtain the decimal ASCII value of a character (Char-TO-Decimal), e.g. n=C2D('A') will set n to 65.

C2X(<char>)
 

Obtain the decimal ASCII value of one or more characters (Char-TO-heX), e.g. n=C2X('AB') will set n to 4142.

DATE("<style>")
 

Return the current date in different styles (one of B, D, E, M, N, O, S, U, W), e.g. today=DATE("S") will return "20080201" on February 1st, 2008).

D2C(<ascii>)
 

Create the character from a given ASCII value (Decimal-To-Character), e.g. SAY D2C(65) will print the letter A or cr= D2C(13) will assign the carriage return character to the variable CR.

FILESPEC(<part>, <filename>)
 

Cut a given part (one of "Drive", "Path", "Name") from a filename, e.g. dir=FILESPEC("Path", ofile)

LEFT(<string>, <num>)
 

Return the first <num> characters from <string>, e.g. SAY LEFT("BEERBOTTLE", 4) will print BEER.

LENGTH(<string>)
 

Return the number of characters in a string.

LINEIN(<filename>)
 

Read the next line of text from a file (see FILE I/O).

LINEOUT(<filename>, <text>)
 

Write a next line of text to a file (see FILE I/O).

POS(<needle>, <haystack>)
 

Find the first string in the second and return the position or 0 if not found.

RIGHT(<string>, <num>)
 

Return the last <num> characters from <string>, e.g. SAY RIGHT("BEERBOTTLE", 6) will print BOTTLE.

STREAM(<filename>, …)
 

Perform a file control operation (see the FILE I/O section below).

SUBSTR(<string>, <pos>[, <length>])
 

Return <length> characters from position <pos> in string. <length> can be omitted and will return the rest of the string.

STRIP(<string>)
 

Remove leading and trailing blanks from a string e.g. str= STRIP(str)

TIME("<style>")
 

Return the current time (style is one of C, H, L, M, N, S), e.g. SAY TIME("N") will show the time in HH:MM:SS format.

TRANSLATE(<string>)
 

Translate the characters in a string to upper case.

TRUNC(<n>, <m>)
 

Cut the value <n> so that it has <m> decimal places.

X2C(<ascii>)
 

Create the character(s) from a given hex value (heX-To-Character), e.g. SAY X2C(41) will print the letter A or crlf= X2C(0D0A) will assign the carriage return and line feed characters to the variable CRLF.


FILE I/O
 

Check if File Exists
 

IF STREAM(<filename>, "C", "QUERY EXISTS")\="" THEN …

Open for Writing
 

CALL STREAM <filename>, "C", "OPEN WRITE"

Open for Reading
 

CALL STREAM <filename>, "C", "OPEN READ"

Write to File
 

CALL LINEOUT <filename>, <text>

Read from File
 

<variable>= LINEIN(<filename>)

Check End of File
 

IF STREAM(<filename>, "S")\="READY" THEN …

Close File
 

CALL STREAM <filename>, "C", "CLOSE"


 

/* REXX FILE INPUT EXAMPLE */
    
file= "input.txt"
    
DO FOREVER
    ln= LINEIN(file)
    IF STREAM(file, "S")\="READY" THEN LEAVE
    
    /* process line of file (ln) here */
    
END
CALL STREAM file, "C", "CLOSE"

Please also check the FILEIO sample in SCRIPT\RXSAMPLE\TUTORIAL directory.


Parameters to REXX Scripts
 

It is possible to pass a parameter to a REXX scripts from the ZOC command line (or ZOC user buttons), e.g. ZOC /RUN:script\test.zrx "/RUNARG:Hello, World"

The parameter can be accessed via the ARG(1) function from within the REXX Script and if necessary be split using the PARSE command (it is recommended to subsequently use the STRIP function to remove leading and trailing blanks from the parameters).
 

/* PARAMETERS TO REXX */
p= ARG(1)
PARSE VALUE p WITH p1","p2
p1= STRIP(p1)
p2= STRIP(p2)
SAY "Parameters: ("||p||") ("||p1||") ("||p2||")"
    

Equivalents to BASIC Commands
 

ASC
 

D2C()

CHR$
 

C2D(), X2C()

CLOSE
 

CALL STREAM(<file>, "C", "CLOSE")

EOF
 

STREAM(<file>, "S")\="READY"

FOR … NEXT
 

DO n=<first> TO <last> … END

INSTR$
 

POS()

MID$
 

SUBSTR()

LEN
 

LENGTH()

OPEN
 

STREAM(<file>, "C", "OPEN …")

INPUT
 

PULL, ZocAsk()

INPUT#
 

LINEIN()

PRINT
 

SAY, ZocWrite, ZocWriteln

PRINT#
 

LINEOUT

 

 
← Back to Programming ZOC (REXX/DDE)

 

Downloads
Orders
Contact
Support
Terms of Use
Privacy Policy