Gregory | Дата: Чт, 01.08.2019, 23:35 | Сообщение # 1 |
 Генерал-майор
Группа: Доверенные
Сообщений: 479
Статус: Offline
| Коллеги задали мне следующий вопрос: "как разбить загрузочный модуль на образующие его части?". Думаю, не нужно объяснять, для чего это нужно. Я посмотрел на существующие решения - delink0 и delinki из CBTTAPE (файлы 090,134,135), все они имеют недостатки, и я подумал, а нельзя ли решить эту задачу стандартными средствами? И действительно, эта задача может быть решена только стандартными средствами без написания программ.
- program management binder (ex linkage editor) позволяет удалить программные секции (REPLACE). Если загрузочный модуль ABC состоит из секций A, B и С, то следующие упраляющие операторы разберут его на NCAL: Код REPLACE B REPLACE C INCLUDE LOADLIB(ABC) NAME A(R) REPLACE A REPLACE C INCLUDE LOADLIB(ABC) NAME B(R) REPLACE A REPLACE B INCLUDE LOADLIB(ABC) NAME C(R)
это решение применимо как к загрузочным модулям, так и к программным объектам, в отличие от нештатных программ DELINK0 и DELINKI, которыея не обрабатывает программные объекты.
- Чтобы автоматизировать процесс, необходимо получить список программных секций загрузочного модуля (программного объекта), использовав для этого все тот же program management binder (можно использовать также AMBLIST, но вывод AMBLIST труднее разбирать, так как этот вывод различается для program object и load module, что, по-моему, идиотизм).
- Получив список секций, необходимо сгенерировать последовательность управляющих операторов program management binder, приведенную выше. Это можно сделать, написав несложную процедуру, но такое решение недостойно настоящих джедаев) Нужную последовательность управляющих операторов можно построить сортировкой.
Код //IBMUSERS JOB MSGCLASS=H // EXPORT SYMLIST=(LOADLIB,NCALLIB,MEMBER) // SET MEMBER=QDS // SET LOADLIB=CPAC.LINKLIB // SET NCALLIB=IBMUSER.NCALLIB //RELINK EXEC PGM=IEWL,PARM='MAP' //SYSPRINT DD DISP=(NEW,PASS),DSN=&&MAP, // SPACE=(TRK,(10,10)),UNIT=SYSDA //LOADLIB DD DISP=SHR,DSN=&LOADLIB //SYSLMOD DD DISP=(NEW,DELETE),DSN=&&LOAD, // SPACE=(TRK,(10,10,5)),UNIT=SYSDA //SYSLIN DD *,SYMBOLS=EXECSYS INCLUDE LOADLIB(&MEMBER) NAME &MEMBER(R) //CSECTS EXEC PGM=SORT //SYSOUT DD SYSOUT=* //SYSIN DD * OPTION COPY INCLUDE COND=(40,6,CH,EQ,C'CSECT ') OUTFIL FILES=OUT, OUTREC=(C'=',SEQNUM,8,ZD,START=1,INCR=1,C'REPLACE ',21,8,55C' ') //SORTIN DD DISP=(OLD,DELETE),DSN=&&MAP //SORTOUT DD DISP=(,PASS),DSN=&&CSECTS,SPACE=(TRK,(5,5)),UNIT=SYSDA, // DCB=(RECFM=FB,LRECL=80,BLKSIZE=0) //SYSLIN EXEC PGM=SORT //SORTOUT DD DISP=(NEW,PASS),DSN=&&SYSLIN, // SPACE=(TRK,(10,10)),UNIT=SYSDA, // DCB=(RECFM=FB,LRECL=80,BLKSIZE=0) //SORTJNF DD DISP=(OLD,PASS),DSN=&&CSECTS //SORTJNF1 DD DISP=(OLD,PASS),DSN=*.SORTJNF, // UNIT=AFF=SORTJNF,VOL=REF=*.SORTJNF // DD *,SYMBOLS=EXECSYS =99999998INCLUDE LOADLIB(&MEMBER) =99999999NAME //SORTJNF2 DD DISP=(OLD,PASS),DSN=*.SORTJNF, // UNIT=AFF=SORTJNF,VOL=REF=*.SORTJNF //SYSOUT DD SYSOUT=* //SYSIN DD * JOINKEYS FILES=F1,FIELDS=(1,1,A) JOINKEYS FILES=F2,FIELDS=(1,1,A) JOIN UNPAIRED,F1 REFORMAT FIELDS=(F1:1,40,F2:1,40) SORT FIELDS=(42,8,CH,A,2,8,CH,A) OMIT COND=(18,8,CH,EQ,58,8,CH) OUTREC IFTHEN=(WHEN=(10,4,CH,EQ,C'NAME'), BUILD=(C' ',10,8,58,8,62C' ')), IFTHEN=(WHEN=NONE,BUILD=(C' ',10,28,50C' ')) //DELINK EXEC PGM=IEWL,PARM='NCAL' //SYSPRINT DD SYSOUT=* //LOADLIB DD DISP=SHR,DSN=&LOADLIB //SYSLMOD DD DISP=SHR,DSN=&NCALLIB //SYSLIN DD DISP=(OLD,DELETE),DSN=&&SYSLIN //
на написание этого задания я протратил около 3 часов, выполнив при этом 42 запуска. Возможно, пригодится еще кому-нибудь...
Примечание: в задании используются возможности JCL, доступные в z/OS 2.1 и выше.
Сообщение отредактировал Gregory - Пт, 02.08.2019, 23:57 |
|
| |