def __MISSED_FILE(step, i): if i >= len(FILE_CHK): return 0 # termination condition sp1 = spool.retrieve('JESMSGLG') # SPOOL No. 01 sp3 = spool.retrieve('JESYSMSG') # SPOOL No. 03 ctrl = ' ' if FILE_CHK[i] not in spool.list(): # not offered sp1.append(ctrl, strftime('%H.%M.%S '), JCL['jobid'], ' IEC130I {0:<8}'.format(FILE_CHK[i]), ' DD STATEMENT MISSING\n') sp3.append(ctrl, 'IEC130I {0:<8}'.format(FILE_CHK[i]), ' DD STATEMENT MISSING\n') FILE_MISSING.append(FILE_CHK[i]) cnt = __MISSED_FILE(step, i + 1) if FILE_CHK[i] not in spool.list(): if FILE_CHK[i] in FILE_REQ: sp1.append(ctrl, strftime('%H.%M.%S '), JCL['jobid'], ' +{0}\n'.format(FILE_REQ[FILE_CHK[i]])) sp3.append(ctrl, '{0}\n'.format(FILE_REQ[FILE_CHK[i]])) cnt += 1 else: FILE_GEN[FILE_CHK[i]]() return cnt
def finish_job(msg): sp1 = spool.retrieve('JESMSGLG') # SPOOL No. 01 sp3 = spool.retrieve('JESYSMSG') # SPOOL No. 03 if msg in ['ok', 'steprun']: # step was executed JCL['jobstat'] = 'ENDED' JCL['jobend'] = time() diff = JCL['jobend'] - JCL['jobstart'] diff_min = diff / 60 diff_sec = diff % 60 ctrl = ' ' sp1.append(ctrl, strftime('%H.%M.%S '), JCL['jobid'], ' IEF404I {0:<8}'.format(JCL['jobname']), ' - {0}'.format(JCL['jobstat']), strftime(' - TIME=%H.%M.%S\n', localtime(JCL['jobend']))) sp1.append(ctrl, strftime('%H.%M.%S '), JCL['jobid'], ' -{0:<8} ENDED.'.format(JCL['jobname']), ' NAME-{0:<20}'.format(JCL['pgmer']), ' TOTAL TCB CPU TIME= {0:5.2f}'.format(diff_min), ' TOTAL ELAPSED TIME= {0:4.1f}\n'.format(diff_min)) sp1.append(ctrl, strftime('%H.%M.%S '), JCL['jobid'], ' $HASP395 {0:<8} ENDED\n'.format(JCL['jobname'])) sp3.append(ctrl, 'IEF375I JOB/{0:<8}/START '.format(JCL['jobname']), strftime('%Y%j.%H%M', localtime(JCL['jobstart'])), '\n') sp3.append(ctrl, 'IEF376I JOB/{0:<8}/STOP '.format(JCL['jobname']), strftime('%Y%j.%H%M', localtime(JCL['jobend'])), ' CPU {0:>4}MIN {1:05.2f}SEC'.format(int(diff_min), diff_sec), ' SRB {0:>4}MIN {1:05.2f}SEC\n'.format(int(diff_min), diff_sec)) if msg == 'ok': ctrl_new = '1' # the control character to update else: ctrl_new = ' ' for key in SP_DEFAULT: sp = spool.retrieve(key) if sp.empty(): continue # empty spool if key in ['JESMSGLG']: continue # in skip list sp[0, 0] = ctrl_new if key == 'JESYSMSG' and msg != 'ok': sp.pop(0) __JES2_STAT(msg, diff) __WRITE_OUT(SP_DEFAULT_OUT) # write out all registered SPOOLs
def init_job(): sp1 = spool.retrieve('JESMSGLG') # SPOOL No. 01 sp3 = spool.retrieve('JESYSMSG') # SPOOL No. 03 JCL['jobstart'] = time() JCL['jobstat'] = 'STARTED' # ctrl for 1st line will be modified in finish_job() sp3.append('c', '\n') ctrl = ' ' conf = zPE.base.conf.load_ICH70001I() line = 'ICH70001I {0:<8} LAST ACCESS AT {1}\n'.format( JCL['owner'], conf['atime']) sp1.append(ctrl, strftime('%H.%M.%S '), JCL['jobid'], ' ', line) sp3.append(ctrl, line) conf['atime'] = strftime('%H:%M:%S ON %A, %B %d, %Y').upper() zPE.base.conf.dump_ICH70001I(conf) sp1.append( ctrl, strftime('%H.%M.%S '), JCL['jobid'], ' $HASP373 {0:<8} STARTED'.format(JCL['jobname']), ' - INIT {0:<4}'.format(1), # need info ' - CLASS {0}'.format(JCL['class']), ' - SYS {0}\n'.format(SYSTEM['SYS'])) sp1.append(ctrl, strftime('%H.%M.%S '), JCL['jobid'], ' IEF403I {0:<8}'.format(JCL['jobname']), ' - {0}'.format(JCL['jobstat']), strftime(' - TIME=%H.%M.%S\n', localtime(JCL['jobstart']))) sp1.append(ctrl, strftime('%H.%M.%S '), JCL['jobid'], ' - -', '-TIMINGS (MINS.)-- -----PAGING COUNTS----\n') sp1.append( ctrl, strftime('%H.%M.%S '), JCL['jobid'], ' -STEPNAME PROCSTEP RC', ' EXCP CONN TCB SRB CLOCK SERV', # TCB: Task Control Block CPU time # total amount of time spent by the CPU in the execution of # the job step, including the vector facility time, if used # # SRB: System Request Block CPU time # time spent on behalf of the step by the system ' WORKLOAD PAGE SWAP VIO SWAPS\n')
def __WRITE_OUT(dd_list): for fn in dd_list: sp = spool.retrieve(fn) if sp.mode == 'i': continue # input spool if sp.empty(): continue # empty spool core_SPOOL.flush(sp)
def __MISSED_FILE(step): sp1 = spool.retrieve('JESMSGLG') # SPOOL No. 01 sp3 = spool.retrieve('JESYSMSG') # SPOOL No. 03 ctrl = ' ' cnt = 0 for fn in FILE_CHK: if fn not in spool.list(): sp1.append(ctrl, strftime('%H.%M.%S '), JCL['jobid'], ' IEC130I {0:<8}'.format(fn), ' DD STATEMENT MISSING\n') sp3.append(ctrl, 'IEC130I {0:<8}'.format(fn), ' DD STATEMENT MISSING\n') if fn in FILE_REQ: cnt += 1 else: FILE_GEN[fn]() return cnt
def __JES2_STAT(msg, job_time): # vvv JCL not executed vvv if msg in ['label']: ctrl = '0' # ^^^ JCL not executed ^^^ # vvv JCL executed vvv elif msg in ['steplib', 'steprun', 'cond', 'ok']: ctrl = '-' # ^^^ JCL executed ^^^ sp1 = spool.retrieve('JESMSGLG') # SPOOL No. 01 sp1.append('0', '------ JES2 JOB STATISTICS ------\n') if msg not in ['label']: # if JCL executed sp1.append(ctrl, '{0:>13}'.format(strftime(' %d %b %Y').upper()), ' JOB EXECUTION DATE\n') sp1.append(ctrl, '{0:>13}'.format(JCL['read_cnt']), ' CARDS READ\n') cnt = 0 for (k, v) in spool.dict(): if v.mode == 'o': cnt += len(v.spool) cnt += 4 # 4 more lines include this line sp1.append(ctrl, '{0:>13}'.format(cnt), ' SYSOUT PRINT RECORDS\n') cnt = 0 # "punch" is currently not supported sp1.append(ctrl, '{0:>13}'.format(cnt), ' SYSOUT PUNCH RECORDS\n') cnt = 0 for (k, v) in spool.dict(): if v.mode == 'o': for line in v.spool: cnt = cnt + len(line) cnt = (cnt + 72) / 1024 + 1 # 72 more characters include this line sp1.append(ctrl, '{0:>13}'.format(cnt), ' SYSOUT SPOOL KBYTES\n') h_mm = '{0}.{1:0>2}'.format(int(job_time / 3600), int(job_time / 60) % 60) sp1.append(ctrl, '{0:>13}'.format(h_mm), ' MINUTES EXECUTION TIME\n')
def __xin(sp): return spool.retrieve(sp).pop(0)[0] # on EoF, raise exception
def __xout(sp, *words): spool.retrieve(sp).append(*words) return
def __PARSE_OUT_LDR(rc): spi = spool.retrieve('SYSLOUT') # LOADER output SPOOL spo = spool.retrieve('SYSPRINT') # ASSIST output SPOOL ldr_except = e_pop() # get the last exception, is exists ctrl = '0' spo.append( ctrl, '*** PROGRAM EXECUTION BEGINNING - ANY OUTPUT BEFORE EXECUTION TIME MESSAGE IS PRODUCED BY USER PROGRAM ***\n' ) # output for the execution of the module if len(spi): spi[0] = '1' + spi[0][1:] # start an new page on the report for line in spi: spo.append(line) # end of output for the execution of the module diff = TIME['exec_end'] - TIME['exec_start'] if diff: ins_p_sec = int(len(INSTRUCTION) / diff) else: ins_p_sec = 'INF' spo.append(ctrl, '*** EXECUTION TIME = {0:>8.3f} SECS. '.format(diff), '{0:>9} INSTRUCTIONS EXECUTED - '.format(len(INSTRUCTION)), '{0:>8} INSTRUCTIONS/SEC ***\n'.format(ins_p_sec)) if rc >= RC['WARNING']: msg = 'ABNORMAL' # generate err msgs here spo.append('1', 'ASSIST COMPLETION DUMP\n') spo.append(ctrl, 'PSW AT ABEND ', str(SPR['PSW']), ' COMPLETION CODE {0}\n'.format(str(ldr_except)[:76]) ) # only capable of at most 76 characters of exception msg # instructions tracing spo.append( ctrl, '** TRACE OF INSTRUCTIONS JUST BEFORE TERMINATION: PSW BITS SHOWN ARE THOSE BEFORE CORRESPONDING INSTRUCTION DECODED ***\n' ) spo.append( ctrl, ' IM LOCATION INSTRUCTION : IM = PSW BITS 32-39(ILC,CC,MASK) BEFORE INSTRUCTION EXECUTED AT PROGRAM LOCATION SHOWN\n' ) code = [' ' * 4] * 3 for ins in INSTRUCTION[-10:]: # only show last 10 instructions if len(ins[1]) == 12: code[2] = ins[1][8:12] else: code[2] = ' ' * 4 if len(ins[1]) >= 8: code[1] = ins[1][4:8] else: code[1] = ' ' * 4 code[0] = ins[1][0:4] spo.append( ctrl, ' ', b2x(ins[0][32:39]), ' {0:0>6} {1} {2} {3}\n'.format(i2h(ins[0].Instruct_addr), *code)) # append the following words to the end of the last instruction spo[-1, -1] = ' <-- LAST INSTRUCTION DONE - PROBABLE CAUSE OF TERMINATION\n' spo.append(ctrl, '\n') # branch tracing spo.append( '-', '** TRACE OF LAST 10 BRANCH INSTRUCTIONS EXECUTED: PSW BITS SHOWN ARE THOSE BEFORE CORRESPONDING INSTRUCTION DECODED ***\n' ) spo.append( ctrl, ' IM LOCATION INSTRUCTION : IM = PSW BITS 32-39(ILC,CC,MASK) BEFORE INSTRUCTION EXECUTED AT PROGRAM LOCATION SHOWN\n' ) for ins in BRANCHING[-10:]: # only show last 10 branches if len(ins[1]) == 8: code = ' '.join([ins[1][:4], ins[1][4:]]) else: code = ins[1] spo.append( ctrl, ' ', b2x(ins[0][32:39]), ' {0:0>6} {1}\n'.format(i2h(ins[0].Instruct_addr), code)) # register dump spo.append(ctrl, ' REGS 0-7 ', ' '.join([str(r) for r in GPR[:8]]), '\n') spo.append(' ', ' REGS 8-15 ', ' '.join([str(r) for r in GPR[8:]]), '\n') spo.append( ctrl, ' FLTR 0-6 ', # floating-point registers ' '.join(['not..implemented'] * 4), '\n') # storage dump spo.append('1', 'USER STORAGE\n') if len(MEM_DUMP): spo.append(ctrl, MEM_DUMP[0]) for indx in range(1, len(MEM_DUMP)): spo.append(' ', MEM_DUMP[indx]) spo.append(ctrl, '\n') else: msg = 'NORMAL' spo.append(ctrl, '*** AM004 - ', msg, ' USER TERMINATION BY RETURN ***\n')
def init(step): # check for file requirement if __MISSED_FILE(step, 0) != 0: return RC['CRITICAL'] # load in all the pseudo instructions zPE.base.core.asm.pseudo.update(PSEUDO_INS) zPE.base.core.cpu.ins_op.update(PSEUDO_OP) limit = 0 # error tolerance limit; currently hard coded. need info # invoke parser from ASMA90 to assemble the source code core_SPOOL.new('SYSLIN', '+', 'tmp', '', '') # new,pass,delete core_SPOOL.new('SYSUT1', '+', 'tmp', '', '') # new,delete,delete # load the user-supplied PARM and config into the default configuration asm_load_parm({ 'AMODE': 24, 'RMODE': 24, }) asm_load_config({ 'MEM_POS': 0, # always start at 0x000000 for ASSIST 'REGION': step.region, }) TIME['asm_start'] = time() zPE.base.pgm.ASMA90.pass_1() zPE.base.pgm.ASMA90.pass_2() TIME['asm_end'] = time() err_cnt = __PARSE_OUT_ASM(limit) # get instream data, if not specified in DD card spo = spool.retrieve('FT05F001') if 'FT05F001' in FILE_MISSING: spi = spool.retrieve('SYSIN') while not spi.empty(): spo.append('{0:<72}{1:8}\n'.format( spi[0][:-1], '' # keep the deck_id blank )) spi.pop(0) else: for indx in range(len(spo)): spo[indx] = '{0:<80}\n'.format(spo[indx][:-1]) spi = None # unlink spi spo = None # unlink spo # calculate memory needed to execute the module required_mem_sz = 0 for esd in ESD.itervalues(): if esd[0]: sz = esd[0].addr + esd[0].length if sz > required_mem_sz: required_mem_sz = sz asm_init_res() # release resources core_SPOOL.remove('SYSUT1') if err_cnt > limit: if 'FT05F001' in FILE_MISSING: core_SPOOL.remove('FT05F001') core_SPOOL.remove('SYSLIN') return RC['NORMAL'] # skip exec, return with "CC = 0" # invoke HEWLDRGO to link-edit and execute the object module core_SPOOL.new('SYSLOUT', 'o', 'outstream', '', '') # new,delete,delete core_SPOOL.pretend('XREAD', 'FT05F001') # XREAD -> FT05F001 core_SPOOL.pretend('XPRNT', 'SYSLOUT') # XPRNT -> SYSLOUT core_SPOOL.pretend('XSNAPOUT', 'SYSLOUT') # XSNAPOUT -> SYSLOUT # load the user-supplied PARM and config into the default configuration ldr_load_parm({ 'AMODE': 24, 'RMODE': 24, 'PSWKEY': 12, # 12 is the key used by ASSIST on "marist" }) ldr_load_config({ 'MEM_POS': 0, # always start at 0x000000 for ASSIST 'MEM_LEN': required_mem_sz, 'TIME': min( JCL['jobstart'] + JCL['time'] - time(), # job limit step.start + step.time - time() # step limit ), 'REGION': step.region, }) # initialize all register to "F4F4F4F4" for reg in GPR: reg.long = 0xF4F4F4F4 # load OBJMOD into memory, and execute it TIME['exec_start'] = time() rc = zPE.base.pgm.HEWLDRGO.go(zPE.base.pgm.HEWLDRGO.load()) TIME['exec_end'] = time() if 'FT05F001' in FILE_MISSING: core_SPOOL.remove('FT05F001') core_SPOOL.remove('XREAD') # unlink XREAD __PARSE_OUT_LDR(rc) ldr_init_res() # release resources core_SPOOL.remove('SYSLIN') core_SPOOL.remove('SYSLOUT') core_SPOOL.remove('XPRNT') # unlink XPRNT core_SPOOL.remove('XSNAPOUT') # unlink XSNAPOUT return RC['NORMAL']
def load(): '''load all OBJECT MODULEs (statically) into memory''' if LDR_CONFIG['MEM_LEN'] > region_max_sz(LDR_CONFIG['REGION']): abort(9, 'Error: ', LDR_CONFIG['REGION'], ': RIGEON is not big enough.\n') spi = spool.retrieve('SYSLIN') # input SPOOL mem = zPE.base.core.mem.Memory(LDR_CONFIG['MEM_POS'], LDR_CONFIG['MEM_LEN']) LDR_CONFIG['EXIT_PT'] = mem.h_bound rec_tp = { # need to be all lowercase since b2a_hex() returns all lowercase 'ESD' : c2x('ESD').lower(), 'TXT' : c2x('TXT').lower(), 'RLD' : c2x('RLD').lower(), 'END' : c2x('END').lower(), 'SYM' : c2x('SYM').lower(), } rec_order = { # current type : expected type(s) rec_tp['ESD'] : [ rec_tp['ESD'], rec_tp['TXT'], ], rec_tp['TXT'] : [ rec_tp['TXT'], rec_tp['RLD'], rec_tp['END'], ], rec_tp['RLD'] : [ rec_tp['RLD'], rec_tp['END'], ], rec_tp['END'] : [ rec_tp['ESD'], None, ], # None <==> EoF # rec_tp['SYM'] : [ ], } expect_type = [ rec_tp['ESD'] ] # next expected record type obj_id = 1 # 1st OBJECT MODULE mem_loc = mem.min_pos # starting memory location for each OBJMOD (RF) esd_id_next = 1 # next available ESD ID for r in spi.spool: rec = b2a_hex(r) if rec[:2] != '02': # control statement field = resplit_sq(r'\s+', rec, 3) if len(field) < 3 or field[0] != '': abort(13, "Error: ", rec, ":\n invalid OBJECT MODULE control statement.\n") if field[1] == 'ENTRY': LDR_CONFIG['ENTRY_PT'] = '{0:<8}'.format(field[2]) elif field[1] == 'INCLUDE': mark4future('OM INCLUDE statement') elif field[1] == 'NAME': pass # only the linkage-editor need this else: abort(13, "Error: ", rec, ":\n invalid OBJECT MODULE control statement.\n") continue # check record type if rec[2:8] not in expect_type: sys.stderr.write( 'Error: Loader: Invalid OBJECT MODULE record encountered.\n' ) return RC['ERROR'] # OBJECT module format error else: expect_type = rec_order[rec[2:8]] # parse ESD record if rec[2:8] == rec_tp['ESD']: # byte 2-4 byte_cnt = int(rec[20:24], 16) # byte 11-12: byte count esd_id = rec[28:32] # byte 15-16: ESD ID / blank if esd_id == c2x(' '): # 2 spaces # blank => 'LD' esd_id = None # no advancing in ESD ID else: # non-blank, parse it to int esd_id = int(esd_id, 16) esd_id_next = esd_id + 1 for i in [ 32 + j * 32 # vf indx -> start pos for j in range(byte_cnt / 16) # number of vf ]: vf = rec[i : i+32] # each vf is 16 bytes long addr = int(vf[18:24], 16) # vf byte 10-12: address length = vf[26:32] # vf byte 14-16: length / blank if length == c2x(' '): # 3 spaces length = None else: length = int(length, 16) esd = ExternalSymbol( None, esd_id, addr, length, None, LDR_PARM['AMODE'], LDR_PARM['RMODE'], None ) esd.load_type(vf[16:18]) # vf byte 9: ESD type code esd_name = x2c(vf[0:16]) # vf byte 1-8: ESD Name if esd.type in [ 'SD', 'PC', ]: CSECT[obj_id, esd.id] = ( mem_loc, esd, esd_name ) SCOPE[mem_loc, esd.addr, esd.length] = ( obj_id, esd.id ) if esd_name == LDR_CONFIG['ENTRY_PT']: LDR_CONFIG['ENTRY_PT'] = mem_loc elif esd.type == 'ER': EXREF[obj_id, esd.id] = ( 0, esd, esd_name) else: pass # ignore the rest # advance ESD ID by 1 esd_id = esd_id_next esd_id_next = esd_id + 1 # parse TXT record elif rec[2:8] == rec_tp['TXT']: # byte 2-4 addr = int(rec[10:16], 16) # byte 6-8: starting address byte_cnt = int(rec[20:24], 16) # byte 11-12: byte count scope = int(rec[28:32], 16) # byte 15-16: scope id if ( obj_id, scope ) not in CSECT: abort(13, 'Error: ', str(scope), ': Invalid ESD ID in TXT record(s).\n') # calculate the actual location loc = ( CSECT[obj_id, scope][0] + # start of OBJMOD addr # addr into OBJMOD ) mem[loc] = rec[32 : 32 + byte_cnt * 2] # parse RLD record elif rec[2:8] == rec_tp['RLD']: # byte 2-4 byte_cnt = int(rec[20:24], 16) # byte 11-12: byte count remainder = rec[32 : 32 + byte_cnt * 2] df_same = False # not the same ESDID while remainder: if not df_same: # update ESDID if needed rel_id = int(remainder[ : 4], 16) pos_id = int(remainder[4 : 8], 16) remainder = remainder[8:] # parsing flags df_vcon = (remainder[0] == '1') # 1st hex-digit: v-con flag df_flag = int(remainder[1], 16) # 2nd hex-digit: flags df_len = (df_flag >> 2) + 1 # 2.1 - 2.2: length - 1 df_neg = bool(df_flag & 0b10) # 2.3: negative flag df_same = bool(df_flag & 0b01) # 2.4: same ESDID flag # retrieving address df_addr = int(remainder[2:8], 16) remainder = remainder[8:] df_addr += mem_loc # re-mapping the memory address if df_neg: reloc_offset = - mem_loc else: reloc_offset = mem_loc # get the original value of the address constant if df_vcon: found = False for val in CSECT.itervalues(): if ( val[2] == EXREF[obj_id, rel_id][2] and val[1].type == 'SD' ): reloc_value = val[1].addr found = True break if not found: abort(13, 'Error: ', EXREF[obj_id, rel_id][2], ': Storage Definition not found.\n') else: reloc_value = int(mem[df_addr : df_addr + df_len], 16) # relocate the address constant reloc_value += reloc_offset mem[df_addr] = '{0:0>{1}}'.format( i2h(reloc_value)[- df_len * 2 : ], # max len df_len * 2 # min len ) # parse END record elif rec[2:8] == rec_tp['END']: # byte 2-4 # setup ENTRY POINT, if not offered by the user if LDR_CONFIG['ENTRY_PT'] == None: # no ENTRY POINT offered, nor setup by a previous OBJMOD entry = rec[10:16] # byte 6-8: entry point if entry == c2x(' '): # 3 spaces scope = 1 # no ENTRY POINT in END, use 1st CSECT loc = CSECT[obj_id, scope][1].addr else: scope = int(rec[28:32], 16) # byte 15-16: ESD ID for EP loc = int(entry, 16) loc += CSECT[obj_id, scope][0] # add the offset of the OBJMOD LDR_CONFIG['ENTRY_PT'] = loc elif isinstance(LDR_CONFIG['ENTRY_PT'], str): # CSECT name not found sys.stderr.write( 'Error: {0}: Invalid Entry Point specified.\n'.format( LDR_CONFIG['ENTRY_PT'] ) ) return RC['ERROR'] # OBJECT module format error # prepare for next OBJECT MODULE, if any max_offset = 0 for key in CSECT: if key[0] == obj_id: offset = CSECT[key][1].addr + CSECT[key][1].length if max_offset < offset: max_offset = offset # advance to next available loc, align to double-word boundary mem_loc = (mem_loc + max_offset + 7) / 8 * 8 obj_id += 1 # advance OBJECT MODULE counter esd_id_next = 1 # reset next available ESD ID # parse SYM record elif rec[2:8] == rec_tp['SYM']: # byte 2-4 pass # currently not supported # check end state if None not in expect_type: sys.stderr.write( 'Error: Loader: OBJECT MODULE not end with END card.\n' ) return RC['ERROR'] # OBJECT module format error if debug_mode(): print 'Memory after loading Object Deck:' for line in mem.dump_all(): print line[:-1] print return mem
def __PARSE_OUT_ASM(limit): spi = spool.retrieve('SYSUT1') # input SPOOL spo = spool.retrieve('SYSPRINT') # output SPOOL CNT = { 'pln': 1, # printed line counter of the current page 'page': 1, # page counter } ### header portion of the report ctrl = '1' spo.append( ctrl, '*** ASSIST 4.0/A2-05/15/82 470/V7A/0:OS/VS2 INS=SDFP7/X=BGHO, CHECK/TRC/=1180, OPTS=CDKMPR FROM PENN ST*NIU COMPSCI*LT\n' ) CNT['pln'] += SPOOL_CTRL_MAP[ctrl] ctrl = '0' spo.append(ctrl, '\n') CNT['pln'] += SPOOL_CTRL_MAP[ctrl] ### main read loop, op code portion of the report init_line_num = 1 # start at line No. 1 title = '' # default title title_indx = 1 # start at first title, if any # print first header if len(TITLE) > title_indx and TITLE[title_indx][0] == init_line_num: # line No. 1 is TITLE title = TITLE[title_indx][2] title_indx += 1 # advance the index to the next potential TITLE if not INFO_GE(init_line_num, 'I'): init_line_num = 2 # all green with the TITLE line, skip it CNT['pln'] = __PRINT_HEADER(spo, title, CNT['pln'], CNT['page'], ctrl) # define mapping function for error printing def print_err_msg(line_num, err_level): for tmp in INFO[err_level][line_num]: (CNT['pln'], CNT['page']) = __PRINT_LINE( spo, title, [ctrl, gen_msg(err_level, tmp, line)], CNT['pln'], CNT['page']) for line_num in range(init_line_num, len(spi) + 1): # loop through line_num (indx + 1) line = spi[line_num - 1] line_did = spi.deck_id(line_num - 1) ctrl = ' ' if line_num not in MNEMONIC: if INFO_GE(line_num, 'I'): # process error msg (CNT['pln'], CNT['page']) = __PRINT_LINE( spo, title, [ ctrl, '{0:>6} {1:<26} '.format(' ', ' '), '{0:>5} {1:<72}'.format(line_num, line[:-1]), '{0:0>4}{1:0>4}'.format(line_did, '----'), # need info '\n', ], CNT['pln'], CNT['page']) MAP_INFO_GE(line_num, 'I', print_err_msg) continue # comment, EJECT, SPACE, MACRO definition, etc. field = resplit_sq(r'\s+', line[:-1], 3) # check for EJECT and SPACE if line.startswith('*') or len(field) < 2: pass # cannot be EJECT / SPACE, pass elif field[1] == 'EJECT': (CNT['pln'], CNT['page']) = __PRINT_LINE(spo, title, [], CNT['pln'], CNT['page'], new_page=True, print_none=True) continue elif field[1] == 'SPACE': p_line = [] if len(field) > 2: space_n = int(field[2]) else: space_n = 1 line_left = ASM_PARM['LN_P_PAGE'] - CNT['pln'] for i in range(min(space_n, line_left)): (CNT['pln'], CNT['page']) = __PRINT_LINE(spo, title, [' \n'], CNT['pln'], CNT['page']) continue # not EJECT / SPACE if line_did == None: p_line = [ # regular input line ctrl, '{0:>6} {1:<26} '.format(' ', ' '), '{0:>5} {1:<72}'.format(line_num, line[:-1]), '{0:8}'.format(''), # 8 spaces '\n', ] elif isinstance(line_did, int) or line_did.isdigit(): p_line = [ # regular input line ctrl, '{0:>6} {1:<26} '.format(' ', ' '), '{0:>5} {1:<72}'.format(line_num, line[:-1]), '{0:0>4}{1:0>4}'.format(line_did, '----'), # need info '\n', ] else: p_line = [ # expanded line ctrl, '{0:>6} {1:<26} '.format(' ', ' '), '{0:>5}+{1:<72}'.format(line_num, line[:-1]), line_did, # deck ID '\n', ] (CNT['pln'], CNT['page']) = __PRINT_LINE(spo, title, p_line, CNT['pln'], CNT['page']) continue # instructions if len(MNEMONIC[line_num]) == 0: # type 0, TITLE if not INFO_GE(line_num, 'I'): # TITLE require RC = 0 title = TITLE[title_indx][2] # update current TITLE title_indx += 1 # advance the index to the next potential TITLE CNT['page'] += 1 # new page CNT['pln'] = __PRINT_HEADER(spo, title, 0, CNT['page']) # skip the current iteration if no info need to be printed, # since the TITLE will show anyway continue loc = ' ' * 6 # do not print location for this type elif len(MNEMONIC[line_num]) == 1: # type 1 if MNEMONIC[line_num][0] and MNEMONIC_LOC[line_num] != None: # has recorded location, use it loc = i2h(MNEMONIC_LOC[line_num]) elif MNEMONIC[line_num][0]: # has invalid location, indicate it loc = '-' * 6 else: # no scope, no info to print loc = '' elif MNEMONIC[line_num][0] == None: # no scope ==> END (type 2) loc = '' elif len(MNEMONIC[line_num]) == 4: # type 4, EQU loc = i2h(MNEMONIC[line_num][3]) else: # type 2/3/5, inside CSECT or DSECT loc = i2h(MNEMONIC_LOC[line_num]) tmp_str = '' if (len(MNEMONIC[line_num]) == 3 and # type 3 zPE.base.core.asm.can_get_sd( MNEMONIC[line_num][2]) # DC/=const ): for val in zPE.base.core.asm.get_sd(MNEMONIC[line_num][2]): tmp_str += zPE.base.core.asm.X_.tr(val.dump()) if len(tmp_str) > 16: tmp_str = tmp_str[:16] elif len(MNEMONIC[line_num]) == 4: # type 4 tmp_str = '{0:<14} {1:0>5} {0:>5}'.format('', loc) elif len(MNEMONIC[line_num]) == 5: # type 5 # breaking up the op-mnemonic field, if any if MNEMONIC[line_num][2]: code = zPE.base.core.asm.prnt_op(MNEMONIC[line_num][2]) else: code = '' if len(code) == 12: field_3 = code[8:12] else: field_3 = ' ' * 4 if len(code) >= 8: field_2 = code[4:8] else: field_2 = ' ' * 4 if code: field_1 = code[0:4] else: field_1 = ' ' * 4 tmp_str = '{0} {1} {2} '.format(field_1, field_2, field_3) # appending to it the "ADDR1" and "ADDR2" fields, if applied if MNEMONIC[line_num][3] != None: addr_1 = i2h(MNEMONIC[line_num][3]) else: addr_1 = ' ' if MNEMONIC[line_num][4] != None: addr_2 = i2h(MNEMONIC[line_num][4]) else: addr_2 = ' ' tmp_str += '{0:0>5} {1:0>5}'.format(addr_1, addr_2) if line_did == None: p_line = [ # regular input line ctrl, '{0:0>6} {1:<26} '.format(loc, tmp_str), '{0:>5} {1:<72}'.format(line_num, line[:-1]), '{0:8}'.format(''), # 8 spaces '\n', ] elif isinstance(line_did, int) or line_did.isdigit(): p_line = [ # regular input line ctrl, '{0:0>6} {1:<26} '.format(loc, tmp_str), '{0:>5} {1:<72}'.format(line_num, line[:-1]), '{0:0>4}{1:0>4}'.format(line_did, '----'), # need info '\n', ] else: p_line = [ # expanded line ctrl, '{0:0>6} {1:<26} '.format(loc, tmp_str), '{0:>5}+{1:<72}'.format(line_num, line[:-1]), line_did, # deck ID '\n', ] (CNT['pln'], CNT['page']) = __PRINT_LINE(spo, title, p_line, CNT['pln'], CNT['page']) # process error msg, if any MAP_INFO_GE(line_num, 'I', print_err_msg) ### end of main read loop ### summary portion of the report cnt_warn = len(INFO['I']) + len(INFO['N']) + len(INFO['W']) cnt_err = len(INFO['E']) + len(INFO['S']) cnt_all = cnt_warn + cnt_err def format_cnt(cnt): if cnt: return '{0:>5}'.format(cnt) else: return ' NO ' ctrl = '0' spo.append(ctrl, '*** ', format_cnt(cnt_all), ' STATEMENTS FLAGGED - ', format_cnt(cnt_warn), ' WARNINGS, ', format_cnt(cnt_err), ' ERRORS\n') if cnt_err > limit: spo.append(ctrl, '***** NUMBER OF ERRORS EXCEEDS LIMIT OF ', format_cnt(limit), ' ERRORS - PROGRAM EXECUTION DELETED *****\n') spo.append( ctrl, '*** DYNAMIC CORE AREA USED: ', ' LOW: {0:>7} HIGH: {1:>7}'.format('###', '###'), # need info ' LEAVING: {0:>7} FREE BYTES.'.format('#######'), # need info ' AVERAGE: {0:>8} BYTES/STMT ***\n'.format('##')) # (LOW + HIGH) / len(spi) diff = TIME['asm_end'] - TIME['asm_start'] if diff: stmt_p_sec = int(len(spi) / diff) else: stmt_p_sec = 'INF' spo.append(ctrl, '*** ASSEMBLY TIME = {0:>8.3f} SECS, '.format(diff), '{0:>8} STATEMENT/SEC ***\n'.format(stmt_p_sec)) if not debug_mode(): return cnt_err # regular process end here # # debugging information # print '\nMnemonic:' for key in sorted(MNEMONIC.iterkeys()): if len(MNEMONIC[key]) == 0: # type 0 scope = ' ' * 8 else: try: scope = f2x(MNEMONIC[key][0]) except: scope = ' ' * 8 if len(MNEMONIC[key]) == 0: # type 0 loc = '' elif len(MNEMONIC[key]) == 1: # type 1 loc = '' elif len(MNEMONIC[key]) == 4: # type 4 loc = i2h(MNEMONIC[key][3]) else: loc = i2h(MNEMONIC[key][1]) tmp_str = '' if (len(MNEMONIC[key]) == 3 and # type 3 zPE.base.core.asm.can_get_sd(MNEMONIC[key][2]) # DC/=const ): for val in zPE.base.core.asm.get_sd(MNEMONIC[key][2]): tmp_str += zPE.base.core.asm.X_.tr(val.dump()) elif len(MNEMONIC[key]) == 4: # type 4 tmp_str += '{0:<14} {1:0>5} {0:>5}'.format('', loc) elif len(MNEMONIC[key]) == 5: # type 5 if MNEMONIC[key][2]: code = zPE.base.core.asm.prnt_op(MNEMONIC[key][2]) else: code = '' if len(code) == 12: field_3 = code[8:12] else: field_3 = ' ' * 4 if len(code) >= 8: field_2 = code[4:8] else: field_2 = ' ' * 4 if code: field_1 = code[0:4] else: field_1 = ' ' * 4 tmp_str = '{0} {1} {2} '.format(field_1, field_2, field_3) if MNEMONIC[key][3] != None: addr_1 = i2h(MNEMONIC[key][3]) else: addr_1 = ' ' if MNEMONIC[key][4] != None: addr_2 = i2h(MNEMONIC[key][4]) else: addr_2 = ' ' tmp_str += '{0:0>5} {1:0>5}'.format(addr_1, addr_2) print '{0:>5}: {1} {2:0>6} {3}'.format(key, scope, loc, tmp_str) print '\nMnemonic Location Remapping:' for line_num in MNEMONIC_LOC: if (len(MNEMONIC[line_num]) < 2 or MNEMONIC[line_num][1] != MNEMONIC_LOC[line_num]): if len(MNEMONIC[line_num]) < 2: org_loc = '' elif MNEMONIC[line_num][1] == None: org_loc = '[None]' else: org_loc = MNEMONIC[line_num][1] print 'line {0:>4}: {1:0>6} => {2:0>6}'.format( line_num, org_loc, i2h(MNEMONIC_LOC[line_num])) from binascii import b2a_hex print '\n\nObject Deck:' for line in spool.retrieve('SYSLIN'): line = b2a_hex(line).upper() print ' '.join(fixed_width_split(8, line[0:32])), ' ', print ' '.join(fixed_width_split(8, line[32:64])), ' ', print ' '.join(fixed_width_split(8, line[64:96])) print '{0:38}'.format(''), print ' '.join(fixed_width_split(8, line[96:128])), ' ', print ' '.join(fixed_width_split(8, line[128:160])) print print # end of debugging return cnt_err
def __RM_FILE(dd_list): for fn in dd_list: sp = spool.retrieve(fn) core_SPOOL.rm_file(sp.real_path, sp.f_type)
def parse(job): invalid_lable = [] # record all invalid lables if job == '-': fp = sys.stdin else: fp = open(job, 'r') # this is not under the control of SMS sp1 = spool.retrieve('JESMSGLG') # SPOOL No. 01 sp2 = spool.retrieve('JESJCL') # SPOOL No. 02 ctrl = '1' # control character sp1.append(ctrl, '{0:>27} J O B L O G -'.format(SYSTEM['JEST']), '- S Y S T E M {0} -'.format(SYSTEM['SYST']), '- N O D E {0}\n'.format(SYSTEM['NODET'])) sp1.append('0', '\n') ctrl = ' ' # initial read (for JOB card) line = fp.readline() JCL['read_cnt'] += 1 JCL['card_cnt'] += 1 if debug_mode(): print line, if not line.startswith('//'): # invalid JCL JOB card abort(9, 'Error: ', line[:-1], ':\n Not a valid JCL JOB card.\n') if len(line) > 73: # 72+ char + '\n' abort(9, 'Error: line ', str(JCL['read_cnt']), ': Statement cannot exceed colomn 72.\n') # field_0 field_1 field_2 # -------- ------- ------------------------------------ # //label JOB <args> # // EXEC <args> # //maxlabel DD <args> field = re.split('\s+', line[2:], 2) # check lable if bad_label(field[0]): invalid_lable.append(JCL['read_cnt']) # parse JOB card # currently supported parameter: region if field[1] != 'JOB': abort(9, 'Error: No JOB card found.\n') JCL['jobname'] = field[0] if len(JCL['jobname']) != 8: abort(9, 'Error: JOB name is not 8 charactors long.\n') JCL['owner'] = JCL['jobname'][:7] JCL['class'] = JCL['jobname'][-1] JCL['jobid'] = 'JOB{0:0>5}'.format(Config['job_id']) JCL['spool_path'] = '{0}.{1}.{2}'.format(JCL['owner'], JCL['jobname'], JCL['jobid']) # args_0,args_1,args_2 # AccInfo,'pgmer'[,parameters] args = resplit_sq(',', field[2], 2) if len(args) < 2: abort(9, 'Error: Invalid JOB card: missing parameter(s).\n') # parse AccInfo JCL['accinfo'] = args[0] if args[1][0] != '\'' or args[1][-1] != '\'': abort(9, 'Error: ', args[1], ':\n The programmer\'s name need to be ', 'surrounded by single quotes.\n') # parse pgmer JCL['pgmer'] = args[1][1:-1] if len(JCL['pgmer']) > 20: abort(9, 'Error: ', args[1], ':\n The programmer\'s name cannot be exceed ', '20 characters.\n') # parse parameters JCL['time'] = Config['time_limit'] JCL['region'] = Config['memory_sz'] if len(args) == 3: for part in resplit_pp(',', args[2]): if part[:5] == 'TIME=': try: JCL['time'] = parse_time(part[5:]) except SyntaxError: abort(9, 'Error: ', part, ': Invalid time specification.\n') elif part[:7] == 'REGION=': try: JCL['region'] = parse_region(part[7:]) except SyntaxError: abort(9, 'Error: ', part, ': Invalid region size.\n') except ValueError: abort(9, 'Error: ', part, ': Region must be divisible by 4K.\n') # elif part[:9] == 'MSGCLASS=': sp1.append(ctrl, strftime('%H.%M.%S '), JCL['jobid'], '{0:<16}'.format(strftime(' ---- %A,').upper()), strftime(' %d %b %Y ----').upper(), '\n') sp1.append(ctrl, strftime('%H.%M.%S '), JCL['jobid'], ' IRR010I USERID {0:<8}'.format(JCL['owner']), ' IS ASSIGNED TO THIS JOB.\n') # ctrl for 1st line will be modified in finish_job() sp2.append( 'c', '{0:>9}'.format(1), # should always be the first JCL card ' {0:<72}{1}\n'.format(line[:-1], JCL['jobid'])) ctrl = ' ' # main read loop nextline = None # for `__READ_UNTIL()` look-ahead buffer last_dd = None # for DD concatenation card_lbl = None # the label the JCL card jcl_continue = None # the action the JCL card continues while True: if nextline == None: # no left over line in the look-ahead buffer line = fp.readline() else: # line exist in the look-ahead buffer line = nextline nextline = None # check JCL card length if not line: break if len(line) > 73: # 72+ char + '\n' abort(9, 'Error: line ', str(JCL['read_cnt']), ': Statement cannot exceed colomn 72.\n') JCL['read_cnt'] += 1 # check implicit instream data if not line.startswith('//'): nextline = line # store the line in the look-ahead buffer line = '//SYSIN DD * GENERATED STATEMENT\n' # check end of JCL marker elif len(line) == 2 or line[2:].isspace(): JCL['read_cnt'] -= 1 # END mark does not count break # check comment elif line.startswith('//*') or jcl_continue == '*': if debug_mode(): print line, sp2.append(ctrl, '{0:>9} {1}'.format('', line)) if len(line) == 73 and line[71] != ' ': # 72+ char + '\n' col 72 is non-space jcl_continue = '*' else: jcl_continue = None continue # starting from here, line will be guaranteed to start with "//" # increment line counter only for non-comment lines if not jcl_continue: JCL['card_cnt'] += 1 if debug_mode(): print line, field = re.split('\s+', line[2:]) # check lable if jcl_continue and field[0]: # JCL concatenation cannot start at col 3 abort(9, 'Error: line ', str(JCL['read_cnt']), ': Cannot have labels on continuation lines.\n') elif bad_label(field[0]): invalid_lable.append(JCL['read_cnt']) if jcl_continue: if line.index(field[1]) > 15: abort(9, 'Error: line ', str(JCL['read_cnt']), ': JCL continuation must start before col 16.\n') else: card_lbl = field[0] # parse EXEC card # currently supported parameter: parm, time, region # currently assumed parameter: cond=(0,NE) # see also: __COND_FAIL(step) if field[1] == 'EXEC' or jcl_continue == 'EXEC': if jcl_continue not in [None, 'EXEC']: abort(9, 'Error: line ', str(JCL['read_cnt']), ': Invalid JCL continuation.\n') last_dd = None if not jcl_continue: args = re.split(',', field[2], 1) pgm = '' proc = '' if args[0][:4] == 'PGM=': pgm = args[0][4:] elif args[0][:5] == 'PROC=': proc = args[0][5:] else: proc = args[0] parm = '' # parameter list time = JCL['time'] region = JCL['region'] else: args = ['continuation', field[1]] jcl_continue = None if len(args) == 2: for part in resplit_pp(',', args[1]): if jcl_continue: # jcl_continue can only be set by last part abort(9, 'Error: line ', str(JCL['read_cnt']), ': Invalid JCL card\n') elif part[:5] == 'PARM=': parm = part[5:] elif part[:5] == 'TIME=': try: time = parse_time(part[5:]) except SyntaxError: abort(9, 'Error: ', part, ': Invalid time specification.\n') elif part[:7] == 'REGION=': try: region = parse_region(part[7:]) except SyntaxError: abort(9, 'Error: ', part, ': Invalid region size.\n') except ValueError: abort(9, 'Error: ', part, ': Region must be divisible ', 'by 4K.\n') elif part[:5] == 'COND=': pass # assume COND=(0,NE) elif part == '': jcl_continue = 'EXEC' else: abort(9, 'Error: ', part, ': Parameter not supported.\n') if not jcl_continue: JCL['step'].append( JobStep(name=card_lbl, pgm=pgm, proc=proc, time=time, region=region, parm=parm)) # parse DD card # currently supported parameter: dsn, disp, sysout, */data elif field[1] == 'DD' or jcl_continue == 'DD': if jcl_continue not in [None, 'DD']: abort(9, 'Error: line ', str(JCL['read_cnt']), ': Invalid JCL continuation.\n') if not jcl_continue: sysout = '' dsn = [] disp = '' sp_in = None # will hold the tmp SPOOL if instream if not card_lbl: # concatenated DD card pass else: # new DD card last_dd = card_lbl # record the dd name args = field[2] else: args = field[1] jcl_continue = None if args == '*' or args == 'DATA': (nextline, sp_in) = __READ_UNTIL(fp, last_dd, '/*', nextline) elif args[:9] == 'DATA,DLM=\'': (nextline, sp_in) = __READ_UNTIL(fp, last_dd, args[9:11]) elif args[:7] == 'SYSOUT=': sysout = args[7:] else: for part in resplit_pp(',', args): if jcl_continue: # jcl_continue can only be set by last part abort(9, 'Error: line ', str(JCL['read_cnt']), ': Invalid JCL card\n') elif part[:4] == 'DSN=': dsn = conv_path(part[4:]) elif part[:5] == 'DISP=': disp = part[5:] elif part == '': jcl_continue = 'DD' else: abort(9, 'Error: ', part, ': Parameter not supported.\n') if not jcl_continue and disp == '': abort(9, 'Error: ', line[:-1], ': Need DISP=[disp].\n') if not jcl_continue: JCL['step'][-1].dd.append( card_lbl, { # do not use last_dd, since it will be flaged # as duplicated DD names 'SYSOUT' : sysout, 'DSN' : dsn, 'DISP' : disp, }, sp_in ) # ignore other types of cards else: mark4future(field[1]) sp2.append(ctrl, '{0:>9} {1}'.format(JCL['card_cnt'], line)) # end of the main read loop sp3 = spool.retrieve('JESYSMSG') # SPOOL No. 03 if len(invalid_lable) != 0: # ctrl for 1st line will be modified in finish_job() sp3.append('c', ' STMT NO. MESSAGE\n') ctrl = ' ' for indx in invalid_lable: sp3.append(ctrl, '{0:>9} IEFC662I INVALID LABEL\n'.format(indx)) sp3.append(ctrl, '\n') return 'label' return 'ok'
def __PARSE_OUT(rc): spo = spool.retrieve('SYSLOUT') # output SPOOL
def init_step(step): sp1 = spool.retrieve('JESMSGLG') # SPOOL No. 01 sp3 = spool.retrieve('JESYSMSG') # SPOOL No. 03 step.start = time() ctrl = ' ' # check condition if __COND_FAIL(step): sp3.append(ctrl, 'IEF202I {0:<8} '.format(JCL['jobname']), step.name, ' - STEP WAS NOT RUN BECAUSE OF CONDITION CODES\n') return 'cond' sp3.append( ctrl, 'IEF236I ALLOC. FOR {0:<8} {1}\n'.format(JCL['jobname'], step.name)) alloc = False # whether allocated any file if 'STEPLIB' in step.dd.dict(): for ddcard in step.dd['STEPLIB']: if not is_pds(ddcard['DSN']): # STEPLIB cannot be instream, thus DSN= should always exist sp3.pop() # no file allocated sp3.append(ctrl, 'IEF212I {0:<8} '.format(JCL['jobname']), step.name, ' STEPLIB - DATA SET NOT FOUND\n') ddcard['STAT'] = DD_STATUS['abnormal'] JCL['jobstat'] = 'JOB FAILED - JCL ERROR' return 'steplib' sp3.append(ctrl, sysmsg.IGD103('STEPLIB'), '\n') ddcard['STAT'] = DD_STATUS['normal'] alloc = True ddindx_map = {} # { ddname : index_into_dd_concatenation, } for ddname in step.dd.list(): if ddname not in ddindx_map: ddindx_map[ddname] = 0 else: ddindx_map[ddname] += 1 ddindx = ddindx_map[ddname] if step.dd[ddname][ddindx]['STAT'] != DD_STATUS['init']: continue # skip the allocated ones # check for the f_type if step.dd[ddname][ddindx]['TMP_SP']: # instream data f_type = 'instream' sp_in = step.dd[ddname][ddindx]['TMP_SP'] if ddindx: # DD concatenation sp_real = spool.retrieve(ddname) while not sp_in.empty(): sp_real.push(sp_in.pop(0)) else: # new DD core_SPOOL.replace(ddname, sp_in) step.dd[ddname][ddindx]['TMP_SP'] = { 'mode': sp_in.mode, 'f_type': sp_in.f_type, 'virtual_path': sp_in.virtual_path, 'real_path': sp_in.real_path, } else: v_path = [] # virtual path r_path = [] # real path if step.dd[ddname][ddindx]['SYSOUT'] != '': # outstream mode = 'o' f_type = 'outstream' r_path = [ddname] else: if step.dd[ddname][ddindx]['DSN'] != '': # file f_type = 'file' v_path = step.dd[ddname][ddindx]['DSN'] r_path = step.dd[ddname][ddindx]['DSN'] else: # tmp f_type = 'tmp' r_path = [ddname] mode = step.dd.mode(ddname) if ddindx: # DD concatenation core_SPOOL.load(ddname, mode, f_type, r_path) else: # new DD core_SPOOL.new(ddname, mode, f_type, v_path, r_path) step.dd[ddname][ddindx]['TMP_SP'] = { 'mode': mode, 'f_type': f_type, 'virtual_path': v_path, 'real_path': r_path, } if ddindx: # DD concatenation action = 'CONCAT ' else: # new DD action = 'ALLOCATED' if f_type in ['file', 'tmp']: sp3.append(ctrl, sysmsg.IGD103(ddname, f_type, action), '\n') else: sp3.append(ctrl, sysmsg.IEF237(ddname, f_type, action), '\n') step.dd[ddname][ddindx]['STAT'] = DD_STATUS['normal'] alloc = True if not alloc: sp3.pop() # no file allocated return 'ok'
def finish_step(step): sp1 = spool.retrieve('JESMSGLG') # SPOOL No. 01 sp3 = spool.retrieve('JESYSMSG') # SPOOL No. 03 step.end = time() diff = step.end - step.start diff_min = diff / 60 diff_sec = diff % 60 ctrl = ' ' sp1.append( ctrl, strftime('%H.%M.%S '), JCL['jobid'], ' -{0:<8} {1:<8}'.format(step.name, step.procname), ' {0:>5} {1:>5} {2:>5}'.format(step.rc, 0, 0), # need info ' {0:>5.2f} {1:>5.2f}'.format(diff_min, diff_min), ' {0:>5.1f} {1:>5}'.format(diff_min, 0), # need info ' {0:<8}'.format('BATCH'), # need info ' {0:>4} {1:>4}'.format(0, 0), # need info ' {0:>4} {1:>4}\n'.format(0, 0)) # need info if step.rc == 'FLUSH': sp3.append(ctrl, 'IEF272I {0:<8} '.format(JCL['jobname']), step.name, ' - STEP WAS NOT EXECUTED.\n') else: sp3.append(ctrl, 'IEF142I {0:<8}'.format(JCL['jobname']), ' {0} - STEP WAS EXECUTED -'.format(step.name), ' COND CODE {0:0>4}\n'.format(step.rc)) if 'STEPLIB' in step.dd.dict(): for ddcard in step.dd['STEPLIB']: path = ddcard['DSN'] action = DISP_ACTION[step.dd.get_act('STEPLIB', step.rc)] sp3.append(ctrl, sysmsg.IGD104('STEPLIB', conv_back(path), action), '\n') ddindx_map = {} # { ddname : index_into_dd_concatenation, } for ddname in step.dd.list(): if ddname in SP_DEFAULT: # skip default spools continue if ddname == 'STEPLIB': # already processed continue if ddname not in ddindx_map: ddindx_map[ddname] = 0 else: ddindx_map[ddname] += 1 ddindx = ddindx_map[ddname] if step.dd[ddname][ddindx]['STAT'] != DD_STATUS['normal']: sys.error.write(''.join([ 'Warning: ', ddname, ': File status is not', 'normal. (', step.dd[ddname][ddindx]['STAT'], ')\n', ' Ignored.\n' ])) continue if step.dd.is_concat(ddname): if not ddindx: # first DD concatenated path = spool.path_of(ddname) else: path = step.dd[ddname][ddindx]['TMP_SP']['virtual_path'] action = SP_MODE['i'] # must be input data else: path = spool.path_of(ddname) action = SP_MODE[spool.mode_of(ddname)] if step.dd[ddname][ddindx]['TMP_SP']['f_type'] in ['file', 'tmp']: action = DISP_ACTION[step.dd.get_act('STEPLIB', step.rc)] sp3.append(ctrl, sysmsg.IGD104(ddname, conv_back(path), action), '\n') else: sp3.append(ctrl, sysmsg.IEF285(ddname, conv_back(path), action), '\n') if (step.dd.is_concat(ddname) and # concatenated DDs ddname not in spool.list() # already removed ): continue f_type = spool.type_of(ddname) if f_type == 'outstream': # register outstream for writting out core_SPOOL.register_write(ddname, step.name) else: if f_type == 'instream': # remove instream if not PASS pass elif f_type == 'tmp': # remove tmp if not PASS pass else: # sync file if needed if step.dd.get_act(ddname) in ['KEEP', 'PASS', 'CATLG']: __WRITE_OUT([ddname]) elif step.dd.get_act(ddname) == 'DELETE': __RM_FILE([ddname]) if step.dd.get_act(ddname) != 'PASS': core_SPOOL.remove(ddname) # remove SPOOLs of the step sp3.append(' ', 'IEF373I STEP/{0:<8}/START '.format(step.name), strftime('%Y%j.%H%M\n', localtime(step.start))) sp3.append( ' ', 'IEF374I STEP/{0:<8}/STOP '.format(step.name), strftime('%Y%j.%H%M'), ' CPU {0:>4}MIN {1:05.2f}SEC'.format(int(diff_min), diff_sec), ' SRB {0:>4}MIN {1:05.2f}SEC'.format(int(diff_min), diff_sec), ' VIRT {0:>5}K SYS {1:>5}K'.format('#', '#'), # need info ' EXT {0:>7}K SYS {1:>7}K\n'.format(0, '#')) # need info