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

<!-- 030_ooRexx_V15.odp (2026-10-15 09:34) -->

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

. subtitle
**Exceptions, References, Directives (::routine, ::requires)**

. cover-art
. picture img/030_ooRexx_V15/p01-diagram-7.png

<!-- slide # 2 (2026-10-15 09:34) ----------------------------- ODP slide # 2 -->
. slide logo=oorexx reference="Cf. rexxref.pdf (3. Directives)"
# Execution of Programs

. steps
- Phase 1 (loading): file containing the program ("package") gets loaded
    . static
    - ***All lines*** are read
    . static
    - ***All statements*** are syntactically checked and compiled
- Phase 2 (setup): `::REQUIRES`{.rexx} directives are carried out
    - Remaining directives (e.g. `::ROUTINE`{.rexx}, `::CLASS`{.rexx}, …  ) are carried out
- Phase 3 (execution): Program starts with the very first statement
    - This section is called "main program" or "prolog"
    . after
    - At this point in time access to all defined routines and classes of the program ("package") and access to all public routines and public classes of required or called programs is available and can be used

<!-- slide # 3 (2026-10-15 09:34) ----------------------------- ODP slide # 3 -->
. slide reference="Cf. rexxref.pdf (11. Conditions and Condition Traps)" kicker="Conditions #"
# Conditions (Exceptions)

- Conditions

  . plain steps level=2
  | | |
  |---|---|
  | **SYNTAX** | Statement not syntactically correct |
  | **FAILURE** | Error in external program |
  | **ERROR** | Error in external program, not trapped with "**FAILURE**" or "**ANY**" |
  | **HALT** | Ctl-C (Ctl-Break): user aborts program |
  | **NOVALUE** | Do not allow non-initialised variables |
  | **USER usercondition** | User-defined condition named "**usercondition**" |
  | **LOSTDIGITS** | Needs more digits than **NUMERIC DIGITS** |
  | **NOMETHOD**, **NOSTRING**, **NOTREADY** (later ... ) |  |
  | **ANY** | Intercepts (traps) all conditions |

<!-- slide # 4 (2026-10-15 09:34) ----------------------------- ODP slide # 4 -->
. slide reference="Cf. rexxref.pdf (11. Conditions and Condition Traps)" kicker="Conditions #"
# Conditions (Exceptions)

- Activating/deactivating the condition handling statements with
    - [**CALL {on|off} condition \[NAME label\]**]{.fragment .afterPrevious}\
      calls an internal routine that handles the condition from which one can return
    - [**SIGNAL {on|off} condition \[NAME label\]**]{.fragment .afterPrevious}\
      jumps to the internal routine that handles the condition
. click
- Intercepting ("trapping", "catching") conditions can be activated with the keyword **on**, and deactivated with the keyword **off**
. click
- **condition** is the name of one the aforementioned condition
    - The condition **USER**  needs to be followed by its **usercondition** word
. click
- **NAME** optional, allows for defining a **label** which serves as the **CALL** or **SIGNAL** target
    - If omitted, then the interpreter looks for a label which has the same name as the condition
        - In the case of a **USER** condition the interpreter looks for a label named **usercondition**

<!-- slide # 5 (2026-10-15 09:34) ----------------------------- ODP slide # 5 -->
. slide reference="Cf. rexxref.pdf (11. Conditions and Condition Traps)" kicker="Conditions #"
# Conditions (Exceptions)

- Activate **SYNTAX** condition handling ("**SIGNAL ON SYNTAX**"), jump to label "**ANY:**"

  . click
  . with mark 2 "SYNTAX NAME ANY" pen=1
  . with mark 5 "ANY:" pen=1
  ```rexx
  /* */
  SIGNAL ON SYNTAX NAME ANY /* target name "ANY" given   */
  SAY Nix                   /* Variable not initialized! */
  EXIT 0
  ANY:  /* target for any exception     */
    exc_rc   = RC   /* save return code */
    exc_sigl = SIGL /* save line number */
    exc_type = CONDITION("C") /* get exception type */
    CALL say2stderr "REXX 'RC':" exc_rc
    CALL say2stderr "     type:" exc_type
    CALL say2stderr
    CALL say2stderr "  in line:" exc_sigl
    CALL say2stderr "          " SOURCELINE(exc_sigl)
    EXIT -1             /* indicate error   */
  SAY2STDERR:           /* write to STDERR: */
    CALL LINEOUT "STDERR", ARG(1)
    RETURN
  ```

  . click label
  Output:

  . after
  ```output
  NIX
  ```

<!-- slide # 6 (2026-10-15 09:34) ----------------------------- ODP slide # 6 -->
. slide reference="Cf. rexxref.pdf (11. Conditions and Condition Traps)" kicker="Conditions #"
# Conditions (Exceptions)

. with mark 2 "NOVALUE NAME ANY" pen=1
. with mark 5 "ANY:" pen=1
```rexx
/* */
SIGNAL ON NOVALUE NAME ANY
SAY Nix                    /* Variable not initialized! */
EXIT 0
ANY:  /* target for any exception     */
  exc_rc   = RC   /* save return code */
  exc_sigl = SIGL /* save line number */
  exc_type = CONDITION("C") /* get exception type */
  CALL say2stderr "REXX 'RC':" exc_rc
  CALL say2stderr "     type:" exc_type
  CALL say2stderr
  CALL say2stderr "  in line:" exc_sigl
  CALL say2stderr "          " SOURCELINE(exc_sigl)
  EXIT -1             /* indicate error   */
SAY2STDERR:           /* write to STDERR: */
  CALL LINEOUT "STDERR", ARG(1)
  RETURN
```

. click label
Output:

. after
```output
C:\temp>rexx test.rex
REXX 'RC': RC
     type: NOVALUE

  in line: 3
           SAY Nix                    /* Variable not initialized! */
```

<!-- slide # 7 (2026-10-15 09:34) ----------------------------- ODP slide # 7 -->
. slide reference="Cf. rexxref.pdf (11. Conditions and Condition Traps)" kicker="Conditions #"
# Conditions (Exceptions)

. with mark 2 "NOVALUE NAME ANY" pen=1
. with mark 5 "ANY:" pen=1
```rexx
/* */
SIGNAL ON NOVALUE NAME ANY
SAY Nix                    /* Variable not initialized! */
EXIT 0
ANY:  /* target for any exception     */
  exc_rc   = RC   /* save return code */
  exc_sigl = SIGL /* save line number */
  exc_type = CONDITION("C") /* get exception type */
  CALL say2stderr "REXX 'RC':" exc_rc
  CALL say2stderr "     type:" exc_type
  CALL say2stderr
  CALL say2stderr "  in line:" exc_sigl
  CALL say2stderr "          " SOURCELINE(exc_sigl)
  EXIT -1             /* indicate error   */
SAY2STDERR:           /* write to STDERR: */
  CALL LINEOUT "STDERR", ARG(1)
  RETURN
```

[Running program with redirecting error output to a file:]{.fragment}

. columns 5 7

. after id=#p7x15

```output
C:\temp>rexx test.rex 2>myerrors.txt
```



. next column

. after id=#p7x16

. file="myerrors.txt (contains stderr output):"
```output
REXX 'RC': RC
     type: NOVALUE

  in line: 3
           SAY Nix                    /* Variable not initialized! */
```


. end columns

. click arrow #p7x15 -> #p7x16

<!-- slide # 8 (2026-10-15 09:34) ----------------------------- ODP slide # 8 -->
. slide kicker="Excursus #"
# Excursus: Operating System "Process"

- For each program that needs to be executed Unix or Windows
    . click
    - Creates a management unit named "*process*" and
        . after
        - Reserves memory
        . after
        - Reserves processor time
        . after
        - Sets up the following "standard files"
            - "standard input file ('*stdin*', file descriptor number `0`)": default input via the keyboard
            - "standard output file ('*stdout*', file descriptor number `1`)": default output to the screen (window)
            - "standard error file ('*stderr*', file descriptor number `2`): default output to the screen (window)
        . click
        - Sets up the process "environment"
            - Defines environment variables like
                - `PATH` … determines the directories and the order for seeking programs
                - `JAVA_HOME` … determines the Java directory to use
                - `CLASSPATH` … determines the directories and the order for seeking Java classes
    . click
    - Manages and supervises the program execution (using single or multiple threads)

<!-- slide # 9 (2026-10-15 09:34) ----------------------------- ODP slide # 9 -->
. slide reference="Cf. rexxref.pdf (14.1.4. Default Stream Names)" kicker="Excursus #"
# Excursus: "Redirecting Standard Files"

. steps
. static
- Redirecting the standard files when running a program in a process
    . after
    - Redirection operators: '**\<**' (*stdin*), '**\>**'  (*stdout*, *stderr*) and '**\>\>**' (*stdout*, *stderr*)
        - '**\>**' will delete the output file, whereas '**\>\>**' will append output to the output file
    - Examples
        . after
        - Redirect input from the keyboard to the file "*myinput.txt*`"`

          . with
          ```bash
          rexx myprogram.rex  0<myinput.txt
          rexx myprogram.rex   <myinput.txt
          ```

        - Redirect output from the screen to the file "*myoutput.txt*" (will delete file if it exists)

          . with
          ```bash
          rexx myprogram.rex  1>myoutput.txt
          rexx myprogram.rex   >myoutput.txt
          ```

        - Redirect error output from the screen to the file "*myerrors.txt*" (will delete file if it exists)

          . with
          ```bash
          rexx myprogram.rex  2>myerrors.txt
          ```

<!-- slide # 10 (2026-10-15 09:34) --------------------------- ODP slide # 10 -->
.slide kicker="Excursus #"
# Excursus: "Redirecting Standard Files"

- Redirecting standard files when running a program in a process

  . with
  ```bash
  rexx myprogram.rex 0<myinput.txt 1>myoutput.txt 2>myerrors.txt
  rexx myprogram.rex  <myinput.txt  >myoutput.txt 2>myerrors.txt
  ```

    . after
    - Input from file "*myinput.txt*" instead of keyboard, output to "*myoutput.txt*" instead of screen and error output to "*myerrors.txt"* instead of screen
    . click
    - Redirecting *stderr* to *stdout*
        . after
        - Redirect output to a file and also redirect error output to the same file

          . with
          ```bash
          rexx myprogram.rex >myoutput.txt 2>&1
          ```

            . click
            - Output goes to "*myoutput.txt*" instead of screen
            . with
            - Error output goes to where *stdout* goes to, i.e. "*myoutput.txt*" as well
            . with
            - Important note: always redirect *stdout* first and then redirect *stderr* to *stdout*!
        . click
        - Redirecting and *appending* to *stdout* and to *stderr*

          . with
          ```bash
          rexx myprogram.rex >>myoutput.txt 2>>myerrors.txt
          ```

<!-- slide # 11 (2026-10-15 09:34) --------------------------- ODP slide # 11 -->
.slide kicker="Excursus #"
# Excursus: "Redirecting Standard Files"

. after steps
- "Piping"
    . after
    - Redirect *stdout* of one program to *stdin* of the next program
        . after
        - The output of one program becomes the input of another program
    - Piping operator: vertical bar ("**|**")
    - Example

      . with
      ```bash
      rexx myprogram.rex | rexx myfilter.rex
      ```

        . after
        - The output (*stdout*) of "*myprogram.rex*" becomes the input (*stdin*) of "*myfilter.rex*"
    - One can redirect and pipe to/from multiple programs

      . after
      ```bash
      rexx myprogram.rex < myinput.txt | rexx myfilter.rex 2>removed.txt | sort
      ```

        - "*myprogram.rex*": input is taken from the text file "*myinput.txt*", its output (*stdout*) gets piped to the next program's ("*myfilter.rex*") *stdin*
        - "*myfilter.rex*": input is taken from *stdout* of the previous program, *stderr* gets redirected to "removed*.txt*", *stdout* gets piped to next program's ("*sort*") *stdin*
        - "*sort*": input is taken from *stdout* of the previous program, output (*stdout*) goes to the screen

<!-- slide # 12 (2026-10-15 09:34) --------------------------- ODP slide # 12 -->
.slide kicker="Excursus #"
# Excursus: "Redirecting Standard Files"

. steps
. static
- "Null device"
    - Any output redirected to the "null device" gets discarded!
        - Unix null device, a file named

          [**/dev/null**]{.fragment .withPrevious}

        - Windows null device, a pseudo file named

          [**nul**]{.fragment .withPrevious}

    - Used in redirections, examples
        . after
        - Show errors only (discard *stdout* output)

          [`rexx myprogram.rex >nul`                       (Windows)]{.fragment .withPrevious}

          [`rexx myprogram.rex >/dev/null`    (Unix)]{.fragment .afterPrevious}

        . after
        - Show output only (discard *stderr* output, i.e. do not show error messages)

          [`rexx myprogram.rex 2>nul`            (Windows)]{.fragment}

          [`rexx myprogram.rex 2>/dev/null`   (Unix)]{.fragment .afterPrevious}

<!-- slide # 13 (2026-10-15 09:34) --------------------------- ODP slide # 13 -->
. slide kicker="Excursus #"
# "Redirection", Example

```rexx
/* myprogram.rex: write input lines (stdin) to output (stdout) */
do until value=""    -- if empty input, leave
   parse pull value  -- read line from stdin, assign to variable "value"
   say value         -- write to stdout
end
```

[Command (Unix, Windows):]{.fragment}

. columns 9 3

. after id=#p13x18

```output
rexx myprogram.rex < myinput.txt
```



. next column

. after id=#p13x17

. file=myinput.txt:
```output
Max
und
Moritz
konnt
der
Lehrer ...
```


. end columns

. after arrow #p13x17 -> #p13x18

. columns 9 3 tight

. click label
Output:

. after
```output
Max
und
Moritz
konnt
der
Lehrer ...
```


. next column

. end columns

<!-- slide # 14 (2026-10-15 09:34) --------------------------- ODP slide # 14 -->
. slide kicker="Excursus #"
# "Redirection", Example

```rexx
/* myprogram.rex: write input lines (stdin) to output (stdout) */
do until value=""    -- if empty input, leave
   parse pull value  -- read line from stdin, assign to variable "value"
   say value         -- write to stdout
end
```

. after
```rexx
/* myfilter.rex: if value contains 'r' then write it to stdout, else to stderr */
do until value=""
   parse pull value           -- read line from stdin, assign to variable "value"
   if pos('r',value)>0 then say value -- write value to stdout
                       else call lineout 'stderr',value   -- write value to stderr
end
```

. click
Command (Windows):

. columns 9 3

. after id=#p14x20

```output
rexx myprogram.rex < myinput.txt | rexx myfilter.rex >nul
```


[Command (Unix):]{.fragment .afterPrevious}

. after id=#p14x21

```output
rexx myprogram.rex < myinput.txt | rexx myfilter.rex >/dev/null
```



. next column

. after id=#p14x19

. file=myinput.txt:
```output
Max
und
Moritz
konnt
der
Lehrer ...
```


. end columns

. after arrow #p14x19 -> #p14x20

. with arrow #p14x19 -> #p14x21

. click label
Output:

. after
```output
Max
und
konnt
```

<!-- slide # 15 (2026-10-15 09:34) --------------------------- ODP slide # 15 -->
. slide kicker="Excursus #"
# "Redirection", Example

```rexx
/* myprogram.rex: write input lines (stdin) to output (stdout) */
do until value=""    -- if empty input, leave
   parse pull value  -- read line from stdin, assign to variable "value"
   say value         -- write to stdout
end
```

. after
```rexx
/* myfilter.rex: if value contains 'r' then write it to stdout, else to stderr */
do until value=""
   parse pull value           -- read line from stdin, assign to variable "value"
   if pos('r',value)>0 then say value -- write value to stdout
                       else call lineout 'stderr',value   -- write value to stderr
end
```

. click
Command (Windows):

. columns 9 3

. after group id=#p15x23

. after mark 1 "2>nul" pen=1
```output
rexx myprogram.rex < myinput.txt | rexx myfilter.rex 2>nul
```

. end group

[Command (Unix):]{.fragment .afterPrevious}

. after group id=#p15x24

. after mark 1 "2>/dev/null" pen=1
```output
rexx myprogram.rex < myinput.txt | rexx myfilter.rex 2>/dev/null
```

. end group


. next column

. after id=#p15x22

. file=myinput.txt:
```output
Max
und
Moritz
konnt
der
Lehrer ...
```


. end columns

. after arrow #p15x22 -> #p15x23

. with arrow #p15x22 -> #p15x24

. click label
Output:

. after
```output
Moritz
der
Lehrer ...
```

<!-- slide # 16 (2026-10-15 09:34) --------------------------- ODP slide # 16 -->
. slide kicker="Excursus #"
# "Redirection", Example

```rexx
/* myprogram.rex: write input lines (stdin) to output (stdout) */
do until value=""    -- if empty input, leave
   parse pull value  -- read line from stdin, assign to variable "value"
   say value         -- write to stdout
end
```

. after
```rexx
/* myfilter.rex: if value contains 'r' then write it to stdout, else to stderr */
do until value=""
   parse pull value           -- read line from stdin, assign to variable "value"
   if pos('r',value)>0 then say value -- write value to stdout
                       else call lineout 'stderr',value   -- write value to stderr
end
```

. click
Command (Windows):

. columns 9 3

. after group id=#p16x26

. after mark 1 "2>nul | sort" pen=1
```output
rexx myprogram.rex < myinput.txt | rexx myfilter.rex 2>nul | sort
```

. end group

[Command (Unix):]{.fragment .afterPrevious}

. after group id=#p16x27

. after mark 1 "2>/dev/null | sort -f" pen=1
```output
rexx myprogram.rex < myinput.txt | rexx myfilter.rex 2>/dev/null | sort -f
```

. end group


. next column

. after id=#p16x25

. file=myinput.txt:
```output
Max
und
Moritz
konnt
der
Lehrer ...
```


. end columns

. after arrow #p16x25 -> #p16x26

. with arrow #p16x25 -> #p16x27

. click label
Output:

. after
```output
der
Lehrer ...
Moritz
```

<!-- slide # 17 (2026-10-15 09:34) --------------------------- ODP slide # 17 -->
. slide reference="Cf. rexxref.pdf (11. Conditions and Condition Traps)" kicker="Conditions #"
# Conditions (Exceptions), 5 (Repeated)

. with mark 2 "NOVALUE NAME ANY" pen=1
. with mark 5 "ANY:" pen=1
```rexx
/* */
SIGNAL ON NOVALUE NAME ANY
SAY Nix                    /* Variable not initialized! */
EXIT 0
ANY:  /* target for any exception     */
  exc_rc   = RC   /* save return code */
  exc_sigl = SIGL /* save line number */
  exc_type = CONDITION("C") /* get exception type */
  CALL say2stderr "REXX 'RC':" exc_rc
  CALL say2stderr "     type:" exc_type
  CALL say2stderr
  CALL say2stderr "  in line:" exc_sigl
  CALL say2stderr "          " SOURCELINE(exc_sigl)
  EXIT -1             /* indicate error   */
SAY2STDERR:           /* write to STDERR: */
  CALL LINEOUT "STDERR", ARG(1)
  RETURN
```

. after label
Output:

. columns 5 7

. with id=#p17x28

```output
C:\temp>rexx test.rex 2>myerrors.txt
```



. next column

. with id=#p17x29

. file="myerrors.txt (contains stderr output):"
```output
REXX 'RC': RC
     type: NOVALUE

  in line: 3
           SAY Nix                    /* Variable not initialized! */
```


. end columns

. after arrow #p17x28 -> #p17x29

<!-- slide # 18 (2026-10-15 09:34) --------------------------- ODP slide # 18 -->
. slide reference="Cf. rexxref.pdf (2.23. RAISE)" kicker="Conditions #"
# Raising Conditions (Exceptions)

- Usually, the Rexx-Interpreter raises conditions …

  [… but you can also do it! :)]{.fragment .afterPrevious}

. click
- **RAISE** statement
    - **RAISE** condition      … creates ("raises") the given condition
. click
- **RAISE PROPAGATE**
    - Can only be given **during** condition (exception) handling
    - Re-creates the same exception in the caller, which allows the caller to also intercept it!

      . click
      ```rexx
      /* demoRaiseSyntax.rex */
      SAY "hallo"
      RAISE SYNTAX 9.1 /* Pretend syntax error # 9.1 */
      EXIT 0
      ```

      . with label
      Output:

      . click
      ```output
      hallo
            3 *-* RAISE SYNTAX 9.1 /* Pretend syntax error # 9.1 */
      Error 9 running C:\temp\demoRaiseSyntax.rex line 3:
          Unexpected WHEN or OTHERWISE
      Error 9.1: WHEN has no corresponding SELECT
      ```

<!-- slide # 19 (2026-10-15 09:34) --------------------------- ODP slide # 19 -->
. slide reference="Cf. rexxref.pdf (2.23. RAISE)" kicker="Conditions #"
# Raising Conditions (Exceptions)

. with mark 2 "SYNTAX" pen=1
. with mark 7 "SYNTAX:" pen=2
```rexx
/**/
SIGNAL ON SYNTAX /* no label, hence "SYNTAX"   */
SAY "hallo"
RAISE SYNTAX 9.1 /* Pretend syntax error # 9.1 */
EXIT 0

SYNTAX:          /* target for any exception   */
  SAY "In SYNTAX-exception handling code."
  EXIT -1
```

. click label
Output:

. after
```output
hallo
In SYNTAX-exception handling code.
```

<!-- slide # 20 (2026-10-15 09:34) --------------------------- ODP slide # 20 -->
. slide reference="Cf. rexxref.pdf (2.23. RAISE)" kicker="Conditions #"
# Raising Conditions (Exceptions)

. with mark 6 "ANY:" pen=1
. with mark 2 "ANY" pen=1
```rexx
/**/
SIGNAL ON ANY    /* no label, hence "ANY"      */
SAY "hallo"
RAISE SYNTAX 9.1 /* Pretend syntax error # 9.1 */
EXIT 0
ANY:  /* target for any exception     */
  exc_rc   = RC   /* save return code */
  exc_sigl = SIGL /* save line number */
  exc_type = CONDITION("C") /* get exception type */
  CALL say2stderr "REXX 'RC':" exc_rc
  CALL say2stderr "     type:" exc_type
  CALL say2stderr
  CALL say2stderr "  in line:" exc_sigl
  CALL say2stderr "          " SOURCELINE(exc_sigl)
  EXIT -1             /* indicate error   */
SAY2STDERR:           /* write to STDERR: */
  CALL LINEOUT "STDERR", ARG(1)
  RETURN
```

. click label
Output:

. after
```output
REXX 'RC': 9
     type: SYNTAX

  in line: 4
           RAISE SYNTAX 9.1 /* Pretend syntax error # 9.1 */
```

<!-- slide # 21 (2026-10-15 09:34) --------------------------- ODP slide # 21 -->
. slide reference="Cf. rexxref.pdf (3.9. ::ROUTINE)" kicker="Routine #"
# Routine Directive (ooRexx)

. steps
. static
- Routine directives
    - Start with a double-colon (**::**)
    - Routine directives represent procedures and functions (= returning a value)
        . static
        - There is no **EXPOSE** statement available to the routine directive!
    - A routine directive is visible from everywhere in the program that defines it
    - If a routine directive has the subkeyword **PUBLIC** then it is made available to all Rexx programs that require or call the program that defines it
- Routine directives are regarded as if they were programs of their own!
    . after
    - Therefore labels, i.e. internal routines, are available **within** routine directives

<!-- slide # 22 (2026-10-15 09:34) --------------------------- ODP slide # 22 -->
. slide reference="Cf. rexxref.pdf (3.9. ::ROUTINE)" kicker="Routine #"

# Routine Directive (ooRexx)

. after mark 9-12 pen=1
```rexx
/**/
SAY  pp("hello")
CALL oha         /* routine is called */
SAY  pp("hello")

EXIT 0
pp : RETURN "<<<" || ARG(1) || ">>>"

:: ROUTINE oha PUBLIC
  SAY  pp("holla")
  EXIT 0
  pp : RETURN "[" || ARG(1) || "]"
```

. click label
Output:

. after
```output
<<<hello>>>
[holla]
<<<hello>>>
```

<!-- slide # 23 (2026-10-15 09:34) --------------------------- ODP slide # 23 -->
.slide kicker="Routine #"
# Routine Directive and Exceptions

- Routine directives are treated as if they were proper programs

  . click mark 4 pen=1
  . click mark 13 pen=2
  ```rexx
  /**/
  SIGNAL ON USER TOO_SMALL /* intercept a user exception */
  CALL checkAge 10
  CALL checkAge 3
  CALL checkAge 7
  EXIT 0
  TOO_SMALL:               /* dealing with the user exception */
    SAY "// caught exception 'TOO_SMALL' \\"
    EXIT -1
  ::ROUTINE checkAge
    PARSE ARG age
    SAY "--> age:" age
    IF age < 6 THEN RAISE USER too_small
               ELSE SAY "--> checked o.k."
    EXIT 0
  ```

  . click label
  Output:

  . after group
  . mark id=#h3 3-4
  . numbered steps=3,4 each=after
  ```output
  --> age: 10
  --> checked o.k.
  --> age: 3
  // caught exception 'TOO_SMALL' \\
  ```

  . with show #h3 pen=3

  . end group

<!-- slide # 24 (2026-10-15 09:34) --------------------------- ODP slide # 24 -->
.slide kicker="Routine #"
# Routine Directive and Exceptions

. after mark 13 pen=1
. after mark 2 pen=2
. after mark 7-9 pen=3
```rexx
/**/
CALL ON USER TOO_SMALL   /* intercept a user exception */
CALL checkAge 10
CALL checkAge 3
CALL checkAge 7
EXIT 0
TOO_SMALL:               /* dealing with the user exception */
  SAY "// caught exception 'TOO_SMALL' \\"
  RETURN
::ROUTINE checkAge
  PARSE ARG age
  SAY "--> age:" age
  IF age < 6 THEN RAISE USER too_small
             ELSE SAY "--> checked o.k."
  EXIT 0
```

. click label
Output:

. after group
. mark id=#h4 5-6
. numbered steps=3,4,5,6 each=after
```output
--> age: 10
--> checked o.k.
--> age: 3
// caught exception 'TOO_SMALL' \\
--> age: 7
--> checked o.k.
```

. with show #h4 pen=4

. end group

<!-- slide # 25 (2026-10-15 09:34) --------------------------- ODP slide # 25 -->
.slide kicker="Routine #"
# Routine Directive and Exceptions

. after mark 12-20 pen=1
. after mark 1 pen=2
```rexx
CALL ON ANY            /* intercept anything that is not caught explicitly */
CALL ON USER TOO_SMALL /* intercept a user exception */
CALL ON USER too_big   /* intercept a user exception */
CALL checkAge 10
CALL checkAge 3
CALL checkAge 7        /* <- this is line # 6        */
EXIT 0

ANY      : SAY "in line:" SIGL "exception:" CONDITION("C"); RETURN
Too_small: SAY "// caught exception 'TOO_SMALL' \\";        RETURN
TOO_BIG  : SAY "// caught exception 'TOO_BIG' \\";          RETURN
::ROUTINE checkAge
  PARSE ARG age
  SAY '--> age:' age
  IF age < 6 THEN RAISE USER too_small
             ELSE IF age > 9 THEN RAISE USER too_big
                             ELSE SAY '--> checked o.k.'

  RAISE USER something_raised
  EXIT 0
```

. click label
Output:

. after group
. mark id=#h3 7
. numbered steps=0,1,2,3,4,5,6,7
```output
--> age: 10
// caught exception 'TOO_BIG' \\
--> age: 3
// caught exception 'TOO_SMALL' \\
--> age: 7
--> checked o.k.
in line: 6 exception: USER SOMETHING_RAISED
```

. with show #h3 pen=3

. end group

<!-- slide # 26 (2026-10-15 09:34) --------------------------- ODP slide # 26 -->
. slide reference="Cf. rexxref.pdf (3.7. ::REQUIRES)" kicker="Requires #"
# Requires Directive (ooRexx)

. steps
. static
- `::Requires "rexxprogram.rex"`{.rexx}
    - Denotes a Rexx program that is required (e.g. "**rexxprogram.rex**")
        . after
        - Hint: for portable purposes, enclose the filename in quotes (Unix is case sensitive)
    - The interpreter will call the required program before carrying out any of the other directives (`::Routine`{.rexx}, `::Class`{.rexx}, `::Method`{.rexx}, …)
    - Thereafter all of its public routines (and public classes!) are made available
        - If another program requires the same required Rexx program later, then the interpreter will immediately make its (now already known) public routines and public classes available, without calling it a second time

<!-- slide # 27 (2026-10-15 09:34) --------------------------- ODP slide # 27 -->
.slide
# CALL-Statement and Public Routines

. columns 6 6

. click mark 4 pen=1
```rexx
/* cmd1.rex */
SAY "In" "cmd1.rex"
CALL cmd2
SAY "In" pp("cmd1.rex")
```


. next column

. click
```rexx
/* cmd2.rex */
SAY "  /1/ In" pp("cmd2.rex")
CALL cmd3
SAY "  /2/ In" pp("cmd2.rex")
EXIT 0

pp :
  RETURN "c2[" || ARG(1) || "]c2"
```

. end columns

. columns 6 6

. click
```rexx
/* cmd3.rex */
SAY "    \1\ In" pp("cmd3.rex")
CALL cmd4
SAY "    \2\ In" pp("cmd3.rex")
EXIT 0

::ROUTINE pp
  RETURN "c3<<" || ARG(1) || ">>c3"
```


. next column

. click
```rexx
/* cmd4.rex */
SAY "          In" pp("cmd4.rex")
EXIT 0

pp :
  RETURN "c4<" || ARG(1) || ">c4"

::ROUTINE pp PUBLIC
  RETURN "c4<<" || ARG(1) || ">>c4"
```

. end columns

. click label
Output:

. after group
. mark id=#h2 7
. numbered steps=0,1,2,3,4,5,6,7
```output
In cmd1.rex
  /1/ In c2[cmd2.rex]c2
    \1\ In c3<<cmd3.rex>>c3
          In c4<cmd4.rex>c4
    \2\ In c3<<cmd3.rex>>c3
  /2/ In c2[cmd2.rex]c2
In c4<<cmd1.rex>>c4
```

. with show #h2 pen=2

. end group

<!-- slide # 28 (2026-10-15 09:34) --------------------------- ODP slide # 28 -->
.slide  kicker="Requires #"
# Requires-Directive and Public Routines

. columns 6 6

. click mark 2 pen=1
```rexx
/* cmd1.rex */
SAY "In" pp("cmd1.rex")

::REQUIRES cmd2.rex
```


. next column

. click
```rexx
/* cmd2.rex */
SAY "  /1/ In" pp("cmd2.rex")
EXIT 0

pp :
  RETURN "c2[" || ARG(1) || "]c2"

::Requires cmd3.rex
```

. end columns

. columns 6 6

. click
```rexx
/* cmd3.rex */
SAY "    \1\ In" pp("cmd3.rex")
EXIT

:: requires cmd4.rex

::ROUTINE pp
  RETURN "c3<<" || ARG(1) || ">>c3"
```


. next column

. click
. after mark 8 pen=2
```rexx
/* cmd4.rex */
SAY "          In" pp("cmd4.rex")
EXIT

pp :
  RETURN "c4<" || ARG(1) || ">c4"

::ROUTINE pp PUBLIC
  RETURN "c4<<" || ARG(1) || ">>c4"
```

. end columns

. columns 6 6 tight

. after label
Output:

. after group
. mark id=#h3 4
. numbered steps=0,1,2,3,4
```output
          In c4<cmd4.rex>c4
    \1\ In c3<<cmd3.rex>>c3
  /1/ In c2[cmd2.rex]c2
In c4<<cmd1.rex>>c4
```

. with show #h3 pen=3

. end group


. next column

. end columns

<!-- slide # 29 (2026-10-15 09:34) --------------------------- ODP slide # 29 -->
# Variables and Values

- Rexx
    . after
    - Variables hold references to string values ("strings") only
        - If a variable is not set, its uppercase name is used as its string value
    . click
    - Arguments for routines (procedures, functions)
        - Only string values (strings) allowed in classic Rexx
. click
- ooRexx
    . after
    - Variables hold references to any values (objects) including string values
    . click
    - Arguments for routines, methods
        . after
        - **USE ARG** statement
            . after
            - Introduced with ooRexx
            . with
            - Fetches arguments by reference (!)
        . click
        - **PARSE ARG** statement
            . after
            - Fetches arguments by their string value only, if necessary requests a string value from objects

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