10-6 DIRECT MANIPULATION OF DATA STRUCTURES 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 RexxBase structure links the global data structures for all currently active ARexx programs. This linkage uses the node contained in the message port of the RexxTask 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() and 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. 102 APPENDIX A ERROR MESSAGES 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 SYNTAX interrupt has been previously enabled(using the 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 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. ERROR: 1 SEVERITY: 5 MESSGE: PROGRAM NOT FOUND 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 SYNTAX interrupt. ERROR: 2 SEVERITY: 10 MESSAGE: EXECUTION HALTED A control-C break or an external half request was received and the program terminated. This error will be trapped if the HALT interrupt has been enabled. ERROR: 3 SEVERITY: 20 MESSAGE: INSUFFICIENT MEMORY 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. ERROR: 4 SEVERITY: 10 MESSAGE: INVALID CHARACTER 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. ERROR: 5 SEVERITY: 10 MESSAGE: UNMATCHED QUOTE 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. 103 ERROR: 6 SEVERITY: 10 MESSAGE: UNTERMINATED COMMENT 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. ERROR: 7 SEVERITY: 10 MESSAGE: CLAUSE TOO LONG 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. ERROR: 8 SEVERITY: 10 MESSAGE: INVALID TOKEN 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. ERROR: 9 SEVERITY: 10 MESSAGE: SYMBOL OR STRING TOO LONG 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. ERROR: 10 SEVERITY: 10 MESSAGE: INVALID MESSAGE PACKET 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. ERROR: 11 SEVERITY: 10 MESSAGE: COMMAND STRING ERROR A command string could not be processed. This error is detected by the external interface and cannot be trapped by the SYNTAX interrupt. ERROR: 12 SEVERITY: 10 MESSAGE: ERROR RETURN FROM FUNCTION An external function returned a non-zero error code. Check that the correct parameters were supplied to the function. ERROR: 13 SEVERITY: 10 MESSAGE: HOST ENVIRONMENT NOT FOUND The message port corresponding to a host address string could not be found. Check that the required external host is active. ERROR: 14 SEVERITY: 10 MESSAGE: REQUESTED LIBRARY NOT FOUND An attempt was made to open a function library included in 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. ERROR: 15 SEVERITY: 10 MESSGE: FUNCTION NOT FOUND 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. 104 ERROR: 16 SEVERITY: 10 MESSAGE: FUNCTION DID NOT RETURN VALUE 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 instruction. 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. ERROR: 18 SEVERITY: 10 MESSAGE: INVALID ARGUMENT TO FUNCTION An inappropriate argument was supplied to a function,or a required argument was missing. Check the parameter requirements specified for the function. ERROR: 19 SEVERITY: 10 MESSAGE: INVALID PROCEDURE A 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. ERROR: 20 SEVERITY: 10 MESSAGE: UNEXPECTED THEN OR WHEN A WHEN or THEN instruction was executed outside of a valid context. The WHEN instruction is valid only within a SELECT range,and THEN must be the next instruciton following an IF or WHEN. ERROR: 21 SEVERITY: 10 MESSAGE: UNEXPECTED ELSE OR OTHERWISE An ELSE or OTHERWISE was found outside of a valid context. The OTHERWISE instruction is valid only within a SELECT range. ELSE is valid only following the THEN branch of an IF range. ERROR: 22 SEVERITY: 10 MESSAGE: UNEXPECTED BREAK,LEAVE,or ITERATE The BREAK instruction is valid only within a DO range or inside an INTERPRETed string. The LEAVE and ITERATE instuctions are valid only within an iterative DO range. ERROR: 23 SEVERITY: 10 MESSAGE: INVALID STATEMENT IN SELECT A invalid statement was encountered within a SELECT range. Only WHEN,THEN,and OTHERWISE statements are valid within a SELECT range,except for the conditional statements following THEN or OTHERWISE clauses. ERROR: 24 SEVERITY: 10 MESSAGE: MISSING OR MULTIPLE THEN An expected THEN clause was not found,or another THEN was found after one had already been executed. ERROR: 25 SEVERITY: 10 MESSAGE: MISSING OTHERWISE None of the WHEN clauses in a SELECT succeeded,but no OTHERWISE clause was supplied. ERROR: 26 SEVERITY: 10 MESSAGE: MISSING OR UNEXPECTED END The program source ended before an END was found for a DO or SELECT instruction or an END was encountered outside of a DO or SELECT range. 105 ERROR: 27 SEVERITY: 10 MESSAGE: SYMBOL MISMATCH The symbol specified on an END,ITERATE,or LEAVE instruction did not match the index variable for the associated DO range. Check that the active loops have been nested properly. ERROR: 28 SEVERITY: 10 MESSAGE: INVALID DO SYNTAX An invalid DO instruction was executed. An initializer expression must be given if a TO or BY expression is specified,and a FOR expression must yield a non- negative integer result. ERROR: 29 SEVERITY: 10 MESSAGE: INCOMPLETE IF OR SELECT An IF or SELECT range ended before all of the required statement were found. Check whether the conditional statement following a THEN,ELSE,or OTHERWISE clause was omitted. ERROR: 30 SEVERITY: 10 MESSAGE: LABEL NOT FOUND A label specified by a SIGNAL instruction,or implicitly referenced by an enabled interrupt,could not be found in the program source. Labels defined dynamically by an INTERPRET instruction or by interactive input are not included in the search. ERROR: 31 SEVERITY: 10 MESSAGE: SYMBOL EXPECTED A non-symbol token was found where only a symbol token is valid. The DROP,END, LEAVE,ITERATE,and 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. ERROR: 32 SEVERITY: 10 MESSAGE: SYMBOL OR STRING EXPECTED An invalid token was found in a context where only a symbol or string is valid. ERROR: 33 SEVERITY: 10 MESSAGE: INVALID KEYWORD A symbol token in an instruction clause was identified as a keyword,but was invalid in the specific context. ERROR: 34 SEVERITY: 10 MESSAGE: REQUIRED KEYWORD MISSING 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 ON instruction is not followed by one of the interrupt keywords(e.g.SYNTAX.) ERROR: 35 SEVERITY: 10 MESSAGE: EXTRANEOUS CHARACTERS A seemingly valid statement was executed,but extra characters were found at the end of the clause. ERROR: 36 SEVERITY: 10 MESSAGE: KEYWORD CONFLICT Two mutually exclusive keywords were included in an instruction clause,or a keyword was included twice in the same instruction. ERROR: 37 SEVERITY: 10 MESSAGE INVALID TEMPLATE The template provided with an ARG,PARSE,or PULL instruction was not properly constructed. Refer to Chapter 8 for a description of template structure and processing. 106 ERROR: 38 SEVERITY: 10 MESSAGE: INVALID TRACE REQUEST The alphabetic keyword supplied with a TRACE instruction or as the argument to the TRACE()Built-In function was not valid. Refer to Chapter 7 for the valid TRACE options. ERROR: 39 SEVERITY: 10 MESSAGE: UNINITIALIZED VARIABLE An attempt was made to use an uninitialized variable while the NOVALUE interrupt was enabled. ERROR: 40 SEVERITY: 10 MESSAGE: INVALID VARIABLE NAME An attempt was made to assign a value to a fixed symbol. ERROR: 41 SEVERITY: 10 MESSAGE: INVALID EXPRESSION 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. ERROR: 42 SEVERITY: 10 MESSAGE: UNBALANCED PARENTHESE An expression was found with an unequal number of opening and closing parentheses. ERROR: 43 SEVERITY: 43 MESSAGE: NESTING LIMIT EXCEEDED 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. ERROR: 44 SEVERITY: 10 MESSAGE: INVALID EXPRESSION RESULT 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. ERROR: 45 SEVERITY: 10 MESSAGE: EXPRESSION REQUIRED An expression was omitted in a context where one is required. For example,the SIGNAL instruction,if not followed by the keywords ON or OFF,must be followed by an expression. ERROR: 46 SEVERITY: 10 MESSAGE: BOOLEAN VALUE NOT 0 OR 1 An expression result was expected to yield a boolean result,but evaluated to something other than 0 or 1. ERROR: 47 SEVERITY: 10 MESSAGE: ARITHMETIC CONVERSION ERROR 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. ERROR: 48 SEVERITY: 10 MESSAGE: INVALID OPERAND 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. 107 APPENDIX B LIMITS AND COMPATIBILITY ARexx was designed to adhere closely to the REXX language standard. This appendix discusses those areas where ARexx departs from the standard. B-1 LIMITS 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. LENGTH OF STRINGS. Strings,symbol names,and value strings are limited to a maximum length of 65,535 bytes. LENGTH OF CLAUSES. Clauses are limited to a maximum of 800 characters after removing comments and multiple blanks. NODES IN COMPOUND NAMES. Compound symbol names may include a maximum of 50 nodes,including the stem. ARGUMENTS TO FUNCTIONS. 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. SUBEXPRESSION NESTING. The maximum nesting level for subexpressions is 32. B-2 COMPATIBILITY ARexx departs in a few ways from the language definition. The differences can be classified as omissions or extensions,and are described below. OMISSIONS. 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 FUZZ option is not implemented at all. Only the SCIENTIFIC format is used for exponential notation. The full numeric capabilities will be provided in a later release. EXTENSIONS. The following extensions to the language standard have been included in this implementation: BREAK INSTRUCTION. A new instruction called BREAK has been implemented. It is used to exit from the scope of any DO or INTERPRET instruction. ECHO INSTRUCTION. The ECHO instruction has been included as a synonym for SAY. SHELL INSTRUCTION. The SHELL instructiion has been included as a synonym for ADDRESS. 109 SIGNAL OPTIONS. Several additional SIGNAL keywords have been implemented. BREAK_C,BREAK_D,BREAK_E,and BREAK_F will detect and trap the control-C through control-F signals passed by AmigaDOS. The IOERR keyword traps errors detected by the I/O system. STEM SYMBOLS. A stem symbol is valid anywhere that a simple symbol could be employed. TEMPLATE PROCESSING. 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 instruction. 110 APPENDIX C THE AREXX SYSTEMS LIBRARY The ARexx interpreter is supplied as a shared library named rexxsyslib.library 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. C-1 FUNCTION GROUPS The library functions can be frouped into Conversion,Input/Output,Resource Management,and String Manipulation functions. DATA CONVERSION. These functions provide many of the common data-conversion requirements. INPUT/0UTPUT. 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. RESOURCE. These functions allocate,release,or otherwise manage the data structures used with ARexx. STRING FUNCTIONS. All data in ARexx are managed as strings. These functions provide some of the more common string-manipulation operations. 111 TABLE C.1 AREXX SYSTEMS LIBRARY FUNCTIONS NAME FUNCTIONAL GROUP DESCRIPTION AddClipNode Resource Allocate a Clip node ClearMem Resource Clear a block of memory ClearRexxMsg Resource Release argstrings from message CloseF Input/Output Close a file buffer ClosePublicPort Resource Close a port resource node CmpString String Compare string structures for equality CreateArgstring Resource Create an argstring structure CreateDOSPkt Input/Output Creata a DOS Standard Packet CreateRexxMsg Resource Create a message packet CurrentEnv Resource Get current storage environment CVa2i Conversion ASCII to integer CVc2x Conversion Character to Hex or Binary digits CVi2a Conversion Integer to ASCII CVi2arg Conversion Integer to ASCII argstring CVi2az Conversion Integer to ASCII,leading zeroes CVs2i Conversion String structure to integer CVx2c Conversion Hex or binary digits to binary DeleteArgstring Resource Release an argstring structure DeleteDOSPkt Input/Output Release a DOS Standard Packet DeleteRexxMsg Resource Release a message packet DOSRead Input/Output Read from a DOS filehandle DOSWrite Input/Output Write to a DOS filehandle ErrorMsg Conversion Get error message from error code ExistF Input/Output Check whether a DOS file exists FillRexxMsg Resource Convert and install argstrings FindDevice Input/Output Locate a DOS device node FindRsrcNode Resource Locate a resource node FreePort Resource Close a message port FreeSpace Resource Release internal memory GetSpace Resource Allocate internal memory InitList Resource Initialize a list header InitPort Resource Initialize a message port IsRexxMsg Resource Test a message packet LengthArgstring Resource Get length of argstring ListNames Resource Copy node names to an argstring OpenF Input/Output Open a file buffer OpenPublicPort Resource Allocate and open a port resource node QueueF Input/Output Queue a line in a file buffer ReadF Input/Output Read from a file buffer ReadStr Input/Output Read a string from a file buffer RemClipNode Resource Release a Clip node RemRsrcList Resource Release a resource list RemRsrcNode Resource Release a resource node 112 TABLE C.1 LIBRARY FUNCTIONS (cont) NAME FUNCTIONAL GROUP DESCRIPTION SeekF Input/Output Reposition a file buffer StackF Input/Output Stack a line in a file buffer StcToken String Break out a token StrcmpN String Compare strings StrcpyA String Copy a string,converting to ASCII StrcpyN String Copy a string StrCpyU String Copy a string,converting to uppercase StrflipN String Reverse characters in a string Strlen String Find length of a string ToUpper Conversion ASCII to uppercase WriteF Input/Output Write to a file buffer C-2 LIBRARY FUNCTIONS 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. AddClipNode()-allocate and link a Clip node Usage:node=AddClipNode(list,name,length,value) 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()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(). See Also:RemClipNode(),RemRsrcList(),RemRsrcNode() AddRsrcNode()-allocate and link a resource node Usage:node=AddRsrcNode(list,name,length) 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. 113 The returned value is a pointer to the allocated node,or 0 if the allocation failed. See Also:RemRsrcList(),RemRsrcNode() ClearMem()-clear a block of memory Usage:ClearMem(address,length) 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. ClearRexxMsg()-release argument strings Usage:ClearRexxMsg(msgptr,count) 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() CloseF()-close a file buffer Usage:boolean=CloseF(IoBuff) 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(). ClosePublicPort()-close a port resource node Usage:ClosePublicPort(node) 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() CmpString()-compare string structures for equality Usage:test=CmpString(ss1,ss2) 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. 114 CreateArgstring()-create an argument string structure Usage:argstring=CreateArgstring(string,length) 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() CreateDOSPkt()-allocate and initialize a DOS standard Packet. Usage:packet = CreateDOSPkt() 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() CreateRexxMsg()-allocate an ARexx message packet Usage: msgptr=CreateRexxMsg(replyport,extension,host) 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() CVa2i()-convert from ASCII to integer Usage: (digits,value) = CVa2i(buffer) 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. 115 CVc2x()-convert(unpack)from character string to hex or binary digits. Usage: error = CVc2x(outbuff,string,length,mode) 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() CVi2arg()-convert from integer to argstring Usage: argstring=CVi2arg(value,digits) 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(). CVi2az()-convert from integer to ASCII with leading zeroes Usage: (length,pointer)=CVi2az(buffer,value,digits) 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 except that leading zeroes are supplied. See Also:CVi2a() CVs2i()-convert from string structure to integer Usage: (error,value)=CVs2i(ss) 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("Arithmetic conversion error")if the string is not a valid number. 116 CVx2c()-convert from hex or binary digits to(packed)string Usage:error=CVx2c(outbuff,string,length,mode) 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. CurrentEnv()-return the current storage environment Usage:envptr=CurrentEnv(rxtptr) 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. DeleteArgstring()-delete(release)an argstring structure Usage:DeleteArgstring(argstring) 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() DeleteDOSPkt()-release a DOS Standard Packet structure. Usage:DeleteDOSPkt(message) A0 Releases a DOS StandardPacket structure,typically obtained by a prior call to CreateDOSPkt(). See Also:CreateDOSPkt() DeleteRexxMsg()-delete(release)an ARexx message packet. Usage:DeleteRexxMsg(packet) 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() 117 DOSREAD()-read from a DOS file Usage:count=DOSRead(filehandle,buffer,length) 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. DOSWrite()-write to a DOS file Usage:count=DOSWrite(filehandle,buffer,length) 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. ErrorMsg()-find the message associated with an error code Usage:(boolean,ss)=ErrorMsg(code) 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. ExistF()-check whether an external file exists Usage:boolean=ExistF(filename) 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. FillRexxMsg()-convert and install arguments in message packet. Usage:boolean=FillRexxMsg(msgptr,count,mask) 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). 118 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() FindDevice()-check whether a DOS device exists. Usage:device=FindDevice(devicename,type) 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 DLT_DEVICE,DLT_DIRECTORY,or DLT_VOLUME 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. FindRsrcNode()-locate a resource node with the given name. Usage:node=FindRsrcNode(list,name,type) 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. FreePort()-release resources associated with a message port Usage:FreePort(port) 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() FreeSpace()-releases space to the internal memory allocator. Usage:FreeSpace(envptr,block,length) A0 A1 D0 Returns a block of memory to the internal allocator,which must have been obtained from a call to GetSpace(). The envptr argument is a pointer to the base or current storage environment. See Also:CurrentEnv(),GetSpace() 119 GetSpace()-allocate memory using the internal allocator. Usage:block=GetSpace(envptr,length) 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(),FreeSpace() InitList()-initialize a list header Usage:InitList(list) A0 Initializes an EXEC list header structure. InitPort()-initialize a previously-allocated message port. Usage:(signal,port)=InitPort(port,name) 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() IsRexxMsg()-check whether a message came from ARexx. Usage:boolean=IsRexxMsg(msgptr) 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. 120 IsSymbol()-check whether a string is a valid symbol. Usage:(code,length)=IsSymbol(string) 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. ListNames()-build a string of names from a list. Usage:argstring=ListNames(list,separator) 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() after the names are no longer needed. See Also:DeleteArgstring() LockRexxBase()-lock a shared resource. Usage:LockRexxBase(resource) 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() OpenF()-open a file buffer Usage:IoBuff=OpenF(list,filename,mode,logical) 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. 121 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() OpenPublicPort()-open a public message port Usage:node=OpenPublicPort(list,name) 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() QueueF()-queue a line to a file buffer. Usage:count-=QueueF(IoBuff,buffer,length) 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() ReadF()-read characters from a file buffer Usage:count=ReadF(IoBuff,buffer,length) 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. ReadStr()-read a string from a file Usage:(count,pointer)=ReadStr(IoBuff,buffer,length) 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. 122 See Also:ReadF() RemClipNode()-unlink and deallocate a list Clip node. Usage:RemClipNode(node) 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() or RemRsrcList(). See Also:AddClipNode(),RemRsrcList(),RemRsrcNode() RemRsrcList()-unlink and deallocate a list of resource nodes Usage:RemRsrcList(list) 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() RemRsrcNode()-unlink and deallocate a resource node Usage:RemRsrcNode(node) 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() SeekF()-seek to the specified position in a file. Usage:position=SeekF(IoBuff,offset,anchor) 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. StackF()-stack a line to a file buffer. Usage:count=StackF(IoBuff,buffer,length) 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. 123 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() StcToken()-break out the next token from a string Usage:(quote,length,scan,token)=StcToken(string) 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. StrcpyA()-copy a string,converting to ASCII Usage:hash=StrcpyA(destination,source,length) 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(),StrcpyU StrcpyN()-copy a string Usage:hash=StrcpyN(destination,source,length) 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(),StrcpyU StrcpyU()-copy a string,converting to uppercase Usage:hash=StrcpyU(destination,source,length) 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(),StrcpyN 124 StrflipN()-reverse the characters in a string Usage:StrflipN(string,length) A0 D0 Reverses the sequence of characters in a string. The conversion is performed in place. Strlen()-find the length of a null-terminated string Usage:length=Strlen(string) 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. StrcmpN()-compare the values of strings Usage:test=StrcmpN(string1,string2,length) 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. ToUpper()-translate an ASCII character to uppercase Usage:upper=ToUpper(character) D0 D0 Converts an ASCII character to uppercase. Only register D0 is affected. UnlockRexxBase()-unlock a shared resource. Usage:UnlockRexxBase(resource) D0 Releases the specified resource,or all resources if the argument is zero. Every call to LockRexxBase()should be followed eventually by a call to UnlockRexxBase ()for the same resource. See Also:LockRexxBaseF() WriteF()-write characters to a file buffer Usage:count=WriteF(IoBuff,buffer,length) 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, 125 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(),OpenF(),ReadF() 126 APPENDIX D THE AREXX SUPPORT LIBRARY 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,the support library functions are callable from with ARexx programs. The support library was designed to supplement the generic Built-In functions with functions specific to the Amiga. This library will be expanded in future releases,and users are encouraged to submit suggestions for additional functions. The Support Library must be added to the global Library List before it can be accessed by ARexx programs. This can be done using the Built-In function ADDLIB() or by direct communication with the resident process. The library name must be specified as rexxsupport.library,the query function offset is -30,and the version number is 0. The search priority can be set to 0 or whatever value is appropriate. ALLOCMEM() Usage:ALLOCMEM(length,[attribute]) 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() Example: say c2x(allocmem(1000)) ==>00050000 CLOSEPORT() Usage:CLOSEPORT(name) Closes the message port specified by the name argument,which must have been allocated by a call to OPENPORT()within the current ARexx program. Any messages received but not yet REPLYed are automatically returned with the return code set to 10. See Also:OPENPORT() Example: call closeport myport 127 FREEMEM() Usage:FREEMEM(address,length) 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(). FREEMEM()cannot be used to release memory allocated using GETSPACE(),the ARexx internal memory allocator. The returned value is a boolean success flag. See Also:ALLOCMEM() Example: say freemem('00042000'x,32) ==>1 GETARG() Usage:GETARG(packet,[n]) 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(). 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: command = getarg(packet) function= getarg(packet,0) /* name string */ arg1 = getarg(packet,1) /* 1st argumeent*/ GETPKT() Usage:GETPKT(name) 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() 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()and allow other tasks to proceed. See Also:WAITPKT() Example: packet = getpkt('MyPort') OPENPORT() Usage:OPENPORT(name) 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. 128 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() Example: myport = openport("MyPort") REPLY() Usage:REPLY(packet,rc) 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: call reply packet,10 /* error return*/ SHOWDIR() Usage:SHOWDIR(directory,['All' | 'File' | 'Dir']) 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: say showdir("df1:c") ==>rx ts te hi tco tcc SHOWLIST() Usage:SHOWLIST[{'D' | 'L' | 'P' | 'R' | 'W' },[name]) The first argument is an option keyword to select a system list;the options currently supported are Devices,Libraries,Ports,Ready,and Waiting. 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: say showlist('P') ==>REXX MyCon say showlist('P','REXX') ==>1 129 STATEF() Usage:STATEF(filename) 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: say statef("libs:rexxsupport.library") /* would give "FILE 1880 4 RWED " */ WAITPKT() Usage:WAITPKT(name) Waits for a message to be received at the specified(named)port,which must have been opened by a call to 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(),and should be returned eventually using the 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: call waitpkt 'MyPort' /* wait awhile */ 130 APPENDIX E DISTRIBUTION FILES 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. E-1 DIRECTORIES The files are listed below as they would be using the system dir command. For example,"dir df1:c opt a" would list the contents of the :c directory on disk drive 1. THE :C DIRECTORY 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 THE :INCLUDE DIRECTORY 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 131 THE :LIBS DIRECTORY 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 THE :REXX DIRECTORY The :rexx directory contains example programs to illustrate various features of the language. New files will be added from time to time,and users are welcome to contribute files to be distributed in this way. rexx(dir) bigif.rexx break.rexx builtin.rexx calc.rexx cmdtest.rexx fact.rexx factw.rexx haltme.rexx hosttest.rexx iftest.rexx marquis.rexx nesttest.rexx paver.rexx potpourii.rexx rslib.rexx select.rexx sigtest.rexx support.rexx test1.rexx timer.rexx THE :TOOLS DIRECTORY These files are intended for software developers,and include examples of interfacing to ARexx. The file rexxtest is of particular interest;it calls the ARexx interpreter directly,and can be run under a debugger to aid with developing new function libraries. tools(dir) hosttest hosttest.asm loadlib.asm rexxtest rexxtest.asm rxoffsets.o Miscellaneous Files .info Install-ARexx README Start-Aexx 132 E-2 LISTINGS OF HEADER FILES This section of the chapter consists of listings of the header files contained in the :include directory. storage.h This is the main header file and contains definitions for all of the important data structures used by ARexx. /*===rexx/storage.h================================================= * * Copyright (c) 1986,1987 by William S. Hawes (All Rights Reserved) * *================================================================== * Header file to define ARexx data structures. */ #ifndef REXX_STORAGE_H #define REXX_STORAGE_H #ifndef EXEC_TYPES_H #include "exec/types.h" #endif #ifndef EXEC_NODES_H #include "exec/nodes.h" #endif #ifndef EXEC_LISTS_H #include "exec/lists.h" #endif #ifndef EXEC_PORTS_H #include "exec/ports.h" #endif #ifndef EXEC_LIBRARIES_H #include "exec/libraries.h" #endif /* The NexxStr structue is used to maintain the internal strings in REXX. * It includes the buffer area for the string and associated attributes. * This is actually a variable-length structure;it is allocated for a * specific length string,and the length is never modified thereafter * (since it's used for recycling). */ 133 storage.h(cont.) struct NexxStr{ LONG ns_Ivalue; /* integer value */ UWORD ns_Length; /* length in bytes(excl null) */ UBYTE ns_Flags; /* attribute flags */ UBYTE ns_Hash; /* hash code */ BYTE ns_Buff[8]; /* buffer area for strings */ }; /* size: 16 bytes (minimum) */ #define NXADDLEN 9 /* offset plus null byte */ #define IVALUE(nsPtr) (nsPtr->ns_Ivalue) /* String attribute flag bit definitions */ #define NSB_KEEP 0 /* permanent string? */ #define NSB_STRING 1 /* string form valid? */ #define NSB_NOTNUM 2 /* non-numeric? */ #define NSB_NUMBER 3 /* a valid number? */ #define NSB_BINARY 4 /* integer value saved? */ #define NSB_FLOAT 5 /* floating point format? */ #define NSB_EXT 6 /* an external string? */ #define NSB_SOURCE 7 /* part of the program source? */ /* The flag form of the string attributes */ #define NSF_KEEP (1<< NSB_KEEP ) */ #define NSF_STRING (1<< NSB_STRING) #define NSF_NOTNUM (1<< NSB_NOTNUM) #define NSF_NUMBER (1<< NSB_NUMBER) #define NSF_BINARY (1<< NSB_BINARY) #define NSF_FLOAT (1<< NSB_FLOAT ) #define NSF_EXT (1<< NSB_EXT ) #define NSF_SOURCE (1<< NSB_SOURCE) * Combinations of flags #define NSF_INTNUM (NSF_NUMBER | NSF_BINARY | NSF_STRING) #define NSF_DPNUM (NSF_NUMBER | NSF_FLOAT) #define NSF_ALPHA (NSF_NOTNUM | NSF_STRING) #define NSF_OWNED (NSF_SOURCE | NSF_EXT | NSF_KEEP #define KEEPSTR (NSF_STRING | NSF_SOURCE | NSF_NOTNUM) #define KEEPNUM (NSF_STRING | NSF_SOURCE | NSF_NUMBER | NSF_BINARY) 134 storage.h (cont.) /* The RexxArg structure is identical to the NexxStr structure,but * is allocated from system memory rather than from internal storage. * This structure is used for passing arguments to external programs. * It is usually passed as an "argstring",a pointer to the string buffer. */ struct RexxArg { LONG ra_Size; /* total allocated length */ UWORD ra_Length; /* length of string */ UBYTE ra_Flags; /* attribute flags */ UBYTE ra_Hash; /* hash code */ BYTE ra_Buff[8]; /* buffer area */ }; /* size: 16 bytes (minimum) */ /* The RexxMsg structure is used for all communications with Rexx programs. * It is an EXEC message with a parameter block appended. */ struct RexxMsg{ struct Message rm_Node; /* EXEC message structure */ APTR rm_TaskBlock; /* pointer to global structure */ APTR rm_LibBase; /* library base */ LONG rm_Action; /* command (action) code */ LONG rm_Result1; /* primary result (return code) */ LONG rm_Result2; /* secondary result */ STRPTR rm_Args[16]; /* argument block(ARGO-ARG15) */ struct MsgPort *rm_PassPort; /* forwarding port */ STRPTR rm_CommAddr; /* host address (port name) */ STRPTR rm_FileExt; /* file extension */ LONG rm_Stdin; /* input stream(filehandle) */ LONG rm_Stdout; /* output steam(filehandle) */ LONG rm_avail; /* future expension */ }; /* size: 128 bytes */ /* Field definitions #define ARGO(rmp) (rmp->rm_Args[0] /* start of argblock */ #define ARG1(rmp) (rmp->rm_Args[1] /* first argument */ #define ARG2(rmp) (rmp->rm_Args[2] /* second argument */ #define MAXRMARG 15 /* maximum arguments */ /* Command (action) codes for message packets */ #define RXCOMM $01000000 /* a command-level invocation */ #define RXFUNC $02000000 /* a function call */ #define RXCLOSE $03000000 /* close the port */ #define RXQUERY $04000000 /* query for information */ #define RXADDFH $07000000 /* add a function host */ 135 storage.h (cont.) #define RXADDLIB $08000000 /* add a function library */ #define RXREMLIB $09000000 /* remove a function library */ #define RXADDCON $0A000000 /* add/update a ClipList string */ #define RXREMCON $0B000000 /* remove a ClipList string */ #define RXTCOPN $0C000000 /* open the trace console */ #define RXTCCLS $0D000000 /* close the trace console */ /* Command modifier flag bits */ #define RXFB_NOIO 16 /* suppress I/O inheritance? */ #define RXFB_RESULT 17 /* result string expected? */ #define RXFB_STRING 18 /* program is a "string file"? */ #define RXFB_TOKEN 19 /* tokenize the command line? */ #define RXFB_NONRET 20 /* a "no-return" message? */ /* Modifier flags */ #define RXFF_RESULT (1<< RSFB_RESULT) #define RXFF_STRING (1<< RXFB_STRING) #define RXFF_TOKEN (1<< RXFB_TOKEN ) #define RXFF_NONRET (1<< RXFB_NONRET) #define RXCODEMASK $FF000000 #define RXARGMASK $0000000F /* The RexxRsrc structure is used to manage global resources. * The name string for each node is created as a RexxArg structure, * and the total size of the node is saved in the "rr_Size" field. * Functions are provided to allocate and release resource nodes. * If special deletion operations are required,an offset and base can * be provided in "rr_Func" and "rr_Base",respectively. This function * will be called with the base in register A6 and the node in A0. */ struct RexxRsrc { struct Node rr_Node; WORD rr_Func; /* a "auto-delete" offset */ APTR rr_Base; /* "auto-delete" base */ LONG rr_Size; /* total size of node */ LONG rr_Arg1; /* available ... */ LONG rr_Arg2; /* available ... */ }; /* size: 32 bytes */ /* Resource node types */ #define RRT_ANY 0 /* any node type ... */ #define RRT_LIB 1 /* a function library */ #define RRT_PORT 2 /* a public port */ #define RRT_FILE 3 /* a file IoBuff */ #define RRT_HOST 4 /* a function host */ #define RRT_CLIP 5 /* a Clip List node */ 136 storage.h (cont.) /* The RexxTask structure holds the fields used by REXX to communicate with * external processes,including the client task. It includes the global * data structure(and the base environment). The structure is passed to * the newly-created task in its "wake-up" message. */ #define GLOBALSZ 200 /* total size of GlobalData */ struct RexxTask { BYTE rt_Global[GLOBALSZ]; /* global data structure */ struct MsgPort rt_MsgPort; /* global message port */ UBYTE rt_Flags; /* task flag bits */ BYTE rt_SigBit; /* signal bit */ APTR rt_ClientID; /* the client's task ID APTR rt_MsgPkt; /* the packet being processed APTR rt_TaskID; /* our task ID APTR rt_RexxPort; /* the REXX public port APTR rt_ErrTrap; /* Error trap address APTR rt_StackPtr; /* stack pointer for traps struct List rt_Header1; /* Environment list */ struct List rt_Header2; /* Memory freelist */ struct List rt_Header3; /* Memory allocation list */ struct List rt_Header4; /* Files list */ struct List rt_Header5; /* Message Ports List */ }; /* Definitions for RexxTask flag bits #define RTFB_TRACE 0 /* external trace flag */ #define RTFB_HALT 1 /* external halt flag */ #define RTFB_SUSP 2 /* suspend task? */ #define RTFB_TCUSE 3 /* trace console in use? */ #define RTFB_WAIT 6 /* waiting for reply? */ #define RTFB_CLOSE 7 /* task completed? */ /* Definitions for memory allocation constants */ #define MEMQUANT 16 /* quantum of memory space */ #define MEMMASK $FFFFFFF0 /* mask for rounding the size */ #define MEMQUICK (1 << 0 ) /* EXEC flags: MEMF_PUBLIC */ #define MEMCLEAR (1 << 16) /* EXEC flags: MEMF_CLEAR */ 137 storage.h (cont.) /* The SrcNode is a temporary structure used to hold values destined for a * segment array. It is also used to maintain the memory freelist. */ struct SrcNode { struct SrcNode *sn_Succ; /* next node */ struct SrcNode *sn_Pred; APTR sn_Ptr; /* pointer value */ LONG sn_Size; /* size of object */ }; /* size: 16 bytes */ #endif 138 rxslip.h This file defines the library base for the ARexx Systems Library. /* === rexx/rxslib.h======================================================== * * Copyright (c) 1986,1987 by William S. Hawes (All Rights Reserved) * *=========================================================================== * The header file for the REXX Systems Library */ #ifndef REXX_RXSLIB_H #define REXX_RXSLIB_H #ifndef REXX_STORAGE_H #include "rexx/storage.h" #endif /* Some macro definitions */ #define RXSNAME "rexxsyslib.library" #define RXSID "rexxsyslib 1.0 (23 AUG 87)" #define RXSDIR "REXX" #define RXSTNAME "ARexx" /* The REXX systems library structure. This should be considered */ /* semi-private and read-only,except for documented exceptions */ struct RxsLib { struct Library rl_Node; /* EXEC library node */ UBYTE rl_Flags; /* global flags */ UBYTE rl_pad; APTR rl_SysBase; /* EXEC library base */ APTR rl_DOSBase; /* DOS library base */ APTR rl_IeeeDPBase; /* IEEE DP match library base */ LONG rl_SegList; /* library seglist */ LONG rl_MaxAlloc; /* maximum expression allocation*/ LONG rl_Chunk; /* allocation quantum */ LONG rl_MaxNest; /* maximum expression nesting */ struct NexxStr *rl_NULL; /* static string: NULL */ struct NexxStr *rl_FALSE; /* static string: FALSE */ struct NexxStr *rl_TRUE; /* static string: TRUE */ struct NexxStr *rl_REXX; /* static string: REXX */ struct NexxStr *rl_COMMAND; /* static string: COMMAND struct NexxStr *rl_STDIN; /* static string: STDIN struct NexxStr *rl_STDOUT; /* static string: STDOUT struct NexxStr *rl_STDERR; /* static string: STDERR 139 rxslib.h (cont.) STRPTR rl_Version; /* version/configuration string */ STRPTR rl_TaskName; /* name string for tasks */ LONG rl_TaskPri; /* starting prioity */ LONG rl_TaskSeg; /* startup seglist */ LONG rl_StackSize; /* stack size */ STRPTR rl_RexxDir; /* REXX directory */ STRPTR rl_CTABLE; /* character attribute table */ struct NexxStr *rl_Notice; /* copyright notice */ struct MsgPort rl_RexxPort; /* REXX public port */ UWORD rl_ReadLock; /* lock count */ LONG rl_TraceFH; /* global trace console */ struct List rl_TaskList; /* REXX task list */ WORD rl_NumTask; /* task count */ struct List rl_TaskList; /* Library List header */ WORD rl_NumLib; /* library count */ struct List rl_ClipList; /* ClipList header */ WORD rl_NumClip; /* clip node count */ struct List rl_MsgList; /* pending messages */ WORD rl_NumMsg; /* pending count */ }; /* Global flag bit definitions for RexxMaster */ #define RLFB_TRACE RTFB_TRACE /* interactive tracing? */ #define RLFB_HALT RTFB_HALT /* halt execution? */ #define RLFB_SUSP RTFB_SUSP /* suspend execution? */ #define RLFB_TCUSE RTFB_TCUSE /* trace console in use? */ #define RLFB_TCOPN 4 /* trace console open? */ #define RLFB_STOP 6 /* deny further invocations */ #define RLFB_CLOSE 7 /* close the master */ #define RLFMASK 0x07 /* passed flags */ ; Initialization constants #define RXSVERS 2 /* main version */ #define RXSREV 1 /* revision */ #define RXSALLOC 0x800000 /* maximum allocation */ #define RXSCHUNK 1024 /* allocation quantum */ #define RXSNEST 32 /* expression nesting limit */ #define RXSTPRI 0 /* task priority */ #define RXSSTACK 4096 /* stack size */ #define RXSLISTH 4 /* number of list headers */ 140 rxslib.h (cont.) /* Character attribute flag bits used in REXX. Defined only for */ /* ASCII characters (range 0-127) */ #define CTB_SPACE 0 /* white space characters */ #define CTB_DIGIT 1 /* decimal digits 0-9 */ #define CTB_ALPHA 2 /* alphabetic characters */ #define CTB_REXXSYM 3 /* REXX symbol characters */ #define CTB_REXXOPR 4 /* REXX operator characters */ #define CTB_REXXSPC 5 /* REXX special symbols */ #define CTB_UPPER 6 /* UPPERCASE alphabetic */ #define CTB_LOWER 7 /* lowercase alphabetic */ /* Attribute flags */ #define CTF_SPACE (1 << CTB_SPACE) #define CTF_DIGIT (1 << CTB_DIGIT) #define CTF_ALPHA (1 << CTB_ALPHA) #define CTF_REXXASYM (1 << CTB_REXXSYM) #define CTF_REXXOPR (1 << CTB_REXXOPR) #define CTF_REXXSPC (1 << CTB_REXXSPC) #define CTF_UPPER (1 << CTB_UPPER) #define CTF_LOWER (1 << CTB_LOWER) #endif 141 rexxio.h This file defines the data structures used for buffered I/O. ARexx uses linked lists of IoBuff structures to keep track of the files it opens. Each IoBuff node is allocated as an "auto-delete" structure and can be closed and released by a call to either CloseF() or RemRsrcNode(). An entire list of files can be closed with a call to RemRsrcList(). /* ===rexx/rexxio.h======================================================== * * Copyright (c) 1986,1987 by William S. Hawes (All Rights Reserved) * *========================================================================= * Header file for ARexx Input/Output related structures */ #ifndef REXX_REXXIO_H #define REXX_REXXIO_H #ifndef REXX_STORAGE_H #include "rexx/storage.h" #endif #define RXBUFFSZ 204 /* buffeg length */ /* The IoBuff is a resource node used to maintain the File List. Nodes are * allocated and linked into the list whenever a file is opened. */ struct IoBuff{ struct RexxRsrc iobNode; /* structure for files/strings */ APTR iobRpt; /* read/write pointer */ LONG iobRct; /* character count */ LONG iobDFH; /* DOS filehandle */ APTR iobLock; /* DOS lock */ LONG iobBct; /* buffer length */ BYTE iobArea[RXBUFFSZ]; /* buffer area */ }; /* size: 256 bytes */ /* Access mode definitions */ #define RXIO_EXIST -1 /* an external filehandle */ #define RXIO_STRF 0 /* a "string file" */ #define RXIO_READ 1 /* read-only access */ #define RXIO_WRITE 2 /* write mode */ #define RXIO_APPEND 3 /* append mode (existing file) */ 142 rxxio.h (cont.) /* Offset anchors for SeekF() */ #define RXIO_BEGIN -1 /* relative to start */ #define RXIO_CURR 0 /* relative to current position */ #define RXIO_END 1 /* relative to end */ /* The Library List contains just plain resource nodes */ #define LLOFFSET(rrp) (rrp>rr_Arg1) /* "Query" offset */ #define LLVERS(rrp) (rrp->Arg2) /* library version */ /* The RexxClipNode structure is used to maintain the Clip List. The * The ReplyList holds packets that have been received but haven't been * replied. */ struct RexxMsgPort{ struct RexxRsrc rmp_Node; /* linkage node */ struct MsgPort rmp_Port; /* the message port */ struct List rmp_ReplyList; /* messages awaiting reply */ }; /* DOS Device types */ #define DT_DEV 0 /* a device */ #define DT_DIR 1 /* an ASSIGNed directory */ #define DT_VOL 2 /* a volume */ /* Private DOS packet types */ #define ACTION_STACK 2002 /* stack a line */ #define ACTION_QUEUE 2003 /* queue a line */ #endif 143 errors. h This file contains the definitions for all of the error messages issued by the ARexx interpreter. /* == errors.h================================================================ * * Copyright (c) 1987 by Williams S. Hawes (All Rights Reserved) * * =========================================================================== * Definitions for ARexx error codes */ #define EERC_MSG 0 /* error code offset */ #define ERR10_001 (ERRC_MSG+1) /* program not found */ #define ERR10_002 (ERRC_MSG+2) /* execution halted */ #define ERR10_003 (ERRC_MSG+3) /* no memory available */ #define ERR10_004 (ERRC_MSG+4) /* invalid character in program */ #define ERR10_005 (ERRC_MSG+5) /* unmatched quote */ #define ERR10_006 (ERRC_MSG+6) /* unterminated comment */ #define ERR10_007 (ERRC_MSG+7) /* clause too long */ #define ERR10_008 (ERRC_MSG+8) /* unrecognized token */ #define ERR10_009 (ERRC_MSG+9) /* symbol or string too long */ #define ERR10_010 (ERRC_MSG+10) /* invalid message packet */ #define ERR10_011 (ERRC_MSG+11) /* command string error */ #define ERR10_012 (ERRC_MSG+12) /* error return from function */ #define ERR10_013 (ERRC_MSG+13) /* host environment not found */ #define ERR10_014 (ERRC_MSG+14) /* required library not found */ #define ERR10_015 (ERRC_MSG+15) /* function not found */ #define ERR10_016 (ERRC_MSG+16) /* no return value */ #define ERR10_017 (ERRC_MSG+17) /* wrong number of arguments */ #define ERR10_018 (ERRC_MSG+18) /* invalid argument to function */ #define ERR10_019 (ERRC_MSG+19) /* invalid PROCEDURE */ #define ERR10_020 (ERRC_MSG+20) /* unexpected THEN/ELSE */ #define ERR10_021 (ERRC_MSG+21) /* unexpected WHEN/OTHERWISE */ #define ERR10_022 (ERRC_MSG+22) /* unexpected LEAVE or ITERATE */ #define ERR10_023 (ERRC_MSG+23) /* invalid statement in SELECT */ #define ERR10_024 (ERRC_MSG+24) /* missing THEN clauses */ #define ERR10_025 (ERRC_MSG+25) /* missing OTHERWISE */ #define ERR10_026 (ERRC_MSG+26) /* missing or unexpected END */ #define ERR10_027 (ERRC_MSG+27) /* symbol mismatch on END */ #define ERR10_028 (ERRC_MSG+28) /* invalid DO syntax */ #define ERR10_029 (ERRC_MSG+29) /* incomplete DO/IF/SELECT */ 144 errors.h (cont.) #define ERR10_030 (ERRC_MSG+30) /* label not found */ #define ERR10_031 (ERRC_MSG+31) /* symbol expected */ #define ERR10_032 (ERRC_MSG+32) /* string or symbol expected */ #define ERR10_033 (ERRC_MSG+33) /* invalid sub-keyword */ #define ERR10_034 (ERRC_MSG+34) /* required keyword missing */ #define ERR10_035 (ERRC_MSG+35) /* extraneous characters */ #define ERR10_036 (ERRC_MSG+36) /* sub-keyword conflict */ #define ERR10_037 (ERRC_MSG+37) /* invalid template */ #define ERR10_038 (ERRC_MSG+38) /* invalid TRACE request */ #define ERR10_039 (ERRC_MSG+39) /* uninitialized variable */ #define ERR10_040 (ERRC_MSG+40) /* invalid variable name */ #define ERR10_041 (ERRC_MSG+41) /* invalid expression */ #define ERR10_042 (ERRC_MSG+42) /* unbalanced parentheses */ #define ERR10_043 (ERRC_MSG+43) /* nesting level exceeded */ #define ERR10_044 (ERRC_MSG+44) /* invalid expression result */ #define ERR10_045 (ERRC_MSG+45) /* expression required */ #define ERR10_046 (ERRC_MSG+46) /* boolean value not 0 or 1 */ #define ERR10_047 (ERRC_MSG+47) /* arithmetic conversion error */ #define ERR10_048 (ERRC_MSG+48) /* invalid operand */ /* Return Codes for general use ... */ #define RC_FAIL -1 /* something's wrong */ #define RC_OK 0 /* success */ #define RC_WARN 5 /* warning only */ #define RC_ERROR 10 /* something's wrong */ #define RC_FATAL 20 /* complete or severe failure */ 145 GLOSSARY ALLOCATION. A grant of a system resource,such as memory space. Programs designed to run in a multitasking environment generally use dynamic allocation to avoid tying up system resources. AMIGADOS. The higher-level part of the Amiga operating system that supports the filing system and input/output operations. ARGSTRING. An "argument string" structure used to pass data to an ARexx program. The structure is passed as a pointer to the buffer area containing the string data,and can be treated as a pointer to a null-terminated string. ARGUMENT. A data item passed to a function,sometimes called a parameter. CLAUSE. A group of one or more tokens forming a "sentence" in a language. The clause is the smallest executable language fragment. COMMAND LINE INTERFACE (CLI). A program that accepts input from the user and runs programs based on the entered command. The CLI generally refers to the command interpreter supplied with the Amiga,but other command "shells" may be used instead. CONCATENATION. An operation in which two strings are joined or "chained together." ARexx provides two concatenation operators,one of which joins strings directly and the other of which embeds a blank between the operands. EXEC. The multitasking kernel of the Amiga's operating system. EXEC provides the task scheduling,interrupt handlin,and message-passing primitives used to support ARexx. FUNCTION HOST. A program that manages a public message port for receiving function invocation messages. The message port may be the same one used for command messages. FUNCTION LIBRARY. A collection of functions callable from ARexx and managed as an Amiga shared library. Each function library includes an entry point to associate a function name with the code to be called. HOST ADDRESS. The name of the public message port associated with a host application. The host address is used as the unique identifier for the host,and should be unique within the system message ports list. Within an ARexx program the host address identifies the external host to which commands will be sent. 147 HOST APPLICATION. An executable program that program that provides a suitable command interface to receive ARexx commands. Most host applications will also provide a means to invoke macro programs from within the application. INTERRUPT. An event that alters the normal flow of control in a program. Interrupts in ARexx refer to events within the program execution and are distinct from the hardware-level interrupts managed by the Amiga EXEC system. MACRO PROGRAM. A program that implements a complex "macro" operation from a series of "micro" commands. MESSAGE PACKET. A data structure used to pass information between tasks. A message packet is allocated and initialized by one task and then sent to another task's message port. After the recipient has processed the message,it "replies" the message to the replyport associated with the message. MESSAGE PORT. A data structure used as the rendezvous point for message passing. A message port provides the anchor for a list of message packets and identifies the task to be signalled when a message arrives. MULTITASKING. The ability to run more than one program at a time. More precisely, multitasking permits the resources of the computer to be shared among many tasks without forcing any task to be aware of the others. PROCESS. An extension to an EXEC task structure that provides the data fields required to use AmigaDOS functions. All ARexx programs run as AmigaDOS processes. REPLYPORT. A message port designated to receive a returning message packet. Each message packet includes a field that specifies its reply port. RESIDENT PROCESS. The program responsible for launching ARexx programs and for managing various resources used by ARexx. It is structured as a host application and opens a public message port named "REXX." SHARED LIBRARY. A collection of executable code and data managed as a resource by the EXEC operating system. As the name "shared" implies, the code and data in a library can be used by more than one task. STORAGE ENVIRONMENT. The collection of data values forming the current state of an ARexx program. Storage environments are strictly nested and only one environment is current at any time. TASK. An entity consisting of executable code and a data structure managed by the EXEC operating system. The task is the smallest program unit that can be scheduled and run separately. 148 TOKEN. The elementary words or atoms of a language. A token can be considered as a string of one or more characters forming the smallest unit of the language. TYPELESS. Data items having no assumed structure or usage. ARexx treats all data as typeless character strings and checks for specific characteristics only when required by an operation. 149