home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 18 REXX
/
18-REXX.zip
/
rs960115.zip
/
rexxsrc.INF
(
.txt
)
Wrap
OS/2 Help File
|
1996-01-15
|
174KB
|
5,735 lines
ΓòÉΓòÉΓòÉ 1. About the REXX Sourcebook ΓòÉΓòÉΓòÉ
The REXX Sourcebook is a collection of REXX information gotten from various
places on the Internet and turned into an OS/2 .inf document. Except as noted,
I have not contributed any of the factual information contained herein. So, if
you have questions about the contents, you should address the authors of the
various documents. If there is a problem with this file, please let me know.
Also, if you have some REXX documentation or REXX programs that you think
should be included, please contact me.
Dirk Terrell
terrell@astro.ufl.edu
ΓòÉΓòÉΓòÉ 2. The REXX FAQ ΓòÉΓòÉΓòÉ
Frequently Asked Questions About REXX
Last Revised: August 12, 1994
Eric Giguere
giguere@watcom.on.ca
ΓòÉΓòÉΓòÉ 2.1. Copyright Information ΓòÉΓòÉΓòÉ
This document is Copyright 1993, 1994 by Eric Giguere. Permission is granted to
reproduce and distribute all or part of this document for non-commercial
purposes only. All other uses must first be cleared with the author. The
author may be contacted on the Internet at the address giguere@watcom.on.ca or
on paper by writing to Watcom International, 415 Phillip Street, Waterloo,
Ontario, Canada, N2L 3X2. Please note, however, that this document is not
published or endorsed by Watcom.
ΓòÉΓòÉΓòÉ 2.2. Introduction ΓòÉΓòÉΓòÉ
This document is intended to serve as a useful reference for REXX-related
information. It aims for breadth as opposed to depth, and references to other
material are given where appropriate. Suggestions and updates should be sent
to the author in an attempt to keep this document relevant and up- to-date.
Readers will notice the prevalence of OS/2-related materials in this document.
Most of the REXX-related activity at this time is occurring on the OS/2
platform. This document is not intended to be OS/2-specific. The author is
quite happy to include information on other platforms if you pass it on to him.
More information on REXX can also be had from the REXX Language Association.
See below for details.
ΓòÉΓòÉΓòÉ 2.3. What Is REXX? ΓòÉΓòÉΓòÉ
REXX is a programming language designed by Michael Cowlishaw of IBM UK
Laboratories. In his own words: "REXX is a procedural language that allows
programs and algorithms to be written in a clear and structured way." REXX
doesn't look that different from any other procedural language. Here's a simple
REXX program:
/* Count some numbers */
say "Counting..."
do i = 1 to 10
say "Number" i
end
What makes REXX different from most other languages is that it is also designed
to be used as a macro language by arbitrary application programs. The idea is
that application developers don't have to design their own macro languages and
interpreters. Instead they use REXX as the macro language and support the REXX
programming interface. If a REXX macro comes across an expression or function
call that it cannot resolve, it can ask the application to handle it instead.
The application only has to support the features that are specific to it,
freeing the developer from handling the mundane (and time-consuming) task of
writing a language interpreter. And if all applications use REXX as their macro
language, the user only has to learn one language instead of a dozen.
ΓòÉΓòÉΓòÉ 2.4. REXX and the Internet ΓòÉΓòÉΓòÉ
Networks connect computers in various ways for the exchange of data. The
terminology is a bit confusing to the new user. Here are the definitions this
document uses:
Usenet Not really a network, just the set of machines that exchange network
news. Network news is really an extended form of electronic mail
that groups messages from individuals into newsgroups that users can
read using special newsreaders.
Internet The worldwide network based on TCP/IP protocols. Besides being able
to receive mail and newsgroups, these machines can use programs like
ftp and telnet to communicate with other machines in real time. Most
Internet machines are Unix-based.
BITNET The worldwide network that connects many IBM mainframes. BITNET
users can also transfer files using methods that are incompatible
with those of the Internet.
ΓòÉΓòÉΓòÉ 2.4.1. Newsgroups ΓòÉΓòÉΓòÉ
The Usenet group comp.lang.rexx exists for discussion of REXX in all its
variations. Anything posted to this newsgroup also gets sent to the REXXLIST
mailing list (see below) and vice-versa.
Other newsgroups of interest are machine-specific. Recommended groups are
comp.os.os2.programmer and comp.sys.amiga.programmer.
ΓòÉΓòÉΓòÉ 2.4.2. FTP Sites of Interest ΓòÉΓòÉΓòÉ
FTP is a file transmission protocol used on the Internet to transfer files
between machines. The transfers are done in real time and usually require that
the user have an account on both machines. However, many machines on the
Internet support what is known as anonymous FTP, which allows users on other
machines access to a limited set of files without requiring an account. Some of
the more interesting sites that offer this service are:
rexx.uwaterloo.ca General repository for REXX-related information, including
free REXX interpreters for Unix and DOS. An XEDIT clone for Unix and
OS/2 may also be found here. Look under /pub/rexx.
flipper.pvv.unit.no The official home of Regina, one of the free Unix
interpreters. An archive of the messages in comp.lang.rexx is also
maintained here. Check under /pub/rexx.
ftp-os2.cdrom.com, ftp.luth.se General OS/2 archives.
wuarchive.wustl.edu General Amiga archive. Look under /pub/aminet.
ΓòÉΓòÉΓòÉ 2.4.3. Mailing Lists ΓòÉΓòÉΓòÉ
Mailing lists are similar to newsgroups but use normal electronic mail to
deliver the messages. The following mailing lists are mostly BITNET-based but
are accessible from the Internet as well:
List name BITNET Internet Discusses
Node Address
REXXLIST UCF1VM ucf1vm.cc.ucf.edu REXX in general
AREXX-L UCF1VM ucf1vm.cc.ucf.edu Amiga REXX
PC-REXX UCF1VM ucf1vm.cc.ucf.edu Personal REXX
REXXCOMP UCF1VM ucf1vm.cc.ucf.edu IBM's REXX compiler
TSO-REXX UCF1VM ucf1vm.cc.ucf.edu TSO REXX
VM-REXX UCF1VM ucf1vm.cc.ucf.edu VM/SP REXX
UREXX-L (none) liverpool.ac.ak Unix REXX
To subscribe to any of these lists, send a one-line message to the address
LISTSERV@node, where node is the BITNET node or Internet address for the list
you wish to join. In the body of your message should be the line
SUBSCRIBE list-name your--full-name
as in
SUBSCRIBE UREXX-L Eric Giguere
You will then be subscribed to the list and messages will start arriving in
your mailbox. To send a message to the list, simply mail it to listname@node,
as in UREXX- L@liverpool.ac.uk. Note the distinction between the LISTSERV
address and the listname address. You can receive help by sending a HELP
message to the LISTSERV address. Note that some of these mailing lists may be
available on Usenet in the form of newsgroups with names starting with
"bit.listserv". Ask your system administrator if you're not sure.
Thanks to Scott Ophof for providing this summary.
ΓòÉΓòÉΓòÉ 2.4.4. Gopher Service ΓòÉΓòÉΓòÉ
Gopher clients may find REXX-related information at the site
gopher.pvv.unit.no (Europe) and index.almaden.ibm.com (N. America).
ΓòÉΓòÉΓòÉ 2.5. Free REXX Products ΓòÉΓòÉΓòÉ
This sections contains information on some free REXX products.
ΓòÉΓòÉΓòÉ 2.5.1. Interpreters ΓòÉΓòÉΓòÉ
There are at least three REXX interpreters available for free on the Internet.
The first two are Unix based and are well-supported by their authors. The third
is an MS-DOS interpreter.
Regina is Anders Christensen's REXX interpreter for various flavours of Unix
and VMS. It is fairly complete and Anders even has an API for developers. It
also apparently can be ported to OS/2. Anders can be reached at
anders@pvv.unit.no. Regina's official home is ftp.pvv.unit.no.
REXX/imc is Ian Collier's REXX interpreter for SunOS, though it has also been
ported to other Unix systems. Ian can be reached at imc@prg.ox.ac.uk.
BREXX is Bill Vlachoudis' REXX interpreter for MS-DOS. The interpreter is not
complete but is quite small. Bill can be reached at
bill@donoussa.physics.auth.gr.
All three interpreters are available for anonymous FTP on rexx.uwaterloo.ca in
the /pub/freerexx directory, each interpreter in its own subdirectory. Regina
and REXX/imc are in source form, BREXX is only available as binary.
ΓòÉΓòÉΓòÉ 2.5.2. REXX-Aware Text Editors ΓòÉΓòÉΓòÉ
Also on rexx.uwaterloo.ca in the /pub/editors directory is the text editor THE
by Mark Hessling (mark@snark.itc.gu.edu.au). THE is a full-featured XEDIT/KEDIT
clone (by XEDIT here we mean the IBM mainframe text editor, not the X Windows
editor xedit) with REXX support. THE is available in versions for OS/2 and
Unix. THE's official home is on ftp.gu.edu.au in /src/THE.
ΓòÉΓòÉΓòÉ 2.6. Commercial REXX Products ΓòÉΓòÉΓòÉ
This Section contains information on some commercial REXX products.
ΓòÉΓòÉΓòÉ 2.6.1. Interpreters ΓòÉΓòÉΓòÉ
REXX interpreters are available commercially for a wide variety of systems and
come standard on some operating platforms such as the Amiga, OS/2 and the IBM
mainframes. The following vendors sell REXX interpreters:
The Workstation Group [Various UNIX platforms, also VMS]
6300 River Road
Rosemont, IL 60018
(800) 228-0255 (US only)
sales@wrkgrp.com
Quercus Systems [DOS, Windows, Windows NT, OS/2]
P.O. Box 2157
Saratoga, CA 95070
(408) 867-7399
(800) 440-5944 (US & Canada)
75300.2450@compuserve.com
Simware [Novell Netware]
2 Gurdwara Road
Ottawa, Ontario
Canada K2E 1A2
(613) 727-1779
IBM also sells REXX interpreters for AIX and Netware.
ΓòÉΓòÉΓòÉ 2.6.2. Compilers ΓòÉΓòÉΓòÉ
Although REXX is usually thought of as an interpreted language, it can also be
compiled. The following vendors all sell REXX compilers:
Dineen Edwards Group [Amiga]
19785 West 12 Mile Road, Suite 305
Southfield, MI 48076-2553
(313) 352-4288
IBM [MVS/TSO and VM/CMS]
Contact your local representative
Systems Center [VM/CMS]
1800 Alexander Bell Drive
Reston, VA 22091
ΓòÉΓòÉΓòÉ 2.6.3. Visual Development Environments ΓòÉΓòÉΓòÉ
There are three REXX-based visual development environments available for OS/2:
VX-REXX WATCOM International
415 Phillip Street
Waterloo, Ontario
Canada N2L 3X2
Phone: (519) 886-3700
Fax: (519) 747-4971
VisPro/REXX HockWare
315 N. Academy St., Suite 100
Cary, NC 27513
Phone: (919) 380-0616
Fax: (919) 380-0757
GpfRexx Gpf Systems
10 Falls Road
Moodus, Conn. 06469
Phone: (203) 873-3300
Fax: (203) 873-3302
ΓòÉΓòÉΓòÉ 2.6.4. REXX-Aware Text Editors ΓòÉΓòÉΓòÉ
Clones of the popular XEDIT editor are available for Unix from the Workstation
Group (see address above) and for DOS and OS/2 from Mansfield Software. Tritus
sells an ISPF/PDF text editor with REXX support for OS/2. One Up sells
SourceLink, an integrated development environment for OS/2 with REXX macro
capabilities. Command Technology sells the SPF/PC editor.
Mansfield Software
P.O. Box 532
Storrs, CT 06268
Phone: (203) 429-8402
Fax: (203) 487-1185
Tritus
3300 Bee Caves Road, Suite 650
Austin, Texas 78746
Phone: (512) 794-5800
Fax: (512) 7940-3833
One Up
1603 LBJ Freeway, Suite 200
Dallas, Texas 75243
Phone: (800) 678-0187
Command Technology
1040 Marina Village Parkway
Alameda, CA 94501
Phone: (800) 336-3320
The OS/2 Enhanced Editor (EPM.EXE), which is bundled with OS/2, also has REXX
support. Use its online help and search for the 'rx' command.
ΓòÉΓòÉΓòÉ 2.6.5. REXX Extensions ΓòÉΓòÉΓòÉ
A number of vendors sell extensions to REXX:
Quercus Systems sells REXXLIB (a collection of over 150 REXX extension
functions), REXXCOMM (a function package for accessing serial ports from
REXX) and REXXTERM (a full-featured asynchronous communications program).
SofTouch Systems sells the GammaTech REXX SuperSet/2, a collection of
over 300 REXX extension functions for OS/2.
dSoft Development sells the dbfREXX function library that lets you read
and write dBASE files from OS/2 REXX.
Quercus Systems
P.O. Box 2157
Saratoga, CA 95070
(408) 867-7399
(800) 440-5944 (US & Canada)
75300.2450@compuserve.com
SofTouch Systems
1300 S. Meridian, Suite 600
Oklahoma City, Okla. 73108-1751
Phone: (405) 947-8080
Fax: (405) 632-6537
dSoft Development
4710 Innsbruk Drive
Houston, Texas 77066
Phone: (405) 360-3045
Fax: (713) 537-0318
ΓòÉΓòÉΓòÉ 2.7. REXX and ANSI ΓòÉΓòÉΓòÉ
The American National Standards Institute (ANSI) sets national standards for
various things in the United States, including programming languages. The X3J18
REXX Standards Committee is currently defining a formal standard for the REXX
language, using Mike Cowlishaw's book as its base document. The Committee meets
3 or 4 times a year and holds ongoing discussions throughout the year by
electronic mail. Mgopher.pvv.unit.noembers of X3J18 are mostly REXX
implementors, but anyone can participate. The Committee intends to release a
draft standard next year. More information can be had from the vice-chair, Neil
Milsted at nfnm@wrkgrp.com. Note that public ANSI documents relating to X3J18
can be had using the LISTSERV service at PSUVM on BITNET or by Gopher to
gopher.pvv.unit.no on the Internet.
ΓòÉΓòÉΓòÉ 2.8. The REXX Language Association ΓòÉΓòÉΓòÉ
The REXX Language Association is an independent organization dedicated to
promoting the use of the REXX programming language. Activities of the RexxLA
include:
Maintaining an electronic mail server where members share information.
Distributing a quarterly newsletter.
Providing electronic resources for access to language expertise, hints
and tips, example programs, product sources, and other valuable
information.
Developing resource guides, both printed and electronic, for
publications, products, training and language experts.
Developing educational, guest speaker, and publicity programs to promote
the use of REXX.
Participating in the work of standards bodies.
Promoting integration of REXX into all operating systems and as the
common scripting language for a wide array of software.
Cooperating with the REXX Symposium in providing an annual conference
forum.
Join today and start reaping the benefits available from an international
consortium of individuals, corporations, vendors, authors and experts.
For more information, contact the REXX Language Association by mail or fax:
RexxLA Membership
6300 North River Road, Suite 501
Rosemont, Illinois 60018
Fax: (708) 696-2277
Or by electronic mail at rexxla@wrkgrp.com.
ΓòÉΓòÉΓòÉ 2.9. The REXX Symposium ΓòÉΓòÉΓòÉ
The REXX Symposium is an annual conference devoted to REXX, attended both by
users and vendors, held at the beginning of May. It is sponsored by the
Stanford Linear Accelerator, with the cooperation of the RexxLA.
ΓòÉΓòÉΓòÉ 2.10. REXX Bibliography ΓòÉΓòÉΓòÉ
Mike Cowlishaw and Linda Green have kindly provided the following partial
bibliography of REXX books.
The REXX Language -- M.F. Cowlishaw
English: ISBN 0-13-780735-X Prentice-Hall, 1985
ISBN 0-13-780651-5 2nd edition, 1990
German: ISBN 3-446-15195-8 Carl Hanser Verlag, 1988
ISBN 0-13-780784-8 P-H International, 1988
Japanese: ISBN 4-7649-0136-6 Kindai-kagaku-sha, 1988
The REXX Reference Summary Handbook -- Dick Goran
ISBN 0-9639854-1-8, CFS Nevada Inc., 1994
Modern Programming Using REXX -- Robert P. O'Hara and
David R. Gomberg
English: ISBN 0-13-597311-2 Prentice-Hall, 1985
ISBN 0-13-579329-5 2nd edition, 1988
REXX in the TSO Environment -- Gabriel F. Gargiulo
ISBN 0-89435-354-3, QED Information Systems Inc.
320 pages, 1990
Using OS/2 REXX -- Gabriel F. Gargiulo
ISBN 0-894-35449-3, QED Publishing Group
Practical Usage of REXX -- Anthony S. Rudd
ISBN 0-13-682790-X, Ellis Horwood (Simon & Schuster), 1990
Using ARexx on the Amiga -- Chris Zamara and Nick Sullivan
ISBN 1-55755-114-6, Abacus Books, 1991
The REXX Handbook -- Edited by Gabe Goldberg and Phil Smith III
ISBN 0-07-023682-8, McGraw-Hill, 1991
Programming in REXX -- Charles Daney
ISBN 0-07-015305-1, McGraw-Hill, 1992
Command Language Cookbook -- Hallett German
ISBN 0-442-00801-5, Van Nostrand Reinhold, 1992
OS/2 2.1 REXX Handbook -- Hallett German
ISBN 0-442-01734-0, Van Nostrand Reinhold, 1994
OS/2 REXX: From Bark to Byte -- Inter. Technical Supp. Org. (IBM)
IBM Document Number GG24-4199-00, 1993
REXX: Advanced Techniques for Programmers -- Peter Kiesel
ISBN 0-07-034600-3, McGraw Hill, 1992
REXX Tools and Techniques -- Barry Nirmal
ISBN 0-89435-417-5, QED Publishing Group, 1993
The ARexx Cookbook -- Merrill Callaway
ISBN 0-96-327730-8, Whitestone, 1992
Writing OS/2 REXX Programs -- Ronny Richardson
ISBN 0-07-052372, McGraw Hill, 1992
Writing VX-REXX Programs -- Ronny Richardson
ISBN 0-07-9111911-5, McGraw Hill, 1994
ΓòÉΓòÉΓòÉ 2.11. Common REXX Coding Errors ΓòÉΓòÉΓòÉ
The following list of common REXX coding errors is derived from a list included
in the online documentation for Watcom VX-REXX.
ΓòÉΓòÉΓòÉ 2.11.1. Blank space where it does not belong ΓòÉΓòÉΓòÉ
In REXX expressions, blank space is interpreted as an implicit concatenation
operator -- the terms are concatenated with a blank in between. As a result,
REXX will interpret many mistyped statements as an expression involving the
blank concatenation operator.
For example, inserting a blank after a function name in a function call changes
the meaning of the expression from:
text_upper = translate( text )
to:
text_upper = "TRANSLATE" || " " || text
Blank space also plays a special role in the PARSE instruction. Compare the
following:
parse arg a b c
parse arg a, b, c
The first line parses the first argument passed to the routine into three
parts, while the second line sets the three variables to the value of the first
three arguments passed to the routine.
ΓòÉΓòÉΓòÉ 2.11.2. Function calls versus the CALL statement ΓòÉΓòÉΓòÉ
When you call a routine that returns a result, you must enclose the parameters
in parentheses:
text = VRGet( "EF_1", "Value" )
Always assign the value of a function to a variable, or use the CALL statement
as described below.
Otherwise REXX will pass the return value to the default host environment,
leading to strange and possibly damaging behaviour on some systems.
If you are calling a routine that does not return a value, or you wish to
ignore the return value, you should use the CALL instruction:
call VRSet "EF_1", "BackColor", "Blue"
Note that there is no comma between the name of the routine and the first
parameter. Note also that parentheses are not used when using the CALL
instruction.
ΓòÉΓòÉΓòÉ 2.11.3. Line continuation ΓòÉΓòÉΓòÉ
The comma is used in REXX to split clauses across two or more lines. For
example:
call foo a, b, c
can also be written as:
call foo a, ,
b, ,
c
It's easy to forget the second comma when breaking a line in the middle of a
function parameter list.
ΓòÉΓòÉΓòÉ 2.11.4. Omitted arguments ΓòÉΓòÉΓòÉ
REXX allows arguments to be omitted. Be careful not to omit arguments by
accident, such as including an unnecessary comma:
call foo , a, b, c
ΓòÉΓòÉΓòÉ 2.11.5. Undefined variables ΓòÉΓòÉΓòÉ
It is not a syntax error to use undefined variables in REXX. Undefined
variables are defined to have their own name translated to uppercase as their
value. As a result it is often difficult to find programming errors that are a
result of using undefined variables.
Some tips:
Add a SIGNAL ON NOVALUE statement to the main section of your programs.
This will cause the system to issue a syntax error if you use an
undefined variable.
Be careful to include the period when referring to stems. The variables
"A" and "A." are unrelated.
Misspelled commands will often be interpreted as undefined variables. The
line:
sy 'hello'
(which should be "say 'hello'") will be interpreted as:
"SY" || " " || 'hello'
and will be send to the default command host for execution.
ΓòÉΓòÉΓòÉ 2.11.6. Using expressions in the tail of a compound symbol ΓòÉΓòÉΓòÉ
The tail of a compound symbol can only be a simple variable, as in:
ok = A.I
Literals are not allowed. For example, the following is interpreted as a
concatenation between "A." and "name":
bad = A."name"
Expressions are also not allowed. You must first assign the value of the
expression to a symbol and then use that symbol:
J = I - 1
ok = A.J
ΓòÉΓòÉΓòÉ 2.12. Frequently Asked Questions ΓòÉΓòÉΓòÉ
Frequently asked questions about REXX.
ΓòÉΓòÉΓòÉ 2.12.1. Is REXX better than <some other language>? ΓòÉΓòÉΓòÉ
Short answer: Yes. No. Maybe. Does it matter?
Long answer: This question wastes a lot of bandwidth in comp.lang.rexx and
other newsgroups. Every language has its good points and its bad points. Some
people love REXX, some people hate it. Use a language that suits your needs.
(Editorial digression: Programming languages are like sexual positions -- some
are more exciting than others, some are more difficult, some are unusual, few
have tried them all, and everyone has a favorite.)
ΓòÉΓòÉΓòÉ 2.12.2. Why does my OS/2 REXX program run more quickly the second time? ΓòÉΓòÉΓòÉ
When you run a REXX CMD file for the first time, a tokenized version will be
stored on disk using the OS/2 extended file attributes. (You can see how big
the tokenized version is by using the /N option on the DIR command.) If a
tokenized version exists AND the file has not been modified, CMD.EXE will use
the tokenized version instead of parsing the source.
Note that there is a 64K limit on the size of an extended attribute entry, so
very large REXX programs do not benefit from this automatic tokenization.
ΓòÉΓòÉΓòÉ 2.12.3. How can I return multiple values from a function? ΓòÉΓòÉΓòÉ
REXX does not provide any support for returning more than a single value from a
function. If you wish to return multiple values, you must devise an alternate
scheme. A simple solution is to concatenate the values together into a single
string and on return from the function use the PARSE instruction or the various
string functions to split the string back into its elements. Don't forget that
you can use non-printable characters (such as '00'x) to separate the data --
REXX will correctly handle such strings. There may also be other alternatives
available to you if you are using an external function library that lets you
store data in separate memory pools or in disk files.
ΓòÉΓòÉΓòÉ 2.12.4. Why does linein, lineout, charin or charout fail? ΓòÉΓòÉΓòÉ
Most versions of REXX (ARexx is an exception) use implicit file opening. That
is, each time you reference a file in a LINEIN, LINEOUT, CHARIN or CHAROUT
function, REXX will open the file for reading or writing if the file is not
already open. However, some operating systems like DOS and OS/2 impose limits
on the number of files that can be open simultaneously, usually around 20 or
so. After the limit has been reached, any further attempts to open another
file will fail. That is why it is always good practice to close a file when
you're done with it. In OS/2 this is done using the STREAM function, as
follows:
call stream "c:\foo.out", "command", "close"
The STREAM function can also be used to open files, query their sizes and seek
into the file. Consult your REXX documentation for specific instructions for
your interpreter.
ΓòÉΓòÉΓòÉ 2.12.5. How do I iterate over all the tails in a stem variable? ΓòÉΓòÉΓòÉ
One of the features REXX lacks is a function to return a list of defined tails.
There are external libraries that provide functions to do so, but if that is
not an option then the only solution is to maintain your own list of tails in a
string and use the PARSE instruction or the WORDS function to traverse the
list.
ΓòÉΓòÉΓòÉ 2.12.6. How do I REXX-enable my application? ΓòÉΓòÉΓòÉ
REXX-enabling an application means being able to run REXX macros within an
application. This information is very system-specific, so the best place to
start is with the documentation provided with the REXX interpreter.
For OS/2, there are several sources of information. The most basic information
is found in the OS/2 Toolkit, which includes the REXXSAA.H header file and the
REXX Reference online document. The REXX Report (see above) includes a couple
of articles on the subject. Sample source code comes with the OS/2 Toolkit and
is also available on rexx.uwaterloo.ca in the directory /pub/os2/vxrexx as
VX-REXX Tech Notes #1 and #7 (vxtech01.zip, vxtech07.zip -- neither tech note
requires that you own VX-REXX). OS/2 technical conferences such as ColoradOS/2
or the IBM Technical Interchanges often includes sessions on this topic. For
ARexx, a book was available from Commodore, but with the latter's demise it is
unclear whether the book is still available.
ΓòÉΓòÉΓòÉ 2.12.7. How do I do inter-process communication in REXX? ΓòÉΓòÉΓòÉ
Again, this is system-specific. The ARexx interpreter is built on a messaging
model, making it very simple to do inter-process communication, but the OS/2
REXX interpreter has no such features, though in some cases queues can be used
to achieve the desired effect.
ΓòÉΓòÉΓòÉ 2.12.8. How do I use global variables in my REXX programs? ΓòÉΓòÉΓòÉ
The scope of variables is controlled by the PROCEDURE instruction. If a routine
is declared with the PROCEDURE instruction, only those variables exposed using
the EXPOSE instruction are available to the routine. If no PROCEDURE
instruction is used, all of the caller's variables are available to the callee.
Here is a simple example:
a = 10
b = 20
call first
call second
call third
exit
first:
say "first -- a is" a "b is" b
return
second: procedure
say "second -- a is" a "b is" b
return
third: procedure expose a
say "third -- a is" a "b is" b
b = 30
call first
return
Running this program yields the following output:
first -- a is 10 b is 20
second -- a is A b is B
third -- a is 10 b is B
first -- a is 10 b is 30
Use the PROCEDURE instruction to keep variables local to a procedure, using
EXPOSE to explicitly expose any "global" variables. The only catch is that you
have to make sure you expose the variables inside every procedure. One way to
define and use global variables is to use a stem called "Globals." and define
all your procedures like this:
Foo: procedure expose Globals.
Then at the top of you program initialize the Globals stem and assign
appropriate values to your global variables:
Globals. = ''
Globals.!NeedToSave = 0
Globals.!TmpDir = "D:\TMP"
The tail names in this example are all prefixed with '!', though you could also
use an underscore ('_'). This is just a convention used to avoid this kind of
problem:
Globals.TmpDir = "D:\TMP"
call Foo
say Globals.TmpDir
exit
Foo: procedure expose Globals.
tmpdir = "foo"
Globals.TmpDir = tmpdir
return
It's a subtle bug that has to do with how REXX interprets stem tails.
ΓòÉΓòÉΓòÉ 3. The REXX Tutorial for Complete Beginners ΓòÉΓòÉΓòÉ
This document is being ported from a UNIX version for IMC Unix. It was written
by Ian Collier. If you find any mistakes or unixisms in it, please contact Paul
Prescod: papresco@undergrad.math.uwaterloo.ca.
The OS/2 .inf version of this tutorial was done by Dirk Terrell:
terrell@astro.ufl.edu
ΓòÉΓòÉΓòÉ 3.1. Creating a Rexx program ΓòÉΓòÉΓòÉ
Many programmers start by writing a program which displays the message "Hello
world!". Here is how to do that in Rexx...
Write a file called "hello.cmd" containing the following text. Use any text
editor, e, edit, or epm will do. To do this in the WorkPlace shell, just go to
the templates folder and drag a data file object out of it. Bring up its
settings and rename it to "hello.cmd." The text, as with all example text in
this guide, starts at the first indented line and ends at the last. The four
spaces at the start of each line of text should not be entered (this is very
important!):
/* This program says "Hello world!" */
say "Hello world!"
This program consists of a comment saying what the program does, and an
instruction which does it. "say" is the Rexx instruction which displays data on
the terminal.
The method of executing a Rexx program varies greatly between implementations.
On OS/2, you would just type "hello.cmd" in that file's directory, or double
click on its icon in the WorkPlace Shell.
When you execute your first Rexx program using the method detailed above, you
should see the message "Hello world!" appear on the screen.
ΓòÉΓòÉΓòÉ 3.2. Doing arithmetic ΓòÉΓòÉΓòÉ
Rexx has a wide range of arithmetic operators, which can deal with very high
precision numbers. Here is an example of a program which does arithmetic. Make
a file called "arith.cmd" containing the following:
/* This program inputs a number and does some calculations on it */
pull a
b=a*a
c=1/a
d=3+a
e=2**(a-1)
say 'Results are:' a b c d e
in a positive integer. Here is a sample run:
input: 5 output: Results are: 5 25 0.2 8 16
The results you see are the original number (5), its square (25), its
reciprocal (0.2), the number plus three (8) and two to the power of one less
than the number (16).
This example illustrates several things:
variables: in this example a, b, c, d and e are variables. You can assign
a value to a variable by typing its name, "=", and a value, and you can
use its value in an expression simply by typing its name.
input: by typing "pull a" you tell the interpreter to ask the user for
input and to store it in the variable a.
arithmetic: the usual symbols (+ - * /) as well as ** (to-power) were
used to perform calculations. Parentheses (or "brackets") were used to
group together an expression, as they are in mathematics.
string expressions: the last line of the program displays the results by
saying the string expression 'Results are:' a b c d e This has six
components: the string constant 'Results are:' and the five variables.
These components are attached together with spaces into one string
expression, which the "say" command then displays on the terminal. A
string constant is any sequence of characters which starts and ends with
a quotation mark - that is, either " or ' (it makes no difference which
you use, as long as they are both the same).
If you supply the number 6 as input to the program, you should notice that the
number 1/6 is given to nine significant figures. You can easily change this.
Edit the program and insert before the second line:
numeric digits 25
If you run this new program you should see that 25 significant figures are
produced. In this way you can calculate numbers to whatever accuracy you
require, within the limits of the machine.
At this point it seems worth a mention that you can put more than one
instruction on a line in a Rexx program. You simply place a semicolon between
the instructions, like this:
/* This program inputs a number and does some calculations on it */
pull a; b=a*a; c=1/a; d=3+a; e=2**(a-1); say 'Results are:' a b c d e
Needless to say, that example went a bit over the top...
ΓòÉΓòÉΓòÉ 3.3. Errors ΓòÉΓòÉΓòÉ
Suppose you ignored the instructions of the previous section and typed a
non-integer such as 3.4 as input to the program. Then you would get an error,
because the ** (to-power) operator is only designed to work when the second
parameter (that is, the power number) is an integer. You might see this, for
example:
3.4
6 +++ e=2**(a-1)
Error 26 running arith.cmd, line 6: Invalid whole number
Or if you typed zero, you might see the following (because you cannot divide by
zero):
rexx arith
0
4 +++ c=1/a
Error 42 running arith.cmd, line 4: Arithmetic overflow or underflow
Perhaps most interestingly, if you type a sequence of characters which is not a
number, you might see this. It does not complain about the characters you
entered, but at the fact that the program tries to use it as a number.
rexx arith
hello
3 +++ b=a*a
Error 41 running arith.cmd, line 3: Bad arithmetic conversion
In each case, you have generated a "syntax error" (it is classified as a syntax
error, even though the problem was not directly related to the program's
syntax). What you see is a "traceback" starting with the line which caused the
error (no other lines are listed in this traceback, because we have not yet
considered any Rexx control structures), and a description of the error. This
information should help you to determine where the error occurred and what
caused it. More difficult errors can be traced with the "trace" instruction
(see later).
ΓòÉΓòÉΓòÉ 3.4. Untyped data ΓòÉΓòÉΓòÉ
In the previous section, you found that you could input either a number or a
sequence of letters and store it in the variable a, although arithmetic can
only be performed on numbers. That is because data in Rexx are untyped. In
other words, the contents of a variable or the result of an expression can be
any sequence of characters. What those characters are used for matters only to
you, the programmer. However, if you try to perform arithmetic on a random
sequence of characters you will generate a syntax error, as shown in the
previous section.
You have seen that you can add strings together by placing a space in between
them. There are two other ways: the abuttal and the concatenation operator. An
abuttal is simply typing the two pieces of data next to each other without a
space. This is not always appropriate: for example you cannot type an "a" next
to a "b", because that would give "ab", which is the name of another unrelated
variable. Instead, it is safer to use the concatenation operator, ||. Both
these operations concatenate the strings without a space in between. For
example:
/* demonstrates concatenation and the use of untyped data */
a='A string'
b='123'
c='456'
d=a":" (b||c)*3
say d
The above program says "A string: 370368". This is because (b||c) is the
concatenation of strings b and c, which is "123456". That sequence of
characters happens to represent a number, and so it can be multiplied by 3 to
give 370368. Finally, that is added with a space to the concatenation of a with
":" and stored in d.
ΓòÉΓòÉΓòÉ 3.5. More on variables ΓòÉΓòÉΓòÉ
The previous examples only used single-letter variable names. In fact it is
more useful to have whole words as variable names, and Rexx allows this up to
an implementation maximum (which should be suitably large, e.g. 250
characters). Moreover, not only letters but numbers and the six characters
"@#$!?_" are allowed in variable names - or "symbols", as they are called in
the literature. These are valid symbols:
fred
Dan_Yr_0gof
HI!
The case of letters is unimportant, so that for example "Hello", "HELLO" and
"hellO" all mean the same.
If you use a symbol in an expression when it has not been previously given a
value, that does not cause an error (unless "signal on novalue" is set - see
later). Instead, it just results in its own name translated into upper case.
/* A demonstration of simple symbols */
foo=3
bar="Characters"
say foo bar':' hi!
This program says "3 Characters: HI!".
As well as "simple symbols", which are variables like the above, there are
arrays. Any ordinary variable name can also be used as the name of an array:
/* This program uses an array. */
pull a
array.1=a
array.2=a*a
array.3=a**3
say array.1 array.2 array.3 array.1+array.2+array.3
An element of an array is accessed by typing the array name, a dot, and the
element number. The array name and the dot are together known as the "stem" of
the array. The name of the element is called a "compound symbol". Note that an
array does not have to be declared before it is used.
In fact not only numbers, but strings and variable names may be used as
element names. Also, an element name can consist of two or more parts
separated by dots, so giving two or more dimensional arrays.
/* This program uses an array with various elements */
book.1.author="M. F. Cowlishaw"
book.1.title="The REXX Language, a practical approach to programming"
book.1.pub="Englewood Cliffs 1985"
book.2.author="A. S. Rudd"
book.2.title="Practical Usage of REXX"
book.2.pub="Ellis Horwood 1990"
/* insert lots more */
say "Input a book number"
pull i
say "Author: " book.i.author
say "Title: " book.i.title
say "Publisher:" book.i.pub
In the above program, an array called "book" is created, containing a number
of records each with elements AUTHOR, TITLE and PUB. Notice that these three
uppercase names are produced by symbols "author", "title" and "pub", because
those symbols have not been given values. When a book number i has been input,
the elements of the ith record are printed out. It is not an error to
reference an undefined element of an array. If you type "3" into the above
program, you will see this:
Input a book number
3
Author: BOOK.3.AUTHOR
Title: BOOK.3.TITLE
Publisher: BOOK.3.PUB
As before, if a compound symbol has not been given a value, then its name is
used instead.
There is a way to initialise every element of an array: by assigning a value
to the stem itself. Edit the above program and insert after the comment line:
book.="Undefined"
This gives every possible element of the array the value "Undefined", so that
if you again type "3" you will see the following:
Input a book number
3
Author: Undefined
Title: Undefined
Publisher: Undefined
ΓòÉΓòÉΓòÉ 3.6. Functions ΓòÉΓòÉΓòÉ
The Online Rexx Summary contains a list of the functions which are available in
Rexx. Each of these functions performs a specific operation upon the
parameters. For example,
/* Invoke the date function with various parameters */
say date("W")',' date()
This might say, for example, "Friday, 22 May 1992". A function is called by
typing its name immediately followed by "(". After that come the parameters, if
any, and finally a closing ")". In the above example, the "date" function is
called twice. The value of date("W") is the name of the weekday, and the value
of date() is the date in "default" format.
ΓòÉΓòÉΓòÉ 3.7. Conditionals ΓòÉΓòÉΓòÉ
It is time to use some Rexx control structures. The first of these will be the
conditional. Here is an example:
/* Use a conditional to tell whether a number is less than 50 */
pull a
if a<50 then say a "is less than 50"
else say a "is not less than 50"
The program is executed in the manner in which it reads - so, if a is less than
50 then the first instruction is executed, else the second instruction is
executed.
The "a<50" is a conditional expression. It is like an ordinary expression (in
fact conditional expressions and ordinary numeric expressions are
interchangeable), but it contains a comparison operator.
There are many comparison operators, as follows:
= (equal to)
< (less than)
> (greater than)
<= (less or equal)
>= (greater or equal)
<> (greater or less)
\= (not equal)
\> (not greater)
\< (not less)
All the above operators can compare numbers, deciding whether one is equal to,
less than, or greater than the other. They can also compare non-numeric
strings, first stripping off leading and trailing blanks.
There are analogous comparison operators to these for comparing strings
strictly. The main difference between them is that 0 is equal to 0.0,
numerically speaking, but the two are different if compared as strings. The
other difference is that the strict operators do not strip blanks before
comparing. The strict operators are
== (equal to)
<< (less than)
>> (greater than)
<<= (less or equal)
>>= (greater or equal)
\== (not equal)
\>> (not greater)
\<< (not less)
Conditional expressions may be combined with the boolean operators:
& (and)
| (or)
&& (xor)
They may also be reversed with the \ (not) operator.
/* Decide what range a number is in */
pull a
if a>0 & a<10 then say "1-9"
if a\<10 & a<20 then say "10-19"
if \ (a<20 | a>=30) then say "20-29"
if a<=0 | a>=30 then say "Out of range"
As well as demonstrating the boolean and comparison operators, this program
shows that the "else" clause is not required to be present.
The above program may also be written using Rexx's other conditional
instruction, "select":
/* Decide what range a number is in */
pull a
select
when a>0 & a<10 then say "1-9"
when a\<10 & a<20 then say "10-19"
when \ (a<20 | a>=30) then say "20-29"
otherwise say "Out of range"
end
The "select" instruction provides a means of selecting precisely one from a
list of conditional instructions, with the option of providing a list of
instructions to do when none of the above were true. The difference is that if
no part of a "select" instruction can be executed then a syntax error results,
whereas it is OK to miss out the "else" part of an "if" instruction.
Only one instruction may be placed after "then", "else" and "when", but Rexx
provides a way of bracketing instructions together so that they can be treated
as a single instruction. To do this, place the instruction "do" before the
list of instructions and "end" after it.
/* execute some instructions conditionally */
pull a
if a=50 then
do
say "Congratulations!"
say "You have typed the correct number."
end
else say "Wrong!"
If you wish for one of the conditional instructions to do "nothing", then you
must use the instruction "nop" (for "no operation"). Simply placing no
instructions after the "then", "else" or "when" will not work.
ΓòÉΓòÉΓòÉ 3.8. Loops ΓòÉΓòÉΓòÉ
Rexx has a comprehensive set of instructions for making loops, using the words
"do" and "end" which you met briefly in the previous section.
ΓòÉΓòÉΓòÉ 3.8.1. Counted loops ΓòÉΓòÉΓòÉ
The instructions within a counted loop are executed the specified number of
times:
/* Say "Hello" ten times */
do 10
say "Hello"
end
A variation of the counted loop is one which executes forever:
/* This program goes on forever until the user halts it */
do forever
nop
end
ΓòÉΓòÉΓòÉ 3.8.2. Control loops ΓòÉΓòÉΓòÉ
Control loops are like counted loops, but they use a variable (called the
control variable) as a counter. The control variable may count simply in steps
of 1:
/* Count to 20 */
do c=1 to 20
say c
end
or in steps of some other value:
/* Print all multiples of 2.3 not more than 20 */
do m=0 to 20 by 2.3
say m
end
It may take a specific number of steps:
/* Print the first six multiples of 5.7 */
do m=0 for 6 by 5.7
say m
end
or it may go on forever:
/* Print all the natural numbers */
do n=0
say n
end n
The "n" at the end of this last example is optional. At the end of any
controlled loop, the name of the control variable may be placed after the
"end", where it will be checked to see if it matches the control variable.
ΓòÉΓòÉΓòÉ 3.8.3. Conditional loops ΓòÉΓòÉΓòÉ
A set of instructions may be executed repeatedly until some condition is true.
For example,
/* I won't take no for an answer */
do until answer \= "NO"
pull answer
end
Alternatively, they may be executed as long as some condition is true:
/* It's OK to repeat this as long as there is no error */
do while error=0
pull a
if a="ERROR" then error=1
else say a
end
Note that in this example, if there is already an error to start with then the
set of instructions will not be executed at all. However in the previous
example the instructions will always be executed at least once.
ΓòÉΓòÉΓòÉ 3.8.4. Controlled conditional loops ΓòÉΓòÉΓòÉ
It is possible to combine forms a or b with form c mentioned above, like this:
/* I won't take no for an answer unless it is typed three times */
do 3 until answer \= "NO"
pull answer
end
or this:
/* input ten answers, but stop when empty string is entered */
do n=1 to 10 until ans==""
pull ans
a.n=ans
end
The "iterate" and "leave" instructions allow you to continue with, or to leave,
a loop respectively. For example:
/* input ten answers, but stop when empty string is entered */
do n=1 to 10
pull a.n
if a.n=="" then leave
end
/* print all integers from 1-10 except 3 */
do n=1 to 10
if n=3 then iterate
say n
end
If a symbol is placed after the instructions "iterate" or "leave", then you can
iterate or leave the loop whose control variable is that symbol.
/* Print pairs (i,j) where 1 <= i,j <= 5, except (2,j) if j>=3 */
do i=1 to 5
do j=1 to 5
if i=2 & j=3 then iterate i /* or "leave j" would work,
or just "leave" */
say "("i","j")"
end
end
ΓòÉΓòÉΓòÉ 3.9. Parsing ΓòÉΓòÉΓòÉ
The following program examines its arguments:
/* Parse the arguments */
parse arg a.1 a.2 a.3 a.4 .
do i=1 to 4
say "Argument" i "was:" a.i
end
Execute it as usual, except this time type "alpha beta gamma delta" after the
program name on the command line, for example:
arguments alpha beta gamma delta
The program should print out:
Argument 1 was: alpha
Argument 2 was: beta
Argument 3 was: gamma
Argument 4 was: delta
The argument "alpha beta gamma delta" has been parsed into four components. The
components were split up at the spaces in the input. If you experiment with the
program you should see that if you do not type four words as arguments then the
last components printed out are empty, and that if you type more than four
words then the last component contains all the extra data. Also, even if
multiple spaces appear between the words, only the last component contains
spaces. This is known as "tokenisation".
It is not only possible to parse the arguments, but also the input. In the
above program, replace "arg" by "pull". When you run this new program you will
have to type in some input to be tokenised.
Replace "parse" with "parse upper" in the program. Now, when you supply input
to be tokenised it will be uppercased.
"arg" and "pull" are, respectively, abbreviations for the instructions "parse
upper arg" and "parse upper pull". That explains why the "pull" instruction
appeared in previous examples, and why it was that input was always uppercased
if you typed letters in response to it.
Other pieces of data may be parsed as well. "parse source" parses information
about how the program was invoked, and what it is called. "parse version"
parses information about the interpreter itself. However, the two most useful
uses of the parse instruction are "parse var [variable]" and "parse value
[expression] with". These allow you to parse arbitrary data supplied by the
program.
For example,
/* Get information about the date and time */
d=date()
parse var d day month year
parse value time() with hour ':' min ':' sec
The last line above illustrates a different way to parse data. Instead of
tokenising the result of evaluating time(), we split it up at the character
':'. Thus, for example, "17:44:11" is split into 17, 44 and 11.
Any search string may be specified in the "template" of a "parse" command. The
search string is simply placed in quotation marks, for example:
parse arg first "beta" second "delta"
This line assigns to variable first anything which appears before "beta", and
to second anything which appears between "beta" and "delta". If "beta" does not
appear in the argument string, then the entire string is assigned to first, and
the empty string is assigned to "second". If "beta" does appear, but "delta"
does not, then everything after "beta" will be assigned to second.
It is possible to tokenise the pieces of input appearing between search
strings. For example,
parse arg "alpha" first second "delta"
This tokenises everything between "alpha" and "delta" and places the tokens in
first and second.
Placing a dot instead of a variable name during tokenising causes that token to
be thrown away:
parse pull a . c . e
This keeps the first, third and last tokens, but throws away the second and
fourth. It is often a good idea to place a dot after the last variable name,
thus:
parse pull first second third .
Not only does this throw away the unused tokens, but it also ensures that none
of the tokens contain spaces (remember, only the last token may contain spaces;
this is the one we are throwing away).
Finally, it is possible to parse by numeric position instead of by searching
for a string. Numeric positions start at 1, for the first character, and range
upwards for further characters.
parse var a 6 piece1 +3 piece2 +5 piece3
The value of piece1 will be the three characters of a starting at character 6;
piece2 will be the next 5 characters, and piece3 will be the rest of a.
ΓòÉΓòÉΓòÉ 3.10. Interpret ΓòÉΓòÉΓòÉ
Suppose you have a variable "inst" which contains the string "a=a+1". You can
execute that string as an instruction, by typing:
interpret inst
The interpret instruction may be used to accept Rexx instructions from the
user, or to assign values to variables whose names are not known in advance.
/* Input the name of a variable, and set that variable to 42 */
parse pull var
interpret var "=" 42
ΓòÉΓòÉΓòÉ 3.11. The Stack ΓòÉΓòÉΓòÉ
Rexx has a data stack, which is accessed via the "push", "queue" and "pull"
instructions. The "pull" instruction (or in full, "parse pull") inputs data
from the user as we have seen before. However, if there is some data on the
stack then it will pull that instead.
/* Access the Rexx stack */
queue "Hello!"
parse pull a /* a contains "Hello!" */
parse pull b /* b is input from the user */
push "67890"
push "12345"
parse pull c /* c contains "12345" */
/* there is one item left on the stack */
The difference between "push" and "queue" is that when the items are pulled off
the stack, the items which were queued appear in the same order that they were
queued (FIFO, or first in, first out), and the items which were pushed appear
in reverse order (LIFO, or last in, first out).
ΓòÉΓòÉΓòÉ 3.12. Subroutines and functions ΓòÉΓòÉΓòÉ
The following program defines an internal function, and calls it with some
data:
/* Define a function */
say "The results are:" square(3) square(5) square(9)
exit
square: /* function to square its argument */
parse arg in
return in*in
The output from this program should be: "The results are: 9 25 81"
When Rexx finds the function call "square(3)", it searches the program for a
label called "square". It finds the label on line 5 - the name followed by a
colon. The interpreter executes the code which starts at that line, until it
finds the instruction "return". While that code is being executed, the
arguments to the function can be determined with "parse arg" in the same way as
the arguments to a program. When the "return" instruction is reached, the value
specified is evaluated and used as the value of "square(3)".
The "exit" instruction in this program causes it to finish executing instead of
running into the function.
A function which takes multiple arguments may be defined, simply by separating
the arguments with a comma. That is, like this:
/* Define a function with three arguments */
say "The results are:" condition(5,"Yes","No") condition(10,"X","Y")
exit
condition: /* if the first argument is less than 10, return the second,
else return the third. */
parse arg c,x,y
if c<10 then return x
else return y
A subroutine is similar to a function, except that it need not give a value
after the "return" instruction. It is called with the "call" instruction.
/* Define a subroutine to print a string in a box, then call it */
call box "This is a sentence in a box"
call box "Is this a question in a box?"
exit
box: /* Print the argument in a box */
parse arg text
say "+--------------------------------+"
say "|"centre(text,32)"|" /* centre the text in the box */
say "+--------------------------------+"
return
It is possible to call a function, even a built-in function, as if it were a
subroutine. The result returned by the function is placed into the variable
called "result".
/* print the date, using the "call" instruction */
call date "N"
say result
If a function or subroutine does not need to use the variables which the caller
is using, or if it uses variables which the caller does not need, then you can
start the function with the "procedure" instruction. This clears all the
existing variables away out of sight, and prepares for a new set of variables.
This new set will be destroyed when the function finishes executing. The
following program calculates the factorial of a number recursively:
/* Calculate factorial x, that is, 1*2*3* ... *x */
parse pull x .
say x"!="factorial(x)
exit
factorial: /* calculate the factorial of the argument */
procedure
parse arg p
if p<3 then return p
else return factorial(p-1) * p
The variable p which holds the argument to funtion factorial is unaffected
during the calculation of factorial(p-1), because it is hidden by the
"procedure" instruction.
If the subroutine or function needs access to just a few variables, then you
can use "procedure expose" followed by the list of variable names to hide away
all except those few variables.
You can write functions and subroutines which are not contained in the same
Rexx program. In order to do this, write the function and save it into a file
whose name will be recognised by the interpreter. This type of function is
called an "external" function, as opposed to an "internal" function which can
be found inside the currently running program.
If you want to call your function or subroutine using "call foobar" or
"foobar()", then you should save it in a file named "foobar.cmd" which can be
found in the current directory or in your path.
The "procedure" instruction is automatically executed before running your
external function, and so it should not be placed at the start of the function.
It is not possible for an external function to access any of its caller's
variables, except by the passing of parameters.
For returning from external functions, as well as the "return" instruction
there is "exit". The "exit" instruction may be used to return any data to the
caller of the function in the same way as "return", but "exit" can be used
return to the caller of the external function even when it is used inside an
internal function (which is in turn in the external function). "exit" may be
used to return from an ordinary Rexx program, as we have seen. In this case, a
number may be supplied after "exit", which will be used as the exit code of the
interpreter.
ΓòÉΓòÉΓòÉ 3.13. Executing commands ΓòÉΓòÉΓòÉ
Rexx can be used as a control language for a variety of command-based systems.
The way that Rexx executes commands in these systems is as follows. When Rexx
encounters a program line which is nether an instruction nor an assignment, it
treats that line as a string expression which is to be evaluated and passed to
the environment. For example:
/* Execute a given command upon a set of files */
parse arg command
command "file1"
command "file2"
command "file3"
exit
Each of the three similar lines in this program is a string expression which
adds the name of a file (contained in the string constants) to the name of a
command (given as a parameter). The resulting string is passed to the
environment to be executed as a command. When the command has finished, the
variable "rc" is set to the exit code of the command.
The environment to which a command is given varies widely between systems, but
in most systems you can select from a set of possible environments by using the
"address" instruction.
ΓòÉΓòÉΓòÉ 3.14. Signal ΓòÉΓòÉΓòÉ
Where other programming languages have the "goto" command, Rexx has "signal".
The instruction "signal label" makes the program jump to the specified label.
However, once this has been done, it is not possible to resume any "select" or
"do" control structures that have recently been entered. Thus the main use of
"signal" is to jump to an error handling routine when something goes wrong, so
that the program can clean up and exit.
There is a much more useful way of using "signal", however. That is to trap
certain kinds of error condition. The conditions which may be trapped include:
"syntax" (that is, any syntax error), "error" (any environment command that
results in a non-zero exit code), "halt" (when the user interrrupts execution)
and "novalue" (which is when a symbol is used without having been given a
value).
Error trapping for one of these conditions is turned on by
signal on
and is turned off by
signal off
When one of these conditions occurs, the program immediately signals to a label
whose name is the same as that of the condition. Trapping is turned off, so
another "signal on" will be required if you want to continue to trap that
condition.
Whenever a "signal" occurs, the variable "sigl" is set to the line number of
the instruction which caused the jump. If the signal was due to an error trap,
then the variable "rc" will be set to an error code.
/* This program goes on forever until someone stops it. */
say "Press Control-C to halt"
signal on halt
do i=1
say i
do 10000
end
end
halt:
say "Ouch!"
say "Died at line" sigl
ΓòÉΓòÉΓòÉ 3.15. Tracing ΓòÉΓòÉΓòÉ
Full details of how to use Rexx's tracing facility are contained in the online
rexx reference.
If a program goes wrong and you need more information in order to work out why,
then Rexx provides you with the ability to trace all or part of your program to
see what is happening.
The most common form of tracing is turned on by
trace r
This causes each instruction to be listed before it is executed. Also, it
displays the results of each calculation after it has been found.
Another useful trace command is:
trace ?a
This makes the interpreter list each instruction and stop before it is
executed. You can execute the instruction by pressing return, or you can type
in some Rexx to be interpreted, after which the interpreter will pause again.
You can use this to examine the program's variables and so forth.
If you want the interpreter to stop only when passing a label, use:
trace ?l
This is useful for setting breakpoints in the program, or for making the
program stop at a function call.
ΓòÉΓòÉΓòÉ 3.16. The REXX Summary ΓòÉΓòÉΓòÉ
ΓòÉΓòÉΓòÉ 3.16.1. Summary of expression syntax ΓòÉΓòÉΓòÉ
Strings: "String constants" 'enclosed in quotes'
Hex strings: '616263 64'x
Numbers: 123.4e-56
Constant symbols: .abc 1d4 7!
Simple symbols: foo bar xyz3
Stems: array.
Compound symbols: c.3 element.bar.45
Operators: arithmetic: + - * / ** (to-power) % (div) // (mod)
string: [abuttal] [space] || (concatenation)
logical: \ (not) & (and) | (or) && (xor)
comparison: = > < <> <= >= \> \< \=
== >> << <<= >>= \>> \<< \== (strong comparison)
Function calls: fn(1,2,3) bar(,5) 'DATE'()
ΓòÉΓòÉΓòÉ 3.16.2. Summary of instructions ΓòÉΓòÉΓòÉ
/* this is a comment */
expression - execute a host command
symbol=value - assignment
ADDRESS [VALUE] [environment] - change the current environment
ADDRESS environment command - execute a command in an environment
CALL name [arg][,[arg],...]] - call a function or subroutine
CALL ON condition [NAME symbol]- turn on condition handling
CALL OFF condition - turn off condition handling
condition = ERROR | FAILURE | NOTREADY | HALT
DO [ symbol=start [TO finish] ] [WHILE expression_w]
[ [BY step ] ]
[ [FOR count ] ] [UNTIL expression_u]
[ expression_c ] [FOREVER ]
- block or repetitive block instruction
DROP symbol [symbol...] - de-assignment
END [symbol] - end block or repetitive block instruction
EXIT [expression] - exit program or external function
IF expression [;] THEN [;] statement [ ; ELSE [;] statement]
- conditional instruction
INTERPRET expression - dynamically execute a string
ITERATE [symbol] - continue repetitive block
LEAVE [symbol] - leave repetitive block
NOP - do nothing
NUMERIC DIGITS n - set parameters for numeric formatting
NUMERIC FUZZ n
NUMERIC FORM SCIENTIFIC
| ENGINEERING
| "string constant"
| [VALUE] expression
OPTIONS expression - Control system-dependent things
[PARSE [UPPER]] ARG template
[PARSE [UPPER]] PULL [template]
PARSE [UPPER] LINEIN [template]
PARSE [UPPER] SOURCE template
PARSE [UPPER] VERSION template
PARSE [UPPER] NUMERIC template
PARSE [UPPER] VAR symbol template
PARSE [UPPER] VALUE expression WITH template
template -> [firstPosition] assignments [assignments]
assignments -> [nextPosition] varlist [stopPosition]
varlist -> varname ' ' [varlist]
varname -> "non-constant symbol"
| '.'
firstPosition -> position
nextPosition -> position [nextPosition]
stopPosition -> position
position -> searchPosition
| absPosition
| relPosition
| '(' "expression" ')'
searchPosition -> "string constant"
absPosition -> "integer"
| '=' numexpr
relPosition -> '+' numexpr
| '-' numexpr
numexpr -> "integer"
| '(' "integer expression" ')'
PROCEDURE - hide the caller's symbols
PROCEDURE EXPOSE var1 [var2...]
PROCEDURE HIDE var1 [var2...]
PUSH expression - stack a value in LIFO order
QUEUE expression - stack a value in FIFO order
RETURN [value] - return from a function or subroutine
SAY [expression] - echo data
SAYN expression - echo data without newline
SELECT [expression]
WHEN expression THEN statements
WHEN expression THEN statements
...
[OTHERWISE statements]
END [SELECT] - switch on a list of conditions
SIGNAL [VALUE] name - jump to a label
SIGNAL ON condition [NAME symbol] - turn on condition handling
SIGNAL OFF condition - turn off condition handling
condition = ERROR | FAILURE | NOTREADY | HALT | SYNTAX | NOVALUE
TRACE [symbol] - control program tracing. Values are:
TRACE "string" A (all clauses) C (commands) E (error)
TRACE VALUE expression F (failure) I (intermediate values)
L (labels) N (normal, =F) O (off)
R (results)
ΓòÉΓòÉΓòÉ 3.16.3. Summary of builtin functions ΓòÉΓòÉΓòÉ
ΓòÉΓòÉΓòÉ 3.16.3.1. Standard functions ΓòÉΓòÉΓòÉ
ABBREV(information,info[,length]) - check for valid abbreviations
ABS(number) - return the absolute value
ADDRESS() - return the current environment
ARG([n][,opt]) - return or test an argument
BITAND(string1,string2[,pad])
BITOR (string1,string2[,pad]) - combine two strings with bit operations
BITXOR(string1,string2[,pad])
B2D(binary)
B2X(binary)
D2B(decimal)
C2X(string)
C2D(string[,n])
D2C(decimal[,n]) - convert between data formats
D2X(decimal[,n])
X2B(hex)
X2C(hex)
X2D(hex)
CENTER(s,n[,pad]) - centre a string in a field
CENTRE(s,n[,pad])
COMPARE(s1,s2[,pad]) - compare two strings
CONDITION([option]) - return information about trapped condition
Option can be (default I):
C (condition name) D (description)
I (instruction) S (status)
COPIES(s,n) - replicate a string
DATATYPE(string[,type]) - test datatype. Type can be:
A (alphanumeric) B (bits) L (lowercase)
M (mixed case) N (number) S (symbol chars)
U (upper case) W (whole number) X (hex)
DATE([format]) - get date. Format can be:
B (base date - days since 1/1/1 AD)
C (days in century) D (days in year)
E (European) J (Julian) M (month name)
N (normal: dd Mon yyyy) O (ordered)
S (sorted) U (USA) W (day of week)
DELSTR(string,n[,length]) - delete substring
DELWORD(string,n[,length]) - delete words
DIGITS() - NUMERIC DIGITS setting
ERRORTEXT(i) - Rexx error message
FORM() - NUMERIC FORM setting
FORMAT(number [,[before] [,[after] [,[expp] [,expt]]]] )
- format a number as specified
FUZZ() - NUMERIC FUZZ setting
INSERT(new,target[,[n][,[length][,pad]]]) - insert new string into target
JUSTIFY(s,n[,pad]) - justify text to given width
LASTPOS(needle,haystack[,start]) - find last occurrence of a string
LEFT(string,num[,pad]) - return an initial substring
LENGTH(string) - find the length of a string
LINESIZE() - find the terminal width
MAX(number[,number...]) - find the maximum of a set
MIN(number[,number...]) - find the minimum of a set
OVERLAY(new,target[,[n][,[length][,pad]]]) - overlay new string on to target
POS(needle,haystack[,start]) - find the first occurance of a string
QUEUED() - return the number of items on the stack
RANDOM([min][,[max][,seed]]) - return a random number
REVERSE(string) - find the reverse of a string
RIGHT(string,num[,pad]) - return a final substring
SOURCELINE([i]) - return a line of the source program
SPACE(s[,[n][,pad]]) - evenly space words in a sentence
STRIP(string[,[opt][,char]]) - remove leading/trailing spaces
SUBSTR(string,n[,length[,pad]]) - return a substring
SUBWORD(string,n[,k]) - return a substring of words
SYMBOL(name) - test to see if a symbol is defined
TIME([format]) - get the time. Format can be:
C (civil time) N (normal) L (long)
H (hours since midnight)
M (minutes since midnight)
S (seconds since midnight) E (elapsed time)
R (elapsed time then reset)
TRACE([setting]) - get and/or set trace mode (see trace
instruction)
TRANSLATE(string[,[tableo][,[tablei][,pad]]])
- translate characters using given tables
TRUNC(number[,n]) - truncate floating point number
VALUE(s[,[newvalue][,selector]]) - get or set value of a symbol
VERIFY(string,reference[,[option][,start]])
- verify string for valid characters
WORD(string,n) - return a word from a string
WORDINDEX(string,n) - return the position of a word in a string
WORDLENGTH(string,n) - return the length of a word in a string
WORDPOS(phrase,string[,start]) - find a phrase in a string
WORDS(string) - return the number of words in a string
XRANGE([a[,b]]) - return a range of characters
ΓòÉΓòÉΓòÉ 3.16.3.2. I/O functions (some of which are UNIX-specific) ΓòÉΓòÉΓòÉ
CHARIN([stream] [,[position] [,count]]) - read characters
CHAROUT([stream] [,[string] [,position] ]- write characters
CHARS([stream]) - number of characters available
CLOSE(stream) - close a stream
FDOPEN(fd [,[mode] [,stream]]) - open an fd number
FILENO(stream) - find an fd number
FTELL(stream) - return the current file pointer
LINEIN([stream] [,[line] [,count]]) - read a line
LINEOUT([stream] [,[string] [,line]]) - write a line
LINES([stream]) - determine whether lines may be read
OPEN(file [,[mode] [,stream]]) - open a file
PCLOSE(stream) - close a pipe
POPEN(command [,[mode] [,stream]]) - open a pipe to a shell command
STREAM(stream [,[option] [,command]]) - miscellaneous stream operations
ΓòÉΓòÉΓòÉ 3.16.3.3. UNIX-specific functions ΓòÉΓòÉΓòÉ
CHDIR(directory) - change to new directory
GETCWD() - return current working directory
GETENV(name) - get an environment variable
PUTENV(string) - set an environment variable
SYSTEM(s) - return the output of a shell command
USERID() - return the process owner's login name
ΓòÉΓòÉΓòÉ 3.16.3.4. Mathematical functions (implemented as separate package) ΓòÉΓòÉΓòÉ
ACOS(x) the arc-cosine of x in radians (0<=acs(x)<=pi)
ASIN(x) the arc-sine of x in radians (-pi/2<=asn(x)<=pi/2)
ATAN(x) the arc-tangent of x in radians (-pi/2<=atn(x)<=pi/2)
COS(x) the cosine of x radians
EXP(x) the exponential of x (2.718281... to the power x)
LN(x) the natural logarithm of x (x>0)
SIN(x) the sine of x radians
SQRT(x) the square root of x (x>=0) [arbitrary precision possible]
TAN(x) the tangent of x radians (x <> pi/2)
TOPOWER(x,y) x to the power y
ΓòÉΓòÉΓòÉ 4. Six Rules of Thumb for Beginning REXX Programmers ΓòÉΓòÉΓòÉ
SIX RULES OF THUMB FOR BEGINNING REXX PROGRAMMERS
(who already know Pascal or C)
(Copyright (c) 1993 by Raja Thiagarajan. This file may be copied for any
NONcommercial purpose as long as it is left unchanged.)
Since there are plenty of books, articles, and even OS/2 help files that teach
REXX, why do we need this article? Because those books, articles, etc. are
mostly aimed at people who have never programmed before. Thus, they have two
major drawbacks. First, they dwell on things that programmers already know,
like what a variable is. Second, they don't warn would-be REXX programmers that
some things are different in REXX, and some of the "habits" that you might
carry over from other languages can get you in trouble.
This article gives six "rules of thumb" that should help you get started in
REXX if you already know C or Pascal (or, really, any of the children of
Algol).
ΓòÉΓòÉΓòÉ 4.1. START EVERY REXX PROGRAM WITH A COMMENT! ΓòÉΓòÉΓòÉ
You already know this. There shouldn't be any reason for me to repeat it ...
except that it's an easy mistake to make, and it ties in with an important
concept that we'll get to under the second rule. Here's "hello, world" in
REXX:
/* hello.cmd -- program to say hi*/
say "Hello, world"
Type these two lines in your favorite editor, save the result as HELLO.CMD, and
enter HELLO at an OS/2 prompt. Your computer should respond "Hello, world".
Under OS/2, you are required to start every REXX program with a comment. And I
do mean start; if there's so much as a space or carriage return in front of
that comment--well, why don't you try that now? Insert a space in front of the
comment and try running the program again. You'll see a big fat error message.
So: START EVERY REXX PROGRAM WITH A COMMENT.
(By the way, the conventions for comments in REXX are simple. Each comment
begins with a "/*" and ends with a "*/". Comments can be spread over several
lines. Unlike ANSI C or Pascal, REXX permits you to nest comments, so it's much
easier to comment out hunks of code for testing.)
ΓòÉΓòÉΓòÉ 4.2. BE CAREFUL ABOUT USING SPACES IN CERTAIN PLACES! ΓòÉΓòÉΓòÉ
You've already had a taste of this in the previous rule: If you put a space
before the opening comment, your program will bomb. But there are two more
places where the significance of spaces will trip up someone who's used to
programming in C or Pascal. In REXX, everything is ultimately a string. If you
want to concatenate two strings, you can do so by putting the explicit string
abuttal operator ("||") between them. You can also concatenate them by simply
writing one after another (this is known as "implied abuttal"). Please enter
and run the following program.
/* hello2.cmd -- Another program to say hi*/
greeting = "Hello"
say greeting "world"
say greeting"world"
You should see "Hello world" on one line, followed by "Helloworld" on the
second line. Your first guess might be that SAY in REXX is like PRINTF in C or
WRITELN in Pascal; that it can accept an arbitrary number of arguments. But
you'd be wrong. SAY can only be followed by a single expression: the string to
be displayed. However, since greeting holds a string and "world" is a string,
and since you've written one after the other, REXX treats this as implied
abuttal. That is, REXX concatenates the two strings to form a single string
which it then passes to SAY. Thus, the third line in the program above is
equivalent to
say "Hello" "world"
or
say "Hello world"
On the other hand, the last line of the program is equivalent to
say "Hello"'world'
(In REXX, strings can be delimited by either single or double quotes. As in
Pascal, you can "double" the delimiter to make it appear in a string literal.
If I hadn't switched delimiters, the string would have been the one displayed
as Hello"world.) Since there is no space between the strings, REXX abuts the
strings without inserting a space between them. Thus, this line is equivalent
to
say "Helloworld"
and it displays what you saw when you ran the program.
Going back to the third line: You typed it with a single space between the
variable 'greeting' and the string "world". What if you had used two spaces?
Try it now. Edit the program and re-run it.
Surprised? In REXX, more than one space is always treated the same as a single
space (except in string literals). This is why you can write
if greeting = 'hello' then
say "It's hello"
instead of having to always write
if greeting = 'hello' then
say "It's hello"
Some of you are starting to yawn. So spaces are significant when you do string
concatenation; so what? How often do you do string concatenation? Well, in
REXX, you do it a lot. After all, it's the easiest way to output more than one
thing at a time using the "preferred" output instruction! But there's a serious
implication here that will cause you no end of grief until you figure it out.
It's only a problem for people who have learned another language like C or
Pascal and who expect REXX will work the same way. Up above, I wrote "You can
also concatenate [strings] by simply writing one after another." Do you see a
problem there?
No? Enter the following program:
/* func.cmd -- program to demonstrate a "problem" with
function calls*/
say abs(-3) "is *not*" abs (-3)
Before you run it, try to predict what it will display. Now run it.
Well, whatever you predicted, it probably wasn't the
3 is *not* ABS -3
that you actually got. What happened?
The "problem" is this. When you write abs(-3), REXX interprets it as a call to
the absolute value function with -3 as an argument. However, when you put a
space in front of the parentheses, REXX interprets this as an implicit abuttal;
it assumes that you want to concatenate the string value of the variable 'abs'
with the string '-3'. (The default value of 'abs' is "ABS" since the default
value of every REXX variable is a string consisting of its name written in
uppercase. By the way, like Pascal but unlike C, REXX ignores the
upper/lower-case distinction outside of string literals.) Of course, since
there's a space between the elements, you get a space between "ABS" and "-3".
Some of you will recoil in horror at this: How dare REXX mandate that you
cannot put a space between a function's name and its arguments! For my own
part, I can only say that it's reasonable when you get used to it. And if REXX
had been the first language you'd learned, it probably would seem weird the
other way. So, grin and bear it, and BE CAREFUL ABOUT USING SPACES IN CERTAIN
PLACES.
An important digression: These first two rules of thumb bring up a very
important difference between REXX and Pascal, C, or many other programming
languages. Namely: REXX* is not entirely a free-form language. Sometimes, you
have to be careful about where you put spaces in REXX. And sometimes you have
to be careful about where you split lines. For instance, while Pascal or C have
no trouble if you put arguments to a procedure on a different line from the
name of the procedure, REXX is not as forgiving. Using SAY as an example,
say
"Hello world"
is not the same as
say "Hello world"
The latter displays "Hello world"; the former displays a blank line and then
bombs when it tries to execute "Hello world" as an OS/2 command. If you need to
continue a clause across a line break, use a comma. The comma will be replaced
by a space and then REXX will continue as if the end-of-line character didn't
exist. So, for instance,
say ,
"Hello world"
will display "Hello world".
ΓòÉΓòÉΓòÉ 4.3. DON'T CONFUSE SUBROUTINE CALLS WITH FUNCTION CALLS! ΓòÉΓòÉΓòÉ
In C or Pascal, you use pretty much the same syntax whether you're calling a
function (ie, a routine that returns a value) or a procedure (a routine that
doesn't return a value). In fact, C blurs the distinction by letting you
"ignore" the return value of a function if you want. But in REXX, the way you
call a subroutine (which is REXX's term for a procedure) is completely
different from the way you call a function. Here's an example of a function
call in REXX:
length = max(x_coord, y_coord)
and here's an example of a subroutine call:
call charout myFile, dist
In REXX, a function is called by giving its name, followed directly by the left
parenthesis (no space permitted! Remember the second rule!), followed by zero
or more arguments (separated by commas) and then the right parenthesis.
By contrast, a subroutine is called by using the keyword CALL, followed by the
name of the subroutine, followed by a list of zero or more arguments separated
by commas. No parentheses are used.
(Digression: Am I the only one who's noticed that Microsoft's latest Visual
Basic products seem to have picked up this distinction and syntax from REXX?)
Having said all that, let me confess that you can call functions as if they
were subroutines. In this case, the return value goes into the special variable
RESULT. For instance:
/* subr.cmd -- Calls a function like a subroutine */
call abs -3
say "abs(-3) is" result
will display "abs(-3) is 3". Calling a subroutine as if it were a function is
an exercise in futility. Thus, don't do something like
charout(myFile, "foo") /*WRONG!*/
And always remember: DON'T CONFUSE SUBROUTINE CALLS WITH FUNCTION CALLS!
ΓòÉΓòÉΓòÉ 4.4. DON'T TREAT REXX COMPOUND VARIABLES AS ARRAYS! ΓòÉΓòÉΓòÉ
In Pascal and C, you declare arrays and reference their elements using brackets
("[]"). In REXX, you don't declare arrays for two good reasons: First, you
can't declare variables, and second, REXX doesn't have arrays. Okay, more
seriously: REXX's compound variables can often be used as arrays. For instance,
try the following program:
/* comp1.cmd -- 1st program to try compound vars */
do j = 1 to 3
square.j = j * j
end j
do i = 1 to 3
say "square."i "is" square.i
end i
You will get "square.1 is 1", "square.2 is 4", and "square.3 is 9". In this
case, we could treat the square compound variable as if it were an array. But
in other cases, we can't. For instance, try deleting the last three lines in
the above program and replace them with the following:
do i = 2 to 4
say "square."i-1 "is" square.i-1
end i
If the dots in REXX worked like brackets in C or Pascal, this program should
display the same thing as before, right? Well try it.
You got "square.1 is 3", "square.2 is 8", and then a "Bad arithmetic" error
message. What happened? Well, "square.i-1" does not mean "calculate i-1 and
then reference that element of the square array". It more nearly means,
"calculate i, reference that element of the square array, and subtract 1 from
it." (The "bad arithmetic" occurs when you try to subtract 1 from the value of
square.4, which is "SQUARE.4".) Actually, it doesn't even mean that, because
REXX doesn't have arrays--oh, I said that before.
"Aha!" you say. "There's an easy way to fix this! We can use parentheses and
write
do i = 2 to 4
say "square."i-1 "is" square.(i-1)
end i
and that will work!" Uh huh. Try it now.
This time, the program bombs immediately. The problem is, "square.(i-1)" means
"Call the function named 'square.' with the argument 'i-1'." Since you haven't
declared a function named 'square.', REXX complains that the "Routine was not
found."
(Hold it! Do not tell me that we can fix this by putting a space in front of
the parentheses! It'd break my heart to find out that you slept through the
second rule. ;-)
How can we fix this? How can we easily reference an array element in REXX using
an arbitrary expression? Simple enough: We can't. If you want to reference a
compound variable using some arbitrary expression, you should set a variable to
that expression and then use the variable. So, for instance, replacing those
three lines with
do i = 2 to 4
j = i - 1
say "square."j "is" square.j
end i
will do the trick.
In case some of you may still be holding out hopes that you can think of
compound variables in REXX as arrays in C or Pascal, let's try running another
program. Type in and run the following:
/* comp2.cmd -- 2nd program to try compound vars */
j = 3
k = 4
ary.j.k = "one"
m = 34/10
say ary.3.4 "is the same as" ary.j.k "is the same as" ary.m
If you're going to convince me that REXX compound variables are the same as
arrays in C or Pascal, you'll have to explain how the program above works. Any
volunteers?
Actually, the fact that REXX compound variables are not the same as arrays is a
great opportunity, not a difficulty. Try the program below:
/* comp3.cmd -- 3rd use of compound variables */
count. = 0
textWords = ''
say "Enter a line of text below:"
parse upper pull textLine
do i = 1 to words(textLine)
w = word(textLine, i)
count.w = count.w + 1
if count.w = 1 then
textWords = textWords w
end i
do i = 1 to words(textWords)
w = word(textWords, i)
say 'You used the word "'w'"' count.w 'time(s).'
end i
Whew! Okay, now run this program. Enter "The quick brown fox jumps over the
lazy dog". Your computer will tell you each word that appeared in the line of
text, and how many times each word appeared. As far as this rule of thumb goes,
there are two important things to point out in this program:
First, there is the line "count. = 0". This shows the use of a stem variable in
REXX. When you initialize a stem variable, any variable that begins with that
stem is set to that value. So, after this line, the variables count., count.1,
count.57, count.foo, and count.dracula all have a value of zero. (Also, you can
use the DROP instruction on a stem variable to return all those compound
variables to their initial state.)
Second: Loosely speaking, we're turning count. into an "array". But what are
the indexes? The REXX function "words" returns the number of blank-delimited
words in a string, and "word(str, j)" returns the j-th such word in str. So w
is a word -- and the indexes on count are the actual words that appear in the
string! So, for instance, count."the" holds the number of times that "the"
appears in the string -- for our sample run, that was 2.
So it's important that you DON'T TREAT REXX COMPOUND VARIABLES AS ARAYS,
because it can get you into trouble, and because you'll miss the chance to
write some very powerful and flexible programs.
ΓòÉΓòÉΓòÉ 4.5. MAKE THE MOST OF THE EXTERNAL DATA QUEUE! ΓòÉΓòÉΓòÉ
Enter the following program:
/* sayhi.cmd -- program to say hello */
say "Please enter your name below:"
parse pull name
if name = "" then
name = "Stranger"
say "Hello," name"."
and run it, entering your name. Your computer will say hello to you. Okay, this
isn't very earth-shattering. But I want to draw your attention to the third
line of the program: "parse pull name". This is the line that accepts input
from the keyboard. However, that's not its "primary" use. The PARSE PULL
instruction removes a line from the external data queue, falling back on
standard input only if the queue is empty.
To demonstrate this, enter and run the following program:
/* push1.cmd -- program to put an item in the external data queue */
push "Jean-luc"
and run it. What happened?
Okay, so nothing happened. Get a directory, clear the screen, and do some other
housekeeping tasks. Now enter "sayhi" at the prompt.
If that doesn't impress you, nothing will. REXX's external data queue can be
used to communicate between far-flung programs, and it isn't affected by any
intervening non-REXX programs. It's also useful within a program; one
subroutine can stuff as much into the external data queue as it wants, and
another subroutine can get it back out by using PARSE PULL.
You can put things in the external data queue using PUSH or QUEUE. PUSH puts
them at the front of the queue, and QUEUE puts them at the back. (That is, PUSH
treats the queue like a LIFO stack, and QUEUE treats it as a FIFO queue.) You
take elements off the front of the queue by using PARSE PULL. Finally, you use
the REXX function QUEUED to find the number of items that are in the external
data queue. So, one quick way to flush the queue would be
/* flush.cmd -- Program to flush the external data queue*/
do queued()
parse pull dummy
end
(If you want to see what you're flushing, insert a "say dummy" line after the
parse pull line.) By now, I hope I've convinced you to MAKE THE MOST OF THE
EXTERNAL DATA QUEUE.
ΓòÉΓòÉΓòÉ 4.6. USE PARSE TEMPLATES! ΓòÉΓòÉΓòÉ
Type in this sample program:
/* temp1.cmd -- 1st program to use template */
parse arg i j k
say 'i is "'i'", j is "'j'", and k is "'k'"'
and run it by entering
temp1 Alfa Bravo Charlie Delta
at an OS/2 prompt. Your computer will respond
i is "Alfa", j is "Bravo", and k is "Charlie Delta"
Let's analyze the second line in detail. When OS/2 calls this program,
everything after the "temp1 " on the command line will be packed into a string.
The PARSE ARG instruction is used to "split up" this string and put pieces of
it into the variables you specify. In this case, you used a parse template of
"i j k", which means to put the first word from the argument string into i, put
the second word into j, and put the rest into k. The spaces that separate these
words are discarded, though any trailing spaces are saved and put in the last
variable. (As in comp3.cmd, a "word" is any sequence of non-space characters
that is delimited by one or more spaces.) If this program is passed more than
three words (as in our example), the extras all become part of k. If fewer than
three words are given, then the "extra" variables are set to the empty string.
Try entering "temp1 hello world" to see the latter rule in action.
If you're a C programmer, you may already see the great convenience of parse
templates over argc and argv[]; certainly it's nice that the arguments go into
the variables you want without having to do lots of calls to strcpy. But wait,
there's more! For one thing, PARSE ARG is an instruction, not a declaration.
Add the following two lines to the end of temp1.cmd:
parse arg m
say 'm is "'m'"'
and rerun it with "temp1 Alfa Bravo Charlie Delta". You get the same results as
above, and the computer will also inform you that 'm is "Alfa Bravo Charlie
Delta"'. So if you "change your mind" about what values should go where, or if
you want to use the values in several different ways, you can do it easily.
But wait, there's still more! Suppose you're only interested in the first and
third words given to your program. You can use a period as a placeholder in the
template. Add the following lines to temp1:
parse arg w1 . w3 .
say 'w1 is "'w1'" and w3 is "'w3'"'
The top line means, "Put the first word in w1, discard the second word, put the
third word in w3, and discard the rest of the line." You should be able to
easily predict what will happen when you enter "temp1 Alfa Bravo Charlie
Delta". Try it to check if you're right.
If that isn't enough, you can also use column numbers in parse templates. Try
adding these lines to your (now quite large!) temp1.cmd:
parse arg c1 5 c5 10
say 'c1 is "'c1'" and c5 is "'c5'"'
and run it via "temp1 Alfa Bravo Charlie Delta". (Note the spelling of "Alfa".)
You will be told that c1 is "Alfa" and c5 is " Brav". This new PARSE ARG line
means "Put the characters in columns 1-4 into the variable c1, put the
characters in columns 5-9 into the variable c5, and discard the characters from
column 10 on (if any)." Column 1 is the first character after the space that
follows the name of your program. Try predicting what would happen if you put
an extra space in front of the word "Alfa" when you execute temp1 with the same
arguments again, and try it to see if your prediction was correct.
(By the way, you can also use "relative positional patterns"; for instance, the
PARSE ARG line could have been written with "+5" instead of "10".)
Have we exhausted the possibilities of the parse template? NO! However, I'll
just show one more example. I'm sure you're sick of temp1, so let's try a new
program, namely:
/* vcopy.cmd -- verbose copy command */
parse upper arg "FROM: " srcFile "TO: " destFile
"copy" srcFile destFile
Type this program in and save it as vcopy.cmd. (Note that we've added a new
keyword, "upper". This keyword will convert everything to uppercase, so the
program will work no matter what combination of upper- or lowercase our users
type). Now run it by entering
vcopy from: temp1.cmd to: boring.cmd
OS/2 will copy the file temp1.cmd to boring.cmd. (We put the OS/2 copy command
in quotes so REXX wouldn't mistake it for a variable name.) The nice thing is,
the following command will give the same results:
vcopy this is ignored from: temp1.cmd to: boring.cmd
To summarize, you can use string literals in a parse template and REXX will do
all the hard work of matching the arguments to your template. Clearly you
should USE PARSE TEMPLATES because they'll make your job much easier.
(Here's an exercise for the reader: Modify vcopy.cmd so that if the user types
more than one word after "FROM: " or "TO: ", the extra words are ignored. Test
your modified program by entering
vcopy from: temp1.cmd through OS/2 to: boring.cmd at long last
and seeing that it still copies temp1.cmd to boring.cmd. Hint: You only need to
add two characters!)
ΓòÉΓòÉΓòÉ 4.7. WHERE TO GO FROM HERE ΓòÉΓòÉΓòÉ
If you're serious about REXX, I highly recommend that you get Michael F.
Cowlishaw's The REXX Language. TRL is the standard book that defines REXX; it's
like "K&R" is to C. I found the book to be a joy to read because Cowlishaw
explains much of the why behind the features of REXX, and because he has a good
sense of humor that he never uses to put down other computer languages (or the
people who program in them). My only complaint about the book is the price;
does Prentice-Hall really have to charge $38 for a 200-page paperback?
The full title is The REXX Language: A Practical Approach to Programming,
Second Edition. It's published by Prentice Hall, and the ISBN number is
0-13-780651-5.
Another book I found quite helpful is Charles Daney's Programming in REXX,
published by McGraw-Hill, Inc. and with ISBN 0-07-015305-1. Though not as
concise (and sometimes not as clear) as TRL, it provides many interesting
sample programs and a thorough discussion of various time-saving REXX tips and
tricks. I really liked the discussion on writing filters in REXX (page 187 on).
Daney's book is $44.95.
There are several newsgroups and mailing lists that include much useful
information. If you have access to the Internet, I highly recommend that you
check out the comp.lang.rexx newsgroup. The people on c.l.r are among the
friendliest I've "met" on the Internet. For matters specific to OS/2 REXX, it's
also worth reading comp.os.os2.misc and comp.os.os2.programmer. If you have
access to BITNet, check out the REXXLIST discussion list.
Finally, comp.lang.rexx has a FAQ maintained by Eric Giguerre. You can obtain
it as the file rexxfaq in the pub/ directory on the rexx.uwaterloo.ca ftp site.
This FAQ includes a bibliography of REXX books, detailed information on the
BITnet lists, ftp sites for REXX-related information, and much more.
Raja Thiagarajan / sthiagar@bronze.ucs.indiana.edu / 6-6-93
ΓòÉΓòÉΓòÉ 5. REXXUTIL Information and Samples ΓòÉΓòÉΓòÉ
The following attempts to better explain some of the powerful features provided
by OS/2 V2's dynamic link library; REXXUTIL.DLL (Rexx utility functions).
REXXUTIL functions are described in the online 'REXX Information' reference and
the 'OS/2 2.0 Technical Library Procedures Language/2 REXX Reference'
publication (order number S10G-6268). The information following is intended to
provide a more detailed description of some of the functions.
Michael Lamb MIKELAMB(KGNVMC) Michael Lamb
Workstation Technical Support 4 Cross Creek Rd
ISSC - MHV Solution Center New Paltz, NY 12561-3805
30NC/370 Neighborhood Rd
Kingston NY 12401
(914)385-0666 t/l-695-0666
ΓòÉΓòÉΓòÉ 5.1. Plans for this information ΓòÉΓòÉΓòÉ
Much of this file has changed since the first few attempts at compiling useful
REXXUTIL information. Plans are to place this information out on an IBM
Internal FORUM, (REXXOS2 FORUM) and the OS2REXX CFORUM which makes its way out
into the external customer world. Hopefully within a month or so of making it
available I've received any corrections/omissions from both IBMer's and
customers. Thereafter I plan to create an OS2EWS package that will contain this
text information with the sample CMD files as separate files. Also I plan on
including an INF formatted file of the information. I really do want the
information to be as accurate as possible before creating the INF file so
please report to me any items of omission or error.
ΓòÉΓòÉΓòÉ 5.2. Publications ΓòÉΓòÉΓòÉ
One should realize that many of the functions provided by REXXUTIL have origins
with Presentation Manager Winxxx calls. These publications are helpful and be
reviewed for more information:
S10G-6265 OS/2 PM Programming Reference Vol - 2
Contains all the Winxxx calls, the Workplace Shell classes, and
their _wpxxx messages. Also this is available as an online doc
that comes with the OS/2 Toolkit.
S10G-6309 OS/2 System Object Model Reference
Also an online doc that comes with the OS/2 Toolkit.
GBOF-2254 OS/2 Technical Redbooks (series of technical documents)
GG24-3732 OS/2 V2 Volume 3: Presentation Manager & WPS
GG24-3774 OS/2 V2 Volume 4: Application Development
ZB35-5100 The REXX Language: A Practical Approach to Programming,
ISBN 0-13-780651-5
ΓòÉΓòÉΓòÉ 5.3. Some of the functions used/explained herein ΓòÉΓòÉΓòÉ
SysIni: Using REXXUTIL's SysIni function one can modify many settings of the
WorkPlace Shell as well as change other applications settings that
make use of *.INI files such as the system OS2.INI and OS2SYS.INI.
SysCreateObject: (PM WinCreateObject - Create Workplace Object) Using
REXXUTIL's SysCreateObject function one can create various objects;
like folders, programs, and shadow objects using Rexx. This section
for the most part includes parameter information which was gathered
together from various sources of information.
SysSetObjectData: (PM WinSetObjectData - Set Object Data) Using REXXUTIL's
SysSetObjectData function one can change an objects characteristics
(of an already created object, if you know its objectid).
SysDestroyObject: (PM WinDestroyObject - Destroy Workplace Object) Using
REXXUTIL's SysDestroyObject one can delete an object created if you
know its objectid.
ΓòÉΓòÉΓòÉ 5.4. Misc Notes ΓòÉΓòÉΓòÉ
If one views the *.RC files located in your bootdrive:\OS2 directory you can
learn a lot about the various INI settings and folder structure. Review INI.RC
and INISYS.RC files, they are used to create your OS2.INI and OS2SYS.INI files.
(Note in the *.RC files "?:" is used to indicate the boot drive)
Some of REXXUTIL's functions are only available when using the very latest
REXX20 PACKAGE which consists of the very latest REXX fixes and enhancements
for GA OS/2 V2.0. Should you have problems running any of the sample programs
you should make sure your system has the vary latest REXX20 updates. In
addition to the REXX fixes, various OS/2 V2 base fixes may be needed as well.
You may need to install/apply the latest 2.0 Service Pack, or even OS/2 2.1 in
order for some of the operations to behave properly.
If anyone discovers other parameters or other "hidden" features of any of the
functions discussed, please share your discovery. I'll try to update the
information as I receive it.
Thanks...
Michael Lamb MIKELAMB(KGNVMC) Michael Lamb
Workstation Technical Support 4 Cross Creek Rd
ISSC - MHV Solution Center New Paltz, NY 12561-3805
30NC/370 Neighborhood Rd
Kingston NY 12401
(914)385-0666 t/l-695-0666
ΓòÉΓòÉΓòÉ 5.5. Change Log ΓòÉΓòÉΓòÉ
04/30/92 - Added information about DuplicateFlag parm
- Added more setup string information from manuals
06/02/92 - Added information about breaking Title line character "^"
- Added information about adding multiple DOS_DEVICE statements
- Added code to SHADOW.CMD to make shadow object of a file
!!NOTE!! - The REXXOS2 fixes are required to make some of
the newer samples work properly.
06/30/92 - Added information regarding two new REXXUTIL functions:
SysSetObjectData and SysDestroyObject, also two new
samples STARTDOS, BOOTDOS (Thanks to Rick McGuire)
07/13/92 - Reorganized the way the material is presented. Also added more
sample Rexx routines REBUILD, OBJCLASS and LPTADD, descriptions
follow. Also changed parm CONCURRENTVIEW to CCVIEW (Thanks
Dan Kehn, Felix Sawicki)
07/15/92 - Updated entire document as I mistakenly truncated it at 80
characters. Rewrote some sample Rexx routines so they do not
extend beyond 80 characters. Also updated the SysSetObjectData
description to show how can open an object (Thanks Rick). Added
information about creating multi-line titles, carat works for
two line titles but not more than 2.
New samples, OBJECTID and FONTS included, descriptions follow.
07/29/92 - Corrected an error I made when I broke the setup lines into
multiple lines. I needed to add ]]'s to make sure they
concatenated without spaces (Thanks Rick). Also added
information regarding changing some System Settings (added
new section after sample Rexx code). Also added warning
in REBUILD.CMD sample about replacing Folder objects. Also
added new sample ICONRES.CMD which builds a folder containing
many of the OS/2 V2 installed icons using system DLL files.
01/30/93 Added to some examples the use of SysDestroyObject to clean up
after creating objects, also added the syntax for the call.
Changed REBUILD.CMD sample to used 'U' for updateifexists as
the duplicateflag to prevent problems. Added warning about
the 'R' duplicateflag parameter to field description.
Added information about changing Background tab, Change color
button values. Changed OBJECTID.CMD to enclose results in
double quotes to easier distinguish results.
Changed descriptions of calls to better match what's found in the
toolkit documentation for the Winxxx calls.
04/11/93 Added some information in ASSOCTYPE, ASSOCFILTER section.
Added new PROGTYPE values. Added ICONVIEWPOS information.
07/04/93 Too many changes to note. Lots having to do with OS/2 V2.1
ΓòÉΓòÉΓòÉ 5.6. REXXUTIL Functions ΓòÉΓòÉΓòÉ
This section contains information on the some of the functions of the REXXUTIL
library that comes with OS/2 REXX.
ΓòÉΓòÉΓòÉ 5.6.1. SysCreateObject ΓòÉΓòÉΓòÉ
Function: SysCreateObject
Syntax:
result=SysCreateObject(classname, title, location <,setup>, <,duplicateflag>)
classname: The name of the class of which this object is a member.
title: The object title, as it is to appear when displayed on the user
interface underneath an icon or on the title bar of an open object.
(Note this can be changed later using the TITLE keyword)
location: The object location. This can be specified as either an
object ID (for example, <WP_DESKTOP>) or a file system path
(for example, C:\bin\mytools).
(Object ids will be explained later)
setup: A WinCreateObject setup string. Described more later on.
duplicateflag: This parameter indicates what action should be taken
when the Setup string specifies an object ID, and an object with
that object ID already exists. If the setup string does not give
an object ID, another object will be created.
result: The return code from WinCreateObject. This returns 1 (TRUE) if the
object was created and 0 (FALSE) if the object was not created.
Purpose: Create a new instance of an object class.
ΓòÉΓòÉΓòÉ 5.6.2. SysSetObjectData ΓòÉΓòÉΓòÉ
Function: SysSetObjectData
Syntax:
result=SysSetObjectData(name, setup)
name: The object name. This can be specified as an object id (for
example <WP_DESKTOP>) or as a fully qualified file name.
setup: A WinCreateObject setup string. Described more later on.
result: The return code from WinSetObjectData. This will return 1 (TRUE)
if the object was updated and 0 (FALSE) if the object was not
updated.
Purpose: Alter the settings of an existing object.
Can be used to open an instance of an object:
/* open up the system folder */
call SysSetObjectData '<WP_OS2SYS>', 'OPEN=DEFAULT;'
Can be used to change the title of an object:
/* change Information folder name */
call SysSetObjectData '<WP_INFO>', 'TITLE=InfoFolder'
See the description of the SysCreateObject location and setup strings following
for an explanation of the parameters.
ΓòÉΓòÉΓòÉ 5.6.3. SysDestroyObject ΓòÉΓòÉΓòÉ
Function: SysDestroyObject
Syntax:
result=SysDestroyObject(name)
name: The object name. This should be specified as an object id, for
example <WP_CMDREF>. It can also be a fully specified file name.
result: The return code from WinDestroyData. This will return 1 (TRUE)
if the object was destroyed and 0 (FALSE) if the object was
not destroyed.
Purpose: Delete an existing workplace object, or file.
See the description of the SysCreateObject location parameter following for an
explanation of the object name. See the OBJECTID.CMD sample for a way to
determine the objectid's the system knows about.
ΓòÉΓòÉΓòÉ 5.6.4. Parameters Explained ΓòÉΓòÉΓòÉ
Parameters to the functions are now explained in more detail.
ΓòÉΓòÉΓòÉ 5.6.4.1. classname ΓòÉΓòÉΓòÉ
A registered object class defined to the system. Of particular interest are the
WPFolder/WPProgram/WPShadow classes. Note using the sample Rexx code included
in the SysQueryClassList function help screen one can list all of the
registered classes:
call SysQueryClassList "list."
do i = 1 to list.0
say 'Class' i 'is' list.i
end
ΓòÉΓòÉΓòÉ 5.6.4.2. title ΓòÉΓòÉΓòÉ
The objects title you want to use. If you wish to break the title line you use
a comma "," as the line break character. However, there were problems with this
and it may or may not work depending on whether you have the latest REXX and
OS/2 V2 fixes installed. You may instead decide to use a hex 0A character
(line-feed) in the string to separate lines.
Rexx example: Note: x2c is Rexx's hex to character function.
title='First'x2c(A)'Second'x2c(A)'Third'
Note if you wish to use the special characters; comma or semi-colon in the
string, prefix the character with the carat symbol.
Example title, you want:
] My Activities ] you would use...
] December 25, 1992 ] title='My Activities,December 25^,1992'
ΓòÉΓòÉΓòÉ 5.6.4.3. location ΓòÉΓòÉΓòÉ
The object's location can be specified as either an existing object id, for
example <WP_DESKTOP>, or alternatively a fully qualified file name of any file
or directory.
An object id string must always start with the '<' character and be terminated
by the '>' character and is thus an invalid file system name.
By looking at your \OS2\INI.RC file you can see a use of many object ids such
as <WP_DESKTOP>. If this is used as a location then your object will be placed
on the WorkPlace Shell desktop.
If you are creating an object you should make sure you use the OBJECTID setup
string parameter and give that object a unique object id. We'll see how this
works later.
HINTS: Here are some predefined object ids of system folders. Also if you are
thinking of placing an object in the Startup Folder <WP_START>, make it a
shadow of an object.
<WP_DESKTOP> Desktop
<WP_START> Startup folder
<WP_OS2SYS> OS/2 System folder
<WP_TEMPS> Templates folder
<WP_CONFIG> System Setup folder
<WP_INFO> Information folder
<WP_DRIVES> Drives folder
<WP_NOWHERE> Hidden folder
<WP_PROMPTS> Command Prompts folder
<WP_TOOLS> Productivity folder
<WP_GAMES> Games folder
Some other common OS/2 folder objectids:
<MAH_FOLDER> Mahjongg folder
<MMPM2_FOLDER> Multimedia folder
<MMPM2_SOUNDS> Multimedia Sound Bites folder
<MMPM2_MOVIES> Multimedia Movies folder
<TK_TOOLKIT> Toolkit 2.1 folder
<TK_DEVINFO> Toolkit Information folder
<TK_DEVTOOLS> Development Tools folder
<TK_CSAMPLE> Sample Programs folder
ΓòÉΓòÉΓòÉ 5.6.4.4. setup ΓòÉΓòÉΓòÉ
This field needs the most explaining. Each object class, WPProgram, WPFolder,
etc, documents its setup string keynames and parameters. A larger section
follows that details many of the available keynames and parameters. The setup
string contains a series of "keyname=value" pairs, that change the behavior of
the object. "keynames" are separated by semicolons, and "values" are separated
by commas.
"key=value;key2=value1,value2;"
If you want a literal comma or semicolon inside one of your fields you must
precede the comma/semi-colon with a carat as in the following:
^, A literal comma
^; A literal semicolon
Note that ALL setup string parameters have safe defaults, so it is never
necessary to pass unnecessary parameters to an object.
(Note: The setup string was limited to a total length of 255 bytes in the 2.0
GA code, this limitation is removed if the Service Pack is applied or you are
using OS/2 2.1) (APAR PJ02271)
ΓòÉΓòÉΓòÉ 5.6.4.5. duplicateflag ΓòÉΓòÉΓòÉ
There are three possible values for this parameter:
FailIfExists No object should be created if an object with the given object
already exists. This is the default and maps to the PM creation
flag, CO_FAILIFEXISTS
UpdateIfExists If an object with the given object ID already exists, the
existing object will be updated with the new setting information.
Maps to the creation flag, CO_UPDATEIFEXISTS. If the object does not
exist, it is created.
ReplaceIfExists If an object with the given object ID already exists, the
existing object should be replaced. Maps to the PM creation flag, CO_REPLACEIFEXISTS.
WARNING: Be careful using the 'R' ReplaceIfExists value. Any
attempt to rebuild an object first deletes any object that is using
that same <objectid>. This can be useful if you want to restore an
object back to its original installed state. This can also be bad
since if you rebuild a folder it first deletes all objects in it
since those objects are tied to the folder object.
Note: Only the first character is required/examined, i.e. F, R, or U
ΓòÉΓòÉΓòÉ 5.6.5. Setup Strings ΓòÉΓòÉΓòÉ
Using WPFolder and WPProgram classes in your SysCreateObject call you can build
folder and program objects. What follows are setup string parameters. Their
various key names, values, and a short description follow each item.
An instance of each class is created initially by the system in its template
form. It has the title "Folder" / "Program", respectively, and resides in the
systems "Templates" folder.
ΓòÉΓòÉΓòÉ 5.6.5.1. WPFolder setup string parms ΓòÉΓòÉΓòÉ
ΓòÉΓòÉΓòÉ 5.6.5.1.1. View ΓòÉΓòÉΓòÉ
KEYNAME VALUE Description
-----------------------------------------------------------------------------
OPEN ICON Open icon view when object is created/updated.
TREE Open tree view when object is created/updated.
DETAILS Open details view when object is created/updated.
Example:
/* Open up the tree view of the system folder */
call SysSetObjectData '<WP_OS2SYS>', 'OPEN=TREE;'
ICONVIEW s1[,s2,...sn] Set icon view to specified style(s).
TREEVIEW s1[,s2,...sn] Set tree view to specified style(s).
DETAILSVIEW s1[,s2,...sn] Set details view to specified style(s).
(styles) FLOWED flowed list items
NONFLOWED non-flowed list items
NONGRID non-gridded icon view
NORMAL normal size icons
MINI small icons
INVISIBLE no icons
LINES lines in tree view
NOLINES no lines in tree view
ICONFONT value Font size and facename. See Font Notes following.
TREEFONT value Font size and facename. See Font Notes following
DETAILSFONT value Font size and facename. See Font Notes following
Font Notes: The format for the value is normally; size.facename fontstyle hex0
example: 8.Courier Bold
Remember the value should end with null zero. Example code to change the
Information Folder icon view font:
call SysSetObjectData '<WP_INFO>', 'ICONFONT=8.Courier Bold'x2c(0)
We say 'normally' because there are certain circumstances where you must
separate values using a period. Also if you use a font style of 'Normal' you
just leave off the font style (don't use the word 'Normal') Following is a
small table to help.
FaceName: Courier FontStyle: Normal
'ICONFONT=8.Courier'x2c(0)
FaceName: Courier FontStyle: Bold Italic
'TREEFONT=8.Courier Bold Italic'x2c(0)
10 FaceName: System Proportional FontStyle: Bold
'DETAILSFONT=10.System Proportional.Bold'x2c(0)
HINT: To find out what the string should look like, create a folder, name it
simple like MYFOLD, then manually change the font size/name using the
Open/Settings/Change font button. Close the settings, then from an OS/2 command
line first determine the name of your desktop, for a typical 2.0 FAT file
system it would be something like C:\OS!2_2.0_D (It gets easier for 2.1 where
the Desktop is normally named C:\DESKTOP) Then locate the folder you created
C:\OS!2_2.0_D\MYFOLD Then enter: EAUTIL C:\OS!2_2.0_D\MYFOLD MYFOLD.EAS /S /P
This will create a MYFOLD.EAS file, use a browse program to view this file and
you'll see the values required.
ΓòÉΓòÉΓòÉ 5.6.5.1.2. Background ΓòÉΓòÉΓòÉ
KEYNAME VALUE Description
-----------------------------------------------------------------------------
BACKGROUND filename Sets the folder background. filename is the
name of a file in the \OS2\BITMAP directory
of the boot drive.
ΓòÉΓòÉΓòÉ 5.6.5.1.3. File ΓòÉΓòÉΓòÉ
KEYNAME VALUE Description
-----------------------------------------------------------------------------
WORKAREA YES Make the folder a Workarea folder
NO
ΓòÉΓòÉΓòÉ 5.6.5.1.4. Window ΓòÉΓòÉΓòÉ
KEYNAME VALUE Description
-----------------------------------------------------------------------------
HIDEBUTTON YES Views of this object will have a hide button
as opposed to a minimize button.
NO Views of this object will have a minimize button
as opposed to a hide button.
MINWIN HIDE Views of this object will hide when their
minimize button is selected.
VIEWER Views of this object will minimize to the
minimized window viewer when their minimize
button is selected.
DESKTOP Views of this object will minimize to the
Desktop when their minimize button is selected.
CCVIEW YES New views of this object will be created every
time the user selects open.
NO Open views of this object will resurface when
the user selects open.
ΓòÉΓòÉΓòÉ 5.6.5.2. WPProgram setup string parms ΓòÉΓòÉΓòÉ
ΓòÉΓòÉΓòÉ 5.6.5.2.1. Program ΓòÉΓòÉΓòÉ
KEYNAME VALUE Description
-----------------------------------------------------------------------------
EXENAME filename Sets the name of the program
PARAMETERS params Sets the parameters list, which may
include substitution characters
---Substitution characters---
Special substitution parameters are allowed:
[ ] :(bracket blank bracket) You are prompted
to type any parameters you want to use.
[text] :Characters placed inside of the brackets
are displayed as the prompt string.
no parm :If the program object is started by
clicking on it no parameters are passed.
If you start the program object by
dragging a file over it, the full
filename is passed.
% :No parameters are passed. Useful for
program objects you may want to start
from a folders pop-up menu.
%* :Like passing no parms, but useful if you
need to insert the filename of a dragged
object somewhere other than at the end
of the parameter list.
%**P :Insert drive and path information without
the last backslash (\).
%**D :Insert drive with ':' or UNC name.
%**N :Insert file name without extension.
%**F :Insert file name with extension.
%**E :Insert extension without leading dot. In
HPFS, the extension always comes after
the last dot.
REMEMBER: If you specify a parameter in the field
the name of any file being dragged onto
this object is added to the end of the
parameter list.
STARTUPDIR pathname Sets the working directory
ΓòÉΓòÉΓòÉ 5.6.5.2.2. Sessions ΓòÉΓòÉΓòÉ
KEYNAME VALUE Description
-----------------------------------------------------------------------------
PROGTYPE OS/2 session values:
PM Sets the session type to PM
FULLSCREEN Sets the session type to OS/2 full screen
WINDOWABLEVIO Sets the session type to OS/2 windowed
DOS session values:
VDM Sets the session type to DOS full screen
WINDOWEDVDM Sets the session type to DOS windowed
WIN-OS/2 session values:
WIN WIN-OS2 full screen
WINDOWEDWIN WIN-OS2 windowed, NOT a separate VDM session
SEPARATEWIN WIN-OS2 windowed, Separate VDM session
-- Values for OS/2 2.1 systems --
PROG_31_STD WIN-OS2 full screen, Windows 3.1 Standard mode.
PROG_31_STDSEAMLESSVDM
WIN-OS2 windowed, Separate VDM session,
3.1 Standard mode
PROG_31_STDSEAMLESSCOMMON
WIN-OS2 windowed, NOT a separate VDM session,
3.1 Standard mode
PROG_31_ENH WIN-OS/2 full screen, NOT a separate VDM session,
3.1 Enhanced Compatibility
PROG_31_ENHSEAMLESSVDM
WIN-OS2 windowed, Separate VDM session,
3.1 Enhanced Compatibility
PROG_31_ENHSEAMLESSCOMMON
WIN-OS2 windowed, NOT a separate VDM session,
3.1 Enhanced Compatibility
MINIMIZED YES Start program minimized
MAXIMIZED YES Start program maximized
NOAUTOCLOSE YES Leaves the window open upon program termination.
NO Closes the window when the program terminates.
SET XXX=VVV XXX is any environment variable. VVV sets the
value of the environment variable. When used will
wipe out many variables you may have assumed were
set. Check environment space closely when using.
Also used to specify DOS settings for DOS and
Windows programs. --See next section--
ΓòÉΓòÉΓòÉ 5.6.5.2.3. DOS and WIN-OS2 Settings ΓòÉΓòÉΓòÉ
IMPORTANT NOTES:
1. To change these values you use SET keyname=
Example: SET DOS_FILES=45;SET DOS_HIGH=1;
Also for some use values of 1 for On, 0 for off
Example: SET COM_HOLD=1; (on, default is off)
2. To add more than one line to a setting you can use the same technique
used to have more than one title line. See the discussion previous
regarding that technique. Here's an example using the DOS_DEVICE keyname:
setup='...SET DOS_DEVICE=C:\OS2\MDOS\ANSI.SYS'x2c(A)'C:\OS2\MDOS\EGA.SYS...'
3. Some settings may already have default values, like DOS_VERSION. You must
be careful since any action against that setting is treated as a
replacement (even if you are using the updateifexist duplicateflag
value). So if you wanted to add one item to DOS_VERSION, you should also
include all of the existing values.
4. Some settings are new once you've installed the OS/2 V2 Service Pack or
upgraded to OS/2 V2.1. As well some may not be on your workstation due to
your hardware configuration, for instance use of VIDEO_8514A_XGA_IOTRAP
is only available on certain systems.
5. WIN-OS2 Settings are new to V2 users and appear once the Service Pack is
installed or you have upgraded to OS/2 V2.1. Refer to the section "Global
WIN-OS2 Settings" for more information.
List of DOS and WIN-OS2 Setting fields
-----------------------------------------------------------------------------
Keyname Values and notes about usage
(<>'s are used to signify default setting for some)
(Remember 1=on and 0=off for those that us on/off)
-----------------------------------------------------------------------------
WIN_RUNMODE Use the PROGTYPE parameter mentioned previously
to define a enhanced mode WIN-OS2 program (Also
see note 5 from above)
WIN_DDE (See note 5 above)
WIN_CLIPBOARD (See note 5 above)
AUDIO_ADAPTER_SHARING On Off
COM_DIRECT_ACCESS On <Off>
COM_HOLD On <Off>
COM_RECEIVE_BUFFER_FLUSH Valid settings: <NONE>
ALL
RECEIVE DATA INTERRUPT ENABLE
SWITCH TO FOREGROUND
COM_SELECT Valid settings: <ALL> COM1 COM2 COM3 COM4 NONE
DOS_AUTOEXEC C:\AUTOEXEC.BAT
Use full BATch filename also you can pass parameters
DOS_BACKGROUND_EXECUTION <On> Off
DOS_BREAK On <Off>
DOS_DEVICE Default: empty
Remember to separate any used with "," for newline
DOS_FCBS Limits: 0-255, default 16
DOS_FCBS_KEEP Limits: 0-255, default 8
DOS_FILES Limits: 20-255, default 20
DOS_HIGH On <Off>
DOS_LASTDRIVE Limits: last physical drive to Z, default Z
DOS_RMSIZE Limits: 128-640, default 640, increments of 16
DOS_SHELL Default: "?:\OS2\MDOS\COMMAND.COM "
"?:\OS2\MDOS\ /P" where ?
is the boot drive
DOS_STARTUP_DRIVE Default: empty
Accepts text; like A: or C:\DISKS\DRDOS.IMG
DOS_UMB On <Off>
DOS_VERSION Default: DCJSS02.EXE,3,40,255
DFIA0MOD.SYS,3,40,255
DXMA0MOD.SYS,3,40,255
IBMCACHE.COM,3,40,255
IBMCACHE.SYS,3,40,255
ISAM.EXE,3,40,255
ISAM2.EXE,3,40,255
ISQL.EXE,3,40,255
NET3.COM,3,40,255
EXCEL.EXE,10,10,4
PSCPG.COM,3,40,255
SAF.EXE,3,40,255
WIN200.BIN,10,10,4
Remember what you put here will replace the existing
list of items so be careful, also remember to use
carats in front of any commas you need.
Example:
'SET DOS_VERSION=IBMCACHE.SYS^,3^,40^,255;']],...
DPMI_DOS_API Valid settings: <AUTO> ENABLED DISABLED
DPMI_MEMORY_LIMIT Limits: 0-512, default 4
DPMI_NETWORK_BUFF_SIZE Limits: 1-64, default 8
EMS_FRAME_LOCATION Valid settings: <AUTO> NONE C000 C400 C800 CC00
D000 D400 D800 DC00
8000 8400 8800 8C00 9000
EMS_HIGH_OS_MAP_REGION Limits: 0-96, default 32, note increments of 16
EMS_LOW_OS_MAP_REGION Limits: 0-576, default 384, note increments of 16
EMS_MEMORY_LIMIT Limits: 0-32768, default 2048, note increments of 16
HW_NOSOUND On <Off>
HW_ROM_TO_RAM On <Off>
HW_TIMER On <Off>
IDLE_SECONDS Limits: 0-60, default 0
IDLE_SENSITIVITY Limits: 1-100, default 75
INT_DURING_IO On <Off>
KBD_ALTHOME_BYPASS On <Off>
KBD_BUFFER_EXTEND <On> Off
KBD_CTRL_BYPASS Valid settings: <NONE> ALT_ESC CTRL_ESC
KBD_RATE_LOCK On <Off>
MEM_EXCLUDE_REGIONS Initially empty, you can specify a range of memory
to exclude or you can supply a singe address for the
beginning of a 4KB region, if you need several
regions separate them with a comma (don't forget to
use the carat since commas are special setup string
parameters) Example:
'SET MEM_EXCLUDE_REGIONS=C0000^,D0000-D8000;']],
MEM_INCLUDE_REGIONS Initially empty, you can specify a range of memory
to include or you can supply a singe address for the
beginning of a 4KB region, if you need several
regions separate them with a comma (don't forget to
use the carat since commas are special setup string
parameters) Example:
'SET MEM_INCLUDE_REGIONS=C0000^,D0000-D7FFF;']],
NOTE: The include region D0000-D80000 will include
the entire memory between D8000 and D8FFFF.
MOUSE_EXCLUSIVE_ACCESS On <Off>
NETWARE_RESOURCES Valid settings: NONE PRIVATE GLOBAL
Special note, you use the words to change the value
BUT the string MUST be 7 characters long!
Example:
'SET NETWARE_RESOURCES=GLOBAL ;'
PRINT_SEPARATE_OUTPUT <On> Off
PRINT_TIMEOUT Limits: 0-3600, default 15
TOUCH_EXCLUSIVE_ACCESS On Off
VIDEO_8514A_XGA_IOTRAP <On> Off
VIDEO_FASTPASTE On <Off>
VIDEO_MODE_RESTRICTION Valid settings: <NONE> CGA MONO
Special note, you use the words to change the value
BUT the string MUST be 15 characters long!
Example:
'SET VIDEO_MODE_RESTRICTION=CGA ;'
VIDEO_ONDEMAND_MEMORY <On> Off
VIDEO_RETRACE_EMULATION <On> Off
VIDEO_ROM_EMULATION <On> Off
VIDEO_SWITCH_NOTIFICATION On <Off>
VIDEO_WINDOW_REFRESH Limits: 1-600, default 1
XMS_HANDLES Limits: 0-128, default 32
XMS_MEMORY_LIMIT Limits: 0-16384, default 2048, increment of 4
XMS_MINIMUM_HMA Limits: 0-63, default 0
ΓòÉΓòÉΓòÉ 5.6.5.2.4. Association ΓòÉΓòÉΓòÉ
KEYNAME VALUE Description
-----------------------------------------------------------------------------
ASSOCFILTER filters Sets the filename filter for files
associated to this program.
Multiple filters are separated by commas.
See notes about preserving existing filter
values following.
ASSOCTYPE type Sets the type of files associated to this
program. Multiple filters are separated
by commas.
See notes about preserving existing associate
types following.
Preserving existing values
When using ASSOCFILTER and/or ASSOCTYPE include two commas at the end of your
string to preserve any settings that are already applied:
Example: ... ASSOCTYPE=Metafile,PIF file,,;ASSOCFILTER=*.MET,*.PIF,,; ...
ΓòÉΓòÉΓòÉ 5.6.5.2.5. Window ΓòÉΓòÉΓòÉ
KEYNAME VALUE Description
-----------------------------------------------------------------------------
MINWIN HIDE Views of this object will hide when their
minimize button is selected.
VIEWER Views of this object will minimize to the
minimized window viewer when their minimize
button is selected.
DESKTOP Views of this object will minimize to the
Desktop when their minimize button is selected.
CCVIEW YES New views of this object will be created every
time the user selects open.
NO Open views of this object will resurface when
the user selects open.
ΓòÉΓòÉΓòÉ 5.6.5.3. General and Miscellaneous ΓòÉΓòÉΓòÉ
NOTE: Some keynames are valid for any objects. Here in this section many of
them are described. These can be used for the WPFolder and WPProgram objects.
KEYNAME VALUE Description
-----------------------------------------------------------------------------
ICONFILE filename This sets the object's icon.
ICONRESOURCE id,module This sets the object's icon. 'id' is the
identity of an icon resource in the 'module'
dynamic link library (DLL). For example:
ICONRESOURCE=73 PMWP;
This would indicate resource 73 in PMWP.DLL.
See a supplied sample command file for more info.
ICONPOS x,y This sets the object's initial icon position.
The x and y values represent the position in
the object's folder in percentage coordinates.
ICONVIEWPOS w,x,y,z This sets the object's initial size. The values
represent relative position in percentage
coordinates. For example: ICONPOS=25 25 50 50
Would create a folder whose bottom left corner is
25% from the left and 25% from the bottom and half
the screen width/height.
TEMPLATE YES Creates object as a template.
NO Resets objects template property.
TITLE value Can be used to assign a name/title to an object.
OBJECTID <name> This sets the object's identity. The object
id will stay with the object even if it is
moved or renamed. An object id is any unique
string preceded with a '<' and terminated
with a '>'. This may also be a real name
specified as a fully qualified path name.
IMPORTANT: For any object you create you should
use a unique objectid! Do this for two reasons:
1) If you use an objectid it signifies a unique
object that will not be recreated if you use
the "FailIfExists" flag in your Rexx call. Not
using an objectid would cause multiple objects
to be created if the same program was run
over and over.
2) Should you need to later delete it or change
your object, you can use this objectid in your
Rexx call to refer to it.
Also one should not use an objectid that starts
with "WP_" as many OS/2 objects use those,
consider those reserved characters.
HELPPANEL id This sets the object's default help panel.
HELPLIBRARY filename This sets the help library.
OPEN SETTINGS Open settings view of object when created/updated.
DEFAULT Open default view of object when created/updated.
Don't forget for folder objects you can use
OPEN with these values: ICON, TREE, DETAILS
NODELETE YES Will not allow you to delete the object.
NO Resets the object's no delete property.
NOCOPY YES Will not allow you to make a copy.
NO Resets the object's no copy property.
NOMOVE YES Will not allow you to move the object to another
folder, will create shadow on a move.
NO Resets the object's no move property.
NODRAG YES Will not allow you to drag the object.
NO Resets the object's no drag property.
NOLINK YES Will not allow you to create a shadow link.
NO Resets the object's no link property.
NOSHADOW YES Will not allow you to create a shadow link.
NO Resets the object's no shadow property.
NORENAME YES Will not allow you to rename the object.
NO Resets the object's no rename property.
NOPRINT YES Will not allow you to print it.
NO Resets the object's no print property.
NOTVISIBLE YES Will not display the object.
NO Resets the object's not visible property.
ΓòÉΓòÉΓòÉ 5.6.5.4. WPShadow setup string ΓòÉΓòÉΓòÉ
A shadow object is a persistent link or reference to any other object. This is
achieved by storing away the location and identity of the object that it is
linked to and then rerouting all requests for help, context menus, and open
views on to the object that it is linked to. Delete, Copy, and Move are the
only action requests that are handled by the WPShadow object and are not
rerouted to the linked object.
When you place objects into your Startup folder you should be placing a shadow
object there. See the SHADOW sample code for an example of its usage.
These are the keyname-value pairs supported by the WPShadow class.
KEYNAME VALUE Description
-----------------------------------------------------------------------------
SHADOWID <name> or The value for this is an object's id (OBJECTID)
filename or a fully qualified pathname of a directory,
program file, or data file.
Note: When creating a shadow object always use the OBJECTID= string to give
your object a unique id so that later you may refer to it, and potentially
delete it with SysDestroyObject.
ΓòÉΓòÉΓòÉ 5.7. REXX CMD Samples ΓòÉΓòÉΓòÉ
Listing of sample programs
ΓòÉΓòÉΓòÉ 5.7.1. Listing of sample programs ΓòÉΓòÉΓòÉ
FOLDER.CMD
Creates a folder and program objects in the folder
SHADOW.CMD
Creates shadows of objects
FLDSHAD.CMD
Creates a folder, then program object in the folder, then place a
shadow of the program object on the desktop.
MKSHAD.CMD
Creates a shadow object of an objectid, file or drive/directory.
STARTDOS.CMD
Starts a DOS program using specific DOS VDM settings.
BOOTDOS.CMD
Starts a DOS session, booting from a specific DOS image with
specific DOS VDM settings.
REBUILD.CMD
Allows one to rebuild OS/2 system objects, kinda like MAKEINI does.
LPTADD.CMD
Code using SysIni to add LPT4-9 ports.
OBJECTID.CMD
Code using SysIni to list OBJECTIDs known to the WorkPlace Shell
FONTS.CMD
Code using SysIni to list installed fonts and verify their
existence.
ICONRES.CMD
Code building a folder containing many of the various icons found in
installed DLL files for OS/2 V2. Demonstrates use of setup string
parameter ICONRESOURCE.
SWAPEDIT.CMD
Code that allows you to make the Enhanced Editor (EPM) the default
open action for most data objects instead of the OS/2 Enhanced
Editor (E).
OPENWPS.CMD
Code that allows you to open up an objectid or directory using views
you specify.
ΓòÉΓòÉΓòÉ 5.7.2. FOLDER.CMD ΓòÉΓòÉΓòÉ
/* FOLDER.CMD: Sample code using REXXUTIL function calls */
/* */
/* Builds a folder on the DeskTop and places some program objects in it.*/
/* */
/* Demonstrates use of these REXXUTIL functions: */
/* SysCreateObject - create or update an object */
/* SysDestroyObject - delete an object */
/* SysSetObjectData - update an existing object */
/* */
/* Mike Lamb: MIKELAMB/KGNVMC / 30NC/370 Neighborhood Rd */
/* ISSC MHV - Solution Center / Kingston NY 12401 */
/* Version 1.1 */
/* Load REXXUTIL */
Call RxFuncAdd 'SysLoadFuncs','RexxUtil','SysLoadFuncs'
Signal on Syntax Name LoadCheck
Call SysLoadFuncs
LoadCheck: /* rc of 43 means REXXUTILs not found */
If rc=43 Then Do
Say ''
Say 'ERROR: Not able to load REXXUTILs. Perhaps REXX not installed or'
Say ' REXXUTIL.DLL not found in a LIBPATH drive/directory.'
Exit
End
Signal off Syntax
call SysCls
Say '';Say 'Using REXXUTILs to Add a Folder and Program Objects...'
Say '';Say 'Press Y to add Test Folder to Desktop...';Say '';
parse upper value SysGetKey('NOECHO') with key
If key<>'Y' Then Signal Exiter
/* All of the routines pass parameters to a subroutine to perform the call */
classname='WPFolder'
title ='Test Folder'
location ='<WP_DESKTOP>'
setup ='OBJECTID=<TEST_FOLDER>'
Call BldObj
Say '';
Say 'Press ENTER and we will open up that folder and watch as other objects'
Say 'are added into it.'
key=SysGetKey()
Call SysSetObjectData '<TEST_FOLDER>', 'OPEN=DEFAULT;'
Say 'Place a program object into the folder...';Say '';
classname='WPProgram'
title ='SYSLEVEL-FULLSCR'
location ='<TEST_FOLDER>'
setup ='OBJECTID=<TEST_SYSL>;']],
'EXENAME=\OS2\SYSLEVEL.EXE;']],
'PROGTYPE=FULLSCREEN;'
Call BldObj
classname='WPProgram'
title ='CHKDSK-PM'
location ='<TEST_FOLDER>'
setup ='OBJECTID=<TEST_PMCK>;']],
'EXENAME=\OS2\PMCHKDSK.EXE;']],
'MINIMIZED=YES;']],
'PROGTYPE=PM;'
Call BldObj
classname='WPProgram'
title ='SYSLEVEL-VIO'
location ='<TEST_FOLDER>'
setup ='OBJECTID=<TEST_SYSLVIO>;']],
'EXENAME=\OS2\SYSLEVEL.EXE;']],
'PROGTYPE=WINDOWABLEVIO;'
Call BldObj
classname='WPProgram'
title ='MEM-Fullscreen'
location ='<TEST_FOLDER>'
setup ='OBJECTID=<TEST_MEMFUL>;']],
'EXENAME=\OS2\MDOS\MEM.EXE;']],
'PROGTYPE=VDM;']],
'PARAMETERS=/?;']],
'NOAUTOCLOSE=YES;'
Call BldObj
classname='WPProgram'
title ='MEM-WindowVDM'
location ='<TEST_FOLDER>'
setup ='OBJECTID=<TEST_MEMWIN>;']],
'EXENAME=\OS2\MDOS\MEM.EXE;']],
'PROGTYPE=WINDOWEDVDM;']],
'PARAMETERS=/?;']],
'NOAUTOCLOSE=YES;'
Call BldObj
Say ''
Say 'Okay, now lets change the title of the folder using SysSetObjectData.'
Say 'Press ENTER and watch the folder get renamed...'
key=SysGetKey()
Call SysSetObjectData '<TEST_FOLDER>', 'TITLE=System Stuff';
Say ''
Say 'All done, now we will remove the objects by using...'
Say '...the SysDestroyObject call against the folder objectid.'
Say 'Note: If you delete a folder all objects contained within are removed.'
Say 'Press ENTER to watch the objects disappear...'
key=SysGetKey()
Call SysDestroyObject '<TEST_FOLDER>'
Exiter:
Call SysDropFuncs
Exit
/* Build Object */
BldObj:
call charout ,'Building: 'title
/*The basic call is listed next. */
/*rc=SysCreateObject(classname, title, location <,setup>, <,duplicateflag>)*/
/* Build object using UPDATEIFEXIST as duplicateflag */
result = SysCreateObject(classname, title, location, setup, 'U')
If result=1 Then call charout ,'... Object created!'
Else call charout ,'... Not created! Return code='result
Say '';
Return
ΓòÉΓòÉΓòÉ 5.7.3. SHADOW.CMD ΓòÉΓòÉΓòÉ
/* SHADOW.CMD: Sample code using REXXUTIL function calls */
/* */
/* Builds shadows in the DeskTop and Startup Folder */
/* */
/* Demonstrates use of these REXXUTIL functions: */
/* SysCreateObject - create or update an object */
/* SysDestroyObject - delete an object */
/* SysSetObjectData - update an existing object */
/* */
/* Mike Lamb: MIKELAMB/KGNVMC / 30NC/370 Neighborhood Rd */
/* ISSC MHV - Solution Center / Kingston NY 12401 */
/* Version 1.1 */
/* Load REXXUTIL */
Call RxFuncAdd 'SysLoadFuncs','RexxUtil','SysLoadFuncs'
Signal on Syntax Name LoadCheck
Call SysLoadFuncs
LoadCheck: /* rc of 43 means REXXUTILs not found */
If rc=43 Then Do
Say ''
Say 'ERROR: Not able to load REXXUTILs. Perhaps REXX not installed or'
Say ' REXXUTIL.DLL not found in a LIBPATH drive/directory.'
Exit
End
Signal off Syntax
Call SysCls
Say '';Say 'Demonstration using REXXUTILs to Add Shadow Objects...'
/* The titles and objectid's are found from the \OS2\INI.RC file */
Say '';Say 'First lets place some items on the Desktop...'
Call AddShad 'Enhanced Editor',, /* Title */
'<WP_DESKTOP>',, /* Location for shadow object */
'<WP_EPM>',, /* Value of existing objectid or file */
'<SHAD_WP_EPM>' /* New unique value of this shadow object */
Call AddShad 'OS/2 Window',, /* Title */
'<WP_DESKTOP>',, /* Location for shadow object */
'<WP_OS2WIN>',, /* Value of existing objectid or file */
'<SHAD_WP_OS2WIN>' /* New unique value of this shadow object */
Call AddShad 'OS/2 DeskTop',, /* Title */
'<WP_DESKTOP>',, /* Location for shadow object */
'<WP_DESKTOP>',, /* Value of existing objectid or file */
'<SHAD_WP_DESKTOP>' /* New unique value of this shadow object */
Say '';Say 'You can even make shadow objects of files...'
Call AddShad 'CONFIG.SYS',, /* Title */
'<WP_DESKTOP>',, /* Location for shadow object */
'C:\CONFIG.SYS',, /* Value of data file */
'<SHAD_CONFIG_SYS>' /* New unique value of this shadow object */
Say '';Say 'Now lets place an item in the Startup Folder...'
Say 'First would you like me to open the Startup Folder so you can see the'
Say 'object being created? Press Y to open the folder.'
parse upper value SysGetKey('NOECHO') with key
If key='Y' Then Call SysSetObjectData '<WP_START>', 'OPEN=DEFAULT;'
Call AddShad 'System Clock',, /* Title */
'<WP_START>',, /* Location for shadow object */
'<WP_CLOCK>',, /* Value of existing objectid of file */
'<SHAD_WP_CLOCK>' /* New unique value of this shadow object */
Say '';Say 'All done, if you would like me to remove the objects press R'
parse upper value SysGetKey('NOECHO') with key
If key='R' Then Do
Call SysDestroyObject '<SHAD_WP_EPM>'
Call SysDestroyObject '<SHAD_WP_OS2WIN>'
Call SysDestroyObject '<SHAD_WP_CLOCK>'
Call SysDestroyObject '<SHAD_WP_DESKTOP>'
Call SysDestroyObject '<SHAD_CONFIG_SYS>'
End
Say '';Say 'Demonstration over...'
Exiter:
Call SysDropFuncs
Exit
/* Routine to create a shadow object when passed arguments: */
/* Title, Location, ShadowId, and ObjectId */
AddShad:
Parse arg title,loc,shadowid,objectid
Say '';Say 'Press Y to add shadow object: 'title' to 'loc
parse upper value SysGetKey('NOECHO') with key
If key='Y' Then Do
setup='SHADOWID='shadowid';OBJECTID='objectid';'
/*The basic call is listed next. */
/*rc=SysCreateObject(classname,title,location <,setup>, <,duplicateflag>)*/
/* Build object using FAIL as duplicateflag */
result=SysCreateObject('WPShadow', title, loc, setup, 'F')
If result=1 Then Say 'Object created'
Else Say 'Not created, return code='result
End
Return
ΓòÉΓòÉΓòÉ 5.7.4. FLDSHAD.CMD ΓòÉΓòÉΓòÉ
/* FLDSHAD.CMD: Sample code using REXXUTIL function calls */
/* */
/* Builds a folder on the DeskTop places a program object in it then */
/* places a shadow of the program object on the DeskTop. */
/* */
/* Demonstrates use of these REXXUTIL functions: */
/* SysCreateObject - create or update an object */
/* SysDestroyObject - delete an object */
/* SysSetObjectData - update an existing object */
/* */
/* Mike Lamb: MIKELAMB/KGNVMC / 30NC/370 Neighborhood Rd */
/* ISSC MHV - Solution Center / Kingston NY 12401 */
/* Version 1.1 */
/* Load REXXUTIL */
Call RxFuncAdd 'SysLoadFuncs','RexxUtil','SysLoadFuncs'
Signal on Syntax Name LoadCheck
Call SysLoadFuncs
LoadCheck: /* rc of 43 means REXXUTILs not found */
If rc=43 Then Do
Say ''
Say 'ERROR: Not able to load REXXUTILs. Perhaps REXX not installed or'
Say ' REXXUTIL.DLL not found in a LIBPATH drive/directory.'
Exit
End
Signal off Syntax
/*The basic call is listed next. */
/*rc=SysCreateObject(classname, title, location <,setup>, <,duplicateflag>)*/
call SysCls
Say '';Say 'Using REXXUTILs to Add Folder/Program/Shadow Objects...'
Say '';Say 'Press Y to add Test Folder to Desktop...';Say '';
parse upper value SysGetKey('NOECHO') with key
If key<>'Y' Then Signal Exiter
classname='WPFolder'
title ='Test Folder'
location ='<WP_DESKTOP>'
setup ='OBJECTID=<TEST2_FOLDER>'
Call BldObj
Say '';
Say 'Press ENTER and we will open up that folder and watch as an object'
Say 'is added into it.'
key=SysGetKey()
Call SysSetObjectData '<TEST2_FOLDER>', 'OPEN=DEFAULT;'
classname='WPProgram'
title ='SYSLEVEL-VIO'
location ='<TEST2_FOLDER>'
setup ='OBJECTID=<TEST2_SYSLVIO>;']],
'EXENAME=\OS2\SYSLEVEL.EXE;']],
'PROGTYPE=WINDOWABLEVIO;'
Call BldObj
Say '';
Say 'Press ENTER and we will place a shadow of the new object on the Desktop.'
key=SysGetKey()
classname='WPShadow'
title ='SYSLEVEL-VIO'
location ='<WP_DESKTOP>'
setup ='SHADOWID=<TEST2_SYSLVIO>;OBJECTID=<SHAD_TEST2_SYSLVIO>;'
Call BldObj
Say ''
Say 'All done, now we will remove the objects by using...'
Say '...the SysDestroyObject call.'
Say 'Note: If you delete a folder all objects contained within are removed.'
Say 'Press ENTER to watch the objects disappear...'
key=SysGetKey()
Call SysDestroyObject '<SHAD_TEST2_SYSLVIO>'
Call SysDestroyObject '<TEST2_FOLDER>'
Exiter:
Call SysDropFuncs
Exit
/* Build Object */
BldObj:
call charout ,'Building: 'title
/*The basic call is listed next. */
/*rc=SysCreateObject(classname, title, location <,setup>, <,duplicateflag>) */
/* Build object using UPDATEIFEXIST as duplicateflag */
result = SysCreateObject(classname, title, location, setup, 'U')
If result=1 Then call charout ,'... Object created!'
Else call charout ,'... Not created! Return code='result
Say '';
Return
ΓòÉΓòÉΓòÉ 5.7.5. MKSHAD.CMD ΓòÉΓòÉΓòÉ
/* MKSHAD.CMD: Sample code using REXXUTIL function calls */
/* */
/* Builds shadows when passed names of files, drive/directories, or */
/* existing objectid of WorkPlace Shell objects. */
/* */
/* Enter: MKSHAD ? for more information */
/* */
/* Mike Lamb: MIKELAMB/KGNVMC / 30NC/370 Neighborhood Rd */
/* ISSC MHV - Solution Center / Kingston NY 12401 */
/* Version 1.0 */
/* Load REXXUTIL */
Call RxFuncAdd 'SysLoadFuncs','RexxUtil','SysLoadFuncs'
Signal on Syntax Name LoadCheck
Call SysLoadFuncs
LoadCheck: /* rc of 43 means REXXUTILs not found */
If rc=43 Then Do
Say ''
Say 'ERROR: Not able to load REXXUTILs. Perhaps REXX not installed or'
Say ' REXXUTIL.DLL not found in a LIBPATH drive/directory.'
Exit
End
Signal off Syntax
Parse arg name loc how
If name='?' ] translate(name)='HELP' Then Signal Helper
yes=1;no=0;
name=strip(name,'B','"')
loc=strip(loc,'B','"')
how=strip(how,'B','"')
hname=name
/* Default is to prompt before creating shadow unless /N is passed */
If translate(how)='/N' Then Do,
how=''; quiet=yes;
End
Else If translate(loc)='/N' Then Do
loc=''; quiet=yes;
End
Else If translate(name)='/N' Then Do
name=''; quiet=yes;
End
Else quiet=no;
/* If no parm is passed assume need current directory shadowed on desktop */
If name='' Then name=directory()
/* Passing an objectid to be shadowed */
Else If left(name,1)='<' & right(name,1)='>' Then Do
/* Check to see if it exists, build a list of all existing objectids */
App='PM_Workplace:Location'
call SysIni 'USER', App, 'All:', 'ObjIDTab'
Do t=1 to ObjIDTab.0
If name=ObjIDTab.t Then leave
End
If name<>ObjIDTab.t Then Do
Say 'ERROR! Objectid:' name' not found'
Signal Exiter
End
End
Else Do
/* If this file exists then no need to check other possibilities */
Fname=stream(name,'C','Q EXISTS')
If fname<>'' Then name=fname /* fully qualified name is returned */
Else Do /* Must be a drive/directory passed */
If right(name,1)<>'\' Then name=name]]'\'
name=filespec('drive',name)]]filespec('path',name)
name=strip(name,'T','\')
If right(name,1)=':' Then name=name]]'\'
Call SysFileTree name, mystem, 'D'
If mystem.0=0 Then Do
Say 'Sorry, cannot tell what should be shadowed.'
Say 'The value:' hname
Say 'Is not a file nor drive/directory that exists.'
Signal Exiter
End
End
End
/* Location processing */
If loc<>'' Then Do
/* Check to see if location exists, build list of all existing objectids */
App='PM_Workplace:Location'
call SysIni 'USER', App, 'All:', 'ObjIDTab'
Do t=1 to ObjIDTab.0
If loc=ObjIDTab.t Then leave
End
If loc<>ObjIDTab.t Then Do
Say 'WARNING! Location:' loc' not found'
Say 'Will create shadow on DeskTop instead.'
loc='<WP_DESKTOP>'
End
End
Else loc='<WP_DESKTOP>'
/* If an objectid then strip < character, leave end in */
If left(name,1)='<' & right(name,1)='>' Then obj='<SHAD_'strip(name,'B','<')
Else obj='<SHAD_'name'>'
If quiet=no Then Do
Say 'Create a shadow of :' name
Say 'Location to be created :' loc
Say 'Objectid for the object :' obj
Say 'To create press C any other key ends the program'
parse upper value SysGetKey('NOECHO') with key
If key<>'C' Then Signal Exiter
End
setup='SHADOWID='name';OBJECTID='obj';'
result=SysCreateObject('WPShadow', ' ', loc, setup, 'U')
If quiet=no Then Do
If result=1 Then Say 'Shadow object created'
Else Say 'Not created, return code='result
End
/* Common exit point */
Exiter:
Call SysDropFuncs
Exit
/* Help Routine */
Helper:
Say '** MKSHAD ** Make a shadow object'
Say 'Syntax: MKSHAD [name] [location] [/n]'
Say 'If no parameters are passed it is assumed you want the current drive'
Say 'and directory shadowed to the DeskTop.'
Say 'Otherwise you can specify the name of an existing objectid, and existing'
Say 'file, or drive/directory to be shadowed. Followed by the location of'
Say 'where the shadow should be placed. If no location is specified then the'
Say 'DeskTop is assumed. The location should be an existing objectid of a'
Say 'folder and should be enclosed in double quotes, i.e. "<WP_STARTUP>"'
Say 'Look at your \OS2\INI.RC for many existing objectids for system objects.'
Say 'If you use /N then you are not prompted for confirmation, the object'
Say 'will immediately be created.'
Say '---Examples---'
Say ' MKSHAD C:\OS2'
Say ' - Shadow of C:\OS2 directory placed on the DeskTop.'
Say ' MKSHAD "<WP_OS2WIN>" "<WP_STARTUP>"'
Say ' - Shadow of OS/2 Window object placed into Startup folder.'
Say ' MKSHAD C:\CONFIG.SYS /n'
Say ' - Shadow of CONFIG.SYS placed on the DeskTop, no prompts.'
Say ' MKSHAD C:\OS2\MDOS\WINOS2\README.ATM "<WP_INFO>"'
Say ' - Shadow of README.ATM placed in the Information folder.'
Signal Exiter
ΓòÉΓòÉΓòÉ 5.7.6. STARTDOS.CMD ΓòÉΓòÉΓòÉ
/* STARTDOS.CMD: Sample code using REXXUTIL's SysCreateObject function */
/* Starts a DOS program using specific DOS VDM settings. This is */
/* particularly useful for LAN execution that requires NET USE commands.*/
/* The example invokes the PKZIP.EXE program using files setting of 45 */
/* Rick McGuire: MCGUIRE/GDLVM7 */
/* Load REXXUTIL */
call rxfuncadd sysloadfuncs, rexxutil, sysloadfuncs
call sysloadfuncs
/* The basic call is listed next. */
/* result = SysCreateObject(classname, title, location, setup) */
classname='WPProgram'
title='My DOS Program'
location='<WP_NOWHERE>' /* place in invisible folder */
program='EXENAME=C:\PKZIP.EXE;' /* DOS program name */
type='PROGTYPE=WINDOWEDVDM;' /* type of DOS session (windowed) */
startup='STARTUPDIR=C:\;' /* startup directory */
settings='SET DOS_FILES=45;' /* required DOS settings */
open='OPEN=DEFAULT;' /* open now */
call SysCreateObject classname, title, location,,
program]]type]]startup]]settings]]open, 'REPLACE'
Return
ΓòÉΓòÉΓòÉ 5.7.7. BOOTDOS.CMD ΓòÉΓòÉΓòÉ
/* BOOTDOS.CMD: Sample code using REXXUTIL's SysCreateObject function */
/* Starts a DOS session, booting from a specific DOS image with */
/* specific DOS VDM settings. */
/* Rick McGuire: MCGUIRE/GDLVM7 */
/* Load REXXUTIL */
call rxfuncadd sysloadfuncs, rexxutil, sysloadfuncs
call sysloadfuncs
/* The basic call is listed next. */
/* result = SysCreateObject(classname, title, location, setup) */
classname='WPProgram'
title='Booted DR DOS'
location='<WP_NOWHERE>' /* place in invisible folder */
program='EXENAME=*;' /* DOS program name (use shell) */
type='PROGTYPE=WINDOWEDVDM;' /* type of DOS session (windowed) */
image='C:\DRDOS.VM;' /* DOS image file */
/* required DOS settings */
settings='SET DOS_BACKGROUND_EXECUTION=ON;'
open='OPEN=DEFAULT;' /* open now */
call SysCreateObject classname, title, location,,
program]]type]]image]]settings]]open, 'REPLACE'
Return
ΓòÉΓòÉΓòÉ 5.7.8. REBUILD.CMD ΓòÉΓòÉΓòÉ
/* REBUILD.CMD: Sample code using REXXUTIL's SysCreateObject function */
/* Can be used to rebuild objects created during the installation of */
/* your OS/2 system. The \OS2\INSTALL\INI.RC file contains information */
/* that can be used by the SysCreateObject function. */
/* The INI.RC file is used by MAKEINI.EXE to create your OS2.INI file */
/* */
/* Syntax: Enter "REBUILD ?" for complete syntax */
/* */
/* Mike Lamb: MIKELAMB/KGNVMC / 30NC/370 Neighborhood Rd */
/* ISSC MHV - Solution Center / Kingston NY 12401 */
/* Version 1.1 */
'@ECHO OFF'
/* Load REXXUTIL */
Call RxFuncAdd 'SysLoadFuncs','RexxUtil','SysLoadFuncs'
Signal on Syntax Name LoadCheck
Call SysLoadFuncs
LoadCheck: /* rc of 43 means REXXUTILs not found */
If rc=43 Then Do
Say ''
Say 'ERROR: Not able to load REXXUTILs. Perhaps REXX not installed or'
Say ' REXXUTIL.DLL not found in a LIBPATH drive/directory.'
Exit
End
Signal off Syntax
Arg parms
cmdparms=parms /* Save command line parms for later processing */
/* Until REXXUTIL offers a function call to retrieve the OS2 boot drive */
/* we assume the environment variable COMSPEC has location of boot drive. */
BtDrv=filespec('drive',value('COMSPEC',,'OS2ENVIRONMENT'))
parse upper var cmdparms type '(' inifile .
/* If user does not enter location of *.RC file then try to find it */
If inifile='' Then inifile=BtDrv]]'\OS2\INI.RC'
rcx=stream(inifile,'C','Q EXISTS')
If rcx='' Then Do
Say '';Say '';Say inifile 'not found'
Signal Exiter
End
type=left(type,1)
If verify(type,'FPOA') Then Signal Helper
/* Initialize tables and table counters */
iniftab.=''; iniptab.='' iniotab.=''; /*Folders, Programs, Others */
iniflns=0; iniplns=0; iniolns=0;
initab.=''; inilns=0;
Call stream inifile,'C','CLOSE'
Do while lines(inifile)>0 /* Read RC file into tables */
lne=linein(inifile)
parse var lne '"PM_InstallObject"' lne
If lne\='' Then Do
parse var lne '"'rest1'" 'lne
parse var lne '"'setup'"'
parse var rest1 title';'object';'location';'
If object='WPFolder' Then Do
iniflns=iniflns+1
iniftab.1.iniflns=object; iniftab.2.iniflns=title;
iniftab.3.iniflns=location; iniftab.4.iniflns=setup;
End
Else If object='WPProgram' Then Do
iniplns=iniplns+1
iniptab.1.iniplns=object; iniptab.2.iniplns=title;
iniptab.3.iniplns=location; iniptab.4.iniplns=setup;
End
Else Do
iniolns=iniolns+1
iniotab.1.iniolns=object; iniotab.2.iniolns=title;
iniotab.3.iniolns=location; iniotab.4.iniolns=setup;
End
End
End
Call stream inifile,'C','CLOSE'
/* Calculation for screen loop */
parse value SysTextScreenSize() with row col
scrsz=row-12
If type='F' ] type='A' Then Do; /* Folder routine */
objt='Folder'; inilns=iniflns;
Do i=1 to inilns; Do j=1 to 4;
initab.j.i=iniftab.j.i
End; End;
Call DispSel
End;
If type='P' ] type='A' Then Do; /* Program routine */
objt='Program'; inilns=iniplns;
Do i=1 to inilns; Do j=1 to 4;
initab.j.i=iniptab.j.i
End; End;
Call DispSel
End;
If type='O' ] type='A' Then Do; /* Other routine */
objt='Other'; inilns=iniolns;
Do i=1 to inilns; Do j=1 to 4;
initab.j.i=iniotab.j.i
End; End;
Call DispSel
End;
Exiter: /* When get here done with processing */
Call SysDropFuncs
Exit
/* Routine to display objects and allow selection */
DispSel:
key=''
Do while key\='Q'
Call SysCls; Say '';Say objt' objects found in: 'inifile;Say '';
Do i=1 to inilns
If trunc(i/scrsz)==i/scrsz Then Call Promptx 1
If key='Q' Then leave
n=right(' ']]i,3)]]') ']]left(initab.2.i]]copies(' ',30),30)
n=n]]left(initab.3.i]]copies(' ',20),20)
Say n
End
If key\='Q' Then Call Promptx 0
End
Return
/* Screen loop routine also calls object build routine */
Promptx: Arg scr
Say '';Say 'To attempt to rebuild an object enter the number of the object'
If scr=0 Then Say 'or enter Q to quit...'
Else Say 'or press enter to show next screen... Or enter Q to Quit...'
pull key .
If (key>=1) & (key <=inilns) then Do
rcx=BldIt(initab.1.key,initab.2.key,initab.3.key,initab.4.key)
/* Ask if want objects in folder rebuilt */
If object='WPFolder' Then Do
Say '';Say 'Press Y to recreate the program objects in this folder.'
parse upper value SysGetKey('NOECHO') with ansr
If ansr='Y' Then Do
parse var setup 'OBJECTID='obj';'
Do ii=1 to iniplns;
If iniptab.3.ii=obj Then Do
rcx=BldIt(iniptab.1.ii,iniptab.2.ii,iniptab.3.ii,iniptab.4.ii)
End
End;
End;
End;
End;
If scr=1 Then Do;
Call SysCls;Say '';Say objt' objects found in: 'inifile;Say '';
End;
Return
/* Routine to build object */
BldIt: Parse Arg object,title,location,setup
Say 'Command generated:'
Say 'SysCreateObject('object', 'title', 'location', 'setup', U)'
/* Build object using UPDATE as duplicateflag */
result = SysCreateObject(object, title, location, setup, 'U')
If result=1 Then Say '... Object created!'
Else Say '... Not created! Return code='result
Say '';Say 'Press any key to continue...'
SysGetKey('NOECHO')
Return result
/* Syntax help */
Helper:
call SysCls
Say '';Say ''; Say 'REBUILD:'
Say 'Routine to rebuild system installed objects listed in *.RC files.'
Say 'Can be used as an alternative to using the MAKEINI command.'
Say 'Your INI.RC file is used by MAKEINI.EXE during installation to'
Say 'create your OS2.INI file.'
Say ''; Say 'Syntax:';Say '';
Say 'REBUILD object [(filespec]'
Say '';Say 'Valid objects A(ll), F(olders), P(rograms), O(ther)'
Say 'Can also can use (filespec for name of *.RC file, default is \OS2\INI.RC'
Signal Exiter
ΓòÉΓòÉΓòÉ 5.7.9. LPTADD.CMD ΓòÉΓòÉΓòÉ
/* LPTADD.CMD: Sample code using REXXUTIL's SysIni function. */
/* Routine will expand the number of LPT ports the WorkPlace Shell */
/* recognizes from LPT1-3 to LPT1-9. Also a routine to add LPT3-9 to */
/* the WIN-OS2 WIN.INI file. */
/* Mike Lamb: MIKELAMB/KGNVMC / 30NC/370 Neighborhood Rd */
/* ISSC MHV - Solution Center / Kingston NY 12401 */
/* Version 1.0 */
'@ECHO OFF'
/* Load REXXUTIL */
call rxfuncadd sysloadfuncs, rexxutil, sysloadfuncs
call sysloadfuncs
/* The basic call for setting a single key value is listed next. */
/* result = SysIni([inifile], app, key, val) */
call SysCls; Say '';
Say 'Using REXXUTILs SysIni call to add LPT4-9 to the WorkPlace Shell'
Say '';Say 'Press Y to add/initialize LPT4-9 ports...';Say '';
parse upper value SysGetKey('NOECHO') with key
If key='Y' Then Do
Say 'LPT Ports: setting up for LPT4-9 ports...'
Do n=4 to 9
Say ' Setting up PM_LPT'n'...'
rx=SysIni('SYSTEM', 'PM_SPOOLER_PORT', 'LPT'n, ';']]'00'x)
If rx\='' Then Say 'LPT'n' Bad result='result
rx=SysIni('SYSTEM', 'PM_LPT'n, 'DESCRIPTION', 'LPT']]n]]'00'x)
If rx\='' Then Say 'LPT'n' Bad result='result
rx=SysIni('SYSTEM', 'PM_LPT'n, 'INITIALIZATION', ';']]'00'x)
If rx\='' Then Say 'LPT'n' Bad result='result
rx=SysIni('SYSTEM', 'PM_LPT'n, 'PORTDRIVER', 'PARALLEL;']]'00'x)
If rx\='' Then Say 'LPT'n' Bad result='result
rx=SysIni('SYSTEM', 'PM_LPT'n, 'TERMINATION', ';']]'00'x)
If rx\='' Then Say 'LPT'n' Bad result='result
rx=SysIni('SYSTEM', 'PM_LPT'n, 'TIMEOUT', '45;']]'00'x)
If rx\='' Then Say 'LPT'n' Bad result='result
End
Say 'LPT4-9 added... Press any key to continue...'
SysGetKey('NOECHO')
End
call SysCls; Say '';
Say 'Can now attempt to add LPT3-9 to your WIN-OS2 WIN.INI file.'
Say '';Say 'Press Y to attempt to add LPT3-9 ports to WIN-OS2...';Say '';
parse upper value SysGetKey('NOECHO') with key
If key='Y' Then Do
/* Change \OS2\MDOS\WINOS2\WIN.INI to add more ports LPT3-LPT9 */
win.='';winnew.='';
/* Until REXXUTIL offers a function call to retrieve the OS2 boot drive */
/* we assume the environment variable COMSPEC has location of boot drive. */
BtDrv=filespec('drive',value('COMSPEC',,'OS2ENVIRONMENT'))
fn=BtDrv'\OS2\MDOS\WINOS2\WIN.INI';
fnx=stream(fn,'C','QUERY EXISTS')
fn=fnx;
If fn\='' Then Do /* If file exists then process adding extra ports */
Call stream fn,'C','CLOSE'
Do i=1 to 10000 while LINES(fn)>0
parse value linein(fn) with win.i
End
Call stream fn,'C','CLOSE'
i=i-1; k=0;
Do j=1 to i /* Look for FILE:= then if line before = LPT2.OS2= add 3-9 */
If win.j='FILE:=' Then Do
m=j-1; winchg=no;
If win.m='LPT2.OS2=' Then Do
Say 'LPT Ports: setting up for Windows LPT3-9 ports...'
winchg=yes;
Do n=3 to 9
Say ' Setting up: LPT'n'.OS2='
k=k+1; winnew.k='LPT'n'.OS2='
End;
End;
End;
k=k+1;
winnew.k=win.j;
End;
If winchg=yes Then Do;
parse var fnx fnx'.' .
ifn=fnx]]'.???';
ifn=SysTempFileName(ifn)
'@COPY' fn ifn '1>NUL 2>NUL' /* Copy original to backup name */
Say 'Copy of' fn 'saved as' ifn
Say 'Writing' fn 'with added lines.'
call lineout fn,,1 /* Start writing at first character */
Do i=1 to k /* write file back out */
call lineout fn,winnew.i
End
Call stream fn,'C','CLOSE'
End;
Else Say 'Lines not added, either already done or not what we expect.'
End;
Else Say 'Could not locate' fn 'program ending...'
End;
Say 'LPTADD ending...'
Call SysDropFuncs
Exit
ΓòÉΓòÉΓòÉ 5.7.10. OBJECTID.CMD ΓòÉΓòÉΓòÉ
/* OBJECTID.CMD: Sample code using REXXUTIL's SysIni function. */
/* Routine will display the OBJECTIDs known to the WorkPlace Shell */
/* Mike Lamb: MIKELAMB/KGNVMC / 30NC/370 Neighborhood Rd */
/* ISSC MHV - Solution Center / Kingston NY 12401 */
/* Version 1.1 */
'@ECHO OFF'
/* Load REXXUTIL */
call rxfuncadd sysloadfuncs, rexxutil, sysloadfuncs
call sysloadfuncs
/* List ObjectIds */
App='PM_Workplace:Location'
call SysIni 'USER', App, 'All:', 'Keys'
if Result \= 'ERROR:' then do
Call SysCls
Say '';Say '';
Say 'Listing ObjectId information (value enclosed in quotes)'; Say '';
parse value SysTextScreenSize() with row col
j=row-10
Do i=1 to Keys.0
If trunc(i/j)==i/j Then Do
Say '';Say 'Press any key to show next screen...'
key=SysGetKey()
Call SysCls
Say '';Say '';
Say 'Listing ObjectId information (value enclosed in quotes)'; Say '';
End
Say '"'Keys.i'"'
End
End
Else Say 'Error querying for' App
Call SysDropFuncs
Exit
ΓòÉΓòÉΓòÉ 5.7.11. FONTS.CMD ΓòÉΓòÉΓòÉ
/* FONTS.CMD: Sample code using REXXUTIL's SysIni function. */
/* Routine will display the FONTS known to the WorkPlace Shell, */
/* verifies that the font file exists and also if passed REBUILD as a */
/* parameter will rebuild the INI entries based upon INI.RC values. */
/* Mike Lamb: MIKELAMB/KGNVMC / 30NC/370 Neighborhood Rd */
/* ISSC MHV - Solution Center / Kingston NY 12401 */
/* Version 1.1 */
'@ECHO OFF'
/* Load REXXUTIL */
Call RxFuncAdd 'SysLoadFuncs','RexxUtil','SysLoadFuncs'
Signal on Syntax Name LoadCheck
Call SysLoadFuncs
LoadCheck: /* rc of 43 means REXXUTILs not found */
If rc=43 Then Do
Say ''
Say 'ERROR: Not able to load REXXUTILs. Perhaps REXX not installed or'
Say ' REXXUTIL.DLL not found in a LIBPATH drive/directory.'
Exit
End
Signal off Syntax
Parse upper arg parm
App='PM_Fonts'
/* Until REXXUTIL offers a function call to retrieve the OS2 boot drive */
/* we assume the environment variable COMSPEC has location of boot drive. */
BtDrv=filespec('drive',value('COMSPEC',,'OS2ENVIRONMENT'))
If Parm<>'REBUILD' Then Do
call SysIni 'USER', App, 'All:', 'Keys'
If Result \= 'ERROR:' then do
Do j=1 to Keys.0
fname=space(SysIni('USER', App, Keys.j))
msg=''
If stream(BtDrv]]fname,'C','Q EXISTS')='' Then,
msg='**Font file not found***';
Keys.j=Keys.j 'Installed as:' fname ]] msg
End
Call SysCls
Say '';Say '';Say 'Listing Installed Fonts';Say '';
parse value SysTextScreenSize() with row col
j=row-10
Do i=1 to Keys.0
If trunc(i/j)==i/j Then Do
Say '';Say 'Press any key to show next screen...'
key=SysGetKey()
Call SysCls
Say '';Say '';Say 'Listing Installed Fonts';Say '';
End
Say left(Keys.i,75)
End
End
Else Say 'Error querying for' App
End
Else Do /* Requesting to rebuild fonts as listed in INI.RC */
inifile=BtDrv]]'\OS2\INI.RC'
rcx=stream(inifile,'C','Q EXISTS')
If rcx='' Then Do
Say '';Say '';
Say inifile 'not found, cannot rebuild PM_Fonts INI entries'
Signal Exiter
End
Do while lines(inifile)>0
lne=linein(inifile)
parse var lne '"PM_Fonts"' lne
If lne\='' Then Do
parse var lne '"'key'" 'lne
parse var lne '"'val'"'
msg=''
Call charout ,'Building' left(key,13) left(val,25)
If stream(BtDrv]]val,'C','Q EXISTS')='' Then,
Say ' ** Font file 'BtDrv]]val' not found.'
Else Do
Call SysIni 'USER', App, key, val
If result='' Then Say ' ...Okay...'
Else Say ' ...'result
End
End
End
Call stream inifile,'C','CLOSE'
End
Say ''
Say 'FONTS completed, will display the FONTS known to the WorkPlace Shell,'
Say 'and verify that the font file exists. Also if passed REBUILD as a'
Say 'parameter will rebuild the INI entries based upon INI.RC values.'
Exiter:
Call SysDropFuncs
Exit
ΓòÉΓòÉΓòÉ 5.7.12. ICONRES.CMD ΓòÉΓòÉΓòÉ
/* ICONRES.CMD: Sample code using REXXUTIL's SysCreateObject function */
/* Routine will create a folder containing many icons available in */
/* installed DLLs on an OS/2 V2 system. Shows how to use the setup */
/* string parm: ICONRESOURCE */
/* Mike Lamb: MIKELAMB/KGNVMC / 30NC/370 Neighborhood Rd */
/* ISSC MHV - Solution Center / Kingston NY 12401 */
/* Version 1.0 */
'@ECHO OFF'
/* Load REXXUTIL */
call rxfuncadd sysloadfuncs, rexxutil, sysloadfuncs
call sysloadfuncs
call SysCls
Say '';
Say 'Using REXXUTILs to demonstrate use of the ICONRESOURCE parameter.'
Say 'A folder will be created and populated with various icons found'
Say 'in some installed DLL files.'
Say '';
Say 'ICONRESOURCE is a SysCreateObject setup string parameter, has syntax:'
Say '';
Say ' ICONRESOURCE=id module Ex: ICONRESOURCE=3 PMWP;'
Say ' id=number of the icon resource, module=filename of the DLL'
Say ''; Say 'NOTE: Over 70 icons, program will run for a minute or two.'
Say ' After program ends the WPS will continue to resolve objects, also'
Say ' the building of the objects adds approx 100K to your OS2.INI.'
Say '';Say 'Press Y to add the folder to Desktop and populate...';Say '';
parse upper value SysGetKey('NOECHO') with key
If key<>'Y' Then Signal Exiter
/* Build folder for icons */
call charout ,'Building: ICONRESOURCE Icon Folder'
result = SysCreateObject('WPFolder', 'ICONRESOURCE'x2c(A)'Icon Folder',,
'<WP_DESKTOP>', 'OBJECTID=<ICN_FOLDER>;', 'U')
If result=1 Then call charout ,'... Object created!'
Else call charout ,'... Not created! Return code='result
Say '';
classname='WPAbstract'
location='<ICN_FOLDER>'
/* WPCONFIG 1-13 WPPRTMRI 3-16 19-23 */
fn='PMWP'
Do i=1 to 75
If i<5 ] i=13 ] (i>15 & i<21) ] i=22 ] (i>23 & i<30) ] i=32 ] i=33,
] i=44 ] i=46 ] i=48 ] i=52 ] i=53 ] (i>55 & i<73) Then Call BldObj
End
fn='WPCONFIG'
Do i=1 to 13
Call BldObj
End
fn='WPPRTMRI'
Do i=3 to 23
If (i<17 ] i>18) Then Call BldObj
End
Say '';Say 'All done, to remove drag folder to shredder...'
Exiter:
Call SysDropFuncs
Exit
/* Build Object */
BldObj:
if i<10 then j='0']]i
else j=i
title=fn'-']]j
setup='ICONRESOURCE=']]j]]' 'fn';OBJECTID=<ICN-'fn'-']]j]]'>'
call charout ,'Building: 'title
result = SysCreateObject(classname, title, location, setup, 'U')
If result=1 Then call charout ,'... Object created!'
Else call charout ,'... Not created! Return code='result
Say '';
Return
ΓòÉΓòÉΓòÉ 5.7.13. SWAPEDIT.CMD ΓòÉΓòÉΓòÉ
/* SWAPEDIT.CMD: Sample code using REXXUTIL function calls */
/* */
/* Swaps the OS/2 System Editor (E) with the Enhanced Editor (EPM). */
/* */
/* Enter: SWAPEDIT for more information */
/* */
/* Mike Lamb: MIKELAMB/KGNVMC / 30NC/370 Neighborhood Rd */
/* ISSC MHV - Solution Center / Kingston NY 12401 */
/* Version 1.0 */
/* Load REXXUTIL */
Call RxFuncAdd 'SysLoadFuncs','RexxUtil','SysLoadFuncs'
Signal on Syntax Name LoadCheck
Call SysLoadFuncs
LoadCheck: /* rc of 43 means REXXUTILs not found */
If rc=43 Then Do
Say ''
Say 'ERROR: Not able to load REXXUTILs. Perhaps REXX not installed or'
Say ' REXXUTIL.DLL not found in a LIBPATH drive/directory.'
Exit
End
Signal off Syntax
Parse arg parm
/* Default is to prompt before swapping unless /N is passed */
If translate(parm)<>'/N' Then Call Logo
/* First apply the same associations to EPM as the System Editor */
setup ='ASSOCTYPE=Plain Text,OS/2 Command File,DOS Command File,,;']],
'ASSOCFILTER=*.DOC,*.TXT,,;'
result=SysSetObjectData('<WP_EPM>',setup)
If result=1 Then Say 'EPM object updated...'
Else Say 'EPM object NOT updated! Return code='result
/* Now Replace the System Editor object (gets deleted then recreated) */
title ='OS/2 System Editor'
setup ='OBJECTID=<WP_SYSED>;']],
'EXENAME=E.EXE;']],
'ASSOCTYPE=Plain Text,OS/2 Command File,DOS Command File,,;']],
'ASSOCFILTER=*.DOC,*.TXT,,;']],
'HELPPANEL=9289;']],
'PROGTYPE=PM;'
result=SysCreateObject('WPProgram', title, '<WP_TOOLS>', setup, 'R')
If result=1 Then Say 'System Editor object recreated...'
Else Say 'System Editor object NOT created! Return code='result
/* Common exit point */
Exiter:
Call SysDropFuncs
Exit
/* Introductory message and confirmation */
Logo:
Call SysCls; Say; Say;
Say 'SWAPEDIT: Swap OS/2 System Editor (E) with the Enhanced Editor (EPM)'
Say ''
Say 'Some users of OS/2 would rather use the EPM editor for default actions'
Say 'against data file objects. One way to do this is to place the same'
Say 'associations on EPM as are on E, then delete and recreate the E program'
Say 'object. Use: SWAPEDIT /N to perform the operation with no confirmation.'
Say ''
Say 'This program will place the same initial associations the OS/2 System'
Say 'Editor had on the Enhanced Editor. Then recreate the OS/2 System Editor'
Say 'program object. Afterwards for data file objects you will see the'
Say 'Enhanced Editor as the default choice and optionally you can use the'
Say 'OS/2 System Editor if you select the Open setting.'
Say ''
Say 'WARNING: Some files are over 255 characters in length and the EPM'
Say ' editor does not support this, so when editing files such as'
Say ' your CONFIG.SYS you should probably use the OS/2 System Editor.'
Say ''
Say 'Press C to continue or any other key to end the program'
parse upper value SysGetKey('NOECHO') with key
If key<>'C' Then Signal Exiter
Return
ΓòÉΓòÉΓòÉ 5.7.14. OPENWPS.CMD ΓòÉΓòÉΓòÉ
/* OPENWPS.CMD: Sample code using REXXUTIL function calls */
/* */
/* REXX Command file that allows you to open various views of objects. */
/* */
/* Enter: OPENWPS ? for more information */
/* */
/* Mike Lamb: MIKELAMB/KGNVMC / 30NC/370 Neighborhood Rd */
/* ISSC MHV - Solution Center / Kingston NY 12401 */
/* Version 1.0 */
/* Load REXXUTIL */
Call RxFuncAdd 'SysLoadFuncs','RexxUtil','SysLoadFuncs'
Signal on Syntax Name LoadCheck
Call SysLoadFuncs
LoadCheck: /* rc of 43 means REXXUTILs not found */
If rc=43 Then Do
Say ''
Say 'ERROR: Not able to load REXXUTILs. Perhaps REXX not installed or'
Say ' REXXUTIL.DLL not found in a LIBPATH drive/directory.'
Exit
End
Signal off Syntax
Parse Arg parm
If parm='?' ] translate(parm)='HELP' Then Signal Helper
quiet=0; /* Set default message display */
type='DEFAULT' /* Set default open type */
objid='' /* Set default object to open */
Do i=1 to words(parm)
prm=word(parm,i)
uparm=translate(prm)
Select /* See if value is an open type */
when uparm='SETTINGS' Then type='SETTINGS'
when uparm='DEFAULT' Then type='DEFAULT'
when uparm='DETAILS' Then type='DETAILS'
when uparm='TREE' Then type='TREE'
when uparm='ICON' Then type='ICON'
when uparm='/N' Then quiet=1
otherwise Nop
End
If objid='' Then Do
/* See if this value is an objectid */
prm2=strip(prm,'B','"')
If left(prm2,1)='<' & right(prm2,1)='>' Then Do
/* Check to see if it exists, build list of all existing objectids */
App='PM_Workplace:Location'
call SysIni 'USER', App, 'All:', 'ObjIDTab'
Do t=1 to ObjIDTab.0
If prm2=ObjIDTab.t Then leave
End
If prm2<>ObjIDTab.t Then Do
prm3=translate(prm2) /* Maybe need to uppercase value */
Do t=1 to ObjIDTab.0
If prm3=ObjIDTab.t Then leave
End
If prm3<>ObjIDTab.t Then Do
Say 'ERROR! Objectid:' prm2' not found'
Signal Exiter
End
Else objid=prm3
End
Else objid=prm2
End
Else Do
If right(prm,1)=':' Then Call SysFileTree prm'\', mystem, 'D'
Else Call SysFileTree prm, mystem, 'D'
If mystem.0<>0 Then objid=prm
End
End
End
/* If no objectid nor valid directory passed open default directory */
If objid='' Then objid=Directory()
If quiet=0 Then Say 'Opening 'type' view of 'objid
/* Call to open the object */
Call SysSetObjectData objid, 'OPEN='type
If quiet=0 Then Do
If result=1 Then Say 'Object opened'
Else Say 'Object NOT opened, return code='result
End
Exit
/* Common exit point */
Exiter:
Call SysDropFuncs
Exit
/* Help Routine */
Helper:
Call SysCls; Say; Say;
Say '** OPENWPS ** Open a WPS object or directory'
Say ''
Say 'Syntax: OPENWPS [name] [view] [/n]'
Say ''
Say 'If no parameters are passed it is assumed you want the current drive'
Say 'and directory opened using the DEFAULT view.'
Say 'Otherwise you can specify the name of an existing objectid, or'
Say 'drive/directory to be opened. Also you can specify the open view:'
Say 'Valid views: ICON TREE DETAILS SETTINGS DEFAULT'
Say ''
Say 'When you specify an objectid you must enclosed it in double quotes,'
Say 'i.e. "<WP_INFO>" Look in \OS2\INI.RC for many existing objectids.'
Say ''
Say 'If you use /N then no messages are displayed, unless problems occur.'
Say ''
Say '---Examples---'
Say ' OPENWPS OPENWPS D:\ /N '
Say ' - Open the default directory. - Open root of D:, no messages.'
Say ' OPENWPS "<WP_INFO>" OPENWPS "<WP_PULSE>" /N'
Say ' - Open the Information folder. - Open the Pulse object, no messages.'
Signal Exiter
ΓòÉΓòÉΓòÉ 5.8. Code Fragments ΓòÉΓòÉΓòÉ
ΓòÉΓòÉΓòÉ 5.8.1. System Settings ΓòÉΓòÉΓòÉ
During our attempts at customizing the shell using REXXUTILs for newly created
workstations we discovered many items can be controlled. Our first attempt was
to turn off the default setting for Workplace Shell Print Screen. We wanted it
disabled instead of enabled (saves our customers from accidentally printing the
workplace shell screen contents :-)
From there we learned other items could be changed:
Remember the basic SysIni call is:
result = SysIni(inifile, app, key, val)
Note: Some items if changed did not seem to take effect until the next reboot.
ΓòÉΓòÉΓòÉ 5.8.1.1. Confirmation ΓòÉΓòÉΓòÉ
To see the menu items that can be changed go to:
OS/2 System / System Setup / System, Confirmation tab
/* Confirm on folder delete 0=not checked 1=checked */
res=SysIni('USER', 'PM_ControlPanel', 'ConfirmSubDelete', '0']]'00'x)
/* Confirm delete 0=not checked 1=checked */
res=SysIni('USER', 'PM_ControlPanel', 'ConfirmDelete', '0']]'00'x)
/* Confirm on rename of files with extensions 0=not checked 1=checked */
res=SysIni('USER', 'PM_ControlPanel', 'ConfirmRenameFilesWithExt', '0']]'00'x)
/* Confirm on copy, move, create shadow 0=not checked 1=checked */
res=SysIni('USER', 'PM_ControlPanel', 'ConfirmCopyMoveEtc', '0']]'00'x)
/* Display progress indication dialog 0=not checked 1=checked */
res=SysIni('USER', 'PM_ControlPanel', 'DisplayProgressInd', '0']]'00'x)
ΓòÉΓòÉΓòÉ 5.8.1.2. Title ΓòÉΓòÉΓòÉ
To see the menu items that can be changed go to:
OS/2 System / System Setup / System, Title tab
/* Title clash */
/* Prompt for appropriate action 16 */
/* Auto-rename object 2 */
/* Replace existing object 8 */
result = SysIni('USER', 'PM_ControlPanel', 'NameClash', '16']]'00'x)
ΓòÉΓòÉΓòÉ 5.8.1.3. Button appearance for windows ΓòÉΓòÉΓòÉ
To see the menu items that can be changed go to:
OS/2 System / System Setup / System, Window tab
/* Hide button = 1 plus hex 0 */
result = SysIni('USER', 'PM_ControlPanel', 'MinButtonType', '1']]'00'x)
/* Minimize button = 2 plus hex 0 */
result = SysIni('USER', 'PM_ControlPanel', 'MinButtonType', '2']]'00'x)
ΓòÉΓòÉΓòÉ 5.8.1.4. Animation ΓòÉΓòÉΓòÉ
/* Enabled = hex 01 00 00 00 */
result = SysIni('USER', 'PM_ControlPanel', 'Animation', '01000000'x)
/* Disabled = hex 00 00 00 00 */
result = SysIni('USER', 'PM_ControlPanel', 'Animation', '00000000'x)
ΓòÉΓòÉΓòÉ 5.8.1.5. Minimize button behavior ΓòÉΓòÉΓòÉ
/* Hide Window = 1 plus hex 0 */
result = SysIni('USER', 'PM_ControlPanel', 'HiddenMinWindows', '1']]'00'x)
/* Minimize window to viewer = 2 plus hex 0 */
result = SysIni('USER', 'PM_ControlPanel', 'HiddenMinWindows', '2']]'00'x)
/* Minimize window to desktop = 3 plus hex 0 */
result = SysIni('USER', 'PM_ControlPanel', 'HiddenMinWindows', '3']]'00'x)
ΓòÉΓòÉΓòÉ 5.8.1.6. Object Open Behavior ΓòÉΓòÉΓòÉ
/* Display existing window; delete CCVIEW key */
result = SysIni('USER', 'PM_Workplace', 'CCVIEW', 'DELETE:')
/* Create new window; CCVIEW key set to 'ON' */
result = SysIni('USER', 'PM_Workplace', 'CCVIEW', 'ON']]'00'x)
To see the menu items that can be changed go to: OS/2 System / System Setup /
System, Print Screen tab
ΓòÉΓòÉΓòÉ 5.8.1.7. Print Screen ΓòÉΓòÉΓòÉ
/* Disable print screen */
result = SysIni('USER', 'PM_ControlPanel', 'PrintScreen', '0']]'00'x)
/* Enable print screen */
result = SysIni('USER', 'PM_ControlPanel', 'PrintScreen', '1']]'00'x)
Logo
To see the menu items that can be changed go to:
OS/2 System / System Setup / System, Logo tab
/* Indefinite */
result = SysIni('USER', 'PM_ControlPanel', 'LogoDisplayTime', '-1']]'00'x)
/* None */
result = SysIni('USER', 'PM_ControlPanel', 'LogoDisplayTime', '0']]'00'x)
/* Timed Range: Seconds:0-59 Tenths: 0-9 */
/* 100 = 0 seconds 1 tenths */
/* 2000 = 2 seconds 0 tenths (default) */
/* 59900 = 59 seconds 9 tenths */
result = SysIni('USER', 'PM_ControlPanel', 'LogoDisplayTime', '2000']]'00'x)
Change color button
To see the menu items that can be changed hightlight your desktop, then use
Open / Settings / Background tab
Select the Values button to display the numeric values you'll need for the INI
call. (Use the values when the RGB button is selected)
/* Setting Desktop background color R G B */
result = SysIni('USER', 'PM_Colors', 'Background', '204 204 204']]'00'x)
Note: Lots of other colors can be customized as well, review your \OS2\INI.RC
file for the correct App and Key fields.
ΓòÉΓòÉΓòÉ 5.8.1.8. Warning Beep ΓòÉΓòÉΓòÉ
To see the menu items that can be changed go to:
OS/2 System / System Setup / Sound
/* Turn off Warning Beep */
result = SysIni('USER', 'PM_ControlPanel', 'Beep', '0']]'00'x)
/* Turn on Warning Beep */
result = SysIni('USER', 'PM_ControlPanel', 'Beep', '1']]'00'x)
ΓòÉΓòÉΓòÉ 5.8.1.9. Note ΓòÉΓòÉΓòÉ
Remember: Most changes will not be reflected automatically. The next reboot
should pick up your changes. These calls would be best used when first building
a workstation, not for dynamic updates.
ΓòÉΓòÉΓòÉ 5.8.2. Global WIN-OS2 Settings ΓòÉΓòÉΓòÉ
With OS/2 V2.1 you are able to control certain WIN-OS/2 session properties for
all Windows applications. You can locate this new control by going to:
OS/2 System / System Setup / WIN-OS/2 Setup
The changes you make here will be reflected for all newly created objects that
use WIN-OS/2 settings. No setup string exists to change WIN_DDE, nor
WIN_CLIPBOARD on a program by program basis.
ΓòÉΓòÉΓòÉ 5.8.2.1. 3.1 Session tab ΓòÉΓòÉΓòÉ
Key PM_Global31SessionType
Value 15 - WIN-OS/2 Window separate session (3.1 Standard)
Value 16 - WIN-OS/2 Window (3.1 Standard)
Value 17 - WIN-OS/2 Window separate session (3.1 Enhanced Compatibility)
Value 18 - WIN-OS/2 Window (3.1 Enhanced Compatibility)
Value 19 - WIN-OS/2 Full screen (3.1 Enhanced Compatibility)
Value 20 - WIN-OS/2 Full screen (3.1 Standard)
Example:
/* Set global session type to WIN-OS/2 Full screen (3.1 Standard) */
result = SysIni('USER', 'WINOS2', 'PM_Global31SessionType', '20']]'00'x)
ΓòÉΓòÉΓòÉ 5.8.2.2. WIN-OS/2 Settings button ΓòÉΓòÉΓòÉ
Key PM_GlobalWin31DataExchange
Value 0 - WIN_DDE On WIN_CLIPBOARD On
Value 4 - WIN_DDE Off WIN_CLIPBOARD On
Value 8 - WIN_DDE On WIN_CLIPBOARD Off
Value 12 - WIN_DDE Off WIN_CLIPBOARD Off
Example:
/* Set DDE on, Clipboard off */
result = SysIni('USER', 'WINOS2', 'PM_GlobalWin31DataExchange', '8']]'00'x)
Key PM_GlobalWindows31Settings
Need to supply the text of DOS, WIN settings separated by nul 0 character
AND the string ends with nul 0 nul 0
Example:
/* Default settings */
setting='DPMI_MEMORY_LIMIT=64']]'00'x]],
'PROGTYPE=PROG_31_STD']]'00'x]],
'KBD_ALTHOME_BYPASS=1']]'00'x]],
'VIDEO_SWITCH_NOTIFICATION=1']]'00'x]],
'VIDEO_8514A_XGA_IOTRAP=0']]'00'x]]'00'x
result = SysIni('USER', 'WINOS2', 'PM_GlobalWindows31Settings', setting)
ΓòÉΓòÉΓòÉ 5.8.2.3. Data Exchange tab ΓòÉΓòÉΓòÉ
Data exchange between OS/2, DOS and WIN-OS/2 sessions
1. Dynamic data exchange Key PM_DDESupport
- Value 0 - Public (share with WIN-OS/2)
- Value 1 - Private (non-share with WIN-OS/2)
- Example:
/* Set DDE Private */
result = SysIni('USER', 'WINOS2', 'PM_DDESupport', '1']]'00'x)
2. Clipboard
Key PM_ClipboardSupport
- Value 0 - Public (share with WIN-OS/2)
- Value 1 - Private (non-share with WIN-OS/2)
- Example:
/* Set Clipboard Private */
result = SysIni('USER', 'WINOS2', 'PM_ClipboardSupport', '1']]'00'x)
ΓòÉΓòÉΓòÉ 6. Documentation for Various REXX Libraries ΓòÉΓòÉΓòÉ
This section contains the documentation for several REXX libraries available on
the Internet. A good starting place is hobbes.nmsu.edu in the /os2/dev32/rexx
directory.
ΓòÉΓòÉΓòÉ 6.1. rxFTP ΓòÉΓòÉΓòÉ
rxFtp
Rexx Function Package for TCP/IP FTP for OS/2 2.0
by Patrick Mueller
(c) Copyright International Business Machines Corporation 1993.
All rights Reserved.
ΓòÉΓòÉΓòÉ 6.1.1. What is rxFtp? ΓòÉΓòÉΓòÉ
rxFtp is a REXX function package providing access to the OS/2 TCP/IP FTP API as
provided by the IBM TCP/IP product, version 1.2.1.
The function package assumes you know how to use the FTP program. The function
names in the package closely resemble FTP subcommands.
This function package requires the OS/2 TCP/IP product, version 1.2.1 or
higher. A specific DLL for the OS/2 TCP/IP product, version 2.0, is included.
ΓòÉΓòÉΓòÉ 6.1.2. Installation and Removal ΓòÉΓòÉΓòÉ
The rxFtp rexx function package is contained in the file rxFtp.dll. This file
needs to be placed in a directory along your LIBPATH. To get access to the
functions in the rxFtp function package, execute the following rexx code:
rc = RxFuncAdd("FtpLoadFuncs","rxFtp","FtpLoadFuncs")
rc = FtpLoadFuncs()
If you want to use the 32-bit FTP functions available in TCP/IP for OS/2
Version 2.0, rename the "rxftp32.dll" file to "rxftp.dll".
You may not use both the 16-bit and 32-bit versions at the same time as they
have the same function names.
To unload the DLL, you should first call the FtpDropFuncs() function, then exit
all CMD.EXE shells. After exiting all the command shells, the DLL will be
dropped by OS/2 and can be deleted or replaced.
ΓòÉΓòÉΓòÉ 6.1.3. Parameters and Return Values ΓòÉΓòÉΓòÉ
ΓòÉΓòÉΓòÉ 6.1.3.1. Set errors ΓòÉΓòÉΓòÉ
The following functions return Set error codes:
FtpSetUser
FtpSetBinary
The return code is 1 if the string passed in are valid, 0 if not.
FtpSetBinary() should be passed an abbreviation of "BINARY" or "ASCII" (thus,
"b", "as", "BIN", etc).
ΓòÉΓòÉΓòÉ 6.1.3.2. FTP errors ΓòÉΓòÉΓòÉ
The rest of the functions (all the functions but the Set functions) return ftp
error conditions.
It will have one of the following values (or a numeric value if the number
isn't one of these documented values):
"0" - successful call
"-1" - Error during FTP function call
If the function returns a "-1" for a return code, the variable FTPERRNO will
be set to one of the following values:
"FTPSERVICE" - unknown service
"FTPHOST" - unknown host
"FTPSOCKET" - unable to obtain socket
"FTPCONNECT" - unable to connect to server
"FTPLOGIN" - login failed
"FTPABORT" - transfer aborted
"FTPLOCALFILE" - problem openning local file
"FTPDATACONN" - problem initializing data connection
"FTPCOMMAND" - command failed
"FTPPROXYTHIRD" - proxy server does not support third party transfers
"FTPNOPRIMARY" - no primary connection for proxy transfer
ΓòÉΓòÉΓòÉ 6.1.4. Functions Reference ΓòÉΓòÉΓòÉ
This section lists the command syntax for each function and gives a description
of it.
ΓòÉΓòÉΓòÉ 6.1.4.1. FtpLoadFuncs ΓòÉΓòÉΓòÉ
rc = FtpLoadFuncs(quiet)
Loads all the functions in the rxFtp package.
If ANY parameters are passed to this function, it will bypass the
program/author/copyright information normally displayed. All parameters are
ignored (except to determine whether or not to bypass displaying the
information).
ΓòÉΓòÉΓòÉ 6.1.4.2. FtpDropFuncs ΓòÉΓòÉΓòÉ
rc = FtpDropFuncs()
Drops all the functions in the rxFtp package.
ΓòÉΓòÉΓòÉ 6.1.4.3. FtpVersion ΓòÉΓòÉΓòÉ
rc = FtpVersion(variable)
Returns the version of RxFtp that you are running in the variable "variable".
ΓòÉΓòÉΓòÉ 6.1.4.4. Set Functions ΓòÉΓòÉΓòÉ
FtpSetUser(host,userid,password<,account>)
FtpSetBinary("Binary" | "Ascii")
FtpSetUser() sets the host, userid, and password for the remote host that most
of the other functions require. FtpSetBinary() sets the default text
translation for functions that can use this. This Binary or Ascii setting can
be overriden by any function that takes it as an option parameter.
Note that the host, userid, password, and account are retained during the life
of the process. If you are using the RxFtp package within a .CMD file run the
OS/2 prompt, this means the life of the CMD.EXE process. You may want to
'blank' out the password (at least) when you are finished, to prevent
unauthorized access to a host you previously used.
ΓòÉΓòÉΓòÉ 6.1.4.5. File Functions ΓòÉΓòÉΓòÉ
FtpAppend(localFile,remoteFile[,"Binary" | "Ascii"])
FtpDelete(remoteFile)
FtpGet(localFile,remoteFile[,"Binary" | "Ascii"])
FtpPut(localFile,remoteFile[,"Binary" | "Ascii"])
FtpPutUnique(localFile,remoteFile[,"Binary" | "Ascii"])
FtpRename(oldFile,newFile)
These functions perform work on files. The function should be obvious, except
for FtpPutUnique() which insures the remote file created is unique, and does
not overwrite the name of a file which already exists.
ΓòÉΓòÉΓòÉ 6.1.4.6. Directory List Functions ΓòÉΓòÉΓòÉ
FtpLs(pattern,stem)
FtpDir(pattern,stem)
These functions return directory list information in the stemmed variable
passed in. FtpLs() returns 'short' form; FtpDir() returns 'long' form. The
Stem value should be a string with a "." at the end. When the function
completes, the variable stem || ".0" will be set to the number of stem
variables returned, which are set in variables stem || ".1", stem || ".2",
etc.
ΓòÉΓòÉΓòÉ 6.1.4.7. Directory Functions ΓòÉΓòÉΓòÉ
FtpPwd(variable)
FtpChDir(directory)
FtpMkDir(directory)
FtpRmDir(directory)
These functions work with directories. The function should be obvious.
FtpPwd() returns the name of the current directory on the remote host if no
error occurred in the variable "variable"
ΓòÉΓòÉΓòÉ 6.1.4.8. Logoff Function ΓòÉΓòÉΓòÉ
FtpLogoff()
This function should be called to terminate all ftp sessions.
ΓòÉΓòÉΓòÉ 6.1.4.9. Miscellaneous Functions ΓòÉΓòÉΓòÉ
FtpQuote(quote)
FtpSite(site)
FtpSys(variable)
FtpQuote() and FtpSite() pass information to server as the "site" and "quote"
commands do.
FtpSys() returns the name of the operating system that server is running if no
error occurred in the variable "variable"
ΓòÉΓòÉΓòÉ 6.1.4.10. Proxy Function ΓòÉΓòÉΓòÉ
FtpProxy(host,userid,password,account,pFile,rFile[,"Binary" | "Ascii"])
FtpProxy() copies a file from the named host/userid/password/account (account
may be empty) to the host specified with the Set functions. pFile is name of
the file on the named host/userid/password/account, rFile is the file on the
host specified with the Set functions.
ΓòÉΓòÉΓòÉ 6.1.5. Utilities Provided ΓòÉΓòÉΓòÉ
miniftp.cmd
A test program demonstrating the use of the rxFtp package.
ΓòÉΓòÉΓòÉ 6.2. rxSock ΓòÉΓòÉΓòÉ
rxSock -Rexx Function Package for TCP/IP Sockets for OS/2 2.0
by Patrick Mueller (pmuellr@vnet.ibm.com)
(c) Copyright International Business Machines Corporation 1993.
All rights Reserved.
ΓòÉΓòÉΓòÉ 6.2.1. what is rxSock? ΓòÉΓòÉΓòÉ
rxSock is a REXX function package providing access to the OS/2 TCP/IP socket
API as provided by the IBM TCP/IP product, version 1.2.1.
The function reference below is minimalistic. It is assumed you are already
familiar with the basic socket APIs, and can reference the OS/2 specific ones.
A widely available book with information on the basic socket APIs is
"Internetworking with TCP/IP Volume I: Principals, Protocols, and Architecture"
by Douglas Comer.
This function package requires the OS/2 TCP/IP product, version 1.2.1 or
higher.
ΓòÉΓòÉΓòÉ 6.2.2. Installation and Removal ΓòÉΓòÉΓòÉ
The rxSock rexx function package is contained in the file rxSock.dll. This file
needs to be placed in a directory along your LIBPATH. To get access to the
functions in the rxSock function package, execute the following rexx code:
rc = RxFuncAdd("SockLoadFuncs","rxSock","SockLoadFuncs")
rc = SockLoadFuncs()
To unload the DLL, you should first call the SockDropFuncs() function, then
exit all CMD.EXE shells. After exiting all the command shells, the DLL will be
dropped by OS/2 and can be deleted or replaced.
ΓòÉΓòÉΓòÉ 6.2.3. Parameters and Return Values ΓòÉΓòÉΓòÉ
Return values for most functions are the same as the C equivalents, unless
otherwise noted.
There are a number of standard parameters types referenced in the function
reference.
socket
This is a socket value. It is an integral number.
domain
This is a domain value. The only currently supported domain is "AF_INET".
address
This is the 'stem' of a stemmed variable with the following values:
- address.family
should always be "AF_INET"
- address.port
a port number
- address.addr
a dotted decimal address, or where appropriate, "INADDR_ANY"
When this parameter is needed you should set it the name of a stem
variable for the function to set (or that the function will read from).
For example, if you passed the string "xxx.!" as a parameter, the
variables
"xxx.!family",
"xxx.!port", and
"xxx.!addr"
will be set by the function, or queried by the function.
dotAddress
the standard dotted decimal address. For example, the string "9.23.19.63"
is a valid address.
host
This is the 'stem' of a stemmed variable with the following values:
- host.name
the standard name of the host
- host.alias.0
number of aliases for this host
- host.alias.1
First alias for this host
- host.alias.n
n'th alias for this host
- host.addrtype
should always be "AF_INET"
- host.addr
a dotted decimal address (default address)
- host.addr.0
number of addresses for this host
- host.addr.1
First address for this host
- host.addr.n
n'th address for this host
When this parameter is needed you should set it the name of a stem
variable for the function to set (or that the function will read from).
For example, if you passed the string "xxx.!" as a parameter, the
variables
"xxx.!name",
"xxx.!alias.0", "xxx.!alias.1" ... "xxx.!alias.n",
"xxx.!addrtype"
"xxx.!addr"
"xxx.!addr.0", "xxx.!addr.1" ... "xxx.!addr.n",
will be set by the function, or queried by the function.
Special note on stemmed variables
The address and host type of parameters are stemmed variable names.
Traditionally, you would pass a string like "addr." as a parameter, and expect
to have the variables addr.family, addr.port, and addr.addr set by the
function. In the examples above though, I showed using a stem like "addr.!".
The exclamation point helps to distinguish the tail values, so they won't get
mis-used as normal variables. For instance, look at the following code:
port = 923
sNew = SockAccept(sOld,"addr.")
say addr.port
You might expect the say statement to write the port number of the accept'ed
socket. Instead it writes the value of the variable addr.923, since the port
variable is SET to a value.
Since you probably don't normally use exclamation points in your variables,
it's unlikely that you will be using the variable "!port" in your program.
Also note, some folk prefer other characters, including "_", "0", and "1" (the
digits are allowed to prefix tail values and are very secure against this kind
of accidental misuse - I don't use them because the characters are hard to
distinguish from O, I, and l).
ΓòÉΓòÉΓòÉ 6.2.4. Variables set ΓòÉΓòÉΓòÉ
errno
The errno variable is set after every rxSock function call. It will have
one of the following values (or a numeric value if the number isn't one
of these values, probably indicating an errno value the compiler that the
tcp/ip product was written in). Note the value is set even if the
function that was called does not neccessarily set the variable, in which
case the value has no meaning. The value 0 indicates no error occurred.
"EWOULDBLOCK"
"EINPROGRESS"
"EALREADY"
"ENOTSOCK"
"EDESTADDRREQ"
"EMSGSIZE"
"EPROTOTYPE"
"ENOPROTOOPT"
"EPROTONOSUPPORT"
"ESOCKTNOSUPPORT"
"EOPNOTSUPP"
"EPFNOSUPPORT"
"EAFNOSUPPORT"
"EADDRINUSE"
"EADDRNOTAVAIL"
"ENETDOWN"
"ENETUNREACH"
"ENETRESET"
"ECONNABORTED"
"ECONNRESET"
"ENOBUFS"
"EISCONN"
"ENOTCONN"
"ESHUTDOWN"
"ETOOMANYREFS"
"ETIMEDOUT"
"ECONNREFUSED"
"ELOOP"
"ENAMETOOLONG"
"EHOSTDOWN"
"EHOSTUNREACH"
"ENOTEMPTY"
h_errno
The h_errno variable is set after every rxSock function call. It will
have one of the following values (or a numeric value if the number isn't
one of these values). Note the value is set even if the function that was
called does not neccessarily set the variable, in which case the value
has no meaning. The value 0 indicates no error occurred.
"HOST_NOT_FOUND"
"TRY_AGAIN"
"NO_RECOVERY"
"NO_ADDRESS"
ΓòÉΓòÉΓòÉ 6.2.5. Function Reference ΓòÉΓòÉΓòÉ
Most of the functions below correspond to their like-named C functions
available in the OS/2 TCP/IP socket library.
ΓòÉΓòÉΓòÉ 6.2.5.1. SockLoadFuncs ΓòÉΓòÉΓòÉ
rc = SockLoadFuncs()
Loads all the functions in the rxSock package.
If ANY parameters are passed to this function, it will bypass the
program/author/copyright information normally displayed. All parameters are
ignored (except to determine whether or not to bypass displaying the
information).
ΓòÉΓòÉΓòÉ 6.2.5.2. SockDropFuncs ΓòÉΓòÉΓòÉ
rc = SockDropFuncs()
Drops all the functions in the rxSock package.
ΓòÉΓòÉΓòÉ 6.2.5.3. SockVersion ΓòÉΓòÉΓòÉ
vers = SockVersion()
Prior to version 1.2, this function did not exist. To check to see if a
previous version of RxSock is installed, use the following code, after loading
the function package with SockLoadFuncs().
/* oldVersion will be '1' if a version of RxSock < 1.2 is loaded */
oldVersion = (1 = RxFuncQuery("SockVersion"))
ΓòÉΓòÉΓòÉ 6.2.5.4. SockAccept ΓòÉΓòÉΓòÉ
Implements C function accept()
socket = SockAccept(socket<,address>)
ΓòÉΓòÉΓòÉ 6.2.5.5. SockBind ΓòÉΓòÉΓòÉ
Implements C function bind()
rc = SockBind(socket,address)
ΓòÉΓòÉΓòÉ 6.2.5.6. SockClose ΓòÉΓòÉΓòÉ
Implements C function soclose()/close()
rc = SockClose(socket)
Exactly the same as SockSoClose()
ΓòÉΓòÉΓòÉ 6.2.5.7. SockConnect ΓòÉΓòÉΓòÉ
Implements C function connect()
rc = SockConnect(socket,address)
ΓòÉΓòÉΓòÉ 6.2.5.8. SockGetHostByAddr ΓòÉΓòÉΓòÉ
Implements C function gethostbyaddr()
rc = SockGetHostByAddr(dotAddress,host<,domain>)
Returns 1 for success, 0 for error.
ΓòÉΓòÉΓòÉ 6.2.5.9. SockGetHostByName ΓòÉΓòÉΓòÉ
Implements C function gethostbyname()
rc = SockGetHostByName(nameAddress,host)
nameAddress should be the textual name of a host, for example
"pmuellr.vnet.ibm.com".
Returns 1 for success, 0 for error.
ΓòÉΓòÉΓòÉ 6.2.5.10. SockGetHostId ΓòÉΓòÉΓòÉ
Implements C function gethostid()
dotAddress = SockGetHostId()
ΓòÉΓòÉΓòÉ 6.2.5.11. SockGetPeerName ΓòÉΓòÉΓòÉ
Implements C function getpeername()
rc = SockGetPeerName(socket,address)
ΓòÉΓòÉΓòÉ 6.2.5.12. SockGetSockName ΓòÉΓòÉΓòÉ
Implements C function getsockname()
rc = SockGetSockName(socket,address)
ΓòÉΓòÉΓòÉ 6.2.5.13. SockGetSockOpt ΓòÉΓòÉΓòÉ
Implements C function getsockopt()
rc = SockGetSockOpt(socket,level,optVar,optVal)
The only valid value for level is "SOL_SOCKET"
optVar may be one of the following:
"SO_BROADCAST"
"SO_DEBUG"
"SO_DONTROUTE"
"SO_ERROR"
"SO_KEEPALIVE"
"SO_LINGER"
"SO_OOBINLINE"
"SO_RCVBUF"
"SO_RCVLOWAT"
"SO_RCVTIMEO"
"SO_REUSEADDR"
"SO_SNDBUF"
"SO_SNDLOWAT"
"SO_SNDTIMEO"
"SO_TYPE"
"SO_USELOOPBACK"
optVal is the value of the option. Most of the options' values are integral.
The exceptions are:
"SO_LINGER"
expects two blank delimited integers - the first is the l_onoff
value, the second is the l_linger value.
"SO_TYPE"
a string of either "STREAM", "DGRAM", or "RAW"
ΓòÉΓòÉΓòÉ 6.2.5.14. SockInit ΓòÉΓòÉΓòÉ
Implements C function sock_init()
rc = SockInit()
SockInit() is not strictly needed, as initialization is done for each RxSock
function if initialization has not yet occurred.
ΓòÉΓòÉΓòÉ 6.2.5.15. SockIoctl ΓòÉΓòÉΓòÉ
Implements C function ioctl()
rc = SockIoctl(socket,ioctlCmd,ioctlData)
ioctlCmd is the ioctl command to perform. Valid commands are:
"FIONBIO"
"FIONREAD"
ioctlData is the command specific value. Values are:
"FIONBIO" - "1" or "0"
"FIONREAD" - name of a variable to contain number of immediately readable bytes
ΓòÉΓòÉΓòÉ 6.2.5.16. SockListen ΓòÉΓòÉΓòÉ
Implements C function listen()
rc = SockListen(socket,backlog)
ΓòÉΓòÉΓòÉ 6.2.5.17. SockRecv ΓòÉΓòÉΓòÉ
Implements C function recv()
rc = SockRecv(socket,var,len<,flags>)
var is the name of a rexx variable the data should be received into.
len is the maximum amount of data to read.
flags is a blank delimited list of options: "MSG_OOB", "MSG_PEEK".
Returns the return code from the recv() function.
ΓòÉΓòÉΓòÉ 6.2.5.18. SockSelect ΓòÉΓòÉΓòÉ
Implements C function select()
rc = SockSelect(reads,writes,excepts<,timeout>)
reads, writes, and excepts are stem variables which are queried and set by this
function. The stem.0 variable should contain the number of sockets, stem.1 the
first socket, etc. Upon return, the stem variables will be reset to the sockets
which are ready. For instance,
r.0 = 2
r.1 = 101
r.2 = 102
w.0 = 1
w.1 = 103
e.0 = 0
rc = SockSelect("r.","w.","e.")
do i = 1 to r.0
say "socket" r.i "is ready for reading."
end
timeout is the number of seconds to wait before timing out. 0 should be used
for polling behaviour (no waiting), and "" should be used to wait indefinitely.
If no timeout value is passed, "" is assumed. The number must be integral (no
fractional values) - if fractional values are required, this could be
implemented - contact me. Non-numeric and negative numbers are considered 0.
If any of the stem variables are "", or no parameter is passed, no sockets for
that type will be checked. For instance, the SockSelect() call above could have
been invoked as either of:
rc = SockSelect("r.","w.","")
rc = SockSelect("r.","w.",)
The function call SockSelect(,,,x) results in the program pausing for x
seconds.
The return code from SockSelect() is the number of ready sockets or 0 if a
timeout occurred. If a timeout occurred, the socket arrays are not modified.
ΓòÉΓòÉΓòÉ 6.2.5.19. SockSend ΓòÉΓòÉΓòÉ
Implements C function send()
rc = SockSend(socket,data<,flags>)
data is a string of text to be sent on the sock.
flags is a blank delimited list of options:
"MSG_OOB", "MSG_DONTROUTE".
Returns the return code from the send() function.
ΓòÉΓòÉΓòÉ 6.2.5.20. SockSetSockOpt ΓòÉΓòÉΓòÉ
Implements C function setsockopt()
rc = SockSetSockOpt(socket,level,optVar,optVal)
The only valid value for level is "SOL_SOCKET"
optVar is the option to set. See SockGetSockOpt() for valid values. Some
options listed in SockGetSockOpt() are not valid for SockSetSockOpt(). They
are:
"SO_ERROR"
"SO_TYPE"
optVal is the value to set the option to. The formats are the same as that of
SockGetSockOpt(), except the actual value should be passed in, instead of a
variable name.
ΓòÉΓòÉΓòÉ 6.2.5.21. SockShutDown ΓòÉΓòÉΓòÉ
Implements C function shutdown()
rc = SockShutDown(socket,how)
ΓòÉΓòÉΓòÉ 6.2.5.22. SockSocket ΓòÉΓòÉΓòÉ
Implements C function socket()
socket = SockSocket(domain,type,protocol)
domain must be "AF_INET".
type may be one of "SOCK_STREAM", "SOCK_DGRAM", or "SOCK_RAW"
protocol may be one of "IPPROTO_UDP", "IPPROTO_TCP", or "0"
ΓòÉΓòÉΓòÉ 6.2.5.23. SockSoClose ΓòÉΓòÉΓòÉ
Implements C function soclose()/close()
rc = SockSoClose(socket)
ΓòÉΓòÉΓòÉ 6.2.6. Utilities Provided ΓòÉΓòÉΓòÉ
This section lists the utilities provided with the rxSock package.
ΓòÉΓòÉΓòÉ 6.2.6.1. killsock.cmd ΓòÉΓòÉΓòÉ
This program takes socket numbers and closes them. Useful for terminating a
stubborn server, or cleaning up after accidents.
Use "netstat -s" to get a list of currently open sockets.
ΓòÉΓòÉΓòÉ 6.2.6.2. rnr.cmd ΓòÉΓòÉΓòÉ
A very basic news reader. Used to demonstrate a fairly complex application
using rxSock functions.
ΓòÉΓòÉΓòÉ 6.2.6.3. test_h.cmd ΓòÉΓòÉΓòÉ
A test program testing address to hostname conversions.
ΓòÉΓòÉΓòÉ 6.2.6.4. test_c.cmd and test_s.cmd ΓòÉΓòÉΓòÉ
These program are test client/server programs. Start test_s.cmd in one session,
and then test_c.cmd in another. The programs exchange data and print some
timing information before quitting. The server and client can run across two
different hosts. Pass the host name of the server as a parameter to test_c.cmd
ΓòÉΓòÉΓòÉ 6.2.6.5. test*.cmd ΓòÉΓòÉΓòÉ
These test programs test other parts of the RxSock package. Not all that
useful, unless you are looking for info on SockSelect(), SockIoctl(),
Sock?etSockOpt() functions.
ΓòÉΓòÉΓòÉ 6.2.7. History ΓòÉΓòÉΓòÉ
08/05/93
- version 1.3
- fixed stupid bug in SockGetPeerName() and SockGetSockName()
07/16/93
- version 1.2
- added SockVersion(), SockClose(), SockIoctl(), SockSelect(),
SockGetSockOpt(), SockSetSockOpt()
- changed documentation for SockGetHostByName() and SockGetHostByAddr()
to reflect what the code actually does
- now return a list of addresses per host instead of just one
03/11/93
- version 1.1
- first release in OS/2 Employee Written Software program
- simulataneous (or nearly) release on OS2TOOLS
distant past
- version 1.0