@DATABASE "arexx.guide"
@MASTER "DOCS:arexx.doc"
@REMARK Tutorial by: South West Amiga Group 1991
@REMARK AmigaGuide® version by E.F.Pritchard. All credits to Original Authors!


@NODE "Main" "Contents"

@{b} South West Amiga Group  Presents: Introduction To ARexx     30th March 1991@{ub}
                    @{b}AmigaGuide® Version by E.F.Pritchard.@{ub}


@{b}Contents@{ub}

@{"Introduction" LINK "INTRODUCTION"},Introduction to this Tutorial.

@{"Chapter 1" LINK "CHAPTER 1"},What is ARexx?,gives an overview of the ARexx language and its
implementation of the Amiga.

@{"Chapter 2" LINK "CHAPTER 2"},Getting Acquainted,tells how to install ARexx on your Amiga and
presents several example programs to illustrate the features of the language.

@{"Chapter 3" LINK "CHAPTER 3"},Elements of the Language,introduces the language structure and
syntax.

@{"Chapter 4" LINK "CHAPTER 4"},Instructions,describes the action statements of ARexx.

@{"Chapter 5" LINK "CHAPTER 5"},Commands,describes the program statements used to communicate
with external programs.

@{"Chapter 6" LINK "CHAPTER 6"},Functions,explains how functions are called and documents the
Built-In Function library.

@{"Chapter 7" LINK "CHAPTER 7"},Tracing and Interrupts,describes the source level debugging
features useful for developing and testing programs.

@{"Chapter 8" LINK "CHAPTER 8"},Parsing and Templates,describes the instructions used to extract
words or fields from strings.

@{"Chapter 9" LINK "CHAPTER 9"},The Resident Process,describes the capabilities of the global
communications and resources manager.

@{"Chapter 10" LINK "CHAPTER 10"},Interfacing to ARexx,describes how to design and implement an
interface between ARexx and an external program.

@{"Appendix A" LINK "APPENDIX A"},Error Messages,lists the error messages issued by the interpreter.

@{"Appendix B" LINK "APPENDIX B"},Limits and Compatibility,discusses the compatibility of ARexx
with the language standard.

@{"Appendix C" LINK "APPENDIX C"},The ARexx Systems Library,documents the functions of ARexx 
systems library.

@{"Appendix D" LINK "APPENDIX D"},The Support Library,documents the library of Amiga specific
functions.

@{"Appendix E" LINK "APPENDIX E"},The ARexx Directories, documents the directories and files 
in an ARexx installation.

@{"Credits" LINK "CREDITS"}

@{"Alphabetical Index" LINK "ALPHABETICAL INDEX"}, Index of all sections in aphabetical order.

@{"Full Contents" LINK "FULL CONTENTS"}, Full Contents of this document.

@ENDNODE

@NODE "INTRODUCTION" "Introduction To Arexx"

@{b} South West Amiga Group  Presents: Introduction To ARexx     30th March 1991@{ub}



Welcome to ARexx,an implementation of the REXX language for the Amiga computer.

ARexx is a powerful programming tool,but because of its clean syntax and

sparse vocabulary is also easy to learn and easy to use.



This tutorial will attempt to give an insight of the apparent ease that ARexx

may be used. The chapters that follow have been organised to provide a gentle

introduction to the language.

@ENDNODE


@NODE "CHAPTER 1" "Chapter 1"

                      @{b}CHAPTER 1  USING THIS TUTORIAL@{ub}


If you are new to the REXX language,or perhaps to programming itself,you should

review chapters 1 through 4 and then play with ARexx by running some of the

sample programs given in @{"chapter 2" LINK "CHAPTER 2"}. Further examples are available in the arexx

drawer of the ARexx Tutorial disk.



If you are already familiar with REXX you may wish to skip directly to chapter

5,which begins to present some of the system-dependent features of this

implementation. A summary of the compatibility of ARexx with the language

definition is contained in @{"Appendix B" LINK "APPENDIX B"}.


@{b}Contents@{ub}

@{"Typographic Conventions" LINK "TYPOGRAPHIC CONVENTIONS"}

@{"Future Directions" LINK "FUTURE DIRECTIONS"}

@{"Language Features" LINK "LANGUAGE FEATURES"}

@{"AREXX on the Amiga" LINK "AREXX ON THE AMIGA"}


@ENDNODE

@NODE "TYPOGRAPHIC CONVENTIONS" "Typographic Conventions"
@{b}Typographic Conventions@{ub}


Describing a language is sometimes difficult because of the multiple and

changing contexts involved. To help clarify the presentation here,a simply

typographic convention has been adopted throughout the document. All of the

terms and words specific to the REXX language,as well as the program examples

and computer input and output,have been set in italic font @{i}like this@{ui}. This

should help to distinguish the language keywords and examples from the

surrounding text.

@ENDNODE

@NODE "FUTURE DIRECTIONS" "Future Developments"
@{b}Future Developments@{ub}


ARexx,like most software products,will probably evolve somewhat over the next

few years as new features are added,old bugs are removed,and market imperatives

become more apparant. While the core language will probably undergo few

modifications,many capabilities will be added to the function libraries

supported by ARexx. Your comments and suggestions for improvements to ARexx are

most welcome.



The author sincerely hopes that other software developers will consider using

ARexx with their products. The advantages of having a rich variety of software

products sharing a common user interface and a common procedural interface

cannot be overstated. This is the underlying promise of the Amiga's

multitasking capability,and that which most sets it apart from other

inexpensive computers.



Example Programs. One of the best ways to learn a computer language is to study

examples written by more experienced programmers. The ARexx Tutorial disk

includes a few example programs in the arexx drawer,and more programs will be

 added in future releases.



If you have written REXX language program(for any computer)that you think would

be of interest to a more general audience,please send it to Fred Fish PD for

consideration. Programs should be of interest either in terms of their specific

funtionality or as an example of programming technique. Each program submitted

should include an author credit and a few lines of commentary on its intended

fuction.




ARexx is a high-level language useful for prototyping,software integration,and

general programming tasks. It is an implementation of the REXX language

described by M.F. Cowlishaw in @{b}The REXX Language:A Practical Approach to

Programming@{ub}(Prentice-Hall,1985),and follow the language definition closely.

ARexx is particularly well suited as a command language. Command programs,

sometimes called "scripts" or "macros",are widely used to extend the predefined

commands of an operating system or to customize an applications program.



As a programming language,ARexx can be useful to a wide cross section of users.

For the novice programmer,ARexx is an easy-to-learn yet powerful language that

serves as a good introduction to programming techniques. Its source-level

debugging facilities will help take some of the mystery out of how programs

work(or don't work,as is more frequently the case.)



For the more sophisticated user,ARexx provides the means to build fully

integrated software packages,combining different applications programs into an

environment tailored to their needs. A common command language among

applications that support ARexx will bring uniformity to procedural interfaces,

much as the Amiga's Intuition provides uniformity in the graphical interface.



Finally,for the software developer,ARexx offers a straightforward way to build

fully programmable applications programs. Developers can concentrate their

efforts on making the basic operations of their programs fast and efficient,and

let the end user add the frills and custom features.

@ENDNODE

@NODE "LANGUAGE FEATURES" "Language Features"
@{b}Language Features@{ub}


Some of the important features of the language are:



@{b}TYPELESS DATA@{ub}. Data are treated as typeless character strings. Variables do not

have to be declared before being used,and all operations dynamically check the

validity of the operands.



@{b}COMMAND INTERFACE@{ub}. ARexx programs can issue commands to external programs that

provide a suitable command interface. Any software package that implements the

command interface is then fully programmable using ARexx,and can be extended

and customized by the end user.



@{b}TRACING AND DEBUGGING@{ub}. ARexx includes source-level debugging facilities that

allow the programmer to see the step-by-step actions of a program as it runs,

thereby reducing the time required to develop and test programs. An internal

interrupt system permits special handling of errors that would otherwise cause

the program to terminate.



@{b}INTERPRETED EXECUTION@{ub}. ARexx programs are run by an interpreter,so separate

compilation and linking steps are not required. This makes it especially useful

for prototyping and as a learning tool.



@{b}FUNCTION LIBRARIES@{ub}. External function libraries can be used to extend the

capabilities of the language or as bridges to other programs. Libraries also

allow ARexx programs to be used as "test drivers" for software development and

testing.



@{b}AUTOMATIC RESOURCE MANAGEMENT@{ub}. Internal memory allocation related to the

creation and destruction of strings and other data structures are handled

automatically.


@ENDNODE
@NODE "AREXX ON THE AMIGA" "AREXX on the Amiga"
@{b}AREXX on the Amiga@{ub}


ARexx was designed to run on the Amiga,and makes use of many of the features of

its multitasking operating system. ARexx programs run as separate tasks and

may communicate with each other or with external programs. The interpreter

follows the design guidelines expected of well-behaved programs in a

multitasking environment: specifically,it uses as little memory as possible and

is careful to return resources to the operating system when they are no longer

needed. Memory requirements were minimized by implementing the entire ARexx

system as a shared library,so that only one copy of the program code must be

loaded.

@ENDNODE


@NODE "CHAPTER 2" "Chapter 2"

                   @{b}CHAPTER 2  GETTING ACQUAINTED@{ub}


This chapter explains how to install ARexx on your Amiga computer and shows

some example programs.


@{b}Contents@{ub}

@{"Installing AREXX" LINK "INSTALLING AREXX"}

@{"AREXX and Workbench" LINK "AREXX AND WORKBENCH"}

@{"Installation" LINK "INSTALLATION"}

@{"Starting the Resident Process" LINK "STARTING THE RESIDENT PROCESS"}

@{"Naming Conventions" LINK "NAMING CONVENTIONS"}

@{"The REXX: Directory" LINK "THE REXX DIRECTORY"}

@{"Program Examples" LINK "PROGRAM EXAMPLES"}

@ENDNODE


@NODE "INSTALLING AREXX" "Installing AREXX"
@TOC "CHAPTER 2"
@{b}Installing AREXX@{ub}



ARexx requires an Amiga computer with at least 256k of memory,and will operate

under V1.2 or V1.3 of the operating system. It uses the double-precision math

library called "mathieeedoubbas.library" that is supplied with the Amiga

WorkBench disk,so make sure that this file is present in your LIBS: directory.

The Tutorial disk includes the language system,some example programs,and a

set of the INCLUDE files required for integrating ARexx with other software

packages.

@ENDNODE

@NODE "AREXX AND WORKBENCH" "AREXX and Workbench"
@TOC "CHAPTER 2"
@{b}AREXX and Workbench@{ub}



ARexx can be installed and loaded from within the icon-based environment

provided by the Amiga WorkBench. However,it is a primarily a text-oriented

language system and requires a good text editor and file management environment

to be most effective. Unless you purchased ARexx as part of an applications

package that includes an integrated editor,you'll probably find it useful to

become familiar with the Commmand Line Interface (CLI)environment on the Amiga.

@ENDNODE


@NODE "INSTALLATION" "Installation"
@TOC "CHAPTER 2"
@{b}Installation@{ub}



The ARexx language system consists of a shared library,a resident program,and

several command utilities. All of the required files are contained in the :c

and :libs directories of the Tutorial disk. ARexx may be installed on any of

the system disks with which it will be used,but first check the :c and :libs

directores of each disk to make sure that there are no naming conflicts.




@{b}1.@{ub} Activate a CLI window.

@{b}2.@{ub} Insert the Tutorial disk into drive 0 and type "@{i}df0:rxinstall@{ui}".

@{b}3.@{ub} At the program prompt,insert the system disk on which ARexx is to be

installed into drive 0.

@{b}4.@{ub} Repeat step 3 as required.


@ENDNODE

@NODE "STARTING THE RESIDENT PROCESS" "Starting the Resident Process"
@TOC "CHAPTER 2"
@{b}Starting the Resident Process@{ub}



ARexx programs are launched by a background program called the resident

process. It can be started by issuing the command rexxmast and must be active

before any ARexx programs can be run. The rexxmast program briefly displays a

small window to announce itself,and then disappears into the background to

await your next request. If you will be using ARexx frequently,you can place

the rexxmast command in the "startup-sequence" file that resides in the system

S: directory. This will start the resident process automatically when you

reboot the computer.



After the resident process has been loaded,ARexx programs can be run from the

CLI by typing the command rx followed by the program name and any arguments.

For example,the sample program Stars.rexx,could be run by typing "@{i}rx :rexx/stars@{ui}."



You may not need to start up the resident process if you are using a software

package that starts it automatically. Applications that use ARexx can test

whether the resident process is active by checking for a public message port

named "REXX." If the port hasn't been opened,the program can issue the rexxmast

command directly.



The resident process can be closed using the command @{i}rxc@{ui};it will then exit as

soon as the last ARexx program finishes execution. Unless you are very short on

memory space,there is usually no reason to close ARexx,as it simply waits in

the background for the next program to run.

@ENDNODE

@NODE "NAMING CONVENTIONS" "Naming Conventions"
@TOC "CHAPTER 2"
@{b}Naming Conventions@{ub}



ARexx programs can be named anything,but adopting a simple naming convention

will make managing the programs much easier. Programs to be run from the CLI

are usually given the file extention .rexx to distinguish them from programs

written in other languages. Programs written as "macros" or "scripts" for a

particular applications program should be given a file extension specific to

that program. For example,a macro written for a communications program called

"@{i}MyComm@{ui}" might be named "@{i}download.myc@{ui}". ARexx uses this file extention when it

searches for a program file to be executed.

@ENDNODE


@NODE "THE REXX DIRECTORY" "The REXX: Directory"
@TOC "CHAPTER 2"
@{b}The REXX: Directory@{ub}



You can designate one directory as the system-wide source for ARexx programs by

defining a REXX: "device" with the assign command. This directory should reside

on a volume that is usually mounted,such as SYS: or a hard disk. For example,

the command "@{i}assign rexx: sys:rexx@{ui}" defines the REXX: device as the :rexx

directory on the system disk. Once defined,the REXX: device is searched after

the current directory when looking for an ARexx program.

@ENDNODE

@NODE "PROGRAM EXAMPLES" "Program Examples"
@TOC "CHAPTER 2"
@{b}Program Examples@{ub}



Before introducing the structure and syntax of the language,let's look at a few

examples of ARexx programs. Readers familiar with other high-level programming

languages should find many points of similarity between ARexx and other

languages. In the examples that follow,new terms are highlighted in the text as

they are introduced,and will be convered in depth in the next few chapters.



These short programs can be created using any text editor and then run from the

Command Line Interface (CLI),or may simply be read as samples of the language.

If the examples are to be run,first complete the installation procedures

outlined in the previous section,and then start the ARexx resident process.

Example programs can then be run by entering,for example,"@{i}rx age@{ui}" at the CLI

prompt.

@{i}
        /* A simple program */

        say 'Hello,World'
@{ui}


This program consists of a comment line that describes the program and an

instruction that displays text on the console. For historical reasons, ARexx

programs begin with a comment line;the initial "@{i}/*@{ui}" says "I'm an ARexx program"

to the interpreter when it searches for a program.



Instructions are language statements that denote a certain action to be

performed,and always start with a symbol,in this case the word say. Symbols are

translated to uppercase when the program is run,so the symbol @{"say" LINK "SAY"} here is

equivalent to @{i}SAY@{ui}. Following @{i}say@{ui} is an example of a string,which is a series of

characters surrounded by quotes ('). Double quotes (") could also have been

used to define the string.



In the next program we'll display a prompt for input and then read some

information from the user.


@{i}
        /* Calculate age in days */

        say 'Please enter your age'

        pull age

        say 'You are about' age*365 'days old'
@{ui}


This program uses the @{"pull" LINK "PULL"} instruction to read a line of input into a variable

called @{i}age@{ui},which is then used with a @{i}say@{ui} instuction. Variables are symbols that

may be assigned a value. The words following say form an expression in which

strings are joined and an arithmetic calculation is performed.



Note that the variable @{i}age@{ui} did not have to be declared as a number;instead,its

value was checked when it was actually used in the expression. To see what

would happen if @{i}age@{ui} wasn't a number,try rerunning the program with a

non-numeric entry for the age. The resulting error message shows the line

number and type of error that occurred,after which the program ends.



The next program introduces the @{"do" LINK "DO"} instruction,which allows program statements

to be executed repeatedly. It also illustrates the exponentiation operator,

which is used to raise a number to an integral power.


@{i}
        /* Calculate some squares and cubes      */

        do i = 1 to 10      /* 10 interations    */

           say i i**2 i**3  /* calculations      */

           end

        say ' all done '
@{ui}


The @{i}do@{ui} instruction causes the statements between the @{i}do@{ui} and @{"end" LINK "END"} instructions to

be executed 10 times. The variable @{i}i@{ui} is the index variable for the loop,and is

incremented by 1 for each iteration. The number following the symbol to is the

limit for the @{i}do@{ui} instruction,and could have been a full expression rather than

just the constant 10. Note that the statements within the loop have been

indented. This is not required by the language,but it makes the program more

readable and is therefore good programming practice.



The subject of the next example is the @{"if" LINK "IF"} instruction,a often-used control

statement that allows statements to be conditionally executed. The numbers from

1 to 10 are classified as even or odd by dividing them by 2 and then checking

the remainder.


@{i}
        /* Even or odd? */

        do i = 1 to 10

           if i//2 = 0 then type = 'even'

                       else type = 'odd'

           say i 'is' type

           end
@{ui}


This example intoduces the @{i}//@{ui} arithmetic operator,which calculates the

remainder after a division operation. The @{i}if@{ui} instruction tests whether the

remainder is 0 and executes the then branch if it is,thereby setting the

variable type to "even." If the remainder was not 0,the alternative @{"else" LINK "ELSE"} branch

is executed and type is set to "odd."



The next example introduces the concept of a function,which is a group of

statements that can be executed by mentioning the function name in a suitable

context. Functions are an important part of most programming languages,as they

allow large,complex programs to be built from smaller modules. Functions are

specified in an expression as a name followed by an open parenthesis. One or

more expressions called arguments may follow the parenthesis;these are used to

pass information to the function for processing.


@{i}
        /* 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*/
@{ui}


The function @{i}square@{ui} is defined in the lines followed the label square: up

through the @{"return" LINK "RETURN"} instruction. Two new instructions are introduced here: @{"arg" LINK "ARG"}

retrieves the value of the argument string,and @{i}return@{ui} passes the functon's

result back to the point where the function was called.



One final example will suffice for now. A new instruction called @{"trace" LINK "TRACE"} is used

here to activate the tracing features of ARexx.


@{i}
        /* 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
@{ui}


When this program is run,the console displays the source lines as they are

excuted,and shows the final results of expressions. This makes it easy to tell

what the program is really doing,and helps reduce the time required to develop

and test a new program. One minor point is illustrated here: the third line

shows two distinct statements separated by a semicolon (;). The semicolon is an

example of a special character,characters that have particular meanings within

ARexx programs.



The following chapters will present further information on the language

statements illustrated here and will introduce others that have not been shown.

Take heart,though;ARexx is a "small" language and there are relatively few

words and rules to learn.

@ENDNODE

@NODE "CHAPTER 3" "Chapter 3"

                    @{b}CHAPTER 3  ELEMENTS OF THE LANGUAGE@{ub}


This chapter introduces the rules and concepts that make up the REXX language.

The intent is not to present a formalized definition,but rather to convey a

practical understanding of how the language elements "fit together" to form

programs.


@{b}Contents@{ub}

@{"Format" LINK "FORMAT"}

@{"Tokens" LINK "TOKENS"}

@{"Comment Tokens" LINK "COMMENT TOKENS"}

@{"Symbol Tokens" LINK "SYMBOL TOKENS"}

@{"String Tokens" LINK "STRING TOKENS"}

@{"Operators" LINK "OPERATORS"}

   @{"Operator Sequences" LINK "OPERATOR SEQUENCES"}

@{"Special Character Tokens" LINK "SPECIAL CHARACTER TOKENS"}

@{"Clauses" LINK "CLAUSES"}

   @{"Clause Continuation" LINK "CLAUSE CONTINUATION"}

   @{"Multiple Clauses" LINK "MULTIPLE CLAUSES"}

   @{"Null Clauses" " LINK "NULL CLAUSES"}

   @{"Label Clauses" LINK "LABEL CLAUSES"}

   @{"Assignment Clauses" LINK "ASSIGNMENT CLAUSES"}

   @{"Instruction Clauses" LINK "INSTRUCTION CLAUSES"}

   @{"Command Clauses" LINK "COMMAND CLAUSES"}

   @{"Clause Classification" LINK "CLAUSE CLASSIFICATION"}

@{"Expressions" LINK "EXPRESSIONS"}

@{"Symbol Resolution" LINK "SYMBOL RESOLUTION"}

@{"Order of Evaluation" LINK "ORDER OF EVALUATION"}   

@{"Numbers and Numeric Precision" LINK "NUMBERS AND NUMERIC PRECISION"}

   @{"Boolean Values" LINK "BOOLEAN VALUES"}

   @{"Numeric Precision" LINK "NUMERIC PRECISION"}

@{"Operators" LINK "OPERATORS2"}

   @{"Arithmetic Operators" LINK "ARITHMETIC OPERATORS"}

   @{"Concatenation Operators" LINK "CONCATENATION OPERATORS"}

   @{"Comparison Operators" LINK "COMPARISON OPERATORS"}

   @{"Logical (boolean) Operators" LINK "LOGICAL (BOOLEAN) OPERATORS"}

@{"Stems and Compound Symbols" LINK "STEMS AND COMPOUND SYMBOLS"}

@{"The Execution Environment" LINK "THE EXECUTION ENVIRONMENT"}

   @{"The External Environment" LINK "THE EXTERNAL ENVIRONMENT"}

   @{"The Internal Environment" LINK "THE INTERNAL ENVIRONMENT"}

@{"Input and Output" LINK "INPUT AND OUTPUT"}

@{"Resource Tracking" LINK "RESOURCE TRACKING"}

@ENDNODE


@NODE "FORMAT" "Format"
@TOC "CHAPTER 3"
@{b}Format@{ub}


ARexx programs are composed of ASCII characters and may be created using any

text editor. No special formatting of the program statements is required or

imposed on the programmer.

@ENDNODE

@NODE "TOKENS" "Tokens"
@TOC "CHAPTER 3"
@{b}Tokens@{ub}


The smallest distinct entities or "words" of the language are called tokens. A

token may be series of characters,as in the symbol MyName,or just a single

character like the "@{i}+@{ui}" operator. Tokens can be categorized into comments,

symbols,strings,operators,and special characters. Each of these groups are

described below.


@ENDNODE

@NODE "COMMENT TOKENS" "Comment Tokens"
@TOC "CHAPTER 3"
@{b}Comment Tokens@{ub}


Any group of characters beginning with the sequence "@{i}/*@{ui}" and ending with "@{i}*/@{ui}"

defines a comment token. Comments may be placed anywhere in a program and cost

little in terms of execution speed,since they are stripped(removed)when the

program is first scanned by the interpreter. Comments may be "nested" within

one another,but each "@{i}/*@{ui}" must have a matching "@{i}*/@{ui}" in the program.

Examples:


@{i}
        /* Your basic comment       */

        /* a  /* nested! */ comment */
@{ui}

@ENDNODE

@NODE "SYMBOL TOKENS" "Symbol Tokens"
@TOC "CHAPTER 3"
@{b}Symbol Tokens@{ub}


Any group of the characters a-z,A-Z,0-9,and .!?$_defines a symbol token.

Symbols are translated to uppercase as the program is scanned by the

interpreter,so the symbol MyName is equivalent to MYNAME. Four types of symbols

are recognized:



        @{b}Fixed symbols@{ub} begin with a digit (0-9) or a period(.).

        @{b}Simple symbols@{ub} do not begin with a digit,and do not contain any

        periods.

        @{b}Stem symbols@{ub} have exactly one period at the end of the symbol name.

        @{b}Compound symbols@{ub} include one or more periods in the interior of the

        name.



Stems and compound symbols have special properties that make them useful for

building arrays and lists.



@{b}SYMBOLS VALUES@{ub}. The value used for a fixed symbol is always the symbol name

itself(as translated to uppercase.) Simple,stem,and compound symbols are called

@{b}variables@{ub} and may be assigned a value;the value used for an uninitialized

variable is just the variable name itself.

Examples:


@{i}
        123.45          /*a fixed symbol        */

        MyName          /*same as MyName        */

        a.              /*a stem symbol         */

        a.1.Index       /*a compound symbol     */
@{ui}


@ENDNODE
@NODE "STRING TOKENS" "String Tokens"
@TOC "CHAPTER 3"
@{b}String Tokens@{ub}


A group of characters beginning and ending with a quote (')or double quote(")

delimiter defines a string token. The delimiter character itself may be

included within the string by a double-delimiter sequence (" or ""). The number

of characters in the string is called its length,and a string of length zero is

called a null string. A string is treated as a literal in an expression;that

is,its value is just the string itself.



Strings followed immediately by an "@{i}X@{ui}" or "@{i}B@{ui}" character that is not part of a

longer symbol are classified as hex or binary strings,respectively,and must be

composed of hexadecimal digits(0-9,A-F) or binary digits(0,1). Blanks are

permitted at byte boundaries for added readability. Hex and binary strings are

convenient for specifying non-ASCII characters and for machine-specific

information like addresses in a program. They are converted immediately to the

"packed" internal form.

Examples:
@{i}
        "Now is the time"       /*a simple example      */

        ""                      /*a null string         */

        'Can't you see??'       /*Can't you see??       */

        '4A 3B CO'X             /*a hex string          */

        '00110111'b             /*binary for '7'        */
@{ui}

@ENDNODE
@NODE "OPERATORS" "Operators"
@TOC "CHAPTER 3"
@{b}Operators@{ub}


The characters  +-*/=><*| may be combined in the sequences shown in @{"Table 3.1" LINK "OPERATOR SEQUENCES"}

to form operator tokens. Operator sequences may include leading,trailing,and

embedded blanks,all of which are removed when the program is scanned. In

addition to the above characters,the blank character as a concatenation

operator if it follows a symbol or string and is not adjacent to an operator or

special character.



Each operator has an associated priority that determines the order in which

operations will be performed in an expression. Operators with higher priorities

before those with lower priorities.

@NEXT "SPECIAL CHARACTER TOKENS"
@ENDNODE

@NODE "OPERATOR SEQUENCES" "Operator Sequences"
@TOC "CHAPTER 3"
@{b}Operator Sequences@{ub}


@{b}SEQUENCE                PRIORITY                OPERATOR DEFINITION@{ub}



                        8                       Logical NOT

+                       8                       Prefix Conversion

-                       8                       Prefix Negation

**                      7                       Exponentiation

*                       6                       Multiplication

/                       6                       Division

%                       6                       Integer Division

//                      6                       Remainder

+                       5                       Addition

-                       5                       Subtration

||                      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

@NEXT "OPERATORS"
@ENDNODE

@NODE "SPECIAL CHARACTER TOKENS" "Special Character Tokens"
@TOC "CHAPTER 3"
@{b}Special Character Tokens@{ub}


The characters :():,are each treated as a separate special character token and

have particular meanings within an ARexx program. Blanks adjacent to these

special characters are removed,except for those preceding an open parenthesis

or following a close parenthesis.



@{b}COLON@{ub} (:). A colon,if preceded by a symbol token,defines a label within the

program. Lavels are locations in the program to which control may be

transferred under various conditions.



@{b}OPENING AND CLOSING PARENTHESES@{ub} (()). Parentheses are used in expressions to

group operators and operands into subexpressions,in order to override the

normal operator primorities. An open parenthesis also serves to identify a

function call within an expression;a symbol or string followed immediately by

an open parenthesis defines a function name. Parentheses must always be

balanced within a statement.



@{b}SEMICOLON@{ub} (;). The semicolon acts as a program statement terminator. Several

statements may be placed on a single source line if separated by semicolons.



@{b}COMMA@{ub} (,). A comma token acs as the continuation character for statements that

must be entered on several source lines. It is also used to separate the

argument expressions in a function call.


@ENDNODE
@NODE "CLAUSES" "Clauses"
@TOC "CHAPTER 3"
@{b}Clauses@{ub}


Tokens are grouped together to form clauses,the smallest language unit that can

be executed as a statement. Every clause in ARexx can be classified as either a

@{"null" LINK "NULL CLAUSES"},@{"label" LINK "LABEL CLAUSES"},@{"assignment" LINK "ASSIGNMENT CLAUSES"},@{"instruction" LINK "INSTRUCTION CLAUSES"},or @{"command" LINK "COMMAND CLAUSES"} clause. The @{"classification" LINK "CLAUSE CLASSIFICATION"} process

is very simple,since no more than two tokens are required to classify any

clause. Assignment,instruction,and command clauses are jointly termed

@{b}statements@{ub}.

@ENDNODE
@NODE "CLAUSE CONTINUATION" "Clause Continuation"
@TOC "CLAUSES"
@{b}CLAUSE CONTINUATION@{ub}. The end of a source line normally acts as the implicit end

of a clause. A clause can be continued on the next source line by ending the

line with a comma (,). The commas is then removed,and the next line is

considered as a continuation of the clause. There is no limit to the number of

continuations that may occur. String and comment tokens are automatically

continued if a line end before the closing delimiter has been found,and the

"newline" character is not considered to be part of the token.

@ENDNODE
@NODE "MULTIPLE CLAUSES" "Multiple Clauses"
@TOC "CLAUSES"

@{b}MULTIPLE CLAUSES@{ub}. Several clauses can be placed on a single line by separating

them with semicolons(;).

@NEXT "EXPRESSIONS"
@ENDNODE

@NODE "NULL CLAUSES" "Null Clauses"
@TOC "CLAUSES"
@{b}Null Clauses@{ub}


Lines consisting only of blanks or comments are called null clauses. They have

no function in the execution of a program,except to aid its readability and to

increment the source line count. Null clauses may appear anywhere in a program.

Example:


@{i}
        /* perform annuity calculations         */
@{ui}

@ENDNODE
@NODE "LABEL CLAUSES" "Label Clauses"
@TOC "CLAUSES"
@{b}Label Clauses@{ub}


A symbol followed immediately by a colon defines a label clause. A label acts

as a placemarker in the program,but no action occurs with the "execution" of a

label. The colon is considered as an implicit clause terminator,so each label

stands as a separate clause. Label clauses may appear anywhere in a program.

Examples:


@{i}
        start:          /* begin execution      */

        syntax:         /* error processing     */
@{ui}

@PREV "CLAUSES"
@ENDNODE
@NODE "ASSIGNMENT CLAUSES" "Assignment Clauses"
@TOC "CLAUSES"
@{b}Assignment Clauses@{ub}


Assignments are identified by a variable symbol followed by an "=" operator. In

this context the operator's normal definition(an equality comparison)is

overridden,and it becomes an assignment operator. The tokens to the right of

the "=" are evaluated as an expression,and the result is assigned to(becomes

the value of)the variable symbol.

Examples:
@{i}
        when= 'Now is the time'

        answ= 3.14 * fact(5)
@{ui}
@ENDNODE
@NODE "INSTRUCTION CLAUSES" "Instruction Clauses"
@TOC "CLAUSES"
@{b}Instruction Clauses@{ub}


Instructions begin with certain keyword symbols,each of which denotes a

particular action to be performed. Instruction keywords are recognized as such

only at the beginning of a clause,and may otherwise be used freely as symbols

(although such use may become confusing at times.) The ARexx instructions are

described in detail in @{"Chapter 4" LINK "CHAPTER 4"}.

Examples:


@{i}
        drop a b c              /* reset variables      */

        say 'please'            /* a polite program     */

        if j > 5 then leave;    /* several instructions */
@{ui}
@ENDNODE

@NODE "COMMAND CLAUSES" "Command Clauses"
@TOC "CLAUSES"
@{b}Command Clauses@{ub}


Commands are any ARexx expression that can't be classified as one of the

preceding types of clauses. The expression is evaluated and the result is

issued as a command to an external host,which might be the native operating

system or an application program. Commands are discussed in @{"Chapter 5" LINK "CHAPTER 5"},and the

details of the host command interface are given in @{"Chapter 10" LINK "CHAPTER 10"}.

Examples:


@{i}
        'delete' 'myfile'       /* a DOS command        */

        'jump' current+10       /* an editor command?   */
@{ui}

@ENDNODE
@NODE "CLAUSE CLASSIFICATION" "Clause Classification"
@TOC "CLAUSES"
@{b}Clause Classification@{ub}


The process by which program lines are divided into clauses and then classified

is important in understanding the operation of an ARexx program. The language

interpreter splits the program source into groups of clauses as the program is

read,using the end of each line as a clause separator and applying the

continuation rule as required. These groups of one or more clauses are then

tokenized,and each clause is classified into one of the above types. Note that

seemingly small syntactic differences may completely change the semantic

content of a statement. For example,


@{i}
        SAY 'Hello, Bill'
@{ui}


is an instruction clause and will display "Hello, Bill" on the console,but


@{i}
        ""SAY 'Hello, Bill'
@{ui}


is a command clause,and will issue "@{i}SAY Hello, Bill@{ui}" as a command to an

external program. The presence of the leading null string changes the

classification from an instruction clause to a command clause.


@ENDNODE

@NODE "EXPRESSIONS" "Expressions"
@TOC "CHAPTER 3"
@{b}Expressions@{ub}


Expression evaluation is an important part of ARexx programs,since most

statements include at least one expression. Expressions are composed of

strings,symbols,operators,and parentheses. @{b}Strings@{ub} are used as literals in an

expression;their value in an operation is just the string itself. @{b}Fixed symbols@{ub}

are also literals (remember that symbols are always translated to uppercase,)

but variable symbols may have an assigned value. @{b}Operator@{ub} tokens represent the

predefined operations of ARexx;each operator has an associated priority that

determines the order in which operations will be performed. @{b}Parentheses@{ub} may be

used to alter the normal order of evaluation in the expression,or to identify

function calls. A symbol or string followed immediately by an open parenthesis

defines the @{b}function name@{ub},and the tokens between the opening and(final)closing

parenthesis form the @{b}argument list@{ub} for the function.



For example,the expression "@{i}J 'fractorial is' fact(J)@{ui}" is composed of a symbol

@{i}J@{ui},a blank operator,the string @{i}'factorial is'@{ui},another blank,the symbol @{i}fact@{ui},an

open parenthesis,the symbol @{i}J@{ui} again,and a closing parenthesis. @{i}FACT@{ui} is a

function name and (@{i}J@{ui}) is its argument list,in this case the single expression

@{i}J@{ui}.
@PREV "CLAUSES"
@ENDNODE

@NODE "SYMBOL RESOLUTION" "Symbol Resolution"
@TOC "CHAPTER 3"
@{b}Symbol Resolution@{ub}


Before the evaluation of an expression can proceed,the interpreter must obtain

a value for each symbol in the expression. For fixed symbols the value is just

the symbol name itself,but variable symbols must be looked up in the current

symbol table. In the example above,the expression after symbol resolution would

be "@{i}3 'factorial is' FACT(3)@{ui}", assuming that the symbol @{i}J@{ui} had the value 3.



Suppose that the example above had been "@{i}FACT(J) 'is' J 'factorial'@{ui}". Would the

second occurrence of symbol @{i}J@{ui} still resolve to 3 in this case? In general,

function calls may have "side effects" that include altering the values of

variables,so the value of @{i}J@{ui} might have been changed by the call to @{i}FACT@{ui}. In

order to avoid ambiguities in the values assigned to symbols during the

resolution process, ARexx guarantees a strict @{b}left-to-right@{ub} resolution order.

Symbol resolution proceeds irrespective of operator priority or parenthetical

grouping;if a function call is found,the resolution is suspended while the

function is evaluated. Note that it is possible for the same symbol to have

more than one value in an expression.

@ENDNODE

@NODE "ORDER OF EVALUATION" "Order of Evaluation"
@TOC "CHAPTER 3"
@{b}Order of Evaluation@{ub}


After all symbol values have been resolved,the expression is evaluated based on

operator priority and subexpression grouping. Operators of higher priority are

evaluated first. ARexx does not guarantee an order of evaluation among

operators of equal priority,and does @{b}not@{ub} employ a "fast path" evaluation of

boolean operators. For example,in the expression


@{i}
        (1 = 2) & (FACT(3) = 6)
@{ui}


the call to the @{i}FACT@{ui} function will be made,although it is clear that the final

result will be 0,since the first term of the AND operation is 0.


@ENDNODE

@NODE "NUMBERS AND NUMERIC PRECISION" "Numbers and Numeric Precision"
@TOC "CHAPTER 3"
@{b}Numbers and Numeric Precision@{ub}


An important class of operands are those representing numbers. Numbers consist

of the characters 0-9,.+-,and blanks;an e or E may follow a number to indicate

exponential notation,in which case it must be followed by a (signed) integer).



Both string tokens and symbol tokens may be used to specify numbers. Since the

language is typeless,variables do not have to be declared as "numeric" before

being used in an arithmetic operation. Instead,each value string is examined

when it is used to verify that it represents a number. The following examples

are all valid numbers:


@{i}
        33

        "   12.3   "

        0.321e12

        ' + 15.'
@{ui}


Note that leading and trailing blanks are permitted,and that blanks may be

embedded between a "+" or "-" sign and the number body(but not within the

body.)

@ENDNODE

@NODE "BOOLEAN VALUES" "Boolean Values"
@TOC "CHAPTER 3"
@{b}Boolean Values@{ub}


The numbers 0 and 1 are used to represent the boolean values False and True,

respectively. The use of a value other than 0 or 1 when a boolean operand is

expected will generate an error. Any number equivalent to 0 or 1,for example

"0.000" or "0.1E1," is also acceptable as a boolean value.

@ENDNODE

@NODE "NUMERIC PRECISION" "Numeric Precision"
@TOC "CHAPTER 3"
@{b}Numeric Precision@{ub}


ARexx allows the basic precision used for arithmetic calculations to be

modified while a program is executing. The number of significant figures used

in arithmetic operations is determined by the Numeric Digits environment

variable, and may be modified using the @{"NUMERIC" LINK "NUMERIC"} instruction.



The number of decimal places used for a result depends on the operation

performed and the number of decimal places in the operands. Unlike many

languages,ARexx preserves trailing zeroes to indicate the precision of the

result. If the total number of digits required to express a value exceeds the

current Numeric Digits setting,the number is formatted in exponential notation.

Two such formats are provided:



In @{i}SCIENTIFIC@{ui} notation,the exponent is adjusted so that a single digit is

placed to the left of the decimal point.



in @{i}ENGINEERING@{ui} notation,the number is scaled so that the exponent is a multiple

of 3 and the digits to the left of the decimal point range from 1 to 999.



The numeric precision and format can be set using the @{"NUMERIC" LINK "NUMERIC"} instruction.

@ENDNODE 

@NODE "OPERATORS2" "Operators"
@TOC "CHAPTER 3"
@{b}Operators@{ub}


Operators can be grouped into four categories:



@{"Arithmetic operators" LINK "ARITHMETIC OPERATORS"} require one or two numeric operands,and produce a numeric

result.

@{"Concatenation operators" LINK "CONCATENATION OPERATORS"} join two strings into a single string.

@{"Comparison operators" LINK "COMPARISON OPERATORS"} require two operands,and produce a boolean(0 or 1) result.

@{"Logical Operators" LINK "LOGICAL (BOOLEAN) OPERATORS"} require one or two boolean operands,and produce a boolean

result.

@ENDNODE

@NODE "ARITHMETIC OPERATORS" "Arithmetic Operators"
@TOC "CHAPTER 3"
@{b}Arithmetic Operators@{ub}


The aritmetic operators are listed in Table 3.2 below. Note the inclusion of

the integer division(%)and remainder(//)operators,along with the usual

arithmetic operations. The result of an arithmetic operation is always formatted

based on the current Numeric Digits setting,and will never have leading or

trailing blanks.



                         @{b}ARITHMETIC OPERATORS@{ub}

        SEQUENCE                PRIORITY                OPERATION

        +                       8                       @{"Prefix Conversion" LINK "PREFIX CONVERSION"}

        -                       8                       @{"Prefix Negation" LINK "PREFIX NEGATION"}

        **                      7                       @{"Exponentiation" LINK "EXPONENTIATION"}

        *                       6                       @{"Multiplication" LINK "MULTIPLICATION"}

        /                       6                       @{"Division" LINK "DIVISION"}

        %                       6                       @{"Integer Division" LINK "INTEGER DIVISION"}

        //                      6                       @{"Remainder" LINK "REMAINDER"}

        +                       5                       @{"Addition" LINK "ADDITION"}

        -                       5                       @{"Subtraction" LINK "SUBTRACTION"}

@NEXT "CONCATENATION OPERATORS"
@ENDNODE

@NODE "PREFIX CONVERSION" "Prefix Conversion"
@TOC "CHAPTER 3"

@{b}PREFIX CONVERSION@{ub}(+). This unary operator converts the operand to and internal

numeric form and formats the result based on the current Numeric Digits

settings. This causes any leading and trailing blanks to be removed,and may

result in a loss of precision.

Examples:


@{i}
        '  3.12 '               ==> 3.12

        1.5001                  ==> 1.500 /* If digits = 3  */
@{ui}
@ENDNODE

@NODE "PREFIX NEGATION" "Prefix Negation"
@TOC "CHAPTER 3"

@{b}PREFIX NEGATION@{ub}(-). This unary operator negates the operand. The result is

formatted based on the current Numeric Digits setting.


Examples:


@{i}
        -'  3.12 '              ==> -3.12

        1.5E2                   ==>-150
@{ui}
@ENDNODE

@NODE "EXPONENTIATION" "Exponentiation"
@TOC "CHAPTER 3"

@{b}EXPONENTIATION@{ub}(**). The left operand is raised to the power specified by the

right operand,which must be an integer. The number of decimal places for the

result is the product of the exponent and the number of decimal places in the

base.

Examples:


@{i}
        2**3                    ==>8

        3**-1                   ==>.333333333

        0.5**3                  ==>0.125
@{ui}
@ENDNODE
@NODE "MULTIPLICATION" "Multiplication"
@TOC "CHAPTER 3"

@{b}MULTIPLICATION@{ub}(*). The product of two numbers is computed. The number of

decimal places for the result is the sum of the decimal places of the operands.

Examples:


@{i}
        12 * 3                  ==>36

        1.5 * 1.50              ==>2.250
@{ui}

@ENDNODE
@NODE "DIVISION" "Division"
@TOC "CHAPTER 3"

@{b}DIVISION@{ub}(/). The quotient of two numbers is computed. The number of decimal

places for the result depends on the current setting of the numeric @{i}DIGITS@{ui}

variable;the number is formatted to the maximum precision required.

Examples:


@{i}
        6 / 3                   ==>2

        8 / 3                   ==>2.66666667
@{ui}

@ENDNODE
@NODE "INTEGER DIVISION" "Integer Division"
@TOC "CHAPTER 3"

@{b}INTEGER DIVISION@{ub}(%). The quotient of two numbers is computed,and the integer

part of the quotient is used as the result.

Examples:


@{i}
        5 % 3                   ==>1

        -8 % 3                  ==>-2
@{ui}

@ENDNODE
@NODE "REMAINDER" "Remainder"
@TOC "CHAPTER 3"

@{b}REMAINDER@{ub}(//). The result is the remainder after the two operands are divided.

The remainder for "@{i}a//b@{ui}" is calculated as "@{i}a-(a%b)*b@{ui}." If both operands are

positive integers,this operation yields the usual "modulo" result.


Examples:


@{i}
        5 // 3                  ==>2

        -5 // 3                 ==>-2

        5.1 // 0.2              ==>0.1
@{ui}

@ENDNODE
@NODE "ADDITION" "Addition"
@TOC "CHAPTER 3"

@{b}ADDITION@{ub}(+). The sum of two numbers is computed. The number of decimal places

for the result is the larger of the decimal places of the operands.

Examples:


@{i}
        12 + 3                  ==>15

        3.1 + 4.05              ==>7.15
@{ui}

@ENDNODE
@NODE "SUBTRACTION" "Subtraction"
@TOC "CHAPTER 3"

@{b}SUBTRACTION@{ub}(-). The difference of two numbers is computed. As in the case of

addition,the number of decimals places for the result is the larger of the

decimal places of the operands.

Examples:


@{i}
        12 - 3                  ==>9

        5.55 - 1.55             ==>4.00
@{ui}

@ENDNODE
@NODE "CONCATENATION OPERATORS" "Concatenation Operators"
@TOC "CHAPTER 3"
@{b}Concatenation Operators@{ub}



ARexx defines two concatenation operators,both of which require two operands.

The first,identified by the operator sequence "||",joins two strings into a

single string with no intervening blank. The second concatenation operation is

identified by the blank operator,and joins the two operand strings with one

intervening blank.



An implicit concatenation operator is recognized when a symbol and a string are

directly abutted in an expression. Concatenation by abuttal uses the "||"

operator,and behaves exactly as though the operator had been provided

explicitly.

Examples:


@{i}
        'why me,' || 'Mom?'             ==>why me,Mom?

        'good' 'times'                  ==>good times

        one'two'three                   ==>ONEtwoTHREE
@{ui}
@PREV "ARITHMETIC OPERATORS"
@ENDNODE
@NODE "COMPARISON OPERATORS" "Comparison Operators"
@TOC "CHAPTER 3"
@{b}Comparison Operators@{ub}


Comparisons are performed in one of three modes,and always result in a boolean

value(0 or 1.)



@{b}Exact comparisons@{ub} proceed character-by-character,including any leading blanks

that may be present.



@{b}String comparisons@{ub} ignore leading blanks,and pad the shorter string with blanks

if necessary.



@{b}Numeric comparisons@{ub} first convert the operands to an internal numeric form

using the current Numeric Digits setting,and then perform a standard arithmetic

comparison.



Except for the exact equality and exact inequality operators,all comparison

operators dynamically determine whether a string of numeric comparison is to be

performed. A numeric comparison is performed if both operands are valid numbers

otherwise,the operands are compared as strings.


                         @{b}COMPARISON OPERATORS@{ub}



SEQUENCE        PRIORITY        OPERATION               MODE



==              3               Exact Equality          Exact

~==             3               Exact Inequality        Exact

=               3               Equality                String/Numeric

~=              3               Inequality              String/Numeric

>               3               Greater Than            String/Numeric

>=,~<           3               Greater Than or Equal   String/Numeric

<               3               Less Than               String/Numeric

<=,~>           3               Less Than or Equal      String/Numeric


@ENDNODE
@NODE "LOGICAL (BOOLEAN) OPERATORS" "Logical (boolean) Operators"
@TOC "CHAPTER 3"
@{b}Logical (boolean) Operators@{ub}


ARexx defines the four logical operations NOT,AND,OR,and Exclusive OR,all of

which require boolean operands and produce a boolean result. Boolean operands

must have values of either 0(False)or 1(True.) An attempt to perform a logical

operation on a non-boolean operand will generate an error.



                         @{b}LOGICAL OPERATORS@{ub}



        SEQUENCE        PRIORITY        OPERATION



        ~               8               NOT(Inversion)

        &               2               AND

        |               1               OR

        ^,&&            1               Exclusive OR


@ENDNODE

@NODE "STEMS AND COMPOUND SYMBOLS" "Stems and Compound Symbols"
@TOC "CHAPTER 3"
@{b}Stems and Compound Symbols@{ub}


Stems and compound symbols have special properties that allow for some

interesting and unusual programming. A compound symbol can be regarded as

having the structure @{i}stem.n1.n2.n3...nk@{ui} where the leading name is a stem symbol

and each node @{i}n1...nk@{ui} is a fixed or simple symbol. Whenever a compound symbol

appears in a program,its name is expanded by replacing each node with its

current value as a (simple) symbol. The value string may consist of any

characters,including embedded blanks,and is not converted to uppercase. The

result of the expansion is a new name that is used in place of the compound

symbol. For example if @{i}j@{ui} has the value of 3 and @{i}k@{ui} has the value 7,then the

compound symbol @{i}a.j.k@{ui} will expand to @{i}A.3.7@{ui}.



Stem symbols provide a way to initialize a whole class of compound symbols.

When an assignment is made to a stem symbol,it assigns that value to all

possible compound symbols derived from the stem. Thus,the value of a compound

symbol depends on the prior assignments made to itself or its associated stem.



Compound symbols can be regarded as a form of "@{b}associative@{ub}" or "@{b}content-

addressable@{ub}" memory. For example,suppose that you needed to store and retrieve

a set of names and telephone numbers. The conventional approach would be to set

up two arrays @{i}NAME@{ui} and @{i}NUMBER@{ui},each indexed by an integer running from one to

the number of entries. A number would be "looked up" by scanning the name array

until the given name was found,say in @{i}NAME.12@{ui},and then retrieving @{i}NUMBER.12@{ui}.

With compound symbols,the symbol @{i}NAME@{ui} could hold the name to be looked-up,and

@{i}NUMBER.NAME@{ui} would then expand to @{i}NUMBER.Bill@{ui}(for example),which be the

corresponding number.



Of course,compound symbols can also be used as conventional indexed arrays,with

the added convenience that only a single assignment(to the stem)is required to

initialize the entire array.


@ENDNODE
@NODE "THE EXECUTION ENVIRONMENT" "The Execution Environment"
@TOC "CHAPTER 3"
@{b}The Execution Environment@{ub}



The ARexx interpreter provides a uniform environment by running each program as

a separate task(actually,as a DOS process)in the Amiga's multitasking operating

system. This allows for a flexible interface between an external host program

and the interpreter,as the host can either proceed concurrently with its

operations or can simply wait for the interpreted program to finish.


@ENDNODE
@NODE "THE EXTERNAL ENVIRONMENT" "The External Environment"
@TOC "CHAPTER 3"
@{b}The External Environment@{ub}


The external environment of a program includes its task(process)structure,

input and output streams,and current directory. When each ARexx task is

created,it inherits the input and output streams and current directory from its

client,the external program that invoked the ARexx program. The current

directory is used as the starting point in a search for a program or data file.



@{b}EXTERNAL PROGRAMS@{ub}. The external environment usually includes one or more

external programs with which the ARexx program may communicate. Any program

that supports a suitable interface can receive commands from ARexx programs.

The command interface is discussed in @{"Chapter 5" LINK "CHAPTER 5"}.


@ENDNODE
@NODE "THE INTERNAL ENVIRONMENT" "The Internal Environment"
@TOC "CHAPTER 3"
@{b}The Internal Environment@{ub}


The internal environment of an ARexx program consists of a static global

structure and one or more storage environments. The global data values are

fixed at a time the program is invoked,and include the @{"argument strings" LINK "ARGUMENT STRINGS"},program

source code,and static data strings. The storage environment includes the

@{"symbol table" LINK "THE SYMBOL TABLE"} used for variable values,the numeric options,trace options,and

host address strings. While the global environment is unique,there may be many

storage environments during the course of the program execution. Each time an

internal function is called a new storage environment is activated and

initialized. The initial values for most fields are inherited from the previous

environment,but values may be changed afterwards without affecting the caller's

environment. The new environment persists until control returns from the

function.

@NEXT "INPUT AND OUTPUT"
@ENDNODE

@NODE "ARGUMENT STRINGS" "Argument Strings"
@TOC "CHAPTER 3"

@{b}ARGUMENT STRINGS@{ub}. A program may receive one or more argument strings when it is

first invoked. These arguments persist for the duration of the program and are

never altered. The number of arguments a program receives depends in part on

the mode of invocation. ARexx programs invoked as commands normally have only

one argument string,although the "command tokenization" option may provide more

than one. A program invoked as a function can have any number of arguments if

called as an internal function,but external functions are limited to a maximum

of 15 arguments.



The argument strings can be retrieved using either the @{i}@{"ARG" LINK "ARG"}@{ui} instruction or the

@{i}@{"ARG()" LINK "ARG()"}@{ui} Built-In function. @{i}ARG()@{ui} can also return the total number of arguments,or

the status(as "exists" or "omitted")of a particular argument.

@ENDNODE

@NODE "THE SYMBOL TABLE" "The Symbol Table"

@{b}THE SYMBOL TABLE@{ub}. Every storage environment includes a symbol table to store

the value strings that have been assigned to variables. This symbol table is

organized as a two-level stores entries for simple and stem symbols,and the

secondary level is used for compound symbols. All of the compound symbols

associated with a particular stem are stored in one tree,with the root of the

tree held by the entry for the stem.



Symbols are not entered into the table until an assignment is made to the

symbol. Once created,entries at the primary level are never removed,even if the

symbol subsequently becomes uninitialized. Secondary trees are released

whenever an assignment is made to the stem associated with the tree.


@ENDNODE

@NODE "INPUT AND OUTPUT" "Input and Output"
@TOC "CHAPTER 3"
@{b}Input and Output@{ub}



Most computer programs require some means of communicating with the outside

world,either to accept input data or to pass along results. The REXX language

includes only a minimal specification of input and output (I/O)operations,

leaving the choice of additional functionality to the language implementor.

This is in keeping with the design of many computer languages. For instance,the

"C" language has no statements dedicated to I/O,but instead relies on a

standardized set of I/O functions.



ARexx extends the I/O facilities fo REXX by providing Built-In functions to

manipulate external files. Files are referenced by a logical name associated

with the file when it is first opened. The initial input and output streams are

given the names @{i}STDIN@{ui} and @{i}STDOUT@{ui}.



ARexx maintains a list of all of the files opened by a program and

automatically closes them when the program finishes. There is no limit to the

number of files that may be open simultaneously.

@PREV "THE INTERNAL ENVIRONMENT"
@ENDNODE

@NODE "RESOURCE TRACKING" "Resource Tracking"
@TOC "CHAPTER 3"
@{b}Resource Tracking@{ub}



ARexx provides complete tracking for all of the dynamically-allocated resources

that it uses to execute a program. These resources include memory space,DOS

files and related structures,and the message port structures supported by

ARexx. The tracking system was designed to allow a program to "bail out" at any

point(perhaps due to an execution error)without leaving any hanging resources.



It is possible to go outside of the interpreter's resource tracking net by

making calls directly to the Amiga's operating system from within an ARexx

program. In these cases it is the programer's responsibility to track and

return all of the allocated resources. ARexx provides a special interrupt

facility so that a program can retain control after an execution error,perform

the required cleanup,and then make an orderly exit. @{"Chapter 7" LINK "CHAPTER 7"} has information

on the ARexx interrupt system.

@ENDNODE

@NODE "CHAPTER 4" "Chapter 4"

                         @{b}CHAPTER 4  INSTRUCTIONS@{ub}



Instruction clauses are identified by an initial keyword symbol that is not

followed by a colon(:)or an equals(=)operator. Each instruction signifies a

specific action,and may be followed by one or more subkeywords,expressions,or

other instruction-specific information. Instruction keywords and subkeywords

are recognized only in this specific context,and are therefore not "reserved

words" in the usual sense of the term. Keywords may be used freely as variables

or function names,although such usage may become confusing at times.



In the descriptions that follow,keywords are shown in uppercase and optional

parts of the instruction are enclosed in brackets. Alternative selections are

separated by a vertical bar(|),and required alternative are enclosed in braces

({}).


@{b}Contents@{ub}

@{"ADDRESS  " LINK "ADDRESS"}        @{"PARSE    " LINK "PARSE"}
@{"ARG      " LINK "ARG"}        @{"PROCEDURE" LINK "PROCEDURE"}
@{"BREAK    " LINK "BREAK"}        @{"PULL     " LINK "PULL"}
@{"CALL     " LINK "CALL"}        @{"PUSH     " LINK "PUSH"}
@{"DO       " LINK "DO"}        @{"QUEUE    " LINK "QUEUE"}
@{"DROP     " LINK "DROP"}        @{"RETURN   " LINK "RETURN"}
@{"ECHO     " LINK "ECHO"}        @{"SAY      " LINK "SAY"}
@{"ELSE     " LINK "ELSE"}        @{"SELECT   " LINK "SELECT"}
@{"END      " LINK "END"}        @{"SHELL    " LINK "SHELL"}
@{"EXIT     " LINK "EXIT"}        @{"SIGNAL   " LINK "SIGNAL"}
@{"IF       " LINK "IF"}        @{"THEN     " LINK "THEN"}
@{"INTERPRET" LINK "INTERPRET"}        @{"TRACE    " LINK "TRACE"}
@{"ITERATE  " LINK "ITERATE"}        @{"UPPER    " LINK "UPPER"}
@{"LEAVE    " LINK "LEAVE"}        @{"WHEN     " LINK "WHEN"}
@{"NOP      " LINK "NOP"}
@{"NUMERIC  " LINK "NUMERIC"}
@{"OPTIONS  " LINK "OPTIONS"}
@{"OTHERWISE" LINK "OTHERWISE"}
@ENDNODE

@NODE "ADDRESS" "ADDRESS"
@TOC "CHAPTER 4"
@{b}ADDRESS@{ub}



Usage: @{b}ADDRESS [Symbol|string|VALUE] [expression]]@{ub}

This instruction specifies a host address for commands issued by the

interpreter. A host address is the name associated with an external program to

which commands can be sent;external hosts are described in @{"Chapter 5" LINK "CHAPTER 5"}. ARexx

maintains two host addresses:a "current" and a "previous"address is lost,and

the "current" and a "previous" value. Whenever a new host address is supplied,

the "previous" address is lost,and the "current" address becomes the "previous"

one. These host addresses are part of a program's storage environment and are

preserved across internal function calls. The current address can be retrieved

with the Built-In function @{"ADDRESS()" LINK "ADDRESS()"}. There are four distinct forms for the

@{b}ADDRESS@{ub} instruction:



@{b}ADDRESS {string | symbol}@{ub} expression. The expression is evaluated and the

result is issued to the host specified by the string or symbol,which is taken

as a literal. No changes are made to the current or previous address strings.

This provides a convenient way to issue a single command to an external host

without disturbing the current host addresses. The return code from the command

is treated as it would be from a command clause.



@{b}ADDRESS {string | symbol}@{ub}. The string or symbol,taken as a literal,specifies

the new host address. The current host address becomes the previous address.



@{b}ADDRESS [VALUE]@{ub} expression. The result of the expression specifies the new host

address,and the current address becomes the previous address. The VALUE keyword

may be omitted if the first token of the expression is not a symbol or string.



@{b}ADDRESS@{ub}. This form interchanges the current and previous hosts. Repeated

execution will therefore "toggle" between the two host addresses.



        Examples:


@{i}
address edit            /* set an new host address      */

address edit 'top'      /* move to the top              */

address VALUE edit n    /* compute a new host address   */

address                 /* swap current and previous    */
@{ui}

@ENDNODE
@NODE "ARG" "ARG"
@TOC "CHAPTER 4"
@{b}ARG@{ub}



Usage: @{b}ARG [template] [,template...]@{ub}

ARG is shorthand form for the @{"PARSE" LINK "PARSE"} @{i}UPPER ARG@{ui} instruction. It retrieves one or

more of the argument strings available to the program,and assigns values to the

variables in the template. The number of argument strings available depends on

the whether the program was invoked as a command or a function. Command

invocations normally have only one argument string,but functions may have up to

15. The argument strings are not altered by the ARG instruction.



The structure and processing of templates is described briefly with the PARSE

instruction,and in greater depth in @{"Chapter 8" LINK "CHAPTER 8"}.

        Example:


@{i}
arg first,second /* fetch arguments */
@{ui}

@ENDNODE
@NODE "BREAK" "BREAK"
@TOC "CHAPTER 4"
@{b}BREAK@{ub}



Usage: @{b}BREAK@{ub}

The BREAK instruction is used to exit from the range of a @{"DO" LINK "DO"} instruction or

from within an @{"INTERPRET" LINK "INTERPRET"}ed string,and is valid only in these contexts. If used

within a DO statement, BREAK exits from the innermost DO statement containing

the BREAK. This contrasts with the otherwise similar @{"LEAVE" LINK "LEAVE"} instruction,which

exits only from an interative DO}.

        Example:


@{i}
do                      /* begin block          */

  if i>3 then break     /* all done?            */

  a = a + 1

  y.a = name

  end                   /* end block            */
@{ui}

@ENDNODE
@NODE "CALL" "CALL"
@TOC "CHAPTER 4"
@{B}CALL@{ub}



Usage: @{b}CALL {symbol | string} [expression] [,expression,...]@{ub}

The CALL instruction is used to invoke an internal or external function. The

function name is specified by the symbol or string token,which is taken as a

literal. Any expressions that follow are evaluated and become the arguments to

the called function. The value returned by the function is assigned to the

special variable @{"RESULT" LINK "RESULT"}. It is not an error if a result string is not returned;

in this case the variable RESULT is @{"DROP" LINK "DROP"}ed(becomes uninitialized.)



The linkage to the function is established dynamically at the time of the call.

ARexx follows a specific search order in attempting to locate the called

function;this process is described in @{"Chapter 6" LINK "CHAPTER 6"}.

        Example:


@{i}
call center name,length+4,'+'
@{ui}
@ENDNODE
@NODE "DO" "DO"
@TOC "CHAPTER 4"
@{b}DO@{ub}



Usage: @{b}DO [var=exp] [To exp] [BY exp]] [FOR exp] [FOREVER] [WHILE exp | UNTIL

exp]@{ub}

The DO instruction begins a group of instructions to be executed as a block.

The range of the DO instruction includes all statements up to and including an

eventual @{"END" LINK "END"} instruction. There are two basic forms of the instruction:



The DO keyword by itself defines a block of instructions to be executed once.



If any iteration specifiers follow the DO keyword,the block of instructions is

executed repeatedly until a termination condition occurs.



An interative DO instruction is sometimes called a "loop",since the interpreter

"loops back" to perform the instruction repeatedly. The various parts of the DO

instruction are described below.



@{b}Initializer expression@{ub}. An initializer expression of the form "@{i}variable=

expression@{ui}" defines the index variable of the loop. The expression is evaluated

when the DO range is first activated,and the result is assigned to the index

variable. On subsequent iterations an expression of the form "@{i}variable =

variable + increment@{ui}" is evaluated,where the increment is the result of the BY

expression. If specified, the initializer expression must precede any of the

other subkeywords.



@{b}BY@{ub} expression. The expression following a BY symbol defines the increment to be

added to the index variable in each subsequent iteration. The expression must

yield a numeric result,which may be positive or negative and need not be an

integer. The default increment is 1.



@{b}TO@{ub} expression. The result of the TO expression specifies the upper(or lower)

limit for the index variable. At each iteration the index variable is compared

to the TO result. If the increment(BY result)is positive and the variable is

greater than the limit,the DO instruction terminates and control passes to the

statement following the @{"END" LINK "END"} instruction. Similarly,the loop terminates if the

increment is negative and the index variable is less than the limit.



@{b}FOR@{ub} expression. The FOR expression must yield a positive whole number when

evaluated,and specifies the maximum number of iterations to be performed. The

loop terminates when this limit is reached irrespective of the value of the

index variable.



@{b}FOREVER@{ub}. The FOREVER keyword can be used if an iterative DO instruction is

required but no index variable is necessary. Presumably the loop will be

terminated by a @{"LEAVE" LINK "LEAVE"} or @{"BREAK" LINK "BREAK"} instruction contained within the loop body.



@{b}WHILE@{ub} expression. The WHILE expression is evaluated at the beginning of each

iteration and must result in a boolean value. The iteration proceeds if the

result is 1;otherwise,the loop terminates.



@{b}UNTIL@{ub} expression. The UNTIL expression is evaluated at the end of each

iteration and must result in a boolean value. The instruction continues with

the next iteration if the result is 0,and terminates otherwise.



The initializer, BY, TO, and FOR expressions are evaluated only when the

instruction is first activated,so the increment and limits are fixed throughout

the execution. Note that a limit need not be supplied;for example,the

instruction "@{i}DO i=1@{ui}" will simply count away forever. Note also that only one of

the WHILE or UNTIL keywords can be specified.

Example:


@{i}
do i=1 to limit for 5 while time <50

   y.1=i*time

   end
@{ui}
@ENDNODE
@NODE "DROP" "DROP"
@TOC "CHAPTER 4"
@{b}DROP@{ub}



Usage: @{b}DROP variable [variable...]@{ub}

The specified variable symbols are reset to their uninitialized state,in which

the value of the variable is the variable name itself. It is not an error to

DROP a variable that is already uninitialized. DROPping a stem symbol is

equivalent to DROPping the values of all possible compound symbols derived from

that stem.

Example:


@{i}
a=123           /* assign a value       */

drop a b        /* drop some            */

say a b         /* ==>A B               */
@{ui}
@ENDNODE
@NODE "ECHO" "ECHO"
@TOC "CHAPTER 4"
@{b}ECHO@{ub}



Usage: @{b}ECHO [expression]@{ub}

The ECHO instruction is a synonym for the @{"SAY" LINK "SAY"} instruction. It displays the

expression result on the console.

Example:


@{i}
echo  "You don't SAY!"
@{ui}
@ENDNODE
@NODE "ELSE" "ELSE"
@TOC "CHAPTER 4"
@{b}ELSE@{ub}



Usage: @{b}ELSE [;] [conditional statement]@{ub}

The ELSE instruction provides the alternative conditional branch for an @{"IF" LINK "IF"}

statement. It is valid only within the range of an IF instruction,and must

follow the conditional statement of the @{"THEN" LINK "THEN"} branch. If the THEN branch wasn't

executed,the statement following the @{"ELSE" LINK "ELSE"} clause is performed.



@{b}Binding@{ub}. ELSE clauses always bind to the nearest(preceding) IF statement. It may

be necessary to provide "dummy" ELSE clauses for the inner IF ranges of a

compound IF statement in order to allow alternative branches for the outer IF

statements. In this case it is not sufficient to follow the else with a

semicolon or a @{"null clause" LINK "NULL CLAUSES"}. Instead,the @{"NOP" LINK "NOP"}(no-operation)instruction can be

used for this purpose.



Example:


@{i}
if 1 > 2 then say 'really?'

         else say 'I thought so'
@{ui}
@ENDNODE
@NODE "END" "END"
@TOC "CHAPTER 4"
@{b}END@{ub}



Usage: @{b}END [variable]@{ub}

The END instruction terminates the range of a @{"DO" LINK "DO"} or @{"SELECT" LINK "SELECT"} instruction. If the

optional variable symbol is supplied,it is compared to the index variable of

the DO statement(which must therefore be iterative). An error is generated if

the symbols do not match,so this provides a simple mechanism for matching the

DO and END statements.

Example:


@{i}
do i=1 to 5             /* index variable is I  */

   say i

   end i                /* end "I" loop         */
@{ui}
@ENDNODE
@NODE "EXIT" "EXIT"
@TOC "CHAPTER 4"
@{b}EXIT@{ub}



Usage: @{b}EXIT [expression]@{ub}

The EXIT instruction terminates the execution of a program,and is valid

anywhere within a program. The evaluated expression is passed back to the

caller as the function or command result.



Results Processing. The processing of the EXIT result depends on whether a

result string was requested by the calling program,and whether the current

invocation resulted from a command or function call. If a result string was

requested,the expression result is copied to a block of allocated memory and a

pointer to the block is returned as the secondary result of the call.



If the caller did not request a result string,and the program was invoked as a

command,then an attempt is made to convert the expression result to an

integer. This value is then returned as the primary result,with 0 as the

secondary result. This allows the EXIT expression to be interpreted as a

"return code" by the caller. Refer to @{"Chapter 10" LINK "CHAPTER 10"} for further information on

the data structures used to return the result string.

Examples:


@{i}
exit                    /* no result needed     */

exit 12                 /* an error return?     */
@{ui}
@ENDNODE
@NODE "IF" "IF"
@TOC "CHAPTER 4"
@{b}IF@{ub}



Usage: @{b}IF expression [THEN] [;] [conditional statement]@{ub}

The IF instruction is used in conjunction with @{"THEN" LINK "THEN"} and @{"ELSE" LINK "ELSE"} instruction to

conditionally execute a statement. The result of the expression must be a

boolean value. If the result is 1 (True),the statement following the THEN

symbol is executed;otherwise,control passes to the next statement(which might

be an ELSE clause.) The THEN keyword need not immediately follow the IF

expression,but may appear as a separate clause. The instruction

is actually analyzed as "@{i}IF expression; THEN; statement;@{ui}." In essence,the IF

statement begins a syntactic range and establishes the test condition that

determines whether subsequent THEN or ELSE clauses will be performed.



Any valid statement may follow the THEN symbol;in particular,a "@{i}@{"DO" LINK "DO"}; ... @{"END" LINK "END"};@{ui}"

group allows a series of statements to be performed conditionally.

Examples:


@{i}
if result < 0 then exit    /* all done?   */
@{ui}
@ENDNODE
@NODE "INTERPRET" "INTERPRET"
@TOC "CHAPTER 4"
@{b}INTERPRET@{ub}



Usage: @{b}INTERPRET expression@{ub}

The expression is evaluated and the result is executed as one or more program

statements. The statements are considered as a group,as though surrounded by a

"@{"DO" LINK "DO"}; ...;@{"END" LINK "END"}" combination. Any statements can be included in the INTERPRETed

source,including DO or @{"SELECT" LINK "SELECT"} instruction.



An INTERPRET instruction activates a control range when it is executed,which

serves as a "fence" for @{"LEAVE" LINK "LEAVE"} and @{"ITERATE" LINK "ITERATE"} instructions. These instructions can

therefore be used only with DO-loops defined within the INTERPRET. The @{"BREAK" LINK "BREAK"}

instuction can be used to terminate the processing of INTERPRETed statements.

While it is not an error to include label clauses within the interpreted

string,only those labels defined in the original source code are searched

during a transfer of control.



The INTERPRET instruction can be used to solve programming problems in

interesting and novel ways. Programs can be constructed dynamically and then

executed using this instruction,or program fragments may be passed as arguments

to functions,which then INTERPRET them.

Example:


@{i}
inst = 'say'            /* an instruction       */

interpret inst hello    /* ..."say HELLO"       */
@{ui}
@ENDNODE
@NODE "ITERATE" "ITERATE"
@TOC "CHAPTER 4"
@{b}ITERATE@{ub}



Usage: ITERATE [variable]

The ITERATE instruction terminates the current iteration of a @{"DO" LINK "DO"} instruction

and begins the next iteration. Effectively,control passes to the @{"END" LINK "END"} statement

and then(depending on the outcome of the @{"UNTIL" LINK "UNTIL"} expression)back to the DO

statement. The instruction normally acts on the innermost iterative DO range

containing the instruction. An error results if the @{"LEAVE" LINK "LEAVE"} instruction is not

contained within an iterative DO instruction.



The optional variable symbol specifies which DO range is to be exited,in the

event that several nested ranges exist. The variable is taken as a literal and

must match the index variable of a currently active DO instruction. An error

results if no such matching DO instruction is found.



Example:


@{i}
        do i=1 to 3

           if i=j then iterate i

           end
@{ui}
@ENDNODE
@NODE "LEAVE" "LEAVE"
@TOC "CHAPTER 4"
@{b}LEAVE@{ub}



Usage:@{b}LEAVE [variable]@{ub}

LEAVE forces an immediate exit from the iterative @{"DO" LINK "DO"} range containing the

instruction. An error results if the @{"LEAVE" LINK "LEAVE"} instruction is not contained within

an iterative DO instruction.



The optional variable symbol specifies which DO range is to be exited,in the

event that several nested ranges exist. The variable is taken as a literal and

must match the index variable of a currently active DO instruction. An error

results if no such matching DO instruction is found.

Example:


@{i}
        do i=1 to limit

           if i > 5 then leave  /* maximum iterations  */

           end
@{ui}
@ENDNODE
@NODE "NOP" "NOP"
@TOC "CHAPTER 4"
@{b}NOP@{ub}



Usage: @{b}NOP@{ub}

The NOP or "no-operation" instruction does just that:nothing. It is provided to

control the binding of @{"ELSE" LINK "ELSE"} clauses in compound @{"IF" LINK "IF"} statements.

Example:


@{i}
        if i=j then             /* first (outer) IF     */

           if j=k then a=o      /* inner IF             */

                else nop        /* binds to inner IF    */

           else a=a+1           /* binds to outer IF    */
@{ui}
@ENDNODE
@NODE "NUMERIC" "NUMERIC"
@TOC "CHAPTER 4"
@{b}NUMERIC@{ub}



Usage: @{b}NUMERIC {DIGITS | FUZZ} expression@{ub}

   or: @{b}NUMERIC FORM {SCIENTIFIC | ENGINEERING}@{ub}

This instruction sets options relating to the numeric precision and format. The

valid forms of the NUMERIC instruction are:



@{b}NUMERIC DIGITS@{ub} expression. Specifies the number of digits of precision for

arithmetic calculations. The expression must evaluate to a positive whole

number.



@{b}NUMERIC FUZZ@{ub} expression. Specifies the number of digits to be ignored in

numeric comparison operations. This must be a positive whole number that is

less than the current DIGITS setting.



@{b}NUMERIC FORM SCIENTIFIC@{ub}. Specifies that numbers that require exponential

notation be expressed in SCIENTIFIC notation. The exponent is adjusted so that

the mantissa (for non-zero) numbers) is between 1 and 10. This is the default

format.



@{b}NUMERIC FORM ENGINEERING@{ub}. Selects ENGINEERING format for numbers that require

exponential notation. ENGINEERING format normalizes a number so that its

exponent is a multiple of three and the mantissa(if not 0)is between 1 and

1000.



The numberic options are preserved when an internal function is called.

Examples:


@{i}
        numeric digits 12               /* precision            */

        numeric form scientific         /* format               */
@{ui}
@ENDNODE
@NODE "OPTIONS" "OPTIONS"
@TOC "CHAPTER 4"
@{b}OPTIONS@{ub}



Usage: @{b}OPTIONS [FAILAT expression]@{ub}

   or: @{b}OPTIONS [PROMPT expression]@{ub}

   or: @{b}OPTIONS [RESULTS]@{ub}

The OPTIONS instruction is used to set various internal defaults. The FAILAT

expression sets the limit at or above which command return codes will be

signalled as errors,and must evaluate to an integer value. The PROMPT

expression provides a string to be used as the prompt with the @{"PULL" LINK "PULL"} (or

@{"PARSE" LINK "PARSE"} PULL)instruction. The RESULTS keyword indicates that the interpreter

should request a result string when it issues commands to an external host.



The internal options controlled by this instruction are preserved across

function calls,so an OPTIONS instruction can be issued within an internal

function without affecting the callers environment. If no keyword is specified

with the OPTIONS instuction,all controlled options revert to their default

settings.

Example:


@{i}
        options failat 10

        options prompt "Yes Boss?"

        options results
@{ui}
@ENDNODE
@NODE "OTHERWISE" "OTHERWISE"
@TOC "CHAPTER 4"
@{b}OTHERWISE@{ub}



Usage: @{b}OTHERWISE [;] [conditional statement]@{ub}

This instruction is valid only within the range of a @{"SELECT" LINK "SELECT"} instruction,and

must follow the "@{"WHEN" LINK "WHEN"} ... @{"THEN" LINK "THEN"}" statements. If none of the preceding WHEN

clauses have succeeded,the statement following the OTHERWISE instruction is

executed. An OTHERWISE is not mandatory within a SELECT range. However,an error

will result if the OTHERWISE clause is omitted and none of the WHEN

instructions succeed.

Example:


@{i}
        select

                when i=1 then say 'one'

                when i=2 then say 'two'

                otherwise say 'other'

                end
@{ui}

@ENDNODE
@NODE "PARSE" "PARSE"
@TOC "CHAPTER 4"
@{b}PARSE@{ub}



Usage: @{b}PARSE [UPPER] inputsorce [template] [,template...]@{ub}

The PARSE instruction provides a mechanism to extract one or more substrings

from a string and assign them to variables. The input string can come from a

variety of sources,including argument strings,an expression,or from the

console. The template provides both the variables to be given values and the

way to determine the value strings. The template may be omitted if the

instruction is intended only to create the input string. The different options

of the instruction are described below.



@{b}INPUT SOURCES@{ub}



The sources for the input strings are specified by the keyword symbols listed

below. When multiple templates are supplied,each template receives a new input

string, although for some source options the new string will be identical to

the previous one. The input source string is copied before being parsed,so the

original strings are never altered by the parsing process.



@{b}UPPER@{ub}. This optional keyword may be used with any of the input sources,and

specifies that the input string is to be translated to uppercase before being

parsed. It must be the first token following PARSE.



@{b}ARG@{ub}. This input option retrieves the argument strings supplied when the program

was invoked. Command invocations normally have only a single argument string,

but functions may have up to 15 argument strings. Multiple templates may be

given to retrieve successive argument strings.



@{b}EXTERNAL@{ub}. The input strings is read from the console. If multiple templates are

supplied,each template will read a new string. This source option is the same

as @{"PULL" LINK "PULL"}.



@{b}NUMERIC@{ub}. The current numeric options are placed in a string in the order

DIGITS,FUZZ,and FORM,separated by a single space.



@{b}PULL@{ub}. Reads a string from the input console. If multiple templates are

supplied,each template will read a new string.



@{b}SOURCE@{ub}. The "source" string for the program is retrieved. This string is

formatted as "{COMMAND | FUNCTION} {0 | 1} called resolved ext host." The first

token indicates whether the program was invoked as a command or as a function.

The second token is a boolean flag indicating whether a result string was

requested by the caller. The called token is the name used to invoke this

program,while the resolved token is the final resolved name of the program. The

ext token is the file extension to be used for searching(the default is

"REXX"). Finally,the host token is the initial host address for commands.



@{b}VALUE@{ub} expression @{b}WITH@{ub}. The input string is the result of the supplied

expression. The WITH keyword is required to separate the expression from the

template. The expression result may be parsed repeatedly by using multiple

templates,but the expression is not reevaluated.



@{b}VAR@{ub} variable. The value of the specified variable is used as the input string.

When multiple templates are provided,each template uses the current value of

the variable.



This value may change if the variable is included as an assignment target in

any of the templates.



@{b}VERSION@{ub}. The current configuation of the ARexx interpreter is supplied in the

form "ARexx version cpu mpu video freq". The version toekn is the release level

of the interpreter,formatted as V1.0. The cpu token indicates the processor

currently running the program,and will be one of the values 68000,68010,or

68020. The mpu token will be either NONE or 68881 depending on whether a math

coprocessor is available on the system. The video token will indicate either

NTSC or PAL,and the freq token gives the clock(line)frequency as either 60HZ or

50 HZ.



@{b}TEMPLATES@{ub}



Parsing is controlled by a template,which may consist of symbols,strings,

operators,and parentheses. During the parsing operation the input string is

split into substrings that are assigned to the variable symbols in the

template. The process continues until all of the variables in the template have

been assigned a value;if the input string is "used up",any remaining variables

are given null values.



Templates are described in depth in @{"Chapter 8" LINK "CHAPTER 8"},so only a simplified description

is presented here. The goal of the parsing operation is to associate a

"current" and "next" position with each variable symbol in the template. The

substring between these positions is then assigned as the value to the

variable. There are three basic methods used to determine the value strings.



@{b}PARSING BY TOKENIZATION@{ub}. When a variable in the template is followed

immediately by another variable,the value string is determined by breaking the

input string into words separated by blanks. Each word is assigned to a

variable in the template.



Values determined by tokenization will never have leading or trailing blanks.

Normally the last variable in the template receives the untokenized remainder

of the input string,since it is not followed by a symbol. A "placeholder"

symbol,signified by a period(.),may be used to force tokenization. Placeholders

behave like variables in the template except that they are never actually

assigned a value.

Example:


@{i}
        /* Numeric string is: "9 0 SCIENTIFIC"  */

        parse numeric digits fuzz form .

        say digits              /* =>9                  */

        say fuzz                /* =>0                  */

        say from                /*=> SCIENTIFIC        */
@{ui}


@{b}PARSING BY POSITION@{ub}. If the fields in the input string have known positions,

value strings can be specified by absolute or relative positions. Relative

positions are indicated by a number preceded by a "+" or "-" operator. Each

positional marker updates the scan position in the string. The value assigned

to a variable is the string from the current position up to,but not including,

the next position in the string.



Example:


@{i}
        /* assume argument is "1234567890"              */

        parse arg 1 a 3 b +2 1 c

        say a b c               /* ==> 12 34 1234567890 */
@{ui}


@{b}PARSING WITH PATTERNS@{ub}. Fields in the input string separated by specific

characters or strings can be parsed using a pattern,which is matched against

the input string. A pattern is specified in the template as a string token,or

alternatively as a symbol enclosed in parentheses. The position in the parse

string matched by the pattern determines the value strings. The pattern is

removed from the input string when a match is found;this is the only parsing

operation that modifies the input string.

Example:


@{i}
        check = 'one,two,three'

        parse var check a ',' b ',' c

        say a b c       /* ==> one two three    */
@{ui}
@ENDNODE
@NODE "PROCEDURE" "PROCEDURE"
@TOC "CHAPTER 4"
@{b}PROCEDURE@{ub}



Usage:@{b}PROCEDURE [EXPOSE variable [variable...]]@{ub}

The PROCEDURE instruction is used within an internal function to create a new

symbol table. This protects the symbols defined in the caller's environment

from being altered by the execution of the function. PROCEDURE is usually the

first statement within the function,although it is valid anywhere withing the

function body. It is an error to execute two PROCEDURE statements within the

function.



@{b}EXPOSING VARIABLES@{ub}. The @{b}EXPOSE@{ub} subkeyword provides a selective mechanism for

accessing the caller's symbol table,and for passing global variables to a

function. The variables following the EXPOSE keyword are taken to refer to

symbols in the caller's table. Any subsequent changes made to these variables

will be reflected in the caller's environment.



The variables in the EXPOSE list may include stems or compound symbols,in which

case the ordering of the variables becomes significant. The EXPOSE list is

processed from left to right,and compound symbols are expanded based on the

values in effect in the new generation. For example,suppose that the value of

the symbol J in the previous gneration is 123,and that J is unitialized in the

new generation. Then @{i}PROCEDURE EXPOSE J A.J@{ui} will expose J and A.123,whereas

@{i}PROCEDURE EXPOSE A.J J@{ui} will expose A. J. and J. Exposing a stem has the effect

of exposing all possible compound symbols derived from that stem.

Example:


@{i}
        fact: procedure         /* a recursive function */

           arg i

           if i <=1

              then return 1

              else return i*fact(i-1)
@{ui}
@ENDNODE
@NODE "PULL" "PULL"
@TOC "CHAPTER 4"
@{b}PULL@{ub}



Usage:@{b}PULL [template] [,template...]@{ub}

This is a shorthand form of the @{"PARSE UPPER PULL" LINK "PARSE"} instruction. It reads a string

from the input console,translates it to uppercase,and parses it using the

template. Multiple strings can be ready by supplying additional templates. The

instruction will read from the console even if no template is given.



Templates are described briefly with the PARSE instruction and in greater depth

in @{"Chapter 8" LINK "CHAPTER 8"}.

Example:


@{i}
        pull first last.        /* read names           */
@{ui}
@ENDNODE
@NODE "PUSH" "PUSH"
@TOC "CHAPTER 4"
@{b}PUSH@{ub}



Usage: @{b}PUSH [expression]@{ub}

The PUSH instruction is used to prepare a stream of data to be ready by a

command shell or other program. It appends a "newline" to the result of the

expression and then stacks or "pushes" it into the STDIN stream. Stacked lines

are placed in the stream in "last-in, first-out" order,and are then available

to be ready just as though they had been entered interactively. For example,

after issuing the instructions


@{i}
        push line 1

        push line 2

        push line 3
@{ui}


the steam would be read in the order "line 3," "line 2" and "line 1."



There are several restrictions governing the use of the PUSH instruction and

its alter ego @{"QUEUE" LINK "QUEUE"}. These instructions use a special I/O mechanism to

accomplish their task,and as a result can be used only with an interactive

(stream-model) I/O device like a console or pipe. The stream must be managed by

with a DOS handler that supports the special @{b}ACTION_STACK@{ub} (for PUSH) or

@{b}ACTION_QUEUE@{ub} (for QUEUE) command.



PUSH allows the STDIN stream to be used as a private scratchpad to prepare data

for subsequent processing. For example,several files could be concatenated with

delimiters between them by simply reading the input files,PUSHing the lines

into the stream,and inserting a delimiter where required. Once the stacked

lines are exhausted,the stream reverts to its normal source of data.

Example:


@{i}
        /* Stack commands for compile and link*/

        push "blink c.o+main.o library amiga.lib to myprog"

        push "cc main"
@{ui}
@ENDNODE
@NODE "QUEUE" "QUEUE"
@TOC "CHAPTER 4"
@{b}QUEUE@{ub}



Usage:@{b}QUEUE [expression]@{ub}

The QUEUE instruction is used to prepare a stream of data to be read by a

command shell or other program. It is very similar to the preceding @{"PUSH" LINK "PUSH"}

instruction,and differs only that the data lines are placed in the STDIN stream

in "first-in,first-out" order. In this case the instruction


@{i}
        queue line 1

        queue line 2

        queue line 3
@{ui}


would be read in the order "line 1," "line 2," and "line 3." The QUEUEd lines

always precede all interactivly-entered lines,and always follow any PUSHed

(stacked)lines.



The same restriction noted with the use of the PUSH instruction apply to the

QUEUE instruction. The queueing mechanism uses the @{b}ACTION_QUEUE@{ub} command,so the

DOS handler associated with the STDIN stream must support this command.



In most cases the choice of whether to use PUSH or QUEUE is just a matter of

convenience or personal preference. Each of them provides a "scratch pad"

facility similar to that provided by an I/O pipe,but useful within one program

or task rather than just for interprocess communications.

Example:


@{i}
        /* Queue commands for compile and link */

        queue "cc main"

        queue "blink c.o+main.o library amiga.lib to myprog"
@{ui}
@ENDNODE
@NODE "RETURN" "RETURN"
@TOC "CHAPTER 4"
@{b}RETURN@{ub}

Usage: @{b}RETURN@{ub}

RETURN is used to leave a function and return control to the point of the

previous function invocation. The evaluated expression is returned as the

function result. If an expression is not supplied,an error may result in the

caller's environment. Functions called from within an expression must return a

result string,and will generate an error if no result is available. Function

invoked by the @{"CALL" LINK "CALL"} instruction need not return a result.



A RETURN issued from the base environment of a program is not an error,and is

equivalent to an EXIT instruction. Refer to the @{"EXIT" LINK "EXIT"} instruction for a

description of how result strings are passed back to an external caller.

Example:


@{i}
        return 6*7              /*the answer    */
@{ui}
@ENDNODE
@NODE "SAY" "SAY"
@TOC "CHAPTER 4"
@{b}SAY@{ub}



Usage:@{b}SAY [expression]@{ub}

The result of the evaluated expression is written to the output console,with a

"newline" character appended. If the expression is omitted,a null string is

sent to the console.

Example:


@{i}
        say 'The anwer is ' value
@{ui}
@ENDNODE
@NODE "SELECT" "SELECT"
@TOC "CHAPTER 4"
@{b}SELECT@{ub}



Usage:@{b}SELECT@{ub}

This instruction begins a group of instructions containing one or more @{"WHEN" LINK "WHEN"}

clauses and possibly a single @{"OTHERWISE" LINK "OTHERWISE"} clause,each followed by a conditional

statement.



Only one of the conditional statements within the SELECT group will be

executed. Each WHEN statement is executed in succession until one succeeds;if

none succeeds,the OTHERWISE statement is executed. The SELECT range must be

terminated by an eventual @{"END" LINK "END"} statement.

Example:


@{i}
        select

                when i=1 then say 'one'

                when i=2 then say 'two'

                otherwise say 'other'

                end
@{ui}
@ENDNODE
@NODE "SHELL" "SHELL"
@TOC "CHAPTER 4"
@{b}SHELL@{ub}



Usage:@{b}SHELL [symbol | string] [expression]@{ub}

The SHELL instruction is a synonym for the @{"ADDRESS" LINK "ADDRESS"} instruction.

Example:


@{i}
        shell edit      /* set host to 'EDIT'   */
@{ui}
@ENDNODE
@NODE "SIGNAL" "SIGNAL"
@TOC "CHAPTER 4"
@{b}SIGNAL@{ub}



Usage: @{b}SIGNAL {ON |OFF} condition@{ub}

   or: @{b}SIGNAL [VALUE] expression@{ub}

There are two forms of the SIGNAL instruction. The first form illustrated

controls the state of the internal interrupt flags. Interrupts allow a program

to detect and retain control when certain errors occur,and are discussed in

@{"Chapter 7" LINK "CHAPTER 7"}. In this form SIGNAL must be followed by one of the keywords ON or

OFF and one of the condition keywords listed below. The interrupt flag

specified by the condition symbol is then set to the indicated state. The valid

signal conditions are:



@{b}BREAK_C@{ub}  A "control-C" break was detected.

@{b}BREAK_D@{ub}  A "control-D" break was detected.

@{b}BREAK_E@{ub}  A "control-E" break was detected.

@{b}BREAK_F@{ub} A "control-F" break was detected.

@{b}ERROR@{ub} A Host command returned a non-zero code.

@{b}HALT@{ub}  An external HALT request was detected.

@{b}IOERR@{ub} An error was detected by the I/O system.

@{b}NOVALUE@{ub} An uninitialized variable was used.

@{b}SYNTAX@{ub}  A syntax or execution error was detected.



The condition keywords are interpreted as labels to which control will

transferred if the selected condition occurs. For example,if the ERROR

interrupt is enabled and a command returns a non-zero code,the interpreter will

transfer control to the label ERROR:. The condition label must of course be

defined in the program;otherwise,an immediate SYNTAX error results and the

program exits.



In the second form of the instruction,the tokens following SIGNAL are evaluated

as an expression. An immediate interrupt is generated that transfers control to

the label specified by the expression result. The instruction thus acts as a

"computed goto."



@{b}INTERRUPTS@{ub}. Whenever an interrupt occurs,all currently active control ranges

(@{"IF" LINK "IF"},@{"DO" LINK "DO"},@{"SELECT" LINK "SELECT"},@{"INTERPRET" LINK "INTERPRET"},or interactive @{"TRACE" LINK "TRACE"}) are dismantled before the

transfer of control. Thus,the transfer cannot be used to jump into the range of

a DO-loop or other control structure. Only the control structures in the

current environment are affected by a SIGNAL condition,so it is safe to SIGNAL

from within an internal function without affecting the state of the caller's

environment.



@{b}SPECIAL VARIABLES@{ub}. The special variable @{b}SIGL@{ub} is set to the current line number

whenever a transfer of control occurs. The program can inspect SIGL to

determine which line was being executed before the transfer. If an ERROR or

SYNTAX condition causes an interrupt,the special variable @{b}RC@{ub} is set to the

error code that triggered the interrupt. For the ERROR condition,this code is

usually an error secerity level. The SYNTAX condition will always indicate an

ARexx error code.

Examples:


@{i}
        signal on error         /* enable interrupt     */

        signal off syntax       /* disable SYNTAX       */

        signal start            /* goto START           */
@{ui}
@ENDNODE
@NODE "THEN" "THEN"
@TOC "CHAPTER 4"
@{b}THEN@{ub}



Usage:@{b}THEN[;] [conditional statement]@{ub}

The THEN instruction must be the next statement following an @{"IF" LINK "IF"} or @{"WHEN" LINK "WHEN"}

instruction,and is valid only in that context. It tests whether the preceding

expression evaluated to 1(True),in which case the conditional statement

following the THEN is performed. If the expression result was a 0(False),the

conditional statement is skipped.



Example:


@{i}
        if i=j

           then say 'equal'

           else say 'not equal'
@{ui}
@ENDNODE
@NODE "TRACE" "TRACE"
@TOC "CHAPTER 4"
@{b}TRACE@{ub}



Usage:@{b}TRACE [symbol|string|[[VALUE] expression]]@{ub}

The TRACE instruction is used to set the internal tracing mode. If a symbol or

string is supplied,it is taken as a literal. Otherwise,the tokens following the

@{b}VALUE@{ub} keyword are evaluated as an expression. The @{b}VALUE@{ub} keyword can be omitted

if the expression doesn't start with a symbol or string token.



In either case the result string is converted to uppercase and checked first

for one of the "alphabetic" options. The valid alphabetic options are @{b}ALL,

COMMANDS,ERRORS,INTERMEDIATES,LABELS,RESULTS,@{ub}and @{b}SCAN@{ub}. These can be spelled out

in full or shortened to the initial character,and are described in @{"Chapter 7" LINK "CHAPTER 7"}.

If the result doesn't match any of these options,the interpreter attempts to

convert it to an integer. A conversion failure here will be reported as an

error.



@{b}PREFIX CHARACTERS@{ub}. Two special symbol characters may precede any of the

alphabetic keywords. The "?" character interactive tracing,and the "!"

character controls command inhibition. These characters act as "toggles" to

alternatively select and de-select the respective modes. Any number of prefix

characters may precede an alphabetic option. Interactive tracing and command

inhibition are described in @{"Chapter 7" LINK "CHAPTER 7"}.



@{b}NUMERIC OPTION@{ub}. If the specified trace option is a negative whole number,it is

accepted as a trace suppression count. The suppression count is the number of

clauses(that would otherwise be traced)to be passed over before resuming the

tracing display. Suppression counts are ignored execept during interactive

tracing.

Examples:


@{i}
        trace ?r                /* interactive RESULTS  */

        trace off

        trace -20               /* skip 20 clauses      */
@{ui}
@ENDNODE
@NODE "UPPER" "UPPER"
@TOC "CHAPTER 4"
@{b}UPPER@{ub}



Usage:@{b}UPPER variable [variable...]@{ub}

The values of the variables in the list are converted to uppercase. It is not

an error to include an uninitialized variable in the list,but it will be

trapped if the @{b}NOVALUE@{ub} interrupt has been enabled.



The @{"TRANSLATE()" LINK "TRANSLATE()"} or @{"UPPER()" LINK "UPPER()"} Built-In functions could also be used to convert

variables to uppercase,but the instruction form is more concise(and faster) if

several variables are being converted.


Example:


@{i}
        when='Now is the time'

        upper when

        say when                /* NOW IS THE TIME      */
@{ui}
@ENDNODE
@NODE "WHEN" "WHEN"
@TOC "CHAPTER 4"
@{b}WHEN@{ub}



Usage:@{b}WHEN expression [THEN [;] [conditional statement]]@{ub}

The WHEN instruction is similar to the @{"IF" LINK "IF"} instruction,but is valid only within

a @{"SELECT" LINK "SELECT"} range. Each WHEN expression is evaluated in turn and must result in a

boolean value. If the result is a 1,the conditional statement is executed and

control passes to the @{"END" LINK "END"} statement that terminates the SELECT. As in the case

of the IF instruction,the @{"THEN" LINK "THEN"} need not be part of the same clause.

Example:


@{i}
        select;

           when i<j thn say 'less'

           when i=j then say 'equal'

           otherwise     say 'greater'

           end
@{ui}
@ENDNODE
@NODE "CHAPTER 5" "Chapter 5"

                           @{b}CHAPTER 5  COMMANDS@{ub}


The REXX language is unusual in that an entire syntactic class of program

statements are reserved for commands, statements that have meaning not within the

language itself but rather to an external program. When a @{"command clause" LINK "5.COMMAND CLAUSES"} is

found in a program,it is evaluated as an expression and then sent through the

command interface to an explicit or implicit host application,an external

program that has announced its ability to receive commands. The host

application then processes the command and returns a result code that indicates

whether the command was performed successfully. In this manner every host

program becomes fully programmable,and with even a limited set of predefined

operations can be customized by the end user.



This chapter discusses the ARexx command interface and examines some of the

ways in which commands can be used to build programs for an external program.

Such programs are ofter called "macro programs" because they implement a

complex ("macro") action from a series of simpler "micro" commands.



@{"Chapter 10" LINK "CHAPTER 10"} has detailed information on the data structers required to implement

a command interface for an applications program.
@ENDNODE

@NODE "5.COMMAND CLAUSES" "Command Clauses"
@{b}COMMAND CLAUSES@{ub}



Syntactically,a command clause is just an expression that can't be classified

as another type of clause. The actual structure of the command is dictated by

the external host to which it is intended,but in most cases will follow the

model of a name or letter followed by parameter data. Command names can be

given as either a symbol or a string. However,it is generally safer to use a

string for the name,since it can't be assigned a value or be mistaken for an

instruction keyword. For example,the following might be commands for a text

editor:


@{i}
        JUMP current+10         /* advance to next      */

        'insert' newstring      /* blast it in          */

        'TOP'                   /* back to the top      */
@{ui}


Since command clauses are expressions,they are fully evaluated before being

sent to the host. Any part of the final command string can be computed within

the program,so virtually any sort of command structure can be created.



The interpretation of the received commands depends entirely on the host

application. In the simplest case the command strings will correspond exactly

to commands that could be entered directly by a user. For instance,positional

control(up/down)commands for a text editor would probably have identical

interpretations whether issued by the user or from a program. Other commands

may be valid only when issued from a macro program;a command to simulate a menu

operation would probably not be entered by the user.
@ENDNODE

@NODE "THE HOST ADDRESS" "The Host Address"
@{b}THE HOST ADDRESS@{ub}



The destination for a command is determined by the current host address,which

is the name of the public message port managed by an external program. ARexx

maintains two implicit host addresses,a "current" and a "previous" value,as

part of the program's storage environment. These values can be changed at any

time using the @{"ADDRESS" LINK "ADDRESS"} instruction(or its synonym,@{"SHELL" LINK "SHELL"},)and the current host

address can be inspected with the @{"ADDRESS()" LINK "ADDRESS()"} Built-In fuction. The default host

address string is "REXX",but this can be overridden when a program is invoked.

In particular,most host applications will supply the name of their public port

when they invoke a macro program,so that the macro can automatically issue

commands back to the host.



One special host address is recognized: the string @{b}COMMAND@{ub} indicates that the

command should be issued directly to the underlying DOS. All other host

addresses are assumed to refer to a public message port. An attempt to send a

commmand to a non-existent message port will generate the syntax error "Host

environment not found."



Single commands can be sent to a specific host without disturbing the host

address settings. This is done using the @{"ADDRESS" LINK "ADDRESS"} instruction,as the following

example illustrates:


@{i}
ADDRESS MYEDIT 'jump top'
@{ui}


This example would send the command "@{i}jump top@{ui}" to an external host named

"MYEDIT."



It is important to note that you cannot send commands to a host application

without knowing the name of its public message port. Writing macro programs to

communicate with two or more hosts may require some clever programming to

determine whether both hosts are active and what their respective host

addresses are.
@ENDNODE

@NODE "THE COMMAND INTERFACE" "The Command Interface"
@{b}THE COMMAND INTERFACE@{ub}



ARexx implements its command interface using the message-passing facilities

provided by the EXEC operating system. Each host application must provide a

public message port,the name of which is referred to as the host address. ARexx

programs issue commands by placing the command string in a message packet and

sending the packet to the host's message port. The program "sleeps" while the

host processes the command,and awakens when the message packet returns. The

entire process can be regarded as a dialogue between the host application and a

macro program:the host initiates the dialogue by invoking the macro,and the

macro program replies with one or more command strings. The commands that can

be sent are not limited to simple text strings,but might be address pointers or

even bit-mapped images.



After it finishes processing a command,the host "replies" the message packet

with a return code that indicates the status of the command. This return code

is placed in the ARexx special variable @{b}RC@{ub} so that it can be examined by the

program. A value of zero is assumed to mean that no errors occurred,while

positive values usually indicate progressively more severe error conditions.

The return code allows the macro program to determine whether the command

succeeded and to take action if it failed,so it is important for each

applictions program to document the meanings of the return codes for its

commands.
@ENDNODE

@NODE "USING COMMANDS IN MACRO PROGRAMS" "Using Commands in Macro Programs"
@{b}USING COMMANDS IN MACRO PROGRAMS@{ub}



ARexx can be used to write programs for any host application that includes a

suitable command interface. Some applications programs are designed with an

embedded macro language,and may include many predefined macro commands. With a

well-designed macro language interface the user will be usually unaware of

whether a given action is implemented as a primitive operations or as a macro

program.



The starting point in designing a macro program is to examine the commands that

would be required to perform it manually. The documentation for the host

application program should then describe the possible return codes for each

command;these codes can be used to determine whether the operation performed by

the command was successful. Check also for "shortcut" commands that may be

available only to macro programs;some applications programs may include very

powerful functions that were implemented specifically for use in macro

programs.
@ENDNODE

@NODE "USING AREXX WITH COMMAND SHELLS" "Using ARexx with Command Shells"
@{b}USING AREXX WITH COMMAND SHELLS@{ub}



Although ARexx was designed to work most effectively with programs that support

its specific command interface,it can be used with any "command shell" program

that uses standards I/O mechanisms to obtain its input stream. There are

several ways to use ARexx to prepare a stream of commands for such program.



One obvious technique is to create an actual command file on the "RAM:" disk

and then pass it directly to the command shell. For example,you could open a

new CLI window to run a standard "execute" script using the following short

program:


@{i}
        /* Launch a new CLI     */

        address command

        conwindow = "CON:0/0/640/100/NewOne"



        /* create a command file on the fly  */

        call open out,"ram:$$temp",write

        call writeln out,'echo "this is a test"'

        call close out



        /* open the new CLI window */

        'newcli' conwindow "ram:$$temp"'

        exit
@{ui}


Since no disk accesses are required,this method is actually fairly fast,if not

very elegant.



Another alternative is to use the command stacking facility provided by the

@{"PUSH" LINK "PUSH"} and @{"QUEUE" LINK "QUEUE"} instructions. These instructions allow an ARexx program to stack

an arbitrary stream of commands and data for the command shell or other program

to read. Any set of commands that could be "typed ahead" at a command prompt

can be prepared in this fashion. After the ARexx program exits,the next program

that uses the input stream will read the prepared commands and can process them

in the normal fashion.
@ENDNODE

@NODE "COMMAND INHIBITION" "Command Inhibition"
@{b}COMMAND INHIBITION@{ub}



Sometimes it is necessary to write and test macro programs that issue

potentially destructive commands. For instance,a program to find and delete

unneeded files would be difficult to test safely,since it might accidentally

delete the wrong files and would require a continual source of new files for

testing.



To simply the development and testing of such programs,ARexx provides a special

tracing mode called command inhibition that suppresses host commands. While in

command inhibition mode,command processing proceeds normally except that the

command is not actually issued and the variable @{b}RC@{ub} is set to 0. This allows the

program logic to be verified before any commands are actually sent to the

external program. @{"Chapter 7" LINK "CHAPTER 7"} has further information on this facility.
@ENDNODE


@NODE "CHAPTER 6" "Chapter 6"

                           @{b}CHAPTER 6  FUNCTIONS@{ub}



The basic concept of a function is a program or group of statements that will

be executed whenever the function name appears in a certain context. Functions

are an important building block of most computer languages in that they allow

modular programming -- the ability to build a large program from a series of

smaller,more easily developed modules. In ARexx a function may be defined as

part of(internal to)a program,as part of a library,or as a separate external

program.

@{"Syntax and Search Order" LINK "SYNTAX AND SEARCH ORDER"}

   @{"Search Order" LINK "SEARCH ORDER"}

@{"Internal Functions" LINK "INTERNAL FUNCTIONS"}

@{"Built-In Functions" LINK "BUILT-IN FUNCTIONS"}

@{"Exernal Function Libraries" LINK "EXTERNAL FUNCTION LIBRARIES"}

@{"Function Hosts" LINK "FUNCTION HOSTS"}

@{"The Built-In Function Library" LINK "THE BUILT-IN FUNCTION LIBRARY"}

   @{"Contents" LINK "BUILT-IN FUNCTION LIBRARY INDEX"}
@ENDNODE

@NODE "SYNTAX AND SEARCH ORDER" "Syntax and Search Order"
@TOC "CHAPTER 6"
@{b}SYNTAX AND SEARCH ORDER@{ub}



Function calls in an expression are defined syntactically as a symbol or string

followed immediately by an open parenthesis. The symbol or string(taken an a

literal)specifies the function name,and the open parenthesis begins the

argument list. Between the opening and eventual closing parentheses are zero or

more argument expressions,separated by commas,that supply the data being passed

to the function. For example,


@{i}
        CENTER('title",20)

        ADDRESS()

        'AllocMem'(256*4,1)
@{ui}


are all valid function calls. Each argument expression is evaluated in turn and

the resulting strings are passed as the argument list to the function. There is

no limit to the number of arguments that may be passed to an internal

function,but calls to Built-In or external functions are limited to a maximum

of 15 arguments. Note that each argument expression,while ofter just a single

literal value,can include arithmetic or string operations or even other

function calls. Argument expressions are evaluated from left to right.



Functions can also be invoked using the @{"CALL" LINK "CALL"} instruction. The syntax of this

form is slightly different,and is described in @{"Chapter 4" LINK "CHAPTER 4"}. The CALL instruction

can be used to invoke a function that may not return a value.
@ENDNODE

@NODE "SEARCH ORDER" "Search Order"
@TOC "CHAPTER 6"
@{b}SEARCH ORDER@{ub}



Function linkages in ARexx are established dynamically at the time of the

function call. A specific search order is followed until a function matching

the name symbol or string is found. If the specified function cannot be

located, an error is generated and the expression evaluation is terminated. The

full search order is:



@{b}1. Internal Functions@{ub}. The program source is examined for a label that matches

the function name. If a match is found,a new storage environment is created and

control is transferred to the label.



@{b}2. Built-In Functions@{ub}. The Build-In function library is searched for the

specified name. All of these functions are defined by uppercase names,and the

library has been specially organized to make the search as efficient as

possible.



@{b}3. Function Libraries and Function Hosts@{ub}. The available function libraries and

function hosts are maintained in a prioritized list,which is searched starting

at the highest priority until the requested function is found or the end of the

list is reached. Each function library is opened and called at a special entry

point to determine whether it contains a function matching the given name.

Function hosts are called using a message-passing protocol similar to that used

for commands,and may be used as gateways for remote procedure calls to other

machines in a network.



@{b}4. External ARexx Programs@{ub}. The final search step is to check for an external

ARexx program file by sending an invocation message to the ARexx resident

process. The search always begins in the current directory,and follows the same

search path as the original ARexx program invocation. The name matching process

is not case-sensitive.



Note that the function name-matching procedure may be case-sensitive for some

of the search steps but not for others. The matching procedure used in a

function library or function host is left to the discretion of the applications

designer. Functions defined with mixed-case names must be called using a string

token,since symbol names are always translated to uppercase.



The full search order is followed whenever the function name is defined by a

symbol token. However,the search for internal functions is bypassed if the name

is specified by a string token. This allows internal functions to usurp the

names of external functions,as in the following example:


@{i}
CENTER:                         /* internal "CENTER" */

arg string,length               /* get arguments     */

length = min(length,60)         /* compute length    */

return 'CENTER'(string,length)
@{ui}


Here the Built-In fuction @{"CENTER()" LINK "CENTER()"} has been replaced by an internal function of

the same name,which calls the original function after modifying the length

argument.
@ENDNODE

@NODE "INTERNAL FUNCTIONS" "Internal Functions"
@TOC "CHAPTER 6"
@{b}INTERNAL FUNCTIONS@{ub}



The interpreter creates a new storage environment when an internal function is

called,so that the previous(caller's)environment is preserved. The new

environment inherits the values from its predecessor,but subsequent changes to

the environment variables do not affect the previous environment. The specific

values that are preserved are:



The current and previous host addresses,

The @{b}NUMERIC DIGITS,FUZZ,and FORM@{ub} settings,

The trace option,inhibit flag,and interace flag,

The state of the interrupt flags defined by the @{"SIGNAL" LINK "SIGNAL"} instruction,and

The current prompt string as set by the @{"OPTIONS" LINK "OPTIONS"} PROMPT instruction.



The new environment does not automatically get a new symbol table,so initially

all of the variables in the previous environment are available to the called

function. The PROCEDURE instruction can be used to create a new symbol table

and thereby protect the caller's symbol values.



Execution of the internal function proceeds until a @{"RETURN" LINK "RETURN"} instruction is

executed. At this point the new environment is dismantled and control resumes

at the point of the function call. The expression supplied with the RETURN

instruction is evaluated and passed back to the caller as the fuction result.
@ENDNODE

@NODE "BUILT-IN FUNCTIONS" "Built-In Functions"
@TOC "CHAPTER 6"
@{b}BUILT-IN FUNCTIONS@{ub}



ARexx provides a substantial library of predefined functions as part of the

language system. These functions are always available and have been optimized

to work with the internal data structures. In general the Built-In functions

execute much faster than an equivalent interpreted function,so their usage is

strongly recommended.



The Built-In Function Library is not user-extensible,but additional functions

will be included in later releases.
@ENDNODE

@NODE "EXTERNAL FUNCTION LIBRARIES" "External Function Libraries"
@TOC "CHAPTER 6"
@{b}EXTERNAL FUNCTION LIBRARIES@{ub}



External function libraries provide a mechanism with which users and

applications developers can extend the functionality of ARexx. A function

library is a collection of one or more functions together with a "query" entry

point that serves to match a name string with the appropriate function.

External function libraries are supported as standard Amiga shared libraries,

and may be either memory or disk-resident. Disk-resident libraries are loaded

and opened as needed.



The ARexx resident process maintains a list,called @{"the Library List" LINK "THE LIBRARY LIST"},of the

currently available function libraries and function hosts. Applications

programs can add or remove function libraries as required. The Library List is

maintained as a priority-sorted queue,and entries can be added at an

appropriate priority to control the function name resolution. Libraries with

higher priorities are searched first;within a given priority level,those

libraries added first are searched first.



During the search process the ARexx interpreter opens each library and calls

its "query" entry point. The query function must then check to see whether the

requested function name is in the library. If not,it returns a "function not

found" error code and the search continues with the next library in the list.

Function libraries are always closed after being checked so that the operatiing

system can reclaim the memory space if required. Once the requested function

has been found,it is called with the arguments passed by the interpreter,and

must return an error code and a result string.



The ARexx language system includes an external function library in a file

called "rexxsupport.library". It contains a number of Amiga-specific functions

and is described in @{"Appendix D" LINK "APPENDIX D"}. @{"Chapter 10" LINK "CHAPTER 10"} provides information on designing

and implementing function libraries.
@ENDNODE

@NODE "FUNCTION HOSTS" "Function Hosts"
@TOC "CHAPTER 6"
@{b}FUNCTION HOSTS@{ub}



Function hosts are called by sending a function invocation message packet to

the public message port identified by the host's name. No constraints are

imposed on the iternal design of the host except that it must eventually return

the invocation message with an appropriate return code and result string. The

function call may result in a new program being loaded and run,or might even be

sent to a network handler as a remote procedure call.



The available function hosts,along with the function libraries,are contained in

the Library List maintained by the resident process. This list provides a

general mechanism for resolving function names in a priority-controlled manner.



The ARexx resident process is an example of a function host. It is added to the

Library List at a nominal priority of -60 when the resident process is started,

using the same name ("REXX")that is used for command invocations. When it

receives a function invocation packet,it searches for an external file matching

the function name,just as it would for a command invocation of the same name.

In particular,the search begins with the current directory and process is not

case-sensitive,but is affected by the presence of explicit directory

specifications or file extensions in the name string. The rules governing the

search for external programs are covered in @{"Chapter 9" LINK "CHAPTER 9"}.



External programs are always run as a separate process in the Amiga's

multitasking system. The calling program "sleeps" until the called function

finishes and the message packet returns. The result string and error code are

returned in the packet.
@ENDNODE

@NODE "THE BUILT-IN FUNCTION LIBRARY" "The Built-In Function Library"
@TOC "CHAPTER 6"
@{b}THE BUILT-IN FUNCTION LIBRARY@{ub}



This section of the chapter is devoted to descriptions of the individual Built

In functions,which are listed alphabetically. Many of the functions have

optional as well as required arguments. The optional arguments are shown in

brackets,and generally have a default value that is used if the argument is

omitted.



@{b}MAXIMUM ARGUMENTS@{ub}. While internal functions can be called with any number of

arguments,the Built-In functions(and external functions as well)are limited to

a maximum of 15 arguments.



@{b}PAD AND OPTION CHARACTERS@{ub}. For functions that accept a "pad" character

argument,only the first character of the argument string is significant. If a

null string is supplied,the default padding character(usually a blank)will be

used. Similarly,where an option keyword is specified as an argument,only the

first character is significant. Option keywords may be given in uppercase or

lowercase.



@{b}I/O SUPPORT FUNCTIONS@{ub}. ARexx provides functions for creating and manipulating

external DOS files. The functions available at the present time are @{"OPEN()" LINK "OPEN()"},

@{"CLOSE()" LINK "CLOSE()"},@{"READCH()" LINK "READCH()"},@{"READLN()" LINK "READLN()"},@{"WRITECH()" LINK "WRITECH"},@{"WRITELN()" LINK "WRITELN()"},@{"EOF()" LINK "EOF()"},@{"SEEK()" LINK "SEEK()"},and @{"EXISTS()" LINK "EXISTS()"}. Files

are referenced by a "logical name," a case-sensitive name that is assigned to a

file when it is first opened.



There is no limit to the number of files that may be open simultaneously,and

all open files are closed automatically when the program exits.



@{b}BIT-MANIPULATION FUNCTIONS@{ub}. The functions @{"BITCHG()" LINK "BITCHG()"},@{"BITCLR()" LINK "BITCLR()"},@{"BITCOMP()" LINK "BITCOMP()"},@{"BITSET()" LINK "BITSET()"},

and @{"BITTST()" LINK "BITTST()"} are provided to implement extended bit-testing on character

strings. These functions differ from similar string-manipulation functions in

that the elementary unit of comparison is the bit rather than the byte. Bit

number are defined such that bit 0 is the low-order bit of the rightmost byte

of the string.
@ENDNODE

@NODE "BUILT-IN FUNCTION LIBRARY INDEX" "Built-In Functions"
@TOC "CHAPTER 6"

@{b}Contents@{ub}

@{"ABBREV()" LINK "ABBREV()"}
@{"ABS()" LINK "ABS()"}
@{"ADDLIB()" LINK "ADDLIB()"}
@{"ADDRESS()" LINK "ADDRESS()"}
@{"ARG()" LINK "ARG()"}
@{"B2C()" LINK "B2C()"}
@{"BITAND()" LINK "BITAND()"}
@{"BITCHG()" LINK "BITCHG()"}
@{"BITCLR()" LINK "BITCLR()"}
@{"BITCOMP()" LINK "BITCOMP()"}
@{"BITOR()" LINK "BITOR()"}
@{"BITSET()" LINK "BITSET()"}
@{"BITTST()" LINK "BITTST()"}
@{"BITXOR()" LINK "BITXOR()"}
@{"C2B()" LINK "C2B()"}
@{"C2D()" LINK "C2D()"}
@{"C2X()" LINK "C2X()"}
@{"CENTER() or CENTRE()" LINK "CENTER()"}
@{"CLOSE()" LINK "CLOSE()"}
@{"COMPRESS()" LINK "COMPRESS()"}
@{"COMPARE()" LINK "COMPARE()"}
@{"COPIES()" LINK "COPIES()"}
@{"DC2()" LINK "D2C()"}
@{"DATATYPE()" LINK "DATATYPE()"}
@{"DELSTR()" LINK "DELSTR()"}
@{"DELWORD()" LINK "DELWORD()"}
@{"EOF()" LINK "EOF()"}
@{"ERRORTEXT()" LINK "ERRORTEXT()"}
@{"EXISTS()" LINK "EXISTS()"}
@{"EXPORT()" LINK "EXPORT()"}
@{"FREESPACE()" LINK "FREESPACE()"}
@{"GETCLIP()" LINK "GETCLIP()"}
@{"GETSPACE()" LINK "GETSPACE()"}
@{"HASH()" LINK "HASH()"}
@{"IMPORT()" LINK "IMPORT()"}
@{"INDEX()" LINK "INDEX()"}
@{"INSERT()" LINK "INSERT()"}
@{"LASTPOS()" LINK "LASTPOS()"}
@{"LEFT()" LINK "LEFT()"}
@{"LENGTH()" LINK "LENGTH()"}
@{"MAX()" LINK "MAX()"}
@{"MIN()" LINK "MIN()"}
@{"OPEN()" LINK "OPEN()"}
@{"OVERLAY()" LINK "OVERLAY()"}
@{"POS()" LINK "POS()"}
@{"PRAGMA()" LINK "PRAGMA()"}
@{"RANDOM()" LINK "RANDOM()"}
@{"RANDU()" LINK "RANDU()"}
@{"READCH()" LINK "READCH()"}
@{"READLN()" LINK "READLN()"}
@{"REMLIB()" LINK "REMLIB()"}
@{"REVERSE()" LINK "REVERSE()"}
@{"RIGHT()" LINK "RIGHT()"}
@{"SEEK()" LINK "SEEK()"}
@{"SETCLIP()" LINK "SETCLIP()"}
@{"SHOW()" LINK "SHOW()"}
@{"SIGN()" LINK "SIGN()"}
@{"SPACE()" LINK "SPACE()"}
@{"STORAGE()" LINK "STORAGE()"}
@{"STRIP()" LINK "STRIP()"}
@{"SUBSTR()" LINK "SUBSTR()"}
@{"SUBWORD()" LINK "SUBWORD()"}
@{"SYMBOL()" LINK "SYMBOL()"}
@{"TIME()" LINK "TIME()"}
@{"TRACE()" LINK "TRACE()"}
@{"TRANSLATE()" LINK "TRANSLATE()"}
@{"TRIM()" LINK "TRIM()"}
@{"UPPER()" LINK "UPPER()"}
@{"VALUE()" LINK "VALUE()"}
@{"VERIFY()" LINK "VERIFY()"}
@{"WORD()" LINK "WORD()"}
@{"WORDINDEX()" LINK "WORDINDEX()"}
@{"WORDLENGTH()" LINK "WORDLENGTH()"}
@{"WORDS()" LINK "WORDS()"}
@{"WRITECH()" LINK "WRITECH()"}
@{"WRITELN()" LINK "WRITELN()"}
@{"X2C()" LINK "X2C()"}
@{"XRANGE()" LINK "XRANGE()"}

@ENDNODE


@NODE "ABBREV()" "ABBREV()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}ABBREV()@{ub}



Usage:@{b}ABBREV(string1,string2,[length]@{ub}

Returns a boolean value that indicates whether string2 is an abbreviation of

string1 with length greater than or equal to the specified length argument. The

default length is 0,so the null string is an acceptable abbreviation.

Example:


@{i}
        say abbrev('fullname','ful'  ==>1

        say abbrev('almost','alm',4) ==>0

        say abbrev('any','')         ==>1
@{ui}
@ENDNODE

@NODE "ABS()" "ABS()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}ABS()@{ub}



Usage:@{b}ABS(number)@{ub}

Returns the absolute value of the number argument,which must be numeric.

Examples:


@{i}
        say abs(-5.35)                  ==>5.35

        say abs(10)                     ==>10
@{ui}
@ENDNODE
@NODE "ADDLIB()" "ADDLIB()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}ADDLIB()@{ub}



Usage:@{b}ADDLIB(name,priority,[offset,version])@{ub}

Adds a function library or a function host to @{"the Library List" LINK "THE LIBRARY LIST"} maintained by

the resident process. The name argument specifies either the name of a function

library or the public message port associated with a function host. The name is

case-sensitive,and any libraries thus declared should reside in the system

LIBS: directory. The priority argument specifies the search priority and must

be an integer between 100 and -100,inclusive. The offset and version arguments

apply only to libraries. The offset is the integer offset to the library's

"query" entry point,and the version is an integer specifying the minimum

acceptable release level of the library.



The function returns a boolean result that indicates whether the operation was

successful. Note that if a library is specified,it is not actually opened at

this time;similarly,no check is performed as to whether a specified function

host port has been opened yet.

Example:


@{i}
        say addlib("rexxsupport.library",0,-30,0)==>1

        call addlib "EtherNet",-20      /* a gateway */
@{ui}
@ENDNODE

@NODE "ADDRESS()" "ADDRESS()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}ADDRESS()@{ub}



Usage:@{b}ADDRESS()@{ub}

Returns the current host address string. The host address is the message port

to which commands will be sent. The SHOW()function can be used to check whether

the required external host is actually available.

See Also:@{"SHOW()" LINK "SHOW()"}

Example:


@{i}
        say address()           ==>REXX
@{ui}
@ENDNODE

@NODE "ARG()" "ARG()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}ARG()@{ub}



Usage:@{b}ARG([number],['Exists' | 'Omitted'])@{ub}

ARG() returns the number of arguments supplied to the current environment. If

the number parameter alone is supplied,the corresponding argument string is

returned. If a number and one of the keywords Exists or Omitted is given,the

boolean return indicates the status of the corresponding argument. Note that

the existence or omission test does not indicate whether the string has a null

value,but only whether a string was supplied.

Examples:


@{i}
        /* Assume arguments were: ('one,,10)            */

        say arg()                       ==>3

        say arg(1)                      ==>one

        say arg(2,'0')                  ==>1
@{ui}
@ENDNODE

@NODE "B2C()" "B2C()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}B2C()@{ub}



Usage:@{b}B2C(string)@{ub}

Converts a string of binary digits(0,1)into the corresponding(packed)character

representation. The conversion is the same as though the argument string had

been specified as a literal binary string(e.g. '1010'B). Blanks are permitted

in the string,but only at byte boundaries. This function is particularly useful

for creating strings that are to be used as bit masks.

See also:@{"X2C()" LINK "X2C()"}

Examples:


@{i}
        say b2c('00110011')             ==>3

        say b2c('01100001')             ==>a
@{ui}
@ENDNODE
@NODE "BITAND()" "BITAND()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}BITAND()@{ub}



Usage:@{b}BITAND(string1,string2,[pad])@{ub}

The argument strings are logically ANDed together,with the length of the result

being the longer of the two operand strings. If a pad character is supplied,the

shorter string is padded on the right;otherwise,the operation terminates at the

end of the shorter string and the remainder of the longer string is appended to

the result.

Example:


@{i}
        bitand('0313'x,'FFF0'x)         ==>'0310'x
@{ui}
@ENDNODE
@NODE "BITCHG()" "BITCHG()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}BITCHG()@{ub}

Usage:@{b}BITCHG(string,bit)@{ub}

Changes the state of the specified bit in the argument string. Bit numbers are

defined such that bit 0 is the low-order bit of the rightmost byte of the

string.

Example:
@{i}
        bitchg('0313'x,4)               ==>'0303'x
@{ui}
@ENDNODE
@NODE "BITCLR()" "BITCLR()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}BITCLR()@{ub}

Usage:@{b}BITCLR(string,bit)@{ub}

Clears(sets to zero)the specified bit in the argument string. Bit numbers are

defined such that bit 0 is the low-order bit of the rightmost byte of the

string.

Example:
@{i}
        bitclr('0313'x,4)               ==>'0303'x
@{ui}
@ENDNODE
@NODE "BITCOMP()" "BITCOMP()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}BITCOMP()@{ub}

Usage:@{b}BITCOMP(string1,string2,[pad])@{ub}

Compares the argument strings bit-by-bit,starting at bit number 0. The returned

value is the bit number of the first bit in which the strings differ,or -1 if

the strings are identical.

Examples:
@{i}
        bitcomp('7F'x,'FF'x)            ==>7

        bitcomp('FF'x,'FF'x)            ==>-1
@{ui}
@ENDNODE
@NODE "BITOR()" "BITOR()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}BITOR()@{ub}

Usage:@{b}BITOR(string1,string2,[pad])@{ub}

The argument strings are logically ORed together,with the length of the result

being the longer of the two operand strings. If a pad character is supplied,the

shorter string is padded on the right;otherwise,the operation terminates at the

end of the shorter string and the remainder of the longer string is appended to

the result.

Example:
@{i}
        bitor('0313'x,'003F'x)          ==>'033F'x
@{ui}
@ENDNODE
@NODE "BITSET()" "BITSET()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}BITSET()@{ub}

Usage:@{b}BITSET(string,bit)@{ub}

Sets the specified bit in the argument string is 1. Bit numbers are defined

such that bit 0 is the low-order bit of the rightmost byte of the string.

Example:

@{i}
        bitset('0313'x,2)               ==>'0317'x
@{ui}
@ENDNODE
@NODE "BITTST()" "BITTST()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}BITTST()@{ub}

Usage:@{b}BITTST(string,bit)@{ub}

The boolean return indicates the state of the specified bit in the argument

string.


Bit numbers are defined such that bit 0 is the low-order bit of the rightmost

byte to the string.

Example:
@{i}
        bittst('0313'x,4)               ==>1
@{ui}
@ENDNODE
@NODE "BITXOR()" "BITXOR()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}BITXOR()@{ub}

Usage:@{b}BITAND(string1,string2,[pad])@{ub}

The argument strings are logically exclusively-ORed together,with the length of

the result being the longer of the two operand strings. If a pad character is

supplied,the shorter string is padded on the right;otherwise,the operation

terminates at the end of the shorter string and the remainder of the longer

string is appended to the result.

Example:
@{i}
        bitxor('0313'x,'001F'x)         ==>'030C'x
@{ui}
@ENDNODE
@NODE "C2B()" "C2B()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}C2B()@{ub}

Usage:@{b}C2B(string)@{ub}

Converts the character string into the equivalent string of binary digits.

See Also:@{"C2X()" LINK "C2X()"}

Example:
@{i}
        say c2b('abc')                  ==>011000010110001001100011
@{ui}
@ENDNODE
@NODE "C2D()" "C2D()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}C2D()@{ub}

Usage:@{b}C2D(string,[n])@{ub}

Converts the string argument from its character representation to the

corresponding decimal number,expressed as ASCII digits(0-9). If n is supplied,

the character string is considered to be a number expressed in n bytes. The

string is truncated or padded with nulls on the left as required,and the sign

bit is extended for the conversion.

Examples:
@{i}
        say c2d('0020'x)                ==>32

        say c2d('FFFF')                 ==>1

        say c2d('FF0100',x,2)           ==>256
@{ui}
@ENDNODE
@NODE "C2X()" "C2X()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}C2X()@{ub}

Usage:@{b}C2X(string)@{ub}

Converts the string argument from its character representation to the

corresponding hexadecimal number,expressed as the ACSII characters 0-9 and A-F.

See Also:@{"C2B()" LINK "C2B()"}

Example:
@{i}
        say c2x('abc')                  ==>616263
@{ui}
@ENDNODE

@NODE "CENTER()" "CENTER() or CENTRE()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}CENTER()@{ub} or @{b}CENTRE()@{ub}

Usage:@{b}CENTER(string,length,[pad])@{ub}or @{b}CENTRE(string,length,[pad])@{ub}

Centers the string argument in a string with the specified length. If the

length is longer than that of the string,pad characters or blanks are added as

necessary.

Examples:
@{i}
        say center('abc',6)             ==>' abc '

        say center('abc',6,'+')         ==>'+abc++'

        say center('123456',3)          ==>'234'
@{ui}
@ENDNODE

@NODE "CLOSE()" "CLOSE()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}CLOSE()@{ub}

Usage:@{b}CLOSE(file)@{ub}

Closes the file specified by the given logical name. The returned value is a

boolean success flag,and will be 1 unless the specified file was not open.

Example:
@{i}
        say close('input')              ==>1
@{ui}
@ENDNODE
@NODE "COMPRESS()" "COMPRESS()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}COMPRESS()@{ub}

Usage:@{b}COMPRESS(string,[list])@{ub}

If the list argument is omitted,the function removes leading,trailing,or

embedded blank characters from the string argument. If the optional list is

supplied,it specifies the characters to be removed from the string.

Examples:
@{i}
        say compress (' why not ')      ==>whynot

        say compress ('++12-34-+','+-') ==>1234
@{ui}
@ENDNODE
@NODE "COMPARE()" "COMPARE()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}COMPARE()@{ub}

Usage:@{b}COMPARE(string1,string2,[pad])@{ub}

Compares two strings and returns the index of the first position in which they

differ,or 0 if the strings are identical. The shorter string is padded as

required using the supplied character or blanks.

Examples:
@{i}
        say compare('abcde','abcce')    ==>4

        say compare('abcde',abcde')     ==>0

        say compare('abc++','abc+-','+') ==>5
@{ui}
@ENDNODE

@NODE "COPIES()" "COPIES()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}COPIES()@{ub}

Usage:@{b}COPIES(string,number)@{ub}

Creates a new string by concatenating the specified number of copies of the

original. The number argument may be zero,in which case the null string is

returned.

Example:
@{i}
        say copies('abc',3)             ==>abcabcabc
@{ui}
@ENDNODE
@NODE "D2C()" "D2C()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}D2C()@{ub}

Usage:@{b}D2C(number)@{ub}

Creates a string whose value is the binary(packed)representation of the given

decimal number.

Example:
@{i}
        d2c(31)                         ==>'1F'x
@{ui}
@ENDNODE
@NODE "DATATYPE()" "DATATYPE()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}DATATYPE()@{ub}

Usage:@{b}DATATYPE9string,[option])@{ub}

If the option parameter is not specified,DATATYPE()tests whether the string

parameter is a valid number and returns either NUM or CHAR. If an option

keyword is given,the boolean return indicates whether the string satisfied the

requested test. The following option keywords are recognized:



                         @{b}DATATYPE() Options@{ub}



        KEYWORD                 CHARACTERS ACCEPTED

        Alphanumeric            Alphabetics (A-Z,a-z)

                                or Numerics (0-9)

        Binary                  Binary Digits String

        Lowercase               Lowercase Alphabetics (a-z)

        Mixed                   Mixed Upper/Lowercase

        Numeric                 Valid Numbers

        Symbol                  Valid REXX Symbols

        Upper                   Uppercase Alphabetics (A-Z)

        Whole                   Integer Numbers

        X                       Hex Digits String

Examples:
@{i}
        say datatype('123')                     ==>NUM

        say datatype('1a f2','x')               ==>1

        say datatype('aBcde','L')               ==>0
@{ui}
@ENDNODE

@NODE "DELSTR()" "DELSTR()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}DELSTR()@{ub}

Usage:@{b}DELSTR(string,n,[length])@{ub}

Deletes the substring of the string argument beginning with the nth character

for the specified length in characters. The default length is the remaining

length of the string.

Example:
@{i}
        say delstr('123456',2,3)                ==>156
@{ui}
@ENDNODE

@NODE "DELWORD()" "DELWORD()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}DELWORD()@{ub}

Usage:@{b}DELWORD(string,n,[length])@{ub}

Deletes the substring of the string argument beginning with the nth word for

the specified length in words. The default length is the remaining length of

the string. The deleted string includes any trailing blanks following the last

word.

Examples:
@{i}
        say delword('Tell me a story',2,2)==>'Tell story'

        say delword('one two three',3)    ==>'one two '
@{ui}
@ENDNODE

@NODE "EOF()" "EOF()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}EOF()@{ub}

Usage:@{b}EOF(file)@{ub}

Checks the specified logical file name and returns the boolean value 1(True)if

the end-of-file has been reached,and 0(False)otherwise.

Example:
@{i}
        say eof(infile)                 ==>1
@{ui}
@ENDNODE
@NODE "ERRORTEXT()" "ERRORTEXT()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}ERRORTEXT()@{ub}

Usage:@{b}ERRORTEXT(n)@{ub}

Returns the error message associated with the specified ARexx code. The null

string is returned if the number is not a valid error code.

Example:
@{i}
        say errortext(41)               ==>Invalid expression
@{ui}
@ENDNODE

@NODE "EXISTS()" "EXISTS()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}EXISTS()@{ub}

Usage:@{b}EXISTS(filename)@{ub}

Tests whether an external file of the given filename exists. The name string

may include device and directory specifications.

Example:
@{i}
        say exists('df0:c/ed')          ==>1
@{ui}
@ENDNODE

@NODE "EXPORT()" "EXPORT()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}EXPORT()@{ub}

Usage:@{b}EXPORT(address,[string],[length],[pad])@{ub}

Copies data from the (optional) string into a previously-allocated memory area,

which must be specified as a 4-byte address. The length parameter specifies the

maximum number of characters to be copied; the default is the length of the

string. If the specified length is longer than the string,the remaining area is

filled with the pad character or nulls('00'x). The returned value is the number

of characters copied.



Caution is advised in using this function. Any area of memory can be

overwritten,possibly causing a system crash. Task switching is forbidden while

the copy is being done,so system performance may be degraded if long strings

are copied.

See Also:@{"IMPORT()" LINK "IMPORT()"},@{"STORAGE()" LINK "STORAGE()"}

Example:
@{i}
        count = export('0004 0000'x,'The answer')
@{ui}
@ENDNODE
@NODE "FREESPACE()" "FREESPACE()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}FREESPACE()@{ub}

Usage:@{b}FREESPACE(address,length)@{ub}

Returns a block of memory of the given length to the interpreter's internal

pool. The address argument must be a 4-byte string obtained by a prior call to

@{"GETSPACE()" LINK "GETSPACE()"},the internal allocator. It is not always necessary to release

internally-allocated memory,since it will be released to the system when the

program terminates. However,if a very large block has been allocated,returning

it to the pool may avoid memory space problems. The return value is a boolean

success flag.

See Also:@{"GETSPACE()" LINK "GETSPACE()"}

Example:
@{i}
        say freespace('00042000'x,32)           ==>1
@{ui}
@ENDNODE
@NODE "GETCLIP()" "GETCLIP()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}GETCLIP()@{ub}

Usage:@{b}GETCLIP(name)@{ub}

Searches @{"the Clip List" LINK "THE CLIP LIST"} for an entry matching the supplied name parameter,and

returns the associated value string. The name-matching is case-sensitive,and

the null string is returned if the name cannot be found. The usage and

maintenance of Clip List entries is described in the @{"Chapter 9" LINK "CHAPTER 9"}.

See Also:@{"SETCLIP()" LINK "SETCLIP()"}

Example:
@{i}
        /* Assume 'numbers' contains 'PI=3.14159'    */

        say getclip('numbers')          ==>PI=3.14159
@{ui}
@ENDNODE
@NODE "GETSPACE()" "GETSPACE()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}GETSPACE()@{ub}

Usage:@{b}GETSPACE(length)@{ub}

Allocates a block of memory of the specified length from the interpreter's

internal pool. The returned value is the 4-byte address of the allocated block,

which is not cleared or otherwise initialized. Internal memory is automatically

returned to the system when the ARexx program terminates,so this function

should not be used to allocate memory for use by external programs. The Support

Library(described in @{"Appendix D" LINK "APPENDIX D"})includes the function @{"ALLOCMEM()" LINK "ALLOCMEM()"} which to

allocate memory from the system free list.

See Also:@{"FREESPACE()" LINK "FREESPACE()"}

Example:
@{i}
        say c2x(getspace(32))           ==>'0003BF40'x
@{ui}
@ENDNODE
@NODE "HASH()" "HASH()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}HASH()@{ub}

Usage:@{b}HASH(string)@{ub}

Returns the hash attribute of a string as a decimal number,and updates the

internal hash value of the string.

Example:
@{i}
        say hash('1')                   ==>49
@{ui}
@ENDNODE
@NODE "IMPORT()" "IMPORT()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}IMPORT()@{ub}

Usage:@{b}IMPORT(address,[length])@{ub}

Creates a string by copying data from the specified 4-byte address. If the

length parameter is not supplied,the copy terminates when a null byte is found.

See Also:@{"EXPORT()" LINK "EXPORT()"}

Example:
@{i}
        extval = import('0004 0000'x,8)
@{ui}
@ENDNODE
@NODE "INDEX()" "INDEX()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}INDEX()@{ub}

Usage:@{b}INDEX(string,pattern,[start])@{ub}

Searches for the first occurrence of the pattern argument in the string

argument,beginning at the specified start position. The default start position

is 1. The returned value is the index of the matched pattern,or 0 if the

pattern was not found.

Examples:
@{i}
        say index("123456","23")        ==>2

        say index("123456","77")        ==>0

        say index("123123","23",3)      ==>5
@{ui}
@ENDNODE
@NODE "INSERT()" "INSERT()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}INSERT()@{ub}

Usage:@{b}INSERT(new,old,[start],[length],[pad])@{ub}

Inserts the new string into the old string after the specified start position.

The default starting position is 0. The new string is truncated or padded to

the specified length as required,using the supplied pad character or blanks. If

the start position is beyond the end of the old string,the old string is padded

on the right.

Examples:
@{i}
        say insert('ab,'12345')         ==>ab12345

        say insert('123','++',3,5,'-')  ==>++-123--
@{ui}
@ENDNODE
@NODE "LASTPOS()" "LASTPOS()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}LASTPOS()@{ub}

Usage:@{b}LASTPOS(pattern,string,[start])@{ub}

Searches backwards for the first occurrence of the pattern argument in the

string argument,beginning at the specified start position. The default starting

position is the end of the string. The returned value is the index of the

matched pattern,or 0 if the pattern was not found.

Examples:
@{i}
        say lastpos("123234","2")       ==>4

        say lastpos("123234","5")       ==>0

        say lastpos("123234","2",3)     ==>2
@{ui}
@ENDNODE
@NODE "LEFT()" "LEFT()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}LEFT()@{ub}

Usage:@{b}LEFT(string,length,[pad])@{ub}

Returns the leftmost substring in the given string argument with the specified

length. If the substring is shorter than the requested length,it is padded on

the left with the supplied pad character or blanks.

Examples:
@{i}
        say left('123456',3)            ==>123

        say left('123456',8,'+')        ==>123456++
@{ui}
@ENDNODE
@NODE "LENGTH()" "LENGTH()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}LENGTH()@{ub}

Usage:@{b}LENGTH(string)@{ub}

Returns the length of the string.

Example:
@{i}
        say length('three')             ==>5
@{ui}
@ENDNODE
@NODE "MAX()" "MAX()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}MAX()@{ub}

Usage:@{b}MAX(number,number[,number,...])@{ub}

Returns the maximum of the supplied arguments,all of which must be numeric. At

least two parameters must be supplied.

Example:
@{i}
        say max(2.1,3,-1_               ==>3
@{ui}
@ENDNODE
@NODE "MIN()" "MIN()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}MIN()@{ub}

Usage:@{b}MIN(number,number[,number,...])@{ub}

Returns the minimum of the supplied arguments,all of which must be numeric. At

least two parameters must be supplied.

Example:
@{i}
        say min(2.1,3,-1)               ==>-1
@{ui}
@ENDNODE
@NODE "OPEN()" "OPEN()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}OPEN()@{ub}

Usage:@{b}OPEN(file,filename,['Append' | 'Read' | 'Write'])@{ub}

Opens an external file for the specified operation. The file argument defines

the logical name by which the file will be referenced. The filename is the

external name of the file,and may include device and directory specifications.

The function returns a boolean value that indicates whether the operation was

successful. There is no limit to the number of files that can be open

simultaneusly,and all open files are closed automatically when the program

exits.

See Also:@{"CLOSE()" LINK "CLOSE()"},@{"READ()" LINK "READ()"},@{"WRITE()" LINK "WRITE()"}

Examples:
@{i}
        say open('MyCon','CON:160/50/320/100/MyCon/cds') ==>1

        say open('outfile','ram:temp','W')               ==>1
@{ui}
@ENDNODE
@NODE "OVERLAY()" "OVERLAY()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}OVERLAY()@{ub}

Usage:@{b}OVERLAY(new,old,[start],[length],[pad])@{ub}

Overlays the new string onto the old string beginning at the specified start

position,which must be positive. The default starting position is 1. The new

string is truncated or padded to the specified length as required,using the

supplied pad character or blanks. If the start position is beyond the end of

the old string,the old string is padded on the right.

Examples:
@{i}
        say overlay('bb,'abcd')                 ==>bbcd

        say overlay('4','123',5,5,'-')          ==>123--4----
@{ui}
@ENDNODE
@NODE "POS()" "POS()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}POS()@{ub}

Usage:@{b}POS(pattern,string,[start])@{ub}

Searches for the first occurrence of the pattern argument in the string

argument,beginning at the position specified by the start argument. The default

starting position is 1. The returned value is the index of the matched

string,or 0 if the pattern wasn't found.

Examples:
@{i}
        say pos('23','123234')                  ==>2

        say pos('77','123234')                  ==>0

        say pos('23','123234',3)                ==>4
@{ui}
@ENDNODE
@NODE "PRAGMA()" "PRAGMA()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}PRAGMA()@{ub}

Usage:@{b}PRAGMA(option,[value])@{ub}

This function allows a program to change various attributes relating to the

system environment within which the program executes. The option argument is a

keyword that specifies an environmental attribute;the currently implemented

options are Directory and Priority. The value argument supplies the new

attribute value to be installed. The value returned by the function depends on

the attribute selected. Some attributes return the previous value

installed,while others may simply set a boolean success flag. The currently

defined option keywords are listed below.



@{b}DIRECTORY@{ub}. Specifies a new "current" directory. The current directory is used

as the "root" for filenames that do not explicitly include a device

specification. The return value is a boolean success flag.



@{b}PRIORITY@{ub}. Specifies a new task priority. The priority value must be an integer

in the range -128 to 127,but the practical range is much more limited. ARexx

programs should never be run at a priority higher than that of the resident

process,which currently runs at priority 4. The returned value is the previous

priority level.

Examples:
@{i}
        say pragma('priority',-5)               ==>0

        call pragma 'Directory','df0:system'
@{ui}
@ENDNODE
@NODE "RANDOM()" "RANDOM()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}RANDOM()@{ub}

Usage:@{b}RANDOM([min],[max],[seed])@{ub}

Returns a pseudorandom integer in the interval specified by the min and max

arguments. The default minimum value is 0 and the default maximum value is 999.

The interval max-min must be less than or equal to 1000. If a greater range of

random integers is required,the values from the @{"RANDU()" LINK "RANDU()"} function can be suitable

scaled and translated.



The seed argument can be supplied to initialize the internal state of the

random number generator.

See Also:@{"RANDU()" LINK "RANDU()"}

Example:
@{i}
        thisroll = random(1,6)  /* might be 1   */

        nextroll = random(1,6)  /* snake eyes?  */
@{ui}
@ENDNODE
@NODE "RANDU()" "RANDU()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}RANDU()@{ub}

Usage:@{b}RANDU([seed])@{ub}

Returns a uniformly-distributed pseudorandom number between 0 and 1. The number

of digits of precision in the result is always equal to the current Numeric

Digits setting. With the choice of suitable scaling and translation values,

RANDU()can be used to generate pseudorandom numbers on an arbitrary interval.



The optional seed argument is used to initialize the internal state of the

random number generator.

See Also:@{"RANDOM()" LINK "RANDOM()"}

Example:
@{i}
        firsttry = randu()      /* 0.371902021? */

        numeric digits 3

        tryagain = randu()      /* 0.873?       */
@{ui}
@ENDNODE
@NODE "READCH()" "READCH()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}READCH()@{ub}

Usage:@{b}READCH(file,length)@{ub}

Reads the specified number of characters from the given logical file into a

string. The length of the returned string is the actual number of characters

read,and may be less than the requested length if,for example,the end-of-file

was reached.

See Also:@{"READLN()" LINK "READLN"}

Example:
@{i}
        instring = readch('input',10)
@{ui}
@ENDNODE
@NODE "READLN()" "READLN()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}READLN()@{ub}

Usage:@{b}READLN(file)@{ub}

Reads characters from the given logical file into a string until a "newline"

character is found. The returned string does not include the "newline".

See Also:@{"READCH()" LINK "READCH()"}

Examples:
@{i}
        instring = readln('MyFile')
@{ui}
@ENDNODE
@NODE "REMLIB()" "REMLIB()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}REMLIB()@{ub}

Usage:@{b}REMLIB(name)@{ub}

Removes an entry with the given name from @{"the Library List" LINK "THE LIBRARY LIST"} maintained by the

resident process. The boolean return is 1 if the entry was found and

successfully removed. Note that this function does not make a distinction

between function libraries and function hosts,but simply removes a named entry.

See Also:@{"ADDLIB()" LINK "ADDLIB()"}

Example:
@{i}
        say remlib('MyLibrary.library')==>1
@{ui}
@ENDNODE
@NODE "REVERSE()" "REVERSE()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}REVERSE()@{ub}

Usage:@{b}REVERSE(string)@{ub}

Reverses the sequence of characters in the string.

Example:
@{i}
        say reverse('?ton yhw')         ==>why not?
@{ui}
@ENDNODE
@NODE "RIGHT()" "RIGHT()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}RIGHT()@{ub}

Usage:@{b}RIGHT(string,length,[pad])@{ub}

Returns the rightmost substring in the given string argument with the specified

length. If the substring is shorter than the requested length,it is padded on

the left with the supplied pad character or blanks.

Examples:
@{i}
        say right('123456',4)           ==>3456

        say right('123456',8,'+')       ==>++123456
@{ui}
@ENDNODE
@NODE "SEEK()" "SEEK()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}SEEK()@{ub}

Usage:@{b}SEEK(file,offset,['Begin' | 'Current' | 'End'])@{ub}

Moves to a new position in the given logical file,specified as an offset from

an anchor position. The default anchor is Current. The returned value is the

new position relative to the start of the file.

Examples:
@{i}
        say seek('input',10,'B')        ==>10

        say seek('input',O,'E')         ==>356  /* file length  */
@{ui}
@ENDNODE
@NODE "SETCLIP()" "SETCLIP()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}SETCLIP()@{ub}

Usage:@{b}SETCLIP(name,[value])@{ub}

Adds a name-value pair to @{"the Clip List" LINK "THE CLIP LIST"} maintained by the resident process. If

an entry of the same name already exists,its value is updated to the supplied

value string. Entries may be removed by specifying a null value. The function

returns a boolean value that indicates whether the operation was successful.

Examples:
@{i}
        say setclip('path','df0:s')     ==>1

        say setclip('path')             ==>1
@{ui}
@ENDNODE
@NODE "SHOW()" "SHOW()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}SHOW()@{ub}

Usage:@{b}SHOW(option,[name],[pad])@{ub}

Returns the names in the resource list specified by the option argument,or

tests to see whether an entry with the specified name is available. The

currently implemented options keywords are Clip,Files,Libraries,and Ports,

which are described below.



@{b}Clip@{ub}. Examines the names in @{"the Clip List" LINK "THE CLIP LIST"}.

@{b}Files@{ub}. Examines the names of the currently open logical file names.

@{b}Libraries@{ub}. Examines the names in @{"the Library List" LINK "THE LIBRARY LIST"},which are either function

libraries or function hosts.

@{b}Ports@{ub}. Examine the names in the system Ports List.



If the name argument is omitted,the function returns a string with the resource

names separated by a blank space or the pad character,if one was supplied. If

the name argument is given,the returned boolean value indicates whether the

name was found in the resource list. The name entries are case-sensitive.
@ENDNODE

@NODE "SIGN()" "SIGN()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}SIGN()@{ub}

Usage:@{b}SIGN(number)@{ub}

Returns 1 if the number argument is positive or zero,and -1 if number is

negative. The argument must be numeric.

Examples:
@{i}
        say sign(12)                    ==>1

        say sign(-33)                   ==>-1
@{ui}
@ENDNODE
@NODE "SPACE()" "SPACE()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}SPACE()@{ub}

Usage:@{b}SPACE(string,n,[pad])@{ub}

Reformats the string argument so that there are n spaces(blank characters)

between each pair of words. If the pad character is specified,it is used

instead of blanks as the separator character. Specifying n as 0 will remove all

blanks from the string.

Examples:
@{i}
        say space('Now is the time',3)  ==>'Now   is   the   time'

        say space('Now is the time',0)  ==>'Nowisthetime'

        say space('1 2 3',1,'+')        ==>'1+2+3'
@{ui}
@ENDNODE
@NODE "STORAGE()" "STORAGE()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}STORAGE()@{ub}

Usage:@{b}STORAGE([address],[string],[length],[pad])@{ub}

Calling STORAGE()with no arguments returns the available system memory. If the

address argument is given,it must be a 4-byte string,and the function copies

data from the(optional)string into the indicated memory area. The length

parameter specifies the maximum number of bytes to be copied,and defaults to

the length of the string. If the specified length is longer than the string,the

remaining area is filled with the pad character or nulls('00'x.)



The returned value is the previous contents of the memory area. This can be

used in a subsequent call to restore the original contents.



Caution is advised in using this function. Any area of memory can be

overwritten,possibly causing a system crash. Task switching is forbidden while

the copy is being done,so system performance may be degraded if long strings

are copied.

See Also:@{"EXPORT()" LINK "EXPORT()"}

Examples:
@{i}
        say storage()                   ==>248400

        oldval = storage('0004 000'x,'The answer')

        call storage '0004 0000'x,,32,'+'
@{ui}
@ENDNODE
@NODE "STRIP()" "STRIP()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}STRIP()@{ub}

Usage:@{b}STRIP(string,[{'B' | 'L' | 'T'}],[pad])@{ub}

If neither of the optional parameters is supplied,the function removes both

leading and trailing blanks from the string argument. The second argument

specifies whether Leading,Trailing,or Both(leading and trailing)characters are

to be removed. The optional pad(or unpad,perhaps)argument selects the character

to be removed.

Examples:
@{i}
        say strip(' say what? ')                ==>'say what?'

        say strip(' say what? ','L')            ==>'say what? '

        say strip('++123+++','B','+')           ==>'123'
@{ui}
@ENDNODE
@NODE "SUBSTR()" "SUBSTR()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}SUBSTR()@{ub}	

Usage:@{b}SUBSTR(string,start,[length],[pad])@{ub}

Returns the substring of the string argument beginning at the specified start

position for the specified length. The starting position must be positive,and

the default length is the remaining length of the string. If the substring is

shorter than the requested length,it is padded on the left with the blanks or

the specified pad character.

Examples:
@{i}
        say substr('23456',4,2)         ==>45

        say substr('myname',3,6,'=')    ==>name==
@{ui}
@ENDNODE
@NODE "SUBWORD()" "SUBWORD()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}SUBWORD()@{ub}

Usage:@{b}SUBWORD(string,n,[length])@{ub}

Returns the substring of the string argument beginning with the nth word for

the specified length in words. The default length is the remaining length of

the string. The returned string will never have leading or trailing blanks.

Example:
@{i}
        say subword('Now is the time ',2,2)     ==>is the
@{ui}
@ENDNODE
@NODE "SYMBOL()" "SYMBOL()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}SYMBOL()@{ub}

Usage:@{b}SYMBOL(name)@{ub}

Tests whether the name argument is a valid REXX symbol. If the name is not a

valid symbol,the function returns the string BAD. Otherwise,the returned string

is LIT if the symbol is uninitialized and VAR if it has been assigned a value.

Examples:
@{i}
        say symbol('J')                 ==>VAR

        say symbol('x')                 ==>LIT

        say symbol('++')                -->BAD
@{ui}
@ENDNODE
@NODE "TIME()" "TIME()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}TIME()@{ub}

Usage:@{b}TIME(option)@{ub}

Returns the current system time or controls the internal elapsed time counter.

The valid option keywords are listed below.



                         @{b}TIME() Options@{ub}



        OPTION KEYWORD          DESCRIPTION

        Elapsed                 Elapsed time in seconds.

        Hours                   Current time in hours since midnight

        Minutes                 Current time in minutes since midnight

        Reset                   Reset the elapsed time clock

        Seconds                 Current time in seconds since midnight



If no option is specified,the function returns the current system time in the

form HH:MM:SS.

Examples:
@{i}
        /* Suppose that the time is 1:02 AM ...         */

        say time('Hours')               ==>1

        say time('m')                   ==>62

        say time('S')                   ==>3720

        call time 'R'                   /* reset timer  */

        say time('E')                   ==>.020
@{ui}
@ENDNODE
@NODE "TRACE()" "TRACE()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}TRACE()@{ub}

Usage:@{b}TRACE(option)@{ub}

Sets the tracing mode to that specified by the option keyword,which must be one

of the valid alphabetic or prefix options. The tracing options are described in

@{"Chapter 7" LINK "CHAPTER 7"}. The TRACE()function will alter the tracing mode even during

interactive tracing,when @{"TRACE" LINK "TRACE"} instructions in the source program are ignored.

The returned value is the mode in effect before the function call;this allows

the previous trace mode to be restored later.

Example:
@{i}
        /* Assume tracing mode is ?AL           */

        say trace('Results')            ==>?A
@{ui}
@ENDNODE
@NODE "TRANSLATE()" "TRANSLATE()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}TRANSLATE()@{ub}

Usage:@{b}TRANSLATE(string,[output],[input],[pad])@{ub}

This function constructs a translation table and uses it to replace selected

characters in the argument string. If only the string argument is given,it is

translated to uppercase. If an input table is supplied,it modifies the

translation table so that characters in the argument string that occur in the

input table are replaced with the corresponding character in the output table.

Characters beyond the end of the output table are replaced with the specified

pad character or a blank.



Note that the result string is always of the same length as the original

string. The input and output tables may be of any length.

Examples:
@{i}
        say translate("abcde","123","cbade","+")        ==>321++

        say translate("low")                            ==>LOW

        say translate("0110","10","01")                 ==>1001
@{ui}
@ENDNODE
@NODE "TRIM()" "TRIM()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}TRIM()@{ub}

Usage:@{b}TRIM(string)@{ub}

Removes trailing blanks from the string argument.

Example:
@{i}
        say length(trim(' abc  '))      ==>4
@{ui}
@ENDNODE
@NODE "UPPER()" "UPPER()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}UPPER()@{ub}

Usage:@{b}UPPER(string)@{ub}

Translates the strip to uppercase. The action of this function is equivalent to

that of @{"TRANSLATE" LINK "TRANSLATE()"}(string),but it is slightly faster for short strings.

Example:
@{i}
        say upper('One Fine Day')       ==>ONE FINE DAY
@{ui}
@ENDNODE
@NODE "VALUE()" "VALUE()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}VALUE()@{ub}

Usage:@{b}VALUE(name)@{ub}

Returns the value of the symbol represented by the name argument.

Example:
@{i}
        /* Assume that J has the value of 12            */

        say value('j')                  ==>12
@{ui}
@ENDNODE
@NODE "VERIFY()" "VERIFY()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}VERIFY()@{ub}

Usage:@{b}VERIFY(string,list,['Match'])@{ub}

If the Match argument is omitted,the function returns the index of the first

character in the string argument which is not contained in the list argument,or

0 if all of the characters are in the list. If the Match keyword is supplied,

the function returns the index of the first character which is in the list,or 0

if none of the characters are.

Examples:
@{i}
        say verify('123456','0123456789')       ==>0

        say verify('123a56','0123456789')       ==>4

        say verify('123a45','abcdefghij','m')   ==>4
@{ui}
@ENDNODE
@NODE "WORD()" "WORD()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}WORD()@{ub}

Usage:@{b}WORD(string,n)@{ub}

Returns the nth word in the string argument,or the null string if there are

fewer than n words.

Example:
@{i}
        say word('Now is the time ',2)          ==>is
@{ui}
@ENDNODE
@NODE "WORDINDEX()" "WORDINDEX()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}WORDINDEX()@{ub}

Usage:@{b}WORINDEX(string,n)@{ub}

Returns the starting position of the nth word in the argument string,or 0 if

there are fewer than n words.

Example:
@{i}
        say wordindex('Now is the time ',3)     ==>8
@{ui}
@ENDNODE
@NODE "WORDLENGTH()" "WORDLENGTH()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}WORDLENGTH()@{ub}

Usage:@{b}WORDLENGTH(string,n)@{ub}

Returns the length of the nth word in the string argument.

Example:
@{i}
        say wordlength('one two three',3)       ==>5
@{ui}
@ENDNODE
@NODE "WORDS()" "WORDS()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}WORDS()@{ub}

Usage:@{b}WORDS(string)@{ub}

Returns the number of words in the string argument.

Example:
@{i}
        say words("You don't say!")             ==>3
@{ui}
@ENDNODE
@NODE "WRITECH()" "WRITECH()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}WRITECH()@{ub}

Usage:@{b}WRITECH(file,string)@{ub}

Writes the string argument to the given logical file. The returned value is the

actual number of characters written.

Example:
@{i}
        say writech('output','Testing')         ==>7
@{ui}
@ENDNODE
@NODE "WRITELN()" "WRITELN()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}WRITELN()@{ub}

Usage:@{b}WRITELN(file,string)@{ub}

Writes the string argument to the given logical file with a "newline" appended.

The returned value is the actual number of characters written.

Example:
@{i}
        say writeln('output','Testing')         ==>8
@{ui}
@ENDNODE
@NODE "X2C()" "X2C()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}X2C()@{ub}

Usage:@{b}X2C(string)@{ub}

Converts a string of hex digits into the(packed)character representation. Blank

characters are permitted in the argument string at byte boundaries.

Examples:
@{i}
        say x2c('12ab')                         ==>'12ab'x

        say x2c('12 ab')                        ==>'12ab'x
@{ui}
@ENDNODE
@NODE "XRANGE()" "XRANGE()"
@TOC "BUILT-IN FUNCTION LIBRARY INDEX"
@{b}XRANGE()@{ub}

Usage:@{b}XRANGE([start],[end])@{ub}

Generates a string consisting of all characters numerically between the

specified start and end values. The default start character is '00'x,and the

default end character is 'FF'x. Only the first character of the start and end

arguments is significant.

Examples:
@{i}
        say xrange()                    ==>'00010203 ... FDFEFF'x

        say xrange('a','f')             ==>'abcdef'

        say xrange(,'10'x)              ==>'00010203040506070809010'x
@{ui}
@ENDNODE

@NODE "CHAPTER 7" "Chapter 7"

                        @{b}CHAPTER 7 TRACING AND INTERRUPTS@{ub}



ARexx provides tracing and source-level debugging facilities that are unusual

in a high-level language. Tracing refers to the ability to display selected

statements in a program as the program executes. When a clause is traced,its

line number,source text,and related information are displayed on the console.

The tracing action of the interpreter is determined by a trace option that

selects which source clauses will be traced,and two modifier flags that control

command inhibition and interactive tracing.



The internal interrupt system enables an ARexx program to detect certain

synchronous or asynchronous events and to take special actions when they occur.

Events such as a syntax error or an external halt request that would normally

cause the program to exit can instead be trapped so that corrective actions can

be taken.

@ENDNODE
@NODE "TRACING OPTIONS" "Tracing Options"
@{b}TRACING OPTIONS@{ub}



Trace options are sometimes called an alphabetic options,since the keywords

that select an option can be shortened to one letter for convenience. The

alphabetic options are:



@{b}ALL@{ub}. All clauses are traced.

@{b}COMMANDS@{ub}. All command clauses are traced before being sent to the external

host. Non-zero return codes are displayed on the console.

@{b}ERRORS@{ub}. Commands that generate a non-zero return code are traced after the

clause is executed.

@{b}INTERMEDIATES@{ub}. All clauses are traced,and intermediate results are displayed

during expression evaluation. These include the values retrieved for variables,

expanded compound names,and the results of function calls.

@{b}LABELS@{ub}. All label clauses are traced as they are executed. A label will be

displayed each time a transfer of control takes place.

@{b}NORMAL@{ub}. Command clauses will return codes that exceed the current error failure

level are traced after execution,and an error message is displayed. This is the

default trace option.

@{b}RESULTS@{ub}. All clauses are traced before execution,and the final result of each

expression is displayed. Values assigned to variables by ARG,PARSE,or PULL

instructions are also displayed.

@{b}SCAN@{ub}. This is a special option that traces all clauses and checks for errors,

but suppresses the actual execution of the statements. It is helpful as a

preliminary screening steop for a newly-created program.



The tracing mode can be set using either the @{"TRACE" LINK "TRACE"} instruction or the @{"TRACE()" LINK "TRACE()"}

Built-In function. The RESULTS trace option is recommended for general-purpose

testing. Tracing can be selectively disabled from within a program so that

previously-tested parts of a program can be skipped.
@ENDNODE

@NODE "DISPLAY FORMATTING" "Display Formatting"
@{b}DISPLAY FORMATTING@{ub}



Each trace line displayed on the console is indented to show the effective

control(nesting)level at that clause,and is identified by a special three-

character code,as shown in Table 7.1 below. The source for each clause is

preceded by its line number in the program. Expression results or intermediates

are enclosed in double quotes so that leading and trailing blanks will be

apparent.



                         @{b}TRACING PREFIX CODES@{ub}



                CODE            DISPLAYED VALUES

                +++             Command or syntax error

                >C>             Expanded compound name

                >F>             Result of a function call

                >L>             Label clause

                >O>             Result of a dyadic operation

                >P>             Result of a prefix operation

                >U>             Uninitialized variable

                >V>             Value of a variable

                >>>             Expression or template result

                >.>             "Placeholder" token value
@ENDNODE

@NODE "TRACING OUTPUT" "Tracing Output"
@{b}TRACING OUTPUT@{ub}



The tracing output from a program is always directed to one of two logical

streams. The interpreter first checks for a stream named @{b}STDERR@{ub},and directs the

output there if the steam exists. Otherwise the trace output goes to the

standard output stream STDOUT and will be interleaved with the normal console

output of the program. The STDERR and STDOUT streams can be opened and closed

under program control,so the programmer has complete control over the

destination of tracing output.



In some cases a program may not have a predefined output stream. For example,a

program invoked from a host application that did not provide input and output

streams would not have an output console. To provide a tracing facility for

such programs,the resident process can open a special global tracing console

for use by any active program. When this console opens,the interpreter

automatically opens a stream named STDERR for each ARexx program in which

STDERR is not currently defined,and the program then diverts its tracing output

to the new stream.



The global console can be opened and closed using the command utilities @{b}too@{ub} and

@{b}tcc@{ub},respectively. The console may not close immediately upon request,however.

The resident process waits until all active programs have diverted their

tracing streams back to the default state before actually closing the console.

Applications programs may provide direct control over the tracing console by

sending request packets to the resident process,which is discussed in 

@{"Chapter 10" LINK "CHAPTER 10"}.



The trace stream(STDERR or STDOUT)is also used for trace input,so a program in

interactive tracing mode will wait for user input from this console. The global

tracing console is always shared among all currently active programs. Since it

may be confusing to have several programs simultaneously writing to the same

console,it is recommended that only one program at a time be traced using the

global console.
@ENDNODE

@NODE "7.COMMAND INHIBITION" "Command Inhibition"
@{b}COMMAND INHIBITION@{ub}



ARexx provides a tracing mode called command inhibition that suppresses host

commands. In this mode command clauses are evaluated in the normal manner,but

the command is not actually sent to the external host,and the return code is

set to zero. This provides a way to test programs that issue potentially

destructive commands,such as erasing files or formatting disks. Command

inhibition does not apply to command clauses that are entered interactively.

These commands are always performed,but the value of the special variable @{b}RC@{ub} is

left unchanged.



Command inhibition may be used in conjunction with any trace option. It is

controlled by the "!" character,which may appear by itself or may precede any

of the alphabetic options in a @{"TRACE" LINK "TRACE"} instruction. Each occurrence of the "!"

character "toggles" the inhibition mode currently in effect. Command inhibition

is cleared when tracing is set to OFF.
@ENDNODE

@NODE "INTERACTIVE TRACING" "Interactive Tracing"
@{b}INTERACTIVE TRACING@{ub}



Interactive tracing is a debugging facility that allows the user to enter

source statements while a program is executing. These statements may be used to

examine or modify variable values,issue commands,or otherwise interact with the

program. Any valid language statements can be entered interactively,with the

same rules and restrictions that apply to the @{"INTERPRET" LINK "INTERPRET"} instruction. In

particular,compound statements such as @{"DO" LINK "DO"} and @{"SELECT" LINK "SELECT"} must be complete within

the entered line.



Interactive tracing can be used with any of the trace options. While in

interactive tracing mode,the interpreter pauses after each traced clause and

prompts for input with the code "+++." At each pause,three types of user

responses are possible.



        @{b}If a null line is entered@{ub},the program continues to the next pause

        point.

        @{b}If an "=" character is entered@{ub},the preceding clause is executed again.

        @{b}Any other input@{ub} is treated as a debugging statement,and is scanned and

        executed.



The pause points during interactive tracing are determined by the tracing

option currently in effect,as the interpreter pauses only after a traced

clause. However,certain instructions cannot be safely(or sensibly)re-executed,

so the interpreter will not pause after executing one of these. The "no-pause"

instructions are @{"CALL" LINK "CALL"},@{"DO" LINK "DO"},@{"ELSE" LINK "ELSE"},@{"IF" LINK "IF"},@{"THEN" LINK "THEN"},and @{"OTHERWISE" LINK "OTHERWISE"}. The interpreter will also

not pause after any clause that generate and execution error.



Interactive tracing mode is controlled by the "?" character,either by itself or

in combination with an alphabetic trace option. Any number of "?" characters

may precede an option,and each occurrence toggles the mode currently in effect.

For example,if the current trace option was NORMAL,then "@{i}TRACE ?R@{ui}" would set

the option to RESULTS and select interactive tracing mode. A subsequent "@{i}TRACE

?@{ui}" would turn off interactive tracing.
@ENDNODE

@NODE "ERROR PROCESSING" "Error Processing"
@{b}ERROR PROCESSING@{ub}



The ARexx interpreter provides special error processing while it executes

debugging statements. Errors that occur during interactive debugging are

reported,but do not cause the program to terminate. This special processing

applies only to the statements that were entered interactively. Errors occuring

in the program source statements are treated in the usual way whether or not

the interpreter is in interactive tracing mode.



In addition to the special error processing,the interpreter also disables the

internal interrupt flags during interactive debugging. This is necessary to

prevent an accidental transfer of control due to an error or uninitialized

variable. However,if a "SIGNAL label" instruction is entered,the transfer will

take place,and any remaining interactive input will be abandoned. The @{"SIGNAL" LINK "SIGNAL"}

instruction can still be used to alter the interrupt flags,and the new settings

will take effect when the interpreter returns to normal processing.
@ENDNODE

@NODE "THE EXTERNAL TRACING FLAG" "The External Tracing Flag"
@{b}THE EXTERNAL TRACING FLAG@{ub}



The ARexx resident process maintains an external tracing flag that can be used

to force programs into interactive tracing mode. The tracing flag can be set

using the ts command utility. When the flag is set,any program not already in

interactive tracing mode will enter it immediately. The internal trace option

is set to @{b}RESULTS@{ub} unless it is currently set to @{b}INTERMEDIATES@{ub} or @{b}SCAN@{ub},in which

case it remains unchanged. Programs invoked while the external tracing flag is

set will begin executing in interactive tracing mode.



The external tracing flag provides a way to regain control over programs that

are caught in loops or are otherwise unresponsive. Once a program enters

interactive tracing mode,the user can step through the program statements and

diagnose the problem. There is one caveat,though:external tracing is global

flag,so all currently-active programs are affected by it. The tracing flag

remains set until it is cleared using the "@{b}te@{ub}" command utility. Each program

maintains an internal copy of the last state of the tracing flag,and sets its

tracing option to @{b}OFF@{ub} when it observes that the tracing flag has been cleared.
@ENDNODE

@NODE "INTERRUPTS" "Interrupts"
@{b}INTERRUPTS@{ub}



ARexx maintains an internal interrupt system that can be used to detect and

trap certain error conditions. When an interrupt is enabled and its

corresponding condition arises,a transfer of control to the label specific to

that interrupt occurs. This allows a program to retain control in circumstances

that might otherwise cause the program to terminate. The interrupt conditions

can caused by either synchronous events like a syntax error,or asynchronous

events like a "control-C" break request. Note that these internal interrupts

are completely separate from the hardware interrupt system managed by the EXEC

operating system.



The interrupts supported by ARexx are described below. The name assigned to

each is actually the label to which control will be tranferred. Thus,a SYNTAX

interrupt will transfer control to the label "SYNTAX:." Interrupts can be

enabled or disabled using the @{"SIGNAL" LINK "SIGNAL"} instruction. For example,the instruction

"@{i}SIGNAL ON SYNTAX@{ui}" would enable the SYNTAX interrupt.



@{b}BREAK_C@{ub}. This interrupt will trap a control-C break request generated by DOS.

If the interrupt is not enabled,the program terminates immediately with the

error message "Execution halted" and returns with the error code set to 2.



@{b}BREAK_D@{ub}. The interrupt will detect and trap a control-D break request issued by

DOS. The break request is ignored if the interrupt is not enabled.



@{b}BREAK_E@{ub}. The interrupt will detect and trap a control-E break request issued by

DOS. The break request is ignored if the interrupt is not enabled.



@{b}BREAK_F@{ub}. The interrupt will detect and trap a control-F break request issued by

DOS. The break request is ignored if the interrupt is not enabled.



@{b}ERROR@{ub}. This interrupt is generated by any host command that returns a non-zero

code.



@{b}HALT@{ub}. An external halt request will be trapped if this interrupt is enabled.

Otherwise,the program terminates immediately with the error message "Execution

halted" and returns with the error code set to 2.



@{b}IOERR@{ub}. Errors detected by the I/O system will be trapped if this interrupt is

enabled.



@{b}NOVALUE@{ub}. An interrupt will occur if an uninitialized variable is used while

this condition is enabled. The usage could be within an expression,in the

@{"UPPER" LINK "UPPER"} instruction,or with the @{"VALUE()" LINK "VALUE()"} built-in function.



@{b}SYNTAX@{ub}. A syntax or execution error will generate this interrupt. Not all

errors such errors can be trapped,however. In particular,certain errors

occurring before a program is actually executing,and those detected by the

ARexx external interface,cannot be trapped by the SYNTAX interrupt.



When an interrupt forces a transfer of control,all of the currently active

control ranges are dismantled,and the interrupt that caused the transfer is

disabled. This latter action is necessary to prevent a possible recursive

interrupt loop. Only the control structures in the current environment are

affected,so an interrupt generated within a function will not affect the

caller's environment.



@{b}SPECIAL VARIABLES@{ub}. Two special variables are affected when an interrupt occurs.

The variable @{b}SIGL@{ub} is always set to the current line number before the transfer

of control takes place,so that the program can determine which source line was

being executed. When an ERROR or SYNTAX interrupt occurs,the variable @{b}RC@{ub} is set

to the error code that caused the condition. For ERROR interrupts this value

will be a command return code,and can usually be interpreted as an error

severity level. The value for SYNTAX interrupts is always an ARexx error code.



Interrupts are useful primarily to allow a program to take special

error-recovery actions. Such actions might involve informing external programs

that an error ocurred,or simply reporting further diagnostics to help in

isolating the problem. In the following example,the program issues a "message"

command to an external host called "MyEdit" whenever a syntax error is

detected:


@{i}
        /* A macro program for 'MyEdit'                 */

        signal on syntax        /* enable interrupt     */

          .

          . (normal processing)

          .

        exit

        syntax:                 /* syntax error detected*/

           address 'MyEdit'

           'message' 'error' rc errortext(rc)

           exit 10
@{ui}
@ENDNODE
@NODE "CHAPTER 8" "Chapter 8"

                        @{b}CHAPTER 8 PARSING AND TEMPLATES@{ub}



Parsing is a operation that extracts substrings from a string and assigns them

to variables. It corresponds roughly to the notion of a "formatted read" used

in other languages,but has been generalized in the several ways. Parsing is

performed using the @{"PARSE" LINK "PARSE"} instruction or its variants @{"ARG" LINK "ARG"} and @{"PULL" LINK "PULL"}. The input

for the operation is called the parse string and can come from several sources;

these source options are described with the @{"PARSE" LINK "PARSE"} instruction in @{"Chapter 4" LINK "CHAPTER 4"}.



Parsing is controlled by a template,a group of tokens that specifies both the

variables to be given values and the way to determine the value strings.

Templates were described briefly with the PARSE instruction;the present chapter

presents a more formal description of their structure and operation.

@{b}Contents@{ub}

@{"Template Structure" LINK "TEMPLATE STRUCTURE"}
@{"Template Objects" LINK "TEMPLATE OBJECTS"}
@{"The Scanning Process" LINK "THE SCANNING PROCESS"}
@{"Templates in Action" LINK "TEMPLATES IN ACTION"}

@ENDNODE

@NODE "TEMPLATE STRUCTURE" "Template Structure"
@{b}TEMPLATE STRUCTURE@{ub}



The tokens that are valid in a template are symbols,strings,operators,

parentheses,and commas. Any blanks that may be present as separators are

removed before the template is processed. The tokens in a template ultimately

serve to specify one of the two basic template objects:



Markers determine a scan position within the parse string,and

Targets are symbols to be assigned a value.



With these objects in mind,the parsing process can be described as one of

associating with each target a starting and ending position in the parse

string. The substring between these positions then becomes the value for the

target.



@{b}MARKERS@{ub}. There are three types of marker objects:



@{b}ABSOLUTE@{ub} markers specify an actual index position in the parse string,

@{b}RELATIVE@{ub} markers specify a positive or negative offset from the current

position,and

@{b}PATTERN@{ub} markers specify a position implicitly,by matching the pattern against

the parse string beginning at the current scan position.



@{b}TARGETS@{ub}. Targets,like markers,can affect the scan position if value strings are

being extracted by tokenization. Parsing by tokenization extracts words(tokens)

from the parse string, and is used whenever a target is followed immediately

by another target. During tokenization the current scan position is advanced

past any blanks to the start of the next word. The ending index is the position

just past the end of the word,so that the value string has neither leading nor

trailing blanks.
@ENDNODE

@NODE "TEMPLATE OBJECTS" "Template Objects"
@{b}TEMPLATE OBJECTS@{ub}



Each template object is specified by one or more tokens,which have the

following interpretations.



@{b}SYMBOLS@{ub}. A symbol token may specify either a target or a marker object. If it

follows an operator token(+,-,or=),it represents a marker,and the symbol value

is used as an absolute or relative position. Symbols enclosed in parentheses

specify pattern markers,and the symbol value is used as the pattern string.



If neither of the preceding cases applies and the symbol is a variable,then it

specifies a target. Fixed symbols always specify absolute markers and must be

whole numbers,except for the period(.)symbol which defines a placeholder

target.



@{b}STRINGS@{ub}. A string token always represents a pattern marker.



@{b}PARENTHESES@{ub}. A symbol enclosed in parentheses is a pattern marker,and the value

of the symbol is used as the pattern string. While the symbol may be either

fixed or variable,it will usually be a variable,since a fixed pattern could be

given more simply as a string.



@{b}OPERATORS@{ub}. The three operators "+,"-,"and "=" are valid within a template,and

must be followed by a fixed or variable symbol. The value of the symbol is used

as a marker and must therefore represent a whole number. The "+" and "-"

operators signify a relative marker,whose value is negated by the "-" operator.

The "=" operator indicates an absolute marker,and is optional if the marker is

defined by a fixed symbol.



@{b}COMMAS@{ub}. The comma(,)marks the end of a template,and is used as a separator when

multiple templates are provided with an instruction. The interpreter obtains a

new parse string before processing each succeeding template. For some source

options,the new string will be identical to the previous one. The @{b}ARG@{ub}, @{b}EXTERNAL@{ub},

and @{b}PULL@{ub} options will generally supply a different string,as will the @{b}VAR@{ub}

option if the variable has been modified.
@ENDNODE

@NODE "THE SCANNING PROCESS" "The Scanning Process"
@{b}THE SCANNING PROCESS@{ub}



Scan positions are expressed as an index in the parse string,and can range from

1(the start of the string)to the length of the string plus 1(the end). An

attempt to set the scan position before the start or after the end of the

string instead sets it to the beginning or end,respectively.



The substring specified by two scan indices includes the characters from the

starting position up to,but not including,the ending position. For example,the

indices 1 and 10 specify characters 1-9 in the parse string. One additional

rule is applied if the second scan index is less than or equal to the first: in

this case the remainder of the parse string is used as the substring. This

means that a template specificaiton like

@{i}
        parse arg 1 all 1 first second
@{ui}

will assign the entire parse string to the variable ALL. Of course,if the

current scan index is already at the end of the parse string,then the remainder

is just the null string.



When a pattern marker is matched against the parse string,the marker position

is the index of the first character of the matched pattern,or the end of the

string if no match was found. The pattern is removed from the string whenever a

match is found. This is the only operation that modifies the parse string

during the parsing process.



Templates are scanned from left to right with the initial scan index set to 1,

the start of the parse string. The scan position is updated each time a marker

object is encountered,according to the type and value of the marker. Whenever a

target object is found,the value to be assigned is determined by examining the

next template object. If the next object is another target,the value string is

determined by tokenizing the parse string. Otherwise,the current scan position

is used as the start of the value string,and the position specified by the

following marker is used as the end point.



The scan continous until all of the objects in the template have been used.

Note that every target will be assigned a value;once the parse string has been

exhausted,the null string is assigned to any remaining targets.
@ENDNODE


@NODE "TEMPLATES IN ACTION" "TEMPLATES IN ACTION"
@{b}TEMPLATES IN ACTION@{ub}



The preceding section is rather abstract,so let's look now at some examples of

parsing with templates.

@{"Parsing by Tokenization" LINK "PARSING BY TOKENIZATION"}
@{"Pattern Parsing" LINK "PATTERN PARSING"}
@{"Positional Markers" LINK "POSITIONAL MARKERS"}
@{"Multiple Templates" LINK "MULTIPLE TEMPLATES"}

@ENDNODE

@NODE "PARSING BY TOKENIZATION" "Parsing by Tokenization"
@{b}PARSING BY TOKENIZATION@{ub}



Computer programs frequently require splitting a string into its component

words or tokens. This is easily accomplished with a template consisting

entirely of variables(targets).


@{i}
        /* Assume "hammer 1 each $600.00" was entered   */

        pull item qty untils cost .
@{ui}


In this example the input line from the @{"PULL" LINK "PULL"} instruction is split into words

and assigned to the variables in the template. The variable item receives the

value "hammer," qty is set to "1," units is set to "each," and cost gets the

value "$600.00." The final placeholder(.) is given a null value,since there are

only four words in the input. However,it forces the preceding variable cost to

be given a tokenized value. If the placeholder were omitted,the remainder of

the parse string would be assigned to cost,which would then have a leading

blank.



In the next example,the first word of a string is removed and the remainder is

placed back in the string. The process continues until no more words are

extracted.

@{i}
        /* Assume "result" contains a string of words   */

        do forever

           /* Get first word of string                  */

           parse var result first result

           if first == '' then leave

           /* ... process words ...                     */

           end
@{ui}
@ENDNODE

@NODE "PATTERN PARSING" "PATTERN PARSING"
@{b}PATTERN PARSING@{ub}



The next example uses pattern markers to extract the desired fields. The

"pattern" in this case is very simple -- just a single character -- but in

general can be an arbitrary string of any length. This form of parsing is

useful whenever delimiter characters are present in the parse string.


@{i}
        /* Assume an argument string "12,34.5,1         */

        arg hours ',' rate ',' withhold
@{ui}


Keep in mind that the pattern is actually removed from the parse string when a

match is found. If the parse string is scanned again from the beginning,the

length and structure of the string may be different than at the start of the

parsing process. However,the original source of the string is never modified.
@ENDNODE

@NODE "POSITIONAL MARKERS" "POSITIONAL MARKERS"
@{b}POSITIONAL MARKERS@{ub}



Parsing with positional markers is used whenever the fields of interest are

known to be in certain positions in a string. In the next example,the records

being processed contain a variable length field. The starting position and

length of the field are given in the first part of the record,and a variable

positional marker is used to extact the desired field.


@{i}
        /* records look like:                           */

        /* start:   1-5                                 */

        /* length:  6-10                                */

        /* name:    @(start,length)                     */

        parse value record with 1 start +5 length +5 =start name +length
@{ui}


The "@{i}=start@{ui}" sequence in the above example is an absolute marker whose value is

the position paced in the variable start earlier in the scan. The "@{i}+length@{ui}"

sequence supplies the effective length of the field.
@ENDNODE

@NODE "MULTIPLE TEMPLATES" "Multiple Templates"
@{b}MULTIPLE TEMPLATES@{ub}



It is sometimes useful to specify more than one template with an instruction,

which can be done by separating the templates with a comma. In this next

example,the @{"ARG" LINK "ARG"} instruction(or @{"PARSE" LINK "PARSE"} UPPER ARG)is used to access the argument

strings provided when the program was called. Each template accesses the

succeeding argument string.


@{i}
        /* Assume arguments were ('one two',12,sort)    */

        arg first second,amount,action,option
@{ui}


The first template consists of the variables first and second,which are set to

the values "one" and "two,"respectively. In the next two templates amount gets

the value "12" and action is set to "SORT". The last template consists of the

variable "option,"which is set to the null string,since only three arguments

were available.



When multiple templates are used with the EXTERNAL or PULL source options,each

additional template requests an additional line of input from the user. In the

next example two lines of input are read:


@{i}
        /* read last,first,and middle names and ssn     */

        pull last ',' first middle,ssn
@{ui}


The first input line is expected to have three words,the first of which is

followed by a comma,which are assigned to the variables last,first,and middle.

The entire second input line is assigned to the variable ssn.



Multiple templates can be useful even with a source option that returns the

identical parse string. If the first template included pattern markers that

altered the parse string,the subsequent templates could still access the

original string. Note that subsequent parse strings obtained from the VALUE

source do not cause the expression to be reevaluated,but only retrieve the

prior result.
@ENDNODE


@NODE "CHAPTER 9" "Chapter 9"

                        @{b}CHAPTER 9 THE RESIDENT PROCESS@{ub}



This chapter describes some of the capabilities of the ARexx resident process,

a global communications and resources manager. The material presented here is

directed to the general user;@{"Chapter 10" LINK "CHAPTER 10"} covers these topics in greater depth

for software developers who wish to integrate ARexx with other applications

programs.



The resident process must be active before any ARexx programs can be run. It

announces its presence to the system by opening a public message port named

"@{b}REXX@{ub},"so applications programs that use ARexx should check for the presence of

this port. If the port is not open,the user can either be informed that the

macro processor is not available,or else the applications program can start up

the resident process. The latter option can be done using the @{b}rexxmast@{ub} command.



The primary function of the resident process is to launch ARexx programs. When

an applications program sends a "command" or "function" message to the "REXX"

port,the resident process creates a new DOS process to execute the program, and

forwards the invocation message to newly created process. It also creates a new

instance of the ARexx global data structure,which links together all of the

structures manipulated by the program.



In addition to launching programs,the resident process managers various

resources used by ARexx. These resources include a list of available function

libraries called @{"the Library List" LINK "THE LIBRARY LIST"},a list of(name,value)pairs called the Clip

List,and a list of the currently active ARexx programs. Built-In functions are

available to manipulate the Library List and Clip List from within an ARexx

program. Applications programs can modify a resource list either by sending a

request packet to the resident process or by direct manipulation of the list.
@ENDNODE

@NODE "COMMAND UTILITIES" "Command Utilities"
@{b}COMMAND UTILITIES@{ub}



ARexx is supplied with a number of command utilities to provide various control

functions. These are executable modules that can be run from the CLI,and should

reside in the system command(C:)directory for convenience. These commands are

relevant only when the ARexx resident process is active.



The functions performed by these utilities may also be available from within an

applications program. All of the utilities are implemented by sending message

packets to the resident process,so an application designed to work closely with

ARexx could easily provide these functions as part of its control menu.


@{b}Contents@{ub}

@{"HI" LINK "HI"}
@{"RX" LINK "RX"}
@{"RXSET" LINK "RXSET"}
@{"RXC" LINK "RXC"}
@{"TCC" LINK "TCC"}
@{"TCO" LINK "TCO"}
@{"TE" LINK "TE"}
@{"TS" LINK "TS"}

@ENDNODE

@NODE "HI" "HI"
@TOC "COMMAND UTILITIES"
@{b}HI@{ub}

Usage:@{b}HI@{ub}

Sets the global halt flag,which causes all active programs to receive an

external halt request. Each program will exit immediately unless its HALT

interrupt has been enabled. The halt flag does not remain set,but is cleared

automatically after all current programs have received the request.

@ENDNODE
@NODE "RX" "RX"
@TOC "COMMAND UTILITIES"
@{b}RX@{ub}

Usage:@{b}RX name[arguments]@{ub}

This command launches an ARexx program. If the specified name includes an

explicit path,only that directory is searched for the program;otherwise,the

current directory and the system REXX: device are checked for a program with

the given name. The optional argument string is passed to the program.

@ENDNODE
@NODE "RXSET" "RXSET"
@TOC "COMMAND UTILITIES"
@{b}RXSET@{ub}

Usage:@{b}RXSET name value@{ub}

Adds a(name,value)pair to @{"the Clip List" LINK "THE CLIP LIST"}. Name strings are assumed to be in

mixed case. If a pair with the same name already exists,its value is replaced

with the current string. If a name without a value string is given,the entry is

removed from the Clip List.

@ENDNODE
@NODE "RXC" "RXC"
@TOC "COMMAND UTILITIES"
@{b}RXC@{ub}

Usage:@{b}RXC@{ub}

Closes the resident process. The "REXX" public port is withdrawn immediately,

and the resident process exits as soon as the last ARexx program finishes. No

new programs can be launched after a "close" request.

@ENDNODE
@NODE "TCC" "TCC"
@TOC "COMMAND UTILITIES"
@{b}TCC@{ub}

Usage:@{b}TCC@{ub}

Closes the global tracing console as soon as all active programs are no longer

using it. All read read requests queued to the console must be satisfied before

it can be closed.

@ENDNODE
@NODE "TCO" "TCO"
@TOC "COMMAND UTILITIES"
@{b}TCO@{ub}

Usage:@{b}TCO@{ub}

Open the global tracing console. The tracing output from all active programs is

diverted automatically to the new console. The console window can be moved and

resized by the user,and can be closed with the "@{"TCC" LINK "TCC"}" command.
@ENDNODE

@NODE "TE" "TE"
@TOC "COMMAND UTILITIES"
@{b}TE@{ub}

Usage:@{b}TE@{ub}

Clears the global tracing flag,which forces the tracing mode to @{b}OFF@{ub} for all

active ARexx programs.
@ENDNODE

@NODE "TS" "TS"
@TOC "COMMAND UTILITIES"
@{b}TS@{ub}

Usage:@{b}TS@{ub}

Starts interactive tracing by setting the external trace flag,which forces all

active ARexx programs into interactive tracing mode. Programs will start

producing trace output and will pause after the next statement. This command is

useful for regaining control over programs caught in infinite loops or

otherwise misbehaving. The trace flag remains set until cleared by the @{"TE" LINK "TE"}

command,so subsequent program invocations will begin executing in interactive

tracing mode.
@ENDNODE

@NODE "RESOURCE MANAGEMENT" "Resource Management"
@{b}RESOURCE MANAGEMENT@{ub}



Individual ARexx programs manage their internal memory allocation and I/O file

resources,but some resources need to be available to all programs. The

management of these global resources is one of the major functions of the

resident process. Global resources are maintained as doubly-linked lists,in

keeping with the general design principles of the EXEC operating system. Linked

lists provide a flexible and open mechanism for resource management,and help

avoid the built-in limits common with other approaches.
@ENDNODE

@NODE "THE GLOBAL TRACING CONSOLE" "The Global Tracing Console"
@{b}THE GLOBAL TRACING CONSOLE@{ub}



The tracing output from an ARexx program usually goes to the standard output

stream STDOUT,and is therefore interleaved with the normal output of the

program. Since this may be confusing at times,a global trace console can be

opened to display only tracing output. The console can be opened using the @{"tco" LINK "TCO"}

command utility or be sending an @{b}RXTCOPN@{ub} request packet to the resident

process. ARexx programs will automatically divert their tracing output to the

new window,which is opened as a standard AmigaDOS console. The user can move it

and resize it as required.



The tracing console also serves as the input stream for programs during

interactive tracing. When a program pauses for tracing input,the input line

must be entered at the trace console. Any number of programs may use the

tracing console simultaneously,although it is generally recommended that only

one program at a time be traced.



The tracing console can be closed using the tcc command or by sending an

@{b}RXTCCLS@{ub} request packet to the resident process. The closing is delayed until

all read requests to the console have been satisfied. Only when all of the

active programs indicate that they are no longer using the console will it

actually be closed.
@ENDNODE

@NODE "THE LIBRARY LIST" "The Library List"
@{b}THE LIBRARY LIST@{ub}



The resident process maintains a Library List of the function libraries and

function hosts currently available to ARexx programs. This list is used to

resolve all references to external functions. Each entry has an associated

search priority in the range 100 to -100,with the higher-valued entries being

searched first until the requested function is found. The list is searched by

calling each entry,using the appropriate protocol,until the return code

indicates that the function was found.



The two types of entities maintained by the list are quite different in some

respects,but the ultimate way in which a function call is resolved is

transparent to the calling program. A function library is a collection of

functions organized as an Amiga shared library,while a function host is a

separate task that manages a message port. Function libraries are called as

part of the ARexx interpreter's task context,but calls to function hosts are

mediated by passing a message packet. The ARexx resident process is itself a

function host,and is installed in the Library List at a priority of -60.



The resident process provides addition and deletion operations for maintaining

the Library List;these operations are performed by sending an appropriate

message packet. The Library List is always maintained in priority order. Within

a given priority level any new entries are added to the end of the chain, so

that entries added first will be searched fist. The priority levels are

significant if any of the libraries have duplicate function name

definitions,since the function located further down the search chain could

never be called.
@ENDNODE

@NODE "FUNCTION LIBRARIES" "Function Libraries"
@{b}FUNCTION LIBRARIES@{ub}. Each function library entry in @{"the Library List" LINK "THE LIBRARY LIST"} contains a

library name,a search priority,an entry point offset,and a version number. The

library name must refer to a standard Amiga shared library residing in the

system LIBS: directory so that it can be loaded when needed. Function libraries

can be created and maintained by users or applications developers;@{"Chapter 10" LINK "CHAPTER 10"}

has information on their design and implementation.



The "@{b}query@{ub}" function is the library entry point that is actually called by the

interpreter. It must be specified as an integer offset(e.g. "-30")from the

library base. The return code from the query call then indicates whether the

desired function was found;it it was,the function is called with the parameters

passed by the interpreter and the function result is returned to the caller.

Otherwise,the search continues with the next entry in the list. In either event

the library is closed to await the next call.



@{b}A note of caution@{ub}: not every Amiga shared library can be used as a function

library. Function libraries must have a special entry point to perform the

dynamic linking required to access the functions from within ARexx. Each

library should include documentation providing its version number and the

integer offset to its "query" entry point.
@ENDNODE

@NODE "9.FUNCTION HOSTS" "Function Hosts"
@{b}FUNCTION HOSTS@{ub}. The name associated with a function host is the name of its

public message port. Function calls are passed to the host as a message packet;

it is then up to the individual host to determine whether the specified

function name is one that it recognizes. The name resolution is completely

internal to the host,so function hosts provide a natural gateway mechanism for

implementing remote procedure calls to other machines in a network.
@ENDNODE

@NODE "THE CLIP LIST" "The Clip List"
@{b}THE CLIP LIST@{ub}



The Clip List maintains a set of(name,value)pairs that may be used for a

variety of purposes. Each entry in the list consists of a name and a value

string,and may be located by name. Since the Clip List is publicly accessible,

it may be used as a general clipboard-like mechanism for intertask

communication. In general,the names used should be chosen to be unique to an

application to prevent collisions with other programs. Any number of entries

may be posted to the list.



One potential application for the Clip List is as a mechanism for loading

predefined constants into an ARexx program. The language definition does not

include a facility comparable to the "header file" preprocessor in the "C"

language. However,consider a string in the Clip List of the form


@{i}
        pi=3.14159; e=2.718; sqrt2=1.414 ...
@{ui}


i.e.,a series of assignments separated by semicolons. In use,such a string

could be retrieved by name using the Built-In function @{"GETCLIP()" LINK "GETCLIP()"} and then

@{"INTERPRET" LINK "INTERPRET"}ed within the program. The assignment statements within the string

would then create the required constant definitions. The following program

fragment illustrates the process::


@{i}
        /* assume a string called "numbers" is available*/

        numbers=getclip('numbers')    /* case-sensitive */

        interpret numbers             /* ... assignments*/

        ...
@{ui}


More generally,the strings would not be restricted to contain only assignment

statements,but could include any valid ARexx statements. The Clip List could

thus provide a series of programs for initializations or other processing

tasks.



The resident process supports addition and deletion operations for maintaining

the Clip List. The names in the(name,value)pairs are assumed to be in mixed

cases,and are maintained to be unique in the list. An attempt to add a string

with an existing name will simply update the value string. The name and value

strings are copied when an entry is posted to the list,so the program that adds

an entry is not required to maintain the strings.



Entries posted to the Clip List remain available until explicitly removed. The

Clip List is automatically released when the resident process exits.

@ENDNODE

@NODE "CHAPTER 10" "Chapter 10"

                        @{b}CHAPTER 10 INTERFACING TO AREXX@{ub}



This chapter discusses the issues involved in designing and implementing an

interface between ARexx and an external applications program. The material

presented here is directed to software developers,so a high degree of

familiarity with programming the Amiga in either "C" or assembly-language is

assumed.



ARexx can interact with external programs in several ways. The command

interface is used to communicate with an external program running as a separate

task in the Amiga's multitasking environment. The interaction takes place by

passing messages between public message ports,and is in many ways similar to

the interaction of a program with Intution,the Amiga's window and menu manager.

The command interface provides both a means of sharing data and a method of

controlling an applications program.



@{"Function libraries" LINK "FUNCTION LIBRARIES"} provide a mechanism for calling external code as part of an

ARexx program's tasks context. The linkages for such calls are established

dynamically at run time rather than when the program is linked,so each function

library must include an entry point to match function names with the address of

the function to be called.



@{"Function hosts" LINK "FUNCTION HOSTS"} are external tasks that manage a public message port for

communicating with ARexx or other programs. Both function hosts and function

libraries are managed by the Library List,which provides a prioritized search

mechanism for resolving function names. Function hosts may be used as a gateway

into a metwork to provide a remote procedure call facility. ARexx imposes no

constraints on the internal operations of a function host,except to require

that message packets be returned with an appropriate code.



@{b}The resident process@{ub} acts as the hub for communications between ARexx and

external entities. It opens and manages a public message port named "REXX," and

provides a number of support services. Note that the resident process is itself

a "host application" whose function it is to launch ARexx programs and maintain

global resources. The activation structures for all ARexx programs are linked

into a list maintained by the resident process,and in principle their compete

internal states are accessible to external programs.



@{b}The ARexx interpreter@{ub} is structured as an Amiga shared library and includes

entry points specifically designed to help implement an interface to ARexx.

Functions are available to create and delete message packets,argument

strings,and other resources. Software developers are rged to use these library

routines whenever possible,as they provide "safe" access to the internal

structures. The ARexx Systems Library functions are documented in @{"Appendix C" LINK "APPENDIX C"}.
@ENDNODE

@NODE "BASIC STRUCTURES" "Basic Structures"
@{b}BASIC STRUCTURES@{ub}



Most developers will need to work with only two of the data structures used by

ARexx. The RexxArg structure is used for all of the strings manipulated by the

interpreter. It is usually passed as an argstring,a pointer offset from the

structure base that may be treated like an ordinary string pointer. The RexxMsg

structure is an extension of an EXEC Message,and is the message packet used for

all communications with external programs.



@{b}ARGSTRINGS@{ub}. All ARexx strings are maintained as @{b}RexxArg@{ub} structures,which are

diagrammed in Table 10.1 below. Note that his actually a variable-length

structure allocated for each specific string length. String parameters are sent

in the form of argstrings,a pointer to the string buffer area of the RexxArg

structure. The string in the stucture is always given a trailing null byte,so

that external programs can treat argstrings like a pointer to a null-terminated

string. Additional data about the string(its length,hash code,and attributes)

are available at negative offsets from the argstring pointer.



                         @{b}The RexxArg Structure@{ub}



                STRUCTURE RexxArg,0

                LONG    ra_Size         ; allocated length

                UWORD   ra_Length       ; length of string

                UBYTE   ra_Flags        ; attribute flags

                UBYTE   ra_Hash         ; hash code

                STRUCT  ra_Buff,8       ; buffer (argstring points here)



Library functions are available to create and delete argstrings,and for

converting integers into argstring format. The function @{"CreateArgstring()" LINK "CreateArgstring()"}

allocates a structure and copies a string into it,and returns an argstring

pointer to the structure. The function @{"DeleteArgstring()" LINK "DeleteArgstring()"} can be used to release

an argstring when it is no longer needed.



@{b}MESSAGE PACKETS@{ub}. All communications between ARexx and external programs are

mediated with with message packets,whose structure is diagrammed in @{"Table 10.2" LINK "TABLE 10.2"}

below. Functions are provided in the ARexx Systems Library to create,

initialize,and delete these message packets. Each packet sent from ARexx to an

external program is marked with a special pointer in its name field. This can

be used to distinguish the message packets from those belonging to other

programs,in case a message port is being shared.



Message packets are created using the @{"CreateRexxMsg()" LINK "CreateRexxMsg()"} function,and can be

released using the @{"DeleteRexxMsg()" LINK "DeleteRexxMsg()"}. Note that the message packets passed by

ARexx to a host application(as a command,for instance)are identical to the

packets the host would use to invoke an ARexx program. This commonality of

design means that only one set of functions is needed to create and delete

message packets,and that external programs can use the same routines that the

interpreter uses to handle the packets.



@{b}RESOURCE NODES@{ub}. A somewhat higher-level data structure called a "resource node"

(a @{b}RexxRsrc@{ub} structure)is used extensively within ARexx to maintain resource

lists. These nodes are variable-length structures that include the total

allocated length as a field within the node,and that also provide for an

"auto-delete" function. This latter capability allows the address of a clean-up

function to be associated with the node so that an entire(possibly

inhomogeneous)list of resource nodes can be deallocated with a single function

call.
@ENDNODE

@NODE "TABLE 10.2" "The RexxMsg Structure"
                         @{b}The RexxMsg Structure@{ub}



                STRUCTURE RexxMsg,MN_SIZE

                APTR    rm_TaskBlock    ; global pointer

                APTR    rm_LibBase      ; library pointer

                LONG    rm_Action       ; command code

                LONG    rm_Result1      ; primary result

                LONG    rm_Result2      ; secondary result

                STRUCT  rm_Args,16*4    ; arguments (ARGO-ARG15)

                                     ;  the extension area

                APTR    rm_PassPort     ; forwarding port

                APTR    rm_CommAddr     ; host address

                APTR    rm_FileExt      ; file extention

                LONG    rm_Stdin        ; input stream

                LONG    rm_Stdout       ; output steam

                LONG    rm_avail        ; reserved

                LABEL   rm_SIZEOF       ; 128 bytes
@ENDNODE

@NODE "DESIGNING A COMMAND INTERFACE" "Designing a Command Interface"
@{b}DESIGNING A COMMAND INTERFACE@{ub}



The minimal command interface between ARexx and an applications program

requires only a public message port and a routine to process the commands

received. For most host applications this will require little extra machinery,

as the program will probably already have several message ports for key and

menu events,timer messages,and so on. Processing the command strings should be

relatively straightforward for command-oriented applications. Hosts that are

entirely menu-driven will require somewhat more additional programming,unless

commands are supported only as simulated menu events. The specific choice of

which commands to support is always left up to the applications designer,as

ARexx imposes no restrictions on the structure of the commands that can be

issued.



The basic sequence of events in the command interface begins when the host

sends a command invocation message to the ARexx resident process. This is

usually in response primitives supported by the host. When the resident process

receives the message packet,it spawns a new DOS process the run the macro

program. The command line is parsed to extract the command token(the first

word),and the interpreter searches for a file that matches the command name.



Once a macro program file has been found,it is executed by the interpreter and

(usually)results in one or more commands being issued back to the host

application's public port. The macro program waits while each command is

processed by the host,and takes appropriate actions if the return code

indicates that an error occurred. Eventually the macro program finishes and

returns the invocation message packet back to the host.



Error handling is an important consideration in the interface design. Macro

programs must receive return codes so that processing actions can be altered

when errors occur.



Normally,the host application should not return a message packet until the

command has been processed and its error status in known. Hosts that support

two streams of commands(from the user and from the command interface)will need

a flag to indicate the source of each command. Errors in user commands might

normally be reported on the screen,but errors in ARexx commands must be

reported by setting the result field in the message packet.



@{b}Return codes@{ub} should generally be chosen to follow the model of an error

severity level,with small integers representing relatively harmless conditions

and larger values indicating progressively more severe errors. This will allow

a characteristic failure level to be established within a macro program,so that

insignificant errors can be ignored. The choice of the specific return code

values is left to the applications designer.
@ENDNODE

@NODE "RECEIVING COMMAND MESSAGES" "Receiving Command Messages"
@{b}RECEIVING COMMAND MESSAGES@{ub}



Each host application must open a public message port to support the command

interface. When a macro program issues a command to the host,a message packet

containing the command is sent to this public port. The structure of these

message packets is shown in @{"Table 10.2" LINK "TABLE 10.2"}. The @{b}rm_Action@{ub} field will be set to

@{b}RXCOMM@{ub},and the ARGO parameter slot will contain the command as an argstring

pointer. Parameter slots ARG1-ARG15 are not used for command messages. Two

other fields are potentially of interest: the @{b}rm_RexxTask@{ub} field contains a

pointer to the global data structure for the program that issued the command,

and the @{b}rm_LibBase@{ub} field has the ARexx library base address. The fields in the

extension area may also be of interest to the host program;these are described

later on. Except for setting the result fields @{b}rm_Result1@{ub} and @{b}rm_Result2@{ub},the

host application should not alter the message packet.
@ENDNODE

@NODE "RESULT FIELDS" "Result Fields"
@{b}RESULT FIELDS@{ub}



When the host program finishes processing the command,it must set the primary

result field rm_Result1 to an error severity level or zero if no errors

occurred. This is the field which will be assigned to the special variable @{b}RC@{ub}

in the macro program. The secondary result field @{b}rm_Result2@{ub} should be set to

zero unless a result string(as described below)is being returned. The packet

can then be returned to the sender using the EXEC function @{b}ReplyMsg()@{ub}.



In some cases a macro program may request a result string by setting the

@{b}RXFB_RESULT@{ub} modifier bit in the command code. If possible,the host application

should then return the result as an argstring pointer in the secondary result

field @{b}rm_Result2@{ub}. A result string should only be returned if explicitly

requested and if no errors occurred during the call(@{b}rm_Result1@{ub} set to zero).

Failure to observe these rules will result either in memory loss or in

corruption of the system free-memory list.
@ENDNODE

@NODE "MULTIPLE HOST PROCESSES" "Multiple Host Processes"
@{b}MULTIPLE HOST PROCESSES@{ub}



Many applications programs support concurrent activities on several sets of

data. For example,most text editors allow several files to be edited at once. A

command issued from a particular instance of the editor might invoke an ARexx

macro program,so clearly any commands issued from that macro would have to be

directed to the correct instance of the editor. ARexx provides for this by

allowing the applications program to declare an initial host address when a

program is invoked. A separate message port would be opened for each instance

of the host application,and this port would be named as the initial host

address for all invocations from that instance. In the example above,if the

editor opened two ports named "MyEdit1" and "MyEdit2,"then programs invoked by

the "MyEdit1" instance would send commands back to the "MyEdit1" port.



@{b}MULTIPLE MESSAGE PORTS@{ub}. Host applications are not limited to having a single

message port for commands. If several different kinds of commands are to be

received,it might be appropriate to set up more than one port. Macro programs

would then use the @{"ADDRESS" LINK "ADDRESS"} instruction to direct commands to the appropriate

port. The different ports could be used simultaneously,since ARexx programs

execute as separate tasks.
@ENDNODE

@NODE "INVOKING AREXX PROGRAMS" "Invoking ARexx Programs"
@{b}INVOKING AREXX PROGRAMS@{ub}



ARexx programs are invoked by sending a message packet to the resident process.

Programs may be invoked as either a command or as a function. The command mode

of invocation is generally simpler,as it requires setting only a few fields in

the message packet.
@ENDNODE

@NODE "MESSAGE PACKETS" "Message Packets"
@{b}MESSAGE PACKETS@{ub}



The structure of the message packet supported by ARexx is shown in @{"Table 10.2" LINK "TABLE 10.2"}.

This structure provides fields for passing arguments and for specifying

overrides to various internal defaults. The packets are cleared(set to 0)when

allocated,and the client-supplied fields are never altered by ARexx. Message

packets can be reused after being returned,and generally only one is required.



@{b}COMMAND(ACTION)CODE@{ub}. The @{b}rm_Action@{ub} field of the message packet determines the

mode of invocation. It can be set to either @{b}RXCOMM@{ub} or @{b}RXFUNC@{ub} for command or

function mode,respectively. Several modifier flags can be used with the command

code;these are described later in this chapter.



@{b}ARGUMENT STRINGS@{ub}. Command strings,function names,and argument strings must be

supplied as argstrings. Strings can be conveniently packaged into argstrings

using the @{"CreateArgstring()" LINK "CreateArgstring()"} library function,which takes a string pointer and a

length as its arguments. Argstrings point to a null-terminated string and may

be treated like an ordinary string pointer in most cases. In principle,a host

application could build the argstrings directly,but since the strings must

remain unchanged for the duration of a ARexx program,the host might need to

maintain many such structures.



The argstrng pointer returned by @{"CreateArgstring()" LINK "CreateArgstring()"} is installed in the

appropriate parameter slot of the message package:ARGO for the command string

or function name,and ARG1-ARG15 for argument strings. Argstrings can be

recycled after a packet has returned by calling the @{"DeleteArgstring()" LINK "DeleteArgstring()"} function.



@{b}SENDING THE PACKET@{ub}. Once the required fields have been filled in,the host

application can send the packet to the "REXX" public port using the EXEC

function PutMsg(). The address of the "REXX" port can be obtained by a call to

the FindPort()function,but this address should not be cached internally,since

the port could close at any time. To be absolutely safe,the calls to FindPort()

and PutMsg()should be bracketed by calls to the EXEC routines Forbid()and

Permit(). This will exclude the slight possibility that the message port could

close in the few microseconds before the message packet is actually sent to the

port address.



After sending the packet the host can return to its normal processing,since the

macro program will execute as a separate task. In most cases it will be

advisable to "lock-out" further user commands while the ARexx program is

running,to preserve te integrity of any shared data structures that may be

accessed externally.
@ENDNODE

@NODE "COMMAND INVOCATIONS" "Command Invocations"
@{b}COMMAND INVOCATIONS@{ub}



In the command mode of invocation the host supplies a command string consisting

of a name token followed by an argument string. ARexx parses the string to

extract the command name,which is usually the name of a program file. The

default action is to use the remainder of the command string as the(single)

argument string for the program. This may be overridden by requesting command

tokenization,which is done by setting the @{b}RXFB_TOKEN@{ub} modifier flag in the

action code of the message packet. In this case the entire command string will

be parsed,and the program may have many argument strings.(There is no limit to

the number of arguments that may be derived from the command string,since they

don't have to fit into the parameter slots of the message packet.)



The parsing process uses "white space" (blanks,tabs,etc.)as the token

separators,and has a several special features.



@{b}QUOTING CONVENTION@{ub}. Either single(')or double(")quotes may be used to surround

items that include "white space" and would otherwise be separated during

parsing. Single quotes may appear within a double-quote-delimited token,and

vice versa;however,double-delimiter sequences are not accepted. The quotes are

removed from the parsed token. An "implicit" quote at the end of the string is

also recognized. If the command string ends before the closing delimiter has

been found,the null byte is accepted as the final delimiter. For example,

@{i}
        look.rexx "Now is the time" "can't you see"
@{ui}

is a command with the two arguments strings "Now is the time" and "can't you

see"(but without the quotes.)



@{b}STRING FILES@{ub}. If the command name(the first token of the string)is quoted,it is

assumed to be a "string file" --an ARexx program in a string,rather than the

name of a disk file. This is a convenient way to run very brief programs,

although programs of any length may be stored this way. If command tokenization

has not been specified,the remainder of the string is not scanned and no quote

characters are removed. In this case the quoting convention isuseful only for

indicating "string file" programs. The entire command string can be declared as

a "string file" by setting the @{b}RXFB_STRING@{ub} modifier flag of the action code.

When this flag is set,no parsing at all is applied to the command.



@{b}RESULT STRING@{ub}. Command invocations do not usually request a result string,but

can do so by setting the @{b}RXFB_RESULT@{ub} modifier flag. The host application must

be prepared to recycle the returned result string once it is no longer needed.
@ENDNODE


@NODE "FUNCTION INVOCATIONS" "Function Invocations"
@{b}FUNCTION INVOCATIONS@{ub}



In a function invocation the host application supplies a function name string

and from 0 to 15 argument strings. The name string is used to locate an

external program file and may include directory specifiers and a file

extension. The actual argument count(not including the name string)must be

placed in the low-order byte of the command code.



This mode of invocation is normally used when a result string is expected and

the argument strings are conveniently available. Note that a result does not

have to be requested,however.



@{b}RESULT STRINGS@{ub}. Function invocations request a result string by setting the

@{b}RXFB_RESULT@{ub} modifier flag bit. If no errors occurred and a result string was

requested,the secondary result field in the returned packet will be a pointer

to the result string. However,if the program exited without supplying a result,

the secondary field will be zero.



@{b}STRING FILES@{ub}. The function name argument may specify a "string file" rather

than the name of a filing system object. This is indicated by setting the

@{b}RXFB_STRING@{ub} modifier flag.
@ENDNODE

@NODE "10.SEARCH ORDER" "Search Order"
@{b}SEARCH ORDER@{ub}



The search for a program file matching a command or function name is normaly a

two-step process. For each directory to be checked,a search is made first with

the current file extension appended to the name string. If this search fails,

the second search uses the unmodified name string. The first step is skipped if

the command or function name includes an explicit file extension.



The default file extension is ".rexx,"but this can be changed by supplying a

file extension string in an extended message packet. Host applications will

usually specify a file extension,since it provides a convenient way to

distinguish the macro programs that are specific to that application. Refer to

the section on @{"Extension Fields" LINK "EXTENSION FIELDS"} for further details.



The search path for a program depends on the way the program name was

specified. If an explicit device or directory specification precedes the

program name,only that directory will be searched. For example,the command-

level invocation of "rx df0:s/test" will search only the df0:s directory for a

file named test.rexx or test. If the program name does not include a path,the

search path begins with the current directory and proceeds to the system REXX:

directory. To further the above example,invoking the program as "rx test 1 2 3"

would search for the files test.rexx,test,REXX:test.rexx,and REXX:test,in that

order.



If an ARexx program cannot be found,one alternative action may be taken. If the

@{b}rm_PassPort@{ub} field of an extended packet was supplied,the message packet is

passed along to that port,which might be the next process in a search chain.

Otherwise the message is returned with a "Program not found"error indication

(error code 1.)
@ENDNODE


@NODE "EXTENSION FIELDS" "Extension Fields"
@{b}EXTENSION FIELDS@{ub}



The @{"RexxMsg" LINK "TABLE 10.2"} structure includes several "extension fields" that can be used to

override various defaults when a program is invoked. These extension fields can

be filled in selectively,and only the non-zero values will override the

corresponding default. ARexx never modifies the extension area.



Host applications should supply values for the file extension and host address

fields of the message packet. The file extension affects which program files

will match a given command name,and allows macro programs specific to the host

to be given distinctive names. The host address must refer to a public message

port,and will usually indicate the host's own port. Any appropriate(but usually

short)strings can be chosen for these values. Oftern,the name of the

applications program itself can be used as its host address and file extension.



@{b}PASSPORT@{ub}. The rm_PassPort field allows the search for a program to be "passed

along" to another messsage port after checking for an ARexx program. If the

command or function name doesn't resolve to an ARexx program,the message packet

is forwarded to the message port specified as the PassPort. This allows

applications to maintain control over the search order for external program

files.



Note that the rm_PassPort field must be the actual address of a message port,

rather than a name string. The PassPort therefore does not have a public port,

but the port should be a secured resource,since the message is sent directly to

this address without checking to see whether it is a valid message port.



@{b}HOST ADDRESS@{ub}. The rm_ComAddr field overrides the default initial host address,

which is "REXX." The host address is the name of the messsage port to which

commands will be directed,and is supplied as a pointer to a null-terminated

string. Applications that support multiple instances of user data will usually

create a separate message port for each instance. The name of this port would

then be supplied as the host address for any commands issued from that

instance.



@{b}FILE EXTENSION@{ub}. The rm_FileExt field is used to override the default file

extension for ARexx programs,which is "REXX". Host applications can use the

file extension to distinguish the names of the macro programs specific to that

application. It is supplied as a pointer to a null-terminated string.
@ENDNODE

@NODE "INPUT AND OUTPUT STREAMS" "Input and Output Streams"
@{b}INPUT AND OUTPUT STREAMS@{ub}. The default input and output steams for an ARexx

program are inherited from the host application's process structure,if the host

is a process rather than just a task. One or both of these streams may be

overridden by supplying an appropriate value in the rm_Stdin or rm_stdout

fields. The values supplied must be valid DOS filehandles,and must not be

closed while the program is executing. The steams are installed directly into

the program's process structure,replacing the prior values.



The output stream is also used as the default tracing stream for the program.

If interactive tracing is to be used in a program,the output stream should

refer to a console device,since it will be used for input as well.



In the event than an ARexx program is invoked by an EXEC task,rather than by an

DOS process,the extension field streams are the only way that the launched

program can be given default I/O streams.
@ENDNODE

@NODE "INTERPRETING THE RESULT FIELDS" "Interpreting the Result Fields"
@{b}INTERPRETING THE RESULT FIELDS@{ub}



The message packet that invoked an ARexx program is returned to the client when

the program finishes. The two result fields will contain error codes or

possibly a result string. The interpretation of the result fields depends

partly on the mode of invocation. If the primary result field @{b}rm_Result1@{ub} is

zero,the program executed normally and the secondary field @{b}rm_Result2@{ub} will

contain a pointer to a result string,assuming that one was requested(and

available.)



If the primary result is non-zero,it represents either an error severity level

or else the return code from a command invocation. The two cases can be

distinguished by examining the secondary result. If the secondary field is also

non-zero,an error occurred and the secondary field is an ARexx error code. If

the secondary result is zero,then the primary result is the return code passed

by an "@{"EXIT" LINK "EXIT"} rc" or "@{"RETURN" LINK "RETURN"} rc" instruction in the program. The application

program can use this return code either as an error indication or to initiate

some particular processing action.



Result strings are always returned as an argstring and become the property(that

is,responsibility)of the host. When the string is no longer needed,it can be

released using the @{"DeleteArgstring()" LINK "DeleteArgstring()"} function.



Errors occurring in macro programs should usually be reported to the user.

Explanatory messages are available for all ARexx error codes,and can be

obtained by calling the ARexx Systems Library function @{"ErrorMsg()" LINK "ErrorMsg()"}.
@ENDNODE

@NODE "COMMUNICATING WITH THE RESIDENT PROCESS" "Communicating with the Resident Process"
@{b}COMMUNICATING WITH THE RESIDENT PROCESS@{ub}



All communications with the resident process are handled by passing message

packets,which were previously diagrammed in @{"Table 10.2" LINK "TABLE 10.2"}. The packet has a

command field that describes the action to be performed and parameter fields

that are specific to the command. Message packets are processed as they are

received,and are then either returned to the sender or passed along to another

process(in the case of a program invocation.) The packet includes two result

fields that are used to return error codes or result strings. The parameter

fields of the message packet may contain either(long)integer values or pointers

to argument strings. String arguments are assumed to be argstring pointers

unless otherwise specified.
@ENDNODE

@NODE "COMMAND(ACTION)CODES" "Command(Action)Codes"
@{b}COMMAND(ACTION)CODES@{ub}



The command codes that are currently implemented in the resident process are

described below. Commands are listed by their mnemonic codes,followed by the

valid modifier flags. The final code value is always the logical OR of the code

value and all of the modifier flags selected. The command code is installed in

the rm_Action field of the message packet.

@{b}Contents@{ub}

@{"RXADDCON" LINK "RXADDCON"}
@{"RXADDFH" LINK "RXADDFH"}
@{"RXADDLIB" LINK "RXADDLIB"}
@{"RXCOMM" LINK "RXCOMM"}
@{"RXFUNC" LINK "RXFUNC"}
@{"RXREMCON" LINK "RXREMCON"}
@{"RXREMLIB" LINK "RXREMLIB"}
@{"RXTCCLS" LINK "RXTCCLS"}
@{"RXTCOPN" LINK "RXTCOPN"}

@ENDNODE
@NODE "RXADDCON" "RXADDCON"
USAGE: @{b}RXADDCON [RXFB_NONRET]@{ub}

This code specifies an entry to be added to @{"the Clip List" LINK "THE CLIP LIST"}. Parameter slot ARGO

points to the name string,slot ARG1 points to the value string,and slot ARG2

contains the length of the value string.


The name and value arguments do not need to be argstrings,but can be just

pointers to storage areas. The name should be a null-terminated string,but the

value can contain arbitrary data including nulls.
@ENDNODE

@NODE "RXADDFH" "RXADDFH"
USAGE: @{b}RXADDFH [RSFB_NONRET]@{ub}

This action code specifies a function host to be added to the @{"Library List" LINK "THE LIBRARY LIST"}.

Parameter slot ARGO points to the(null-terminated)host name string,and slot

ARG1 holds the search priority for the node. The search priority should be an

integer between 100 and -100 inclusive;the remaining priority ranges are

reserved for future extensions. If a none already exists with the same name,the

packet is returned with a warning level error code. Note that no test is made

at this time as to whether the host port exists.
@ENDNODE

@NODE "RXADDLIB" "RXADDLIB"
USAGE:@{b}RXADDLIB [RXFB_NONRET]@{ub}

This code specifies an entry to be added to @{"the Library List" LINK "THE LIBRARY LIST"}. Parameter slot

ARGO points to a null-terminated name string referring either to a function

library or a function host. Slot ARG1 is the priority for the node and should

be an integer between 100 and -100 inclusive;the remaining priority ranges are

reserved for future extensions. Slot ARG2 contains the entry oint offset and

slot ARG3 is the library version number. If a node already exists with the same

name,the packet is returned with a warning level error code. Otherwise,a new

entry is added and the library or host becomes available to ARexx programs.

Note that no test is made at this time as to whether the library exists and can

be opened.
@ENDNODE

@NODE "RXCOMM" "RXCOMM"
USAGE:@{b}RXCOMM [RXFB_TOKEN] [RXFB_STRING] [RXFB_RESULT] [RXFB_NOIO]@{ub}

Specifies a command-mode invocation of an ARexx program. Parameter slot ARGO

must contain an argstring ointer to the command string. The RXFB_TOKEN flag

specifies that the command line is to be tokenized before being passed to the

invoked program. The RXFB_STRING flag bit indicates that the command string is

a "string file." Command invocations do not normally return result strings,but

the RXFB_RESULT flag can be set if the caller is prepared to handle the cleanup

associated with a returned string. The RXFB_NOIO modifier suppresses the

inheritance of the host's input and output streams.
@ENDNODE

@NODE "RXFUNC" "RXFUNC"
USAGE:@{b}RXFUNC [RXFB_RESULT] [RXFB_STRING] [RXFB_NOIO] argcount@{ub}

This command code specifies a function invoction. Parameter slot ARGO contains

a pointer to the function name string,and slots ARG1 through ARG15 point to the

argument strings,all of which must be passed as argstrings. The lower byte of

the command code is the argument count;this count excludes the function name

string itself. Function calls normally set the RXFB_RESULT flag,but this is not

mandatory. The RXFB_STRING modifier indicates that the function name string is

actually a "string file". The RXFB_NOIO modifier suppresses the inheritance of

the host's input and output streams.
@ENDNODE

@NODE "RXREMCON" "RXREMCON"
USAGE:@{b}RXREMCON [RXFB_NONRET]@{ub}

This code requests that an entry be removed from @{"the Clip List" LINK "THE CLIP LIST"}. Parameter slot

ARGO points to the null-terminated name to be removed. The Clip List is

searched for a node matching the supplied name,and if a match is found the list

node is removed and recycled. If no match is found the packet is returned with

a warning error code.
@ENDNODE

@NODE "RXREMLIB" "RXREMLIB"
USAGE:@{b}RXREMLIB [RXFB_NONRET]@{ub}

This command removes a @{"Library List" LINK "THE LIBRARY LIST"} entry. Parameter slot ARGO points to the

null terminated string specifying the library to be removed. The Library List

is searched for a node matching the library name,and if a match is found the

node is removed and released. If no match is found the packet is returned with

a warning error code. The libary node will not be removed if the library is

currently being used by an ARexx program.
@ENDNODE

@NODE "RXTCCLS" "RXTCCLS"
USAGE:@{b}RXTCCLS [RXFB_NONRET]@{ub}

This code requests that the global tracing console be closed. The console

window will be closed immediately unless one or more ARexx programs are waiting

for input from the console. In this event,the window will be closed as soon as

the active programs are no longer using it.
@ENDNODE

@NODE "RXTCOPN" "RXTCOPN"
USAGE:@{b}RXTCOPN [RXFB_NONRET]@{ub}

This command requests that the global tracing console be opened. Once the

console is open,all active ARexx programs will divert their tracing output to

the console. Tracing input(for interactive debugging)will also be diverted to

the new console. Only one console can be opened;subsequent RXTCOPN requests

will be returned with a warning error message.
@ENDNODE

@NODE "MODIFIER FLAGS" "Modifier Flags"
@{b}MODIFIER FLAGS@{ub}



Command codes may include modifier flags to select various processing options.

Modifier flags are specific to certain commands,and are ignored otherwise.



@{b}RXFB_NOIO@{ub}. This modifier is used with the @{"RXCOMM" LINK "RXCOMM"} and @{"RXFUNC" LINK "RXFUNC"} command codes to

suppress the automatic inheritance of the host's input and output streams.



@{b}RXFB_NONRET@{ub}. Specifies that the message packet is to be recycled by the

resident process rather than being returned to the sender. This implies that

the sender doesn't care about whether the requested action succeeded,since the

returned packet provides the only means of acknowledgement. Message packets are

released using the library function @{"DeleteRexxMsg()" LINK "DeleteRexxMsg()"}.



@{b}RXFB_RESULT@{ub}. This modifer is valid with the @{"RXCOMM" LINK "RXCOMM"} and @{"RXFUNC" LINK "RXFUNC"} commands,and

requests that the called program return a result string. If the program

@{"EXIT" LINK "EXIT"}s(or @{"RETURN" LINK "RETURN"}s)with an expression,the expression result is returned to the

caller as an argstring. It is then the caller's responsibility to release the

argstring when it is no longer needed;this can be done using the library

function @{"DeleteArgstring()" LINK "DeleteArgstring()"}.



@{b}RXFB_STRING@{ub}. This modifer is valid with the @{"RXCOMM" LINK "RXCOMM"} and @{"RXFUNC" LINK "RXFUNC"} command codes. It

indicates that the command or function argument(in slot ARGO)is a "string file"

rahter than a file name.



@{b}RXFB_TOKEN@{ub}. This flag is used with the @{"RXCOMM" LINK "RXCOMM"} code to request that the command

string be completely tokenized before being passed to the invoked program.

Programs invoked as commands normally have only a single argument string. The

tokenization process uses "white space" to separate the tokens,except within

quoted strings. Quoted strings can use either single or double quotes,and the

end of the command string(a null character)is considered as an implicit closing

quote.
@ENDNODE

@NODE "10.RESULT FIELDS" "Result Fields"
@{b}RESULT FIELDS@{ub}



The resident process uses the standard command-level conventions for the

primary return code installed in @{b}rm_Result1@{ub}. Minor or warning errors are

indicated by a value of 5,and more serious errors are returned as values of 10

or 20. The secondary result field @{b}rm_Result2@{ub} will either be zero or an ARexx

error code if applicable.



Note that @{"RXCOMM" LINK "RXCOMM"} and @{"RXFUNC" LINK "RXFUNC"} messages are returned directly by the invoked macro

program,rathe than by the residen process.
@ENDNODE

@NODE "10.EXTERNAL FUNCTION LIBRARIES" "External Function Libraries"
@{b}EXTERNAL FUNCTION LIBRARIES@{ub}



ARexx supports external function libraries as a mechanism for user-defined

extensions to the language. Function libraries may be written and maintained by

users or applications developers.



Regardless of the intended application,all function libraries share a common

structure. The initial design follows that of the standard EXEC shared library,

with the three required entry points Open,Close,and Expunge,plus a reserved

slot. The library must also have a "query" entry point,which serves to match

the name supplied by ARexx with the intended function. Typically,this will

consist of a table of function names and a routine to search for the specified

one.



@{b}REENTRANCY@{ub}. Functions libraries should be designed to be fully reentrant,since

any number of ARexx programs may be running at any time. If this is not

feasible due to other design constraints,the query function should include a

lockout mechanism to prevent multiple calls to the library routines.
@ENDNODE


@NODE "CALLING CONVENTION" "Calling Convention"
@{b}CALLING CONVENTION@{ub}



The library's query function will be called from the interpreter's context with

the address of a message packet in register A0 and the library base in A6. The

structure of the message packet is the same as that in @{"Table 10.2" LINK "TABLE 10.2"},but note that

although a message packet is used to carry the arguments,it is not queued at a

message port and does not need to be unlinked. The name of the function to be

called is carried in the ARGO parameter slot. The query function must search

for this function name and,if the name cannot be found,must return an error

code of 1("Program not found")in register D0. The library will then be closed

and the search continued in the next function library. The query function

should not modify any fields within the message packet,as it must be passed

along to the next library until the function is located.
@ENDNODE

@NODE "PARAMETER CONVERSION" "Parameter Conversion"
@{b}PARAMETER CONVERSION@{ub}



Once the requested function has been found,the query funcion may need to

transform the parameters passed by ARexx into the form expected by the

function. Whether the parameter strings need to be converted depends on how

they are to be used. In some cases it may be sufficient just to foward a

pointer to the message packet to the called function,while in other cases the

query function may need to load parameters into registers or to perform

conversion operations. The parameters in ARG1-ARG15 are always passed as

argstrings,and may be treated like a pointer to a null-terminated string.

Further attributes are stored at negative offsets from the argstring pointer,

and may be helpful in working with the string.



@{b}Numeric quantities@{ub} are passed as strings of ASCII characters and will need to

be converted to integer or floating-point format if arithmetic calculations are

to be performed. The ARexx System Library includes a limited set of functions

to do parameter conversions.



The actual parameter count can be obtained from the low-order byte of the

rm_Action field in the message packet. The count never includes the function

name itself(in ARGO),but does include arguments specified as "defaults." Such

arguments will have a zero value in the corresponding parameter slot.



Note that the parameter block of the message packet,containing the fields

ARG0-ARG15,is structured like the argument array expected by the main(argc,

argv)function of a "C" program. This suggests a simple way that a function

library could provide a bridge to a series of "C" programs. The query function

would need only to determine the address of the called function,and then push

the parameter block address and argument count onto the program stack.
@ENDNODE

@NODE "RETURNED VALUES" "Returned Values"
@{b}RETURNED VALUES@{ub}



Each library function must return an error code and a value string. The error

code is returned in register D0,and should be 0 if no errors occurred. The

value string must be returned as an argstring pointer in register A1,unless D0

indicates that an error occurred during the call. The mechanisms for creating

the proper return values can be made part of the query function,so that all

functions in the library share a common return path.
@ENDNODE

@NODE "DIRECT MANIPULATION OF DATA STRUCTURES" "Direct Manipulation of Data Structures"
@{b}DIRECT MANIPULATION OF DATA STRUCTURES@{ub}



All of the data structures maintained by the resident process are built into

the ARexx Systems Library base and are therefore accessible to external

programs. The Task List in the @{b}RexxBase@{ub} structure links the global data

structures for all currently active ARexx programs. This linkage uses the node

contained in the message port of the @{b}RexxTask@{ub} structure,rather than at the head

of the structure. The RexxTask structure is the global data structure and

initial storage environment for the ARexx program,and all descendant storage

environments are linked into the Environment List. The linkage of internal data

structures is such that the complete internal state of all ARexx programs can

be reached starting from the library base pointer.



Two library functions,@{"LockRexxBase()" LINK "LockRexxBase()"} and @{"UnlockRexxBase()" LINK "UnlockRexxBase()"},are provided to

mediate access to the global structures. The structure base should be locked

before reading any of the data items or traversing any of the lists. The

present version of these functions provides only a global lock,but future

extensions will allow individual resources to be locked.



In general it should not be necessary to manipulate directly any of these data

structures. Functions have been provided in the ARexx Systems Library to

perform all of the operations required to interface external program to the

ARexx system. It is therefore recommended that applictions developers avoid

using any of the internal structures except as provided through the library

functions.
@ENDNODE
@NODE "APPENDIX A" "Appendix A"

                        @{b}APPENDIX A ERROR MESSAGES@{ub}



When the ARexx interpeter detects an error in a program,it returns an error

code to indicate the nature of the problem. Errors are normally handled by

displaying the error code,the source line number where the error occurred,and a

brief message explaining the error condition. Unless the @{b}SYNTAX@{ub} interrupt has

been previously enabled(using the @{"SIGNAL" LINK "SIGNAL"} instruction),the program then

terminates and control returns to the caller. Most syntax and execution errors

can be trapped by the SYNTAX interrupt,allowing the user to retain control and

perform whatever special error processing is required. Certain errors are

generated outside of the context of an ARexx program,and therefore cannot be

trapped by this mechanism. Refer to @{"chapter 7" LINK "CHAPTER 7"} for further information on error

trapping and processing.



Associated with each error code is a severity level that is reported to the

calling program as the primary result code. The error code itself is returned

as the secondary result. The subsequent propagation or reporting of these codes

is of course dependent on the external(calling)program.



The following pages list all of the currently-defined error codes,along with

the associated severity level and message string.

@{b}Contents@{ub}

@{"1 PROGRAM NOT FOUND" LINK "ERROR 1"}
@{"2 EXECUTION HALTED" LINK "ERROR 2"}
@{"3 INSUFFICIENT MEMORY" LINK "ERROR 3"}
@{"4 INVALID CHARACTER" LINK "ERROR 4"}
@{"5 UNMATCHED QUOTE" LINK "ERROR 5"}
@{"6 UNTERMINATED COMMENT" LINK "ERROR 6"}
@{"7 CLAUSE TOO LONG" LINK "ERROR 7"}
@{"8 INVALID TOKEN" LINK "ERROR 8"}
@{"9 SYMBOL OR STRING TOO LONG" LINK "ERROR 9"}
@{"10 INVALID MESSAGE PACKET" LINK "ERROR 10"}
@{"11 COMMAND STRING ERROR" LINK "ERROR 11"}
@{"12 ERROR RETURN FROM FUNCTION" LINK "ERROR 12"}
@{"13 HOST ENVIRONMENT NOT FOUND" LINK "ERROR 13"}
@{"14 REQUESTED LIBRARY NOT FOUND" LINK "ERROR 14"}
@{"15 FUNCTION NOT FOUND" LINK "ERROR 15"}
@{"16 FUNCTION DID NOT RETURN VALUE" LINK "ERROR 16"}
@{"17 WRONG NUMBER OF ARGUMENTS" LINK "ERROR 17"}
@{"18 INVALID ARGUMENT TO FUNCTION" LINK "ERROR 18"}
@{"19 INVALID PROCEDURE" LINK "ERROR 19"}
@{"20 UNEXPECTED THEN OR WHEN" LINK "ERROR 20"}
@{"21 UNEXPECTED ELSE OR OTHERWISE" LINK "ERROR 21"}
@{"22 UNEXPECTED BREAK,LEAVE,or ITERATE" LINK "ERROR 22"}
@{"23 INVALID STATEMENT IN SELECT" LINK "ERROR 23"}
@{"24 MISSING OR MULTIPLE THEN" LINK "ERROR 24"}
@{"25 MISSING OTHERWISE" LINK "ERROR 25"}
@{"26 MISSING OR UNEXPECTED END" LINK "ERROR 26"}
@{"27 SYMBOL MISMATCH" LINK "ERROR 27"}
@{"28 INVALID DO SYNTAX" LINK "ERROR 28"}
@{"29 INCOMPLETE IF OR SELECT" LINK "ERROR 29"}
@{"30 LABEL NOT FOUND" LINK "ERROR 30"}
@{"31 SYMBOL EXPECTED" LINK "ERROR 31"}
@{"32 SYMBOL OR STRING EXPECTED" LINK "ERROR 32"}
@{"33 INVALID KEYWORD" LINK "ERROR 33"}
@{"34 REQUIRED KEYWORD MISSING" LINK "ERROR 34"}
@{"35 EXTRANEOUS CHARACTERS" LINK "ERROR 35"}
@{"36 KEYWORD CONFLICT" LINK "ERROR 36"}
@{"37 MESSAGE INVALID TEMPLATE" LINK "ERROR 37"}
@{"38 INVALID TRACE REQUEST" LINK "ERROR 38"}
@{"39 UNINITIALIZED VARIABLE" LINK "ERROR 39"}
@{"40 INVALID VARIABLE NAME" LINK "ERROR 40"}
@{"41 INVALID EXPRESSION" LINK "ERROR 41"}
@{"42 UNBALANCED PARENTHESE" LINK "ERROR 42"}
@{"43 NESTING LIMIT EXCEEDED" LINK "ERROR 43"}
@{"44 INVALID EXPRESSION RESULT" LINK "ERROR 44"}
@{"45 EXPRESSION REQUIRED" LINK "ERROR 45"}
@{"46 BOOLEAN VALUE NOT 0 OR 1" LINK "ERROR 46"}
@{"47 ARITHMETIC CONVERSION ERROR" LINK "ERROR 47"}
@{"48 INVALID OPERAND" LINK "ERROR 48"}

@ENDNODE

@NODE "ERROR 1" "1 PROGRAM NOT FOUND"
@TOC "APPENDIX A"
@{b}ERROR: 1 SEVERITY: 5 MESSGE: PROGRAM NOT FOUND@{ub}

The named program could not be found,or was not an ARexx program. ARexx

programs are expected to start with a "/*" sequence. This error is detected by

the external interface and cannot be trapped by the @{b}SYNTAX@{ub} interrupt.
@ENDNODE

@NODE "ERROR 2" "2 EXECUTION HALTED"
@TOC "APPENDIX A"
@{b}ERROR: 2 SEVERITY: 10 MESSAGE: EXECUTION HALTED@{ub}

A control-C break or an external half request was received and the program

terminated. This error will be trapped if the @{b}HALT@{ub} interrupt has been enabled.
@ENDNODE

@NODE "ERROR 3" "3 INSUFFICIENT MEMORY"
@TOC "APPENDIX A"
@{b}ERROR: 3 SEVERITY: 20 MESSAGE: INSUFFICIENT MEMORY@{ub}

The interpreter was unable to allocate enough memory for an operation. Since

memory space is required for all parsing and execution operations,this error

cannot usually be trapped by the SYNTAX interrupt.
@ENDNODE

@NODE "ERROR 4" "4 INVALID CHARACTER"
@TOC "APPENDIX A"
@{b}ERROR: 4 SEVERITY: 10 MESSAGE: INVALID CHARACTER@{ub}

A non-ASCII character was found in the program. Control codes and other non-

ASCII characters may be used in a program by defining them as hex or binary

strings. This is a scan phase error and cannot be trapped by the SYNTAX

interrupt.
@ENDNODE

@NODE "ERROR 5" "5 UNMATCHED QUOTE"
@TOC "APPENDIX A"
@{b}ERROR: 5 SEVERITY: 10 MESSAGE: UNMATCHED QUOTE@{ub}

A closing single or double quote was missing. Check that each string is

properly delimited. This is a scan phase error and cannot be trapped by the

SYNTAX interrupt.
@ENDNODE

@NODE "ERROR 6" "6 UNTERMINATED COMMENT"
@TOC "APPENDIX A"
@{b}ERROR: 6 SEVERITY: 10 MESSAGE: UNTERMINATED COMMENT@{ub}

The closing "*/" for a comment field was not found. Remember that comments may

be nested,so each "/*" must be matched by a "*/." This is a scan phase error

and cannot be trapped by the SYNTAX interrupt.
@ENDNODE

@NODE "ERROR 7" "7 CLAUSE TOO LONG"
@TOC "APPENDIX A"
@{b}ERROR: 7 SEVERITY: 10 MESSAGE: CLAUSE TOO LONG@{ub}

A clause was too long for the internal buffer used as temporary storage. The

source line in question should be broken into smaller parts. This is a scan

phase error and cannot be trapped by the SYNTAX interrupt.
@ENDNODE

@NODE "ERROR 8" "8 INVALID TOKEN"
@TOC "APPENDIX A"
@{b}ERROR: 8 SEVERITY: 10 MESSAGE: INVALID TOKEN@{ub}

An unrecognized lexical token was found,or a clause could not be properly

classified. This is a scan phase error and cannot be trapped by the SYNTAX

interrupt.
@ENDNODE

@NODE "ERROR 9" "9 SYMBOL OR STRING TOO LONG"
@TOC "APPENDIX A"
@{b}ERROR: 9 SEVERITY: 10 MESSAGE: SYMBOL OR STRING TOO LONG@{ub}

An attempt was made to create a string longer than the maximum supported by the

interpreter. The implementation limits for internal structure are given in

@{"Appendix B" LINK "APPENDIX B"}.
@ENDNODE

@NODE "ERROR 10" "10 INVALID MESSAGE PACKET"
@TOC "APPENDIX A"
@{b}ERROR: 10 SEVERITY: 10 MESSAGE: INVALID MESSAGE PACKET@{ub}

An invalid action code was found in a message packet sent to the ARexx resident

process. The packet was returned without being processed. This error is

detected by the external interface and cannot be trapped by the SYNTAX

interrupt.
@ENDNODE

@NODE "ERROR 11" "11 COMMAND STRING ERROR"
@TOC "APPENDIX A"
@{b}ERROR: 11 SEVERITY: 10 MESSAGE: COMMAND STRING ERROR@{ub}

A command string could not be processed. This error is detected by the external

interface and cannot be trapped by the SYNTAX interrupt.
@ENDNODE

@NODE "ERROR 12" "12 ERROR RETURN FROM FUNCTION"
@{b}ERROR: 12 SEVERITY: 10 MESSAGE: ERROR RETURN FROM FUNCTION@{ub}

An external function returned a non-zero error code. Check that the correct

parameters were supplied to the function.
@ENDNODE

@NODE "ERROR 13" "13 HOST ENVIRONMENT NOT FOUND"
@TOC "APPENDIX A"
@{b}ERROR: 13 SEVERITY: 10 MESSAGE: HOST ENVIRONMENT NOT FOUND@{ub}

The message port corresponding to a host address string could not be found.

Check that the required external host is active.
@ENDNODE

@NODE "ERROR 14" "14 REQUESTED LIBRARY NOT FOUND"
@TOC "APPENDIX A"
@{b}ERROR: 14 SEVERITY: 10 MESSAGE: REQUESTED LIBRARY NOT FOUND@{ub}

An attempt was made to open a function library included in @{"the Library List" LINK "THE LIBRARY LIST"},but

the library could not be opened. Check that the correct name and version of the

library were specified when the library was added to the resource list.
@ENDNODE

@NODE "ERROR 15" "15 FUNCTION NOT FOUND"
@TOC "APPENDIX A"
@{b}ERROR: 15 SEVERITY: 10 MESSGE: FUNCTION NOT FOUND@{ub}

A function was called that could not be found in any of the currently

accessible libraries,and could not be located as an external program. Check

that the appropriate function libraries have been added to the Libraries List.
@ENDNODE

@NODE "ERROR 16" "16 FUNCTION DID NOT RETURN VALUE"
@TOC "APPENDIX A"
@{b}ERROR: 16 SEVERITY: 10 MESSAGE: FUNCTION DID NOT RETURN VALUE@{ub}

A function was called which failed to return a result string,but did not

otherwise report an error. Check that the function was programmed correctly,or

invoke it using the @{"CALL" LINK "CALL"} instruction.
@ENDNODE

@NODE "ERROR 17" "17 WRONG NUMBER OF ARGUMENTS"
@TOC "APPENDIX A"
ERROR: 17 SEVERITY: 10 MESSAGE: WRONG NUMBER OF ARGUMENTS

A call was made to a function which expected more(or fewer)arguments. This

error will be generated if a Built-In or external function is called with more

arguments than can be accomodated in the message packet used for external

communications.
@ENDNODE

@NODE "ERROR 18" "18 INVALID ARGUMENT TO FUNCTION"
@TOC "APPENDIX A"
@{b}ERROR: 18 SEVERITY: 10 MESSAGE: INVALID ARGUMENT TO FUNCTION@{ub}

An inappropriate argument was supplied to a function,or a required argument was

missing. Check the parameter requirements specified for the function.
@ENDNODE

@NODE "ERROR 19" "19 INVALID PROCEDURE"
@TOC "APPENDIX A"
@{b}ERROR: 19 SEVERITY: 10 MESSAGE: INVALID PROCEDURE@{ub}

A @{"PROCEDURE" LINK "PROCEDURE"} instruction was issued in an invalid context. Either no internal

functions were active,or a PROCEDURE had already been issued in the current

storage environment.
@ENDNODE

@NODE "ERROR 20" "20 UNEXPECTED THEN OR WHEN"
@TOC "APPENDIX A"
@{b}ERROR: 20 SEVERITY: 10 MESSAGE: UNEXPECTED THEN OR WHEN@{ub}

A @{"WHEN" LINK "WHEN"} or @{"THEN" LINK "THEN"} instruction was executed outside of a valid context. The WHEN

instruction is valid only within a @{"SELECT" LINK "SELECT"} range,and THEN must be the next

instruciton following an @{"IF" LINK "IF"} or WHEN.
@ENDNODE

@NODE "ERROR 21" "21 UNEXPECTED ELSE OR OTHERWISE"
@TOC "APPENDIX A"
@{b}ERROR: 21 SEVERITY: 10 MESSAGE: UNEXPECTED ELSE OR OTHERWISE@{ub}

An @{"ELSE" LINK "ELSE"} or @{"OTHERWISE" LINK "OTHERWISE"} was found outside of a valid context. The OTHERWISE

instruction is valid only within a @{"SELECT" LINK "SELECT"} range. ELSE is valid only following

the @{"THEN" LINK "THEN"} branch of an @{"IF" LINK "IF"} range.
@ENDNODE

@NODE "ERROR 22" "22 UNEXPECTED BREAK,LEAVE,or ITERATE"
@TOC "APPENDIX A"
@{b}ERROR: 22 SEVERITY: 10 MESSAGE: UNEXPECTED BREAK,LEAVE,or ITERATE@{ub}

The @{"BREAK" LINK "BREAK"} instruction is valid only within a @{"DO" LINK "DO"} range or inside an @{"INTERPRET" LINK "INTERPRET"}ed

string. The @{"LEAVE" LINK "LEAVE"} and @{"ITERATE" LINK "ITERATE"} instuctions are valid only within an iterative DO

range.
@ENDNODE

@NODE "ERROR 23" "23 INVALID STATEMENT IN SELECT"
@TOC "APPENDIX A"
@{b}ERROR: 23 SEVERITY: 10 MESSAGE: INVALID STATEMENT IN SELECT@{ub}

A invalid statement was encountered within a @{"SELECT" LINK "SELECT"} range. Only @{"WHEN" LINK "WHEN"},@{"THEN" LINK "THEN"},and

@{"OTHERWISE" LINK "OTHERWISE"} statements are valid within a SELECT range,except for the conditional

statements following THEN or OTHERWISE clauses.
@ENDNODE

@NODE "ERROR 24" "24 MISSING OR MULTIPLE THEN"
@TOC "APPENDIX A"
@{b}ERROR: 24 SEVERITY: 10 MESSAGE: MISSING OR MULTIPLE THEN@{ub}

An expected @{"THEN" LINK "THEN"} clause was not found,or another THEN was found after one had

already been executed.
@ENDNODE

@NODE "ERROR 25" "25 MISSING OTHERWISE"
@TOC "APPENDIX A"
@{b}ERROR: 25 SEVERITY: 10 MESSAGE: MISSING OTHERWISE@{ub}

None of the @{"WHEN" LINK "WHEN"} clauses in a @{"SELECT" LINK "SELECT"} succeeded,but no @{"OTHERWISE" LINK "OTHERWISE"} clause was

supplied.
@ENDNODE

@NODE "ERROR 26" "26 MISSING OR UNEXPECTED END"
@TOC "APPENDIX A"
@{b}ERROR: 26 SEVERITY: 10 MESSAGE: MISSING OR UNEXPECTED END@{ub}

The program source ended before an @{"END" LINK "END"} was found for a @{"DO" LINK "DO"} or @{"SELECT" LINK "SELECT"} instruction

or an END was encountered outside of a DO or SELECT range.
@ENDNODE

@NODE "ERROR 27" "27 SYMBOL MISMATCH"
@TOC "APPENDIX A"
@{b}ERROR: 27 SEVERITY: 10 MESSAGE: SYMBOL MISMATCH@{ub}

The symbol specified on an @{"END" LINK "END"},@{"ITERATE" LINK "ITERATE"},or @{"LEAVE" LINK "LEAVE"} instruction did not match the

index variable for the associated @{"DO" LINK "DO"} range. Check that the active loops have

been nested properly.
@ENDNODE

@NODE "ERROR 28" "28 INVALID DO SYNTAX"
@TOC "APPENDIX A"
@{b}ERROR: 28 SEVERITY: 10 MESSAGE: INVALID DO SYNTAX@{ub}

An invalid @{"DO" LINK "DO"} instruction was executed. An initializer expression must be given

if a @{b}TO@{ub} or @{b}BY@{ub} expression is specified,and a @{b}FOR@{ub} expression must yield a non-

negative integer result.
@ENDNODE

@NODE "ERROR 29" "29 INCOMPLETE IF OR SELECT"
@TOC "APPENDIX A"
@{b}ERROR: 29 SEVERITY: 10 MESSAGE: INCOMPLETE IF OR SELECT@{ub}

An @{"IF" LINK "IF"} or @{"SELECT" LINK "SELECT"} range ended before all of the required statement were found.

Check whether the conditional statement following a @{"THEN" LINK "THEN"},@{"ELSE" LINK "ELSE"},or @{"OTHERWISE" LINK "OTHERWISE"}

clause was omitted.
@ENDNODE

@NODE "ERROR 30" "30 LABEL NOT FOUND"
@TOC "APPENDIX A"
@{b}ERROR: 30 SEVERITY: 10 MESSAGE: LABEL NOT FOUND@{ub}

A label specified by a @{"SIGNAL" LINK "SIGNAL"} instruction,or implicitly referenced by an

enabled interrupt,could not be found in the program source. Labels defined

dynamically by an @{"INTERPRET" LINK "INTERPRET"} instruction or by interactive input are not

included in the search.
@ENDNODE

@NODE "ERROR 31" "31 SYMBOL EXPECTED"
@TOC "APPENDIX A"
@{b}ERROR: 31 SEVERITY: 10 MESSAGE: SYMBOL EXPECTED@{ub}

A non-symbol token was found where only a symbol token is valid. The @{"DROP" LINK "DROP"},@{"END" LINK "END"},

@{"LEAVE" LINK "LEAVE"},@{"ITERATE" LINK "ITERATE"},and @{"UPPER" LINK "UPPER"} instructions may only be followed by a symbol token,and

will generate this error if anything else is supplied. This message will also

be issued if a required symbol is missing.
@ENDNODE

@NODE "ERROR 32" "32 SYMBOL OR STRING EXPECTED"
@TOC "APPENDIX A"
@{b}ERROR: 32 SEVERITY: 10 MESSAGE: SYMBOL OR STRING EXPECTED@{ub}

An invalid token was found in a context where only a symbol or string is valid.
@ENDNODE

@NODE "ERROR 33" "33 INVALID KEYWORD"
@TOC "APPENDIX A"
@{b}ERROR: 33 SEVERITY: 10 MESSAGE: INVALID KEYWORD@{ub}

A symbol token in an instruction clause was identified as a keyword,but was

invalid in the specific context.
@ENDNODE

@NODE "ERROR 34" "34 REQUIRED KEYWORD MISSING"
@TOC "APPENDIX A"
@{b}ERROR: 34 SEVERITY: 10 MESSAGE: REQUIRED KEYWORD MISSING@{ub}

An instuction clause required a specific keyword token to be present,but it was

not supplied. For example,this messge will be issued if a @{"SIGNAL" LINK "SIGNAL"} ON instruction

is not followed by one of the interrupt keywords(e.g.SYNTAX.)
@ENDNODE

@NODE "ERROR 35" "35 EXTRANEOUS CHARACTERS"
@TOC "APPENDIX A"
@{b}ERROR: 35 SEVERITY: 10 MESSAGE: EXTRANEOUS CHARACTERS@{ub}

A seemingly valid statement was executed,but extra characters were found at the

end of the clause.
@ENDNODE

@NODE "ERROR 36" "36 KEYWORD CONFLICT"
@TOC "APPENDIX A"
@{b}ERROR: 36 SEVERITY: 10 MESSAGE: KEYWORD CONFLICT@{ub}

Two mutually exclusive keywords were included in an instruction clause,or a

keyword was included twice in the same instruction.
@ENDNODE

@NODE "ERROR 37" "37 MESSAGE INVALID TEMPLATE"
@TOC "APPENDIX A"
@{b}ERROR: 37 SEVERITY: 10 MESSAGE INVALID TEMPLATE@{ub}

The template provided with an @{"ARG" LINK "ARG"},@{"PARSE" LINK "PARSE"},or @{"PULL" LINK "PULL"} instruction was not properly

constructed. Refer to @{"Chapter 8" LINK "CHAPTER 8"} for a description of template structure and

processing.
@ENDNODE

@NODE "ERROR 38" "38 INVALID TRACE REQUEST"
@TOC "APPENDIX A"
@{b}ERROR: 38 SEVERITY: 10 MESSAGE: INVALID TRACE REQUEST@{ub}

The alphabetic keyword supplied with a @{"TRACE" LINK "TRACE"} instruction or as the argument to

the @{"TRACE()" LINK "TRACE()"} Built-In function was not valid. Refer to @{"Chapter 7" LINK "CHAPTER 7"} for the valid

TRACE options.
@ENDNODE

@NODE "ERROR 39" "39 UNINITIALIZED VARIABLE"
@TOC "APPENDIX A"
@{b}ERROR: 39 SEVERITY: 10 MESSAGE: UNINITIALIZED VARIABLE@{ub}

An attempt was made to use an uninitialized variable while the NOVALUE

interrupt was enabled.
@ENDNODE

@NODE "ERROR 40" "40 INVALID VARIABLE NAME"
@{b}ERROR: 40 SEVERITY: 10 MESSAGE: INVALID VARIABLE NAME@{ub}

An attempt was made to assign a value to a fixed symbol.
@ENDNODE

@NODE "ERROR 41" "41 INVALID EXPRESSION"
@TOC "APPENDIX A"
@{b}ERROR: 41 SEVERITY: 10 MESSAGE: INVALID EXPRESSION@{ub}

An error was detected during the evaluation an expression. Check that each

operator has the correct number of operands,and that no extraneous tokens

appear in the expression. This error will be detected only in expressions that

are actually evaluated. No checking is performed on expressions in clauses that

are being skipped.
@ENDNODE

@NODE "ERROR 42" "42 UNBALANCED PARENTHESE"
@TOC "APPENDIX A"
@{b}ERROR: 42 SEVERITY: 10 MESSAGE: UNBALANCED PARENTHESE@{ub}

An expression was found with an unequal number of opening and closing

parentheses.
@ENDNODE

@NODE "ERROR 43" "43 NESTING LIMIT EXCEEDED"
@TOC "APPENDIX A"
@{b}ERROR: 43 SEVERITY: 43 MESSAGE: NESTING LIMIT EXCEEDED@{ub}

The number of subexpressions in an expression was greater than the maximum

allowed. The expression should be simplified by breaking it into two or more

intermediate expressions.
@ENDNODE

@NODE "ERROR 44" "44 INVALID EXPRESSION RESULT"
@TOC "APPENDIX A"
@{b}ERROR: 44 SEVERITY: 10 MESSAGE: INVALID EXPRESSION RESULT@{ub}

The result of an expression was not valid within its context. For example,this

messge will be issued if an increment or limit expression in a DO instruction

yields a non-numeric result.
@ENDNODE

@NODE "ERROR 45" "45 EXPRESSION REQUIRED"
@TOC "APPENDIX A"
@{b}ERROR: 45 SEVERITY: 10 MESSAGE: EXPRESSION REQUIRED@{ub}

An expression was omitted in a context where one is required. For example,the

@{"SIGNAL" LINK "SIGNAL"} instruction,if not followed by the keywords ON or OFF,must be followed

by an expression.
@ENDNODE

@NODE "ERROR 46" "46 BOOLEAN VALUE NOT 0 OR 1"
@TOC "APPENDIX A"
@{b}ERROR: 46 SEVERITY: 10 MESSAGE: BOOLEAN VALUE NOT 0 OR 1@{ub}

An expression result was expected to yield a boolean result,but evaluated to

something other than 0 or 1.
@ENDNODE

@NODE "ERROR 47" "47 ARITHMETIC CONVERSION ERROR"
@TOC "APPENDIX A"
@{b}ERROR: 47 SEVERITY: 10 MESSAGE: ARITHMETIC CONVERSION ERROR@{ub}

A non-numeric operand was used in a operation requiring numeric operands. This

message will also be generated by an invalid hex or binary string.
@ENDNODE

@NODE "ERROR 48" "48 INVALID OPERAND"
@TOC "APPENDIX A"
@{b}ERROR: 48 SEVERITY: 10 MESSAGE: INVALID OPERAND@{ub}

An operand was not valid for the intended operation. This message will be

generated if an attempt is made to divide by 0,or if a fractional exponent is

used in an exponentiation operation.
@ENDNODE

@NODE "APPENDIX B" "Appendix B"

                      @{b}APPENDIX B LIMITS AND COMPATIBILITY@{ub}



ARexx was designed to adhere closely to the REXX language standard. This

appendix discusses those areas where ARexx departs from the standard.

@{b}Contents@{ub}

@{"Limits" LINK "LIMITS"}
@{"Compatibility" LINK "COMPATIBILITY"}
@{"Omissions" LINK "OMISSIONS"}
@{"Extensions" LINK "EXTENSIONS"}

@ENDNODE

@NODE "LIMITS" "Limits"
@TOC "APPENDIX B"
@{b}LIMITS@{ub}



Language definitions seldom include predefined limits to the program structures

that can be created. Only a few such restrictions were imposed in implementing

ARexx,and most of the internal structure are limited only by the total amount

of memory available. The current implementation limits are listed below.



@{b}LENGTH OF STRINGS@{ub}. Strings,symbol names,and value strings are limited to a

maximum length of 65,535 bytes.



@{b}LENGTH OF CLAUSES@{ub}. Clauses are limited to a maximum of 800 characters after

removing comments and multiple blanks.



@{b}NODES IN COMPOUND NAMES@{ub}. Compound symbol names may include a maximum of 50

nodes,including the stem.



@{b}ARGUMENTS TO FUNCTIONS@{ub}. Built-In and external functions are limited to a

maximum of 15 arguments. There is no limit to the number of arguments that may

be passed to an internal function.



@{b}SUBEXPRESSION NESTING@{ub}. The maximum nesting level for subexpressions is 32.
@ENDNODE

@NODE "COMPATIBILITY" "Compatibility"
@TOC "APPENDIX B"
@{b}COMPATIBILITY@{ub}



ARexx departs in a few ways from the language definition. The differences can

be classified as omissions or extensions,and are described below.
@ENDNODE

@NODE "OMISSIONS" "Omissions"
@TOC "APPENDIX B"
@{b}OMISSIONS@{ub}. The only significant specification of the language standard omitted

from this implementation is the arbitrary-precision arithmetic facility.

Arithmetic operations are limited to about 14 digits of precision,and the @{b}FUZZ@{ub}

option is not implemented at all. Only the @{b}SCIENTIFIC@{ub} format is used for

exponential notation. The full numeric capabilities will be provided in a later

release.
@ENDNODE

@NODE "EXTENSIONS" "Extensions"
@TOC "APPENDIX B"
@{b}EXTENSIONS@{ub}. The following extensions to the language standard have been

included in this implementation:



@{b}BREAK INSTRUCTION@{ub}. A new instruction called @{"BREAK" LINK "BREAK"} has been implemented. It is

used to exit from the scope of any @{"DO" LINK "DO"} or @{"INTERPRET" LINK "INTERPRET"} instruction.



@{b}ECHO INSTRUCTION@{ub}. The @{"ECHO" LINK "ECHO"} instruction has been included as a synonym for @{"SAY" LINK "SAY"}.



@{b}SHELL INSTRUCTION@{ub}. The @{"SHELL" LINK "SHELL"} instructiion has been included as a synonym for

@{"ADDRESS" LINK "ADDRESS"}.



@{b}SIGNAL OPTIONS@{ub}. Several additional @{"SIGNAL" LINK "SIGNAL"} keywords have been implemented.

@{b}BREAK_C,BREAK_D,BREAK_E,@{ub}and @{b}BREAK_F@{ub} will detect and trap the control-C through

control-F signals passed by AmigaDOS. The @{b}IOERR@{ub} keyword traps errors detected

by the I/O system.



@{b}STEM SYMBOLS@{ub}. A stem symbol is valid anywhere that a simple symbol could be

employed.



@{b}TEMPLATE PROCESSING@{ub}. Templates have been generalized in several ways. Variable

symbols may be used as positional tokens if preceded by an operator;the "="

operator is used to denote an absolute position. Multiple templates can be used

with all source forms of the @{"PARSE" LINK "PARSE"} instruction.
@ENDNODE

@NODE "APPENDIX C" "Appendix C"

                       @{b}APPENDIX C THE AREXX SYSTEMS LIBRARY@{ub}



The ARexx interpreter is supplied as a shared library named @{b}rexxsyslib.library@{ub}

and should reside in the system LIBS:directory. While many of the library

routines are highly specific to the interpreter,some of the functions will be

useful to applications that use ARexx. The library is opened when the ARexx

resident process is first loaded and will always be available while it remains

active.



The system library routines were designed to be called from assembly-language

programs and,unless otherwise noted,save all registers except for A0/A1 and

D0/D1. Many routines return values in more than one register to help reduce

code size. In addition,the routines will set the condition-code register(CCR)

wherever appropriate. In mode cases the CCR reflects the value returned in D0.



The library offsets are defined in the file rxslib.i,which should be INDLUDEd

in the program source code. Calls may be made from "C" programs if suitable

binding routines are provided when the program is linked. The definitions for

the constants and data structures used in ARexx are provided as INCLUDE files

on the program distribution disk. These should be reviewed carefully before

attempting to use the library functions.

@{b}Contents@{ub}

@{"Function Groups" LINK "FUNCTION GROUPS"}
@{"ARexx Systems Library Functions" LINK "AREXX SYSTEMS LIBRARY FUNCTIONS"}
@{"Library Function Docs" LINK "LIBRARY FUNCTION DOCS"}

@ENDNODE

@NODE "FUNCTION GROUPS" "Function Groups"
@TOC "APPENDIX C"
@{b}FUNCTION GROUPS@{ub}

The library functions can be frouped into Conversion,Input/Output,Resource

Management,and String Manipulation functions.



@{b}DATA CONVERSION@{ub}. These functions provide many of the common data-conversion

requirements.



@{b}INPUT/0UTPUT@{ub}. Two levels of I/O support are provided. The low level functions

use DOS filehandles directly,while the higher-level functions use linked lists

of IoBuff structures and support logical file names.



@{b}RESOURCE@{ub}. These functions allocate,release,or otherwise manage the data

structures used with ARexx.



@{b}STRING FUNCTIONS@{ub}. All data in ARexx are managed as strings. These functions

provide some of the more common string-manipulation operations.
@ENDNODE
@NODE "AREXX SYSTEMS LIBRARY FUNCTIONS" "ARexx Systems Library Functions"
@TOC "APPENDIX C"

                @{b}TABLE C.1 AREXX SYSTEMS LIBRARY FUNCTIONS@{ub}



NAME            FUNCTIONAL GROUP        DESCRIPTION

@{"AddClipNode" LINK "AddClipNode()"}     Resource                Allocate a Clip node

@{"ClearMem" LINK "ClearMem()"}        Resource                Clear a block of memory

@{"ClearRexxMsg" LINK "ClearRexxMsg()"}    Resource                Release argstrings from message

@{"CloseF" LINK "CloseF()"}          Input/Output            Close a file buffer

@{"ClosePublicPort" LINK "ClosePublicPort()"} Resource                Close a port resource node

@{"CmpString" LINK "CmpString()"}       String                  Compare string structures for equality

@{"CreateArgstring" LINK "CreateArgstring()"} Resource                Create an argstring structure

@{"CreateDOSPkt" LINK "CreateDOSPkt()"}    Input/Output            Creata a DOS Standard Packet

@{"CreateRexxMsg" LINK "CreateRexxMsg()"}   Resource                Create a message packet

@{"CurrentEnv" LINK "CurrentEnv()"}      Resource                Get current storage environment

@{"CVa2i" LINK "CVa2i()"}           Conversion              ASCII to integer

@{"CVc2x" LINK "CVc2x()"}           Conversion              Character to Hex or Binary digits

@{"CVi2a" LINK "CVi2a()"}           Conversion              Integer to ASCII

@{"CVi2arg" LINK "CVi2arg()"}         Conversion              Integer to ASCII argstring

@{"CVi2az" LINK "CVi2az()"}          Conversion              Integer to ASCII,leading zeroes

@{"CVs2i" LINK "CVs2i()"}           Conversion              String structure to integer

@{"CVx2c" LINK "CVx2c()"}           Conversion              Hex or binary digits to binary

@{"DeleteArgstring" LINK "DeleteArgstring()"} Resource                Release an argstring structure

@{"DeleteDOSPkt" LINK "DeleteDOSPkt()"}    Input/Output            Release a DOS Standard Packet

@{"DeleteRexxMsg" LINK "DeleteRexxMsg()"}   Resource                Release a message packet

@{"DOSRead" LINK "DOSRead()"}         Input/Output            Read from a DOS filehandle

@{"DOSWrite" LINK "DOSWrite()"}        Input/Output            Write to a DOS filehandle

@{"ErrorMsg" LINK "ErrorMsg()"}        Conversion              Get error message from error code

@{"ExistF" LINK "ExistF()"}          Input/Output            Check whether a DOS file exists

@{"FillRexxMsg" LINK "FillRexxMsg()"}     Resource                Convert and install argstrings

@{"FindDevice" LINK "FindDevice()"}      Input/Output            Locate a DOS device node

@{"FindRsrcNode" LINK "FindRsrcNode()"}    Resource                Locate a resource node

@{"FreePort" LINK "FreePort()"}        Resource                Close a message port

@{"FreeSpace" LINK "FreeSpace()Sys"}       Resource                Release internal memory

@{"GetSpace" LINK "GetSpace()Sys"}        Resource                Allocate internal memory

@{"InitList" LINK "InitList()"}        Resource                Initialize a list header

@{"InitPort" LINK "InitPort()"}        Resource                Initialize a message port

@{"IsRexxMsg" LINK "IsRexxMsg()"}       Resource                Test a message packet

@{"LengthArgstring" LINK "LengthArgstring()"} Resource                Get length of argstring

@{"ListNames" LINK "ListNames()"}       Resource                Copy node names to an argstring

@{"OpenF" LINK "OpenF()"}           Input/Output            Open a file buffer

@{"OpenPublicPort" LINK "OpenPublicPort()"}  Resource                Allocate and open a port resource node

@{"QueueF" LINK "QueueF()"}          Input/Output            Queue a line in a file buffer

@{"ReadF" LINK "ReadF()"}           Input/Output            Read from a file buffer

@{"ReadStr" LINK "ReadStr()"}         Input/Output            Read a string from a file buffer

@{"RemClipNode" LINK "RemClipNode()"}     Resource                Release a Clip node

@{"RemRsrcList" LINK "RemRsrcList()"}     Resource                Release a resource list

@{"RemRsrcNode" LINK "RemRsrcNode()"}     Resource                Release a resource node

@{"SeekF" LINK "SeekF()"}           Input/Output            Reposition a file buffer

@{"StackF" LINK "StackF()"}          Input/Output            Stack a line in a file buffer

@{"StcToken" LINK "StcToken()"}        String                  Break out a token

@{"StrcmpN" LINK "StrcmpN()"}         String                  Compare strings

@{"StrcpyA" LINK "StrcpyA()"}         String                  Copy a string,converting to ASCII

@{"StrcpyN" LINK "StrcpyN()"}         String                  Copy a string

@{"StrCpyU" LINK "StrCpyU()"}         String                  Copy a string,converting to uppercase

@{"StrflipN" LINK "StrflipN()"}        String                  Reverse characters in a string

@{"Strlen" LINK "Strlen()"}          String                  Find length of a string

@{"ToUpper" LINK "ToUpper()"}         Conversion              ASCII to uppercase

@{"WriteF" LINK "WriteF()"}          Input/Output            Write to a file buffer

@ENDNODE

@NODE "LIBRARY FUNCTION DOCS" "Library Function Docs"
@TOC "APPENDIX C"
@{b}LIBRARY FUNCTION DOCS@{ub}

The following descriptions of the ARexx Systems Library functions are listed

alphabetically. The required arguments and register assignments are shown in

parentheses after the function name. Multiple returns are shown in parentheses

on the left-hand side of the call.

@{b}Contents@{ub}

@{"AddClipNode()" LINK "AddClipNode()"}
@{"AddRsrcNode()" LINK "AddRsrcNode()"}
@{"ClearMem()" LINK "ClearMem()"}
@{"ClearRexxMsg()" LINK "ClearRexxMsg()"}
@{"CloseF()" LINK "CloseF()"}
@{"ClosePublicPort()" LINK "ClosePublicPort()"}
@{"CmpString()" LINK "CmpString()"}
@{"CreateArgstring()" LINK "CreateArgstring()"}
@{"CreateDOSPkt()" LINK "CreateDOSPkt()"}
@{"CreateRexxMsg()" LINK "CreateRexxMsg()"}
@{"CVa2i()" LINK "CVa2i()"}
@{"CVc2x()" LINK "CVc2x()"}
@{"CVi2arg()" LINK "CVi2arg()"}
@{"CVi2az()" LINK "CVi2az()"}
@{"CVs2i()" LINK "CVs2i()"}
@{"CVx2c()" LINK "CVx2c()"}
@{"CurrentEnv()" LINK "CurrentEnv()"}
@{"DeleteArgstring()" LINK "DeleteArgstring()"}
@{"DeleteDOSPkt()" LINK "DeleteDOSPkt()"}
@{"DeleteRexxMsg()" LINK "DeleteRexxMsg()"}
@{"DOSRead()" LINK "DOSRead()"}
@{"DOSWrite()" LINK "DOSWrite()"}
@{"ErrorMsg()" LINK "ErrorMsg()"}
@{"ExistF()" LINK "ExistF()"}
@{"FillRexxMsg()" LINK "FillRexxMsg()"}
@{"FindDevice()" LINK "FindDevice()"}
@{"FindRsrcNode()" LINK "FindRsrcNode()"}
@{"FreePort()" LINK "FreePort()"}
@{"FreeSpace()" LINK "FreeSpace()Sys"}
@{"GetSpace()" LINK "GetSpace()Sys"}
@{"InitList()" LINK "InitList()"}
@{"InitPort()" LINK "InitPort()"}
@{"IsRexxMsg()" LINK "IsRexxMsg()"}
@{"IsSymbol()" LINK "IsSymbol()"}
@{"ListNames()" LINK "ListNames()"}
@{"LockRexxBase()" LINK "LockRexxBase()"}
@{"OpenF()" LINK "OpenF()"}
@{"OpenPublicPort()" LINK "OpenPublicPort()"}
@{"QueueF()" LINK "QueueF()"}
@{"ReadF()" LINK "ReadF()"}
@{"ReadStr()" LINK "ReadStr()"}
@{"RemClipNode()" LINK "RemClipNode()"}
@{"RemRsrcList()" LINK "RemRsrcList()"}
@{"RemRsrcNode()" LINK "RemRsrcNode()"}
@{"SeekF()" LINK "SeekF()"}
@{"StackF()" LINK "StackF()"}
@{"StcToken()" LINK "StcToken()"}
@{"StrcpyA()" LINK "StrcpyA()"}
@{"StrcpyN()" LINK "StrcpyN()"}
@{"StrcpyU()" LINK "StrcpyU()"}
@{"StrflipN()" LINK "StrflipN()"}
@{"Strlen()" LINK "Strlen()"}
@{"StrcmpN()" LINK "StrcmpN()"}
@{"ToUpper()" LINK "ToUpper()"}
@{"UnlockRexxBase()" LINK "UnlockRexxBase()"}
@{"WriteF()" LINK "WriteF()"}

@ENDNODE

@NODE "AddClipNode()" "AddClipNode()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}AddClipNode()-allocate and link a Clip node@{ub}

Usage:@{b}node=AddClipNode(list,name,length,value)@{ub}

        D0              A0   A1    D0     D1

        A0

       (CCR)



Allocates and links a Clip node into the specified list. Clip nodes are

resource nodes containing a name and value string,and include an "auto-delete"

function for simple maintenance. The list argument must point to a properly-

initialized EXEC list header. The name argument points to a null-terminated

name string,the value argument is a pointer to a storage area,and the length

argument is its length in bytes. The returned value is a pointer to the

allocated node,or 0 if the allocation failed.



The @{"RemClipNode()" LINK "RemClipNode()"} function is installed as the "auto-delete" function for each

node. Clip nodes can be intermixed with other resource nodes in a list and then

released with a single call to @{"RemRsrcList()" LINK "RemRsrcList()"}.

See Also:@{"RemClipNode()" LINK "RemClipNode()"},@{"RemRsrcList()" LINK "RemRsrcList()"},@{"RemRsrcNode()" LINK "RemRsrcNode()"}
@ENDNODE

@NODE "AddRsrcNode()" "AddRsrcNode()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}AddRsrcNode()-allocate and link a resource node@{ub}

Usage:@{b}node=AddRsrcNode(list,name,length)@{ub}

        D0              A0   A1    D0

        A0

       (CCR)



Allocates and links a resource node(a RexxRsrc structure)to the specified list.

The name argument is a pointer to a null-terminated string,a copy of which is

installed in the node structure. The length argument is the total length for

the node;this length is saved within the node so that it may be released later.


The returned value is a pointer to the allocated node,or 0 if the allocation

failed.

See Also:@{"RemRsrcList()" LINK "RemRsrcList()"},@{"RemRsrcNode()" LINK "RemRsrcNode()"}
@ENDNODE

@NODE "ClearMem()" "ClearMem()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}ClearMem()-clear a block of memory@{ub}

Usage:@{b}ClearMem(address,length)@{ub}

                A0       D0



Clears a block of memory beginning at the given address for the specified

length in bytes. The address must be word-aligned and the length must be a

multiple of 4 bytes;all structures allocated by ARexx meet these restrictions.

Register A0 is preserved.
@ENDNODE

@NODE "ClearRexxMsg()" "ClearRexxMsg()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}ClearRexxMsg()-release argument strings@{ub}

Usage:@{b}ClearRexxMsg(msgptr,count)@{ub}

                    A0     D0



Releases one or more argstrings from a message packet and clears the

corresponding slots. The count argument specifies the number of argument slots

to clear,and can be set to less than 16 to reserve some to the slots for

private use. No action is taken if the slot already contains a zero value.

See Also:@{"FillRexxMsg()" LINK "FillRexxMsg()"}
@ENDNODE

@NODE "CloseF()" "CloseF()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}CloseF()-close a file buffer@{ub}

Usage:@{b}boolean=CloseF(IoBuff)@{ub}

        D0             A0



Release the IoBuff structure and closes the associated DOS file. CloseF()is the

"auto-delete" function for the IoBuff structure,so an entire list of file

buffers can be closed with a single call to @{"RemRsrcList()" LINK "RemRsrcList()"}.
@ENDNODE

@NODE "ClosePublicPort()" "ClosePublicPort()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}ClosePublicPort()-close a port resource node@{ub}

Usage:@{b}ClosePublicPort(node)@{ub}

                       A0



Unlinks and closes the message port and releases the resource node structure.

The node must have been allocated by the OpenPublicPort()function.

See Also:@{"OpenPublicPort()" LINK "OpenPublicPort()"}
@ENDNODE

@NODE "CmpString()" "CmpString()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}CmpString()-compare string structures for equality@{ub}

Usage:@{b}test=CmpString(ss1,ss2)@{ub}

       D0             A0 A1

      (CCR)



The arguments ss1 and ss2 must be pointers to ARexx string structures and are

compared for equality. String structures include the length and hash code of

the string,so the actual strings are not compared unless the lengths and hash

codes match. The return value sets the CCR and will be -1(True)if the strings

match and 0(False)otherwise.
@ENDNODE

@NODE "CreateArgstring()" "CreateArgstring()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}CreateArgstring()-create an argument string structure@{ub}

Usage:@{b}argstring=CreateArgstring(string,length)@{ub}

          D0                      A0     D0

          A0

         (CCR)



Allocates a RexxArg structure and copies the supplied string into it. The

argstring return is a pointer to the string buffer of the structure,and can be

treated like an ordinary string pointer. The RexxArg structure stores the

structure size and string length at negative offsets to the string pointer. The

string pointer can be set to NULL if only an uninitialized structure is

required.

See Also:@{"DeleteArgstring()" LINK "DeleteArgstring()"}
@ENDNODE

@NODE "CreateDOSPkt()" "CreateDOSPkt()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}CreateDOSPkt()-allocate and initialize a DOS standard Packet.@{ub}

Usage:@{b}packet = CreateDOSPkt()@{ub}

       D0

       A0

      (CCR)



Allocates a DOS StandardPacket structure and initializes it by interlinking the

EXEC message and the DOS packet substructures. No replyport is installed in

either the message or the packet,as these fields are generally filled in just

before the message is sent.

See Also:@{"DeleteDOSPkt()" LINK "DeleteDOSPkt()"}
@ENDNODE

@NODE "CreateRexxMsg()" "CreateRexxMsg()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}CreateRexxMsg()-allocate an ARexx message packet@{ub}

Usage: @{b}msgptr=CreateRexxMsg(replyport,extension,host)@{ub}

         D0                     A0       A1      D0

         A0

        (CCR)



This function allocates an ARexx message packet from the system free memory

list. The message packet consists of a standard EXEC message structure extended

to include space for function arguments,returned results,and internal defaults.

The replyport argument points to a public or private message port and must be

supplied,as it is required to return the message packet to the sender. The

extension and host arguments are pointers to null-terminated strings that

provide values for the default file extension and the initial host address,

respectively. Additional override fields in the extended packet except for the

primary and secondary result fields rm_Result1 and rm_Result2.

See Also: @{"DeleteRexxMsg()" LINK "DeleteRexxMsg()"}
@ENDNODE

@NODE "CVa2i()" "CVa2i()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}CVa2i()-convert from ASCII to integer@{ub}

Usage: @{b}(digits,value) = CVa2i(buffer)@{ub}

          D0     D1             A0



Converts the buffer of ASCII characters to a signed long integer value. The

scan proceeds until a non-digit character is found or until an overflow is

detected. The function returns both the number of digits scanned and the

converted value.
@ENDNODE

@NODE "CVc2x()" "CVc2x()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}CVc2x()-convert(unpack)from character string to hex or binary digits.@{ub}

Usage: @{b}error = CVc2x(outbuff,string,length,mode)@{ub}

        D0             A0      A1     D0    D1



Converts the signed integer value argument to ASCII characters using the

supplied buffer pointer. The digits argument specifies the maximum number of

characters that will be copied to the buffer. The returned length is the actual

number of characters copied. The pointer return is the new buffer pointer.

See Also: @{"CVi2az()" LINK "CVi2az()"}
@ENDNODE

@NODE "CVi2arg()" "CVi2arg()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}CVi2arg()-convert from integer to argstring@{ub}

Usage: @{b}argstring=CVi2arg(value,digits)@{ub}

          D0               D0    D1

          A0

         (CCR)



Converts the signed long integer value argument to ASCII characters,and

installs them in an argstring(a RexxArg structure). The returned value is an

argstring pointer or 0 if the allocation failed. The allocated structure can be

released using @{"DeleteArgstring()" LINK "DeleteArgstring()"}.
@ENDNODE

@NODE "CVi2az()" "CVi2az()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}CVi2az()-convert from integer to ASCII with leading zeroes@{ub}

Usage: @{b}(length,pointer)=CVi2az(buffer,value,digits)@{ub}

          D0      A0            A0     D0    D1



Converts the signed long integer value argument to ASCII characters in the

supplied buffer,with leading zeroes to fill out the requested number of digits.

This function is identical to @{"CVi2a" LINK "CVi2a()"} except that leading zeroes are supplied.

See Also:@{"CVi2a()" LINK "CVi2a()"}
@ENDNODE

@NODE "CVs2i()" "CVs2i()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}CVs2i()-convert from string structure to integer@{ub}

Usage: @{b}(error,value)=CVs2i(ss)@{ub}

         D0    D1          A0



The ss argument must be a pointer to a string structure. It is converted to a

signed long integer value return. The error return code is @{"47" LINK "ERROR 47"}("Arithmetic

conversion error")if the string is not a valid number.
@ENDNODE


@NODE "CVx2c()" "CVx2c()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}CVx2c()-convert from hex or binary digits to(packed)string@{ub}

Usage:@{b}error=CVx2c(outbuff,string,length,mode)@{ub}

       D0           A0      A1     D0    D1



Converts the string argument of hex(0-9,A-F)or binary(0,1)digits to the packed

binary representation. The mode argument specifies the(hex or binary)conversion

mode,and must be set to -1 for hex strings or 0 for binary strings. Blank

characters may be embedded in the string for readability,but only at byte

boundaries. The error return code is 47 if the string is not a valid hex or

binary string.
@ENDNODE

@NODE "CurrentEnv()" "CurrentEnv()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}CurrentEnv()-return the current storage environment@{ub}

Usage:@{b}envptr=CurrentEnv(rxtptr)@{ub}

        D0                A0



Returns a pointer to the current storage environment associated with an

executing ARexx program. The rxptr argument is a pointer to the RexxTask

structure,and may be obtained from the message packet sent to an external

application.
@ENDNODE

@NODE "DeleteArgstring()" "DeleteArgstring()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}DeleteArgstring()-delete(release)an argstring structure@{ub}

Usage:@{b}DeleteArgstring(argstring)@{ub}

                          A0



Releases an argstring (RexxArg) structure. The RexxArg structure contains the

total allocated length at a negative offset from the argstring pointer.

See Also:@{"CreateArgstring()" LINK "CreateArgstring()"}
@ENDNODE

@NODE "DeleteDOSPkt()" "DeleteDOSPkt()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}DeleteDOSPkt()-release a DOS Standard Packet structure.@{ub}

Usage:@{b}DeleteDOSPkt(message)@{ub}

                      A0



Releases a DOS StandardPacket structure,typically obtained by a prior call to

@{"CreateDOSPkt()" LINK "CreateDOSPkt()"}.

See Also:@{"CreateDOSPkt()" LINK "CreateDOSPkt()"}
@ENDNODE

@NODE "DeleteRexxMsg()" "DeleteRexxMsg()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}DeleteRexxMsg()-delete(release)an ARexx message packet.@{ub}

Usage:@{b}DeleteRexxMsg(packet)@{ub}

                      A0



Release an ARexx message packet to the system free-memory list. The internal

MN_LENGTH field is used as the total size of the memory block to be released,so

this function can be used to release any message packet that contains the total

length in this field. Any embedded argument strings must be released before

calling DeleteRexxMsg().

See Also:@{"CreateRexxMsg()" LINK "CreateRexxMsg()"}
@ENDNODE

@NODE "DOSRead()" "DOSRead()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}DOSRead()-read from a DOS file@{ub}

Usage:@{b}count=DOSRead(filehandle,buffer,length)@{ub}

        D0              A0       A1     D0

       (CCR)



Reads one or more characters from a DOS filehandle into the supplied buffer.

The length argument specifies the maximum number of characters that will be

read. The returned count is the actual number of bytes transferred,or -1 if an

error occurred.
@ENDNODE

@NODE "DOSWrite()" "DOSWrite()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}DOSWrite()-write to a DOS file@{ub}

Usage:@{b}count=DOSWrite(filehandle,buffer,length)@{ub}

       D0               A0        A1     D0

      (CCR)



Writes a buffer of the specified length to a DOS filehandle. The retuned count

is the actual number of bytes written,or -1 if an error occurred.
@ENDNODE

@NODE "ErrorMsg()" "ErrorMsg()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}ErrorMsg()-find the message associated with an error code@{ub}

Usage:@{b}(boolean,ss)=ErrorMsg(code)@{ub}

          D0   A0            D0



Returns the error message(as a pointer to a string structure)associated with

the specified ARexx error code. The boolean return will be -1 if the supplied

code was a valid ARexx error code,and 0 otherwise.
@ENDNODE

@NODE "ExistF()" "ExistF()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}ExistF()-check whether an external file exists@{ub}

Usage:@{b}boolean=ExistF(filename)@{ub}

        D0              A0

       (CCR)



Tests whether an external file currently exists by attempting to obtain a read

lock on the file. The boolean return indicates whether the operation succeeded,

and the lock is released.
@ENDNODE

@NODE "FillRexxMsg()" "FillRexxMsg()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}FillRexxMsg()-convert and install arguments in message packet.@{ub}

Usage:@{b}boolean=FillRexxMsg(msgptr,count,mask)@{ub}

        D0                 A0     D0    D1



This function can be used to convert and install up to 16 argument strings in a

RexxMsg structure. The message packet must be allocated and the argument fields

of interest set to either a pointer to a null-terminated string or an integer

value. The count argument specifies the number of fields,beginning with ARGO,to

be converted into argstrings and installed into the argument slot. Bits 0-15 of

the mask argument specify whether the corresponding argument is a string

pointer(bit clear)or an integer value(bit set).



The count argument is normally set to the exact number of strings to be passed.

By setting this count to less than 16,a number of the slots can be reserved for

private uses.



The returned value is -1(True)if all of the arguments were successfully

converted. In the event of an allocation failure,all of the partial results are

released and a value of 0 is returned.

See Also:@{"ClearRexxMsg()" LINK "ClearRexxMsg()"}
@ENDNODE

@NODE "FindDevice()" "FindDevice()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}FindDevice()-check whether a DOS device exists.@{ub}

Usage:@{b}device=FindDevice(devicename,type)@{ub}

        D0                  A0      D0

        A0

       (CCR)



Scans the DOS DeviceList for a device node of the specified type matching the

null-terminated name string. The acceptable values for the type argument are

the constants @{b}DLT_DEVICE,DLT_DIRECTORY@{ub},or @{b}DLT_VOLUME@{ub} define in the DOS INCLUDE

files. Device names are conveted to uppercase before checking for a match. The

returned value is a pointer to the matched device node,or 0 if the device was

not found.
@ENDNODE

@NODE "FindRsrcNode()" "FindRsrcNode()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}FindRsrcNode()-locate a resource node with the given name.@{ub}

Usage:@{b}node=FindRsrcNode(list,name,type)@{ub}

      D0                 A0   A1   D0

      A0

     (CCR)



Searchs the specified list for the first node of the selected type with the

given name. The list argument must be a pointer to a properly-initialized EXEC

list header. The name argument is a pointer to a null-terminated string. If the

type argument is 0,all nodes are selected;otherwise,the supplied type must

match the LN_TYPE field of the node. The returned value is a pointer to the

node or 0 if no matching node was found.
@ENDNODE

@NODE "FreePort()" "FreePort()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}FreePort()-release resources associated with a message port@{ub}

Usage:@{b}FreePort(port)@{ub}

                A0



This function deallocates the signal bit associated with a message port and

marks the port as "closed." The task calling FreePort() must be the same one

that initialized the port,since signal bit allocations are specific to a task.

The memory space associated with the port is not released.

See Also:@{"InitPort()" LINK "InitPort()"}
@ENDNODE

@NODE "FreeSpace()Sys" "FreeSpace()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}FreeSpace()-releases space to the internal memory allocator.@{ub}

Usage:@{b}FreeSpace(envptr,block,length)@{ub}

                  A0     A1    D0



Returns a block of memory to the internal allocator,which must have been

obtained from a call to @{"GetSpace()" LINK "GetSpace()Sys"}. The envptr argument is a pointer to the

base or current storage environment.

See Also:@{"CurrentEnv()" LINK "CurrentEnv()"},@{"GetSpace()" LINK "GetSpace()Sys"}
@ENDNODE

@NODE "GetSpace()Sys" "GetSpace()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}GetSpace()-allocate memory using the internal allocator.@{ub}

Usage:@{b}block=GetSpace(envptr,length)@{ub}

       D0              A0     D0

       A0

      (CCR)



Allocates a block of memory using the internal allocator. The memory is

obtained from an internal pool managed by the interpreter and is returned to

the operating system when the ARexx program terminates. The envptr argument is

a pointer to the base or current storage environment for the program.



The internal allocator must be used to allocate strings for use as values for

symbols,and is convenient for obtaining small blocks of memory whose lifetime

will not exceed that of the ARexx program.

See Also:@{"CurrentEnv()" LINK "CurrentEnv()"},@{"FreeSpace()" LINK "FreeSpace()Sys"}
@ENDNODE

@NODE "InitList()" "InitList()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}InitList()-initialize a list header@{ub}

Usage:@{b}InitList(list)@{ub}

                A0



Initializes an EXEC list header structure.
@ENDNODE

@NODE "InitPort()" "InitPort()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}InitPort()-initialize a previously-allocated message port.@{ub}

Usage:@{b}(signal,port)=InitPort(port,name)@{ub}

         D0    A1             A0   A1



Initializes a message port structure for which memory space has been previously

allocated,typically as part of a larger structure or as static storage in a

program. It installs the task ID(of the task calling the function)into the

MP_SIGTASK field and allocates a signal bit. The name parameter must be a

pointer to a null-terminated string. The signal return is the signal bit that

was allocated for the port. In the event that a signal could not be assigned,a

value of -1 is returned.



Note that the port is not linked into the system Ports List. If the port is to

be made public,this can be done after the function returns. The port address is

returned in the correct register(A1)for a subsequent call to the EXEC function

AddPort().

See Also:@{"FreePort()" LINK "FreePort()"}
@ENDNODE

@NODE "IsRexxMsg()" "IsRexxMsg()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}IsRexxMsg()-check whether a message came from ARexx.@{ub}

Usage:@{b}boolean=IsRexxMsg(msgptr)@{ub}

         D0               A0



Tests whether the message packet specified by the msgptr argument came from an

ARexx program. ARexx marks its messages with a pointer to a static string

"REXX" in the LN_NAME field. The returned value is either -1(True)if the

message came from ARexx or 0(False)otherwise.
@ENDNODE


@NODE "IsSymbol()" "IsSymbol()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}IsSymbol()-check whether a string is a valid symbol.@{ub}

Usage:@{b}(code,length)=IsSymbol(string)@{ub}

        D0    D1               A0



Scans the supplied string pointer for ARexx symbol characters. The code return

is the symbol type if a symbol was found,or 0 if the string did not start with

a symbol character. The length return is the total length of the symbol.
@ENDNODE

@NODE "ListNames()" "ListNames()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}ListNames()-build a string of names from a list.@{ub}

Usage:@{b}argstring=ListNames(list,separator)@{ub}

         D0                A0   D0[0:7]

         A0

        (CCR)



Scans the specified list and copies the name strings into an argstring. The

list argument must be a pointer to an initialized EXEC list header. The

separator argument is the character,possibly a null,to be placed as a delimiter

between the node names.



The list is traversed inside a Forbid() exclusion and so may be used with shared

or system lists. The returned argstring can be released using @{"DeleteArgstring()" LINK "DeleteArgstring()"}

after the names are no longer needed.

See Also:@{"DeleteArgstring()" LINK "DeleteArgstring()"}
@ENDNODE

@NODE "LockRexxBase()" "LockRexxBase()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}LockRexxBase()-lock a shared resource.@{ub}

Usage:@{b}LockRexxBase(resource)@{ub}

                      D0



Secures the specified resource in the ARexx Systems Library base for read

access. The resource argument is a manifest constant for the required resource,

or zero to lock the entire structure.



Note that write access to shared resources is normally mediated by the ARexx

resident process,which operates at an elevated priority to gain exclusive

access. Locking a resource should not be attempted from a process operating at

a priority higher than the resident process.

See Also:@{"UnlockRexxBase()" LINK "UnlockRexxBase()"}
@ENDNODE

@NODE "OpenF()" "OpenF()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}OpenF()-open a file buffer@{ub}

Usage:@{b}IoBuff=OpenF(list,filename,mode,logical)@{ub}

        D0          A0    A1      D0     D1

        A0

       (CCR)



Attempts to open an external file in the specified mode,which should be one of

the constants RXIO_READ,RXIO_WRITE,or RXIO_APPEND defined in the ARexx INCLUDE

files.


If successful,an IoBuff structure is allocated and linked into the specified

list. The list argument must be a pointer to a properly-initialized EXEC list

header.



The optional logical argument is the logical name for the file,and must be

either a pointer to a null-terminated string or zero(NULL)if a name is not

required.

See Also:@{"CloseF()" LINK "CloseF()"}
@ENDNODE

@NODE "OpenPublicPort()" "OpenPublicPort()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}OpenPublicPort()-open a public message port@{ub}

Usage:@{b}node=OpenPublicPort(list,name)@{ub}

       D0                  A0   A1

       A0

      (CCR)



Allocates a message port as an "auto-delete" resource node and links it into

the specified list. The list argument must point to a properly initialized EXEC

list header. The message port is initialized with the given name and linked

into the system Ports List.

See Also:@{"ClosePublicPort()" LINK "ClosePublicPort()"}
@ENDNODE

@NODE "QueueF()" "QueueF()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}QueueF()-queue a line to a file buffer.@{ub}

Usage:@{b}count-=QueueF(IoBuff,buffer,length)@{ub}

        D0            A0     A1     D0



Queues a buffer of characters in the stream associated with the IoBuff

structure. The stream must be managed by a DOS handler that supports the

ACTION_QUEUE packet.



Queued lines are placed in "first-in,first-out" order and are immediately

available to be read from the stream. The buffer argument is a pointer to a

string of characters,and the length specifies the number of characters to be

queued. The return value is the actual count of characters or -1 if an error

occurred.

See Also:@{"StackF()" LINK "StackF()"}
@ENDNODE

@NODE "ReadF()" "ReadF()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}ReadF()-read characters from a file buffer@{ub}

Usage:@{b}count=ReadF(IoBuff,buffer,length)@{ub}

       D0           A0     A1     D0

      (CCR)



Reads one or more characters from the file specified by the IoBuff pointer. The

buffer argument is a pointer to a storage area,and the length argument

specifies the maximum number of characters to be read. The return value is the

actual number of characters read,or -1 if an error occurred.
@ENDNODE

@NODE "ReadStr()" "ReadStr()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}ReadStr()-read a string from a file@{ub}

Usage:@{b}(count,pointer)=ReadStr(IoBuff,buffer,length)@{ub}

        D0     A1               A0     A1     D0



Reads characters from the file specified by the IoBuff pointer until a

"newline" character is found. The "newline" is not included in the returned

string. The return value is the actual number of characters read,or -1 if an

error occurred.

See Also:@{"ReadF()" LINK "ReadF()"}
@ENDNODE

@NODE "RemClipNode()" "RemClipNode()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}RemClipNode()-unlink and deallocate a list Clip node.@{ub}

Usage:@{b}RemClipNode(node)@{ub}

                   A0



Unlinks and releases the specified Clip node. The function is the "auto-delete"

function for Clip nodes,and will be called automatically by @{"RemRsrcNode()" LINK "RemRsrcNode()"} or

@{"RemRsrcList()" LINK "RemRsrcList()"}.

See Also:@{"AddClipNode()" LINK "AddClipNode()"},@{"RemRsrcList()" LINK "RemRsrcList()"},@{"RemRsrcNode()" LINK "RemRsrcNode()"}
@ENDNODE

@NODE "RemRsrcList()" "RemRsrcList()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}RemRsrcList()-unlink and deallocate a list of resource nodes@{ub}

Usage:@{b}RemRsrcList(list)@{ub}

                   A0



Scans the supplied list and releases any nodes found. The list must consist of

resource nodes(RexxRsrc structures),which contain information to allow

automatic cleanup and deletion.

See Also:@{"RemRsrcNode()" LINK "RemRsrcNode()"}
@ENDNODE

@NODE "RemRsrcNode()" "RemRsrcNode()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}RemRsrcNode()-unlink and deallocate a resource node@{ub}

Usage:@{b}RemRsrcNode(node)@{ub}

                   A0



Unlinks and releases the specified resource node,including the name string if

one is present. If an "auto-delete" function has been specified in the node,it

is called to perform any required resource deallocation before the node is

released.

See Also:@{"RemRsrcList()" LINK "RemRsrcList()"}
@ENDNODE

@NODE "SeekF()" "SeekF()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}SeekF()-seek to the specified position in a file.@{ub}

Usage:@{b}position=SeekF(IoBuff,offset,anchor)@{ub}

        D0             A0    D0      D1



Seeks to a new position in the file is specified by the IoBuff pointer. The

position is given by the offset argument,a byte offset relative to the supplied

anchor argument. The anchor may specify the beginning(-1),the current position

(0),or the end of the file(1). The return value is the new position relative to

the beginning of the file.
@ENDNODE

@NODE "StackF()" "StackF()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}StackF()-stack a line to a file buffer.@{ub}

Usage:@{b}count=StackF(IoBuff,buffer,length)@{ub}

        D0           A0     A1     D0



Stacks a buffer of characters in the stream associated with the IoBuff

structure. The buffer argument is a pointer to a string of characters,and the

length specifies the number of characters to be stacked. The return value is

the actual count of characters to be stacked. The return value is the actual

count of characters or -1 if an error occurred.



Stacked lines are placed in "last-in,first-out" order and are immediately

available to be read from the stream. The stream must be managed by a DOS

handler that supports the ACTION_STACK packet.

See Also:@{"QueueF()" LINK "QueueF()"}
@ENDNODE

@NODE "StcToken()" "StcToken()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}StcToken()-break out the next token from a string@{ub}

Usage:@{b}(quote,length,scan,token)=StcToken(string)@{ub}

        D0     D1    A0   A1               A0



Scans a null-terminated string to select the next token delimited by "white

space,"and returns a pointer to the start of the token. The quote return will

be an ASCII single or double quote if the token was quoted and 0 otherwise;

white space characters are ignored within quoted strings. The length return is

the total length of the token,including any quote characters. The scan return

is advanced beyond the current token to prepare for the next call.
@ENDNODE

@NODE "StrcpyA()" "StrcpyA()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}StrcpyA()-copy a string,converting to ASCII@{ub}

Usage:@{b}hash=StrcpyA(destination,source,length)@{ub}

       D0              A0        A1     D0



Copies the source string to the destination area,converting the characters to

ASCII by clearing the high-order bit of each byte. The length of the string

(which may include embedded nulls)is considered as a 2-byte usingned integer.

So the string is limited in length to 65,535 bytes. The hash return is the

internal hash byte for the copied string.

See Also:@{"StrcpyN()" LINK "StrcpyN()"},@{"StrcpyU" LINK "StrcpyU"}
@ENDNODE

@NODE "StrcpyN()" "StrcpyN()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}StrcpyN()-copy a string@{ub}

Usage:@{b}hash=StrcpyN(destination,source,length)@{ub}

       D0              A0        A1     D0



Copies the source string to the destination area. The length of the string

(which may include embedded nulls)is considered as a 2-byte unsigned integer.

The hash return is the internal hash byte for the copied string.

See Also:@{"StrcpyA()" LINK "StrcpyA()"},@{"StrcpyU" LINK "StrcpyU"}
@ENDNODE

@NODE "StrcpyU()" "StrcpyU()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}StrcpyU()-copy a string,converting to uppercase@{ub}

Usage:@{b}hash=StrcpyU(destination,source,length)@{ub}

       D0               A0       A1     D0



Copies the source string to the destination area,converting to uppercase

alphabetics. The length of the string(which may include embedded nulls)is

considered as a 2-byte unsigned integer. The has return is the internal hash

byte for the copied string.

See Also:@{"StrcpyA()" LINK "StrcpyA()"},@{"StrcpyN" LINK "StrcpyN"}
@ENDNODE

@NODE "StrflipN()" "StrflipN()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}StrflipN()-reverse the characters in a string@{ub}

Usage:@{b}StrflipN(string,length)@{ub}

                 A0     D0



Reverses the sequence of characters in a string. The conversion is performed in

place.
@ENDNODE

@NODE "Strlen()" "Strlen()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}Strlen()-find the length of a null-terminated string@{ub}

Usage:@{b}length=Strlen(string)@{ub}

        D0            A0

       (CCR)



Returns the number of characters in a null-terminated string. Register A0 is

preserved,and the CCR is set for the returned length.
@ENDNODE

@NODE "StrcmpN()" "StrcmpN()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}StrcmpN()-compare the values of strings@{ub}

Usage:@{b}test=StrcmpN(string1,string2,length)@{ub}

       D0             A0      A1     D0

      (CCR)



The string1 and string2 arguments are compared for the specified number of

characters. The comparison proceeds character-by-character until a difference

is found or the maximum number of characters have been examined. The returned

value is -1 if the first string was less,1 if the first string was greater,and

0 if the strings match exactly. The CCR register is set for the returned value.
@ENDNODE

@NODE "ToUpper()" "ToUpper()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}ToUpper()-translate an ASCII character to uppercase@{ub}

Usage:@{b}upper=ToUpper(character)@{ub}

       D0               D0



Converts an ASCII character to uppercase. Only register D0 is affected.
@ENDNODE

@NODE "UnlockRexxBase()" "UnlockRexxBase()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}UnlockRexxBase()-unlock a shared resource.@{ub}

Usage:@{b}UnlockRexxBase(resource)@{ub}

                        D0



Releases the specified resource,or all resources if the argument is zero. Every

call to @{"LockRexxBase()" LINK "LockRexxBase()"} should be followed eventually by a call to UnlockRexxBase

()for the same resource.

See Also:@{"LockRexxBase()" LINK "LockRexxBase()"}
@ENDNODE

@NODE "WriteF()" "WriteF()"
@TOC "LIBRARY FUNCTION DOCS"
@{b}WriteF()-write characters to a file buffer@{ub}

Usage:@{b}count=WriteF(IoBuff,buffer,length)@{ub}

        D0          A0      A1     D0

       (CCR)



Writes a buffer of characters of the specified length to the file associated

with the IoBuff pointer. The buffer argument is a pointer to a storage area,

and the length argument specifies the number of characters to be written. The

returned value is the actual number of characters written or -1 if an error

occurred.

See Also:@{"CloseF()" LINK "CloseF()"},@{"OpenF()" LINK "OpenF()"},@{"ReadF()" LINK "ReadF()"}

@ENDNODE

@NODE "APPENDIX D" "Appendix D"

                   @{b}APPENDIX D THE AREXX SUPPORT LIBRARY@{ub}



The ARexx language system is distributed with an external function library that

provides a number of Amiga-specific functions. It is a standard Amiga shared

library named rexxsupport.library and should reside in the system

LIBS:directory. Unlike the Systems Library described in the previous

@{"Appendix" LINK "APPENDIX C"},the support library functions are callable from within ARexx programs.

@{b}Contents@{ub}

@{"ALLOCMEM()" LINK "ALLOCMEM()"}
@{"CLOSEPORT()" LINK "CLOSEPORT()"}
@{"FREEMEM()" LINK "FREEMEM()"}
@{"GETARG()" LINK "GETARG()"}
@{"GETPKT()" LINK "GETPKT()"}
@{"OPENPORT()" LINK "OPENPORT()"}
@{"REPLY()" LINK "REPLY()"}
@{"SHOWDIR()" LINK "SHOWDIR()"}
@{"SHOWLIST()" LINK "SHOWLIST()"}
@{"STATEF()" LINK "STATEF()"}
@{"WAITPKT()" LINK "WAITPKT()"}

@ENDNODE



@NODE "ALLOCMEM()" "ALLOCMEM()"
@TOC "APPENDIX D"
@{b}ALLOCMEM()@{ub}

Usage:@{b}ALLOCMEM(length,[attribute])@{ub}

Allocates a block of memory of the specified length from the system free-

memory pool and returns its address as a 4-byte string. The optional attribute

parameter must be a standard EXEC memory allocation flag,supplied as a 4-byte

string. The default attribute is for "PUBLIC" memory(not cleared).



This function should be used whenever memory is allocated for use by external

programs. It is the user's responsibility to release the memory space when it

is no longer needed.

See Also:@{"FREEMEM()" LINK "FREEMEM()"}

Example:
@{i}
        say c2x(allocmem(1000)) ==>00050000
@{ui}
@ENDNODE
@NODE "CLOSEPORT()" "CLOSEPORT()"
@TOC "APPENDIX D"
@{b}CLOSEPORT()@{ub}

Usage:@{b}CLOSEPORT(name)@{ub}

Closes the message port specified by the name argument,which must have been

allocated by a call to @{"OPENPORT()" LINK "OPENPORT()"} within the current ARexx program. Any messages

received but not yet @{"REPLY" LINK "REPLY()"}ed are automatically returned with the return code

set to 10.

See Also:@{"OPENPORT()" LINK "OPENPORT()"}

Example:
@{i}
        call closeport myport
@{ui}
@ENDNODE
@NODE "FREEMEM()" "FREEMEM()"
@TOC "APPENDIX D"
@{b}FREEMEM()@{ub}

Usage:@{b}FREEMEM(address,length)@{ub}

Releases a block of memory of the given length to the system freelist. The

address parameter is a four-byte string,typically obtained by a prior call to

@{"ALLOCMEM()" LINK "ALLOCMEM()"}. FREEMEM() cannot be used to release memory allocated using

@{"GETSPACE()" LINK "GETSPACE()"},the ARexx internal memory allocator. The returned value is a boolean

success flag.

See Also:@{"ALLOCMEM()" LINK "ALLOCMEM()"}

Example:
@{i}
        say freemem('00042000'x,32)     ==>1
@{ui}
@ENDNODE
@NODE "GETARG()" "GETARG()"
@TOC "APPENDIX D"
@{b}GETARG()@{ub}

Usage:@{b}GETARG(packet,[n])@{ub}

Extracts a command,function name,or argument string from a message packet. The

packet argument must be a 4-byte address obtained from a prior call to

@{"GETPKT()" LINK "GETPKT()"}. The optional n argument specifies the slot containing the string to

be extracted,and must be less than or equal to the actual argument count for

the packet. Commands and functions names are always in slot 0;function packets

may have argument strings in slots 1-15.

Examples:
@{i}
        command = getarg(packet)

        function= getarg(packet,0)      /* name string  */

        arg1    = getarg(packet,1)      /* 1st argumeent*/
@{ui}
@ENDNODE
@NODE "GETPKT()" "GETPKT()"
@TOC "APPENDIX D"
@{b}GETPKT()@{ub}

Usage:@{b}GETPKT(name)@{ub}

Checks the message port specified by the name argument to see whether any

messages are available. The named message port must have been opened by a prior

call to @{"OPENPORT()" LINK "OPENPORT()"} within the current ARexx program. The returned value is the

4-byte address of the first message packet,or '0000 0000'x if no packets were

available.



The function returns immediately whether or not a packet is enqueued at the

message port. Programs should never be designed to "busy-loop" on a message

port. If there is no useful work to be done until the next message packet

arrives,the program should call @{"WAITPKT()" LINK "WAITPKT()"} and allow other tasks to proceed.

See Also:@{"WAITPKT()" LINK "WAITPKT()"}

Example:
@{i}
        packet = getpkt('MyPort')
@{ui}
@ENDNODE
@NODE "OPENPORT()" "OPENPORT()"
@TOC "APPENDIX D"
@{b}OPENPORT()@{ub}

Usage:@{b}OPENPORT(name)@{ub}

Creates a public message port with the given name. The returned value is the

4-byte address of the Port Resource strcture or '0000 000'xif the port could

not be opened or initialized. An initialization failure will occur if another

port of the same name already exists,or if a signal bit couldn't be allocated.


The message port is allocated as a Port Resource node and is linked into the

program's global data structure. Ports are automatically closed when the

program exits,and any pending messages are returned to the sender.

See Also:@{"CLOSEPORT()" LINK "CLOSEPORT()"}

Example:
@{i}
        myport = openport("MyPort")
@{ui}
@ENDNODE
@NODE "REPLY()" "REPLY()"
@TOC "APPENDIX D"
@{b}REPLY()@{ub}

Usage:@{b}REPLY(packet,rc)@{ub}

Returns a message packet to the sender,with the primary result field set to the

value given by the rc argument. The secondary result is cleared. The packet

argument must be supplied as a 4-byte address,and the rc argument must be a

whole number.

Example:
@{i}
        call reply packet,10            /* error return*/
@{ui}
@ENDNODE
@NODE "SHOWDIR()" "SHOWDIR()"
@TOC "APPENDIX D"
@{b}SHOWDIR()@{ub}

Usage:@{b}SHOWDIR(directory,['All' | 'File' | 'Dir'])@{ub}

Returns the contents of the specified directory as a string of names separated

by blanks. The second parameter is an option keyword that selects whether all

entries,only files,or only subdirectories will be included.

Example:
@{i}
        say showdir("df1:c")            ==>rx ts te hi tco tcc
@{ui}
@ENDNODE
@NODE "SHOWLIST()" "SHOWLIST()"
@TOC "APPENDIX D"
@{b}SHOWLIST()@{ub}

Usage:@{b}SHOWLIST[{'D' | 'L' | 'P' | 'R' | 'W' },[name])@{ub}

The first argument is an option keyword to select a system list;the options

currently supported are @{b}Devices,Libraries,Ports,Ready,@{ub}and @{b}Waiting@{ub}. If only the

first parameter is supplied,the function scans the selected list and returns

the node names in a string separated by blanks. If the name parameter is

supplied,the boolean return indicates whether the specified list contains a

node of that name. The name matching is case-sensitive.



The list is scanned with task switching forbidden so as to provide an accurate

snapshot of the list at that time.

Example:
@{i}
        say showlist('P')               ==>REXX MyCon

        say showlist('P','REXX')        ==>1
@{ui}
@ENDNODE
@NODE "STATEF()" "STATEF()"
@TOC "APPENDIX D"
@{b}STATEF()@{ub}

Usage:@{b}STATEF(filename)@{ub}

Returns a string containing information about an external file. The string is

formatted as   "{DIR | FILE} length blocks protection comment."

The length token gives the file length in bytes,and the block token specifies

the file length in blocks.

Example:
@{i}
        say statef("libs:rexxsupport.library")

        /* would give "FILE 1880 4 RWED "       */
@{ui}
@ENDNODE
@NODE "WAITPKT()" "WAITPKT()"
@TOC "APPENDIX D"
@{b}WAITPKT()@{ub}

Usage:@{b}WAITPKT(name)@{ub}

Waits for a message to be received at the specified(named)port,which must have

been opened by a call to @{"OPENPORT()" LINK "OPENPORT()"} within the current ARexx program. The

returned boolean value indicates whether a message packet is available at the

port. Normally the returned value will be 1(True),since the function waits

until an event occurs at the message port.



The packet must then be removed by a call to @{"GETPKT()" LINK "GETPKT()"},and should be returned

eventually using the @{"REPLY()" LINK "REPLY()"} function. Any message packets received but not

returned when an ARexx program exits are automatically REPLYed with the return

code set to 10.

Example:
@{i}
        call waitpkt 'MyPort'   /* wait awhile  */
@{ui}
@ENDNODE
@NODE "APPENDIX E" "Appendix E"

                        @{b}APPENDIX E DISTRIBUTION FILES@{ub}



This appendix lists the directores of the standard ARexx distribution disk. The

contents of some of the directories may change from time to time,so your disk

may not show exactly the same files. Most notably,the :rexx directory will

expand as more program examples are included in it.



The second section of the Appendix lists the HEADER files that define the

constants and data structures used with ARexx. All of these files are available

in the :INCLUDE directory,but are listed here for convenience in studying the

structures.

@{b}Contents@{ub}

@{"THE :C DIRECTORY" LINK "THE C DIRECTORY"}
@{"THE :INCLUDE DIRECTORY" LINK "THE INCLUDE DIRECTORY"}
@{"THE :LIBS DIRECTIRY" LINK "THE LIBS DIRECTORY"}

@ENDNODE

@NODE "DIRECTORIES" "DIRECTORIES"
@TOC "APPENDIX E"
@{b}DIRECTORIES@{ub}



The files are listed below as they would be using the system @{b}dir@{ub} command. For

example,"@{i}dir df1:c opt a@{ui}" would list the contents of the :c directory on disk

drive 1.

@ENDNODE
@NODE "THE C DIRECTORY" "THE :C DIRECTORY"
@TOC "APPENDIX E"
@{b}THE :C DIRECTORY@{ub}



This directory contains the command utilities used with ARexx. These files

should be copied to your system C: directory when you install the program.



                c(dir)

                hi                      loadlib

                rexxmast                rx

                rxc                     rxset

                tcc                     tco

                te                      ts


@ENDNODE
@NODE "THE INCLUDE DIRECTORY" "THE :INCLUDE DIRECTORY"
@TOC "APPENDIX E"
@{b}THE :INCLUDE DIRECTORY@{ub}



This directory has the INCLUDE and HEADER files used for assembly language and

"C" programming,respectively. These files contain the structure definitions

necessary to build an interface to ARexx.



                include(dir)

                errors.h                rexxio.h

                rxslib.h                storage.h

                errors.i                rexxio.i

                rxslib.i                storage.i
@ENDNODE

@NODE "THE LIBS DIRECTORY" "THE :LIBS DIRECTORY"
@TOC "APPENDIX E"
@{b}THE :LIBS DIRECTORY@{ub}



These are the library files for the language interpreter and the Support

Library functions. Both files should be copied to your system LIBS:directory

when you install ARexx.



                libs(dir)

                rexxsupport.library     rexxsyslib.library

@ENDNODE

@NODE "CREDITS" "Credits"
@{b}Credits@{ub}

  This rather long but comprehensive Tutorial by: South West Amiga Group 1991

  AmigaGuide® Version By E.F.Pritchard efp90@dircon.co.uk  27-Mar-1993.

@ENDNODE

@NODE "ALPHABETICAL INDEX" "Alphabetical Index"
@{b}Alphabetical Index@{ub}

@{"ABBREV()" LINK "ABBREV()"}
@{"ABS()" LINK "ABS()"}
@{"AddClipNode()" LINK "AddClipNode()"}
@{"Addition" LINK "ADDITION"}
@{"ADDLIB()" LINK "ADDLIB()"}
@{"ADDRESS" LINK "ADDRESS"}
@{"ADDRESS()" LINK "ADDRESS()"}
@{"AddRsrcNode()" LINK "AddRsrcNode()"}
@{"ALLOCMEM()" LINK "ALLOCMEM()"}
@{"Alphabetical Index" LINK "ALPHABETICAL INDEX"}
@{"Appendix A" LINK "APPENDIX A"}
@{"Appendix B" LINK "APPENDIX B"}
@{"Appendix C" LINK "APPENDIX C"}
@{"Appendix D" LINK "APPENDIX D"}
@{"Appendix E" LINK "APPENDIX E"}
@{"AREXX and Workbench" LINK "AREXX AND WORKBENCH"}
@{"AREXX on the Amiga" LINK "AREXX ON THE AMIGA"}
@{"ARexx Systems Library Functions" LINK "AREXX SYSTEMS LIBRARY FUNCTIONS"}
@{"ARG" LINK "ARG"}
@{"ARG()" LINK "ARG()"}
@{"Argument Strings" LINK "ARGUMENT STRINGS"}
@{"Arithmetic Operators" LINK "ARITHMETIC OPERATORS"}
@{"Assignment Clauses" LINK "ASSIGNMENT CLAUSES"}
@{"B2C()" LINK "B2C()"}
@{"Basic Structures" LINK "BASIC STRUCTURES"}
@{"BITAND()" LINK "BITAND()"}
@{"BITCHG()" LINK "BITCHG()"}
@{"BITCLR()" LINK "BITCLR()"}
@{"BITCOMP()" LINK "BITCOMP()"}
@{"BITOR()" LINK "BITOR()"}
@{"BITSET()" LINK "BITSET()"}
@{"BITTST()" LINK "BITTST()"}
@{"BITXOR()" LINK "BITXOR()"}
@{"Boolean Values" LINK "BOOLEAN VALUES"}
@{"BREAK" LINK "BREAK"}
@{"Built-In Functions" LINK "BUILT-IN FUNCTION LIBRARY INDEX"}
@{"Built-In Functions" LINK "BUILT-IN FUNCTIONS"}
@{"C2B()" LINK "C2B()"}
@{"C2D()" LINK "C2D()"}
@{"C2X()" LINK "C2X()"}
@{"CALL" LINK "CALL"}
@{"Calling Convention" LINK "CALLING CONVENTION"}
@{"CENTER() or CENTRE()" LINK "CENTER()"}
@{"Chapter 1" LINK "CHAPTER 1"}
@{"Chapter 10" LINK "CHAPTER 10"}
@{"Chapter 2" LINK "CHAPTER 2"}
@{"Chapter 3" LINK "CHAPTER 3"}
@{"Chapter 4" LINK "CHAPTER 4"}
@{"Chapter 5" LINK "CHAPTER 5"}
@{"Chapter 6" LINK "CHAPTER 6"}
@{"Chapter 7" LINK "CHAPTER 7"}
@{"Chapter 8" LINK "CHAPTER 8"}
@{"Chapter 9" LINK "CHAPTER 9"}
@{"Clause Classification" LINK "CLAUSE CLASSIFICATION"}
@{"Clause Continuation" LINK "CLAUSE CONTINUATION"}
@{"Clauses" LINK "CLAUSES"}
@{"ClearMem()" LINK "ClearMem()"}
@{"ClearRexxMsg()" LINK "ClearRexxMsg()"}
@{"CLOSE()" LINK "CLOSE()"}
@{"CloseF()" LINK "CloseF()"}
@{"CLOSEPORT()" LINK "CLOSEPORT()"}
@{"ClosePublicPort()" LINK "ClosePublicPort()"}
@{"CmpString()" LINK "CmpString()"}
@{"Command Clauses" LINK "5.COMMAND CLAUSES"}
@{"Command Clauses" LINK "COMMAND CLAUSES"}
@{"Command Inhibition" LINK "7.COMMAND INHIBITION"}
@{"Command Inhibition" LINK "COMMAND INHIBITION"}
@{"Command Invocations" LINK "COMMAND INVOCATIONS"}
@{"Command Utilities" LINK "COMMAND UTILITIES"}
@{"Command(Action)Codes" LINK "COMMAND(ACTION)CODES"}
@{"Comment Tokens" LINK "COMMENT TOKENS"}
@{"Communicating with the Resident Process" LINK "COMMUNICATING WITH THE RESIDENT PROCESS"}
@{"COMPARE()" LINK "COMPARE()"}
@{"Comparison Operators" LINK "COMPARISON OPERATORS"}
@{"Compatibility" LINK "COMPATIBILITY"}
@{"COMPRESS()" LINK "COMPRESS()"}
@{"Concatenation Operators" LINK "CONCATENATION OPERATORS"}
@{"Contents" LINK "Main"}
@{"COPIES()" LINK "COPIES()"}
@{"CreateArgstring()" LINK "CreateArgstring()"}
@{"CreateDOSPkt()" LINK "CreateDOSPkt()"}
@{"CreateRexxMsg()" LINK "CreateRexxMsg()"}
@{"Credits" LINK "CREDITS"}
@{"CurrentEnv()" LINK "CurrentEnv()"}
@{"CVa2i()" LINK "CVa2i()"}
@{"CVc2x()" LINK "CVc2x()"}
@{"CVi2arg()" LINK "CVi2arg()"}
@{"CVi2az()" LINK "CVi2az()"}
@{"CVs2i()" LINK "CVs2i()"}
@{"CVx2c()" LINK "CVx2c()"}
@{"D2C()" LINK "D2C()"}
@{"DATATYPE()" LINK "DATATYPE()"}
@{"DeleteArgstring()" LINK "DeleteArgstring()"}
@{"DeleteDOSPkt()" LINK "DeleteDOSPkt()"}
@{"DeleteRexxMsg()" LINK "DeleteRexxMsg()"}
@{"DELSTR()" LINK "DELSTR()"}
@{"DELWORD()" LINK "DELWORD()"}
@{"Designing a Command Interface" LINK "DESIGNING A COMMAND INTERFACE"}
@{"Direct Manipulation of Data Structures" LINK "DIRECT MANIPULATION OF DATA STRUCTURES"}
@{"DIRECTORIES" LINK "DIRECTORIES"}
@{"Display Formatting" LINK "DISPLAY FORMATTING"}
@{"Division" LINK "DIVISION"}
@{"DO" LINK "DO"}
@{"DOSRead()" LINK "DOSRead()"}
@{"DOSWrite()" LINK "DOSWrite()"}
@{"DROP" LINK "DROP"}
@{"ECHO" LINK "ECHO"}
@{"ELSE" LINK "ELSE"}
@{"END" LINK "END"}
@{"EOF()" LINK "EOF()"}
@{"Error Processing" LINK "ERROR PROCESSING"}
@{"ErrorMsg()" LINK "ErrorMsg()"}
@{"ERRORTEXT()" LINK "ERRORTEXT()"}
@{"ExistF()" LINK "ExistF()"}
@{"EXISTS()" LINK "EXISTS()"}
@{"EXIT" LINK "EXIT"}
@{"Exponentiation" LINK "EXPONENTIATION"}
@{"EXPORT()" LINK "EXPORT()"}
@{"Expressions" LINK "EXPRESSIONS"}
@{"Extension Fields" LINK "EXTENSION FIELDS"}
@{"Extensions" LINK "EXTENSIONS"}
@{"External Function Libraries" LINK "EXTERNAL FUNCTION LIBRARIES"}
@{"External Function Libraries (¶ 10)" LINK "10.EXTERNAL FUNCTION LIBRARIES"}
@{"FillRexxMsg()" LINK "FillRexxMsg()"}
@{"FindDevice()" LINK "FindDevice()"}
@{"FindRsrcNode()" LINK "FindRsrcNode()"}
@{"Format" LINK "FORMAT"}
@{"FREEMEM()" LINK "FREEMEM()"}
@{"FreePort()" LINK "FreePort()"}
@{"FREESPACE() (Built-In Function)" LINK "FREESPACE()"}
@{"FreeSpace() (System Library)" LINK "FreeSpace()Sys"}
@{"Full Contents" LINK "FULL CONTENTS"}
@{"Function Groups" LINK "FUNCTION GROUPS"}
@{"Function Hosts" LINK "FUNCTION HOSTS"}
@{"Function Hosts (¶ 9)" LINK "9.FUNCTION HOSTS"}
@{"Function Invocations" LINK "FUNCTION INVOCATIONS"}
@{"Function Libraries" LINK "FUNCTION LIBRARIES"}
@{"Future Developments" LINK "FUTURE DIRECTIONS"}
@{"GETARG()" LINK "GETARG()"}
@{"GETCLIP()" LINK "GETCLIP()"}
@{"GETPKT()" LINK "GETPKT()"}
@{"GETSPACE() (Built-In Function)" LINK "GETSPACE()"}
@{"GetSpace() (System Library)" LINK "GetSpace()Sys"}
@{"HASH()" LINK "HASH()"}
@{"HI" LINK "HI"}
@{"IF" LINK "IF"}
@{"IMPORT()" LINK "IMPORT()"}
@{"INDEX()" LINK "INDEX()"}
@{"InitList()" LINK "InitList()"}
@{"InitPort()" LINK "InitPort()"}
@{"Input and Output Streams" LINK "INPUT AND OUTPUT STREAMS"}
@{"Input and Output" LINK "INPUT AND OUTPUT"}
@{"INSERT()" LINK "INSERT()"}
@{"Installation" LINK "INSTALLATION"}
@{"Installing AREXX" LINK "INSTALLING AREXX"}
@{"Instruction Clauses" LINK "INSTRUCTION CLAUSES"}
@{"Integer Division" LINK "INTEGER DIVISION"}
@{"Interactive Tracing" LINK "INTERACTIVE TRACING"}
@{"Internal Functions" LINK "INTERNAL FUNCTIONS"}
@{"INTERPRET" LINK "INTERPRET"}
@{"Interpreting the Result Fields" LINK "INTERPRETING THE RESULT FIELDS"}
@{"Interrupts" LINK "INTERRUPTS"}
@{"Introduction To Arexx" LINK "INTRODUCTION"}
@{"Invoking ARexx Programs" LINK "INVOKING AREXX PROGRAMS"}
@{"IsRexxMsg()" LINK "IsRexxMsg()"}
@{"IsSymbol()" LINK "IsSymbol()"}
@{"ITERATE" LINK "ITERATE"}
@{"Label Clauses" LINK "LABEL CLAUSES"}
@{"Language Features" LINK "LANGUAGE FEATURES"}
@{"LASTPOS()" LINK "LASTPOS()"}
@{"LEAVE" LINK "LEAVE"}
@{"LEFT()" LINK "LEFT()"}
@{"LENGTH()" LINK "LENGTH()"}
@{"Library Function Docs" LINK "LIBRARY FUNCTION DOCS"}
@{"Limits" LINK "LIMITS"}
@{"ListNames()" LINK "ListNames()"}
@{"LockRexxBase()" LINK "LockRexxBase()"}
@{"Logical (boolean) Operators" LINK "LOGICAL (BOOLEAN) OPERATORS"}
@{"MAX()" LINK "MAX()"}
@{"Message Packets" LINK "MESSAGE PACKETS"}
@{"MIN()" LINK "MIN()"}
@{"Modifier Flags" LINK "MODIFIER FLAGS"}
@{"Multiple Clauses" LINK "MULTIPLE CLAUSES"}
@{"Multiple Host Processes" LINK "MULTIPLE HOST PROCESSES"}
@{"Multiple Templates" LINK "MULTIPLE TEMPLATES"}
@{"Multiplication" LINK "MULTIPLICATION"}
@{"Naming Conventions" LINK "NAMING CONVENTIONS"}
@{"NOP" LINK "NOP"}
@{"Null Clauses" LINK "NULL CLAUSES"}
@{"Numbers and Numeric Precision" LINK "NUMBERS AND NUMERIC PRECISION"}
@{"Numeric Precision" LINK "NUMERIC PRECISION"}
@{"NUMERIC" LINK "NUMERIC"}
@{"Omissions" LINK "OMISSIONS"}
@{"OPEN()" LINK "OPEN()"}
@{"OpenF()" LINK "OpenF()"}
@{"OPENPORT()" LINK "OPENPORT()"}
@{"OpenPublicPort()" LINK "OpenPublicPort()"}
@{"Operator Sequences" LINK "OPERATOR SEQUENCES"}
@{"Operators" LINK "OPERATORS"}
@{"Operators 2" LINK "OPERATORS2"}
@{"OPTIONS" LINK "OPTIONS"}
@{"Order of Evaluation" LINK "ORDER OF EVALUATION"}
@{"OTHERWISE" LINK "OTHERWISE"}
@{"OVERLAY()" LINK "OVERLAY()"}
@{"Parameter Conversion" LINK "PARAMETER CONVERSION"}
@{"PARSE" LINK "PARSE"}
@{"Parsing by Tokenization" LINK "PARSING BY TOKENIZATION"}
@{"PATTERN PARSING" LINK "PATTERN PARSING"}
@{"POS()" LINK "POS()"}
@{"POSITIONAL MARKERS" LINK "POSITIONAL MARKERS"}
@{"PRAGMA()" LINK "PRAGMA()"}
@{"Prefix Conversion" LINK "PREFIX CONVERSION"}
@{"Prefix Negation" LINK "PREFIX NEGATION"}
@{"PROCEDURE" LINK "PROCEDURE"}
@{"Program Examples" LINK "PROGRAM EXAMPLES"}
@{"PULL" LINK "PULL"}
@{"PUSH" LINK "PUSH"}
@{"QUEUE" LINK "QUEUE"}
@{"QueueF()" LINK "QueueF()"}
@{"RANDOM()" LINK "RANDOM()"}
@{"RANDU()" LINK "RANDU()"}
@{"READCH()" LINK "READCH()"}
@{"ReadF()" LINK "ReadF()"}
@{"READLN()" LINK "READLN()"}
@{"ReadStr()" LINK "ReadStr()"}
@{"Receiving Command Messages" LINK "RECEIVING COMMAND MESSAGES"}
@{"Remainder" LINK "REMAINDER"}
@{"RemClipNode()" LINK "RemClipNode()"}
@{"REMLIB()" LINK "REMLIB()"}
@{"RemRsrcList()" LINK "RemRsrcList()"}
@{"RemRsrcNode()" LINK "RemRsrcNode()"}
@{"REPLY()" LINK "REPLY()"}
@{"Resource Management" LINK "RESOURCE MANAGEMENT"}
@{"Resource Tracking" LINK "RESOURCE TRACKING"}
@{"Result Fields" LINK "RESULT FIELDS"}
@{"Result Fields (¶ 10)" LINK "10.RESULT FIELDS"}
@{"RETURN" LINK "RETURN"}
@{"Returned Values" LINK "RETURNED VALUES"}
@{"REVERSE()" LINK "REVERSE()"}
@{"RIGHT()" LINK "RIGHT()"}
@{"RX" LINK "RX"}
@{"RXADDCON" LINK "RXADDCON"}
@{"RXADDFH" LINK "RXADDFH"}
@{"RXADDLIB" LINK "RXADDLIB"}
@{"RXC" LINK "RXC"}
@{"RXCOMM" LINK "RXCOMM"}
@{"RXFUNC" LINK "RXFUNC"}
@{"RXREMCON" LINK "RXREMCON"}
@{"RXREMLIB" LINK "RXREMLIB"}
@{"RXSET" LINK "RXSET"}
@{"RXTCCLS" LINK "RXTCCLS"}
@{"RXTCOPN" LINK "RXTCOPN"}
@{"SAY" LINK "SAY"}
@{"Search Order" LINK "10.SEARCH ORDER"}
@{"Search Order" LINK "SEARCH ORDER"}
@{"SEEK()" LINK "SEEK()"}
@{"SeekF()" LINK "SeekF()"}
@{"SELECT" LINK "SELECT"}
@{"SETCLIP()" LINK "SETCLIP()"}
@{"SHELL" LINK "SHELL"}
@{"SHOW()" LINK "SHOW()"}
@{"SHOWDIR()" LINK "SHOWDIR()"}
@{"SHOWLIST()" LINK "SHOWLIST()"}
@{"SIGN()" LINK "SIGN()"}
@{"SIGNAL" LINK "SIGNAL"}
@{"SPACE()" LINK "SPACE()"}
@{"Special Character Tokens" LINK "SPECIAL CHARACTER TOKENS"}
@{"StackF()" LINK "StackF()"}
@{"Starting the Resident Process" LINK "STARTING THE RESIDENT PROCESS"}
@{"STATEF()" LINK "STATEF()"}
@{"StcToken()" LINK "StcToken()"}
@{"Stems and Compound Symbols" LINK "STEMS AND COMPOUND SYMBOLS"}
@{"STORAGE()" LINK "STORAGE()"}
@{"StrcmpN()" LINK "StrcmpN()"}
@{"StrcpyA()" LINK "StrcpyA()"}
@{"StrcpyN()" LINK "StrcpyN()"}
@{"StrcpyU()" LINK "StrcpyU()"}
@{"StrflipN()" LINK "StrflipN()"}
@{"String Tokens" LINK "STRING TOKENS"}
@{"STRIP()" LINK "STRIP()"}
@{"Strlen()" LINK "Strlen()"}
@{"SUBSTR()" LINK "SUBSTR()"}
@{"Subtraction" LINK "SUBTRACTION"}
@{"SUBWORD()" LINK "SUBWORD()"}
@{"Symbol Resolution" LINK "SYMBOL RESOLUTION"}
@{"Symbol Tokens" LINK "SYMBOL TOKENS"}
@{"SYMBOL()" LINK "SYMBOL()"}
@{"Syntax and Search Order" LINK "SYNTAX AND SEARCH ORDER"}
@{"TCC" LINK "TCC"}
@{"TCO" LINK "TCO"}
@{"TE" LINK "TE"}
@{"Template Objects" LINK "TEMPLATE OBJECTS"}
@{"Template Structure" LINK "TEMPLATE STRUCTURE"}
@{"TEMPLATES IN ACTION" LINK "TEMPLATES IN ACTION"}
@{"THE :C DIRECTORY" LINK "THE C DIRECTORY"}
@{"THE :INCLUDE DIRECTORY" LINK "THE INCLUDE DIRECTORY"}
@{"THE :LIBS DIRECTORY" LINK "THE LIBS DIRECTORY"}
@{"The Built-In Function Library" LINK "THE BUILT-IN FUNCTION LIBRARY"}
@{"The Clip List" LINK "THE CLIP LIST"}
@{"The Command Interface" LINK "THE COMMAND INTERFACE"}
@{"The Execution Environment" LINK "THE EXECUTION ENVIRONMENT"}
@{"The External Environment" LINK "THE EXTERNAL ENVIRONMENT"}
@{"The External Tracing Flag" LINK "THE EXTERNAL TRACING FLAG"}
@{"The Global Tracing Console" LINK "THE GLOBAL TRACING CONSOLE"}
@{"The Host Address" LINK "THE HOST ADDRESS"}
@{"The Internal Environment" LINK "THE INTERNAL ENVIRONMENT"}
@{"The Library List" LINK "THE LIBRARY LIST"}
@{"The REXX: Directory" LINK "THE REXX DIRECTORY"}
@{"The RexxMsg Structure" LINK "TABLE 10.2"}
@{"The Scanning Process" LINK "THE SCANNING PROCESS"}
@{"The Symbol Table" LINK "THE SYMBOL TABLE"}
@{"THEN" LINK "THEN"}
@{"TIME()" LINK "TIME()"}
@{"Tokens" LINK "TOKENS"}
@{"ToUpper()" LINK "ToUpper()"}
@{"TRACE" LINK "TRACE"}
@{"TRACE()" LINK "TRACE()"}
@{"Tracing Options" LINK "TRACING OPTIONS"}
@{"Tracing Output" LINK "TRACING OUTPUT"}
@{"TRANSLATE()" LINK "TRANSLATE()"}
@{"TRIM()" LINK "TRIM()"}
@{"TS" LINK "TS"}
@{"Typographic Conventions" LINK "TYPOGRAPHIC CONVENTIONS"}
@{"UnlockRexxBase()" LINK "UnlockRexxBase()"}
@{"UPPER" LINK "UPPER"}
@{"UPPER()" LINK "UPPER()"}
@{"Using ARexx with Command Shells" LINK "USING AREXX WITH COMMAND SHELLS"}
@{"Using Commands in Macro Programs" LINK "USING COMMANDS IN MACRO PROGRAMS"}
@{"VALUE()" LINK "VALUE()"}
@{"VERIFY()" LINK "VERIFY()"}
@{"WAITPKT()" LINK "WAITPKT()"}
@{"WHEN" LINK "WHEN"}
@{"WORD()" LINK "WORD()"}
@{"WORDINDEX()" LINK "WORDINDEX()"}
@{"WORDLENGTH()" LINK "WORDLENGTH()"}
@{"WORDS()" LINK "WORDS()"}
@{"WRITECH()" LINK "WRITECH()"}
@{"WriteF()" LINK "WriteF()"}
@{"WRITELN()" LINK "WRITELN()"}
@{"X2C()" LINK "X2C()"}
@{"XRANGE()" LINK "XRANGE()"}


@ENDNODE

@NODE "FULL CONTENTS" "Full Contents"
@{b}Full Contents@{ub}

@{"Contents" LINK "Main"}
@{"Introduction To Arexx" LINK "INTRODUCTION"}

@{"Chapter 1" LINK "CHAPTER 1"}
 @{"Typographic Conventions" LINK "TYPOGRAPHIC CONVENTIONS"}
 @{"Future Developments" LINK "FUTURE DIRECTIONS"}
 @{"Language Features" LINK "LANGUAGE FEATURES"}
 @{"AREXX on the Amiga" LINK "AREXX ON THE AMIGA"}
 @{"Chapter 2" LINK "CHAPTER 2"}
 @{"Installing AREXX" LINK "INSTALLING AREXX"}
 @{"AREXX and Workbench" LINK "AREXX AND WORKBENCH"}
 @{"Installation" LINK "INSTALLATION"}
 @{"Starting the Resident Process" LINK "STARTING THE RESIDENT PROCESS"}
 @{"Naming Conventions" LINK "NAMING CONVENTIONS"}
 @{"The REXX: Directory" LINK "THE REXX DIRECTORY"}
 @{"Program Examples" LINK "PROGRAM EXAMPLES"}

@{"Chapter 3" LINK "CHAPTER 3"}
 @{"Format" LINK "FORMAT"}
 @{"Tokens" LINK "TOKENS"}
 @{"Comment Tokens" LINK "COMMENT TOKENS"}
 @{"Symbol Tokens" LINK "SYMBOL TOKENS"}
 @{"String Tokens" LINK "STRING TOKENS"}
 @{"Operators" LINK "OPERATORS"}
 @{"Operator Sequences" LINK "OPERATOR SEQUENCES"}
 @{"Special Character Tokens" LINK "SPECIAL CHARACTER TOKENS"}
 @{"Clauses" LINK "CLAUSES"}
  @{"Clause Continuation" LINK "CLAUSE CONTINUATION"}
  @{"Multiple Clauses" LINK "MULTIPLE CLAUSES"}
  @{"Null Clauses" LINK "NULL CLAUSES"}
  @{"Label Clauses" LINK "LABEL CLAUSES"}
  @{"Assignment Clauses" LINK "ASSIGNMENT CLAUSES"}
  @{"Instruction Clauses" LINK "INSTRUCTION CLAUSES"}
  @{"Command Clauses" LINK "COMMAND CLAUSES"}
  @{"Clause Classification" LINK "CLAUSE CLASSIFICATION"}
 @{"Expressions" LINK "EXPRESSIONS"}
 @{"Symbol Resolution" LINK "SYMBOL RESOLUTION"}
 @{"Order of Evaluation" LINK "ORDER OF EVALUATION"}
 @{"Numbers and Numeric Precision" LINK "NUMBERS AND NUMERIC PRECISION"}
 @{"Boolean Values" LINK "BOOLEAN VALUES"}
 @{"Numeric Precision" LINK "NUMERIC PRECISION"}
 @{"Operators" LINK "OPERATORS2"}
  @{"Arithmetic Operators" LINK "ARITHMETIC OPERATORS"}
   @{"Prefix Conversion" LINK "PREFIX CONVERSION"}
   @{"Prefix Negation" LINK "PREFIX NEGATION"}
   @{"Exponentiation" LINK "EXPONENTIATION"}
   @{"Multiplication" LINK "MULTIPLICATION"}
   @{"Division" LINK "DIVISION"}
   @{"Integer Division" LINK "INTEGER DIVISION"}
   @{"Remainder" LINK "REMAINDER"}
   @{"Addition" LINK "ADDITION"}
   @{"Subtraction" LINK "SUBTRACTION"}
  @{"Concatenation Operators" LINK "CONCATENATION OPERATORS"}
  @{"Comparison Operators" LINK "COMPARISON OPERATORS"}
  @{"Logical (boolean) Operators" LINK "LOGICAL (BOOLEAN) OPERATORS"}
 @{"Stems and Compound Symbols" LINK "STEMS AND COMPOUND SYMBOLS"}
 @{"The Execution Environment" LINK "THE EXECUTION ENVIRONMENT"}
  @{"The External Environment" LINK "THE EXTERNAL ENVIRONMENT"}
  @{"The Internal Environment" LINK "THE INTERNAL ENVIRONMENT"}
 @{"Argument Strings" LINK "ARGUMENT STRINGS"}
 @{"The Symbol Table" LINK "THE SYMBOL TABLE"}
 @{"Input and Output" LINK "INPUT AND OUTPUT"}
 @{"Resource Tracking" LINK "RESOURCE TRACKING"}

@{"Chapter 4" LINK "CHAPTER 4"}
 @{"ADDRESS" LINK "ADDRESS"}
 @{"ARG" LINK "ARG"}
 @{"BREAK" LINK "BREAK"}
 @{"CALL" LINK "CALL"}
 @{"DO" LINK "DO"}
 @{"DROP" LINK "DROP"}
 @{"ECHO" LINK "ECHO"}
 @{"ELSE" LINK "ELSE"}
 @{"END" LINK "END"}
 @{"EXIT" LINK "EXIT"}
 @{"IF" LINK "IF"}
 @{"INTERPRET" LINK "INTERPRET"}
 @{"ITERATE" LINK "ITERATE"}
 @{"LEAVE" LINK "LEAVE"}
 @{"NOP" LINK "NOP"}
 @{"NUMERIC" LINK "NUMERIC"}
 @{"OPTIONS" LINK "OPTIONS"}
 @{"OTHERWISE" LINK "OTHERWISE"}
 @{"PARSE" LINK "PARSE"}
 @{"PROCEDURE" LINK "PROCEDURE"}
 @{"PULL" LINK "PULL"}
 @{"PUSH" LINK "PUSH"}
 @{"QUEUE" LINK "QUEUE"}
 @{"RETURN" LINK "RETURN"}
 @{"SAY" LINK "SAY"}
 @{"SELECT" LINK "SELECT"}
 @{"SHELL" LINK "SHELL"}
 @{"SIGNAL" LINK "SIGNAL"}
 @{"THEN" LINK "THEN"}
 @{"TRACE" LINK "TRACE"}
 @{"UPPER" LINK "UPPER"}
 @{"WHEN" LINK "WHEN"}

@{"Chapter 5" LINK "CHAPTER 5"}
 @{"Command Clauses" LINK "5.COMMAND CLAUSES"}
 @{"The Host Address" LINK "THE HOST ADDRESS"}
 @{"The Command Interface" LINK "THE COMMAND INTERFACE"}
 @{"Using Commands in Macro Programs" LINK "USING COMMANDS IN MACRO PROGRAMS"}
 @{"Using ARexx with Command Shells" LINK "USING AREXX WITH COMMAND SHELLS"}
 @{"Command Inhibition" LINK "COMMAND INHIBITION"}

@{"Chapter 6" LINK "CHAPTER 6"}
 @{"Syntax and Search Order" LINK "SYNTAX AND SEARCH ORDER"}
  @{"Search Order" LINK "SEARCH ORDER"}
 @{"Internal Functions" LINK "INTERNAL FUNCTIONS"}
 @{"Built-In Functions" LINK "BUILT-IN FUNCTIONS"}
 @{"External Function Libraries" LINK "EXTERNAL FUNCTION LIBRARIES"}
 @{"Function Hosts" LINK "FUNCTION HOSTS"}
 @{"The Built-In Function Library" LINK "THE BUILT-IN FUNCTION LIBRARY"}
  @{"Built-In Functions Index" LINK "BUILT-IN FUNCTION LIBRARY INDEX"}
   @{"ABBREV()" LINK "ABBREV()"}
   @{"ABS()" LINK "ABS()"}
   @{"ADDLIB()" LINK "ADDLIB()"}
   @{"ADDRESS()" LINK "ADDRESS()"}
   @{"ARG()" LINK "ARG()"}
   @{"B2C()" LINK "B2C()"}
   @{"BITAND()" LINK "BITAND()"}
   @{"BITCHG()" LINK "BITCHG()"}
   @{"BITCLR()" LINK "BITCLR()"}
   @{"BITCOMP()" LINK "BITCOMP()"}
   @{"BITOR()" LINK "BITOR()"}
   @{"BITSET()" LINK "BITSET()"}
   @{"BITTST()" LINK "BITTST()"}
   @{"BITXOR()" LINK "BITXOR()"}
   @{"C2B()" LINK "C2B()"}
   @{"C2D()" LINK "C2D()"}
   @{"C2X()" LINK "C2X()"}
   @{"CENTER() or CENTRE()" LINK "CENTER()"}
   @{"CLOSE()" LINK "CLOSE()"}
   @{"COMPRESS()" LINK "COMPRESS()"}
   @{"COMPARE()" LINK "COMPARE()"}
   @{"COPIES()" LINK "COPIES()"}
   @{"D2C()" LINK "D2C()"}
   @{"DATATYPE()" LINK "DATATYPE()"}
   @{"DELSTR()" LINK "DELSTR()"}
   @{"DELWORD()" LINK "DELWORD()"}
   @{"EOF()" LINK "EOF()"}
   @{"ERRORTEXT()" LINK "ERRORTEXT()"}
   @{"EXISTS()" LINK "EXISTS()"}
   @{"EXPORT()" LINK "EXPORT()"}
   @{"FREESPACE()" LINK "FREESPACE()"}
   @{"GETCLIP()" LINK "GETCLIP()"}
   @{"GETSPACE()" LINK "GETSPACE()"}
   @{"HASH()" LINK "HASH()"}
   @{"IMPORT()" LINK "IMPORT()"}
   @{"INDEX()" LINK "INDEX()"}
   @{"INSERT()" LINK "INSERT()"}
   @{"LASTPOS()" LINK "LASTPOS()"}
   @{"LEFT()" LINK "LEFT()"}
   @{"LENGTH()" LINK "LENGTH()"}
   @{"MAX()" LINK "MAX()"}
   @{"MIN()" LINK "MIN()"}
   @{"OPEN()" LINK "OPEN()"}
   @{"OVERLAY()" LINK "OVERLAY()"}
   @{"POS()" LINK "POS()"}
   @{"PRAGMA()" LINK "PRAGMA()"}
   @{"RANDOM()" LINK "RANDOM()"}
   @{"RANDU()" LINK "RANDU()"}
   @{"READCH()" LINK "READCH()"}
   @{"READLN()" LINK "READLN()"}
   @{"REMLIB()" LINK "REMLIB()"}
   @{"REVERSE()" LINK "REVERSE()"}
   @{"RIGHT()" LINK "RIGHT()"}
   @{"SEEK()" LINK "SEEK()"}
   @{"SETCLIP()" LINK "SETCLIP()"}
   @{"SHOW()" LINK "SHOW()"}
   @{"SIGN()" LINK "SIGN()"}
   @{"SPACE()" LINK "SPACE()"}
   @{"STORAGE()" LINK "STORAGE()"}
   @{"STRIP()" LINK "STRIP()"}
   @{"SUBSTR()" LINK "SUBSTR()"}
   @{"SUBWORD()" LINK "SUBWORD()"}
   @{"SYMBOL()" LINK "SYMBOL()"}
   @{"TIME()" LINK "TIME()"}
   @{"TRACE()" LINK "TRACE()"}
   @{"TRANSLATE()" LINK "TRANSLATE()"}
   @{"TRIM()" LINK "TRIM()"}
   @{"UPPER()" LINK "UPPER()"}
   @{"VALUE()" LINK "VALUE()"}
   @{"VERIFY()" LINK "VERIFY()"}
   @{"WORD()" LINK "WORD()"}
   @{"WORDINDEX()" LINK "WORDINDEX()"}
   @{"WORDLENGTH()" LINK "WORDLENGTH()"}
   @{"WORDS()" LINK "WORDS()"}
   @{"WRITECH()" LINK "WRITECH()"}
   @{"WRITELN()" LINK "WRITELN()"}
   @{"X2C()" LINK "X2C()"}
   @{"XRANGE()" LINK "XRANGE()"}

@{"Chapter 7" LINK "CHAPTER 7"}
 @{"Tracing Options" LINK "TRACING OPTIONS"}
  @{"Display Formatting" LINK "DISPLAY FORMATTING"}
  @{"Tracing Output" LINK "TRACING OUTPUT"}
  @{"Command Inhibition" LINK "7.COMMAND INHIBITION"}
  @{"Interactive Tracing" LINK "INTERACTIVE TRACING"}
 @{"Error Processing" LINK "ERROR PROCESSING"}
  @{"The External Tracing Flag" LINK "THE EXTERNAL TRACING FLAG"}
  @{"Interrupts" LINK "INTERRUPTS"}

@{"Chapter 8" LINK "CHAPTER 8"}
 @{"Template Structure" LINK "TEMPLATE STRUCTURE"}
  @{"Template Objects" LINK "TEMPLATE OBJECTS"}
  @{"The Scanning Process" LINK "THE SCANNING PROCESS"}
  @{"Templates IN Action" LINK "TEMPLATES IN ACTION"}
  @{"Parsing by Tokenization" LINK "PARSING BY TOKENIZATION"}
  @{"Pattern Parsing" LINK "PATTERN PARSING"}
  @{"Positional Markers" LINK "POSITIONAL MARKERS"}
  @{"Multiple Templates" LINK "MULTIPLE TEMPLATES"}

 @{"Chapter 9" LINK "CHAPTER 9"}
  @{"Command Utilities" LINK "COMMAND UTILITIES"}
   @{"HI" LINK "HI"}
   @{"RX" LINK "RX"}
   @{"RXSET" LINK "RXSET"}
   @{"RXC" LINK "RXC"}
   @{"TCC" LINK "TCC"}
   @{"TCO" LINK "TCO"}
   @{"TE" LINK "TE"}
   @{"TS" LINK "TS"}
  @{"Resource Management" LINK "RESOURCE MANAGEMENT"}
  @{"The Global Tracing Console" LINK "THE GLOBAL TRACING CONSOLE"}
  @{"The Library List" LINK "THE LIBRARY LIST"}
   @{"Function Libraries" LINK "FUNCTION LIBRARIES"}
  @{"Function Hosts" LINK "9.FUNCTION HOSTS"}
  @{"The Clip List" LINK "THE CLIP LIST"}

@{"Chapter 10" LINK "CHAPTER 10"}
 @{"Basic Structures" LINK "BASIC STRUCTURES"}
  @{"The RexxMsg Structure" LINK "TABLE 10.2"}
  @{"Designing a Command Interface" LINK "DESIGNING A COMMAND INTERFACE"}
  @{"Receiving Command Messages" LINK "RECEIVING COMMAND MESSAGES"}
  @{"Result Fields" LINK "RESULT FIELDS"}
 @{"Multiple Host Processes" LINK "MULTIPLE HOST PROCESSES"}
 @{"Invoking ARexx Programs" LINK "INVOKING AREXX PROGRAMS"}
  @{"Message Packets" LINK "MESSAGE PACKETS"}
  @{"Command Invocations" LINK "COMMAND INVOCATIONS"}
  @{"Function Invocations" LINK "FUNCTION INVOCATIONS"}
  @{"Search Order" LINK "10.SEARCH ORDER"}
 @{"Extension Fields" LINK "EXTENSION FIELDS"}
 @{"Input and Output Streams" LINK "INPUT AND OUTPUT STREAMS"}
 @{"Interpreting the Result Fields" LINK "INTERPRETING THE RESULT FIELDS"}
 @{"Communicating with the Resident Process" LINK "COMMUNICATING WITH THE RESIDENT PROCESS"}
 @{"Command(Action)Codes" LINK "COMMAND(ACTION)CODES"}
  @{"RXADDCON" LINK "RXADDCON"}
  @{"RXADDFH" LINK "RXADDFH"}
  @{"RXADDLIB" LINK "RXADDLIB"}
  @{"RXCOMM" LINK "RXCOMM"}
  @{"RXFUNC" LINK "RXFUNC"}
  @{"RXREMCON" LINK "RXREMCON"}
  @{"RXREMLIB" LINK "RXREMLIB"}
  @{"RXTCCLS" LINK "RXTCCLS"}
  @{"RXTCOPN" LINK "RXTCOPN"}
 @{"Modifier Flags" LINK "MODIFIER FLAGS"}
 @{"Result Fields" LINK "10.RESULT FIELDS"}
 @{"External Function Libraries" LINK "10.EXTERNAL FUNCTION LIBRARIES"}
  @{"Calling Convention" LINK "CALLING CONVENTION"}
  @{"Parameter Conversion" LINK "PARAMETER CONVERSION"}
  @{"Returned Values" LINK "RETURNED VALUES"}
  @{"Direct Manipulation of Data Structures" LINK "DIRECT MANIPULATION OF DATA STRUCTURES"}

@{"Appendix A" LINK "APPENDIX A"}
 @{"1 PROGRAM NOT FOUND" LINK "ERROR 1"}
 @{"2 EXECUTION HALTED" LINK "ERROR 2"}
 @{"3 INSUFFICIENT MEMORY" LINK "ERROR 3"}
 @{"4 INVALID CHARACTER" LINK "ERROR 4"}
 @{"5 UNMATCHED QUOTE" LINK "ERROR 5"}
 @{"6 UNTERMINATED COMMENT" LINK "ERROR 6"}
 @{"7 CLAUSE TOO LONG" LINK "ERROR 7"}
 @{"8 INVALID TOKEN" LINK "ERROR 8"}
 @{"9 SYMBOL OR STRING TOO LONG" LINK "ERROR 9"}
 @{"10 INVALID MESSAGE PACKET" LINK "ERROR 10"}
 @{"11 COMMAND STRING ERROR" LINK "ERROR 11"}
 @{"12 ERROR RETURN FROM FUNCTION" LINK "ERROR 12"}
 @{"13 HOST ENVIRONMENT NOT FOUND" LINK "ERROR 13"}
 @{"14 REQUESTED LIBRARY NOT FOUND" LINK "ERROR 14"}
 @{"15 FUNCTION NOT FOUND" LINK "ERROR 15"}
 @{"16 FUNCTION DID NOT RETURN VALUE" LINK "ERROR 16"}
 @{"17 WRONG NUMBER OF ARGUMENTS" LINK "ERROR 17"}
 @{"18 INVALID ARGUMENT TO FUNCTION" LINK "ERROR 18"}
 @{"19 INVALID PROCEDURE" LINK "ERROR 19"}
 @{"20 UNEXPECTED THEN OR WHEN" LINK "ERROR 20"}
 @{"21 UNEXPECTED ELSE OR OTHERWISE" LINK "ERROR 21"}
 @{"22 UNEXPECTED BREAK,LEAVE,or ITERATE" LINK "ERROR 22"}
 @{"23 INVALID STATEMENT IN SELECT" LINK "ERROR 23"}
 @{"24 MISSING OR MULTIPLE THEN" LINK "ERROR 24"}
 @{"25 MISSING OTHERWISE" LINK "ERROR 25"}
 @{"26 MISSING OR UNEXPECTED END" LINK "ERROR 26"}
 @{"27 SYMBOL MISMATCH" LINK "ERROR 27"}
 @{"28 INVALID DO SYNTAX" LINK "ERROR 28"}
 @{"29 INCOMPLETE IF OR SELECT" LINK "ERROR 29"}
 @{"30 LABEL NOT FOUND" LINK "ERROR 30"}
 @{"31 SYMBOL EXPECTED" LINK "ERROR 31"}
 @{"32 SYMBOL OR STRING EXPECTED" LINK "ERROR 32"}
 @{"33 INVALID KEYWORD" LINK "ERROR 33"}
 @{"34 REQUIRED KEYWORD MISSING" LINK "ERROR 34"}
 @{"35 EXTRANEOUS CHARACTERS" LINK "ERROR 35"}
 @{"36 KEYWORD CONFLICT" LINK "ERROR 36"}
 @{"37 MESSAGE INVALID TEMPLATE" LINK "ERROR 37"}
 @{"38 INVALID TRACE REQUEST" LINK "ERROR 38"}
 @{"39 UNINITIALIZED VARIABLE" LINK "ERROR 39"}
 @{"40 INVALID VARIABLE NAME" LINK "ERROR 40"}
 @{"41 INVALID EXPRESSION" LINK "ERROR 41"}
 @{"42 UNBALANCED PARENTHESE" LINK "ERROR 42"}
 @{"43 NESTING LIMIT EXCEEDED" LINK "ERROR 43"}
 @{"44 INVALID EXPRESSION RESULT" LINK "ERROR 44"}
 @{"45 EXPRESSION REQUIRED" LINK "ERROR 45"}
 @{"46 BOOLEAN VALUE NOT 0 OR 1" LINK "ERROR 46"}
 @{"47 ARITHMETIC CONVERSION ERROR" LINK "ERROR 47"}
 @{"48 INVALID OPERAND" LINK "ERROR 48"}

@{"Appendix B" LINK "APPENDIX B"}
 @{"Limits" LINK "LIMITS"}
 @{"Compatibility" LINK "COMPATIBILITY"}
 @{"Omissions" LINK "OMISSIONS"}
 @{"Extensions" LINK "EXTENSIONS"}

@{"Appendix C" LINK "APPENDIX C"}
 @{"Function Groups" LINK "FUNCTION GROUPS"}
 @{"ARexx Systems Library Functions" LINK "AREXX SYSTEMS LIBRARY FUNCTIONS"}
 @{"Library Function Docs" LINK "LIBRARY FUNCTION DOCS"}
  @{"AddClipNode()" LINK "AddClipNode()"}
  @{"AddRsrcNode()" LINK "AddRsrcNode()"}
  @{"ClearMem()" LINK "ClearMem()"}
  @{"ClearRexxMsg()" LINK "ClearRexxMsg()"}
  @{"CloseF()" LINK "CloseF()"}
  @{"ClosePublicPort()" LINK "ClosePublicPort()"}
  @{"CmpString()" LINK "CmpString()"}
  @{"CreateArgstring()" LINK "CreateArgstring()"}
  @{"CreateDOSPkt()" LINK "CreateDOSPkt()"}
  @{"CreateRexxMsg()" LINK "CreateRexxMsg()"}
  @{"CVa2i()" LINK "CVa2i()"}
  @{"CVc2x()" LINK "CVc2x()"}
  @{"CVi2arg()" LINK "CVi2arg()"}
  @{"CVi2az()" LINK "CVi2az()"}
  @{"CVs2i()" LINK "CVs2i()"}
  @{"CVx2c()" LINK "CVx2c()"}
  @{"CurrentEnv()" LINK "CurrentEnv()"}
  @{"DeleteArgstring()" LINK "DeleteArgstring()"}
  @{"DeleteDOSPkt()" LINK "DeleteDOSPkt()"}
  @{"DeleteRexxMsg()" LINK "DeleteRexxMsg()"}
  @{"DOSRead()" LINK "DOSRead()"}
  @{"DOSWrite()" LINK "DOSWrite()"}
  @{"ErrorMsg()" LINK "ErrorMsg()"}
  @{"ExistF()" LINK "ExistF()"}
  @{"FillRexxMsg()" LINK "FillRexxMsg()"}
  @{"FindDevice()" LINK "FindDevice()"}
  @{"FindRsrcNode()" LINK "FindRsrcNode()"}
  @{"FreePort()" LINK "FreePort()"}
  @{"FreeSpace()" LINK "FreeSpace()Sys"}
  @{"GetSpace()" LINK "GetSpace()Sys"}
  @{"InitList()" LINK "InitList()"}
  @{"InitPort()" LINK "InitPort()"}
  @{"IsRexxMsg()" LINK "IsRexxMsg()"}
  @{"IsSymbol()" LINK "IsSymbol()"}
  @{"ListNames()" LINK "ListNames()"}
  @{"LockRexxBase()" LINK "LockRexxBase()"}
  @{"OpenF()" LINK "OpenF()"}
  @{"OpenPublicPort()" LINK "OpenPublicPort()"}
  @{"QueueF()" LINK "QueueF()"}
  @{"ReadF()" LINK "ReadF()"}
  @{"ReadStr()" LINK "ReadStr()"}
  @{"RemClipNode()" LINK "RemClipNode()"}
  @{"RemRsrcList()" LINK "RemRsrcList()"}
  @{"RemRsrcNode()" LINK "RemRsrcNode()"}
  @{"SeekF()" LINK "SeekF()"}
  @{"StackF()" LINK "StackF()"}
  @{"StcToken()" LINK "StcToken()"}
  @{"StrcpyA()" LINK "StrcpyA()"}
  @{"StrcpyN()" LINK "StrcpyN()"}
  @{"StrcpyU()" LINK "StrcpyU()"}
  @{"StrflipN()" LINK "StrflipN()"}
  @{"Strlen()" LINK "Strlen()"}
  @{"StrcmpN()" LINK "StrcmpN()"}
  @{"ToUpper()" LINK "ToUpper()"}
  @{"UnlockRexxBase()" LINK "UnlockRexxBase()"}
  @{"WriteF()" LINK "WriteF()"}

@{"Appendix D" LINK "APPENDIX D"}
 @{"ALLOCMEM()" LINK "ALLOCMEM()"}
 @{"CLOSEPORT()" LINK "CLOSEPORT()"}
 @{"FREEMEM()" LINK "FREEMEM()"}
 @{"GETARG()" LINK "GETARG()"}
 @{"GETPKT()" LINK "GETPKT()"}
 @{"OPENPORT()" LINK "OPENPORT()"}
 @{"REPLY()" LINK "REPLY()"}
 @{"SHOWDIR()" LINK "SHOWDIR()"}
 @{"SHOWLIST()" LINK "SHOWLIST()"}
 @{"STATEF()" LINK "STATEF()"}
 @{"WAITPKT()" LINK "WAITPKT()"}

@{"Appendix E" LINK "APPENDIX E"}
 @{"DIRECTORIES" LINK "DIRECTORIES"}
  @{"THE :C DIRECTORY" LINK "THE C DIRECTORY"}
  @{"THE :INCLUDE DIRECTORY" LINK "THE INCLUDE DIRECTORY"}
  @{"THE :LIBS DIRECTORY" LINK "THE LIBS DIRECTORY"}

@{"Credits" LINK "CREDITS"}

@{"Alphabetical Index" LINK "ALPHABETICAL INDEX"}

Full Contents

@ENDNODE

