|
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 - 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»