Jump to content

REXX Tips & Tricks:Miscellaneous: Difference between revisions

From EDM2
Ak120 (talk | contribs)
Ak120 (talk | contribs)
Line 462: Line 462:


=="Compiling" REXX programs==
=="Compiling" REXX programs==
I don't know of a real REXX compiler for OS/2 REXX. But because the REXX interpreter stores an tokenized copy of each REXX program in the EAs of the program, it is possible to delete the source code from REXX programs (see REXXCC). Another method to "compile" a REXX program is used by the program RxCLS. But this is also no real compiler.
The only method to create a standalone REXX program that runs on any machine with or without REXX installed is to create an EXE containing the REXX program and a static version of a REXX interpreter. This is possible with the package Rexx/Wrapper and the REXX Interpreter Regina from Mark Hessling (see Internet - Web Pages)
To "compile" an Object-Oriented REXX program you can use the program REXXC.EXE which is part of Object-Oriented REXX. REXXC.EXE creates the token image and saves it in a REXX cmd. This method avoids the 64 K limit for the token image. (see also the [[#Creating "compiled" programs for Classic REXX and Object REXX]])
Another method to create a token image of your REXX program is to load the REXX program into the macro space and save the macro space into a file. This will produce a token image of your REXX program that you can reload into the macrospace and execute it from there. This method also avoids the 64 K limit of the EAs. (see REXXCC - a REXX "compiler") In this case you need an additional loader to load the token image into the macro space again before you can execute it.
Or use LoadMac.cmd to create and load the token image:
<code>
REM *** Create the token image
LOADMAC CLEAR ADD:myProg.CMD SAVE:myProg.IMG
REM *** Load the image into the REXX macro space
LOADMAC CLEAR LOAD:MyProg.IMG
REM *** Execute the image
REXXTRY call myprog myparms
REM *** Drop the image from the REXX macro space
LOADMAC DROP:MyProg
REM *** or (if the image contains more than one macro)
LOADMAC CLEAR
</code>
see also Debugging a "compiled" REXX program, Get the source code of a "compiled" REXX program, and Protect the source code of a REXX program
===Creating "compiled" programs for Classic REXX and Object REXX===
To use a "compiled" program in Classic REXX and in Object REXX you must create a "compiled" version for Classic REXX (created for example with REXXCC) and a "compiled" version for Object REXX (created with REXXC.EXE from Object REXX). Then, to call your "compiled" REXX program you should use a "wrapper" program written in REXX (Do not "compile" the wrapper program!).
The wrapper program might look as follows:
<code>
/* ------------------------------------------------------------------ */
/* sample wrapper to call a "compiled" REXX program depending on the  */
/* version of the current REXX interpreter (Classic REXX or          */
/* Object REXX)                                                      */
/*                                                                    */
/* Note:                                                              */
/*                                                                    */
/* This program assumes                                              */
/*                                                                    */
/* - the REXX program "compiled" for Classic REXX is called          */
/*  <name_of_this_prog>C.CMD                                        */
/*                                                                    */
/* - the REXX program "compiled" for Object REXX is called            */
/*  <name_of_this_prog>O.CMD                                        */
/*                                                                    */
/* - both programs are in the same directory as this program          */
/*                                                                    */
                    /* init the return code                          */
  rc = 255
                    /* get the parameter                              */
  parse arg thisParameters
                    /* get the name of this program                  */
  parse source . . thisFile
  progBaseName = substr( thisFile,1 lastPos( ".", thisFile )-1 )
                    /* check the version of the current REXX          */
                    /* interpreter                                    */
  parse upper version thisVersion thisVersionNo
  if thisVersion = "OBJREXX" | thisVersionNo > 4.00 then
  do
                    /* current REXX interpreter is Object REXX        */
    "@cmd /c " progBaseName || "O.CMD" thisParameters
  end /* if thisVersion = "OBJREXX" | thisVersionNo > 4.00 then */
  else
  do
                    /* current REXX interpreter is Classic REXX      */
    "@cmd /c " progBaseName || "C.CMD" thisParameters
  end /* else */
return rc
</code>


==Prevent REXX from creating a token image==
==Prevent REXX from creating a token image==

Revision as of 20:01, 27 January 2020

This section contains some further useful information.

Using PMREXX

The syntax for PMREXX is:

 >>──PMREXX───┬────┬──┬─────────────┬─┬───────────┬─><
              ├─/Q─┤  └─rexxprogram─┘ └─parameter─┘
              └─/T─┘

Where:

/Q
Close PMREXX after the REXX program ends (no "The program has ended" message box)
/T
Start PMREXX in trace mode
rexxprogram
Name of the rexx program
parameter
Parameter for the REXX program

All parameters, except rexxprogram, are optional.

Using PMREXX with the parameter /Q is useful for simple programs which only need to show a PM messagebox (using RxMessageBox). For an example see Saving the Desktop (3.0)

(see Run a REXX program under a specific environment on how to force a program to run under PMREXX)

Please note that you cannot use OS/2 commands that change the environment in a REXX program running under PMREXX. You have to use a similar REXX function for that purpose (e.g. directory() instead of CD, VALUE() instead of SET, etc.).

Warning: The default address environment for a REXX program started via PMREXX in WARP 3 is PMREXX; the default environment in WARP 4 is CMD. Therefore, you cannot distinguish between the environments using ADDRESS() in WARP 4!

Note
see also PMPopup/2 if you only want to use simple dialog boxes in REXX programs.

The RXQUEUE filter

The purpose of the RXQUEUE filter is to copy the output of an OS/2 program into a REXX queue (The RXQUEUE filter is the external program RXQUEUE.EXE - not the built-in function RXQUEUE!) The syntax for RXQUEUE filter is:

>>──RXQUEUE──┬───────────┬──┬────────┬──────><
             └─queuename─┘  ├─/FIFO──┤
                            ├─/LIFO──┤
                            └─/CLEAR─┘

The RXQUEUE filter usually operates on the default queue named "SESSION". However, if an environment variable named "RXQUEUE" exists, the RXQUEUE value is used for the queue name.

Parameters

queuename
This is the name of the queue to use. The queue must already exist. The name of a queue can only contain the following characters: 'A'...'Z', '0'...'9', '.', '!', '?' and '_'. Lowercase letters are converted to uppercase letters.
/LIFO
Stacks items from STDIN last in, first out (LIFO) on a REXX queue.
/FIFO
Queues items from STDIN first in, first out (FIFO) on a REXX queue.
/CLEAR
Removes all lines from a REXX queue.
Note
Again, do not confuse the RXQUEUE filter with the RXQUEUE built-in function! Note further that you cannot use the RXQUEUE filter to write a REXX queue to STDOUT - you've to write a REXX program to do this task. (see Write the REXX Queue to STDOUT for an example).

Return code of the function ADDRESS

A REXX program can use the function ADDRESS to detect the current environment. Following is a list of environments I know about (see Passing parameter to Rexx Dialog programs and Run a REXX program under a specific environment for examples for using this function.):

Return code of ADDRESS Environment Comments
CMD OS/2 REXX Interpreter; also Object REXX for Win95/WinNT use PARSE SOURCE to distinguish between the interpreter: OS/2 REXX returns OS/2; Object REXX for WinNT returns WIN32
CMS VM/ESA 1.1 REXX Interpreter
COMMAND Bill's REXX for DOS
IBM PC DOS 7 REXX Interpreter
Use PARSE VERSION to distinguish between the environments.
CPEDIT CPEDIT, an XEDIT clone from IBM
CPICOMM SAA common environment especially used with communications
DFS Display File Systems
DOS Bill's REXX for DOS
IBM PC DOS 7 REXX Interpreter
Use PARSE VERSION to distinguish between the environments.
EPM EPM, OS/2 Editor
GLOBE PMGlobe 2.18 IBM EWS Graphic program from Mike Cowlishaw, IBM UK Laboratories
FLEETSTREET FleetStreet v1.03 Msg Reader & Editor for Squish msg bases
INT2E Bill's REXX for DOS
ispcir OS/2 DialogManager, IBM
IPSEXEC Tritus SPF, Tritus Inc.
ISREDIT SPF/2, CTC
KEDIT KEDIT, an XEDIT clone from Mansfield Software
ksh IBM's AIX REXX The value is independent from the current shell
MVS OS/390 v1.2 (PGM=IRXJCL) REXX Interpreter
NULL DrDialog this is an alternate SubCommand-Handler for DrDialog programs
PMREXX PMREXX, OS/2 PMREXX.EXE (see the warning in the section Using PMREXX)
REXXTERM REXXTERM, Quercus Software
RXDLG Rexx Dialog
SAY DrDialog this is an alternate SubCommand-Handler for DrDialog programs
STARTDOS StartDOS a program to start DOS VDMs by Monte Copeland
SYSTEM Bill's REXX for DOS
Mark Hesslings's Regina REXX for Windows NT
use PARSE SOURCE to distinguish between the interpreter: Bill's REXX returns MSDOS, Mark's REXX returns WIN32
TE2 TE/2, Oberon Software
THE THE Hessling Editor by Mark Hessling THE is an XEDIT clone for various operating systems
TSO OS/390 v1.2 (TSO) REXX Interpreter
VISION ObjectVision, Borland
UNIX uniREXX on Solaris v2.6
ZOC ZOC 2.x, Markus Schmidt One of the best OS/2 terminal programs available!

ANSI ESC Sequences

ANSI ESC Sequences - also called ANSI commands - are useful for doing some display I/O control in REXX.

To use ANSI commands the OS/2 ANSI support must be active. To activate the ANSI support use the OS/2 command ANSI ON and to deactivate the ANSI support use the OS/2 command ANSI OFF. To get the current status of the ANSI support use the OS/2 command ANSI without a parameter. The default for the ANSI support is ON. (see Check if ANSI is active - 1 - or Check if ANSI is active - 2 - for REXX source to detect if ANSI support is active from within a REXX program)

Each ANSI command begins with the sequence ESC[. where ESC represents the ASCII code 1Bh (= 27 decimal). If there is more than one parameter for an ANSI command, use a semicolon (;) to separate the parameter.

To output ANSI commands you can use the functions LINEOUT and CHAROUT or the statement SAY. Example:

say "1B"x || "[30;41m" || "This text is black on red"

call lineOut , "1B"x || "[31;40m" || "This text is red on black"

call charOut , "1B"x || "[0m" || "This text is in default color"

(see Using ANSI sequences for some sample code using ANSI sequences and RxLBox - menu routine in REXX is a menu program using only ANSI sequences to implement the navigation with cursor keys and function keys)

Note
To use the ANSI commands to set or get the cursor position you must use the function CHAROUT! (see SysCls for another minor restriction)
Further Note
Almost all ANSI Control Characters are documented in the command reference of WARP version 4.
ANSI Commands
Command Function
ESC[colsA Cursor up # lines
ESC[colsB Cursor down # lines
ESC[rowsC Cursor right # columns
ESC[rowsD Cursor left # columns
ESC[row;colH Position the cursor (the upper left corner is 1,1)
ESC[2J Clear the whole screen
ESC[K Clear the rest of the line
ESC[6n Get the current cursor position (see Get the current cursor position)
ESC[row;colf Position the cursor (like "H")
ESC[row;colR Report current cursor line and column (*)
ESC[=modeh Set the display mode (see below)
ESC[=model Set the display mode (see below)
ESC[attr;attr;..m Set the color attribute (see below)
ESC[key;"str"p Redefine the key "key" with the string "str" (see Key redefinitions and Key Codes for key redefinitions)
ESC[s Save the current cursor position (nested calls are not allowed)
ESC[u Restore the cursor position (nested calls are not allowed)
Display attributes
Attribute Description
0 all attributes off (white on black)
1 bold
2 normal
4 underline (only on b/w displays)
5 blink
7 reverse video
8 invisible
30-37 set the foreground color:
30=Black, 31=Red, 32=Green, 33=Yellow
34=Blue, 35=Magenta, 36=Cyan, 37=White
40-47 set the background color:
40=Black, 41=Red, 42=Green, 43=Yellow
44=Blue, 45=Magenta, 46=Cyan, 47=White
Display modes
Mode Description
0 Text 40x25 monochrome
1 Text 40x25 color
2 Text 80x25 monochrome
3 Text 80x25 color
4 Graphics 320x200 4 colors
5 Graphics 320x200 2 color
6 Graphics 640x200 2-color
7 cursor wrap off (7l) or on (7h)

Key Codes for key redefinitions

Keycodes for key redefinitions (extract)
ASCII Key Codes Code SHIFT+Code CTRL+Code ALT+Code
F1 0;59 0;84 0;94 0;104
F2 0;60 0;85 0;95 0;105
F3 0;61 0;86 0;96 0;106
F4 0;62 0;87 0;97 0;107
F5 0;63 0;88 0;98 0;108
F6 0;64 0;89 0;99 0;109
F7 0;65 0;90 0;100 0;110
F8 0;66 0;91 0;101 0;111
F9 0;67 0;92 0;102 0;112
F10 0;68 0;93 0;103 0;113
F11 0;133 0;135 0;137 0;139
F12 0;134 0;136 0;138 0;140
Home (numeric key) 0;71 55 0;119
Up Arrow (numeric key) 0;72 56 (0;141)
Page Up (numeric key) 0;73 57 0;132
Left Arrow (numeric key) 0;75 52 0;115
Right Arrow (numeric key) 0;77 54 0;116
End (numeric key) 0;79 49 0;117
Down Arrow (numeric key) 0;80 50 (0;145)
Page Down (numeric key) 0;81 51 0;118
Ins (numeric key) 0;82 48 (0;146)
Del (numeric key) 0;83 46 (0;147)
Home (224;71) (224;71) (224;119) (224;151)
Up Arrow (224;72) (224;72) (224;141) (224;152)
Page Up (224;73) (224;73) (224;132) (224;153)
Left Arrow (224;75) (224;75) (224;115) (224;155)
Right Arrow (224;77) (224;77) (224;116) (224;157)
End (224;79) (224;79) (224;117) (224;159)
Down Arrow (224;80) (224;80) (224;145) (224;154)
Page Down (224;81) (224;81) (224;118) (224;161)
Insert (224;82) (224;82) (224;146) (224;162)
Delete (224;83) (224;83) (224;147) (224;163)
Print Screen 0;114
Pause/Break 0;0
Backspace 8 8 127 (0)
Enter 13 10 (0,28)
Tab 9 0;15 (0;148) (0;165)
Null 0;3
ESC 27 27 27 27
Space 32 32 32 23
A 97 65 1 0;30
B 98 66 2 0;48
C 99 67 3 0;46
D 100 68 4 0;32
E 101 69 5 0;18
F 102 70 6 0;33
G 103 71 7 0;34
H 104 72 8 0;35
I 105 73 9 0;23
J 106 74 10 0;36
K 107 75 11 0;37
L 108 76 12 0;38
M 109 77 13 0;50
N 110 78 14 0;49
O 111 79 15 0;24
P 112 80 16 0;25
Q 113 81 17 0;16
R 114 82 18 0;19
S 115 83 19 0;31
T 116 84 20 0;20
U 117 85 21 0;22
V 118 86 22 0;47
W 119 87 23 0;17
X 120 88 24 0;45
Y 121 89 25 0;21
Z 122 90 26 0;44
1 49 (*) 0;120
2 50 (*) 0;121
3 51 (*) 0;122
4 52 (*) 0;123
5 53 (*) 0;124
6 54 (*) 0;125
7 55 (*) 0;126
8 56 (*) 0;126
9 57 (*) 0;127
0 48 (*) 0;129
! 33 (*)
" 34 (*)
21 (*)
$ 36 (*)
% 37 (*)
& 38 (*)
/ 47 (*)
( 40 (*)
) 41 (*)
= 61 (*)
? 63 (*)
` 96
' 39
* 42
+ 43
# 35
, 44
; 59
. 46
: 58
- 45
_ 95
< 60
> 62
^ 94
° 248
\ 92
[ 91
] 93
{ 123
} 125
| 124
~ 126
@ 64
ENTER (keypad) 13 10 (0;166)
/ (keypad) 47 47 (0;142) (0;74)
* (keypad) 42 (0;144) (0;78)
- (keypad) 45 45 (0;149) (0;164)
+ (keypad) 43 43 (0;150) (0;55)
5 (keypad) (0;76) 53 (0;143)
ä (German umlaut) 132 142
ö (German umlaut) 148 153
ü (German umlaut) 129 154
ß (German special) 225
Note
Use the values in parenthesis with care - they may work or may not work.

"Compiling" REXX programs

I don't know of a real REXX compiler for OS/2 REXX. But because the REXX interpreter stores an tokenized copy of each REXX program in the EAs of the program, it is possible to delete the source code from REXX programs (see REXXCC). Another method to "compile" a REXX program is used by the program RxCLS. But this is also no real compiler.

The only method to create a standalone REXX program that runs on any machine with or without REXX installed is to create an EXE containing the REXX program and a static version of a REXX interpreter. This is possible with the package Rexx/Wrapper and the REXX Interpreter Regina from Mark Hessling (see Internet - Web Pages)

To "compile" an Object-Oriented REXX program you can use the program REXXC.EXE which is part of Object-Oriented REXX. REXXC.EXE creates the token image and saves it in a REXX cmd. This method avoids the 64 K limit for the token image. (see also the #Creating "compiled" programs for Classic REXX and Object REXX)

Another method to create a token image of your REXX program is to load the REXX program into the macro space and save the macro space into a file. This will produce a token image of your REXX program that you can reload into the macrospace and execute it from there. This method also avoids the 64 K limit of the EAs. (see REXXCC - a REXX "compiler") In this case you need an additional loader to load the token image into the macro space again before you can execute it.

Or use LoadMac.cmd to create and load the token image:

REM *** Create the token image
LOADMAC CLEAR ADD:myProg.CMD SAVE:myProg.IMG

REM *** Load the image into the REXX macro space
LOADMAC CLEAR LOAD:MyProg.IMG

REM *** Execute the image
REXXTRY call myprog myparms

REM *** Drop the image from the REXX macro space
LOADMAC DROP:MyProg

REM *** or (if the image contains more than one macro)
LOADMAC CLEAR

see also Debugging a "compiled" REXX program, Get the source code of a "compiled" REXX program, and Protect the source code of a REXX program

Creating "compiled" programs for Classic REXX and Object REXX

To use a "compiled" program in Classic REXX and in Object REXX you must create a "compiled" version for Classic REXX (created for example with REXXCC) and a "compiled" version for Object REXX (created with REXXC.EXE from Object REXX). Then, to call your "compiled" REXX program you should use a "wrapper" program written in REXX (Do not "compile" the wrapper program!).

The wrapper program might look as follows:

/* ------------------------------------------------------------------ */
/* sample wrapper to call a "compiled" REXX program depending on the  */
/* version of the current REXX interpreter (Classic REXX or           */
/* Object REXX)                                                       */
/*                                                                    */
/* Note:                                                              */
/*                                                                    */
/* This program assumes                                               */
/*                                                                    */
/* - the REXX program "compiled" for Classic REXX is called           */
/*   <name_of_this_prog>C.CMD                                         */
/*                                                                    */
/* - the REXX program "compiled" for Object REXX is called            */
/*   <name_of_this_prog>O.CMD                                         */
/*                                                                    */
/* - both programs are in the same directory as this program          */
/*                                                                    */

                    /* init the return code                           */
  rc = 255

                    /* get the parameter                              */
  parse arg thisParameters

                    /* get the name of this program                   */
  parse source . . thisFile

  progBaseName = substr( thisFile,1 lastPos( ".", thisFile )-1 )

                    /* check the version of the current REXX          */
                    /* interpreter                                    */
  parse upper version thisVersion thisVersionNo
  if thisVersion = "OBJREXX" | thisVersionNo > 4.00 then
  do
                    /* current REXX interpreter is Object REXX        */
    "@cmd /c " progBaseName || "O.CMD" thisParameters
  end /* if thisVersion = "OBJREXX" | thisVersionNo > 4.00 then */
  else
  do
                    /* current REXX interpreter is Classic REXX       */
    "@cmd /c " progBaseName || "C.CMD" thisParameters
  end /* else */

return rc

Prevent REXX from creating a token image

Set the read-only attribute of REXX cmds for which the REXX interpreter should not create a token image (or copy them to a read-only disk or to a filesystem not supporting Extended Attributes).

"Undocumented" REXX functions

The following REXX functions to work with DBCS mixed Strings are only documented in the IBM: OS/2 2.0 Procedures Language/2 Reference Manual and in the Object-Oriented REXX online documentation:

  • DBADJUST
  • DBBRACKET
  • DBCENTER
  • DBLEFT
  • DBRIGHT
  • DBRLEFT
  • DBRRIGHT
  • DBTODBCS
  • DBTOSBCS
  • DBUNBRACKET
  • DBVALIDATE
  • DBWIDTH

Well, for the "normal" REXX programmer only two of these functions are interesting (The functions also work with SBCS strings):

Name       DBRLEFT( string, n {,option} ) 
Function   Delete n chars beginning with the first char 
Example    DBRLEFT( "ABCDEFG", 2 ) gives "CDEFG"
Note       The parameter option is only needed for DBCS strings)
           For SBCS strings you should not use this parameter.
Name       DBRRIGHT( string, n {,option} ) 
Function   Delete n chars beginning with the last char 
Example    DBRRIGHT( "ABCDEFG", 3 ) gives "ABCD"
Note       The parameter option is only needed for DBCS strings)
           For SBCS strings you should not use this parameter.