|
DataMuseum.dkPresents historical artifacts from the history of: Jet Computer Jet80 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Jet Computer Jet80 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 22400 (0x5780) Types: TextFile Names: »L2.C«
└─⟦1275f6521⟧ Bits:30005823 BD Software C Compiler v1.50a └─ ⟦this⟧ »L2.C«
/* ******** * L2.C * New linker for BDS C ******** Written 1980 by Scott W. Layson Modified 1982 by David Kirkland This code is in the public domain. This is an improved linker for BDS C CRL format. It supports the c debugger. Compilation instructions: cc l2.c -e4C00 (use -e4900 if linking with L2.COM) cc chario.c clink l2 chario -ns (or) l2 l2 chario -ns */ /**************** Globals ****************/ /* The DEF_DRIVE macro is used to define the drive from which L2 will * load C.CCC, DEFF.CRL, DEFF2.CRL, and DEFF3.CRL (if it exists). The * macro takes as an argument the filename and extension, and "returns" * the name with whatever drive designator is needed. The macro also * encloses the name in quotes; thus, the argument when the macro is * invoked must NOT be within quotes. * That is, to open C.CCC on the proper drive, we use the C code * if (ERROR==fopen(DEF_DRIVE(C.CCC), iobuf)) ..... */ #define DEF_DRIVE(fn) "fn" /* Make this "0/A:fn" for, say, user 0 on A */ #define SUB_FILE "$$$.SUB" /* submit file to delete on error exit... * if you use SDOS, use "a:$$$$.sub"; if you've * hacked your CCP, you may need to change the * drive designator letter */ #define RST_NUM 6 /* C debugger RST number. Should be identical to the RSTNUM symbol in CCC.ASM */ #define OVERLAYS /* comment this out for shorter version */ /* #define MARC /* for MARC cross-linker version (enables the "-marc" option) */ */ #include <bdscio.h> /* for i/o buffer defs */ #define NUL 0 #define FLAG char #define repeat while (1) #define STDOUT 1 /* Phase control */ #define INMEM 1 /* while everything still fits */ #define DISK1 2 /* overflow; finish building table */ #define DISK2 3 /* use table to do window link */ int phase; /* function table */ struct funct æ char fnameÆ9Å; FLAG flinkedp; /* in memory already? */ FLAG fdebug; /* TRUE unless this routine required only by a lib function after -s */ char *faddr; /* address of first ref link if not linked */ å *ftab; int nfuncts; /* no. of functions in table */ int maxfuncts; /* table size */ #define LINKED 1 /* (flinkedp) function really here */ #define EXTERNAL 2 /* function defined in separate symbol table */ char fdir Æ512Å; /* CRL file function directory */ /* command line parameters etc. */ int nprogs, nlibs; char progfiles Æ30Å Æ15Å; /* program file names */ char libfiles Æ20Å Æ15Å; /* library file names */ int deflibindex; /* index of first default (DEFF*) library */ FLAG symsp, /* write symbols to .sym file? */ appstatsp, /* append stats to .sym file? */ sepstatsp; /* write stats to .lnk file? */ #ifdef MARC FLAG maxmemp, /* punt MARC shell? */ marcp; /* uses CM.CCC */ #endif char mainfunctÆ10Å; FLAG ovlp; /* make overlay? */ char symsfile Æ15Å; /* file to load symbols from (for overlays) */ /* C debugger variables */ FLAG Dflag; FLAG SysStat; /* TRUE if "-s" option given & now active */ int SysNum; /* index into libfiles of "-s", or -1 if none */ FLAG Tflag; /* TRUE if "-t" option given */ unsigned Tval; /* arg to "-t", if present */ /* 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 exts; /* start of externals */ union ptr acodend; /* actual code-end address */ unsigned extspc; /* size of externals */ unsigned origin; /* origin of code */ unsigned buforg; /* origin of code buffer */ unsigned jtsaved; /* bytes of jump table saved */ 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 symbufÆBUFSIZÅ; /* seek opcodes */ #define ABSOLUTE 0 #define RELATIVE 1 #define INPUT 0 #define TRUE (-1) #define FALSE 0 #define NULL 0 /* 8080 instructions */ #define LHLD 0x2A #define LXISP 0x31 #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 Linker ver. 2.2.2Øn"); setup (argc, argv); linkprog(); linklibs(); if (phase == DISK1) rescan(); else wrtcom(); if (symsp) wrtsyms(); å setup (argc, argv) /* initialize function table, etc. */ int argc; char **argv; æ symsp = appstatsp = sepstatsp = FALSE; /* default options */ #ifdef MARC marcp = maxmemp = FALSE; #endif ovlp = FALSE; nprogs = 0; nlibs = 0; strcpy (&mainfunct, "MAIN"); /* default top-level function */ origin = 0x100; /* default origin */ maxfuncts = 200; /* default function table size */ Tflag = FALSE; /* no "-t" given yet */ SysStat = FALSE; SysNum = -1; Dflag = FALSE; cmdline (argc, argv); ftab = endext(); lspace = ftab + maxfuncts; lspcend = topofmem() - (1024 + 2100); if (lspace > lspcend) Fatal ("Insufficient memory to do anything at all!Øn"); loadccc(); nfuncts = 0; #ifdef OVERLAYS if (ovlp) loadsyms(); #endif intern (&mainfunct); phase = INMEM; buforg = origin; jtsaved = 0; å cmdline (argc, argv) /* process command line */ int argc; char **argv; æ int i, progp, syslib; if (argc == 1) æ puts ("Usage is:Øn"); puts (" l2 æprogram fileså Æ-l ælibrary fileså Å "); puts ("Æ-s ælibrary fileså ÅØn"); puts ("ØtÆ-m <main_name>Å Æ-f <maxfuncts>Å Æ-org <addr>Å"); puts (" Æ-t <addr>ÅØn"); puts ("ØtÆ-dÅ Æ-nsÅ Æ-w ø -wa ø -wsÅØn"); #ifdef OVERLAYS puts ("ØtÆ-ovl <rootname> <addr>Å"); #endif #ifdef MARC puts ("ØtÆ-marcÅ"); #endif lexit (1); å syslib = TRUE; progp = TRUE; for (i=1; i < argc; ++i) æ if (argvÆiÅÆ0Å == '-') æ if (!strcmp (argvÆiÅ, "-F")) æ if (++i>=argc) Fatal ("-f argument missing.Øn"); sscanf (argvÆiÅ, "%d", &maxfuncts); å else if (!strcmp (argvÆiÅ, "-L")) progp = FALSE; else if (!strcmp (argvÆiÅ, "-S")) æ progp = FALSE; SysNum = nlibs; å else if (!strcmp (argvÆiÅ, "-M")) æ if (++i>=argc) Fatal ("-m argument missing.Øn"); strcpy (&mainfunct, argvÆiÅ); å #ifdef MARC else if (!strcmp (argvÆiÅ, "-MARC")) æ maxmemp = TRUE; marcp = TRUE; å #endif else if (!strcmp (argvÆiÅ, "-ORG")) æ if (++i>=argc) Fatal ("-org argument missing.Øn"); sscanf (argvÆiÅ, "%x", &origin); å else if (!strcmp (argvÆiÅ, "-T")) æ if (++i >= argc) Fatal ("-t argument missing.Øn"); Tflag = TRUE; sscanf (argvÆiÅ, "%x", &Tval); å #ifdef OVERLAYS else if (!strcmp (argvÆiÅ, "-OVL")) æ ovlp = TRUE; if (i + 2 >= argc) Fatal ("-ovl argument missing.Øn"); strcpy (&symsfile, argvÆ++iÅ); sscanf (argvÆ++iÅ, "%x", &origin); å #endif else if (!strcmp (argvÆiÅ, "-D")) Dflag = TRUE; else if (!strcmp (argvÆiÅ, "-W")) symsp = TRUE; else if (!strcmp (argvÆiÅ, "-WA")) symsp = appstatsp = TRUE; else if (!strcmp (argvÆiÅ, "-WS")) symsp = sepstatsp = TRUE; else if (!strcmp (argvÆiÅ, "-NS")) syslib = FALSE; else printf ("Unknown option: '%s'Øn", argvÆiÅ); å else æ if (progp) strcpy (&progfilesÆnprogs++Å, argvÆiÅ); else strcpy (&libfilesÆnlibs++Å, argvÆiÅ); å å if (ovlp) strcpy(&mainfunct, &progfilesÆ0ÅÆ2*(progfilesÆ0ÅÆ1Å==':')Å ); if (Dflag øø !syslib øø SysNum!=-1) Dflag = symsp = TRUE; if (syslib && SysNum == -1) SysNum = nlibs; #define NDEFF 3 deflibindex = nlibs; #ifdef MARC strcpy (&libfilesÆnlibs++Å, marcp ? "DEFFM" : "DEFF"); strcpy (&libfilesÆnlibs++Å, marcp ? "DEFF2M" : "DEFF2"); strcpy (&libfilesÆnlibs++Å, marcp ? "DEFF3M" : "DEFF3"); #else strcpy (&libfilesÆnlibs++Å, DEF_DRIVE(DEFF) ); strcpy (&libfilesÆnlibs++Å, DEF_DRIVE(DEFF2) ); strcpy (&libfilesÆnlibs++Å, DEF_DRIVE(DEFF3) ); #endif å loadccc() /* load C.CCC (runtime library) */ æ union ptr temp; unsigned len; codend.b = lspace; if (!ovlp) æ #ifdef MARC if (copen (&ibuf, marcp ? "CM.CCC" : "C.CCC") < 0) #else if (copen (&ibuf, DEF_DRIVE(C.CCC) ) < 0) #endif Fatal ("Can't open %sØn",DEF_DRIVE(C.CCC)); if (cread (&ibuf, lspace, 128) < 128) /* read a sector */ Fatal ("%s: read error!Øn",DEF_DRIVE(C.CCC)); temp.b = lspace + 0x17; len = *temp.w; /* how long is it? */ cread (&ibuf, lspace + 128, len - 128); /* read rest */ codend.b += len; cclose (&ibuf); å else codend.i++->opcode = JMP; å 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 if (phase != DISK2) æ 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) æ if (ifile==SysNum) SysStat = TRUE; scanlib (ifile); å while (missingp()) æ puts ("Enter the name of a file to be searched or CR: "); gets (&libfilesÆnlibsÅ); if (libfilesÆnlibsÅÆ0Å) æ SysStat = FALSE; scanlib (nlibs); å else æ if (SysNum!=-1) SysStat = TRUE; for (ifile=0; ifile<NDEFF; ++ifile) scanlib (deflibindex + ifile); å å acodend.b = codend.b - lspace + buforg; /* save that number! */ if (!exts.b) exts.b = acodend.b; å 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); å rescan() /* perform second disk phase */ æ int i; for (i=0; i < nfuncts; ++i) if (ftabÆiÅ.flinkedp == LINKED) ftabÆiÅ.flinkedp = FALSE; phase = DISK2; buforg = origin; puts ("ØnØn**** Beginning second disk pass ****Øn"); if (!ovlp) makeext (&progfilesÆ0Å, "COM"); else makeext (&progfilesÆ0Å, "OVL"); ccreat (&obuf, &progfilesÆ0Å); loadccc(); hackccc(); linkprog(); linklibs(); if (cwrite (&obuf, lspace, codend.b - lspace) == -1 øø cflush (&obuf) < 0) Fatal ("Disk write error!Øn"); cclose (&obuf); stats (STDOUT); å 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"); if (phase == INMEM && mainp) æ cread (&ibuf, &extp, 1); cread (&ibuf, &extstmp, 2); cread (&ibuf, &extspc, 2); if (extp) exts.b = extstmp; else exts.b = 0; /* will be set later */ å else 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 (phase == DISK1 øø codend.b + len >= lspcend) æ if (phase == INMEM) æ puts("Øn** Out of memory--switching to disk mode **Øn"); phase = DISK1; å if (phase == DISK2) æ if (cwrite (&obuf, lspace, codend.b - lspace) == -1) Fatal ("Disk write error!Øn"); å buforg += codend.b - lspace; codend.b = lspace; if (codend.b + len >= lspcend) Fatal ("Module won't fit in memory at all!Øn"); å lodstart = codend.b; if (cread (&ibuf, lodstart, len) < len) Fatal ("-- read error!Øn"); å scanlib (ifile) int ifile; æ int i; union ptr dirtmp; makeext (&libfilesÆifileÅ, "CRL"); if (copen (&ibuf, libfilesÆifileÅ) < 0) æ if (ifile != deflibindex + (NDEFF-1)) 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!Ø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!"); 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; if (phase != DISK2) æ finalloc.b = codend.b - lspace + buforg; if (phase == INMEM) chase (fnct->faddr, finalloc.b); fnct->faddr = finalloc.b; å else finalloc.b = fnct->faddr; body.b = modstart.b + strlen(modstart.b) + 3; /* loc. of fn 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; if (Dflag && fnct->fdebug) æ if (phase!=DISK1) æ codend.i->opcode = (0307 + (8*RST_NUM)); codend.i->address = 0; finalloc.b += 3; å codend.b += 3; å offset = code.b - codend.b; if (phase != DISK1) while (nrelocs--) relocate (*temp.w++, body.b, jtsiz, finalloc.b, offset, flen); flen -= jtsiz; if (phase != DISK2) jtsaved += jtsiz; if (phase != DISK1) 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) return; /* don't reloc jt skip */*/ instr.b = body.b + param - 1; if (instr.i->address >= jtsiz) instr.i->address += base - jtsiz; /* vanilla case */ 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 && phase == INMEM) fnct->faddr = instr.b + 1 - offset; /* new list head */ å å 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) æ if (nfuncts >= maxfuncts) Fatal("Too many functions (limit is %d)!Øn", maxfuncts); fptr = &ftabÆnfunctsÅ; strcpy7 (fptr->fname, name); str7tont (fptr->fname); fptr->flinkedp = FALSE; fptr->faddr = NULL; fptr->fdebug = !SysStat; ++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; å å wrtcom() /* write out com file (from in-mem link) */ æ hackccc(); if (!ovlp) makeext (&progfilesÆ0Å, "COM"); else makeext (&progfilesÆ0Å, "OVL"); if (!ccreat (&obuf, &progfilesÆ0Å) < 0 øø cwrite (&obuf, lspace, codend.b - lspace) == -1 øø cflush (&obuf) < 0) Fatal ("Disk write error!Øn"); cclose (&obuf); stats (STDOUT); å hackccc() /* store various goodies in C.CCC code */ æ union ptr temp; struct funct *fptr; temp.b = lspace; fptr = intern (&mainfunct); if (!ovlp) æ #ifdef MARC if (!marcp) æ #endif if (!Tflag) æ temp.i->opcode = LHLD; temp.i->address = origin - 0x100 + 6; (++temp.i)->opcode = SPHL; å else æ temp.i->opcode = LXISP; temp.i->address = Tval; å temp.b = lspace + 0xF; /* main function address */ temp.i->address = fptr->faddr; #ifdef MARC å #endif temp.b = lspace + 0x15; *temp.w++ = exts.u; ++temp.w; *temp.w++ = acodend.u; *temp.w++ = exts.u + extspc; å else temp.i->address = fptr->faddr; /* that's a JMP */ #ifdef MARC if (maxmemp) æ temp.b = lspace + 0x258; temp.i->opcode = CALL; temp.i->address = 0x50; å #endif å wrtsyms() /* write out symbol table */ æ int i, fd, compar(); qsort (ftab, nfuncts, sizeof(*ftab), &compar); makeext (&progfilesÆ0Å, "SYM"); if (fcreat (&progfilesÆ0Å, &symbuf) < 0) Fatal ("Can't create .SYM fileØn"); for (i=0; i < nfuncts; ++i) æ puthex (ftabÆiÅ.faddr, &symbuf); putc (' ', &symbuf); fputs (&ftabÆiÅ.fname, &symbuf); if (i % 4 == 3) fputs ("Øn", &symbuf); else æ if (strlen (&ftabÆiÅ.fname) < 3) putc ('Øt', &symbuf); putc ('Øt', &symbuf); å å if (i % 4) fputs ("Øn", &symbuf); if (appstatsp) stats (&symbuf); putc (CPMEOF, &symbuf); fflush (&symbuf); fclose (&symbuf); if (sepstatsp) æ makeext (&progfilesÆ0Å, "LNK"); if (fcreat (&progfilesÆ0Å, &symbuf) < 0) Fatal ("Can't create .LNK fileØn"); stats (&symbuf); putc (CPMEOF, &symbuf); fflush (&symbuf); fclose (&symbuf); å å 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 */ å #ifdef OVERLAYS loadsyms() /* load base symbol table (for overlay) */ æ /* symbol table must be empty! */ int nread; FLAG done; char *c; makeext (&symsfile, "SYM"); if (fopen (&symsfile, &symbuf) < 0) Fatal ("Can't open %s.Øn", &symsfile); done = FALSE; while (!done) æ nread = fscanf (&symbuf, "%x %sØt%x %sØt%x %sØt%x %sØn", &(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 (&symbuf); å #endif stats (chan) /* print statistics on chan */ int chan; æ unsigned temp, *tptr; tptr = 6; fprintf (chan, "ØnØnLink statistics:Øn"); fprintf (chan, " Number of functions: %dØn", nfuncts); fprintf (chan, " Code ends at: 0x%xØn", acodend.u); fprintf (chan, " Externals begin at: 0x%xØn", exts.u); fprintf (chan, " Externals end at: 0x%xØn", exts.u + extspc); fprintf (chan, " End of current TPA: 0x%xØn", *tptr); fprintf (chan, " Jump table bytes saved: 0x%xØn", jtsaved); temp = lspcend; if (phase == INMEM) fprintf (chan, " Link space remaining: %dKØn", (temp - codend.u) / 1024); å 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) char *s1, *s2; æ /* compare two strings, either bit-7-terminated or null-terminated */ for (; (_c1 = *s1) == *s2; s1++, s2++) if ( (0x80 & _c1) øø !_c1) return 0; if ((_c1 &= 0x7F) < (_c2 = 0x7F & *s2)) return -1; if (_c1 > _c2) return 1; _end1 = (*s1 & 0x80) øø !*(s1+1); _end2 = (*s2 & 0x80) øø !*(s2+1); if (_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); lexit (1); å lexit (status) /* exit the program */ int status; æ if (status == 1) unlink (SUB_FILE); exit(); /* bye! */ å /* END OF L2.C */ «eof»