mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-27 02:14:19 +00:00
Upload
Digital Research
This commit is contained in:
@@ -0,0 +1,413 @@
|
||||
/* this is the archiver for the Zilog edition of the C compiler */
|
||||
|
||||
typedef long time_t; /* a time */
|
||||
typedef int dev_t; /* device code */
|
||||
typedef long off_t; /* offset in file */
|
||||
|
||||
struct stat
|
||||
{
|
||||
dev_t st_dev;
|
||||
unsigned int st_ino;
|
||||
unsigned short st_mode;
|
||||
short st_nlink;
|
||||
short st_uid;
|
||||
short st_gid;
|
||||
dev_t st_rdev;
|
||||
off_t st_size;
|
||||
time_t st_atime;
|
||||
time_t st_mtime;
|
||||
time_t st_ctime;
|
||||
};
|
||||
|
||||
#define S_IFMT 0170000 /* type of file */
|
||||
#define S_IFDIR 0040000 /* directory */
|
||||
#define S_IFCHR 0020000 /* character special */
|
||||
#define S_IFBLK 0060000 /* block special */
|
||||
#define S_IFREG 0100000 /* regular */
|
||||
#define S_IFMPC 0030000 /* multiplexed char special */
|
||||
#define S_IFMPB 0070000 /* multiplexed block special */
|
||||
#define S_ISUID 0004000 /* set user id on execution */
|
||||
#define S_ISGID 0002000 /* set group id on execution */
|
||||
#define S_ISVTX 0001000 /* save swapped text even after use */
|
||||
#define S_IREAD 0000400 /* read permission, owner */
|
||||
#define S_IWRITE 0000200 /* write permission, owner */
|
||||
#define S_IEXEC 0000100 /* execute/search permission, owner */
|
||||
|
||||
#define AR8KMAGIC 0177545
|
||||
#define EVEN 0
|
||||
#define ODD 1
|
||||
|
||||
|
||||
struct ar8k_hd {
|
||||
char ar8k_name[14];
|
||||
long ar8k_date;
|
||||
char ar8k_uid, /* not used except for compatibility */
|
||||
ar8k_gid; /* only for compatibility */
|
||||
int ar8k_mode; /* compatibility */
|
||||
long ar8k_size;
|
||||
}
|
||||
head; /* header from the old archive */
|
||||
|
||||
struct stat statbuf;
|
||||
|
||||
char **filvec, /* pointer to start of vertor of files */
|
||||
*filename, /* current file being processed */
|
||||
*archive, /* the name of the archive file */
|
||||
*tail(), /* find the real name of the file */
|
||||
filmrk[256], /* marks for up to 256 files */
|
||||
buffer[512]; /* the copying buffer */
|
||||
|
||||
char *tmpname = "ar8kxxxx.tmp";
|
||||
|
||||
int key = 0, /* one of d r q t x */
|
||||
verbose, /* set if the 'v' key is used */
|
||||
arfile, /* file number of the archive file */
|
||||
tpfile, /* file number of the temporary file */
|
||||
tmpflag = 0, /* flag set if a tempfile created */
|
||||
file, /* file number of the input or output file */
|
||||
magic = {AR8KMAGIC}, /* the output magic word */
|
||||
inmagic, /* the file magic word is read here */
|
||||
filyet, /* count of files not yet processed */
|
||||
filcnt; /* count of files in filvec to process */
|
||||
|
||||
main(argc,argv) char **argv;{
|
||||
|
||||
register i;
|
||||
register char *cp;
|
||||
|
||||
if( argc < 3 ){
|
||||
printf("usage: ar8k key archfile [files ...]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cp = argv[1];
|
||||
while( i = *cp++ ) switch( i ){
|
||||
|
||||
case 'd':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 't':
|
||||
case 'x':
|
||||
if( key ) errex("only one of d q r t x allowed");
|
||||
key = i;
|
||||
continue;
|
||||
|
||||
case 'v': verbose++;
|
||||
continue;
|
||||
|
||||
default: errex("illegal key");
|
||||
}
|
||||
if( key == 0 ) errex("no key specified");
|
||||
|
||||
archive = argv[2];
|
||||
filvec = &argv[3];
|
||||
filyet = filcnt = argc-3;
|
||||
if( filcnt > 256 ) errex( "too many file names" );
|
||||
|
||||
/* now create a temporary file for the functions needing it */
|
||||
|
||||
switch( key ){
|
||||
|
||||
case 'd':
|
||||
case 'r':
|
||||
tmpflag = settmp();
|
||||
}
|
||||
|
||||
/* now open the archive for the functions needing to read it */
|
||||
|
||||
switch( key ){
|
||||
|
||||
case 'd':
|
||||
case 'r':
|
||||
case 't':
|
||||
case 'x':
|
||||
arfile = openb( archive , 0 );
|
||||
if( arfile < 0 ){ /* can't read */
|
||||
if( key != 'r' ) errex("can't read %s\n",archive );
|
||||
key = 'q';
|
||||
} else {
|
||||
chmagic( arfile );
|
||||
}
|
||||
}
|
||||
|
||||
if( key == 'q' ){ /* quick append to end */
|
||||
arfile = openb( archive , 2 );
|
||||
if( arfile < 0 ){
|
||||
arfile = creatb( archive , 0666 );
|
||||
if( arfile >= 0 ) wrmagic( arfile );
|
||||
else errex("can't append to %s",archive);
|
||||
} else {
|
||||
chmagic( arfile );
|
||||
lseek( arfile , 0L , 2 ); /* seek to end */
|
||||
}
|
||||
append( arfile );
|
||||
close(arfile);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* now do the main body of processing */
|
||||
|
||||
while( read( arfile, (char *) &head, sizeof head ) == sizeof head ){
|
||||
|
||||
switch( key ){
|
||||
|
||||
case 'd': /* deletion */
|
||||
if( inlist() ){
|
||||
comment("deleting");
|
||||
skip();
|
||||
} else {
|
||||
puthead( tpfile );
|
||||
copy( tpfile , EVEN , arfile , EVEN );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r': /* replacement */
|
||||
if( inlist() && (file = openb(filename,0)) >= 0 ){
|
||||
skip();
|
||||
getfile( tpfile , "replacing");
|
||||
} else {
|
||||
puthead( tpfile );
|
||||
copy( tpfile , EVEN , arfile , EVEN );
|
||||
}
|
||||
break;
|
||||
|
||||
case 't': /* listing */
|
||||
if( filcnt == 0 || inlist() ){
|
||||
if( verbose ){
|
||||
printf(" %7D ", head.ar8k_size );
|
||||
}
|
||||
printf("%-14.14s\n",head.ar8k_name);
|
||||
}
|
||||
skip();
|
||||
break;
|
||||
|
||||
case 'x': /* extracting */
|
||||
if( (filcnt == 0 || inlist()) &&
|
||||
(file=creatb(head.ar8k_name,0666)) >=0 ){
|
||||
comment("extracting");
|
||||
copy( file , ODD , arfile , EVEN );
|
||||
close( file );
|
||||
} else {
|
||||
skip();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* the main body of the work is done, copy the archive file back */
|
||||
|
||||
switch( key ){
|
||||
|
||||
case 'r':
|
||||
if( filyet )append( tpfile );
|
||||
|
||||
case 'd':
|
||||
close( arfile );
|
||||
arfile = creatb( archive , 0666 );
|
||||
if( arfile < 0 ){
|
||||
printf("cannot create %s\n",archive );
|
||||
} else {
|
||||
lseek( tpfile , 0L , 0 );
|
||||
while( (i = read( tpfile , buffer , 512)) > 0 )
|
||||
if( write( arfile , buffer , i ) != i )
|
||||
errex("botch in recopying the archive");
|
||||
}
|
||||
}
|
||||
if( filyet != 0 ){
|
||||
printf("\nfiles not processed:\n\n");
|
||||
for( i=0; i<filcnt; i++ )
|
||||
if( !filmrk[i] )
|
||||
printf("\t%s\n",filvec[i] );
|
||||
}
|
||||
if (tmpflag) {
|
||||
close(tpfile);
|
||||
unlink(tmpname);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
settmp(){ /* create a temporary archive file */
|
||||
|
||||
close( creatb( tmpname ) , 0600 );
|
||||
tpfile = openb( tmpname , 2 );
|
||||
/* unlink( "/tmp/ar8kxxxxxxx" ); */
|
||||
if( tpfile < 0 ){
|
||||
printf("cannot create tempfile\n" );
|
||||
exit(1);
|
||||
}
|
||||
wrmagic( tpfile );
|
||||
return(1);
|
||||
}
|
||||
|
||||
wrmagic( f ){ /* write the magic word */
|
||||
|
||||
if( write( f , (char *) &magic , sizeof(int) ) != sizeof(int) )
|
||||
errex("can't write magic word\n");
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
tail( s ) char *s; {
|
||||
|
||||
register i;
|
||||
register char *t,*u;
|
||||
|
||||
for(;;){
|
||||
u = t = s;
|
||||
while( i = *u++ )
|
||||
if( i == '/' ) t = u;
|
||||
if( *t ) return( t );
|
||||
if( t == s )errex("bad file name");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
comment(s) register char *s; {
|
||||
|
||||
if( verbose ) printf("%s:\t%-14.14s\n",s,head.ar8k_name);
|
||||
}
|
||||
|
||||
|
||||
errex(s,a,b,c) char *s; {
|
||||
|
||||
printf("fatal:\t");
|
||||
printf(s,a,b,c);
|
||||
printf("\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
getfile( f , s ) char *s;{ /* make a header and copy a file to f */
|
||||
|
||||
register char *cp;
|
||||
register i;
|
||||
|
||||
|
||||
cp = tail( filename );
|
||||
fstat( file , &statbuf );
|
||||
lseek(file, 0L, 0); /* reposition at head; "fstat" */
|
||||
/* corrupts the file position. */
|
||||
head.ar8k_size = statbuf.st_size;
|
||||
head.ar8k_uid = statbuf.st_uid;
|
||||
head.ar8k_gid = statbuf.st_gid;
|
||||
head.ar8k_date = statbuf.st_mtime;
|
||||
head.ar8k_mode = statbuf.st_mode;
|
||||
for( i=0; i<14; i++ )
|
||||
if( head.ar8k_name[i] = *cp )
|
||||
cp++;
|
||||
comment( s );
|
||||
puthead( f );
|
||||
copy( f , EVEN , file , ODD );
|
||||
close( file );
|
||||
}
|
||||
|
||||
|
||||
inlist(){ /* check to see if the current header name is in the list */
|
||||
|
||||
register char *cp,*bp;
|
||||
register j;
|
||||
int i;
|
||||
|
||||
for( i=0; i<filcnt; i++ ){
|
||||
if( !filmrk[i] ){
|
||||
cp = tail( filvec[i] );
|
||||
bp = head.ar8k_name;
|
||||
for( j=0; j<14; j++ ){
|
||||
if( *cp != *bp++ ) break;
|
||||
if( *cp ) cp++;
|
||||
}
|
||||
if( j == 14 ){
|
||||
filmrk[i]++;
|
||||
filyet--;
|
||||
filename = filvec[i];
|
||||
return( 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
copy( outf, outflag , inf, inflag ){
|
||||
|
||||
|
||||
register i,j;
|
||||
|
||||
i = head.ar8k_size >> 9;
|
||||
while( --i >= 0 ){
|
||||
if( read( inf , buffer , 512 ) != 512 ) errex("bad read");
|
||||
if( write( outf , buffer , 512) != 512 ) errex("bad write");
|
||||
}
|
||||
i = head.ar8k_size;
|
||||
j = i = i & 0777;
|
||||
if( i & 1 ){ /* odd length */
|
||||
if( inflag == EVEN ) i++;
|
||||
if( outflag == EVEN ) j++;
|
||||
}
|
||||
if( i ){
|
||||
if( read( inf , buffer , i ) != i ) errex("bad read.");
|
||||
buffer[i] = 0;
|
||||
if( write( outf , buffer , j ) != j ) errex("bad write.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
skip(){ /* skip over a file */
|
||||
|
||||
long size;
|
||||
|
||||
size = head.ar8k_size;
|
||||
if( size & 1 ) size++;
|
||||
lseek( arfile , size , 1 );
|
||||
}
|
||||
|
||||
|
||||
puthead( f ){ /* write the header */
|
||||
|
||||
if( write( f , (char *) &head , sizeof head ) != sizeof head )
|
||||
errex( "header write error" );
|
||||
}
|
||||
|
||||
|
||||
append( f ){
|
||||
|
||||
register i;
|
||||
|
||||
|
||||
for( i=0; i<filcnt; i++ ){
|
||||
if( !filmrk[i] ){
|
||||
filename = filvec[i];
|
||||
if( (file = openb(filename,0)) >= 0 ){
|
||||
filmrk[i]++;
|
||||
filyet--;
|
||||
getfile( f ,"appending");
|
||||
} else {
|
||||
printf("cannot read %s\n",filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chmagic( f ){ /* check the file for the magic code */
|
||||
|
||||
read( f , (char *) &inmagic , sizeof(int) );
|
||||
if( inmagic != AR8KMAGIC ) errex("%s is not an archive",archive);
|
||||
}
|
||||
|
||||
/* Dummy fstat since we're not in UNIX anymore. The call to _filesz */
|
||||
/* has the side effect of positioning the file at the end. */
|
||||
|
||||
fstat(fd,stp)
|
||||
int fd;
|
||||
struct stat *stp;
|
||||
{
|
||||
register long fsize;
|
||||
|
||||
fsize = _filesz(fd);
|
||||
stp->st_size = fsize;
|
||||
stp->st_uid = 0;
|
||||
stp->st_gid = 0;
|
||||
stp->st_mtime = 0;
|
||||
stp->st_mode = 0666;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,598 @@
|
||||
/******************************************************************************
|
||||
*******************************************************************************
|
||||
**
|
||||
** Unidot object format to x.out convertor.
|
||||
**
|
||||
** Usage is:
|
||||
**
|
||||
** xcon [-o outfile] [-s] file.obj
|
||||
**
|
||||
** The input file (file.obj) must be in the standard Unidot object file format,
|
||||
** and its name must end with ".obj". The input file is converted into the
|
||||
** x.out format, and the result is put in the output file specified by the
|
||||
** "-o" switch. If no "-o" switch is given, the file "x.out" is created as
|
||||
** a default.
|
||||
**
|
||||
** The "-s" switch will force the output to be marked as segmented, for
|
||||
** those rare cases where xcon cannot determine that from the input file.
|
||||
**
|
||||
** Care has been taken to ensure machine independence. The output file
|
||||
** generated by this program will be correct for a Z8000 regardless of
|
||||
** the processor on which this program is run. In particular, this program
|
||||
** may be run on a PDP-11 or on a VAX without any byte swap problems in the
|
||||
** output file. One consequence of this policy is that routines are used
|
||||
** to output the various structures defined in "xout.h". If the x.out
|
||||
** file format is changed, or if "xout.h" is changed, the corresponding
|
||||
** routines will probably need changing too. The routines to check are
|
||||
** outhdr(), outrel(), outseg(), outsym(), and outtxt().
|
||||
**
|
||||
** John D. Polstra
|
||||
** September 13, 1982
|
||||
**
|
||||
*******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#include "stdio.h"
|
||||
#include "xout.h"
|
||||
#include "obj.h"
|
||||
|
||||
/*
|
||||
* Constants.
|
||||
*/
|
||||
#define EXTMAX (RBMSK+1-RBEXT) /* Maximum number of external symbols allowed */
|
||||
#define SEGMAX 128 /* Maximum number of segments allowed */
|
||||
|
||||
/*
|
||||
* Type definitions.
|
||||
*/
|
||||
typedef unsigned short uns;
|
||||
|
||||
/*
|
||||
* Global variables.
|
||||
*/
|
||||
uns exttab[EXTMAX]; /* Mapping from external # to symbol # */
|
||||
uns *exttop = exttab; /* Pointer to top of exttab */
|
||||
|
||||
struct x_sg segtab[SEGMAX]; /* Table of information about segments */
|
||||
|
||||
struct x_hdr header; /* Header for x.out file */
|
||||
|
||||
long curoff; /* Current x.out file offset */
|
||||
long reloff; /* X.out file offset for next reloc. entry */
|
||||
long segoff[SEGMAX]; /* X.out file offsets for segments */
|
||||
long symoff; /* X.out file offset for next symbol */
|
||||
|
||||
uns symct; /* Number of symbols for the x.out file */
|
||||
|
||||
char dbgflg = 0; /* Debug output flag on =1 off =0 */
|
||||
char objbuf[255]; /* Buffer holding body of current .obj block */
|
||||
FILE *objiop; /* Standard I/O pointer for .obj file */
|
||||
char *objname; /* Name of .obj file */
|
||||
char *objpt, *objtop; /* Pointers into objbuf */
|
||||
int objtyp; /* Type of current .obj block */
|
||||
|
||||
int outfd; /* File descriptor for x.out file */
|
||||
char *outname = "x.out"; /* Name of x.out file */
|
||||
|
||||
int firstseg; /* First segment (0 or 1) actually output */
|
||||
char pass2; /* Flag set for second pass over .obj file */
|
||||
|
||||
char *prname; /* Name of this program */
|
||||
|
||||
/*
|
||||
* Here is a brief description of our section / segment numbering
|
||||
* scheme. The tables segtab[] and segoff[] are indexed by the Unidot
|
||||
* section number; thus they always have a slot for the absolute section
|
||||
* (number 0) whether it is used or not. However, we do not want to
|
||||
* output a segment descriptor for the absolute section unless it is
|
||||
* really used. So in the interlude we set the variable firstseg to
|
||||
* one iff the absolute section is used. Within the various x.out
|
||||
* outputting routines (outrel, outsym, etc.) we adjust the section numbers
|
||||
* according to the value of firstseg. The general philosophy is that
|
||||
* the outputting routines are called with Unidot section numbers; they
|
||||
* perform the necessary adjustments to produce the required x.out
|
||||
* segment numbers in the output file.
|
||||
*
|
||||
* Got it?
|
||||
*/
|
||||
|
||||
/*
|
||||
* Function declarations.
|
||||
*/
|
||||
long lseek(); /* Move I/O pointer to new file position */
|
||||
uns ogetb(); /* Get next byte from object block */
|
||||
long ogetl(); /* Get next long from object block */
|
||||
char *ogets(); /* Get next string from object block */
|
||||
uns ogetw(); /* Get next word from object block */
|
||||
|
||||
/*
|
||||
* main - The main program consists simply of some initialization followed
|
||||
* by two processing passes, with some interlude processing in between
|
||||
* the two passes.
|
||||
*/
|
||||
main(argc, argv)
|
||||
|
||||
int argc;
|
||||
char *argv[];
|
||||
|
||||
{
|
||||
init(argc, argv);
|
||||
dopass();
|
||||
interlude();
|
||||
pass2 = 1;
|
||||
rewind(objiop);
|
||||
dopass();
|
||||
close(outfd);
|
||||
fclose(objiop);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* dopass - Performs a scan of the .obj file.
|
||||
*/
|
||||
dopass() {
|
||||
|
||||
uns action;
|
||||
uns adr;
|
||||
uns base;
|
||||
uns len;
|
||||
uns relent;
|
||||
uns relpos;
|
||||
uns sec;
|
||||
char *sym;
|
||||
int type;
|
||||
uns val;
|
||||
|
||||
header.x_nseg = 1; /* We always leave room for an absolute segment */
|
||||
if(ofill() != OBOST)
|
||||
ferr("Bad .obj file format\n");
|
||||
while(ofill() != OBOND) {
|
||||
switch(objtyp) {
|
||||
|
||||
case OBSEC: /* Sections block */
|
||||
while(objpt < objtop) {
|
||||
ogetb(); /* Discard alignment */
|
||||
ogetb(); /* Discard extent */
|
||||
ogetb(); /* Discard attributes */
|
||||
sym = ogets(); /* Get section name */
|
||||
if(pass2 && dbgflg) printf("sections %s\n",sym);
|
||||
if(!pass2) {
|
||||
/*
|
||||
* Enter a new segment into segtab.
|
||||
* Increment the number of segments
|
||||
* in the header. Also increase
|
||||
* the symbol table size to account
|
||||
* for the segment name symbol.
|
||||
*/
|
||||
segtab[header.x_nseg].x_sg_no = 255;
|
||||
if (strcmp(sym,"__text")== 0)
|
||||
segtab[header.x_nseg].x_sg_typ = X_SG_COD;
|
||||
if (strcmp(sym,"__con")== 0)
|
||||
segtab[header.x_nseg].x_sg_typ = X_SG_CON;
|
||||
if (strcmp(sym,"__data")== 0)
|
||||
segtab[header.x_nseg].x_sg_typ = X_SG_DAT;
|
||||
if (strcmp(sym,"__bss")== 0)
|
||||
segtab[header.x_nseg].x_sg_typ = X_SG_BSS;
|
||||
header.x_symb += sizeof(struct x_sym);
|
||||
symct++;
|
||||
} else
|
||||
outsym(sym, X_SY_SEG, 0, header.x_nseg);
|
||||
header.x_nseg++;
|
||||
}
|
||||
break;
|
||||
|
||||
case OBGLO: /* Global symbols block */
|
||||
if(pass2 && dbgflg) printf("global ");
|
||||
case OBLOC: /* Local symbols block */
|
||||
if(pass2 && dbgflg) printf("symbols block\n");
|
||||
while(objpt < objtop) {
|
||||
val = (uns)ogetl();
|
||||
sec = ogetb();
|
||||
sym = ogets();
|
||||
if(!pass2) {
|
||||
if(sec == RBUND) /* Enter symbol # of new external */
|
||||
*exttop++ = symct;
|
||||
header.x_symb += sizeof(struct x_sym);
|
||||
symct++;
|
||||
} else {
|
||||
type = objtyp==OBGLO ? X_SY_GLB : X_SY_LOC;
|
||||
if(sec == RBUND)
|
||||
type = X_SY_UNX;
|
||||
outsym(sym, type, val, sec);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OBTXT: /* Text block */
|
||||
adr = (uns)ogetl();
|
||||
sec = ogetb();
|
||||
len = ogetb();
|
||||
if(pass2 && dbgflg)
|
||||
printf("text section[%x] at %x for %x bytes\n",sec,adr,len);
|
||||
if(!pass2) {
|
||||
if(adr+len > segtab[sec].x_sg_len)
|
||||
segtab[sec].x_sg_len = adr+len;
|
||||
objpt += len;
|
||||
while(objpt < objtop) {
|
||||
ogetb(); /* Relocation byte number */
|
||||
relent = ogetw(); /* Relocation entry */
|
||||
header.x_reloc += sizeof(struct x_rel);
|
||||
relent &= RAMSK;
|
||||
if(relent==RAZLS || relent==RAZSS || relent==RAZOF)
|
||||
header.x_magic = X_SU_MAGIC;
|
||||
}
|
||||
} else {
|
||||
outtxt(adr, sec, objpt, len);
|
||||
objpt += len;
|
||||
while(objpt < objtop) {
|
||||
relpos = adr + ogetb() - 6;
|
||||
relent = ogetw();
|
||||
action = relent & RAMSK;
|
||||
base = relent & RBMSK;
|
||||
switch(action) {
|
||||
|
||||
case RAA32M: /* absolute 32-bit address */
|
||||
/*
|
||||
* The loader can only relocate the least
|
||||
* significant half of a 32-bit item.
|
||||
*/
|
||||
relpos += 2;
|
||||
/* Fall through to next case */
|
||||
|
||||
case RAA16M: /* absolute 16-bit address */
|
||||
case RAZOF: /* segmented offset */
|
||||
type = base<RBEXT ? X_RL_OFF : X_RL_XOF;
|
||||
break;
|
||||
|
||||
case RAZSS: /* short segmented address */
|
||||
type = base<RBEXT ? X_RL_SSG : X_RL_XSSG;
|
||||
break;
|
||||
|
||||
case RAZLS: /* long segmented address */
|
||||
type = base<RBEXT ? X_RL_LSG : X_RL_XLSG;
|
||||
break;
|
||||
|
||||
default:
|
||||
ferr("Illegal reloc. 0x%x at loc. 0x%x of sec. 0x%x\n",
|
||||
relent, relpos, sec);
|
||||
}
|
||||
outrel(type, relpos, sec, base);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ferr - Issues a fatal error message and terminates.
|
||||
*/
|
||||
ferr(a, b, c, d, e)
|
||||
|
||||
char *a;
|
||||
int b, c, d, e;
|
||||
|
||||
{
|
||||
fprintf(stderr, a, b, c, d, e);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* init - Initialization.
|
||||
*/
|
||||
init(argc, argv)
|
||||
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
char *ap;
|
||||
|
||||
prname = argv[0];
|
||||
argv[argc] = (char *)0; /* For the benefit of UNIX Version 6 */
|
||||
header.x_magic = X_NU_MAGIC;
|
||||
while(*++argv != (char *)0) {
|
||||
ap = *argv;
|
||||
if(*ap == '-') /* options */
|
||||
while(*++ap != '\0')
|
||||
switch(*ap) {
|
||||
|
||||
case 'd': /* debug flag on */
|
||||
dbgflg = 1;
|
||||
break;
|
||||
case 'o': /* Next argument is output file */
|
||||
if((outname = *++argv) == (char *)0)
|
||||
usage();
|
||||
break;
|
||||
|
||||
case 's': /* Force segmented magic number */
|
||||
header.x_magic = X_SU_MAGIC;
|
||||
break;
|
||||
|
||||
default: /* Illegal switch */
|
||||
usage();
|
||||
}
|
||||
else { /* object file name */
|
||||
if(objname != (char *)0)
|
||||
usage();
|
||||
objname = ap;
|
||||
}
|
||||
}
|
||||
|
||||
if(objname==(char *)0 || strcmp(&objname[strlen(objname)-4], ".obj")!=0)
|
||||
usage();
|
||||
if((objiop = fopenb(objname, "r")) == NULL)
|
||||
ferr("Cannot open %s\n", objname);
|
||||
if(strcmp(objname, outname) == 0)
|
||||
ferr("Would destroy %s\n", objname);
|
||||
|
||||
/*
|
||||
* The 0th entry in the segment table is the absolute segment.
|
||||
* We will output it only if some code is generated into it. If we
|
||||
* do end up outputting it, we will hard assign it to segment number 0.
|
||||
*/
|
||||
segtab[0].x_sg_typ = X_SG_BSS;
|
||||
}
|
||||
|
||||
/*
|
||||
* interlude - Performs interpass processing.
|
||||
*/
|
||||
interlude() {
|
||||
|
||||
long off;
|
||||
uns *extptr;
|
||||
int segno;
|
||||
|
||||
if(exttop == exttab) { /* No undefined externals, make executable */
|
||||
header.x_magic = header.x_magic==X_SU_MAGIC ? X_SX_MAGIC : X_NXN_MAGIC;
|
||||
outfd = creatb(outname, 0777);
|
||||
} else
|
||||
outfd = creatb(outname, 0666);
|
||||
if(outfd == -1)
|
||||
ferr("Cannot create %s\n", outname);
|
||||
|
||||
if(segtab[0].x_sg_typ==X_SG_BSS || segtab[0].x_sg_typ==X_SG_STK)
|
||||
/*
|
||||
* There is no code going into the absolute segment, so we skip it.
|
||||
*/
|
||||
firstseg = 1;
|
||||
|
||||
off = (sizeof header) + (header.x_nseg - firstseg) * sizeof(struct x_sg);
|
||||
for(segno=0 ; segno<header.x_nseg ; segno++) {
|
||||
segoff[segno] = off;
|
||||
if(segtab[segno].x_sg_typ!=X_SG_BSS &&
|
||||
segtab[segno].x_sg_typ!=X_SG_STK) {
|
||||
off += segtab[segno].x_sg_len;
|
||||
header.x_init += segtab[segno].x_sg_len;
|
||||
}
|
||||
}
|
||||
reloff = off;
|
||||
symoff = reloff + header.x_reloc;
|
||||
|
||||
curoff = 0L;
|
||||
outhdr();
|
||||
outseg();
|
||||
}
|
||||
|
||||
/*
|
||||
* ofill - Reads the next object block into objbuf, and returns the block type.
|
||||
*/
|
||||
ofill() {
|
||||
|
||||
int ch;
|
||||
|
||||
if((objtyp = getc(objiop)) == EOF) return(0);
|
||||
if((ch = getc(objiop)) == EOF) ferr("Premature EOF\n");
|
||||
objtop = &objbuf[ch];
|
||||
for(objpt=objbuf ; objpt<objtop ; objpt++) {
|
||||
if((ch = getc(objiop)) == EOF) ferr("Premature EOF\n");
|
||||
*objpt = ch;
|
||||
}
|
||||
objpt = objbuf;
|
||||
return(objtyp);
|
||||
}
|
||||
|
||||
/*
|
||||
* ogetb - Returns the next byte from the object buffer.
|
||||
*/
|
||||
uns
|
||||
ogetb() {
|
||||
|
||||
if(objpt >= objtop) {
|
||||
ferr("Off the end of objbuf\n");
|
||||
}
|
||||
return(*objpt++&0377);
|
||||
}
|
||||
|
||||
/*
|
||||
* ogetl - Returns the next long word from the object buffer.
|
||||
*/
|
||||
long
|
||||
ogetl() {
|
||||
|
||||
long l;
|
||||
|
||||
l = ogetw();
|
||||
return((long)ogetw()<<16|l);
|
||||
}
|
||||
|
||||
/*
|
||||
* ogets - Returns a pointer to the next string in the object buffer.
|
||||
*/
|
||||
char *
|
||||
ogets() {
|
||||
|
||||
char *s;
|
||||
|
||||
s = objpt; while(ogetb());
|
||||
return(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* ogetw - Returns the next word from the object buffer.
|
||||
*/
|
||||
uns
|
||||
ogetw() {
|
||||
|
||||
uns w;
|
||||
|
||||
w = ogetb();
|
||||
return(ogetb()<<8|w);
|
||||
}
|
||||
|
||||
/*
|
||||
* outb - Outputs a single byte to the .out file.
|
||||
*/
|
||||
outb(val)
|
||||
|
||||
char val;
|
||||
{
|
||||
write(outfd, &val, 1);
|
||||
curoff++;
|
||||
}
|
||||
|
||||
/*
|
||||
* outhdr - Outputs the header section of the .out file.
|
||||
*/
|
||||
outhdr()
|
||||
{
|
||||
outw(header.x_magic);
|
||||
outw(header.x_nseg - firstseg);
|
||||
outl(header.x_init);
|
||||
outl(header.x_reloc);
|
||||
outl(header.x_symb);
|
||||
}
|
||||
|
||||
/*
|
||||
* outl - Outputs a single long word to the .out file. The long word is
|
||||
* written in Z8000 (MSB first) format, regardless of the host processor.
|
||||
*/
|
||||
outl(val)
|
||||
|
||||
long val;
|
||||
{
|
||||
char buf[4];
|
||||
|
||||
buf[3] = val;
|
||||
val >>= 8;
|
||||
buf[2] = val;
|
||||
val >>= 8;
|
||||
buf[1] = val;
|
||||
val >>= 8;
|
||||
buf[0] = val;
|
||||
write(outfd, buf, 4);
|
||||
curoff += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* outrel - Outputs a relocation entry with the specified type, offset,
|
||||
* segment, and relocation base.
|
||||
*/
|
||||
outrel(type, offset, segment, base)
|
||||
|
||||
int type;
|
||||
uns offset;
|
||||
int segment;
|
||||
uns base;
|
||||
{
|
||||
if(curoff != reloff)
|
||||
lseek(outfd, curoff = reloff, 0);
|
||||
if(base >= RBEXT)
|
||||
base = exttab[base-RBEXT];
|
||||
else
|
||||
base -= firstseg;
|
||||
outb(segment - firstseg);
|
||||
outb(type);
|
||||
outw(offset);
|
||||
outw(base);
|
||||
reloff = curoff;
|
||||
}
|
||||
|
||||
/*
|
||||
* outseg - Outputs the segments section of the .out file.
|
||||
*/
|
||||
outseg()
|
||||
{
|
||||
struct x_sg *p;
|
||||
|
||||
for(p = &segtab[firstseg] ; p < &segtab[header.x_nseg] ; p++) {
|
||||
outb(p->x_sg_no);
|
||||
outb(p->x_sg_typ);
|
||||
outw(p->x_sg_len);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* outsym - Outputs a symbol table entry with the specified name,
|
||||
* type, value, and segment.
|
||||
*/
|
||||
outsym(name, type, value, segment)
|
||||
|
||||
register char *name;
|
||||
int type;
|
||||
unsigned short value;
|
||||
int segment;
|
||||
{
|
||||
register int i;
|
||||
|
||||
if(curoff != symoff)
|
||||
lseek(outfd, curoff = symoff, 0);
|
||||
if(segment==RBABS || segment==RBUND)
|
||||
segment = 255;
|
||||
else
|
||||
segment -= firstseg;
|
||||
outb(segment);
|
||||
outb(type);
|
||||
outw(value);
|
||||
for(i=0 ; i<XNAMELN ; i++) {
|
||||
outb(*name);
|
||||
if(*name != '\0')
|
||||
name++;
|
||||
}
|
||||
symoff = curoff;
|
||||
}
|
||||
|
||||
/*
|
||||
* outtxt - Outputs a block of text for the specified offset in the specified
|
||||
* segment. The text comes from txtptr and has txtct bytes.
|
||||
*/
|
||||
outtxt(offset, segment, txtptr, txtct)
|
||||
|
||||
uns offset;
|
||||
int segment;
|
||||
char *txtptr;
|
||||
int txtct;
|
||||
{
|
||||
long txtoff;
|
||||
|
||||
txtoff = segoff[segment] + (long)offset;
|
||||
if(curoff != txtoff)
|
||||
lseek(outfd, curoff = txtoff, 0);
|
||||
write(outfd, txtptr, txtct);
|
||||
curoff += txtct;
|
||||
}
|
||||
|
||||
/*
|
||||
* outw - Outputs a single word to the .out file. The word is written in
|
||||
* Z8000 (MSB first) format, regardless of the host processor.
|
||||
*/
|
||||
outw(val)
|
||||
|
||||
uns val;
|
||||
{
|
||||
char buf[2];
|
||||
|
||||
buf[1] = val;
|
||||
val >>= 8;
|
||||
buf[0] = val;
|
||||
write(outfd, buf, 2);
|
||||
curoff += 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* usage - Issues a fatal error message for incorrect usage.
|
||||
*/
|
||||
usage() {
|
||||
|
||||
ferr("Usage: %s [-o x.out] [-s] file.obj\n", prname);
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
|
||||
/* quickie program to dump x.out files */
|
||||
|
||||
#include "stdio.h"
|
||||
#include "x.out.h"
|
||||
|
||||
struct x_hdr x_hdr;
|
||||
struct x_sg x_sg[10];
|
||||
struct x_rel x_rel;
|
||||
struct x_sym x_sym;
|
||||
short sbuf[2048];
|
||||
|
||||
char *segtypes[] {
|
||||
"unknown",
|
||||
"bss",
|
||||
"stack",
|
||||
"code",
|
||||
"constant pool",
|
||||
"initialized data",
|
||||
"mixed code/data, not protectable",
|
||||
"mixed code/data, protectable"
|
||||
};
|
||||
|
||||
int floc,
|
||||
bigs,
|
||||
dflag = {1}, /* dump init data */
|
||||
rflag = {1}, /* dump relocation data */
|
||||
sflag = {1}; /* dump symbol table data */
|
||||
|
||||
main( argc, argv ) char **argv; {
|
||||
|
||||
register i,
|
||||
j,
|
||||
k,
|
||||
l;
|
||||
unsigned len,
|
||||
offset;
|
||||
|
||||
i = 1;
|
||||
if( i < argc && argv[i][0] == '-' ) doargs( argv[i++] );
|
||||
if( i < argc ){
|
||||
close( 0 );
|
||||
if( openb( argv[i] , 0 ) != 0 ){
|
||||
printf(stderr,"cannot open '%s'\n",argv[i] );
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
read( 0 , &x_hdr , sizeof( x_hdr ) );
|
||||
if( !bigs )fprintf( stdout,
|
||||
"magic = %x nseg = %d init = %ld reloc = %ld symb = %ld\n",
|
||||
x_hdr.x_magic,
|
||||
x_hdr.x_nseg,
|
||||
x_hdr.x_init,
|
||||
x_hdr.x_reloc,
|
||||
x_hdr.x_symb );
|
||||
floc = sizeof( x_hdr );
|
||||
for( i=0; i<x_hdr.x_nseg; i++ ){
|
||||
read( 0 , &x_sg[i] , sizeof( x_sg[0] ) );
|
||||
if( !bigs )fprintf( stdout,
|
||||
"%4x sg[%d]: sgno = %d typ = %d len = %u\n",
|
||||
floc,
|
||||
i,
|
||||
x_sg[i].x_sg_no & 0377,
|
||||
x_sg[i].x_sg_typ & 0377,
|
||||
x_sg[i].x_sg_len );
|
||||
floc += sizeof( x_sg[0] );
|
||||
}
|
||||
for( i=0; i<x_hdr.x_nseg; i++ ){ /* dump the segments */
|
||||
k = x_sg[i].x_sg_typ;
|
||||
if( !bigs )
|
||||
fprintf( stdout, "segment %d\ttype is %s\n",
|
||||
i, segtypes[k]);
|
||||
if( k == X_SG_BSS || k == X_SG_STK ){
|
||||
if( !bigs )fprintf(stdout,"\nNo initialization");
|
||||
} else {
|
||||
len = x_sg[i].x_sg_len;
|
||||
offset = 0;
|
||||
while(len>0) {
|
||||
l = (len>4096)?4096:len;
|
||||
j = read( 0, sbuf, l );
|
||||
if( j != l ){
|
||||
fprintf(stdout,
|
||||
"unexpected eof: length is %u\n",
|
||||
offset + j);
|
||||
j = 0;
|
||||
}
|
||||
for( k = 0; k<j; offset += 2, k += 2 ){
|
||||
if( dflag ){
|
||||
if( (k & 017) == 0 )
|
||||
fprintf(stdout,"\n%4x %5d %4x ",
|
||||
floc,offset,offset);
|
||||
puth( sbuf[ k>>1 ] );
|
||||
}
|
||||
floc += 2;
|
||||
}
|
||||
len -= l;
|
||||
}
|
||||
}
|
||||
if( dflag ) fprintf(stdout,"\n\n" );
|
||||
}
|
||||
if(x_hdr.x_reloc && rflag && !bigs)
|
||||
fprintf(stdout,"floc sgn flg loc bas\n");
|
||||
for( i=0; i<x_hdr.x_reloc; i += sizeof( x_rel ) ){
|
||||
if( read( 0 , &x_rel, sizeof( x_rel ) ) != sizeof(x_rel)) eof();
|
||||
if( rflag ) fprintf(stdout,
|
||||
"%4x %4d%4d%6d%6d\n",
|
||||
floc,
|
||||
x_rel.x_rl_sgn & 0377,
|
||||
x_rel.x_rl_flg & 0377,
|
||||
x_rel.x_rl_loc,
|
||||
x_rel.x_rl_bas );
|
||||
floc += sizeof( x_rel );
|
||||
}
|
||||
if( sflag || bigs ){
|
||||
if( !bigs )fprintf(stdout,"\nsymbols: \n\n");
|
||||
for( i=0; i<x_hdr.x_symb; i+= sizeof( x_sym ) ){
|
||||
if(read(0, &x_sym, sizeof(x_sym)) != sizeof( x_sym ))
|
||||
eof();
|
||||
if( !bigs )fprintf(stdout,
|
||||
"%4x %4d%4d",
|
||||
floc,
|
||||
x_sym.x_sy_sg & 0377,
|
||||
x_sym.x_sy_fl & 0377);
|
||||
fprintf(stdout,"%6x %.8s\n",
|
||||
x_sym.x_sy_val,
|
||||
x_sym.x_sy_name );
|
||||
floc += sizeof( x_sym );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
doargs( s ) register char *s; {
|
||||
|
||||
sflag = dflag = rflag = 0;
|
||||
for(;;) switch( *s++ ){
|
||||
|
||||
case 0: return;
|
||||
case 'd': dflag++; continue;
|
||||
case 'r': rflag++; continue;
|
||||
case 'S': bigs++;
|
||||
case 's': sflag++; continue;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char hextab[] {"0123456789abcdef"};
|
||||
puth( n ){ /* put out a word in hex */
|
||||
|
||||
register i;
|
||||
|
||||
putchar( ' ' );
|
||||
for( i=12; i>= 0; i -= 4 ) putchar( hextab[ (n>>i) & 017 ] );
|
||||
}
|
||||
|
||||
|
||||
eof(){
|
||||
|
||||
fprintf(stdout,"\n\n*****unexpected eof*****\n");
|
||||
exit(0);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
|
||||
struct x_hdr {
|
||||
short x_magic; /* magic number */
|
||||
short x_nseg; /* number of segments in file */
|
||||
long x_init; /* length of initialized part of file */
|
||||
long x_reloc; /* length of relocation part of file */
|
||||
long x_symb; /* length of symbol table part of file */
|
||||
};
|
||||
|
||||
|
||||
struct x_sg {
|
||||
char x_sg_no; /* assigned number of segment */
|
||||
char x_sg_typ; /* type of segment */
|
||||
unsigned x_sg_len; /* length of segment */
|
||||
}; /* x_sg[] is an array of size x_nseg */
|
||||
|
||||
|
||||
#define X_SU_MAGIC 0xEE00 /* segmented, non executable */
|
||||
#define X_SX_MAGIC 0xEE01 /* segmented, executable */
|
||||
#define X_NU_MAGIC 0xEE02 /* non-segmented, non executable */
|
||||
#define X_NXN_MAGIC 0xEE03 /* non-segmented, executable, non-shared */
|
||||
#define X_NUS_MAGIC 0xEE06 /* non-segmented, non executable, shared */
|
||||
#define X_NXS_MAGIC 0xEE07 /* non-segmented, executable, shared */
|
||||
#define X_NUI_MAGIC 0xEE0A /* non-segmented, non executable, split ID */
|
||||
#define X_NXI_MAGIC 0xEE0B /* non-segmented, executable, split ID */
|
||||
|
||||
#define X_SG_BSS 1 /* non-initialized data segment */
|
||||
#define X_SG_STK 2 /* stack segment, no data in file */
|
||||
#define X_SG_COD 3 /* code segment */
|
||||
#define X_SG_CON 4 /* constant pool */
|
||||
#define X_SG_DAT 5 /* initialized data */
|
||||
#define X_SG_MXU 6 /* mixed code and data, not protectable */
|
||||
#define X_SG_MXP 7 /* mixed code and data, protectable */
|
||||
|
||||
struct x_rel { /* relocation item */
|
||||
char x_rl_sgn; /* segment containing item to be relocated */
|
||||
char x_rl_flg; /* relocation type (see below) */
|
||||
unsigned x_rl_loc; /* location of item to be relocated */
|
||||
unsigned x_rl_bas; /* number of (external) element in symbol table
|
||||
or (internal) segment by which to relocate */
|
||||
};
|
||||
|
||||
|
||||
#define X_RL_OFF 1 /* adjust a 16 bit offset value only */
|
||||
#define X_RL_SSG 2 /* adjust a short form segment plus offset */
|
||||
#define X_RL_LSG 3 /* adjust a long form (32 bit) seg plus off */
|
||||
#define X_RL_XOF 5 /* adjust a 16 bit offset by an external */
|
||||
#define X_RL_XSSG 6 /* adjust a short seg ref by an external */
|
||||
#define X_RL_XLSG 7 /* adjust a long seg ref by an external */
|
||||
|
||||
#define XNAMELN 8 /* length of a symbol */
|
||||
|
||||
struct x_sym {
|
||||
char x_sy_sg; /* the segment number */
|
||||
char x_sy_fl; /* the type of entry */
|
||||
unsigned x_sy_val; /* the value of this entry */
|
||||
char x_sy_name[XNAMELN]; /* the symbol name, padded with 0's */
|
||||
};
|
||||
|
||||
#define X_SY_LOC 1 /* local symbol (for debug only) */
|
||||
#define X_SY_UNX 2 /* undefined external entry */
|
||||
#define X_SY_GLB 3 /* global definition */
|
||||
#define X_SY_SEG 4 /* segmenIq
|
||||
|
||||
|
||||
This directory contains the source and object files for the Z8000 CP/M Ccp,
|
||||
Reference in New Issue
Block a user