---
rexxpub:
  defaults: rony.yaml
  logo: rexx
---

<!-- 020_ooRexx_V08.odp (2026-10-15 09:34) -->

<!-- slide # 1 (2026-10-15 09:34) ----------------------------- ODP slide # 1 -->
. slide cover
# Procedural and Object-oriented Programming 1

. subtitle
**Statement, Routine (Procedure, Function), "Stem"-Variable**

. cover-art
. picture img/020_ooRexx_V08/p01-diagram-7.png

<!-- slide # 2 (2026-10-15 09:34) ----------------------------- ODP slide # 2 -->
. slide reference="Cf. rexxref.pdf (1.12.3. Labels)"
# Labels

- Identifier, followed by a colon (**:**)
. click
- Serves as a target for an internal routine
    - **CALL**-statements (invoking procedures)
    . click
    - Function invocations
    . click
    - **SIGNAL**-statements (like a "**GOTO**" instruction in other languages)
    . click
    - Exception handling (**SIGNAL ON** resp. **CALL ON**)

      . click
      ```rexx
      DO i = 1 TO 3
           SAY "Oho!" i
           IF i = 1 THEN SIGNAL fin
      END
      fin : SAY "C'est la fin!"
      ```

      . click label
      Output:

      . with
      ```output
      Oho! 1
      C'est la fin!
      ```

<!-- slide # 3 (2026-10-15 09:34) ----------------------------- ODP slide # 3 -->
# Internal Routines

- Grouping of statements which repeatedly get executed by different parts in a program
. click
- Start with a label
. click
- Invocation
    . after
    - **CALL** label
    . after
    - Statements after the label get executed
    . after
    - The **RETURN**-statement returns control (to the statement immediately following the **CALL**-statement)
. click
- A „routine“ may also be called „procedure“

<!-- slide # 4 (2026-10-15 09:34) ----------------------------- ODP slide # 4 -->
. slide reference="Cf. rexxref.pdf (7.2. Functions and Subroutines)"
# Internal Routines

```rexx
/* A Rexx-Programm with an internal routine named 'TIMESTAMP' */
CALL TimeStamp       /* call a subroutine   */
CALL SysSleep 5      /* sleep 5 seconds     */
CALL TimeStamp       /* call a subroutine   */
EXIT                 /* exit program        */

TimeStamp :          /* label               */
   SAY "It is rather late ..."
   RETURN
```

. click label
Output:

. after numbered steps=0,1,2 each=after
```output
It is rather late ...
It is rather late ...
```

<!-- slide # 5 (2026-10-15 09:34) ----------------------------- ODP slide # 5 -->
# Functions

- Routines that return a value ("function value") to the caller via the ***RETURN***-statement
. click
- Invocation
    - Variant 1
        - Invocation: the name (label), immediately followed by a left and right parenthesis
        - The return value ("function value") replaces the invocation

          . after
          ```rexx
          today = DATE()
          ```

    . click
    - Variant 2
        - Invocation: **CALL** followed by the name (label) of the routine
        - Interpreter stores the return value in the special variable **RESULT**

          . after
          ```rexx
          CALL DATE
          today = result
          ```

<!-- slide # 6 (2026-10-15 09:34) ----------------------------- ODP slide # 6 -->
. slide reference="Cf. rexxref.pdf (2.3. CALL)"
# Functions

```rexx
/* A Rexx-Programm with an internal function named 'TIMESTAMP' */
SAY  TimeStamp()     /* function call          */
CALL SysSleep 5       /* sleep 5 seconds       */
CALL TimeStamp        /* procedure call        */
SAY result            /* show function value   */
EXIT                  /* exit program          */

TimeStamp :          /* label                 */
     RETURN "It is rather late ..."
```

. click label
Output:

. after numbered steps=0,1,2 each=after
```output
It is rather late ...
It is rather late ...
```

<!-- slide # 7 (2026-10-15 09:34) ----------------------------- ODP slide # 7 -->
. slide reference="Cf. rexxref.pdf (11.3.3. RC, 11.3.4. SIGL)"
# Rexx Variables Used By Rexx

- The Rexx interpreter may set the value of the following variables
    . after
    - **RESULT**
        - If a routine gets invoked with **CALL** and returns a value with its **RETURN** statement then the Rexx interpreter stores that returned value in a variable named **RESULT**
    . click
    - **RC**
        - Stores the "**r**eturn **c**ode" that the external command returned: a value of `0` (zero) indicates that the external command completed without any errors or failures
    . click
    - **SIGL**
        - Stores the line number which contains the **CALL** or **SIGNAL** statement that caused the jump to the routine ("**sig**nal **l**ine")

<!-- slide # 8 (2026-10-15 09:34) ----------------------------- ODP slide # 8 -->
. slide reference="Cf. rexxref.pdf (7.4. Built-in Functions (BIF))"
# All Functions of REXX

- Rexx provides the following built-in functions ("BIF"), some are specific to **strings** or **filenames**:

. plain flow=5
- `ABBREV()`{style="color:#6b8e23"}
- `ABS()`
- `ADDRESS()`
- `ARG()`
- `B2X()`
- `BEEP()`
- `BITAND()`
- `BITOR()`
- `BITXOR()`
- `C2D()`
- `C2X()`
- `CENTER()`{style="color:#6b8e23"}
- `CHANGESTR()`{style="color:#6b8e23"}
- `CHARIN()`{style="color:#c9211e"}
- `CHAROUT()`{style="color:#c9211e"}
- `CHARS()`{style="color:#c9211e"}
- `COMPARE()`
- `COPIES()`{style="color:#6b8e23"}
- `COUNTSR()`{style="color:#6b8e23"}
- `D2C()`
- `D2X()`
- `DATATYPE()`
- `DATE()`
- `DELSTR()`{style="color:#6b8e23"}
- `DELWORD()`{style="color:#6b8e23"}
- `DIGITS()`
- `DIRECTORY()`
- `ENDLOCAL()`
- `ERRORTEXT()`
- `FILESPEC()`{style="color:#c9211e"}
- `FORM()`
- `FORMAT()`
- `FUZZ()`
- `INSERT()`{style="color:#6b8e23"}
- `LASTPOS()`{style="color:#6b8e23"}
- `LEFT()`{style="color:#6b8e23"}
- `LENGTH()`{style="color:#6b8e23"}
- `LINEIN()`{style="color:#c9211e"}
- `LINEOUT()`{style="color:#c9211e"}
- `LINES()`{style="color:#c9211e"}
- `MAX()`
- `MIN()`
- `OVERLAY()`{style="color:#6b8e23"}
- `POS()`{style="color:#6b8e23"}
- `QUEUED()`
- `RANDOM()`
- `REVERSE()`{style="color:#6b8e23"}
- `RIGHT()`{style="color:#6b8e23"}
- `SETLOCAL()`
- `SIGN()`
- `SOURCELINE()`
- `SPACE()`{style="color:#6b8e23"}
- `STREAM()`{style="color:#c9211e"}
- `STRIP()`{style="color:#6b8e23"}
- `SUBSTR()`{style="color:#6b8e23"}
- `SUBWORD()`{style="color:#6b8e23"}
- `SYMBOL()`
- `TIME()`
- `TRACE()`
- `TRANSLATE()`{style="color:#6b8e23"}
- `TRUNC()`{style="color:#6b8e23"}
- `VALUE()`
- `VAR()`
- `VERIFY()`{style="color:#6b8e23"}
- `WORD()`{style="color:#6b8e23"}
- `WORDINDEX()`{style="color:#6b8e23"}
- `WORDLENGTH()`{style="color:#6b8e23"}
- `WORDPOS()`{style="color:#6b8e23"}
- `WORDS()`{style="color:#6b8e23"}
- `X2B()`
- `X2C()`
- `XRANGE()`{style="color:#6b8e23"}

<!-- slide # 9 (2026-10-15 09:34) ----------------------------- ODP slide # 9 -->
# External Rexx Function Packages

- Standardised Interfaces to and from Rexx
    . click
    - Loading an external Rexx function package from Rexx, an example

      . after
      ```rexx
      IF RxFuncQuery("SysLoadFuncs") THEN DO
         CALL RxFuncAdd "SysLoadFuncs","RexxUtil","SysLoadFuncs"
         CALL SysLoadFuncs        /* no quotes! */
      END
      ```

. click
- Function packages, which supply new functions to Rexx that are not part of the language, an example
    - Mark Hessling's "RexxSQL" – Direct access to the most important relational database management systems (DB2, Oracle, SQL-Server, MySQL, etc.)
        - https://sourceforge.net/projects/rexxsql/

<!-- slide # 10 (2026-10-15 09:34) --------------------------- ODP slide # 10 -->
. slide reference="Cf. rexxref.pdf (8. Rexx Utilities (RexxUtil))"
# Function Package "RexxUtil" (Excerpt)

- Contains more than 60 "useful" functions, some of which are only available for **Windows** or **Unix** operating systems.

. plain flow=3
- `RxMessageBox`{style="color:#c9211e"}
- `RxWinExec`{style="color:#c9211e"}
- `SysAddRexxMacro`
- `SysBootDrive`{style="color:#c9211e"}
- `SysClearRexxMacroSpace`
- `SysCls`
- `SysCreatePipe`{style="color:#6b8e23"}
- `SysCurPos`{style="color:#c9211e"}
- `SysCurState`{style="color:#c9211e"}
- `SysDriveInfo`{style="color:#c9211e"}
- `SysDriveMap`{style="color:#c9211e"}
- `SysDropRexxMacro`
- `SysDumpVariables`
- `SysFileCopy`
- `SysFileDelete`
- `SysFileExists`
- `SysFileMove`
- `SysFileSearch`
- `SysFileSystemType`{style="color:#c9211e"}
- `SysFileTree`
- `SysFork`{style="color:#6b8e23"}
- `SysFormatMessage`
- `SysFromUnicode`{style="color:#c9211e"}
- `SysGetErrorText`
- `SysGetFileDateTime`
- `SysGetKey`
- `SysGetMessage`{style="color:#6b8e23"}
- `SysGetMessageX`{style="color:#6b8e23"}
- `SysGetShortPathName`{style="color:#c9211e"}
- `SysIni`{style="color:#c9211e"}
- `SysIsFile`
- `SysIsFileCompressed`{style="color:#c9211e"}
- `SysIsFileDirectory`
- `SysIsFileEncrypted`{style="color:#c9211e"}
- `SysIsFileLink`
- `SysIsFileNotContentIndexed`{style="color:#c9211e"}
- `SysIsFileOffline`{style="color:#c9211e"}
- `SysIsFileSparse`{style="color:#c9211e"}
- ...

<!-- slide # 11 (2026-10-15 09:34) --------------------------- ODP slide # 11 -->
# Searching for Routines

- Searching order for routines

  . plain steps level=1
  | | |
  |---|---|
  | 1a) | Internal routines (in the program itself) |
  | 1b) | Routines defined as directives (in the program itself) |
  | 2) | The built-in Rexx routines ("built-in functions (BIF)") |
  | 3) | External routines (e.g. Rexx programs) |

. click
- It is possible to use the names of the language built-in functions
    . click
    - Overlay the respective routines
    . after
    - The overlayed built-in function can always be invoked by **enclosing its  uppercased name in quotes**!

<!-- slide # 12 (2026-10-15 09:34) --------------------------- ODP slide # 12 -->
# Searching for Routines

```rexx
/* */
SAY date()       /* invoke self programmed function below  */
SAY "DATE"()     /* invoke the Rexx built-in function      */
EXIT
DATE :           /* "DATE" is in effect a Rexx function !  */
     RETURN "Date(), self programmed!"
```

[Output (if run on 2059-05-20):]{.fragment}

. after
```output
Date(), self programmed!
20 May 2059
```

<!-- slide # 13 (2026-10-15 09:34) --------------------------- ODP slide # 13 -->
. slide reference="Cf. rexxref.pdf (2.19. PROCEDURE)"
# Scopes

. steps
. static
- Define which variables and labels are seen in which part of a Rexx program
    - By default all variables in a program are globally visible/accessible, they belong to the **same scope**
    - Labels in a program are always global
- If the keyword instruction **PROCEDURE** follows a label, then a new ("local") scope will be created for it
    - Should there be a need to access variables outside a local scope, then one must use the **EXPOSE** subkeyword of the **PROCEDURE**-Statement denoting those variable names.

<!-- slide # 14 (2026-10-15 09:34) --------------------------- ODP slide # 14 -->
# Scopes

```rexx
/* */
a = 1
b = 2
SAY "a=" a "b=" b
CALL calc
SAY "a=" a "b=" b
EXIT
calc :
     a = a * 2
     b = b * 3 / 4
     RETURN
```

[Output:]{.label .fragment anim=cut}

. numbered steps=0,1,2
```output
a= 1 b= 2
a= 2 b= 1.5
```

<!-- slide # 15 (2026-10-15 09:34) --------------------------- ODP slide # 15 -->
. slide reference="Cf. rexxref.pdf (2.19. PROCEDURE)"
# Scopes

```rexx
/* */
a = 1
b = 2
SAY "a=" a "b=" b
CALL calc
SAY "a=" a "b=" b
EXIT
calc: PROCEDURE  /* no access to global "a" und "b" !  */
     a = 5       /* hence, "a" must be defined locally */
     b = 6       /* hence, "b" must be defined locally */
     a = a * 2
     b = b * 3 / 4
     RETURN
```

. click label
Output:

. numbered steps=0,1,2
```output
a= 1 b= 2
a= 1 b= 2
```

<!-- slide # 16 (2026-10-15 09:34) --------------------------- ODP slide # 16 -->
. slide reference="Cf. rexxref.pdf (2.19. PROCEDURE)"
# Scopes

```rexx
/* */
a = 1
b = 2
SAY "a=" a "b=" b
CALL calc
SAY "a=" a "b=" b
EXIT
calc: PROCEDURE EXPOSE b /* no access to "a", but to "b" !     */
     a = 5                /* hence, "a" must be defined locally */
     a = a * 2
     b = b * 3 / 4
     RETURN
```

. click label
Output:

. numbered steps=0,1,2
```output
a= 1 b= 2
a= 1 b= 1.5
```

<!-- slide # 17 (2026-10-15 09:34) --------------------------- ODP slide # 17 -->
. slide reference="Cf. rexxref.pdf (1.13.4. Stems)"
# "Stem" Variable (Associative Arrays)

. after
- Identifier contains one or more **dots**
. click
- The sequence of characters from the beginning up to and including the first dot is called **stem** (the remainder is called **tail**)

  . click
  ```rexx
  a.n                     = "aha"
  a.OnE                   = 1
  a.1                     = "Richard"
  Austria.Tyrol           = 750000
  Austria.Tyrol.Innsbruck = 135000
  SAY a.1 a.n a.OnE
  SAY Austria.Tyrol
  ```

  . click label
  Output:

  . after numbered steps=0,1,2 each=after
  ```output
  Richard aha 1
  750000
  ```

<!-- slide # 18 (2026-10-15 09:34) --------------------------- ODP slide # 18 -->
. slide reference="Cf. rexxref.pdf (1.13.4. Stems)"
# "Stem" Variable (Associative Arrays)

. after
- Some RexxUtil functions (e.g. *SysFileTree()*) use a convention, which mandates that after the dot only integer numbers be used
    . click
    - **stem.0** – stores the total number of "elements"; this allows iterating over all stem entries starting with "**1**" going up to the number stored in **stem.0**

      . click
      ```rexx
      file.1 = "max.doc"
      file.2 = "moritz.doc"
      file.0 = 2           /* maximum number of "elements"  */
      DO i=1 TO file.0
         SAY file.i        /* "i" is also called "index"    */
      END
      ```

      . click label
      Output:

      . after numbered steps=0,1,2 each=after
      ```output
      max.doc
      moritz.doc
      ```

<!-- slide # 19 (2026-10-15 09:34) --------------------------- ODP slide # 19 -->
. slide reference="Cf. rexxref.pdf (9. Parsing)" kicker="PARSE #"
# PARSE by Blank

- **PARSE** statements allow parsing a string and assigning (parts of it) to Rexx variables in one step

  . click
  ```rexx
  text = "  Stiegler   Seppl   Stumm     Zillertal/Tirol"
  PARSE VAR text famName firstName rest
  SAY famName
  SAY firstName
  SAY rest
  ```

  . click label
  Output:

  . after numbered steps=0,1,2,3 each=after
  ```output
  Stiegler
  Seppl
       Stumm   Zillertal/Tirol
  ```

<!-- slide # 20 (2026-10-15 09:34) --------------------------- ODP slide # 20 -->
. slide reference="Cf. rexxref.pdf (9. Parsing)" kicker="PARSE #"
# PARSE by Blank

```rexx
ruler = COPIES("1234+6789|", 5)
text = "  Stiegler   Seppl   Stumm     Zillertal/Tirol"
PARSE VAR text famName firstName rest
SAY ruler; SAY text ; SAY
SAY pp(famName); SAY pp(firstName)
SAY pp(ruler);   SAY pp(rest)
EXIT
PP : RETURN "[" || ARG(1) || "]" -- "pretty print" ;)
```

. click label
Output:

. with
```output
1234+6789|1234+6789|1234+6789|1234+6789|1234+6789|
  Stiegler   Seppl   Stumm     Zillertal/Tirol

[Stiegler]
[Seppl]
[1234+6789|1234+6789|1234+6789|1234+6789|1234+6789|]
[  Stumm     Zillertal/Tirol]
```

<!-- slide # 20+1 (2026-10-15 09:34) --------------------------- ODP slide # 20 -->
. slide reference="Cf. rexxref.pdf (9. Parsing)" kicker="PARSE #"
# PARSE by Blank

```rexx {blanks=all}
ruler = COPIES("1234+6789|", 5)
text = "  Stiegler   Seppl   Stumm     Zillertal/Tirol"
PARSE VAR text famName firstName rest
SAY ruler; SAY text ; SAY
SAY pp(famName); SAY pp(firstName)
SAY pp(ruler);   SAY pp(rest)
EXIT
PP : RETURN "[" || ARG(1) || "]" -- "pretty print" ;)
```

. click label
Output:

. with
```output {blanks=all}
1234+6789|1234+6789|1234+6789|1234+6789|1234+6789|
  Stiegler   Seppl   Stumm     Zillertal/Tirol

[Stiegler]
[Seppl]
[1234+6789|1234+6789|1234+6789|1234+6789|1234+6789|]
[  Stumm     Zillertal/Tirol]
```

<!-- slide # 21 (2026-10-15 09:34) --------------------------- ODP slide # 21 -->
. slide reference="Cf. rexxref.pdf (9. Parsing)" kicker="PARSE #"
# PARSE by Pattern

```rexx
      /*        10        20        30        40
        1234+6789|1234+6789|1234+6789|1234+6789| */
text = "  Ruaniger Annelle        Stumm    Zillertal / Tirol "
PARSE VAR text before "/" after
SAY pp(before)
SAY pp(after)
EXIT
PP : RETURN "[" || ARG(1) || "]" -- "pretty print" ;)
```

. click label
Output:

. after numbered steps=0,1,2 each=after
```output
[    Ruaniger Annelle     Stumm   Zillertal ]
[  Tirol ]
```

<!-- slide # 22 (2026-10-15 09:34) --------------------------- ODP slide # 22 -->
. slide reference="Cf. rexxref.pdf (9. Parsing)" kicker="PARSE #"
# PARSE by Pattern

```rexx
pattern = "/"
      /*        10        20        30        40
        1234+6789|1234+6789|1234+6789|1234+6789| */
text = "  Ruaniger Annelle        Stumm    Zillertal / Tirol "
PARSE VAR text before (pattern) after
SAY pp(before)
SAY pp(after)
EXIT
PP : RETURN "[" || ARG(1) || "]" -- "pretty print" ;)
```

. click label
Output:

. after numbered steps=0,1,2 each=after
```output
[    Ruaniger Annelle     Stumm   Zillertal ]
[  Tirol ]
```

<!-- slide # 23 (2026-10-15 09:34) --------------------------- ODP slide # 23 -->
. slide reference="Cf. rexxref.pdf (9. Parsing)" kicker="PARSE #"
# PARSE by Position, Length, Blank

```rexx
      /*        10        20        30        40
        1234+6789|1234+6789|1234+6789|1234+6789| */
text = "  Ruaniger Annelle        Stumm    Zillertal / Tirol "
PARSE VAR text 3 famName +8 12 firstName city .
SAY pp(famName)
SAY pp(firstName)
SAY pp(city)
EXIT
PP : RETURN "[" || ARG(1) || "]" -- "pretty print" ;)
```

. click label
Output:

. after numbered steps=0,1,2,3 each=after
```output
[Ruaniger]
[Annelle]
[Stumm]
```

<!-- slide # 24 (2026-10-15 09:34) --------------------------- ODP slide # 24 -->
. slide reference="Cf. rexxref.pdf (9. Parsing)" kicker="PARSE #"
# PARSE by Value

```rexx
text = "Sattler;Cilli;Stumm;Zillertal/Tirol"
PARSE VAR text famName ";" firstName ";" city
SAY pp(famName)
SAY pp(firstName)
SAY pp(city)
EXIT
PP : RETURN "[" || ARG(1) || "]" -- "pretty print" ;)
```

. click label
Output:

. after numbered steps=0,1,2,3 each=after
```output
[Sattler]
[Cilli]
[Stumm;Zillertal/Tirol]
```

<!-- slide # 25 (2026-10-15 09:34) --------------------------- ODP slide # 25 -->
. slide reference="Cf. rexxref.pdf (9. Parsing)" kicker="PARSE #"
# PARSE Value Into Variable `a`{.rexx} and Use It for Parsing the Remainder

```rexx
text = ";Sattler;Cilli;Stumm;Zillertal/Tirol"
PARSE VAR text 1 a +1 famName (a) firstName (a) city (a) .
SAY pp(famName)
SAY pp(firstName)
SAY pp(city)
EXIT
PP : RETURN "[" || ARG(1) || "]" -- "pretty print" ;)
```

. click label
Output:

. after numbered steps=0,1,2,3 each=after
```output
[Sattler]
[Cilli]
[Stumm]
```

<!-- slide # 26 (2026-10-15 09:34) --------------------------- ODP slide # 26 -->
. slide reference="Cf. rexxref.pdf (9. Parsing)" kicker="PARSE #"
# PARSE VALUE … WITH ...

- **PARSE VALUE expression WITH pattern**
    . click
    - Makes it possible to immediately parse the result of an **expression**

      . after
      ```rexx
      PARSE VALUE date() WITH day month year
      say "year:" year "month:" month "day:" day
      ```

      . click label
      Example:

      [**Output** (assuming **date()** returned the string `"20 May 2059"`)**:**]{.fragment}

      . click
      ```output
      year: 2059 month: May day: 20
      ```

<!-- slide # 27 (2026-10-15 09:34) --------------------------- ODP slide # 27 -->
. slide reference="Cf. rexxref.pdf (2.18. PARSE)" kicker="PARSE #"
# Input from Keyboard (“STDIN”)

- **PARSE PULL** statements allow parsing a string read from the keyboard and assigning (parts of it) to Rexx variables in one step

  . click
  ```rexx
  SAY "1. What is your name?"   /* Keyboard input: "Max"      */
  PARSE PULL name
  SAY "Your name is:" pp(name)
  SAY "2. What is your name?"   /* Keyboard input: "moritz"   */
  PULL name
  SAY "Your name is:" pp(name)
  EXIT
  PP : RETURN "[" || ARG(1) || "]" -- "pretty print" ;)
  ```

  . click label
  Output:

  . after numbered steps=0,1,2,3,4,5,6 each=after
  ```output
  1. What is your name?
  Max
  Your name is: [Max]
  2. What is your name?
  moritz
  Your name is: [MORITZ]
  ```

<!-- slide # 28 (2026-10-15 09:34) --------------------------- ODP slide # 28 -->
. slide reference="Cf. rexxref.pdf (2.18. PARSE)" kicker="PARSE #"
# Retrieving Arguments PARSE ARG

- **PARSE ARG** allows to fetch argument values

  . click
  ```rexx
  a = 1; b = 2
  SAY "a=" a "b=" b
  CALL calc a , b
  SAY "a=" a "b=" b
  EXIT
  calc: PROCEDURE      /* caller's variables "a" and "b" not visible !       */
     PARSE ARG a , b   /* fetch arguments and assign them to local variables */
     SAY "calc: a=" a "b=" b
     a = a * 2
     b = b * 3 / 4
     SAY "calc: a=" a "b=" b
     RETURN
  ```

. click label
Output:

. numbered steps=0,1,2,3,4
```output
a= 1 b= 2
calc: a= 1 b= 2
calc: a= 2 b= 1.5
a= 1 b= 2
```

<!-- slide # 29 (2026-10-15 09:34) ----------- business card (not in the ODP) -->
. slide card logo=none
# Contact