How to copy stem value to simple variable in REXX - rexx

I'm trying to copy the value of LINE.I to variable THIS_IS_A_COMMENT2 so I can use it my JCL.
The JCLs are properly generated and executed, but the line QUEUE "//* THIS IS A COMMENT2 : " THIS_IS_A_COMMENT2 is completely ignored.
The SAY "VALUE OF LINE.I : " LINE.I works just fine, I can't figure out to copy the value of LINE.I to a simple variable.
THIS_IS_A_COMMENT = "HELLO"
THIS_IS_A_COMMENT2 = ""
DO I = 1 TO LINE.0
SAY "VALUE OF LINE.I : " LINE.I
THIS_IS_A_COMMENT2 = LINE.I
QUEUE "//USERIDK JOB 0000,'HELLO',"
QUEUE "// CLASS=T,"
QUEUE "// MSGCLASS=X,"
QUEUE "// MSGLEVEL=(1,1),"
QUEUE "// USER=USERID,"
QUEUE "// PASSWORD="
QUEUE "//* THIS IS A COMMENT : " THIS_IS_A_COMMENT
QUEUE "//* THIS IS A COMMENT2 : " THIS_IS_A_COMMENT2
QUEUE "//STEP1 EXEC PGM=IEFBR14"
QUEUE "//DD1 DD DUMMY"
QUEUE "/*"
QUEUE "$$"
O = OUTTRAP("OUTPUT.",,"CONCAT")
"SUBMIT * END($$)"
O = OUTTRAP(OFF)
END
I use the following jcl to submit my rexx code:
//JCLSAYHI JOB 00000,'SAY HI',
// CLASS=T,
// MSGCLASS=X,
// MSGLEVEL=(1,1),
// USER=MYUSER,PASSWORD=
/*JOBPARM R=H101,T=999,L=9999,S=ANY
//*----------------------------------------------
//STEPREXX EXEC PGM=IKJEFT01,PARM='SAYHI3'
//SYSEXEC DD DISP=SHR,DSN=MYUSER.REXX
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD DUMMY
//MYDATA DD DISP=SHR,DSN=MYUSER.REXX.DATASET
The SYSEXEC executes the code above, and the MYUSER.REXX.DATASET dataset contains:
********************************* Top of Data ******
HELLO1
HELLO2
HELLO3
HELLO4
HELLO5
******************************** Bottom of Data ****
TRACE results
Found the problem (REXX doesn't add double quotes at the end of the THIS IS A COMMENT2 line, so the line is ignored in the generated JCL). Just not sure how to fix that:
27 *-* QUEUE "//* THIS IS A COMMENT : " THIS_IS_A_COMMENT
>>> "//* THIS IS A COMMENT : HELLO"
28 *-* QUEUE "//* THIS IS A COMMENT2 : " THIS_IS_A_COMMENT2 ""
>>> "//* THIS IS A COMMENT2 : HELLO1 <--- DOUBLE QUOTE MISSING AT THE END HERE

Related

Save job output from SDSF into a PDS and using ISPF functions in REXX

We periodically runs jobs and we need to save the output into a PDS and then parse the output to extract parts of it to save into another member. It needs to be done by issuing a REXX command using the percent sign and the REXX member name as an SDSF command line. I've attempted to code a REXX to do this, but it is getting an error when trying to invoke an ISPF service, saying the ISPF environment has not been established. But, this is SDSF running under ISPF.
My code has this in it (copied from several sources and modified):
parse arg PSDSFPARMS "(" PUSERPARMS
parse var PSDSFPARMS PCURRPNL PPRIMPNL PROWTOKEN PPRIMCMD .
PRIMCMD=x2c(PPRIMCMD)
RC = isfquery()
if RC <> 0 then
do
Say "** SDSF environment does not exist, exec ending."
exit 20
end
RC = isfcalls("ON")
Address SDSF "ISFGET" PPRIMPNL "TOKEN('"PROWTOKEN"')" ,
" (" VERBOSE ")"
LRC = RC
if LRC > 0 then
call msgrtn "ISFGET"
if LRC <> 0 then
Exit 20
JOBNAME = value(JNAME.1)
JOBNBR = value(JOBID.1)
SMPDSN = "SMPE.*.OUTPUT.LISTINGS"
LISTC. = ''
SMPODSNS. = ''
SMPODSNS.0 = 0
$ = outtrap('LISTC.')
MSGVAL = msg('ON')
address TSO "LISTC LVL('"SMPDSN"') ALL"
MSGVAL = msg(MSGVAL)
$ = outtrap('OFF')
do LISTCi = 1 to LISTC.0
if word(LISTC.LISTCi,1) = 'NONVSAM' then
do
parse var LISTC.LISTCi . . DSN
SMPODSNS.0 = SMPODSNS.0 + 1
i = SMPODSNS.0
SMPODSNS.i = DSN
end
IX = pos('ENTRY',LISTC.LISTCi)
if IX <> 0 then
do
IX = pos('NOT FOUND',LISTC.LISTCi,IX + 8)
if IX <> 0 then
do
address ISPEXEC "SETMSG MSG(IPLL403E)"
EXITRC = 16
leave
end
end
end
LISTC. = ''
if EXITRC = 16 then
exit 0
address ISPEXEC "TBCREATE SMPDSNS NOWRITE" ,
"NAMES(TSEL TSMPDSN)"
I execute this code by typing %SMPSAVE next to the spool output line on the "H" SDSF panel and it runs fine until it gets to this point in the REXX:
114 *-* address ISPEXEC "TBCREATE SMPDSNS NOWRITE" ,
"NAMES(TSEL TSMPDSN)"
>>> "TBCREATE SMPDSNS NOWRITE NAMES(TSEL TSMPDSN)"
ISPS118S SERVICE NOT INVOKED. A VALID ISPF ENVIRONMENT DOES NOT EXIST.
+++ RC(20) +++
Does anyone know why it says I don't have a valid ISPF environment and how I can get around this?
I've done quite a bit in the past with REXX, including writing REXX code to handle line commands, but this is the first time I've tried to use ISPEXEC commands within this code.
Thank you,
Alan

Updating my current script which modifies multiple lines into a single one

My current script copies text like this with a shortcut:
:WiltedFlower: aetheryxflower ─ 4
:Alcohol: alcohol ─ 3,709
:Ant: ant ─ 11,924
:Apple: apple ─ 15
:ArmpitHair: armpithair ─ 2
and pastes it modified into a single line
Pls trade 4 aetheryxflower 3 alcohol 11 ant 15 apple 2 armpithair <#id>
As you can see there are already two little problems, the first one is that it copies only the number/s before a comma if one existed instead of ignoring it. The second is that I always need to also copy before hitting the hotkey and start re/start the script, I've thought of modifying the script so that it uses the already selected text instead of the copied one so that I can bind it with a single hotkey.
That is my current script, it would be cool if anyone can also tell me what they used and why exactly, so that I also get better with ahk
!q::
list =
While pos := RegExMatch(Clipboard, "(\w*) ─ (\d*)", m, pos ? pos + StrLen(m) : 1)
list .= m2 " " m1 " "
Clipboard := "", Clipboard := "Pls trade " list " <#951737931159187457>"
ClipWait, 0
If ErrorLevel
MsgBox, 48, Error, An error occurred while waiting for the clipboard.
return
If the pattern of your copied text dont change, you can use something like this:
#Persistent
OnClipboardChange:
list =
a := StrSplit(StrReplace(Clipboard, "`r"), "`n")
Loop,% a.Count() {
b := StrSplit( a[A_Index], ": " )
c := StrSplit( b[2], " - " )
list .= Trim( c[2] ) " " Trim( c[1] ) " "
}
Clipboard := "Pls trade " list " <#951737931159187457>"]
ToolTip % Clipboard ; just for debug
return
With your example text, the output will be:
Pls trade aetheryxflower ─ 4 alcohol ─ 3,709 ant ─ 11,924 apple ─ 15 armpithair ─ 2 <#951737931159187457>
And this will run EVERY TIME your clipboard changes, to avoid this, you can add at the top of the script #IfWinActive, WinTitle or #IfWinExist, WinTitle depending of your need.
The answer given would solve the problem, assuming that it never changes pattern as Diesson mentions.
I did the explanation of the code you provided with comments in the code below:
!q::
list = ; initalize a blank variable
; regexMatch(Haystack, regexNeedle, OutputVar, startPos)
; just for frame of reference in explanation of regexMatch
While ; loop while 'pos' <> 0
pos := RegExMatch(Clipboard ; Haystack is the string to be searched,
in this case the Clipboard
, "(\w*) ─ (\d*)" ; regex needle in this case "capture word characters
(a-z OR A-Z OR 0-9 OR _) any number of times, space dash space
then capture any number of digits (0-9)"
, m ; output var array base name, ie first capture will be in m1
second m2 and so on.
, pos ? pos + StrLen(m) : 1) ; starting position for search
"? :"used in this way is called a ternary operator, what is saying
is "if pos<>0 then length of string+pos is start position, otherwise
start at 1". Based on the docs, this shouldn't actually work well
since 'm' in this case should be left blank
list .= m2 " " m1 " " ; append the results to the 'list' variable
followed with a space
Clipboard := "" ; clear the clipboard.
Clipboard := "Pls trade " list " <#951737931159187457>"
ClipWait, 0 ; wait zero seconds for the clipboard to change
If ErrorLevel ; if waiting zero seconds for the clipboard to change
doesn't work, give error msg to user.
MsgBox, 48, Error, An error occurred while waiting for the clipboard.
return
Frankly this code is what I would call quick and dirty, and seems unlikely to work well all the time.

How to break a long code line into multiple lines in NetLogo?

In Python, we break a long line of code into multiple code lines with backslash like this.
a = 5
b = 11
print(str(a) + " plus " + \
str(b) + " is " + \
str(a + b))
# prints "5 plus 11 is 16"
How do we do that in NetLogo?
NetLogo doesn't care about multiple lines except for comments (the comment marker ; only lasts to the end of the line). All of these are the same:
to testme
; single line
let a 25 print a
; command per line
let b 20
print b
; unreadable
let
c
15
print
c
end

How to save names in a Qbasic file?

I am trying to create a program in Qbasic wherein a person can enter their name and label themselves as admin or unwanted user. How do I save these preferences in my program?
If you have inputed the username with something like,
INPUT "Type your username: ", uName$
To save it to a file, simply use these commands:
OPEN "User.dat" FOR OUTPUT AS #1
PRINT #1, uName$
CLOSE #1
Here's a complete program:
DEFINT A-Z
'Error handler for the first time we run the program. The data file won't exist, so we create it.
ON ERROR GOTO FileNotExist
'Create a type and an Array of users that would include Username and the Status (adminstrator vs. Unwanted user)
TYPE user
Uname AS STRING * 16
Status AS STRING * 1
END TYPE
DIM Users(1 TO 100) AS user
'Gets all the users stored in the file. i is a variable which represents the number of users before adding a new user
i = 0
OPEN "User.txt" FOR INPUT AS #1
WHILE NOT EOF(1)
i = i + 1
INPUT #1, Users(i).Uname
INPUT #1, Users(i).Status
WEND
CLOSE #1
TryAgain:
'Gets info for the new user
CLS
INPUT "User name: ", Users(i + 1).Uname
PRINT "Admin (a), Unwanted user (u), or Regular user (r) ?"
Users(i + 1).Status = LCASE$(INPUT$(1))
'Ensure there are no blank lines in the file
IF Users(i + 1).Uname = "" OR Users(i + 1).Status = "" THEN GOTO TryAgain
'Outputs user data to the file "User.txt"
OPEN "User.txt" FOR OUTPUT AS #1
FOR j = 1 TO i + 1
PRINT #1, Users(j).Uname
PRINT #1, Users(j).Status
NEXT j
CLOSE #1
'Just for a closer: Prints all the current users.
CLS
FOR j = 1 TO i + 1
PRINT Users(j).Uname,
IF Users(j).Status = "a" THEN PRINT "Amdinistrator" ELSE IF Users(j).Status = "u" THEN PRINT "Unwanted User" ELSE IF Users(j).Status = "r" THEN PRINT "Regular user" ELSE PRINT Users(j).Status
NEXT j
END
'*** ERROR HANDLER: ***
FileNotExist:
OPEN "User.txt" FOR OUTPUT AS #1
CLOSE
RESUME
To save a name into a file, you will need to use the WRITE statement.
Eg:
OPEN "Name.txt" FOR OUTPUT AS #1
INPUT"Enter a name";a$
WRITE #1,a$
CLOSE #1
END

How to print dataset content using Rexx

I'm trying to print the data (line by line) found in the IO.ME.DATA dataset (see my jcl).
I get the following error and looking to get the syntax right:
10 +++ DO I = 1 TO SYSTSIN.0
Error running MYREXX, line 10: Bad arithmetic conversion
I'm new to REXX. Thanks
JCL
//JCL01 JOB 000,'TEST REXX',
// CLASS=T,
// MSGCLASS=X,
// USER=ME
/*JOBPARM R=999,T=999,L=9999,S=ANY
//*
//STEPREXX EXEC PGM=IKJEFT01,PARM='MYREXX'
//SYSEXEC DD DISP=SHR,DSN=IO.ME.REXX
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD DISP=SHR,DSN=IO.ME.DATA
//
MYREXX (IO.ME.REXX)
SAY 'START OF REXX CODE.'
"EXECIO * DISKR SYSTSIN (STEM LINE. FINIS"
DO I = 1 TO SYSTSIN.0
SAY "VALUE OF I : " SYSTSIN.I
END
SAY 'END OF REXX CODE.'
DATA (from IO.ME.DATA)
MYDATA1,A
MYDATA2,B
MYDATA3,C
MYDATA4,D
MYDATA5,E
Try changing the do loop to
DO I = 1 TO Line.0
SAY "VALUE OF I : " Line.I
END
the command
"EXECIO * DISKR SYSTSIN (STEM LINE. FINIS"
says read the file SYSTSIN in to the stem variable Line. The number of lines read will be placed into line.0, line.1 will hold the first line in the file etc.
In addition to what #Bruce Martin wrote, don't point SYSTSIN to your input data. Use a different DD. IKJEFT01 uses SYSTSIN for its own purposes. Even if it works in this particular case, it's a bad habit to use DDNAMES that are known to be used for other purposes for your own.
//JCL01 JOB 000,'TEST REXX',
// CLASS=T,
// MSGCLASS=X,
// USER=ME
/*JOBPARM R=999,T=999,L=9999,S=ANY
//*
//STEPREXX EXEC PGM=IKJEFT01,PARM='MYREXX'
//SYSEXEC DD DISP=SHR,DSN=IO.ME.REXX
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD DUMMY
//MYDATA DD DISP=SHR,DSN=IO.ME.DATA
//*
This wasn't going to fit in a comment, but I felt it important to point out.