home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / BDSC / BDSC-2 / MAKOVL.CQ / MAKOVL.C
Text File  |  2000-06-30  |  19KB  |  767 lines

  1. /* MAKOVL.C    Overlay builder/manager
  2.  
  3.     This code is in the public domain.
  4.     Created from L2.C 81.10.29 Gyro
  5.  
  6. This is a variation on L2.C that creates relocatable overlays
  7. according to an overlay descriptor file.
  8.  
  9. Command format:
  10.  
  11.     makovl <root name> <overlay name> {<CRL file>} [-l {<CRL file>}] [-nd]
  12.  
  13. Overlay descriptor file, <root name>.DES, contains:
  14.  
  15.     <overlay slot size> <relocation info size>
  16.     <CRL file> ... (default search list)
  17.     ... (more default search list)
  18.     <blank line>
  19.     <overlay name> <slot number>
  20.         <function name>  <comments or whatnot>
  21.         <function name>  <comments or whatnot>
  22.         ... (an entry for each top-level function in the overlay)
  23.     <blank line>
  24.     <overlay name> <slot number>
  25.         <function name>  <comments or whatnot>
  26.         <function name>  <comments or whatnot>
  27.         ...
  28.     ... (an entry for each overlay in the file)
  29.  
  30.  
  31. Overlay segments are of length <overlay slot size> bytes, of which the
  32. last <relocation info size> bytes holds a list of relocation offsets. 
  33. This is a null-terminated string of byte values giving the difference
  34. between successive addresses to be relocated; a value of 255 means to
  35. add 255 to the next byte value to get the offset.  The first offset is
  36. relative to -1 (so that we can relocate the first word of the
  37. overlay).  At the beginning of the overlay is a table of addresses of
  38. top-level functions, one address for each function listed for that
  39. overlay in the descriptor file.
  40.  
  41. The -l option works as for L2: CRL files listed before the -l are
  42. loaded in entirety; those after are just scanned for needed functions. 
  43. Any functions specified in the default search list in the overlay
  44. descriptor file are also scanned, unless the -nd (no default) option
  45. is given.
  46.  
  47. The overlay, once created, is written into <root name>.OVL, at address
  48. <slot number> * <overlay slot size>.
  49.  
  50. */
  51.  
  52.  
  53. /**************** Globals ****************/
  54.  
  55. #define SDOS                /* comment this out for CP/M */
  56.  
  57. #include "bdscio.h"            /* for i/o buffer defs */
  58.  
  59. #define NUL        0
  60. #define FLAG        char
  61. #define repeat     while (1)
  62.  
  63. #define STDOUT        1
  64.  
  65.  
  66. /* function table */
  67. struct funct {
  68.     char fname[9];
  69.     FLAG flinkedp;            /* in memory already? */
  70.     char *faddr;            /* address of first ref link if not linked */
  71.     } ftab [300];
  72. int nfuncts;                /* no. of functions in table */
  73.  
  74. #define LINKED        255        /* (flinkedp) function really here */
  75. #define EXTERNAL    254        /* function defined in separate symbol table */
  76.  
  77. char fdir [512];            /* CRL file function directory */
  78.  
  79. /* command line parameters etc. */
  80. char rootname[15];            /* name of root program */
  81. char ovlname[40];            /* name of overlay to be built */
  82. int nprogs, nlibs;
  83. char progfiles [20] [15];    /* program file names */
  84. char libfiles [30] [15];        /* library file names */
  85. FLAG srchdefs;                /* search default libraries? */
  86.  
  87. /* overlay description */
  88. int ovlsize, relsize;        /* size of overlay slot & of relocation info */
  89. int ovlslot;                /* slot # to put overlay in */
  90. char topfuncts[10][32];        /* names of top level functions */
  91. int ntops;                /* number of top level functions */
  92. char *relstart;            /* beginning of relocation info */
  93. char *relnext;                /* next relocation value */
  94. char *reladdr;                /* last address relocated */
  95.  
  96.  
  97. /* useful things to have defined */
  98. struct inst {
  99.     char opcode;
  100.     char *address;
  101.     };
  102.  
  103. union ptr {
  104.     unsigned u;            /* an int */
  105.     unsigned *w;            /* a word ptr */
  106.     char *b;                /* a byte ptr */
  107.     struct inst *i;        /* an instruction ptr */
  108.     };
  109.  
  110.  
  111. /* Link control variables */
  112.  
  113. union ptr codend;            /* last used byte of code buffer + 1 */
  114. union ptr acodend;            /* actual code-end address */
  115. unsigned origin;            /* origin of code */
  116. unsigned buforg;            /* origin of code buffer */
  117.  
  118. char *lspace;                /* space to link in */
  119. char *lspcend;                /* end of link area */
  120. char *lodstart;            /* beginning of current file */
  121.  
  122.  
  123. /* i/o buffer */
  124. struct iobuf {
  125.     int fd;
  126.     int isect;            /* currently buffered sector */
  127.     int nextc;            /* index of next char in buffer */
  128.     char buff [128];
  129.     } ibuf, obuf;
  130.  
  131. /* BDS C i/o buffer */
  132. char bdsbuf[BUFSIZ];
  133.  
  134. /* seek opcodes */
  135. #define ABSOLUTE 0
  136. #define RELATIVE 1
  137.  
  138. #define INPUT 0
  139. #define UPDATE 2
  140.  
  141. #define TRUE (-1)
  142. #define FALSE 0
  143. #define NULL 0
  144.  
  145. /* 8080 instructions */
  146. #define LHLD 0x2A
  147. #define LXIH 0x21
  148. #define SPHL 0xF9
  149. #define JMP  0xC3
  150. #define CALL 0xCD
  151.  
  152. /* strcmp7 locals, made global for speed */
  153. char _c1, _c2, _end1, _end2;
  154.  
  155. /**************** End of Globals ****************/
  156.  
  157.  
  158.  
  159. main (argc, argv)
  160.     int argc;
  161.     char **argv;
  162. {
  163.     puts ("Mark of the Unicorn Overlay Builder, vsn. 1.0\n");
  164.     setup (argc, argv);
  165.     linkprog();
  166.     linklibs();
  167.     listfuns();
  168.     wrtovl();
  169.     }
  170.  
  171.  
  172. setup (argc, argv)            /* initialize function table, etc. */
  173.     int argc;
  174.     char **argv;
  175. {
  176.     nprogs = 0;
  177.     nlibs = 0;
  178.     origin = buforg = 0;
  179.     nfuncts = 0;
  180.     srchdefs = TRUE;
  181.     cmdline (argc, argv);
  182.     lspace = endext();
  183.     lspcend = topofmem() - 1024;
  184.     getdesc();
  185.     loadsyms();
  186.     }
  187.  
  188.  
  189. cmdline (argc, argv)        /* process command line */
  190.     int argc;
  191.     char **argv;
  192. {
  193.     int i, progp;
  194.  
  195.     if (argc <= 2) {
  196.         puts ("Usage is:\n");
  197.         puts ("  makovl <root name> <overlay name> {<CRL file>} [-l {<CRL file>}]");
  198.         exit (1);
  199.         }
  200.     strcpy (&rootname, argv[1]);
  201.     strcpy (&ovlname, argv[2]);
  202.     progp = TRUE;
  203.     for (i = 3; i < argc; ++i) {
  204.         if (argv[i][0] == '-') {
  205.             if (!strcmp (argv[i], "-L")) progp = FALSE;
  206.             else if (match (argv[i], "-ND")) srchdefs = FALSE;
  207.             else printf ("Unknown option: '%s'\n", argv[i]);
  208.             }
  209.         else {
  210.             if (progp) strcpy (&progfiles[nprogs++], argv[i]);
  211.             else strcpy (&libfiles[nlibs++], argv[i]);
  212.             }
  213.         }
  214.     }
  215.  
  216.  
  217. getdesc()                    /* get & process overlay description */
  218. {
  219.     makeext (&rootname, "DES");
  220.     if (fopen (&rootname, &bdsbuf) < 0)
  221.         Fatal ("Can't open overlay descriptor file '%s'.\n", &rootname);
  222.     if (fscanf (&bdsbuf, "%d%d", &ovlsize, &relsize) < 2
  223.         ||  ovlsize <= relsize) {
  224.         Fatal ("Error in descriptor file: bad overlay/relocation sizes.\n");
  225.         }
  226.     getlibs();
  227.     findovl();
  228.     readfuns();
  229.     fclose (&bdsbuf);
  230.     }
  231.  
  232.  
  233. getlibs()                    /* get default search list */
  234. {
  235.     char line[MAXLINE], *cp, *dest;
  236.     
  237.     repeat {
  238.         if (!fgets (&line, &bdsbuf)  ||  !line[0]) break;
  239.         if (!srchdefs) continue;
  240.         cp = &line;
  241.         repeat {
  242.             while (isspace (*cp)) ++cp;
  243.             if (!*cp) break;
  244.             dest = &libfiles[nlibs++];
  245.             while (*cp  &&  !isspace (*cp)) *dest++ = *cp++;
  246.             *dest = NUL;
  247.             }
  248.         }
  249.     }
  250.  
  251.  
  252. findovl()                    /* find description of overlay */
  253. {
  254.     char tname[40];
  255.     int nread;
  256.     FLAG skipping, found;
  257.     
  258.     skipping = found = FALSE;
  259.     while (!found
  260.           &&  (nread = fscanf (&bdsbuf, "%s%d", &tname, &ovlslot)) >= 0) {
  261.         if (nread) {
  262.             if (!skipping) {
  263.                 if (match (&tname, &ovlname)) found = TRUE;
  264.                 else skipping = TRUE;
  265.                 }
  266.             }
  267.         else skipping = FALSE;
  268.         }
  269.     if (!found)
  270.         Fatal ("Can't find description of overlay '%s'.\n", &ovlname);
  271.     if (nread < 2) 
  272.         Fatal ("No slot number present for overlay '%s'.\n", &tname);
  273.     printf ("Building overlay %s, for slot %d.\n", &tname, ovlslot);
  274.     }
  275.  
  276.  
  277. readfuns()
  278. {
  279.     char tname[40];
  280.     struct funct *fnct;
  281.     
  282.     ntops = 0;
  283.     RelInit();
  284.     codend.b = lspace;                /* build table of functions */
  285.     puts ("Functions included:\n");
  286.     while (fscanf (&bdsbuf, "%s", &tname) > 0) {
  287.         printf ("%-10s", &tname);
  288.         upcase (&tname);
  289.         tname[8] = NUL;            /* limit size */
  290.         fnct = intern (&tname);
  291.         *codend.w = fnct->faddr;        /* link in reference */
  292.         RelAccum (codend.w);        /* relocate this address */
  293.         fnct->faddr = codend.w++;
  294.         ntops++;
  295.         }
  296.     puts ("\n\n");
  297.     }
  298.  
  299.  
  300. linkprog()                /* link in all program files */
  301. {
  302.     int i;
  303.     union ptr dirtmp;
  304.     struct funct *fnct;
  305.  
  306.     for (i=0; i<nprogs; ++i) {
  307.         makeext (&progfiles[i], "CRL");
  308.         if (copen (&ibuf, progfiles[i]) < 0) {
  309.             printf ("Can't open %s\n", progfiles[i]);
  310.             continue;
  311.             }
  312.         printf ("Loading %s\n", &progfiles[i]);
  313.         readprog (i==0);
  314.         for (dirtmp.b=&fdir; *dirtmp.b != 0x80;) {
  315.             fnct = intern (dirtmp.b);            /* for each module */
  316.             skip7 (&dirtmp);                    /* in directory */
  317.             if (!fnct->flinkedp)
  318.                 linkmod (fnct, lodstart + *dirtmp.w - 0x205);
  319.             else {
  320.                 puts ("  Duplicate program function '");
  321.                 puts (&fnct->fname);
  322.                 puts ("', not linked.\n");
  323.                 }
  324.             dirtmp.w++;
  325.             }                                /* intern & link it */
  326.         cclose (&ibuf);
  327.         }
  328.     }
  329.  
  330.  
  331. linklibs()                /* link in library files */
  332. {
  333.     int ifile;
  334.  
  335.     for (ifile = 0; ifile < nlibs; ++ifile) scanlib (ifile);
  336.     while (missingp()) {
  337.         puts ("Enter the name of a file to be searched: ");
  338.         gets (&libfiles[nlibs]);
  339.         upcase (&libfiles[nlibs]);
  340.         scanlib (nlibs++);
  341.         }
  342.     acodend.b = codend.b - lspace + buforg;        /* save that number! */
  343.     }
  344.  
  345.  
  346. missingp()                /* are any functions missing?  print them out */
  347. {
  348.     int i, foundp;
  349.  
  350.     foundp = FALSE;
  351.     for (i=0; i<nfuncts; ++i)
  352.         if (!ftab[i].flinkedp) {
  353.             if (!foundp) puts ("*** Missing functions:\n");
  354.             puts (&ftab[i].fname);
  355.             puts ("\n");
  356.             foundp = TRUE;
  357.             }
  358.     return (foundp);
  359.     }
  360.  
  361.  
  362. readprog (mainp)            /* read in a program file */
  363.     FLAG mainp;
  364. {
  365.     char extp;                            /* was -e used? */
  366.     char *extstmp;
  367.     union ptr dir;
  368.     unsigned len;
  369.  
  370.     if (cread (&ibuf, &fdir, 512) < 512)            /* read directory */
  371.         Fatal ("-- read error!\n");
  372.     cseek (&ibuf, 5, RELATIVE);
  373.     for (dir.b=&fdir; *dir.b != 0x80; nextd (&dir));    /* find end of dir */
  374.     ++dir.b;
  375.     len = *dir.w - 0x205;
  376.     readobj (len);
  377.     }
  378.  
  379.  
  380. readobj (len)                /* read in an object (program or lib funct) */
  381.     unsigned len;
  382. {
  383.     if (codend.b + len >= lspcend) Fatal ("-- out of memory!\n");
  384.     lodstart = codend.b;
  385.     if (cread (&ibuf, lodstart, len) < len)
  386.         Fatal ("-- read error (read 0x%x)!\n", len);
  387.     }
  388.  
  389.  
  390. scanlib (ifile)
  391.     int ifile;
  392. {
  393.     int i;
  394.     union ptr dirtmp;
  395.  
  396.     makeext (&libfiles[ifile], "CRL");
  397.     if (copen (&ibuf, libfiles[ifile]) < 0) {
  398.         printf ("Can't open %s\n", libfiles[ifile]);
  399.         return;
  400.         }
  401.     printf ("Scanning %s\n", &libfiles[ifile]);
  402.     if (cread (&ibuf, &fdir, 512) < 512)    /* read directory */
  403.         Fatal ("-- Read error (directory)!\n");
  404.     for (i=0; i<nfuncts; ++i) {            /* scan needed functions */
  405.         if (!ftab[i].flinkedp
  406.             && (dirtmp.b = dirsearch (&ftab[i].fname))) {
  407.             readfunct (dirtmp.b);
  408.             linkmod (&ftab[i], lodstart);
  409.             }
  410.         }
  411.     cclose (&ibuf);
  412.     }
  413.  
  414.  
  415. readfunct (direntry)            /* read a function (from a library) */
  416.     union ptr direntry;
  417. {
  418.     unsigned start, len;
  419.  
  420.     skip7 (&direntry);
  421.     start = *direntry.w++;
  422.     skip7 (&direntry);
  423.     len = *direntry.w - start;
  424.     if (cseek (&ibuf, start, ABSOLUTE) < 0)
  425.         Fatal (" -- read error (seek 0x%x)!", start);
  426.     readobj (len);
  427.     }
  428.  
  429.  
  430. linkmod (fnct, modstart)            /* link in a module */
  431.     struct funct *fnct;
  432.     union ptr    modstart;                    /* loc. of module in memory */
  433.  
  434. {
  435.     union ptr temp,
  436.             jump,                    /* jump table temp */
  437.             body,                    /* loc. of function in memory */
  438.             code,                    /* loc. of code proper in mem. */
  439.             finalloc;                    /* runtime loc. of function */
  440.     unsigned flen, nrelocs, jtsiz, offset;
  441.  
  442.     fnct->flinkedp = LINKED;
  443.     finalloc.b = codend.b - lspace + buforg;
  444.     chase (fnct->faddr, finalloc.b);
  445.     fnct->faddr = finalloc.b;
  446.     body.b = modstart.b + strlen(modstart.b) + 3; /* loc. of function body */
  447.     jump.i = body.i + (*modstart.b ? 1 : 0);
  448.     for (temp.b = modstart.b; *temp.b; skip7(&temp)) {
  449.         jump.i->address = intern (temp.b);
  450.         ++jump.i;
  451.         }
  452.     ++temp.b;
  453.     flen = *temp.w;
  454.     code.b = jump.b;
  455.     temp.b = body.b + flen;                /* loc. of reloc parameters */
  456.     nrelocs = *temp.w++;
  457.     jtsiz = code.b - body.b;
  458.     offset = code.b - codend.b;
  459.     while (nrelocs--) relocate (*temp.w++, body.b, jtsiz,
  460.                            finalloc.b, offset, flen);
  461.     flen -= jtsiz;
  462.     movmem (code.b, codend.b, flen);
  463.     codend.b += flen;
  464.     }
  465.  
  466.  
  467. relocate (param, body, jtsiz, base, offset, flen)    /* do a relocation!! */
  468.     unsigned param, jtsiz, base, offset, flen;
  469.     union ptr body;
  470. {
  471.     union ptr instr,                    /* instruction involved */
  472.             ref;                        /* jump table link */
  473.     struct funct *fnct;
  474.  
  475.     if (param == 1  &&  jtsiz) return;        /* don't reloc jt skip */
  476.     instr.b = body.b + param - 1;
  477.     if (instr.i->address >= jtsiz) {
  478.         instr.i->address += base - jtsiz;
  479.         RelAccum (body.b + param - offset);
  480.         }
  481.     else {
  482.         ref.b = instr.i->address + body.u;
  483.         if (instr.i->opcode == LHLD) {
  484.             instr.i->opcode = LXIH;
  485.             --ref.b;
  486.             }
  487.         fnct = ref.i->address;
  488.         instr.i->address = fnct->faddr;        /* link in */
  489.         if (!fnct->flinkedp)
  490.             fnct->faddr = instr.b + 1 - offset;    /* new list head */
  491.         if (fnct->flinkedp != EXTERNAL) RelAccum (instr.b + 1 - offset);
  492.         }
  493.     }
  494.  
  495.  
  496. intern (name)                /* intern a function name in the table */
  497.     char *name;
  498. {
  499.     struct funct *fptr;
  500.  
  501.     if (*name == 0x9D) name = "MAIN";        /* Why, Leor, WHY??? */
  502.     for (fptr = &ftab[nfuncts-1]; fptr >= ftab; --fptr) 
  503.         if (!strcmp7 (name, fptr->fname)) break;
  504.     if (fptr < ftab) {
  505.         fptr = &ftab[nfuncts];
  506.         strcpy7 (fptr->fname, name);
  507.         str7tont (fptr->fname);
  508.         fptr->flinkedp = FALSE;
  509.         fptr->faddr = NULL;
  510.         ++nfuncts;
  511.         }
  512.     return (fptr);
  513.     }
  514.  
  515.  
  516. dirsearch (name)            /* search directory for a function */
  517.     char *name;
  518. {
  519.     union ptr temp;
  520.  
  521.     for (temp.b = &fdir; *temp.b != 0x80; nextd (&temp))
  522.         if (!strcmp7 (name, temp.b)) return (temp.b);
  523.     return (NULL);
  524.     }
  525.  
  526.  
  527. nextd (ptrp)                /* move this pointer to the next dir entry */
  528.     union ptr *ptrp;
  529. {
  530.     skip7 (ptrp);
  531.     ++(*ptrp).w;
  532.     }
  533.  
  534.  
  535. chase (head, loc)            /* chase chain of refs to function */
  536.     union ptr head;
  537.     unsigned loc;
  538. {
  539.     union ptr temp;
  540.  
  541.     while (head.w) {
  542.         temp.w = *head.w;
  543.         *head.w = loc;
  544.         head.u = temp.u;
  545.         }
  546.     }
  547.  
  548.  
  549. RelInit()                    /* initialize relocation accumulator */
  550. {
  551.     relstart = relnext = lspace;
  552.     lspace += relsize;                /* allocate some memory for relocs */
  553.     reladdr = lspace - 1;
  554.     }
  555.  
  556.  
  557. RelAccum (addr)            /* note another relocation */
  558.     char *addr;
  559. {
  560.     unsigned delta;
  561.     
  562.     if (relnext - relstart >= relsize) {
  563.         Deadly ("Out of relocation bytes (limit is %d)\n", relsize);
  564.         relnext = relstart;
  565.         }
  566.     delta = addr - reladdr;
  567.     if (delta >= 255) {
  568.         *relnext++ = 255;
  569.         *relnext++ = delta - 255;
  570.         }
  571.     else *relnext++ = delta;
  572.     reladdr = addr;
  573.     }
  574.  
  575.  
  576. RelFini()                    /* end of relocations */
  577. {
  578.     printf ("Relocation bytes used: %d (limit is %d)\n",
  579.                relnext - relstart, relsize);
  580.     *relnext = NUL;
  581.     }
  582.  
  583.  
  584. wrtovl()                    /* write overlay into slot */
  585. {
  586.     int ovlfd;
  587.     
  588.     RelFini();
  589.     if (codend.b > lspace + ovlsize - relsize)
  590.         Deadly ("Code too long!\n");
  591.     movmem (relstart, lspace + ovlsize - relsize, relsize);
  592.     makeext (&rootname, "OVL");
  593.     if ((ovlfd = open (&rootname, UPDATE)) < 0)
  594.         Fatal ("Can't open overlay file '%s'.\n", rootname);
  595.     if (seek (ovlfd, ovlslot * ovlsize / 128, ABSOLUTE) == -1
  596.         ||  write (ovlfd, lspace, ovlsize / 128) == -1)
  597.         Fatal ("Disk write error.  Check slot # and size of .OVL file.\n");
  598.     close (ovlfd);
  599.     }
  600.  
  601.  
  602. listfuns()                /* list functions linked */
  603. {
  604.     int i, compar();
  605.     
  606.     for (i = 0; i < ntops; ++i) ftab[i].flinkedp = i;
  607.     while (i < nfuncts  &&  ftab[i].flinkedp == EXTERNAL) i++;
  608.     arydel (&ftab, nfuncts, sizeof(*ftab), ntops, i);
  609.     nfuncts -= i - ntops;
  610.     qsort (&ftab, nfuncts, sizeof(*ftab), &compar);
  611.     ftab[nfuncts].faddr = acodend.b;
  612.     puts ("\nContents of overlay:\n");
  613.     puts ("Entry no.   Name        Start     Length\n");
  614.     for (i = 0; i < nfuncts; ++i) {
  615.         if (ftab[i].flinkedp < 255) printf ("%8d", ftab[i].flinkedp);
  616.         else puts ("        ");
  617.         printf ("    %-8s    0x%4x    0x%4x\n",
  618.                ftab[i].fname, ftab[i].faddr,
  619.                ftab[i+1].faddr - ftab[i].faddr);
  620.         }
  621.     printf ("End address: 0x%x\n", acodend.u);
  622.     i = ovlsize - relsize - acodend.u;
  623.     printf ("Code bytes remaining: 0x%x = %d.\n\n", i, i);
  624.     }
  625.  
  626.  
  627. compar (f1, f2)            /* compare two symbol table entries by name */
  628.     struct funct *f1, *f2;
  629. {
  630. /*    return (strcmp (&f1->fname, &f2->fname));    alphabetical order */
  631.     return (f1->faddr > f2->faddr);            /* memory order */
  632.     }
  633.  
  634.  
  635. loadsyms()                /* load base symbol table (for overlay) */
  636. {                        /* symbol table must be empty! */
  637.     int nread;
  638.     FLAG done;
  639.     char *c;
  640.     
  641.     makeext (&rootname, "SYM");
  642.     if (fopen (&rootname, &bdsbuf) < 0) 
  643.         Fatal ("Can't open %s.\n", &rootname);
  644.     done = FALSE;
  645.     while (!done) {
  646.         nread = fscanf (&bdsbuf, "%x%s%x%s%x%s%x%s",
  647.                      &(ftab[nfuncts].faddr), &(ftab[nfuncts].fname),
  648.                      &(ftab[nfuncts+1].faddr), &(ftab[nfuncts+1].fname),
  649.                      &(ftab[nfuncts+2].faddr), &(ftab[nfuncts+2].fname),
  650.                      &(ftab[nfuncts+3].faddr), &(ftab[nfuncts+3].fname));
  651.         nread /= 2;
  652.         if (nread < 4) done = TRUE;
  653.         while (nread-- > 0) ftab[nfuncts++].flinkedp = EXTERNAL;
  654.         }
  655.     fclose (&bdsbuf);
  656.     }
  657.  
  658.  
  659. makeext (fname, ext)        /* force a file extension to ext */
  660.     char *fname, *ext;
  661. {
  662.     while (*fname && (*fname != '.')) {
  663.         *fname = toupper (*fname);        /* upcase as well */
  664.         ++fname;
  665.         }
  666.     *fname++ = '.';
  667.     strcpy (fname, ext);
  668.     }
  669.  
  670.  
  671. strcmp7 (s1, s2)            /* compare two bit-7-terminated strings */
  672.     char *s1, *s2;            /* also works for non-null NUL-term strings */
  673. {
  674. /*    char c1, c2, end1, end2;        (These are now global for speed) */
  675.  
  676.     repeat {
  677.          _c1 = *s1++;
  678.         _c2 = *s2++;
  679.         _end1 = (_c1 & 0x80) | !*s1;
  680.         _end2 = (_c2 & 0x80) | !*s2;
  681.         if ((_c1 &= 0x7F) < (_c2 &= 0x7F)) return (-1);
  682.         if (_c1 > _c2  ||  (_end2  &&  !_end1)) return (1);
  683.         if (_end1  &&  !_end2) return (-1);
  684.         if (_end1  &&  _end2) return (0);
  685.         }
  686.     }
  687.  
  688.  
  689. strcpy7 (s1, s2)            /* copy s2 into s1 */
  690.     char *s1, *s2;
  691. {
  692.     do {
  693.         *s1 = *s2;
  694.         if (!*(s2+1)) {                /* works even if */
  695.             *s1 |= 0x80;                /* s2 is null-term */
  696.             break;
  697.             }
  698.         ++s1;
  699.         } while (!(*s2++ & 0x80));
  700.     }
  701.  
  702.  
  703. skip7 (ptr7)                /* move this pointer past a string */
  704.     char **ptr7;
  705. {
  706.     while (!(*(*ptr7)++ & 0x80));
  707.     }
  708.  
  709.  
  710. str7tont (s)                /* add null at end */
  711.     char *s;
  712. {
  713.     while (!(*s & 0x80)) {
  714.         if (!*s) return;        /* already nul term! */
  715.         s++;
  716.         }
  717.     *s = *s & 0x7F;
  718.     *++s = NUL;
  719.     }
  720.  
  721.  
  722. puthex (n, obuf)            /* output a hex word, with leading 0s */
  723.     unsigned n;
  724.     char *obuf;
  725. {
  726.     int i, nyb;
  727.     
  728.     for (i = 3; i >= 0; --i) {
  729.         nyb = (n >> (i * 4)) & 0xF;
  730.         nyb += (nyb > 9) ? 'A' - 10 : '0';
  731.         putc (nyb, obuf);
  732.         }
  733.     }
  734.  
  735.  
  736. Fatal (arg1, arg2, arg3, arg4)    /* lose, lose */
  737.     char *arg1, *arg2, *arg3, *arg4;
  738. {
  739.     printf (arg1, arg2, arg3, arg4);
  740.     exit (1);
  741.     }
  742.  
  743.  
  744. Deadly (arg1, arg2, arg3, arg4)    /* partially-recoverable error */
  745.     char *arg1, *arg2, *arg3, *arg4;
  746. {
  747.     printf (arg1, arg2, arg3, arg4);
  748.     puts ("   -- overlay being generated anyway, for debugging.\n");
  749.     }
  750.  
  751.  
  752. exit (status)                /* exit the program */
  753.     int status;
  754. {
  755.     if (status == 1) {
  756. #ifdef SDOS
  757.         unlink ("a:$$$$.cmd");
  758. #else
  759.         unlink ("a:$$$.sub");
  760. #endif
  761.         }
  762.     bios (1);                    /* bye! */
  763.     }
  764.  
  765.  
  766. /* End of MAKOVL.C  --  link and store relocatable overlay */
  767.