I have tried to think about a simple solution, how to make the scripts
easily portable between Win NT and MVS. The best thing I have up to now is
to use something like in the next script:
/* EXECIO="Call WinEXECIO" */ /* uncomment on Win NT */
Interpret EXECIO "* DISKR DATADD (FINIS STEM Data.)"
...
EXIT
WinEXECIO:
Data.0 = Lines(...)
...
but this means extra overhead in every script to implement the WinEXECIO
procedure. Also the necessity of adding and removing comments is unpleasant
etc.
Does anybody know a better way how to easily port between Win NT and MVS ?
Thank for any idea.
You could insert some code in your program to check the platform at
execution time.
PARSE SOURCE var .
select; when var = 'TSO' then ...
when var = ...
end
Regards,
Michel Castelein
(Author of a REXX Programming course (OS/390 and VM)
---------------------------------------------------------
Michel Castelein
OS/390 System Engineer & Education Consultant
E-mail Mic...@jeeves.be
Home page http://homepages.infoseek.com/~michelcastelein/
Company: JEEVES Consulting N.V., phone +32-2-251.66.50
http://www.ticnet.com/davea/rexxany
It has tips on detecting which platform you're on and some sample code
which does I/O using different techniques based on the Rexx
implementation.
HtH...Dave
Miroslav Vaic wrote:
> I am developing REXX scripts for MVS and I do prototype the scripts with
> Regina Rexx on Win NT. But there are some inconsistencies, biggest of which
> is the difference in IO operations. MVS REXX uses EXECIO instruction,
> although almost all other REXX implementations use LINES, LINEIN and
> LINEOUT.
<snip>
I prefer to execute the function just once, save the value, and manually
code for
the bytes/lines left to read (example below uses chars() and a 4K buffer for
efficiency).
ifile_len = chars(ifile)
if ifile_len = 0 then
do
say '**ERR**' ifile 'is empty.'
return
end
read_buf = 4096
chars_left = ifile_len
if chars_left > read_buf then
chars_to_read = read_buf
else
chars_to_read = chars_left
do until chars_to_read = 0
ifile_buf = charin(ifile,,chars_to_read)
...
... <your code to process the buffer>
...
chars_left = chars_left - chars_to_read
if chars_left > read_buf then
chars_to_read = read_buf
else
chars_to_read = chars_left
end
--
Nolly Unvala
<remove "_xspam" from address to reply>
David Alcock wrote in message
<46839E98D053AD9B.A45B1533...@library-proxy.airnews.ne
t>...
In an application I have many occasions to check for the existance files. I
know that if I want to use the file, I'd have to request a semaphore to see if
the file is in use.
But what if I just want to check for its presence, busy or not, with
RxFileExists(filename)? If the file is in use when RxFileExists runs, will
there be a collision? I haven't seen one yet and would like to avoid writing
all the extra code if it isn't really necessary. (So I'm lazy...but I like
shorter programs.)
TIA,
Jerry Prather pra...@infi.net
"Many religions are worth dying for; no religion is worth killing for."
- Me (circa 1998)
What I did was instead of using specific commands EXECIO/LINEIN I put each
IO command in a subroutine, ex:
READ_LINE: /* WHEN RUN ON MVS */
ARG DDNAME
"EXECIO 1 DISKR "DDNAME" (STEM "DDNAME".L."
READ_RC=RC
RETURN RC
READ_LINE: /* WHEN RUN THROUGH REGINA ON PC */
ARG DDNAME
DDNAME.L.0=DDNAME.L.0+1
REC_COUNT=DDNAME.L.0
DDNAME.L.REC_COUNT=LINEIN(DDNAME,1)
READ_RC=RC
RETURN RC
In this case I misnamed stream id purposely to ddname to simplify changes.
OPEN_FILE_INPUT: /*MVS*/
ARG DDNAME DSN
"ALLOC FI("DDNAME") DA('"DSN"') SHR REUSE"
ALLOC_RC=RC
RETURN RC
OPEN_FILE_INPUT: /*PC*/
ARG DDNAME DSN /* ON PC NO DIFFERENCE BETWEEN DSN AND DDNAME */
DUMMY_REC=LINEIN(DDNAME,0)
ALLOC_RC=RC
RETURN RC
This way when you switch platforms you only have to change a few procedures.
Since I learned REXX on the mainframe first I made REGINA REXX read
everything into STEMS, just because thats the way I am used to working.
It is a little ugly on the PC side, but the loss of CPU is less noticeable
on the PC. At least for what I did.
Hope this helps.
I know this may be a little clunky, but on the PC I usually use the DIR
command from within REXX and route the output to a file and read that back
in to determine results:
FILE_EXISTS: PROCEDURE
ARG FILENAME
"DEL DIR.LIS"
"DIR "FILENAME" /B >> DIR.LIS"
IF LINES('DIR.LIS')>0 THEN DO
RETURN (1=1)
END;ELSE DO
RETURN (1=0)
END
RETURN /* NOT NECESSARY, BUT IT DELIMITS PROCEDURE */
Try something like this:
filename = 'C:\MYFILE' /* As an example */
name = stream(filename,'c','query exists) /* Get name if it
exists */
if name = '' then say 'File does not exist'
else say 'The file exists'
The stream will return the fully qualified name of the file if it does
in deed exist.
Bob Eberle
rke_so...@ibm.net
That's what I was using before trying to use the RxExtra call. Through
experience, I know (I think) that there can be collisions with this and was
using a semaphore on all OS calls to prevent it. Another precaution involved
is that you also need to close the file after querying it with the STREAM
function. I was hoping to save all that code by using RxExtra.
Thanks for the reply,
Thank for all the responces concerning this issue, I am quite surprised with
so many people interested in it ...
Miroslav Vaic
First let me thank Dick and the other respondants for their attempts to answer
my question, but I'm beginning to realize that either my question wasn't clear
enough or there is some basic knowledge that I'm missing.
What I need to know is:
(1) If the file is currently being used by another process, what will these
various methods report? Will there be a collision that will require the file
to be protected by a semaphore in order to check for its existence?
(2) If I use any of these methods (especially the STREAM function), do I have
to explicitly CLOSE the STREAM function after the check?
Sorry if I'm being dense, but... :-( ...OK, just tell me I'm dense.
I have a set of code that you probably could simply take and use almost
verbatim, assuming you seriously need to FORCE serial access to a file.
I did this by creating a "databaseserver" program that on starting
accesses a database. Programs that need to talk to the database
actually talk to the server. This is isolated into a suite of
subroutines (DatabaseSetup, _Talker, _Read, and _Write) which I simply
drop into programs as needed.
The server has a timer thread that kills the server if the program that
started the server dies without killing the server. Communication from
program to server is via a named pipe.
If Wayne wants this for his site I'll send it to him also. I had
thought this might be a bit to hairy for a collection of short code
fragments, but what the heck.
Doug
Doug, thanks for the offer and I'll gratefully accept. What you are
suggesting is very close to the application I'm working on (although I'm not
dealing with a server). I have Rexxbase database files which need to be
reindexed and/or rebuild a stemmed variable for access by the next option
selected by the user. The stemmed variable is built from a text file built by
the database on demand (my "update" thread). This thread takes a good bit of
time - about three minutes for a ~20K record table. If there has been a
"significant" change to the database records, the text file is deleted. Many
parts of the program need to know if the text file is present so it can be
rebuilt at a high priority if necessary. This sequence of requirements is
what is generating all my fussy questions.
Isn't that like asking an alcoholic if he wants a drink? I can't say
no! :-)
I think the question we need to ask ourselves is, "Is this something I
can share that someone else will find a use for?" I am happy to add
anything you think is worth adding.
As for the size question, I did have Joachim Scholtysik send a zip of
the VisPro forms and code for his submission but deferred using it in
addition to the html of info he sent. (for space reasons) We discussed
it a bit and I think he has convinced me to try to set something up to
archive this type of information also.
I will be checking into this and will let you know if there are any new
developments.
Wayne Swanson
------------------------------------------------------------
email: Ps...@Tech-Center.com
PillarSoft: http://fm-net.com/pillarsoft
Developers of WarpZip, ShowTime/2 and the Enhanced E Editors
Vice President, V.O.I.C.E. (Virtual OS/2 International Consumer
Education)
VOICE: http://www.os2voice.org
------------------------------------------------------------
This may or may not be what you're looking for Jerry but...
Can you write an ea to the file you want to access for each access of
it? Make the ".User" ea anything to let your other processes know that
it is busy and a maybe keyword like "None" to let it know it is
available.
rc=SysGetEA(filename, '.User', 'FileUserName')
If FileUserName='None' Then do
rc=SysPutEA(filename, '.User', 'TheUser')
Do='Your work goes here'
rc=SysPutEA(filename, '.User', 'None')
end
else do
/* Depending on what you are writing this in you can wait for a
"When expired" specified time or SysSleep and check again until
the ea says that the file is available. */
end
I did an editor for someone that wanted to keep files locked so other
people on the network could not change them while someone else was
editing them and used a method quite a bit like this. It got a bit more
complex but this was the general idea.
You'll also need an error handler to guard against an interrupted
shutdown and change the ea's to "None" or you will be locked out when
you restart. :-)
> What I need to know is:
>
> (1) If the file is currently being used by another process, what will these
> various methods report? Will there be a collision that will require the file
> to be protected by a semaphore in order to check for its existence?
>
> (2) If I use any of these methods (especially the STREAM function), do I have
> to explicitly CLOSE the STREAM function after the check?
One of the many advantages of REXX is that you can build yourself little
test cases (I have hundreds of them) to answer your own questions. I
have posted a test case below. STREAM, unless it is used to open a file,
does not create a file handle that you are responsible for closing and
there are no collisions.
/*--------------------------------*\
| Test reporting of an open file |
\*--------------------------------*/
call RxFuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs'
call SysLoadFuncs
/*------------------------------------*\
| Create a file name and write to it |
\*------------------------------------*/
test_file = SysTempFileName( 'test???' )
call LINEOUT test_file, ' '
reply = STREAM( test_file, 'C', 'QUERY EXISTS' )
say 'QUERY EXISTS' reply
reply = STREAM( test_file, 'D' )
say 'Description' reply
call SysFileTree test_file, 'stem.', 'T'
say stem.1
/*--------------------------*\
| Close file and delete it |
\*--------------------------*/
call STREAM test_file, 'C', 'CLOSE'
call SysFileDelete test_file
--------------------------------------------------------------
Dick Goran author, http://cfsrexx.com/WebMaven/
C F S Nevada, Inc. author, REXX Reference Summary Handbook
953 E. Sahara Ave, Suite 9B Voice: 702-732-9616
Las Vegas, NV 89104-3012 FAX: 702-732-3847
http://www.cfsrexx.com dgoran*cfsrexx.com (replace *)
Bingo! Thanks again, Dick, both for the simple answer and the method (which I
should have thougt of using myself) of proving it!
That was just an example. A further extension, which I have used, is to load
every input file into a stem and loop through the stem for the record by
record processing. This is kinda hard to implement on the PC, but it is my
standard process on the mainframe. Your individual reads can then be changed
to just update a counter rather than an actual read, simulating navigating
the records. Substituting the appropriate process for the appropriate
platform.
>And still - is it not possible to find a solution for Regina among the
>function packages for it ?
Not sure what you mean here, but when you mention REGINA and is function
packages you are talking about platform specific IO functions, thus unless
you have some kind of translator you can never be sure of the results. Even
if you did have a translator there is certain to be small problems.