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
Example #2
0
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
Example #3
0
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')
Example #4
0
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
Example #6
0
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')
Example #7
0
def __xin(sp):
    return spool.retrieve(sp).pop(0)[0]  # on EoF, raise exception
Example #8
0
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
Example #13
0
def __RM_FILE(dd_list):
    for fn in dd_list:
        sp = spool.retrieve(fn)
        core_SPOOL.rm_file(sp.real_path, sp.f_type)
Example #14
0
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
Example #16
0
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'
Example #17
0
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