home *** CD-ROM | disk | FTP | other *** search
- /* HEADER: CUG120.10;
- TITLE: L2;
- DATE: 00/00/1980;
- DESCRIPTION: "Variation of L2 that creats relocatable overlays
- according to an overlay descriptor file.";
- KEYWORDS: overlay,relocatable,linker;
- SYSTEM: CP/M;
- FILENAME: MAKOVL.C;
- CRC: 3A28;
- SEE-ALSO: CLINK;
- AUTHORS: Scott W. Layson;
- COMPILERS: BDS 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 */
- ext;
- {
- while (*fname && (*fname != '.')) {
- *fname = toupper (*fname); /* upcase as well */
- ++fname;
- }
- *fname++ =