/* * Copyright (C) 1985, 1991 by the University of Waterloo, * Computer Systems Group. All rights reserved. No part * of this software may be reproduced in any form or by * any means - graphic, electronic or mechanical, * including photocopying, recording, taping or * information storage and retrieval systems - except * with the written permission of the copyright owner. */ /* * disasm -- given a 370 object file, generate assembler code that can * be assembled to give an equivalent object file * * Notes: * 1. This file contains lines such as * #ifdef TARGCMS * #endif * around blocks of code that are CMS dependent. They can be * enabled by compiling with a command such as * CW DISASM ( PRM TARGCMS X * TARGCMS is thus defined as a preprocessor constant. * By default, MVS-dependent code is generated. * * 2. For this version, DISASM does not support COM, DXD, Q-cons * and multiple CSECTs very well. LISTTXT contains some code to * process these, that needs to be incorporated into DISASM. */ #include #include #include #include #include #include #include #include typedef unsigned short int usint; typedef unsigned int uint; typedef union obj_record { esd_record obj_esd; txt_record obj_txt; rld_record obj_rld; sym_record obj_sym; end_record obj_end; } obj_record; typedef struct esd_recdes { char esdrd_name[ 9 ]; char esdrd_type; int esdrd_addr; char esdrd_align; int esdrd_length; usint esdrd_esdid; struct esd_recdes *esdrd_next; } esd_recdes; typedef struct txt_recdes { int txtrd_addr; short int txtrd_length; usint txtrd_esdid; char txtrd_buffer[ 56 ]; struct txt_recdes *txtrd_next; } txt_recdes; typedef struct rld_recdes { usint rldrd_resdid; usint rldrd_pesdid; char rldrd_flag; int rldrd_addr; struct rld_recdes *rldrd_next; } rld_recdes; typedef struct end_recdes { int endrd_entpt; usint endrd_esdid; } end_recdes; typedef struct csect_des { struct csect_des *csd_next; esd_recdes *csd_esdlst; txt_recdes *csd_txtlst; rld_recdes *csd_rldlst; end_recdes csd_end; char csd_csname[ 9 ]; } csect_des; /* specific opttbl indices (origin 1)... */ #define OPT_NOREGEQU 1 #define OPT_REGEQU 2 #define OPT_NONE 3 #define OPT_YES 23 /* start of 'yes' options */ const static char opttbl[] = { /* tblookup retval */ "NORegequ\0" /* 1 */ "Regequ\0" /* 2 */ "NONe\0" /* 3 */ "NOEsa\0" /* 4 */ "NOPriv\0" /* 5 */ "NOXa\0" /* 6 */ "NOBas\0" /* 7 */ "NOCSS\0" /* 8 */ "NOCs\0" /* 9 */ "NOTcc\0" /* 10 */ "NODC\0" /* 11 */ "NODas\0" /* 12 */ "NOEF\0" /* 13 */ "NOEPf\0" /* 14 */ "NOMi\0" /* 15 */ "NOMP\0" /* 16 */ "NOPKh\0" /* 17 */ "NOSki\0" /* 18 */ "NOSR\0" /* 19 */ "NOTB\0" /* 20 */ "NOTR\0" /* 21 */ "NOVector\0" /* 22 */ "Esa\0" "Priv\0" "Xa\0" "Bas\0" "CSS\0" "Cs\0" "Tcc\0" "DC\0" "Das\0" "EF\0" "EPf\0" "Mi\0" "MP\0" "PKh\0" "Ski\0" "SR\0" "TB\0" "TR\0" "Vector\0" }; const int _parms = UNTOKENIZED; const char _clbwarn = 0; extern unsigned short int *dasm370( const unsigned short int *src, char *dst, int dasmopt ); static int open_obj_file( const char *cmdln ); static void esd_proc( const esd_record *esdrecptr ); static void txt_proc( const txt_record *txtrecptr ); static void rld_proc( const rld_record *rldrecptr ); static void end_proc( const end_record *endrecptr ); static void d_assemble( void ); static void print_end( void ); static void disassemble( int last_addr ); static char *nextlabel( char *buf_ptr, char *new_ptr, int cur_addr ); static void print_addr_label( uint address ); static void print_rlds_and_esds( uint curaddr, uint endaddr, int orgback ); static void print_label( esd_recdes *esdrdptr ); static int print_rld( int addr, char *buf_ptr ); static void getname( char *name, usint esdid ); static char *str_chr( char *str, int chr ); static void *dmalloc( size_t size ); static void dprintf( const char *ctl, ... ); csect_des *csect_list; esd_recdes *esd_ptr; rld_recdes *rld_ptr; char *txtbuffer, *end_ptr; int cs_address, txtbufsize; unsigned int dasmopt; int main( int argc, char **argv ) { int objfd; obj_record *objptr; char *obj_label; csect_list = dmalloc( sizeof( csect_des ) ); memzero( csect_list, sizeof( csect_des ) ); txtbufsize = 0; objfd = open_obj_file( *argv ); objptr = dmalloc( sizeof( obj_record ) ); while( read( objfd, (char *) objptr, sizeof( obj_record ) ) > 0 ) { if( objptr->obj_esd.esd_punch != PUNCH_12_2_9 ) continue; obj_label = objptr->obj_esd.esd_label; if( memcmp( obj_label, "ESD", 3 ) == 0 ) esd_proc( &objptr->obj_esd ); else if( memcmp( obj_label, "TXT", 3 ) == 0 ) txt_proc( &objptr->obj_txt ); else if( memcmp( obj_label, "RLD", 3 ) == 0 ) rld_proc( &objptr->obj_rld ); else if( memcmp( obj_label, "END", 3 ) == 0 ) end_proc( &objptr->obj_end ); else if( memcmp( obj_label, "SYM", 3 ) == 0 ) fprintf( stderr, "SYM records are not supported\n" ); else fprintf( stderr, "Unsupported object record '%3.3s' (ignored)\n", obj_label ); } close( objfd ); d_assemble(); return( 0 ); } static int open_obj_file( const char *cmdln ) { char *option_str, *fname, *ftype; int objfd, errnum; unsigned int optlen, optnum; struct stat stbuff; char sysmsg[ 100 ]; option_str = strchr( cmdln, ' ' ); if( option_str != NULL ) option_str = strskip( option_str, ' ' ); if( ( option_str == NULL ) || ( *option_str == '?' ) || ( *option_str == '\0' ) ) { #ifdef TARGCMS fputs( "Syntax: \n" "\n" "DISASM fname > <( options> < >output-file>\n" "\n" "options:\n" " Regequ NONe Esa Priv Xa\n" " Bas CSS Cs Tcc DC\n" " Das EF EPf Mi MP\n" " PKh Ski SR TB TR\n" " Vector\n" "\n" "Example:\n" " DISASM MYFILE ( REG > MYFILE ASSEMBLE ( RECFM F LRECL 80\n", stderr ); #else fputs( "Syntax: \n" "\n" "DISASM fname <<,>options> < >output-file>\n" "\n" "options:\n" " Regequ NONe Esa Priv Xa\n" " Bas CSS Cs Tcc DC\n" " Das EF EPf Mi MP\n" " PKh Ski SR TB TR\n" " Vector\n" "\n" "Example:\n" " DISASM OBJFNAME,REG > ASMFNAME\n", stderr ); #endif exit( 1 ); } dasmopt = 0x80000000U; fname = alloca( strlen( option_str ) + 6 ); strcpy( fname, option_str ); #ifdef TARGCMS option_str = strchr( fname, '(' ); if( option_str != NULL ) #else option_str = fname + strcspn( fname, " ," ); if( *option_str != '\0' ) #endif { *option_str = '\0'; strrtrm( fname ); ++option_str; for(;;) { for(;;) { option_str = strskip( option_str, ' ' ); if( *option_str != ',' ) break; ++option_str; } if( *option_str == '\0' ) break; optlen = strcspn( option_str, " ," ); optnum = tblookup( opttbl, option_str, optlen ); if( optnum == 0 ) { fprintf( stderr, "Unknown option '%s'\n", option_str ); exit( 24 ); } if( optnum == OPT_NOREGEQU ) dasmopt &= 0x7fffffff; else if( optnum == OPT_REGEQU ) dasmopt |= 0x80000000; else if( optnum == OPT_NONE ) dasmopt |= 0x7fffffff; else if( optnum < OPT_YES ) dasmopt |= (1 << (optnum - OPT_NONE - 1)); else dasmopt &= ~(1 << (optnum - OPT_YES)); option_str += optlen; } } #ifdef TARGCMS if( *( strskip( str_chr( fname, ' ' ), ' ' ) ) == '\0' ) strcat( fname, " TEXT" ); #endif objfd = open( fname, O_RDONLY|O_BINARY ); if( objfd == -1 ) { errnum = errno; if( ( errnum == EIO ) || ( errnum == ENOENT ) ) strcpy( sysmsg, _syserr() ); fprintf( stderr, "Unable to open file \"%s\" for input\n", fname ); if( errnum == EIO ) fprintf( stderr, " %s\n", sysmsg ); else if( errnum == ENOENT ) fprintf( stderr, " %s (%s)\n", strerror( errnum ), sysmsg ); else fprintf( stderr, " %s\n", strerror( errnum ) ); exit( 28 ); } #ifdef TARGCMS if( ( fstat( objfd, &stbuff ) != 0 ) || ( stbuff.st_lrecl != sizeof( obj_record ) ) || ( stbuff.st_recfm != 'F' ) ) { fprintf( stderr, "File \"%s\" is not a RECFM F LRECL 80 object/text file\n", fname ); close( objfd ); exit( 32 ); } #endif return( objfd ); } static void esd_proc( const esd_record *esdrecptr ) { esd_recdes *esdrdptr, *esd_cursor, *prevrdptr; esd_item *esditemptr; usint first_esdid; int len; first_esdid = esdrecptr->esd_esdid; esditemptr = esdrecptr->esd_items; for( len = esdrecptr->esd_itemcnt; len >= sizeof( esd_item ); len -= sizeof( esd_item ) ) { /* extract the contents of the esd_item into the esd_recdes... */ esdrdptr = dmalloc( sizeof( esd_recdes ) ); memcpy( esdrdptr->esdrd_name, esditemptr->esd_name, 8 ); esdrdptr->esdrd_name[ 8 ] = '\0'; esdrdptr->esdrd_type = esditemptr->esd__ta.esd_type; if( esdrdptr->esdrd_type == ESDT_LD ) esdrdptr->esdrd_esdid = 0; else esdrdptr->esdrd_esdid = first_esdid++; esdrdptr->esdrd_addr = esditemptr->esd__ta.esd_addr; esdrdptr->esdrd_align = esditemptr->esd__ae.esd_align; esdrdptr->esdrd_length = esditemptr->esd__ae.esd_extra; /* sort the ESD list (insertion sort)... */ esd_cursor = csect_list->csd_esdlst; prevrdptr = NULL; for(;;) { if( ( esd_cursor == NULL ) || ( esd_cursor->esdrd_addr > esdrdptr->esdrd_addr ) || ( ( esd_cursor->esdrd_addr == esdrdptr->esdrd_addr ) && ( esd_cursor->esdrd_type > esdrdptr->esdrd_type ) ) ) { esdrdptr->esdrd_next = esd_cursor; if( prevrdptr == NULL ) csect_list->csd_esdlst = esdrdptr; else prevrdptr->esdrd_next = esdrdptr; break; } prevrdptr = esd_cursor; esd_cursor = esd_cursor->esdrd_next; } ++esditemptr; } } static void txt_proc( const txt_record *txtrecptr ) { txt_recdes *txtrdptr, *txt_cursor, *prevrdptr; txtrdptr = dmalloc( sizeof( txt_recdes ) ); txtrdptr->txtrd_addr = txtrecptr->txt__f.txt_faddr; txtrdptr->txtrd_length = txtrecptr->txt_size; txtbufsize += txtrdptr->txtrd_length; txtrdptr->txtrd_esdid = txtrecptr->txt_esdid; memcpy( txtrdptr->txtrd_buffer, txtrecptr->txt_info, txtrdptr->txtrd_length ); /* sort the TXT list (insertion sort)... */ txt_cursor = csect_list->csd_txtlst; prevrdptr = NULL; for(;;) { if( ( txt_cursor == NULL ) || ( txt_cursor->txtrd_esdid > txtrdptr->txtrd_esdid ) || ( ( txt_cursor->txtrd_esdid == txtrdptr->txtrd_esdid ) && ( txt_cursor->txtrd_addr > txtrdptr->txtrd_addr ) ) ) { txtrdptr->txtrd_next = txt_cursor; if( prevrdptr == NULL ) csect_list->csd_txtlst = txtrdptr; else prevrdptr->txtrd_next = txtrdptr; break; } prevrdptr = txt_cursor; txt_cursor = txt_cursor->txtrd_next; } } static void rld_proc( const rld_record *rldrecptr ) { char prev_flag; usint len, relocation_esdid, position_esdid; rld_recdes *rld_cursor, *rldrdptr, *prevrdptr; rld_entry *rldentptr; rld_faddr *rldfaptr; prev_flag = 0; len = rldrecptr->rld_size; rldentptr = rldrecptr->rld_data; while( len > 0 ) { rldrdptr = dmalloc( sizeof( rld_recdes ) ); /* if the least_significant_bit of the previous flag is off, */ /* new esdids are found... */ if( ( prev_flag & 0x01 ) == 0 ) { relocation_esdid = rldentptr->rld_relesdid; position_esdid = rldentptr->rld_posesdid; rldfaptr = &rldentptr->rld__fa; len -= ( sizeof( rld_entry ) - sizeof( rld_faddr ) ); } rldrdptr->rldrd_resdid = relocation_esdid; rldrdptr->rldrd_pesdid = position_esdid; rldrdptr->rldrd_flag = rldfaptr->rld_flag; rldrdptr->rldrd_addr = rldfaptr->rld_addr; ++rldfaptr; rldentptr = (rld_entry *) rldfaptr; len -= sizeof( rld_faddr ); prev_flag = rldrdptr->rldrd_flag; /* sort the RLD list (insertion sort)... */ rld_cursor = csect_list->csd_rldlst; prevrdptr = NULL; for(;;) { if( ( rld_cursor == NULL ) || ( rld_cursor->rldrd_addr > rldrdptr->rldrd_addr ) || ( ( rld_cursor->rldrd_addr == rldrdptr->rldrd_addr ) && ( rld_cursor->rldrd_resdid > rldrdptr->rldrd_resdid ))) { rldrdptr->rldrd_next = rld_cursor; if( prevrdptr == NULL ) csect_list->csd_rldlst = rldrdptr; else prevrdptr->rldrd_next = rldrdptr; break; } prevrdptr = rld_cursor; rld_cursor = rld_cursor->rldrd_next; } } } static void end_proc( const end_record *endrecptr ) { csect_list->csd_end.endrd_entpt = endrecptr->end__e.end_entpt; if( csect_list->csd_end.endrd_entpt == 0x404040 ) csect_list->csd_end.endrd_entpt = 0; csect_list->csd_end.endrd_esdid = endrecptr->end_esdid; if( csect_list->csd_end.endrd_esdid == 0x4040 ) csect_list->csd_end.endrd_esdid = 0; } static void d_assemble( void ) { txt_recdes *txtrdptr; int cur_addr, last_addr; usint cur_esdid; esd_ptr = csect_list->csd_esdlst; rld_ptr = csect_list->csd_rldlst; txtbuffer = dmalloc( txtbufsize ); /* start copying the TXT list into txtbuffer... */ txtrdptr = csect_list->csd_txtlst; cur_esdid = 1; last_addr = 0; end_ptr = txtbuffer; for(;;) { /* if the end of the TXT list is encountered... */ if( txtrdptr == NULL ) { disassemble( last_addr ); print_rlds_and_esds( last_addr, 0xffffffff, 0 ); print_end(); return; } cur_addr = txtrdptr->txtrd_addr; /* if the start address of the new txt_recdes is different */ /* from the end address of the previous txt_recdes OR if the */ /* esdid of these record are different... */ if( ( txtrdptr->txtrd_esdid != cur_esdid ) || ( cur_addr != last_addr ) ) { disassemble( last_addr ); print_rlds_and_esds( last_addr, cur_addr, 1 ); last_addr = cur_addr; end_ptr = txtbuffer; cur_esdid = txtrdptr->txtrd_esdid; } /* ...otherwise simply copy the txt_recdes into txtbuffer... */ memcpy( end_ptr, txtrdptr->txtrd_buffer, txtrdptr->txtrd_length); end_ptr += txtrdptr->txtrd_length; last_addr += txtrdptr->txtrd_length; txtrdptr = txtrdptr->txtrd_next; } } static void print_end( void ) { esd_recdes *esdrdptr; char csect[ 9 ]; int addr; dprintf( " END" ); if( csect_list->csd_end.endrd_esdid ) { strcpy( csect, "*UNKNOWN" ); addr = 0; /* search the ESD list for the csect name and address... */ for( esdrdptr = csect_list->csd_esdlst; esdrdptr != NULL; esdrdptr = esdrdptr->esdrd_next ) { if( ( esdrdptr->esdrd_esdid == csect_list->csd_end.endrd_esdid ) && ( esdrdptr->esdrd_type == ESDT_SD ) ) { strcpy( csect, esdrdptr->esdrd_name ); *( str_chr( csect, ' ' ) ) = '\0'; addr = esdrdptr->esdrd_addr; break; } } dprintf( " %s", csect ); if( csect_list->csd_end.endrd_entpt ) dprintf( "+X'%X'", addr + csect_list->csd_end.endrd_entpt ); } dprintf( "\n" ); } static void disassemble( int last_addr ) { int cur_addr, len; char *buf_ptr, *new_ptr, *lbl_ptr; char fmtbuf[ 80 ]; cur_addr = last_addr - ( end_ptr - txtbuffer ); buf_ptr = txtbuffer; if( buf_ptr == end_ptr ) print_addr_label( cur_addr ); /* main processing loop... */ while( buf_ptr < end_ptr ) { print_addr_label( cur_addr ); len = print_rld( cur_addr, buf_ptr ); buf_ptr += len; cur_addr += len; if( len != 0 ) continue; /* unaligned code is not permitted... */ if( ((int) buf_ptr) & 1 ) new_ptr = buf_ptr; else new_ptr = (char *) dasm370( (unsigned short int *) buf_ptr, fmtbuf, dasmopt ); if( new_ptr == buf_ptr ) { /* no valid instruction was found... */ lbl_ptr = nextlabel( buf_ptr, new_ptr + 2, cur_addr ); /* if labels occur within the next 2 bytes... */ if( lbl_ptr != NULL ) { cur_addr += ( lbl_ptr - buf_ptr ); for( ; buf_ptr < lbl_ptr; ++buf_ptr ) dprintf( " DC X'%02X'\n", *buf_ptr ); } else if( ((int) buf_ptr) & 1 ) { dprintf( " DC X'%02X'\n", buf_ptr[ 0 ] ); ++cur_addr; ++buf_ptr; } else { dprintf( " DC X'%02X%02X'\n", buf_ptr[ 0 ], buf_ptr[ 1 ] ); cur_addr += 2; buf_ptr += 2; } } else { /* a valid instruction was found... */ lbl_ptr = nextlabel( buf_ptr, new_ptr, cur_addr ); /* if labels occur within the instruction... */ if( lbl_ptr != NULL ) { cur_addr += ( lbl_ptr - buf_ptr ); for( ; buf_ptr < lbl_ptr; ++buf_ptr ) dprintf( " DC X'%02X'\n", *buf_ptr ); } else { dprintf( " %s\n", fmtbuf ); cur_addr += ( new_ptr - buf_ptr ); buf_ptr = new_ptr; } } } } static char *nextlabel( char *buf_ptr, char *new_ptr, int cur_addr ) { esd_recdes *esdrdptr; for( ; buf_ptr < new_ptr; ++buf_ptr, ++cur_addr ) { for(;;) { esdrdptr = esd_ptr; if( ( esdrdptr == NULL ) || ( esdrdptr->esdrd_addr > cur_addr ) ) break; if( esdrdptr->esdrd_addr == cur_addr ) return( buf_ptr ); esd_ptr = esd_ptr->esdrd_next; } } if( new_ptr > end_ptr ) return( end_ptr ); return( NULL ); } static void print_addr_label( uint address ) { uint curaddr; esd_recdes *esdrdptr; curaddr = address; for(;;) { /* if no entries are found with the address... */ esdrdptr = esd_ptr; if( ( esdrdptr == NULL ) || ( esdrdptr->esdrd_addr > address ) ) { if( curaddr != address ) dprintf( " ORG %s+X'%X'\n", csect_list->csd_csname, address - cs_address ); return; } /* if an entry is found with the address... */ if( esdrdptr->esdrd_addr == curaddr ) print_label( esdrdptr ); else { if( esdrdptr->esdrd_type == ESDT_LD ) { curaddr = esdrdptr->esdrd_addr; dprintf( " ORG %s+X'%X'\n", csect_list->csd_csname, curaddr - cs_address ); } print_label( esdrdptr ); } esd_ptr = esdrdptr->esdrd_next; } } static void print_rlds_and_esds( uint curaddr, uint endaddr, int orgback) { for(;;) { if( esd_ptr != NULL ) { if( ( rld_ptr == NULL ) || ( esd_ptr->esdrd_addr <= rld_ptr->rldrd_addr ) ) { if( esd_ptr->esdrd_addr >= endaddr ) break; if( ( curaddr != esd_ptr->esdrd_addr ) && ( esd_ptr->esdrd_type == ESDT_LD ) ) { curaddr = esd_ptr->esdrd_addr; dprintf( " ORG %s+X'%X'\n", csect_list->csd_csname, curaddr - cs_address ); } print_label( esd_ptr ); esd_ptr = esd_ptr->esdrd_next; continue; } } if( ( rld_ptr == NULL ) || ( rld_ptr->rldrd_addr >= endaddr ) ) break; if( curaddr != rld_ptr->rldrd_addr ) { curaddr = rld_ptr->rldrd_addr; dprintf( " ORG %s+X'%X'\n", csect_list->csd_csname, curaddr - cs_address ); } curaddr += print_rld( curaddr, "\0\0\0" ); } if( ( orgback != 0 ) && ( curaddr != endaddr ) ) dprintf( " ORG %s+X'%X'\n", csect_list->csd_csname, endaddr - cs_address ); } static void print_label( esd_recdes *esdrdptr ) { int esd_flag; switch( esdrdptr->esdrd_type ) { case ESDT_SD: strcpy( csect_list->csd_csname, esdrdptr->esdrd_name ); *( str_chr( csect_list->csd_csname, ' ' ) ) = '\0'; dprintf( "%-9sCSECT\n", csect_list->csd_csname ); esd_flag = esdrdptr->esdrd_align; if( esd_flag == 0x40 ) printf( "* NO AMODE/RMODE\n" ); else { if( esd_flag & ESDA_RMODE_ANY ) printf( "%-9sRMODE ANY\n", csect_list->csd_csname ); else printf( "%-9sRMODE 24\n", csect_list->csd_csname ); esd_flag &= 0x03; if( esd_flag == ESDA_AMODE_24D ) printf( "* AMODE 24 (DEFAULT)\n" ); else if( esd_flag == ESDA_AMODE_24 ) printf( "%-9sAMODE 24\n", csect_list->csd_csname ); else if( esd_flag == ESDA_AMODE_31 ) printf( "%-9sAMODE 31\n", csect_list->csd_csname ); else printf( "%-9sAMODE ANY\n", csect_list->csd_csname ); } cs_address = esdrdptr->esdrd_addr; if( ( esdrdptr->esdrd_esdid == 0x0001 ) && ( (dasmopt & 0x80000000) != 0 ) ) dprintf( "R0 EQU 0\n" "R1 EQU 1\n" "R2 EQU 2\n" "R3 EQU 3\n" "R4 EQU 4\n" "R5 EQU 5\n" "R6 EQU 6\n" "R7 EQU 7\n" "R8 EQU 8\n" "R9 EQU 9\n" "R10 EQU 10\n" "R11 EQU 11\n" "R12 EQU 12\n" "R13 EQU 13\n" "R14 EQU 14\n" "R15 EQU 15\n" "F0 EQU 0\n" "F2 EQU 2\n" "F4 EQU 4\n" "F6 EQU 6\n" ); break; case ESDT_LD: dprintf( " ENTRY %s\n", esdrdptr->esdrd_name ); dprintf( "%-9sDS 0X\n", esdrdptr->esdrd_name ); break; case ESDT_ER: dprintf( " EXTRN %s\n", esdrdptr->esdrd_name ); break; case ESDT_PC: dprintf( " CSECT\n" ); break; case ESDT_CM: dprintf( " COM\n" ); break; case ESDT_XD: dprintf( " DXD\n" ); break; case ESDT_WX: dprintf( " WXTRN %s\n", esdrdptr->esdrd_name ); break; } } static int print_rld( int address, char *buf_ptr ) { rld_recdes *rldrdptr; int len, offset; char type, name[ 9 ]; rldrdptr = rld_ptr; for(;;) { if( ( rldrdptr == NULL ) || ( rldrdptr->rldrd_addr > address ) ) return( 0 ); if( rldrdptr->rldrd_addr == address ) { /* from bits 0 and 1 determine the length of offset... */ len = ( ( rldrdptr->rldrd_flag & 0x0c ) >> 2 ) + 1; if( ( rldrdptr->rldrd_flag & 0xf0 ) == 0x30 ) { dprintf( " CXD\n" ); rld_ptr = rldrdptr->rldrd_next; return( len ); } offset = 0; memcpy( ( (char *) &offset ) + sizeof( offset ) - len, buf_ptr, len ); /* from first digit determine the type... */ switch( rldrdptr->rldrd_flag & 0xf0 ) { case 0x00: type = 'A'; break; case 0x10: type = 'V'; break; case 0x20: type = 'Q'; break; } if( offset ) dprintf( " DC %cL%d(%d", type, len, offset ); else dprintf( " DC %cL%d(", type, len ); for(;;) { if( ( rldrdptr == NULL ) || ( rldrdptr->rldrd_addr > address ) ) { dprintf( ")\n" ); rld_ptr = rldrdptr; return( len ); } getname( name, rldrdptr->rldrd_resdid ); /* from bit 2 of the second digit determine sign... */ if( ( rldrdptr->rldrd_flag & 0x02 ) == 0x02 ) dprintf( "-" ); else if( offset != 0 ) dprintf( "+" ); offset = 1; dprintf( "%s", name ); rldrdptr = rldrdptr->rldrd_next; } } rldrdptr = rldrdptr->rldrd_next; } } static void getname( char *name, usint esdid ) { esd_recdes *esdrdptr; for( esdrdptr = csect_list->csd_esdlst; esdrdptr != NULL; esdrdptr = esdrdptr->esdrd_next ) { if( ( esdrdptr->esdrd_esdid == esdid ) && ( ( esdrdptr->esdrd_type != ESDT_LD ) || ( esdrdptr->esdrd_type != ESDT_ER ) ) ) { strcpy( name, esdrdptr->esdrd_name ); *( str_chr( name, ' ' ) ) = '\0'; return; } } } static char *str_chr( char *str, int chr ) { /* return pointer to chr or '\0'... */ while( ( *str != chr ) && ( *str != '\0' ) ) ++str; return( str ); } static void *dmalloc( size_t size ) { void *ptr; ptr = malloc( size ); if( ( ptr != NULL ) || ( size == 0 ) ) return( ptr ); fputs( "Insufficient memory\n", stderr ); exit( 41 ); } static void dprintf( const char *ctl, ... ) { int errnum; va_list ap; char sysmsg[ 100 ]; errno = 0; va_start( ap, ctl ); vprintf( ctl, ap ); va_end( ap ); errnum = errno; if( errnum == 0 ) return; if( errnum == EIO ) strcpy( sysmsg, _syserr() ); fprintf( stderr, "Error writing output file\n %s\n", ( errnum == EIO ) ? sysmsg : strerror( errnum ) ); exit( 28 ); }