RC special variable in REXX? - rexx

how to assign a value to RC special variable in REXX?

/* REXX */
"LISTDS ?" /* Command that sets RC to 12 */
SAY 'RC IS' RC /* RC is 12 */
RC = X /* RC set to X */
SAY 'RC IS' RC /* RC is X */
The above works, there is nothing special about the RC variable except it will be over written by the return code from the last command.
So you can set it to whatever you want at least on a mainframe running Zos.
Maybe you need to provide more detail in your question like what type of Rexx it is (Classic or OO) and what environment you are using.

If you want to set the return value of your method you need to use the "return" commend and to get the return code with the "result", for example:
/* REXX - program A */
SAY "THIS IS PROG. A WITH RC = 4"
RETURN 4
/* REXX - PROGRAM B */
SAY "CALLING PROGRAM A..."
CALL PROG_A
RC = RESULT
SAY "RC = "RC " RETURN FROM PROGRAM A..."

As Deuian said before, RC is set by last command executed and more detail should be provided to get a precise answer (environment, goal/task, batch/interactive etc.).
A silly working way to set RC on Zos REXX is to make a buffer: RC is set to the buffer count (so if you need RC = 100 you should create 100 buffers...), see the example (I do not endorse the usage of this method, it's just a conjecture)
/* rexx */
'MAKEBUF'
say RC
'MAKEBUF'
say RC
'DROPBUF'
say RC
/* exec output */
1
2
0
***
Beware that the previous code leaves a buffer active! (another DROPBUF needed)

The SAY instructions will send screen prompts or include text in the output. If you want to set the RC to something that can be interpreted by subsequent steps in a job, try:
/* REXX */
setrc = X /* set a variable for RC to X */
exit(setrc)

Related

Issue while passing RC from MACRO to caller REXX program

I am executing a MACRO to find string (using regular expression), and want to handle the return code of that regular expression execution in my caller REXX in mainframe.
I tried using PARM and, VGET and VPUT, but no positive result for me.
/* REXX */
ADDRESS ISPEXEC "VPUT (MRC) SHARED"
ADDRESS ISPEXEC "VIEW DATASET('XXXX.XXXX.XXXX') MACRO(REGEX)
SAY "RC IN CALLER:" RC
SAY "MRC:" MRC
Macro defined:
/* REXX */
ADDRESS ISREDIT
"MACRO"
ADDRESS ISPEXEC "VGET (MRC) SHARED"
"F RC'[0-9]{16}'"
MRC = RC
SAY "INSIDE MACRO:" MRC
ADDRESS ISREDIT 'END'
Also tried reversing VGET and VPUT in macro and caller REXX and also changes the place of the statement. Still no result.
Output:
INSIDE MACRO: 0 (when string found)
RC IN CALLER: 0
MRC:
INSIDE MACRO: 4 (when string not found)
RC IN CALLER: 0
MRC:
Could any one please suggest.

using REXX to access vm370 disks

REXX is completely new to me, I like it so far. I am using SixPack running on Hercules. VM/370 is a nice environment, but I am trying to make it user friendly; filling in scripts for everything that works-so as to not need to repeat my steps.
The file attached below was written to search in ISFP, instead I want it to access disks. It searches for a specified file.
I do not know enough to rewrite a REXX program. It stops at strange places saying "found" this or that. Please, give any suggestions.
/* REXX */
ARG PROGNAME
PROGNAME = STRIP(PROGNAME)
ACCESS_TEMPLATE='A2 Y U'
USE VAR ACCESS_TEMPLATE A2 Y U /* NOT PARSE */
VAR1 = A2
VAR2 = Y
VAR3 = U
IF PROGNAME == '' THEN DO
SAY 'ENTER MEMBER NAME'
FULL PROGNAME
PROGNAME = STRIP(PROGNAME)
IF PROGNAME == '' THEN DO
SAY NO MEMBER ENTERED. EXITING THE PROGRAM
EXIT
END
END
SEARCH.1 = PROD1.LIB
SEARCH.2 = PROD2.LIB
SEARCH.3 = PROD3.LIB
CNT = 3
FND = 'N'
DO I = 1 TO CNT
ACCESS 'VAR1' 'VAR2' 'VAR3'
LIB = LIST.I(PROGNAME)
IF SYSDSN('LIB') == OK THEN DO
FND = 'Y'
TYPE('LIB')
END
END
IF FND == 'N'THEN DO
SAY MEMBERS NOT FOUND IN ANY LIBRARIES
SAY PLEASE CHECK THE MEMBER ENTERED
EXIT
END
This is a bit late but it's good advice for novice REXX programmers...
Right near the top of your program put in this:
SIGNAL ON NOVALUE
and then near the every end...
NOVALUE: SAY 'NOVALUE error at line' SIGL
exit 4
Why? REXX has a "feature" in that every undefined variable resolves to its own name in UPPER case, like this:
myvar1='hi there'
mayvar2=', joe'
say myvar1||myvar2
What you probably intended to SAY was
'hi there, joe'
but instead got
'hi thereMYVAR2'
If you had SIGNAL ON NOVALUE it would have given you an error message which is a lot better. I ALWAYS put this into my code.

wait($time >1000); cannot work in system-verilog?

I use this code to wait for a specific simulation time
initial begin
$display("A");
wait($time>1000);
$display("B");
end
the simulation result is:
A
I didnot see B printed.
If I use following code, it works.
while($time <1000) #1;
Is it because vcs needs to judge the wait condition once any viriable in the condition statement changes, $time is changing too frequently so vcs doesnot allow this usage?
#Tudor 's answer enlighten me. I tried #Tudor 's code with some modification. It turns out when wait(func(arglist)); vcs only retry to evaluate the function when arglist changes. Because $time has no args, vcs will only evaluate $time the 1st time, won't retry.
module top;
int the_time = 0;
int in_arg = 0;
function int the_time_f(int in);
return the_time;
endfunction // the_time_f
initial begin
$display("A");
// This works because 'the_time' is a variable
//wait(the_time > 10);
// This doesn't work because 'the_time_f' is a function
wait(the_time_f(in_arg) >10);
$display("B at %t", $time);
end
initial begin
#10ns;
the_time = 11;
#10ns;
in_arg = 1;
#20ns;
$finish();
end
endmodule // top
got following result
A
B at 20ns
This seems to be a gray area in the standard. In section 9.4 Procedural timing controls of the IEEE Std 1800-2012 Standard, it's mentioned that event control can be either implicit (changed of nets or variables) or explicit (fields of type event). $time is a system function, not a variable. I've also tried using a function for the wait and it also doesn't work:
module top;
int the_time = 0;
function int the_time_f();
return the_time;
endfunction // the_time_f
initial begin
$display("A");
// This works because 'the_time' is a variable
//wait(the_time > 10);
// This doesn't work because 'the_time_f' is a function
wait(the_time_f() > 10);
$display("B");
end
initial begin
#10ns;
the_time = 11;
#20ns;
$finish();
end
endmodule // top
Waiting on a change of a variable works fine, but waiting for a change on a function's return value doesn't work. IMHO, the compiler should have flagged this as a compile error (same for using $time) since it seems to just ignore the statement.
In an event control #(expression) or wait(expression) that suspends a process, SystemVerilog scheduling semantics requires an event to evaluate the expression (called an evaluation event. See section 4.3 Event Simulation of the 1800-2012 LRM) If an expression includes a function, only the arguments to that function are visible to cause an event evaluation (There is an exception for class methods in at a write to any member of the object in the method call will cause an event) See section 9.4.2 Event control
In an event driven simulation, the value of time is just an attribute of the current time slot, it is never an event. The simulator processes all events for the current time slot in a queue, and when that queue is empty, it advances time to the next time slot queue. So it might simulate time slots 0,5,7,10, skipping over the unmentioned times. Using your while loop, that would create a time sot for every consecutive time unit between 0 and 1000 - extremely inefficient.
So just use
#(1000); // wait for 1000 relative time units

Does progress 4GL language support hierarchical queries?

The simple question subscribed on progress site:
Does progress 4GL language support hierarchical queries like Oracle (Connect by clause) or Sql Server(CTE)?
I have the following table:
Name parent
-----------------------
Elizabeth II null
Charles Elizabeth II
Andrew Elizabeth II
Edward Elizabeth II
Harry Charles
William Chales
James Edward
George William
Is there a script in progress that will generate the following output?
Elizabeth II
|_Charles
|_William
|_George
|_Harry
|_Andrew
|_Edward
|_James
Since Progress 4GL (actually ABL since a couple years) is a complete turing complete language you can. However perhaps not in a single query...
This recursive example does it, you could do in a number of different ways. You can start with this code but you might need to have more error checks etc.
DEFINE TEMP-TABLE ttPerson NO-UNDO
FIELD PersonName AS CHARACTER FORMAT "x(20)"
FIELD PersonParent AS CHARACTER.
/* A procedure for loading example data */
PROCEDURE createPerson:
DEFINE INPUT PARAMETER pcName AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER pcParent AS CHARACTER NO-UNDO.
CREATE ttPerson.
ASSIGN
ttPerson.personName = pcName
ttPerson.personParent = pcParent.
END.
/* Load some data */
RUN createPerson("Elizabeth II", "").
RUN createPerson("Charles", "Elizabeth II").
RUN createPerson("Andrew", "Elizabeth II").
RUN createPerson("Edward", "Elizabeth II").
RUN createPerson("Harry", "Charles").
RUN createPerson("William", "Charles").
RUN createPerson("James", "Edward").
RUN createPerson("George", "William").
/* Define a frame where the result will be displayed */
DEFINE FRAME f1 ttPerson.personName WITH 20 DOWN.
/* The recursive prodecure */
/* pcPerson - the person where to start track heritage (or perhaps it should have been lineage?*/
/* piDepth, just to format the output */
PROCEDURE trackHeritage:
DEFINE INPUT PARAMETER pcPerson AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER piDepth AS INTEGER NO-UNDO.
piDepth = piDepth + 1.
/* Find the tracked person */
FIND FIRST ttPerson NO-LOCK WHERE ttPerson.personName = pcPerson NO-ERROR.
IF AVAILABLE ttperson THEN DO:
DISPLAY FILL(" ", piDepth) + "|_" + ttPerson.personName # ttPerson.personName WITH FRAME f1.
DOWN 1 WITH FRAME f1.
/* Track all available children to the person */
FOR EACH ttPerson NO-LOCK WHERE ttPerson.personParent = pcPerson:
RUN trackHeritage(ttPerson.personName, piDepth).
END.
END.
END.
/* Start tracking */
RUN trackHeritage("Elizabeth II", 0).
MESSAGE "Done" VIEW-AS ALERT-BOX.

How to export data from browser widget to CSV in Progress 4Gl

Did anyone tried to export data directly from browser to CSV? We are populating data to browser which has complex logic. If i can get data directly from browser to CSV that would be helpful.
Thanks,
MSK
Are you referring to a browse widget? A browse widget visualizes the data in an underlying query -- the query result set would be what you want to export. There is no EXPORT method for a query so, unfortunately you will need to roll your own. Something like this (many details omitted):
function exportData returns logical ( input bh as handle ):
define variable bf as handle no-undo. /* handle to the field */
define variable f as integer no-undo. /* field number */
define variable i as integer no-undo. /* array index */
do f = 1 to bh:num-fields: /* for each field... */
bf = bh:buffer-field( f ). /* get a pointer to the field */
if f > 1 then put stream expFile unformatted field_sep. /* output field separator */
if bf:extent = 0 then /* is it an array? */
put stream expFile unformatted
( if bf:data-type = "character" then /* character data needs to be quoted to */
quoter( string( bf:buffer-value )) /* handle (potential) embedded delimiters */
else /* and quotes within quotes! */
string( bf:buffer-value ) /* other data types should not be quoted */
)
.
else /* array fields need special handling */
do i = 1 to bf:extent: /* each extent is exported individually */
if i > 1 then put stream expFile unformatted field_sep. /* and a field separator */
put stream expFile unformatted
( if bf:data-type = "character" then /* see above... */
quoter( string( bf:buffer-value( i )))
else
string( bf:buffer-value( i ))
)
field_sep
.
end.
end.
put stream expFile skip. /* don't forget the newline! ;-) */
return true.
end.
/* main block...
*/
/* skipping a few things like defining variables and setting up the query that you have, presumably, already done... */
output to "output.dat".
qh:get-first( no-lock ) no-error. /* try to fetch the first record */
do while ( qh:query-off-end = no ): /* loop while there is data being fetched */
exportData( bh ). /* write it to the output file! */
assign /* track the number of records written... */
r = r + 1 /* per table */
.
qh:get-next( no-lock ) no-error. /* fetch the next record */
end.