/* Copyright 1982, 1983 Alcyon Corporation 8716 Production Ave. San Diego, Ca. 92121 */ char *version = "@(#)main.c 1.7 12/28/83"; #include "lo68.h" #ifndef DECC # include #else # include "Isignal" #endif /* * 68000 linking loader * Bill Allen * This loader is basically a two pass operation. The first pass * reads all the relocatable object files including any libraries. * It builds the full symbol table, resolves all external symbol * references if possible, and calculates the total size of the * text, data, and bss segements. Pass 2 then does the binding, * the relocation, and produces the final output file. */ #ifdef MC68000 # define LIBINDEX 8 char libname[] = "/lib/lib7.a"; /*default library name*/ char libxname[] = "/lib/lib "; /*library name*/ char *ofilname = "a.out"; char shortexit[] = "/lib/exit.o"; #else # ifndef VMS # define LIBINDEX 18 char libname[] = "/usr/local/lib/lib7.a"; /*default library name*/ char libxname[] = "/usr/local/lib/lib "; /*library name*/ char *ofilname = "c.out"; /*output file name*/ char shortexit[] = "/usr/local/lib/shortexit.o"; # else # define LIBINDEX 8 char libname[] = "clib:lib7.a"; char libxname[] = "clib:lib "; char *ofilname = "c.out"; /*output file name*/ char shortexit[] = "clib:exit.o"; # endif #endif #ifndef VMS # define FILSEP '/' # define NAMELOC 10 /* location in tfilname where letter is */ char tfilname[18] = "/tmp/_ldtmaXXXXX"; /*first temp file name*/ int shortfildes; /* file designator for short exit */ #else # define FILSEP ']' # define NAMELOC 5 char tfilname[18] = "wk:tmaXXXXX"; /** * declarations for fix to sbrk problem. On the vax when files are opened * between calls to sbrk, the allocated memory is not contiguous. Therefore * all the input files are concatenated into one file which is opened prior * to the calls to sbrk. This process creates a large overhead in disk I/O, * but the structure of the program requires that the memory for the symbol * table be continuous. It would be preferable to find a faster solution * to the problem. **/ int openfilloc[NFILE]; /* pointers to beginning of the input files */ int fdp = 0; /* index to openfilloc */ char *pt, *lpin; #endif long longseek(); char etexstr[] = "_etext\0\0"; char edatstr[] = "_edata\0\0"; char eendstr[] = "_end\0\0\0\0"; int ignflg; int debug; int exstat; int mmuflag; int errno; /* system call error number */ main(argc,argv) int argc; char **argv; { register char **p, *pc, *p1; register i, j; if( signal(SIGINT,SIG_IGN) != SIG_IGN ) signal(SIGINT,endit); if( signal(SIGQUIT,SIG_IGN) != SIG_IGN ) signal(SIGQUIT,endit); if( signal(SIGHUP,SIG_IGN) != SIG_IGN ) signal(SIGHUP,endit); signal(SIGTERM,endit); #ifdef MC68000 sysinfo(0,&mmuflag); #else mmuflag = 1; #endif #ifndef VMS /* init the symbol table after all the files have been opened on the vax */ intsytab(); /*initialize the symbol table*/ #endif firstsym = fsymp; libfctr = lbfictr; libptr = lbfioff; if(argc <= 1) { usage: printf(": Invalid lo68 argument list\n"); endit(-1); } #ifdef VMS /* open all files */ p = argv+1; for (i=1; i < argc; i++) { pc = *p++; if(*pc == '-') { switch(*++pc) { case 'l': pc--; break; case 'o': p++; i++; case 'i': case 'n': case 's': case 'X': case 'Z': case 'I': case 'U': case 'T': case 'D': case 'B': case 'r': case 'v': continue; } } pt = pc; if (*pt == '-' && *++pt == 'l') { if(*++pt) { for(lpin = &libxname[LIBINDEX]; *pt; ) *lpin++ = *pt++; *lpin++ = '.'; *lpin++ = 'a'; pt = libxname; } else /* else default library name -- /lib/lib7.a */ pt = libname; } else pt = pc; if ((openfilloc[fdp++]=open(pt,0)) < 0) { printf("unable to open %s\n",pt); printf("probably too many simultaneous opens for this system\n"); endit(-1); } } fdp = 0; intsytab(); /* initialize the symbol table */ #endif p = argv+1; if (!mmuflag) saverbits++; /* relocation bits forced on nommu sys */ for(i=1; iflags = SYXR; /*extern reference*/ addsym(0); /*put into symbol table*/ continue; } } p1load(pc); /*read file or library*/ } resolve(); /*resolve externals and assign addresses*/ pass2++; /*now in pass 2*/ p = argv+1; firstsym = fsymp; libfctr = lbfictr; libptr = lbfioff; makeofile(); /*make the output file*/ for(i=1; i noload) { /*found a match*/ if(noload) prdup(lastdup); /*print dup defn*/ addsizes(); /*add this files sizes*/ firstsym++; *libfctr += 1; /*count files loaded from this library*/ *libptr++ = lbctr; /*remember offset in library*/ } else /*dont need this file*/ restsymtab(); /*restore symbol table*/ if(libfilsize&1) { /*one byte of padding*/ getc(&ibuf); lbctr++; } lbctr += libfilsize + LIBHDSIZE; longseek(lbctr,&ibuf); /*goto begin of next lib entry*/ } libfctr++; /*point to next library file counter*/ } /*read a library file header*/ rdlibhdr() { if (getarhd(&ibuf,&libhd) == -1) /* 4.1 new library routine */ return(0); /*end of file*/ libhd.lmodti = 0; /* provide end of string delim for name */ libfilsize = libhd.lfsize; /* copy out file size */ return(1); } /* open the file pointed to by ap*/ /* check for the -lx type library spec*/ openfile(ap) char *ap; { register char *p, *lp; #ifdef VAX11 unsigned short omagic; #else int omagic; #endif p = ap; if(*p=='-' && *++p=='l') { if(*++p) { /* 13 apr 83, multi-char libraries */ for (lp = &libxname[LIBINDEX]; *p; ) *lp++ = *p++; *lp++ = '.'; *lp++ = 'a'; *lp = 0; p = libxname; } else /* else default library name -- /lib/lib7.a */ p = libname; } else p = ap; if((ibuf.fd=open(p,0)) < 0) { printf(": unable to open %s\n",p); endit(-1); } ifilname = p; /*point to current file name for error msgs*/ if(read(ibuf.fd,&omagic.hibyte,1)!=1 || read(ibuf.fd,&omagic.lobyte,1)!=1) { printf(": read error on file: %s\n",ifilname); endit(-1); } couthd.ch_magic = omagic; ibuf.cc = 0; if (omagic != LIBMAGIC) { seek(ibuf.fd,0,0); /* was lseek(ibuf.fd,0L,0); */ readhdr(); /*read file header*/ } if(pass2) { /*need file descrptr for reloc bits*/ rbuf.fd = open(p,0); rbuf.cc = 0; } } #ifdef VMS /** * vsetfile - make usable the file pointed to by openfilloc[fdp] * called from p1load only. **/ vsetfile(ap) char *ap; { unsigned short omagic; ibuf.fd = openfilloc[fdp++]; ibuf.cc = 0; ifilname = ap; /* point to current file name for error messages */ if(read(ibuf.fd,&omagic.hibyte,1)!=1 || read(ibuf.fd,&omagic.lobyte,1)!=1) { printf(": read error on file: %s\n",ifilname); endit(-1); } couthd.ch_magic = omagic; ibuf.cc = 0; if (omagic != LIBMAGIC) { seek(ibuf.fd,0,0); /* was lseek(ibuf.fd,0L,0); */ readhdr(); } } #endif /* read the header of the input file*/ readhdr() { if (getchd(&ibuf,&couthd) == -1) { /* 4.1 new library routine */ printf(": error reading header: %s\n",ifilname); endit(-1); } if(couthd.ch_magic != EX_MAGIC) { printf(": file format error: %s %o\n",ifilname,(int)couthd.ch_magic); endit(-1); } if(couthd.ch_rlbflg) { printf(": no relocation bits: %s\n",ifilname); endit(-1); } } /* * load one *.o format file using ibuf * put the symbols into the symbol table relocating each one * and finally add this files sizes into running totals * libflg is set if we are in a library */ do1load(libflg) int libflg; { register long i, l, ret; addfnsym(); /* put file name into symbol table */ *firstsym = lmte; /*remember where this symbol table starts*/ l = couthd.ch_tsize + couthd.ch_dsize + HDSIZE; if(libflg) l += lbctr + LIBHDSIZE; ret = longseek(l,&ibuf); i = couthd.ch_ssize; /*size of symbol table*/ while(i > 0) { getsym(); /*read one symbol entry*/ relocsym(); /*fix its address*/ addsym(libflg); /*add to symbol table*/ i -= OSTSIZE; } } /* put file name into symbol table */ addfnsym() { register char *p,*q; register int i; p = q = ifilname; while(*p) { if(*p == FILSEP) /* directory delimiter */ q = p+1; p++; } p = lmte; for(i=0; iflags = SYFN|SYGL|SYTX; /* file name bit */ lmte->vl1 = textbase; addmte(); } /* get a temp file for the intermediate text*/ gettempf() { register short i,j; struct stat stbuf; while( mktemp(tfilname) ) { #ifndef VMS if( stat(tfilname,&stbuf) >= 0 ) continue; /* this file exists */ #endif if( (j = creat(tfilname,0600)) >= 0 ) return(j); else if (debug) printf("couldn't creat, return value %d\n",j); } printf(": Unable to open temporary file\n"); endit(-1); } /* update the relocation counters with the sizes in the header*/ addsizes() { textbase = textbase + couthd.ch_tsize; database = database + couthd.ch_dsize; bssbase = bssbase + couthd.ch_bsize; } /* assign an address for a block of bss common*/ asgncomn(ap) char *ap; { register char *p, *p1; register long l; p = ap; pack(p,lmte); p1 = lemt(girt); if(p1 != lmte) { /*matches a global entry*/ if(((struct symtab *)p1)->flags&SYTX) { /* linking to text symbol */ printf("text/data symbol name conflict: %s\n",p1); } ((struct symtab *)ap)->vl1 = ((struct symtab *)p1)->vl1; return; } l = 0; lemt(eirt); do { if(((struct symtab *)p)->vl1 > l) l = ((struct symtab *)p)->vl1; ((struct symtab *)p)->vl1 = 0; } while((p = nextsy(((struct symtab *)p)->tlnk)) != lmte); /*now make a global entry for this common block*/ ((struct symtab *)p)->flags = SYDF|SYGL|SYBS; ((struct symtab *)p)->vl1 = bssbase + bsssize; /*copy address to first external*/ ((struct symtab *)ap)->vl1 = ((struct symtab *)p)->vl1; bsssize += l; lemt(girt); /*set ptrs for global chain*/ mmte(); /*add to global chain*/ } /* assign an address to an external by matching it with a global*/ /* print an error message if no match*/ asgnext(ap) char *ap; { register char *p, *pg; p = ap; pack(p,lmte); /*copy current symbol name*/ pg = lemt(girt); if(pg == lmte) { /*no match in global symbols*/ pg = lemt(eirt); /*set ptrs for external chains*/ if(pg == lmte) { printf(": asgnext botch\n"); endit(-1); } while((p = nextsy(((struct symtab *)p)->tlnk)) != lmte) { if(((struct symtab *)p)->vl1) { /*common*/ asgncomn(ap); return; } } if(spendsym(ap)) /*end, etext or edata*/ return; if(undflg==0) { printf(": Undefined:\n"); undflg++; exstat++; } prtsym(p); } else /*assign symbol value*/ ((struct symtab *)p)->vl1 = ((struct symtab *)pg)->vl1; } /* pass 2 load routine:*/ /* read the file or library and do relocation */ p2load(ap) char *ap; { openfile(ap); /*get the file opened using ibuf*/ if(couthd.ch_magic == LIBMAGIC) loadlib(); else { do2load(0); /*load a *.o file*/ addsizes(); } close(ibuf.fd); close(rbuf.fd); } /*make the outut file and write the header*/ makeofile() /* 4.1 restructured */ { register struct hdr2 *lb; struct hdr2 olibhd; if( (obuf.fd = creat(ofilname,0666)) < 0 ) { /* only make exec if all ok */ printf(": Unable to create %s\n",ofilname); endit(-1); } obuf.cc = BSIZE; obuf.cp = &obuf.cbuf[0]; lb = &olibhd; if(Zflag|Dflag|Bflag) { /*expanded header: data & bss bases in header*/ lb->ch_magic = (unsigned short)EX_ABMAGIC; lb->ch_dstart = datastart; lb->ch_bstart = bssstart; } else if (isplit) /* i & d split */ lb->ch_magic = (unsigned short)EX_IDMAGIC; else if(!shtext) /* standard */ lb->ch_magic = (unsigned short)EX_MAGIC; else if (shtext == -1) /* 2k boundary */ lb->ch_magic = (unsigned short)EX_2KSTXT; else /* 4k boundary */ lb->ch_magic = (unsigned short)EX_4KSTXT; lb->ch_tsize = textsize; lb->ch_dsize = datasize; lb->ch_bsize = bsssize; lb->ch_ssize = (long)(lmte - bmte); lb->ch_stksize = stacksize; lb->ch_entry = textstart; if (saverbits) /* bits present ?? */ lb->ch_rlbflg = 0; else lb->ch_rlbflg = -1; /* printf("tsz %d dsz %d bsz %d ssz %d bits %d\n",lb->ch_tsize,lb->ch_dsize,lb->ch_bsize,lb->ch_ssize,lb->ch_rlbflg); */ putchd(&obuf,lb); tmpbinit(&tbuf); /*temp for data words*/ dafnc = tfilname[NAMELOC]; if(saverbits) { tmpbinit(&rtbuf); /*temp for text relocation bits*/ rtfnc = tfilname[NAMELOC]; tmpbinit(&rdbuf); /*temp for data relocation bits*/ rdfnc = tfilname[NAMELOC]; } } tmpbinit(abufp) struct iob *abufp; { register struct iob *bufp; bufp = abufp; bufp->fd = gettempf(); bufp->cc = BSIZE; bufp->cp = &bufp->cbuf[0]; } endit(xstat) int xstat; { if(dafnc) { tfilname[NAMELOC] = dafnc; unlink(tfilname); } if(saverbits) { tfilname[NAMELOC] = rtfnc; unlink(tfilname); tfilname[NAMELOC] = rdfnc; unlink(tfilname); } if( xstat == 0 ) chmod(ofilname,0777); /* if all ok, make it executable [jws] */ #ifdef VMS else printf("load failed - status = %x\n",xstat); #endif exit(xstat); } /* * load files from a library. the library is open in ibuf, the * count of files to load is pointed to by libfctr, and the offset * of each file is pointed to by libptr. */ loadlib() { register int i,j; register long l; #ifndef VMS /* don't short load on a vms vax */ if(shortlflg) { if(shortlflg == 1) /*need to load short exit*/ shortload(); shortlflg++; return; } #endif i = *libfctr++; /*# files to load from this library*/ if(i==0) return; /*none to load*/ while(i--) { /*load the files*/ l = *libptr++; /*library offset for this file*/ longseek(l,&ibuf); /*seek to beginning of file*/ longseek(l,&rbuf); if (!rdlibhdr()) /*read the library header*/ printf("Bad Library Header....\n"); readhdr(); /*read the file header*/ lbctr = l; do2load(1); /*load it*/ addsizes(); } } #ifndef PDP11 /* do a long seek on buffer bp given a long file offset*/ long longseek(al,bp) long al; struct iob *bp; { long ret; ret = lseek(bp->fd,al,0); bp->cc = 0; /*input buffer empty*/ bp->cp = &bp->cbuf; return(ret); } #endif /* * look up the value of an external symbol given the external symbol * number. Since externals are duplicated on the external hash chains, * all external entries don't have values assigned in the symbol table, * so the external name must be looked on the global chains and * the value of the matching symbol used. symptr points to the * first symbol for the current file's symbol table */ long extval(extno) int extno; { register struct symtab *p; register char *pg; p = symptr + extno; if((p->flags&SYXR)==0) return(p->vl1); pack(p,lmte); pg = lemt(girt); if(pg == lmte) pg = lemt(eirt); /*may be common*/ return(((struct symtab *)pg)->vl1); /*return globals address*/ } /* look up the relocation base for an external symbol. must use same*/ /* method as in extval for the same reasons (see comment above)*/ extbase(extno) int extno; { register struct symtab *p; register char *pg; register int i; p = symptr + extno; if((p->flags&SYXR)==0) pg = (char *)p; else { pack(p,lmte); pg = lemt(girt); if(pg == lmte) pg = lemt(eirt); /*may be common*/ } i = ((struct symtab *)pg)->flags; return((i&SYDA)? DRELOC : (i&SYTX)? TRELOC : (i&SYBS)? BRELOC : DABS); } /* load a file doing relocation and external resolution*/ /* libflg is set if we are loading from a library*/ do2load(libflg) int libflg; { int longf; short i, j; register struct iob *p; register struct iob *pr; int saof, wasext; short word; register long tpc, l; long l1; tpc = 0; p = &obuf; pr = &rtbuf; saof = -1; symptr = (struct symtab *)*firstsym++; /*beginning of this symbol table*/ l = couthd.ch_tsize + couthd.ch_dsize + couthd.ch_ssize + HDSIZE; if(libflg) l += lbctr+LIBHDSIZE; longseek(l,&rbuf); /*long seek */ l = couthd.ch_tsize; do2l1: while((l -= 2) >= 0) { /*relocate the text*/ longf = 0; lgetw(&i,&ibuf); /*text or data word */ lgetw(&j,&rbuf); /*relocation word*/ tpc += 2; /*keep pc in this file*/ wasext = 0; switch(j&7) { /*relocation bits*/ case INSABS: /*first word of instr*/ case DABS: /*data absolute*/ lputw(&i,p); if(saverbits) lputw(&j,pr); /*relocation bits*/ break; case LUPPER: /*high word of long*/ l1.hiword = i; if(saverbits) lputw(&j,pr); /*upper word relocation bits*/ lgetw(&l1.loword,&ibuf); lgetw(&j,&rbuf); tpc += 2; longf++; /*doing two words*/ l -= 2; /*count lower half*/ dorelc: switch(j&7) { case DABS: if(saverbits) lputw(&j,pr); break; case INSABS: case LUPPER: default: goto do2l99; case TRELOC: l1 += textbase; if(saverbits) lputw(&j,pr); break; case DRELOC: l1 += database; if(saverbits) lputw(&j,pr); break; case BRELOC: l1 += bssbase; if(saverbits) lputw(&j,pr); break; case EXTVAR: wasext++; l1 += extval((int)j>>3); if(saverbits) { word = extbase((int)j>>3); lputw(&word,pr); } break; case EXTREL: l1 = l1+extval((int)j>>3)-textbase-tpc+2; if(l1<0xffff8000 || l1>0x7fff) { printf(": relative address overflow at %lx in %s\n", tpc,ifilname); prextname((int)j>>3); /*give name referenced*/ exstat++; } l1.hiword = 0; if(saverbits) { word = DABS; lputw(&word,pr); } goto outlowd; } if(ignflg==0 && longf==0 && l1&0xffff8000 && saof) { printf(": short address overflow in %s\n",ifilname); if(wasext) prextname((int)j>>3); exstat++; if(libflg) { l1 = *(libptr-1); printf("library offset = %u\n",(int)l1.loword); l1 = 0; } saof = 0; } if(longf) lputw(&l1.hiword,p); outlowd: lputw(&l1.loword,p); break; case TRELOC: case DRELOC: case BRELOC: case EXTVAR: case EXTREL: l1 = *(libptr-1); if (!mmuflag) { printf("library offset = %u\n",(int)l1.loword); printf("16-bit reloc in %s\n",ifilname); } l1 = i; /*sign extend to long like 68000*/ goto dorelc; default: do2l99: printf(": lo68: invalid relocation flag in %s\n",ifilname); endit(-1); } } if(p == &obuf) { p = &tbuf; /*place to put data*/ pr = &rdbuf; /*file for data relocation bits*/ l = couthd.ch_dsize; goto do2l1; /*now do the data*/ } } /* do the final writting to the output file*/ /* copy the initialized data from the temp file to the output file*/ /* write the symbol table to the output file*/ finalwr() { if((textsize+textstart) != textbase) { printf(": finalwr: text size error\n"); exstat++; } cpdata(&tbuf,dafnc); osymt(); /*write the symbol table*/ if(saverbits) { cpdata(&rtbuf,rtfnc); cpdata(&rdbuf,rdfnc); } fflush(&obuf); /* longseek was: lseek(obuf.fd,14L,0); */ if( longseek(14L,&obuf) < 0 || lwritel(obuf.fd,&stlen) == -1 ) { printf(": output file write error\n"); exstat++; } endit(exstat); } /* copy the initialized data words from temp file to output file*/ cpdata(pb,fnc) struct iob *pb; char fnc; { register int i,cfn; fflush(&obuf); fflush(pb); close(pb->fd); tfilname[NAMELOC] = fnc; if((cfn=open(tfilname,0)) < 0) { printf(": unable to reopen %s\n",tfilname); #ifdef DEBUG printf(": errno=%o\n",errno); #endif endit(-1); } while((i=read(cfn,&pb->cbuf[0],BSIZE)) > 0) { if(write(obuf.fd,&pb->cbuf[0],i) != i) { printf(": output file write error\n"); endit(-1); } } } /*get constant given radix*/ /* this routine only works for radixes of 2, 8, 16*/ /* so as to avoid lmul because of floating point*/ long lgetnum(apc,ardx) char *apc; int ardx; { register trdx,j; register char *pc; register long i; pc = apc; if(ardx==16) trdx = 4; /*radix as power of 2*/ else if(ardx==8) trdx = 3; else if(ardx==2) trdx = 1; else return(0); i=0; while(1) { j = *pc++; if(j>='0' && j<='9') j -= '0'; else if(j>='a' && j<='f') j = j-'a'+10; else if(j>='A' && j<='F') j = j-'A'+10; else break; /*not valid numeric char*/ if(j>=0 && jname[0])) { etextptr = p; return(1); } if(eqstr(edatstr,&p->name[0])) { edataptr = p; return(1); } if(eqstr(eendstr,&p->name[0])) { endptr = p; return(1); } return(0); } /* test two symbol names for equality*/ eqstr(ap1,ap2) char *ap1, *ap2; { register char *p1, *p2; register int i; p1 = ap1; p2 = ap2; for(i = SYNAMLEN; --i != -1; ) /* 2 may 83 */ if(*p1++ != *p2++) return(0); return(1); } /* print an error message giving an external name*/ prextname(extno) int extno; { register struct symtab *p; register char *pc; p = symptr + extno; printf(": external name: "); for(pc = &p->name[0]; pc < &p->name[SYNAMLEN]; pc++) { if(*pc == 0) break; putchar(*pc); } putchar('\n'); } #ifndef VMS /** * check to see if we only need to load exit -- no other * library routines needed. if so, load exit only and * return 1 else return 0. **/ shortsearch() { register char *p; register char **sx1, **sx2; register int i; for(sx1=eirt; sx1<&eirt[63]; sx1 += 2) { /*go thru externals*/ if(*(sx2 = sx1+1)==0) /*this chain empty*/ continue; /* go thru symbols on chain*/ sx2 = (char **)*sx2; /*first entry on this chain*/ while(1) { if(((struct symtab *)sx2)->vl1 == 0) if(eqstr("_exit\0\0\0",sx2)==0&&eqstr("_main\0\0\0",sx2)==0) return(0); p = (char *)sx2; if(p == *sx1) /*end of chain*/ break; sx2 = (char **)((struct symtab *)sx2)->tlnk; /*next entry in chain*/ } } /* found only exit undefined*/ if((i=open(shortexit,0)) < 0) return(0); /*cant open short exit file*/ close(i); close(ibuf.fd); /*close library -- dont need to scan it*/ openfile(shortexit); do1load(0); /*load short exit*/ firstsym++; addsizes(); shortlflg++; return(1); } /* load the short exit routine*/ shortload() { close(ibuf.fd); /*dont need library*/ close(rbuf.fd); openfile(shortexit); do2load(0); addsizes(); } #endif #ifndef MC68000 static char _uniqlet = 'a'; char * mktemp(ap) char *ap; { register char *p; register int i,j; p = ap; i = getpid(); /* process id */ while( *p ) p++; for(j = 5; --j != -1; ) { *--p = ((i&7) + '0'); i =>> 3; } *--p = _uniqlet; _uniqlet++; if( _uniqlet > 'z' ) _uniqlet = 'A'; if( _uniqlet == 'Z' ) return(0); return(ap); } #endif #ifdef PDP11 /** * longseek - do a long seek on buffer bp, given a long * file offset. **/ long longseek(al,bp) long al; struct buf *bp; { long l, ret; register short b,o; l = al>>9; b = l.loword; /* block # */ o = al.loword&0777; /* offset in block */ if((ret=seek(bp->fd,b,3)) < 0) { /* seek to block */ printf(": seek error on file %s\n",ifilname); endit(-1); } if((l=seek(bp->fd,o,1)) < 0) { /* do offset */ printf(": seek error on file %s\n",ifilname); endit(-1); } bp->cc = 0; /* input buff empty */ bp->cp = &bp->cbuf; ret = (b*512) + o; return(ret); } #endif