|
|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 18816 (0x4980)
Types: TextFile
Names: »MAKOVL.C«
└─⟦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«
/* 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»