Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

SCLM parser for Easytrieve plus programs

219 views
Skip to first unread message

Peter Vander Woude

unread,
Aug 10, 2001, 10:59:26 AM8/10/01
to
We are adding support to our SCLM projects so that our applications programmers can compile Easytrieve plus programs. Does anyone have a parser program that will handle Easytrieve plus?

Thanks,


Peter I. Vander Woude

Mainframe Engineer
Harris Teeter, Inc.

Paul Hanrahan

unread,
Aug 10, 2001, 11:36:06 AM8/10/01
to
Had you considered using a call of easytrieve in batch and then use rexx
to parse the output and look for a good return code. I have something like
the above that works for CA's jcl checker. I wrote it in rexx.

I'll send you the code if you think it'd be useful.

Paul

Peter Vander Woude

unread,
Aug 10, 2001, 11:36:43 AM8/10/01
to
What I'm looking for is something like what SCLM does for COBOL source. That is, parse the source and identify if there are any COPYBOOKs used so that SCLM do automatic rebuilds of programs when a copybook is changed. Or to do automatic promotes of copybooks when the base source is promoted.

Peter I. Vander Woude

Mainframe Engineer
Harris Teeter, Inc.

>>> pe...@PO.CWRU.EDU 08/10/2001 >>>

Paul Hanrahan

unread,
Aug 10, 2001, 12:09:08 PM8/10/01
to
Peter:

I think you could force this type of thing to happen through architecture
members.

Peter Vander Woude

unread,
Aug 10, 2001, 12:13:12 PM8/10/01
to
Paul,

That is true. But the default programs (i.e. what's specified on the COMPILE parm of the FLMTRNSL macro (when function=PARSE)) do not process Easytrieve programs (to the best of my knowledge). I am just checking to see if anyone out there wrote a custom parser to process this source when the user saves the source in SCLM option 2.

Paul Hanrahan

unread,
Aug 10, 2001, 2:01:19 PM8/10/01
to
I didn't do anything with copy libs .... There is an example of a home grown
package I picked up for doing this but it wasn't easytrieve. Here's what
the author of the tool had to say:

Doug LaSala
Mail Station 344
Ford New Holland, Inc
P.O. Box 1895
New Holland, PA 17557-0903
(717) 355-3130 / (717) 355-9282

NOTE: This tool is not to be used for profit.
COPYRIGHT 1994 FORD NEW HOLLAND AMERICAS

The SCLM Migration tool can be used to migrate applications which reside in
PDS' or Panvalet libraries into Software Configuration and Library Manager.
Give it some basic information (modules to copy, associated MFS (for IMS -
optional), DB2 DBRMs which make up the DB2 plan associated with each module
(optional), batch or online indicator, and non-default compiler options).
Also, tell it where you are to be copying source, copybooks, panvalet
++includes, DB2 dclgens, and MFS from, and SCLMMIG does the rest.

It determines and copies all copybooks associated with each program, copies
the source, MFS, DB2 dclgens, panvalet ++includes (and converts calls to
them
in the source to COPY statements) into the proper SCLM libraries.

It also scans each corresponding load module and determines if the program
is
IMS, DB2, and subprograms statically linked. Using this information, it
then
builds the Architecture definitions and DB2CLISTs for each program! To top
it
all off, it runs an SCLM migrate against all migrated pieces! This
generates
the accounting information in SCLM.

Once SCLMMIG is finished, all you need to do is build the application you
just
migrated! Magic. Comments and suggestions are welcome at the above
address/phone number.

Stephen T. Parfitt

unread,
Aug 10, 2001, 3:52:22 PM8/10/01
to
You can modify the sample COBOL parser that is supplied by IBM (there's
at least one version ... the REXX one is easy to modify and test
although it runs rather slowly). Here's what I used ... you will have
to modify the <HLQ> for the error dataset. Note that my effort only
finds %macro dependencies. As far as I remember those are the only
'static' dependencies in EasyTrieve although I could be wrong; I have
not used EasyTrieve for a couple of years now.

Steve Parfitt

/* REXX ***************************************************************/
/**********************************************************************/
/* EASYTRIEVE Parser */
/* PROGRAM NAME: FLEZPGEN */
/**********************************************************************/
/* INPUTS: */
/* PARAMETERS - */
/* LISTSIZE=char -- Character value representing dependencies */
/* buffer size in bytes (@@FLMSIZ). */
/* The length of each element is 228 bytes. */
/* For example, a list with 100 elements will */
/* be 100*228 (or 22800) bytes long). */
/* */
/* LISTINFO=char -- Character representation of the address */
/* to the dependencies array (@@FLMLIS). */
/* */
/* STATINFO=char -- Character representation of the address */
/* to the statistics structure (@@FLMSTP). */
/* */
/* Note: These parameters are keyword dependent, not positional. */
/* */
/* FILES - */
/* The DDNAME SOURCE is the input source member to parse. */
/* */
/**********************************************************************/
/* OUTPUTS: */
/* PARAMETERS - */
/* LISTINFO and STATINFO structures are completed by this parser. */
/* */
/* FILES - */
/* A userid.SCLMERR.LISTING sequential data set may be */
/* created by this parser if an error is encountered. */
/* */
/* RETURN CODES - */
/* 0 - Successful completion. */
/* 4 - Mismatched quotes (single and double), */
/* dependency name exceeded 8 characters */
/* 8 - Dependency array full */
/* 10- Invalid or incomplete parameters */
/* 16- Unable to write to error listings file */
/* 20- Unable to close source file */
/* 22- I/O error for source file */
/* */
/**********************************************************************/
/* FUNCTIONAL DESCRIPTION: */
/* This parser will determine the */
/* dependencies and statistics for EZTP source. Dependencies */
/* are created for %MACRO statements */
/* The DDNAME SOURCE is used as input. */
/* */
/* The following statistics are tabulated by this parser: */
/* Total Lines */
/* Blank Lines */
/* Comment Statements */
/* */
/* Comment Lines, Noncomment Lines, Prolog Lines, Total Statements, */
/* Noncomment Statements, Control Statements, and Assignment */
/* Statements are all set to zero by this parser. */
/* For additional information, see the SCLM Guide & Reference. */
/* */
/* Dependencies are generated by the following syntax: */
/* %<member> */
/* */
/* RESTRICTIONS: */
/* The following are not supported by this parser: */
/* */
/* - Syntax error detection of dependency name (caught by */
/* the compiler) */
/* - Double Byte Character Set characters */
/* */
/* Dependency member names of more than eight characters are */
/* truncated to eight characters and added to the dependency list. */
/* If this happens, the parser return code is set to 4, an error */
/* message is written to the error listing, and parsing continues. */
/* */
/**********************************************************************/
/* INTERNAL PROCESS: */
/* Each record is processed to obtain the dependency */
/* information and statistics. State variables are used to see */
/* if something from the previous line affects the current */
/* line. */
/* */
/* The following is the high level process for FLEZPGEN: */
/* */
/* initialization */
/* UNTIL done DO */
/* get_line */
/* process_line */
/* END */
/* termination */
/* */
/* The following state variables are used in this parser: */
/* */
/* */
/* All variables in this module are global. Each routine's */
/* prolog will state variables used and variables changed. */
/* */
/**********************************************************************/
/* CHANGE ACTIVITY: */
/* 1997-09-18 STP - CREATED */
/* */
/**********************************************************************/


arg parm

/* Constants */
/* Boolean variables, Error Conditions */
/* Group 1 contains constants that are common for all SCLM REXX */
/* parsers; Group 2 contain constants specific to this language */
/* parser */

/* Group 1 - not normally altered */

TRUE = 1
FALSE = 0

ON = 1 /* State variables can be ON */
OFF = 0 /* or OFF */

SUCCESSFUL = 0 /* No problems encountered */
CONTINUE_PARSING = 4 /* Problem with a quote or a dep- */
/* endency name. Print error in */
/* listing and continue parsing */
DEP_ARRAY_FULL = 8 /* Dependency array is full */
INVALID_PARMS = 10 /* Invalid parameters passed in */
/* from the language definition */
ERR_IO_ERROR = 16 /*Unable to write to error listings file*/
CLOSE_ERROR = 20 /* Unable to close source file */
IO_ERROR = 22 /* IO error for source file */

DDNAME = 'SOURCE' /* The source DDNAME */

ERROR_DD = 'FLMPERR' /* DDNAME for error listing file */
ERRFILE = '<HLQ>.SCLMERR.LIST'
/* data set name for error */
/* listing file */

EOF_FLAG = 2 /* The RC for EOF is equal to 2 */

DEP_ELEM_SIZE = 228 /* Size of each dependency array */
/* element */

INCLUDE_KEYWORD = 'INCL' /* SCLM dependency keyword (in */
/* array structure) */
INCLUDE_KEY_SIZE = 4 /* Size of dependency keyword */
MEMBER_LENGTH = 8 /* Maximum length of dependency */
/* name */
END_KEYWORD = 'END ' /* End-of-dependecies marker */

OVER ='00000000' /* Left justify dependency address*/
/* with zeros */
NUMBER_OF_PARMS = 3 /* Number of input parms from the */
/* language definition */

/* Group 2 - language parser specific constants */

BLANK = ' ' /* a blank string */


/* the following 7 strings will cause a token to be split */

COMMENT = '*'
MACRO = '%'

VALID_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890@#$'
/* Characters that are valid */
/* in a member name */

/* Main Program Begins */

/* Invoke Initialization routine */

CALL initialization

/* The while loop gets a line from the EZsource file. If it is */
/* not the end of the file, then process the line. Continue looping */
/* until the end of file or an error occurs. */

DO WHILE (ret_code <= CONTINUE_PARSING) &,
(eof = FALSE)

CALL get_line

IF (ret_code <= CONTINUE_PARSING) &,
(eof = FALSE) THEN
CALL process_line

END /* WHILE main processing loop (until EOF) */

/* Termination routine - end the parsing process. Only call */
/* if not a severe error */

IF ret_code <= DEP_ARRAY_FULL THEN
CALL termination

EXIT ret_code


/* ------------------------------------------------------------------ */
/* ROUTINE: initialization */
/* */
/* FUNCTION: */
/* */
/* This routine will initialize the variables used throughout */
/* this parser. The required input parameters are read. */
/* */
/* VARIABLES USED: */
/* parm */
/* */
/* VARIABLES CHANGED: */
/* state (all initialized to OFF), state.prolog, eof, dep_count, */
/* sclm_dep_addr, sclm_dep_array_size, sclm_stats_addr, stats, */
/* reserve_words, dep_words, ret_code */
/* */
/* ------------------------------------------------------------------ */

initialization:

/* initialize variables */

stats. = 0 /* Set all statistics counters to zero */
state. = OFF /* Set all state flags to zero (OFF) */
state.prolog = ON /* Set the prolog state to ON */
parm_number = 0 /* Counter for the number of parms */
eof = FALSE /* Assume file exists, initially */
dep_count = 0 /* Start at the beginning of the dep struct */
ret_code = SUCCESSFUL

/* Get parameters from SCLM to REXX variables */

DO WHILE LENGTH(parm) > 0
PARSE UPPER VALUE parm with temp_parm ',' rest
parm = STRIP(rest)

IF SUBSTR(STRIP(temp_parm),1,9) = 'LISTSIZE=' &,
state.listsize = OFF THEN
DO
sclm_dep_array_size = STRIP(SUBSTR(STRIP(temp_parm),10))
parm_number = parm_number + 1
state.listsize = ON
END /* IF buffer size parameter */

ELSE IF SUBSTR(STRIP(temp_parm),1,9) = 'LISTINFO=' &,
state.dependency_address = OFF THEN
DO
sclm_dep_addr = STRIP(SUBSTR(STRIP(temp_parm),10))
parm_number = parm_number + 1
state.dependency_address = ON
END /* ELSE IF dependency address parameter */

ELSE IF SUBSTR(STRIP(temp_parm),1,9) = 'STATINFO=' &,
state.stats_address = OFF THEN
DO
sclm_stats_addr = STRIP(SUBSTR(STRIP(temp_parm),10))
parm_number = parm_number + 1
state.stats_address = ON
END /* ELSE IF statistics address parameter */
END /* WHILE parameters exist to parse */

/* Ensure all required input parameters are present. */
/* Print an error message (to the error listing file) of all the */
/* missing parameters. */

IF parm_number ¬= NUMBER_OF_PARMS THEN
DO
ret_code = INVALID_PARMS
IF state.listsize = OFF THEN
miss_parm1 = 'LISTSIZE=?'
ELSE
miss_parm1 = ''
IF state.dependency_address = OFF THEN
miss_parm2 = 'LISTINFO=?'
ELSE
miss_parm2 = ''
IF state.stats_address = OFF THEN
miss_parm3 = 'STATINFO=?'
ELSE
miss_parm3 = ''

error_string1 = miss_parm1 ' ' ||,
miss_parm2 ' ' ||,
miss_parm3
error_string2 = ''
CALL error_listing

END /* IF required parameters missing */

/* must have room for at least one entry */

IF sclm_dep_array_size < DEP_ELEM_SIZE THEN
DO
ret_code = INVALID_PARMS
error_string1 = 'LISTSIZE=',
||sclm_dep_array_size
error_string2 = ' LISTSIZE < ',
DEP_ELEM_SIZE
CALL error_listing
END /* IF must have room for at least one entry */

/* address must be a positive whole number */
IF (DATATYPE(sclm_dep_array_size,'W') = 0) | ,
(sclm_dep_array_size <= 0) THEN
DO
ret_code = INVALID_PARMS
error_string1 = 'LISTSIZE=',
||sclm_dep_array_size
error_string2 = ''
CALL error_listing
END /* address must be a positive whole number */

/* address must be a positive whole number */
IF (DATATYPE(sclm_dep_addr,'W') = 0) | ,
(sclm_dep_addr <= 0) THEN
DO
ret_code = INVALID_PARMS
error_string1 = 'LISTINFO=',
||sclm_dep_addr
error_string2 = ''
CALL error_listing
END /* address must be a positive whole number */

/* address must be a positive whole number */
IF (DATATYPE(sclm_stats_addr,'W') = 0) | ,
(sclm_stats_addr <= 0) THEN
DO
ret_code = INVALID_PARMS
error_string1 = 'STATINFO=',
||sclm_stats_addr
error_string2 = ''
CALL error_listing
END /* address must be a positive whole number */


RETURN


/* ------------------------------------------------------------------ */
/* ROUTINE: error_listing */
/* */
/* FUNCTION: */
/* */
/* This routine first checks if the error listing data set has */
/* been allocated. If a previous attempt was made to allocate */
/* the data set and it failed, this routine will not attempt */
/* to allocate it again. The error message, specified in */
/* error_string1 and error_string2 before invocation, are placed */
/* on the stack and printed to the data set. */
/* */
/* VARIABLES USED: */
/* state.error, state.error_alloc_errfile, error_string1, */
/* error_string2 */
/* */
/* VARIABLES CHANGED: */
/* <NONE> */
/* */
/* ------------------------------------------------------------------ */

error_listing:

/* Check for error listing file already opened. Also, if there was */
/* a problem trying to allocate it previously, do not try again. */

IF (state.error = OFF) &,
(state.error_alloc_errfile = OFF) THEN
CALL allocate_error_listing

/* Place the error strings on the QUEUE for printing to the error */
/* listing file. */

IF state.error_ALLOC_errfile = OFF THEN
DO
QUEUE ret_code
QUEUE error_string1
QUEUE error_string2
IF error_string2 ¬= '' THEN QUEUE ''
"EXECIO * DISKW " ERROR_DD
IF RC ¬= 0 THEN
DO
ret_code = ERR_IO_ERROR
END /* bad return from EXECIO */
END /* error listing file allocated */

RETURN


/* ------------------------------------------------------------------ */
/* ROUTINE: allocate_error_listing */
/* */
/* FUNCTION: */
/* */
/* This routine allocates the error listing data set, */
/* userid.SCLMERR.LISTING. If the file exists, it will be */
/* overwritten, otherwise it will be created. If an error */
/* occurs while allocating the data set, a flag is set to not */
/* call this routine again. */
/* */
/* VARIABLES USED: */
/* <NONE> */
/* */
/* VARIABLES CHANGED: */
/* state.error_alloc_errfile, state.error */
/* */
/* ------------------------------------------------------------------ */

allocate_error_listing:

/* Write over or allocate error listing data set */

IF SYSDSN('"ERRFILE"') = 'OK' THEN
disp = 'OLD'
ELSE
disp = 'NEW CATALOG SPACE(1,1) TRACKS BLKSIZE(6160) LRECL(80)',
'RECFM(F,B)'

ADDRESS TSO "ALLOC FILE("ERROR_DD") DA('"ERRFILE"') REUSE" disp

/* Set flag if error listing data set could not be allocated; */
/* another attempt to allocate the file will not be made. */

IF RC ¬= 0 THEN
state.error_alloc_errfile = ON

state.error = ON

RETURN


/* ------------------------------------------------------------------ */
/* ROUTINE: get_line */
/* */
/* FUNCTION: */
/* */
/* This routine will read one line from the source file. If */
/* the end of file is reached, the end of file flag (eof) is set. */
/* */
/* VARIABLES USED: */
/* <NONE> */
/* */
/* VARIABLES CHANGED: */
/* line, eof, ret_code */
/* */
/* ------------------------------------------------------------------ */

get_line:

"EXECIO 1 DISKR " DDNAME
IF RC ¬= 0 THEN
DO
IF RC = EOF_FLAG THEN
eof = TRUE
ELSE
DO
ret_code = IO_ERROR
END /* ELSE error with input file */
END /* IF error or eof with read */
ELSE
DO
PULL line
line = STRIP(line,T)
END /* ELSE no error and not eof */

RETURN


/* ------------------------------------------------------------------ */
/* ROUTINE: process_line */
/* */
/* FUNCTION: */
/* */
/* This procedure will process each line, incrementing */
/* statistics, and adding appropriate dependencies. */
/* */
/* The following statistics are incremented by this routine: */
/* Total Lines */
/* Blank Lines */
/* */
/* The dependency (member) name must be placed inside double */
/* quotation marks or angle brackets for EZTP #include statements */
/* */
/* VARIABLES USED: */
/* line */
/* token */
/* stats.total_lines */
/* stats.blank_lines */
/* */
/* VARIABLES CHANGED: */
/* token */
/* stats.comments */
/* stats.total_lines */
/* stats.blank_lines */
/* error_string1, error_string2, ret_code */
/* */
/* ------------------------------------------------------------------ */

process_line:

/* Increment Total_lines */
stats.total_lines = stats.total_lines + 1

/* Check line for blank line. */
IF line = ' ' THEN
DO
stats.blank_lines = stats.blank_lines + 1
END /* IF blank line */

ELSE
/* line not blank */
DO
/* Process each token on the line until the end of the line */
/* or a severe error has occurred */

column = 1
eoln = FALSE

DO UNTIL (eoln = TRUE) |,
(ret_code >= DEP_ARRAY_FULL)

CALL get_token
CALL process_token

END /* UNTIL end of line */
END /* ELSE not blank line */

RETURN


/* ------------------------------------------------------------------ */
/* ROUTINE: get_token */
/* */
/* FUNCTION: */
/* */
/* This routine obtains one token from the current line */
/* and returns it (in token) to the caller. The current */
/* position in the line is maintained. A token is any */
/* stream of characters not separated by blanks, comment marks, */
/* or quotation marks (',"). The end of line flag (eoln) */
/* is set when the end of the line is reached. */
/* The column marker is set to one past the end of the token */
/* (that is, to the place to start looking for the next token) */
/* */
/* VARIABLES USED: */
/* line, column */
/* */
/* VARIABLES CHANGED: */
/* column, token, eoln */
/* */
/* ------------------------------------------------------------------ */

get_token:

/* Get the first token, starting at column */

unparsed_line = SUBSTR(line,column)
PARSE VALUE unparsed_line WITH token .


started_column = POS(token,line,column)
column = started_column + LENGTH(token);

IF column > LENGTH(line) | token = '' THEN
eoln = TRUE

RETURN


/* ------------------------------------------------------------------ */
/* ROUTINE: process_token */
/* */
/* FUNCTION: */
/* For each token, based on the token and the current state */
/* variables, enter new states and update the dependency list */
/* as needed. */
/* */
/* VARIABLES USED: */
/* token */
/* valid_name */
/* */
/* VARIABLES CHANGED: */
/* stats.comment_stmts */
/* ------------------------------------------------------------------ */
process_token:

IF substr(token,1,1) = COMMENT THEN
DO

stats.comment_stmts = stats.comment_stmts + 1
eoln = TRUE
END

ELSE IF substr(token,1,1) = MACRO THEN
DO
CALL get_include_name

IF (LENGTH(name) > MEMBER_LENGTH) & valid_name THEN
DO
CALL truncate_name
END

IF (LENGTH(name) > 0) & valid_name THEN
DO
CALL add_dep
END
eoln = TRUE

END /* macro name */

RETURN

/* ----------------------------------------------------------------- */
/* ROUTINE: get_include_name */
/* */
/* FUNCTION: */
/* performs the following on the filename in the EZTP include */
/* variable token and returns result as name. */
/* 1) Will strip filenames of all characters up to and including */
/* the rightmost slash (/). */
/* 2) If not a sequential data set, filenames are stripped, */
/* from the right, of all characters up to and including the */
/* leftmost period (.). */
/* 3) All lowercase letters are converted to uppercase. */
/* 4) All underscores '_' are converted to '@'. . */
/* 5) All filenames are truncated to a maximum of eight */
/* characters. */
/* */
/* VARIABLES USED: */
/* name, token */
/* */
/* VARIABLES CHANGED: */
/* name, valid_name */
/* */
/* ----------------------------------------------------------------- */
get_include_name:

name = ''
valid_name = TRUE

PARSE VALUE line WITH '%' name .

RETURN

/* ----------------------------------------------------------------- */
/* ROUTINE: truncate_name */
/* */
/* FUNCTION: */
/* 1) All filenames are truncated to a maximum of eight */
/* eight characters. */
/* 2) Set the return code to note that truncation occured */
/* 3) Note the pre-truncation name in the error listing */
/* */
/* VARIABLES USED: */
/* token, line, name */
/* */
/* VARIABLES CHANGED: */
/* name, ret_code, error_string1, error_string2 */
/* */
/* ----------------------------------------------------------------- */
truncate_name:

ret_code = CONTINUE_PARSING

/* print the current line to the error listing */
error_string1 = line
/* print the long name at the right spot under the line */
error_string2 = SUBSTR(BLANK,1,(POS(token,line)-1))||name

CALL error_listing

name = STRIP(SUBSTR(name,1,8))

RETURN


/* ----------------------------------------------------------------- */
/* ROUTINE: null_include_message */
/* */
/* FUNCTION: */
/* 1) Write a message to the error file showing an include token */
/* that is not supported by the current parser */
/* 2) Set the return code to note that no dependency was */
/* generated */
/* */
/* VARIABLES USED: */
/* line, startpos, state. */
/* */
/* VARIABLES CHANGED: */
/* ret_code, error_string1, error_string2 */
/* */
/* ----------------------------------------------------------------- */
null_include_message:

ret_code = CONTINUE_PARSING

/* print the current line to the error listing */
error_string1 = line
/* print the long name at the right spot under the line */
error_string2 = ,
SUBSTR(BLANK,1,startpos-1)

CALL error_listing

RETURN


/* ----------------------------------------------------------------- */
/* ROUTINE: unsupported_form_message */
/* */
/* FUNCTION: */
/* 1) Write a message to the error file showing an include token */
/* that is not supported by the current parser */
/* 2) Set the return code to note that no dependency was */
/* generated */
/* */
/* VARIABLES USED: */
/* token, line, name */
/* */
/* VARIABLES CHANGED: */
/* ret_code, error_string1, error_string2 */
/* */
/* ----------------------------------------------------------------- */
unsupported_form_message:

ret_code = CONTINUE_PARSING

/* print the current line to the error listing */
error_string1 = line
/* print the long name at the right spot under the line */
error_string2 = SUBSTR(BLANK,1,(POS(token,line)-1))||name

CALL error_listing

RETURN


/* ------------------------------------------------------------------ */
/* ROUTINE: add_dep */
/* */
/* FUNCTION: */
/* */
/* This routine will add the given name to the dependency */
/* array structure, to be passed back to SCLM. If the array */
/* is already full, an error code is passed back to the caller */
/* and processing halts. The array is first checked to ensure */
/* duplicate names are not added. */
/* */
/* VARIABLES USED: */
/* name, sclm_dep_array_size, sclm_dep_addr, dep_count */
/* */
/* VARIABLES CHANGED: */
/* dep_count, error_string1, error_string2, ret_code */
/* */
/* ------------------------------------------------------------------ */
add_dep:

/* Addresses get leftmost zero's truncated when passed */
/* from SCLM. Add zeros back to address using the OVERLAY */
/* function. Number of zeros to add depends on */
/* size of address passed. Address should always be 8 */
/* bytes, therefore the last parameter in the OVERLAY */
/* function is used to calculate where to begin overlay. */

base = OVERLAY(sclm_dep_addr, OVER, (9 - length(sclm_dep_addr)))

/* Loop through dependencies in array structure until */
/* the name is found or the end of the list. */

temp_offset = 0
element = ''

DO WHILE (element ¬= name) &,
(temp_offset < dep_count)

/* Calculate decimal offset of INCL statement in the */
/* dependency buffer */

srcaddr = base + (temp_offset * DEP_ELEM_SIZE)

/* Skip over the INCL keyword and convert to hex */

srcaddrx = D2X(srcaddr + INCLUDE_KEY_SIZE)

/* Pull the dependency name from the buffer */

element = STORAGE(srcaddrx,MEMBER_LENGTH)
temp_offset = temp_offset + 1

END /* WHILE search through array */

/* If name not already in the structure, write the dependency as */
/* INCL name to the structure. */
/* Compute address for INCL, convert to hex, store INCL */
/* Compute address for member name, convert to hex, store it */
/* Increment storage offset */

IF (element ¬= name) THEN
DO

/* Check for array full; check for one less to ensure there */
/* is room for the ending element (END). */

IF sclm_dep_array_size <=,
((dep_count * DEP_ELEM_SIZE) + DEP_ELEM_SIZE) THEN
DO

/* post the buffer full message */
ret_code = DEP_ARRAY_FULL
/* print the current line to the error listing */
error_string1 = line
/* print the dep name at the right spot under the line */
error_string2 = SUBSTR(BLANK,1,(POS(token,line)-1))||token
CALL error_listing
END /* IF dependency array full */
ELSE
DO
target_addr = base + (dep_count * DEP_ELEM_SIZE)
target_addrx = D2X(target_addr)
x = STORAGE(target_addrx,,INCLUDE_KEYWORD)

target_name_addr = target_addr + INCLUDE_KEY_SIZE
target_name_addrx = D2X(target_name_addr)
x = STORAGE(target_name_addrx,,LEFT(name,MEMBER_LENGTH))

dep_count = dep_count + 1
END /* ELSE room in array */
END /* IF add name to dependency array structure */

RETURN


/* ------------------------------------------------------------------ */
/* ROUTINE: termination */
/* */
/* FUNCTION: */
/* */
/* This routine performs all the clean-up work necessary */
/* for the parser before returning back to SCLM. Errors */
/* are generated if mismatched quotes exist. The error */
/* listing data set (if allocated) and the input source file */
/* are closed. The statistics are placed into the address */
/* expected by SCLM. Finally, the terminating record for */
/* the dependency array (END) is placed in the array. */
/* */
/* VARIABLES USED: */
/* state.error, state.add_dep */
/* stats.total_statements, stats.total_lines, stats.comment_lines */
/* sclm_dep_array_size, sclm_dep_addr, dep_count */
/* */
/* VARIABLES CHANGED: */
/* stats.noncomment_stmts, stats.noncomment_lines, ret_code */
/* */
/* ------------------------------------------------------------------ */

termination:

/* Close the listings file if it was open. */

IF state.error = ON THEN
DO
"EXECIO 0 DISKW "ERROR_DD" (FINIS"
IF RC ¬= 0 THEN
DO
ret_code = ERR_IO_ERROR
END /* bad return from EXECIO */
"FREE FILE ("ERROR_DD")"
IF RC ¬= 0 THEN
DO
ret_code = ERR_IO_ERROR
END /* bad return from FREE */
END /* IF need to close and free error file */

/* Close the source file if it was open. */

IF ret_code ¬= IO_ERROR THEN
DO
"EXECIO 0 DISKR " DDNAME "(FINIS"
IF RC ¬= 0 THEN
DO
ret_code = CLOSE_ERROR
END /* bad return from EXECIO */
END

/* Calculate the remaining stats and return them to SCLM */

stats.noncomment_stmts = stats.total_statements
stats.noncomment_lines = stats.total_lines - stats.comment_lines
CALL return_stats_to_sclm

/* Add dependency from previous (last) line if one exists */

IF state.add_dep = ON THEN
DO
name = state.dependency
CALL add_dep
END /* IF add dependency from last line in file */

/* Check dependency array size. Add the END keyword to the */
/* SCLM dependecy array */

IF sclm_dep_array_size <,
((dep_count * DEP_ELEM_SIZE) + DEP_ELEM_SIZE) THEN
DO
ret_code = DEP_ARRAY_FULL
error_string1 = END_KEYWORD
error_string2 = ''
CALL error_listing
END /* IF name larger than allowed */
ELSE
DO
base = overlay(sclm_dep_addr, OVER, (9 - length(sclm_dep_addr)))

rectype = base + (dep_count * DEP_ELEM_SIZE)
rectypex = d2x(rectype)
s = storage(rectypex,,END_KEYWORD)
END /* ELSE add END to last element of array */

RETURN


/* ------------------------------------------------------------------ */
/* ROUTINE: return_stats_to_sclm */
/* */
/* FUNCTION: */
/* */
/* This routine places the statistics into the structure */
/* SCLM is expecting. It uses the input parameter (STATINFO=) */
/* as the address of the structure. */
/* */
/* VARIABLES USED: */
/* sclm_stats_addr, stats.total_lines, stats.comment_lines, */
/* stats.noncomment_lines, stats.blank_lines, stats.prolog_lines, */
/* stats.total_statements, stats.noncomment_stmts */
/* */
/* VARIABLES CHANGED: */
/* <NONE> */
/* */
/* ------------------------------------------------------------------ */

return_stats_to_sclm:

base = OVERLAY(sclm_stats_addr, OVER, (9 - LENGTH(sclm_stats_addr)))

/* Total Lines */
rectypex = d2x(base) /* Convert decimal address to hex */
h = STORAGE(rectypex,,d2c(stats.total_lines,4))

/* Comment Lines */
statadd = base + 4
rectypex = d2x(statadd)
h = STORAGE(rectypex,,d2c(stats.comment_lines,4))

/* Noncomment Lines */
statadd = base + 8
rectypex = d2x(statadd)
h = STORAGE(rectypex,,d2c(stats.noncomment_lines,4))

/* Blank Lines */
statadd = base + 12
rectypex = d2x(statadd)
h = STORAGE(rectypex,,d2c(stats.blank_lines,4))

/* Prolog Lines */
statadd = base + 16
rectypex = d2x(statadd)
h = STORAGE(rectypex,,d2c(stats.prolog_lines,4))

/* Total Statements */
statadd = base + 20
rectypex = d2x(statadd)
h = STORAGE(rectypex,,d2c(stats.total_statements,4))

/* Comment Statements */
statadd = base + 24
rectypex = d2x(statadd)
h = STORAGE(rectypex,,d2c(stats.comment_stmts,4))

/* Control Statements */
statadd = base + 28
rectypex = d2x(statadd)
h = STORAGE(rectypex,,d2c(stats.control_stmts,4))

/* Assignment Statements */
statadd = base + 32
rectypex = d2x(statadd)
h = STORAGE(rectypex,,d2c(stats.assignment_stmts,4))

/* Noncontrol Statements */
statadd = base + 36
rectypex = d2x(statadd)
h = STORAGE(rectypex,,d2c(stats.noncomment_stmts,4))

RETURN

Jeremy C B Nicoll

unread,
Aug 13, 2001, 7:49:12 AM8/13/01
to
In article <sb73c4...@htismtp.harristeeter.com>,

Peter Vander Woude <pwo...@HARRISTEETER.COM> wrote:
> What I'm looking for is something like what SCLM does for COBOL source.
> That is, parse the source and identify if there are any COPYBOOKs used
> so that SCLM do automatic rebuilds of programs when a copybook is
> changed. Or to do automatic promotes of copybooks when the base source
> is promoted.

I wonder if you could do it by invoking an EZT session with no copybook
source pds, and then trap missing copybook messages, or something like
that? You'd also need to concatenate a deliberate error onto the
beginning or end of the source program so that it couldn't compile
cleanly.

--
Jeremy C B Nicoll - my opinions are my own.

Stephen T. Parfitt

unread,
Aug 13, 2001, 9:37:27 AM8/13/01
to
IBM supplies a the sample COBOL parser. There's at least one version
... the REXX one is fairly easy to modify and test
although it runs rather slowly. Most of the code is concerned with
gathering statistics and these may be somewhat irrelevant to languages
such as EasyTrieve. e.g. is there such a thing as an 'executable'
statement in an interpreted language.

My modified version of IBM's REXX sample program is too long to post.
However, if you e-mail me directly, I would be happy to send you a copy
as an attachment.

Steve Parfitt

hegde...@gmail.com

unread,
Apr 9, 2015, 8:08:30 AM4/9/15
to
Steve, I know this is a very old thread.. In case you see it, please can you let us know, where to find IBM supplied COBOL Parser in REXX on zOS?

-Thanks

Stefan Brech

unread,
Apr 10, 2015, 5:46:40 AM4/10/15
to
The SCLM sample Parsers are in the ISPF sample dataset SYS1.ISPF.SISPSAM
The COBOL Parser member is FLMLRCBL
0 new messages