The PL/I compiler generate the compile information with line number
and descritions,
but for most of online modules, if has CICS or SQL statement, the
compile information's line number is not match with the line number of
source, it's hard to find out which line caursed compile problem.
Is there any compiler option to merge source with compiler erorr or
any other solutions?
Actually, i use vim or shell script merge successfully, but it's
much better if we can use on mainframe.
Regrards
Some new features in PL/I like Decimal Floating Point are only supported
by the coprocessor, not the preprocessor.
Jessica
Ricky WU schrieb:
Try the following edit macro. Prerequisite is that your source has
sequence numbers. Not perfect, but will do the job pretty well.
"GETVAR" is a routine that retrieves my site-specific data. "macro ?"
will give a help-"screen". I wrote the initial version of this in
about an hour, with a few tweaks since then. If you find any more
problems, drop me a line. The '\|' on the second line of the source
are NOT and OR signs.
/* REXX edit macro to merge compiler errors with source
*/
/*** trace ?r ***************************************************** \|
*
* (C) Copyright Robert AH Prins, 2009-2009
*
************************************************************************
* ------------------------------------------------------------------
*
* | Date | By | Remarks |
*
* |------------+------+----------------------------------------------|
*
* | | | |
*
* |------------+------+----------------------------------------------|
*
* | 2009-05-13 | RAHP | Add 'ALL' parameter option to display every |
*
* | | | message |
*
* |------------+------+----------------------------------------------|
*
* | 2009-04-15 | RAHP | Cater for multiple messages per statement |
*
* |------------+------+----------------------------------------------|
*
* | 2009-04-02 | RAHP | Suppress IBM1219I W LEAVE will exit |
*
* | | | noniterative DO-group. |
*
* |------------+------+----------------------------------------------|
*
* | 2009-03-25 | RAHP | Suppress IBM1085I I <fieldx> may be |
*
* | | | uninitialized when used. |
*
* |------------+------+----------------------------------------------|
*
* | 2009-03-17 | RAHP | Suppress IBM1042I I String spans <n> lines. |
*
* |------------+------+----------------------------------------------|
*
* | 2009-03-09 | RAHP | Add standard help "screen" |
*
* |------------+------+----------------------------------------------|
*
* | 2009-03-04 | RAHP | Cater for only suppressed messages |
*
* |------------+------+----------------------------------------------|
*
* | 2009-03-03 | RAHP | Cater for my own compile jobs |
*
* |------------+------+----------------------------------------------|
*
* | 2009-02-24 | RAHP | Initial version |
*
* |------------+------+----------------------------------------------|
*
************************************************************************
* ERRPLIX is a REXX edit macro to merge the error messages of the PL/I
*
* Enterprise Compiler with the source of the program being compiled,
*
* making it a lot easier to correct errors.
*
*
*
* Global (!g.0xxxx) variables:
*
*
*
* - stmt - compiled with STMT (1) or NOSTMT (0)
*
* - sl - number of relevant positions in sequence numbers
*
* - lp - position of statement number/line.file
*
* - num - position of sequence numbers
*
* - m - number of compiler messages
*
* - c - start of 'Compiler Source' section
*
* - err. - message ID
*
* - sev. - message severity
*
* - loc. - message location (statement or line.file)
*
* - txt. - message text
*
* - put - did we insert any message lines (Cater for the case that
*
* the only messages are those that we suppress, like line-
*
* spanning comments)
*
************************************************************************
* This program is free software: you can redistribute it and/or
*
* modify it under the terms of the GNU General Public License as
*
* published by the Free Software Foundation, either version 3 of
*
* the License, or (at your option) any later version.
*
*
*
* This program is distributed in the hope that it will be useful,
*
* but WITHOUT ANY WARRANTY; without even the implied warranty of
*
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*
* GNU General Public License for more details.
*
*
*
* You should have received a copy of the GNU General Public License
*
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
***********************************************************************/
parse source source
parse value source with . . moi .
signal on syntax
"isredit macro (parm)"
"ispexec control errors return"
parm = strip(translate(parm))
if parm = '?' then
do
call help
exit 1
end
/
***********************************************************************
* Set up variables, slurp in the compiler listing, extract messages
*
***********************************************************************/
call init
call pre_process
eol = 0
"isredit (CAPS) = caps"
"isredit caps = OFF"
do i = !g.0c + 1 by 1 until eol
if substr(lline.i, 2, 32) = '5655-H31 IBM(R) Enterprise PL/I' then
do
j = i + 1
eol = substr(lline.j, 2, 13) \= ' Line.File'
iterate i
end
if !g.0stmt then
loc = strip(substr(lline.i, !g.0lp, 7))
else
parse value space(substr(lline.i, 2)) with loc ' ' .
if loc = '' then
iterate i
seq = substr(lline.i, !g.0num, !g.0sl)
if !g.loc.0err.1 \= 0 &,
(parm = 'ALL' |,
pos(!g.loc.0err.1, !g.0sup_msg) = 0) then
call put_msg
end
/
***********************************************************************
* Put non-statement/top messages
*
***********************************************************************/
seq = 1
do loc = -1 by -1 while !g.loc.0err \= 0
call put_msg
end
"isredit caps = (CAPS)"
"isredit l 0"
/
***********************************************************************
* Cater for the case where all of the messages are of the types we do
*
* not really care for, like line-spanning comments or strings.
*
***********************************************************************/
if !g.0put then
do
zcmd = ";&l msgline next"
"ispexec control nondispl end"
"ispexec display panel(isr@prim)"
end
else
do
zedlmsg = 'There were compiler messages, but all of them are on',
'the list of messages that are suppressed because they',
'are only informational.'
"ispexec setmsg msg(ISRZ001)"
exit 1
end
exit
/
***********************************************************************
* PUT_MSG:
*
*
*
* Insert a compiler message into the source
*
***********************************************************************/
put_msg: procedure expose !g. seq loc
do i = 1 to !g.loc.0mul
txt = ' '!g.loc.0err.i !g.loc.0sev.i
spc = left(' ', length(txt))
txt = txt !g.loc.0txt.i
do while strip(txt) \= ''
err = left(txt, 72)
txt = substr(txt, 73)
if right(err, 1) \= ' ' &,
left(txt, 1) \= ' ' then
do
parse value reverse(err) with rem ' ' err
err = reverse(err)
txt = reverse(rem)txt
end
txt = spc strip(txt)
"isredit line_before" seq "= msgline (ERR)"
end
end
!g.loc.0err = 0
!g.0put = 1
return
/
***********************************************************************
* INIT:
*
*
*
* Perform a number of initialisations
*
***********************************************************************/
init:
!g. = 0
zedsmsg = ''
"isredit (DSN) = dataset"
"isredit (MEM) = member"
"isredit reset"
"isredit (ZL) = linenum .zl"
if zl < 10000 then
!g.0sl = 4
else
!g.0sl = 5
"isredit res spe"
!pli = translate(getvar('pliRAHP'))
lqual = ''
if dsn \= !pli then
do
!here = getvar('HERE')
if !here = 'NVSM' then
do
!pds = translate(getvar('PDS'))
if right(dsn, length(!pds)) = !pds then
lqual = 'SPFPLI.'
end
end
/
*********************************************************************
* Message if listing does not exist
*
*********************************************************************/
listing = ''''userid()'.'lqual || mem'.LIST'''
if sysdsn(listing) \= 'OK' then
do
zedlmsg = 'Listing dataset' listing 'not found'
"ispexec setmsg msg(ISRZ001)"
exit 1
end
/
*********************************************************************
* Slurp in the listing
*
*********************************************************************/
"alloc f(in) da("listing") shr"
"execio * diskr in (stem lline. finis"
"free f(in)"
/
*********************************************************************
* The following three '!xxx_msg' variables contain the numbers of
*
* the messages that need 'special' processing. Note that, when
*
* adding additional messages to any of these three variables, the
*
* '-' are required to separate them.
*
*
*
* !gen_msg: messages without statement numbers will be put at the
*
* top of the source
*
* - IBM1193I - <N> statements in block <block>. Optimization
*
* restricted.
*
*
*
* !top_msg: messages that will be put at the top of the source
*
* !end_msg: messages that will be put at the bottom of the source
*
*
*
* !sup_msg: messages that will be suppressed
*
* - IBM1036I - The next <N> statements were merged with this
*
* statement.
*
* - IBM1041I - Comment spans <N> lines.
*
* - IBM1042I - String spans <N> lines.
*
* - IBM1085I - <fieldx> may be uninitialized when used.
*
* - IBM1219I - LEAVE will exit noniterative DO-group.
*
*********************************************************************/
!g.0gen_msg = 'IBM1193I ' ||,
''
!g.0top_msg = ''
!g.0end_msg = ''
!g.0sup_msg = 'IBM1036I ' ||,
'IBM1041I ' ||,
'IBM1042I ' ||,
'IBM1085I ' ||,
'IBM1219I ' ||,
''
return
/
***********************************************************************
* PRE_PROCESS:
*
*
*
* - check that this is an Enterprise Compiler listing
*
* - find out the state of the 'STMT' compiler option
*
* - extract all error messages
*
***********************************************************************/
pre_process: procedure expose lline. !g.
ok = 0
do i = 1 to 100 until ok
ok = pos('5655-H31 IBM(R) Enterprise PL/I for z/OS', lline.i) \=
0
end
if \ok then
do
zedlmsg = '''5655-H31 IBM(R) Enterprise PL/I for z/OS''
string',
'not found in the first 100 lines of the compiler',
'listing, processing terminated.'
"ispexec setmsg msg(ISRZ001)"
exit 1
end
ok = 0
do i = i by 1 for 500 until ok
ok = pos(' Compiler Source', lline.i) \= 0
end
if \ok then
do
zedlmsg = 'Start of ''Compiler Source'' section not found in
the',
'first' i 'lines of the compiler listing, processing',
'terminated.'
"ispexec setmsg msg(ISRZ001)"
exit 1
end
i = i + 1
!g.0c = i
select
when pos('Line.File LV NT', space(lline.i)) \= 0 then
do
!g.0stmt = 0
!g.0lp = 2
!g.0num = 96
end
when pos('Line.File Stmt LV NT', space(lline.i)) \= 0 then
do
!g.0stmt = 1
!g.0lp = pos(' Stmt ', lline.i)
!g.0num = 105
end
otherwise
do
zedlmsg = 'Cannot determine the setting of the (NO)STMT',
'compiler option, processing terminated.'
"ispexec setmsg msg(ISRZ001)"
exit 1
end
end
/
*********************************************************************
* Find the 'Compiler Messages' section, scanning backwards
*
*********************************************************************/
ok = 0
do i = lline.0 by -1 until ok
if substr(lline.i, 3, 17) = 'Compiler Messages' then
ok = 1
else
if substr(lline.i, 3, 20) = 'No Compiler Messages' then
do
zedlmsg = 'Compilation ended with ''No Compiler
Messages'',',
'nothing to do, processing terminated.'
"ispexec setmsg msg(ISRZ001)"
exit 1
end
end
/
*********************************************************************
* Process the 'Compiler Messages' section
*
*********************************************************************/
m = 0
ok = 0
do i = i + 1 by 1 until ok
select
/
*****************************************************************
* End of 'Compiler Messages'
*
*****************************************************************/
when substr(lline.i, 3, 20) = 'File Reference Table' then
ok = 1
/
*****************************************************************
* Skip pagebreaks and header lines
*
*****************************************************************/
when substr(lline.i, 2, 16) = '5655-H31 IBM(R)' |,
substr(lline.i, 2, 13) = ' Message ' then
iterate i
/
*****************************************************************
* Continuation of message
*
*****************************************************************/
when substr(lline.i, 3, 8) = ' ' then
do
line = space(substr(lline.i, 3))
!g.0txt.m = !g.0txt.m line
? = !g.loc.0mul
!g.loc.0txt.? = !g.loc.0txt.? line
end
/
*****************************************************************
* Process message
*
*****************************************************************/
when substr(lline.i, 3, 3) = 'IBM' then
do
line = space(substr(lline.i, 3))
parse value line with err ' ' sev ' ' loc ' ' txt
/
*************************************************************
* Is this a statement-less message
*
*************************************************************/
if pos(err, !g.0gen_msg) \= 0 then
txt = space(loc) space(txt)
/
*************************************************************
* Find a free slot for the statement-less and top-of source
*
* messages by using negative locations :)
*
*************************************************************/
if pos(err, !g.0gen_msg) \= 0 |,
pos(err, !g.0top_msg) \= 0 then
do loc = -1 by -1 until !g.loc.0err = 0
end
/* Debug only
************************************************
m = m + 1
!g.0err.m = err
!g.0sev.m = sev
!g.0loc.m = loc
!g.0txt.m = txt
*************************************************************/
!g.loc.0mul = !g.loc.0mul + 1
? = !g.loc.0mul
!g.loc.0err.? = err
!g.loc.0sev.? = sev
!g.loc.0txt.? = txt
end
/
*****************************************************************
* Something unexpected, quit with a message
*
*****************************************************************/
otherwise
do
zedlmsg = 'Cannot determine the type of message line',
'('lline.i'), processing terminated.'
"ispexec setmsg msg(ISRZ001)"
exit 1
end
end
end
!g.0m = m
/
*********************************************************************
* Process the 'File Reference Table' section (Data as yet unused)
*
*********************************************************************/
f = 0
ok = 0
do i = i + 1 by 1 until ok
select
when substr(lline.i, 2, 16) = '5655-H31 IBM(R)' |,
substr(lline.i, 2, 8) = ' Message' then
iterate i
when substr(lline.i, 3, 24) = 'Component Return Code' then
ok = 1
when substr(lline.i, 3, 29) = ' File Included From Name'
then
do
fil = pos(' File ', lline.i) + 1
inc = pos(' Included ', lline.i) + 1
nam = pos(' Name', lline.i) + 1
end
otherwise
if datatype(strip(substr(lline.i, fil, 4))) = 'NUM' then
do
parse var lline.i . =(fil) ?f =(inc) ?i =(nam) ?n
f = f + 1
!g.0fil.f = strip(?f)
!g.0inc.f = strip(?i)
!g.0nam.f = strip(?n)
end
end
end
!g.0f = f
return
/
***********************************************************************
* SYNTAX:
*
*
*
* This procedure gives a 'clean' exit for errors
*
***********************************************************************/
syntax:
call guru source,rc,sigl,sourceline(sigl)
exit
/
***********************************************************************
* HELP:
*
*
*
* This procedure gives a bit of help on how to use the macro
*
***********************************************************************/
help:
line. = ''
type. = 'NOTE'
i = 1
text = 'The' moi 'edit macro'
line.i = center(text, 72)
type.i = 'MSG'
i = i + 1
line.i = center(left('~', length(text), '~'), 72)
type.i = 'MSG'
i = i + 1
line.i = center(' Use DOWN to read all "HELP" screens ', 72, '*')
type.i = 'MSG'
i = i + 2
line.i = ' The' moi 'edit macro can be used to merge the compiler',
'messages'
i = i + 1
line.i = ' with the source of the program being edited. To do so,',
'you must use'
i = i + 1
line.i = ' the "NUM ON" and "AUTONUM ON" edit-profile settings.'
i = i + 2
line.i = ' After the compile job has finished, you can give the',
'command 'moi
i = i + 1
line.i = ' and this will extract the error messages from the data
set'
i = i + 1
line.i = ' containing the compiler listing and insert them into',
'the member in'
i = i + 1
line.i = ' the form of "==MSG>" lines.'
i = i + 2
line.i = ' The macro will also put a "&L MSGLINE NEXT" command on',
'the command-'
i = i + 1
line.i = ' line and you can now move from one inserted message to',
'the next by'
i = i + 1
line.i = ' just pressing Enter.'
i = i + 2
line.i = center(' Legal information ', 72, '*')
type.i = 'MSG'
i = i + 2
line.i = ' This program is free software: you can redistribute it',
'and/or modify'
i = i + 1
line.i = ' it under the terms of the GNU General Public License',
'as published by'
i = i + 1
line.i = ' the Free Software Foundation, either version 3 of the',
'License, or (at'
i = i + 1
line.i = ' your option) any later version.'
i = i + 2
line.i = ' This program is distributed in the hope that it',
'will be useful, but'
i = i + 1
line.i = ' WITHOUT ANY WARRANTY; without even the implied',
'warranty of'
i = i + 1
line.i = ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ',
'See the GNU'
i = i + 1
line.i = ' General Public License for more details.'
i = i + 2
line.i = ' You should have received a copy of the GNU General',
'Public License'
i = i + 1
line.i = ' along with this program. If not, see',
'<http://www.gnu.org/licenses/>.'
i = i + 2
line.i = center(' End of HELP information ', 72, '*')
type.i = 'MSG'
line.0 = i
"isredit (STATE) = user_state"
"isredit caps = off"
do i = line.0 to 1 by -1
lin = line.i
"isredit line_after 0 = "type.i"line (LIN)"
end
"isredit user_state = (STATE)"
"isredit locate 0"
return