DataMuseum.dk

Presents historical artifacts from the history of:

CP/M

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about CP/M

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦29735250f⟧ TextFile

    Length: 18816 (0x4980)
    Types: TextFile
    Names: »MAKOVL.C«

Derivation

└─⟦b35f94715⟧ Bits:30003295 BDS C version 1.50 arbejdsdiskette til RC703 Piccolo
└─⟦b35f94715⟧ Bits:30005324 BDS C version 1.50 arbejdsdiskette til RC703 Piccolo
    └─ ⟦this⟧ »MAKOVL.C« 

TextFile

/* MAKOVL.C	Overlay builder/manager

	This code is in the public domain.
	Created from L2.C 81.10.29 Gyro

This is a variation on L2.C that creates relocatable overlays
according to an overlay descriptor file.

Command format:

	makovl <root name> <overlay name> æ<CRL file>å Æ-l æ<CRL file>åÅ Æ-ndÅ

Overlay descriptor file, <root name>.DES, contains:

	<overlay slot size> <relocation info size>
	<CRL file> ... (default search list)
	... (more default search list)
	<blank line>
	<overlay name> <slot number>
		<function name>  <comments or whatnot>
		<function name>  <comments or whatnot>
		... (an entry for each top-level function in the overlay)
	<blank line>
	<overlay name> <slot number>
		<function name>  <comments or whatnot>
		<function name>  <comments or whatnot>
		...
	... (an entry for each overlay in the file)


Overlay segments are of length <overlay slot size> bytes, of which the
last <relocation info size> bytes holds a list of relocation offsets. 
This is a null-terminated string of byte values giving the difference
between successive addresses to be relocated; a value of 255 means to
add 255 to the next byte value to get the offset.  The first offset is
relative to -1 (so that we can relocate the first word of the
overlay).  At the beginning of the overlay is a table of addresses of
top-level functions, one address for each function listed for that
overlay in the descriptor file.

The -l option works as for L2: CRL files listed before the -l are
loaded in entirety; those after are just scanned for needed functions. 
Any functions specified in the default search list in the overlay
descriptor file are also scanned, unless the -nd (no default) option
is given.

The overlay, once created, is written into <root name>.OVL, at address
<slot number> * <overlay slot size>.

*/


/**************** Globals ****************/

#define SDOS				/* comment this out for CP/M */

#include "bdscio.h"			/* for i/o buffer defs */

#define NUL		0
#define FLAG		char
#define repeat 	while (1)

#define STDOUT		1


/* function table */
struct funct æ
	char fnameÆ9Å;
	FLAG flinkedp;			/* in memory already? */
	char *faddr;			/* address of first ref link if not linked */
	å ftab Æ300Å;
int nfuncts;				/* no. of functions in table */

#define LINKED		255		/* (flinkedp) function really here */
#define EXTERNAL	254		/* function defined in separate symbol table */

char fdir Æ512Å;			/* CRL file function directory */

/* command line parameters etc. */
char rootnameÆ15Å;			/* name of root program */
char ovlnameÆ40Å;			/* name of overlay to be built */
int nprogs, nlibs;
char progfiles Æ20Å Æ15Å;	/* program file names */
char libfiles Æ30Å Æ15Å;		/* library file names */
FLAG srchdefs;				/* search default libraries? */

/* overlay description */
int ovlsize, relsize;		/* size of overlay slot & of relocation info */
int ovlslot;				/* slot # to put overlay in */
char topfunctsÆ10ÅÆ32Å;		/* names of top level functions */
int ntops;				/* number of top level functions */
char *relstart;			/* beginning of relocation info */
char *relnext;				/* next relocation value */
char *reladdr;				/* last address relocated */


/* useful things to have defined */
struct inst æ
	char opcode;
	char *address;
	å;

union ptr æ
	unsigned u;			/* an int */
	unsigned *w;			/* a word ptr */
	char *b;				/* a byte ptr */
	struct inst *i;		/* an instruction ptr */
	å;


/* Link control variables */

union ptr codend;			/* last used byte of code buffer + 1 */
union ptr acodend;			/* actual code-end address */
unsigned origin;			/* origin of code */
unsigned buforg;			/* origin of code buffer */

char *lspace;				/* space to link in */
char *lspcend;				/* end of link area */
char *lodstart;			/* beginning of current file */


/* i/o buffer */
struct iobuf æ
	int fd;
	int isect;			/* currently buffered sector */
	int nextc;			/* index of next char in buffer */
	char buff Æ128Å;
	å ibuf, obuf;

/* BDS C i/o buffer */
char bdsbufÆBUFSIZÅ;

/* seek opcodes */
#define ABSOLUTE 0
#define RELATIVE 1

#define INPUT 0
#define UPDATE 2

#define TRUE (-1)
#define FALSE 0
#define NULL 0

/* 8080 instructions */
#define LHLD 0x2A
#define LXIH 0x21
#define SPHL 0xF9
#define JMP  0xC3
#define CALL 0xCD

/* strcmp7 locals, made global for speed */
char _c1, _c2, _end1, _end2;

/**************** End of Globals ****************/



main (argc, argv)
	int argc;
	char **argv;
æ
	puts ("Mark of the Unicorn Overlay Builder, vsn. 1.0Øn");
	setup (argc, argv);
	linkprog();
	linklibs();
	listfuns();
	wrtovl();
	å


setup (argc, argv)			/* initialize function table, etc. */
	int argc;
	char **argv;
æ
	nprogs = 0;
	nlibs = 0;
	origin = buforg = 0;
	nfuncts = 0;
	srchdefs = TRUE;
	cmdline (argc, argv);
	lspace = endext();
	lspcend = topofmem() - 1024;
	getdesc();
	loadsyms();
	å


cmdline (argc, argv)		/* process command line */
	int argc;
	char **argv;
æ
	int i, progp;

	if (argc <= 2) æ
		puts ("Usage is:Øn");
		puts ("  makovl <root name> <overlay name> æ<CRL file>å Æ-l æ<CRL file>åÅ");
		exit (1);
		å
	strcpy (&rootname, argvÆ1Å);
	strcpy (&ovlname, argvÆ2Å);
	progp = TRUE;
	for (i = 3; i < argc; ++i) æ
		if (argvÆiÅÆ0Å == '-') æ
			if (!strcmp (argvÆiÅ, "-L")) progp = FALSE;
			else if (match (argvÆiÅ, "-ND")) srchdefs = FALSE;
			else printf ("Unknown option: '%s'Øn", argvÆiÅ);
			å
		else æ
			if (progp) strcpy (&progfilesÆnprogs++Å, argvÆiÅ);
			else strcpy (&libfilesÆnlibs++Å, argvÆiÅ);
			å
		å
	å


getdesc()					/* get & process overlay description */
æ
	makeext (&rootname, "DES");
	if (fopen (&rootname, &bdsbuf) < 0)
		Fatal ("Can't open overlay descriptor file '%s'.Øn", &rootname);
	if (fscanf (&bdsbuf, "%d%d", &ovlsize, &relsize) < 2
	    øø  ovlsize <= relsize) æ
		Fatal ("Error in descriptor file: bad overlay/relocation sizes.Øn");
		å
	getlibs();
	findovl();
	readfuns();
	fclose (&bdsbuf);
	å


getlibs()					/* get default search list */
æ
	char lineÆMAXLINEÅ, *cp, *dest;
	
	repeat æ
		if (!fgets (&line, &bdsbuf)  øø  !lineÆ0Å) break;
		if (!srchdefs) continue;
		cp = &line;
		repeat æ
			while (isspace (*cp)) ++cp;
			if (!*cp) break;
			dest = &libfilesÆnlibs++Å;
			while (*cp  &&  !isspace (*cp)) *dest++ = *cp++;
			*dest = NUL;
			å
		å
	å


findovl()					/* find description of overlay */
æ
	char tnameÆ40Å;
	int nread;
	FLAG skipping, found;
	
	skipping = found = FALSE;
	while (!found
		  &&  (nread = fscanf (&bdsbuf, "%s%d", &tname, &ovlslot)) >= 0) æ
		if (nread) æ
			if (!skipping) æ
				if (match (&tname, &ovlname)) found = TRUE;
				else skipping = TRUE;
				å
			å
		else skipping = FALSE;
		å
	if (!found)
		Fatal ("Can't find description of overlay '%s'.Øn", &ovlname);
	if (nread < 2) 
		Fatal ("No slot number present for overlay '%s'.Øn", &tname);
	printf ("Building overlay %s, for slot %d.Øn", &tname, ovlslot);
	å


readfuns()
æ
	char tnameÆ40Å;
	struct funct *fnct;
	
	ntops = 0;
	RelInit();
	codend.b = lspace;				/* build table of functions */
	puts ("Functions included:Øn");
	while (fscanf (&bdsbuf, "%s", &tname) > 0) æ
		printf ("%-10s", &tname);
		upcase (&tname);
		tnameÆ8Å = NUL;			/* limit size */
		fnct = intern (&tname);
		*codend.w = fnct->faddr;		/* link in reference */
		RelAccum (codend.w);		/* relocate this address */
		fnct->faddr = codend.w++;
		ntops++;
		å
	puts ("ØnØn");
	å


linkprog()				/* link in all program files */
æ
	int i;
	union ptr dirtmp;
	struct funct *fnct;

	for (i=0; i<nprogs; ++i) æ
		makeext (&progfilesÆiÅ, "CRL");
		if (copen (&ibuf, progfilesÆiÅ) < 0) æ
			printf ("Can't open %sØn", progfilesÆiÅ);
			continue;
			å
		printf ("Loading %sØn", &progfilesÆiÅ);
		readprog (i==0);
		for (dirtmp.b=&fdir; *dirtmp.b != 0x80;) æ
			fnct = intern (dirtmp.b);			/* for each module */
			skip7 (&dirtmp);					/* in directory */
			if (!fnct->flinkedp)
				linkmod (fnct, lodstart + *dirtmp.w - 0x205);
			else æ
				puts ("  Duplicate program function '");
				puts (&fnct->fname);
				puts ("', not linked.Øn");
				å
			dirtmp.w++;
			å								/* intern & link it */
		cclose (&ibuf);
		å
	å


linklibs()				/* link in library files */
æ
	int ifile;

	for (ifile = 0; ifile < nlibs; ++ifile) scanlib (ifile);
	while (missingp()) æ
		puts ("Enter the name of a file to be searched: ");
		gets (&libfilesÆnlibsÅ);
		upcase (&libfilesÆnlibsÅ);
		scanlib (nlibs++);
		å
	acodend.b = codend.b - lspace + buforg;		/* save that number! */
	å


missingp()				/* are any functions missing?  print them out */
æ
	int i, foundp;

	foundp = FALSE;
	for (i=0; i<nfuncts; ++i)
		if (!ftabÆiÅ.flinkedp) æ
			if (!foundp) puts ("*** Missing functions:Øn");
			puts (&ftabÆiÅ.fname);
			puts ("Øn");
			foundp = TRUE;
			å
	return (foundp);
	å


readprog (mainp)			/* read in a program file */
	FLAG mainp;
æ
	char extp;							/* was -e used? */
	char *extstmp;
	union ptr dir;
	unsigned len;

	if (cread (&ibuf, &fdir, 512) < 512)			/* read directory */
		Fatal ("-- read error!Øn");
	cseek (&ibuf, 5, RELATIVE);
	for (dir.b=&fdir; *dir.b != 0x80; nextd (&dir));	/* find end of dir */
	++dir.b;
	len = *dir.w - 0x205;
	readobj (len);
	å


readobj (len)				/* read in an object (program or lib funct) */
	unsigned len;
æ
	if (codend.b + len >= lspcend) Fatal ("-- out of memory!Øn");
	lodstart = codend.b;
	if (cread (&ibuf, lodstart, len) < len)
		Fatal ("-- read error (read 0x%x)!Øn", len);
	å


scanlib (ifile)
	int ifile;
æ
	int i;
	union ptr dirtmp;

	makeext (&libfilesÆifileÅ, "CRL");
	if (copen (&ibuf, libfilesÆifileÅ) < 0) æ
		printf ("Can't open %sØn", libfilesÆifileÅ);
		return;
		å
	printf ("Scanning %sØn", &libfilesÆifileÅ);
	if (cread (&ibuf, &fdir, 512) < 512)	/* read directory */
		Fatal ("-- Read error (directory)!Øn");
	for (i=0; i<nfuncts; ++i) æ			/* scan needed functions */
		if (!ftabÆiÅ.flinkedp
		    && (dirtmp.b = dirsearch (&ftabÆiÅ.fname))) æ
			readfunct (dirtmp.b);
			linkmod (&ftabÆiÅ, lodstart);
			å
		å
	cclose (&ibuf);
	å


readfunct (direntry)			/* read a function (from a library) */
	union ptr direntry;
æ
	unsigned start, len;

	skip7 (&direntry);
	start = *direntry.w++;
	skip7 (&direntry);
	len = *direntry.w - start;
	if (cseek (&ibuf, start, ABSOLUTE) < 0)
		Fatal (" -- read error (seek 0x%x)!", start);
	readobj (len);
	å


linkmod (fnct, modstart)			/* link in a module */
	struct funct *fnct;
	union ptr	modstart;					/* loc. of module in memory */

æ
	union ptr temp,
			jump,					/* jump table temp */
			body,					/* loc. of function in memory */
			code,					/* loc. of code proper in mem. */
			finalloc;					/* runtime loc. of function */
	unsigned flen, nrelocs, jtsiz, offset;

	fnct->flinkedp = LINKED;
	finalloc.b = codend.b - lspace + buforg;
	chase (fnct->faddr, finalloc.b);
	fnct->faddr = finalloc.b;
	body.b = modstart.b + strlen(modstart.b) + 3; /* loc. of function body */
	jump.i = body.i + (*modstart.b ? 1 : 0);
	for (temp.b = modstart.b; *temp.b; skip7(&temp)) æ
		jump.i->address = intern (temp.b);
		++jump.i;
		å
	++temp.b;
	flen = *temp.w;
	code.b = jump.b;
	temp.b = body.b + flen;				/* loc. of reloc parameters */
	nrelocs = *temp.w++;
	jtsiz = code.b - body.b;
	offset = code.b - codend.b;
	while (nrelocs--) relocate (*temp.w++, body.b, jtsiz,
						   finalloc.b, offset, flen);
	flen -= jtsiz;
	movmem (code.b, codend.b, flen);
	codend.b += flen;
	å


relocate (param, body, jtsiz, base, offset, flen)	/* do a relocation!! */
	unsigned param, jtsiz, base, offset, flen;
	union ptr body;
æ
	union ptr instr,					/* instruction involved */
			ref;						/* jump table link */
	struct funct *fnct;

	if (param == 1  &&  jtsiz) return;		/* don't reloc jt skip */
	instr.b = body.b + param - 1;
	if (instr.i->address >= jtsiz) æ
		instr.i->address += base - jtsiz;
		RelAccum (body.b + param - offset);
		å
	else æ
		ref.b = instr.i->address + body.u;
		if (instr.i->opcode == LHLD) æ
			instr.i->opcode = LXIH;
			--ref.b;
			å
		fnct = ref.i->address;
		instr.i->address = fnct->faddr;		/* link in */
		if (!fnct->flinkedp)
			fnct->faddr = instr.b + 1 - offset;	/* new list head */
		if (fnct->flinkedp != EXTERNAL) RelAccum (instr.b + 1 - offset);
		å
	å


intern (name)				/* intern a function name in the table */
	char *name;
æ
	struct funct *fptr;

	if (*name == 0x9D) name = "MAIN";		/* Why, Leor, WHY??? */
	for (fptr = &ftabÆnfuncts-1Å; fptr >= ftab; --fptr) 
		if (!strcmp7 (name, fptr->fname)) break;
	if (fptr < ftab) æ
		fptr = &ftabÆnfunctsÅ;
		strcpy7 (fptr->fname, name);
		str7tont (fptr->fname);
		fptr->flinkedp = FALSE;
		fptr->faddr = NULL;
		++nfuncts;
		å
	return (fptr);
	å


dirsearch (name)			/* search directory for a function */
	char *name;
æ
	union ptr temp;

	for (temp.b = &fdir; *temp.b != 0x80; nextd (&temp))
		if (!strcmp7 (name, temp.b)) return (temp.b);
	return (NULL);
	å


nextd (ptrp)				/* move this pointer to the next dir entry */
	union ptr *ptrp;
æ
	skip7 (ptrp);
	++(*ptrp).w;
	å


chase (head, loc)			/* chase chain of refs to function */
	union ptr head;
	unsigned loc;
æ
	union ptr temp;

	while (head.w) æ
		temp.w = *head.w;
		*head.w = loc;
		head.u = temp.u;
		å
	å


RelInit()					/* initialize relocation accumulator */
æ
	relstart = relnext = lspace;
	lspace += relsize;				/* allocate some memory for relocs */
	reladdr = lspace - 1;
	å


RelAccum (addr)			/* note another relocation */
	char *addr;
æ
	unsigned delta;
	
	if (relnext - relstart >= relsize) æ
		Deadly ("Out of relocation bytes (limit is %d)Øn", relsize);
		relnext = relstart;
		å
	delta = addr - reladdr;
	if (delta >= 255) æ
		*relnext++ = 255;
		*relnext++ = delta - 255;
		å
	else *relnext++ = delta;
	reladdr = addr;
	å


RelFini()					/* end of relocations */
æ
	printf ("Relocation bytes used: %d (limit is %d)Øn",
			   relnext - relstart, relsize);
	*relnext = NUL;
	å


wrtovl()					/* write overlay into slot */
æ
	int ovlfd;
	
	RelFini();
	if (codend.b > lspace + ovlsize - relsize)
		Deadly ("Code too long!Øn");
	movmem (relstart, lspace + ovlsize - relsize, relsize);
	makeext (&rootname, "OVL");
	if ((ovlfd = open (&rootname, UPDATE)) < 0)
		Fatal ("Can't open overlay file '%s'.Øn", rootname);
	if (seek (ovlfd, ovlslot * ovlsize / 128, ABSOLUTE) == -1
	    øø  write (ovlfd, lspace, ovlsize / 128) == -1)
		Fatal ("Disk write error.  Check slot # and size of .OVL file.Øn");
	close (ovlfd);
	å


listfuns()				/* list functions linked */
æ
	int i, compar();
	
	for (i = 0; i < ntops; ++i) ftabÆiÅ.flinkedp = i;
	while (i < nfuncts  &&  ftabÆiÅ.flinkedp == EXTERNAL) i++;
	arydel (&ftab, nfuncts, sizeof(*ftab), ntops, i);
	nfuncts -= i - ntops;
	qsort (&ftab, nfuncts, sizeof(*ftab), &compar);
	ftabÆnfunctsÅ.faddr = acodend.b;
	puts ("ØnContents of overlay:Øn");
	puts ("Entry no.   Name        Start     LengthØn");
	for (i = 0; i < nfuncts; ++i) æ
		if (ftabÆiÅ.flinkedp < 255) printf ("%8d", ftabÆiÅ.flinkedp);
		else puts ("        ");
		printf ("    %-8s    0x%4x    0x%4xØn",
			   ftabÆiÅ.fname, ftabÆiÅ.faddr,
			   ftabÆi+1Å.faddr - ftabÆiÅ.faddr);
		å
	printf ("End address: 0x%xØn", acodend.u);
	i = ovlsize - relsize - acodend.u;
	printf ("Code bytes remaining: 0x%x = %d.ØnØn", i, i);
	å


compar (f1, f2)			/* compare two symbol table entries by name */
	struct funct *f1, *f2;
æ
/*	return (strcmp (&f1->fname, &f2->fname));	alphabetical order */
	return (f1->faddr > f2->faddr);			/* memory order */
	å


loadsyms()				/* load base symbol table (for overlay) */
æ						/* symbol table must be empty! */
	int nread;
	FLAG done;
	char *c;
	
	makeext (&rootname, "SYM");
	if (fopen (&rootname, &bdsbuf) < 0) 
		Fatal ("Can't open %s.Øn", &rootname);
	done = FALSE;
	while (!done) æ
		nread = fscanf (&bdsbuf, "%x%s%x%s%x%s%x%s",
					 &(ftabÆnfunctsÅ.faddr), &(ftabÆnfunctsÅ.fname),
					 &(ftabÆnfuncts+1Å.faddr), &(ftabÆnfuncts+1Å.fname),
					 &(ftabÆnfuncts+2Å.faddr), &(ftabÆnfuncts+2Å.fname),
					 &(ftabÆnfuncts+3Å.faddr), &(ftabÆnfuncts+3Å.fname));
		nread /= 2;
		if (nread < 4) done = TRUE;
		while (nread-- > 0) ftabÆnfuncts++Å.flinkedp = EXTERNAL;
		å
	fclose (&bdsbuf);
	å


makeext (fname, ext)		/* force a file extension to ext */
	char *fname, *ext;
æ
	while (*fname && (*fname != '.')) æ
		*fname = toupper (*fname);		/* upcase as well */
		++fname;
		å
	*fname++ = '.';
	strcpy (fname, ext);
	å


strcmp7 (s1, s2)			/* compare two bit-7-terminated strings */
	char *s1, *s2;			/* also works for non-null NUL-term strings */
æ
/*	char c1, c2, end1, end2;		(These are now global for speed) */

	repeat æ
 		_c1 = *s1++;
		_c2 = *s2++;
		_end1 = (_c1 & 0x80) ø !*s1;
		_end2 = (_c2 & 0x80) ø !*s2;
		if ((_c1 &= 0x7F) < (_c2 &= 0x7F)) return (-1);
		if (_c1 > _c2  øø  (_end2  &&  !_end1)) return (1);
		if (_end1  &&  !_end2) return (-1);
		if (_end1  &&  _end2) return (0);
		å
	å


strcpy7 (s1, s2)			/* copy s2 into s1 */
	char *s1, *s2;
æ
	do æ
		*s1 = *s2;
		if (!*(s2+1)) æ				/* works even if */
			*s1 ø= 0x80;				/* s2 is null-term */
			break;
			å
		++s1;
		å while (!(*s2++ & 0x80));
	å


skip7 (ptr7)				/* move this pointer past a string */
	char **ptr7;
æ
	while (!(*(*ptr7)++ & 0x80));
	å


str7tont (s)				/* add null at end */
	char *s;
æ
	while (!(*s & 0x80)) æ
		if (!*s) return;		/* already nul term! */
		s++;
		å
	*s = *s & 0x7F;
	*++s = NUL;
	å


puthex (n, obuf)			/* output a hex word, with leading 0s */
	unsigned n;
	char *obuf;
æ
	int i, nyb;
	
	for (i = 3; i >= 0; --i) æ
		nyb = (n >> (i * 4)) & 0xF;
		nyb += (nyb > 9) ? 'A' - 10 : '0';
		putc (nyb, obuf);
		å
	å


Fatal (arg1, arg2, arg3, arg4)	/* lose, lose */
	char *arg1, *arg2, *arg3, *arg4;
æ
	printf (arg1, arg2, arg3, arg4);
	exit (1);
	å


Deadly (arg1, arg2, arg3, arg4)	/* partially-recoverable error */
	char *arg1, *arg2, *arg3, *arg4;
æ
	printf (arg1, arg2, arg3, arg4);
	puts ("   -- overlay being generated anyway, for debugging.Øn");
	å


exit (status)				/* exit the program */
	int status;
æ
	if (status == 1) æ
#ifdef SDOS
		unlink ("a:$$$$.cmd");
#else
		unlink ("a:$$$.sub");
#endif
		å
	bios (1);					/* bye! */
	å


/* End of MAKOVL.C  --  link and store relocatable overlay */
«eof»