|
|
1.1 ! root 1: static char ID[] = "@(#) tv.c: 1.15 5/1/83"; ! 2: ! 3: #include <stdio.h> ! 4: ! 5: #include "system.h" ! 6: ! 7: #if TS || RT ! 8: #include <ar.h> ! 9: #else ! 10: #include <archive.h> ! 11: #endif ! 12: ! 13: #include "reloc.h" ! 14: #include "sdpsrc/hd/define2.h" ! 15: #include "structs.h" ! 16: #include "tv.h" ! 17: #include "ldtv.h" ! 18: #include "ldfcn.h" ! 19: #include "extrns.h" ! 20: #include "list.h" ! 21: #include "sgsmacros.h" ! 22: #include "bool.h" ! 23: #include "ldmacros.h" ! 24: ! 25: static FILE *tvstream = NULL; ! 26: #if AR16WR ! 27: static char *tvbuf; ! 28: #endif ! 29: static FILE *tvread = NULL; ! 30: static int tvnxt; /* next available tv slot */ ! 31: long gettvnxt(); /* finds next usable slot */ ! 32: /*eject*/ ! 33: tvspecdef() ! 34: { ! 35: #if TRVEC ! 36: /* ! 37: * Complete definition of tvspec ! 38: * called just after reading transfer file ! 39: */ ! 40: ! 41: register unsigned spare; ! 42: ! 43: #if !ONEPROC ! 44: tvspec.tvinflnm = (char *) ((int) tvspec.tvinflnm + (int) strbase); ! 45: #endif ! 46: spare = (unsigned) tvspec.tvosptr; ! 47: tvspec.tvosptr = (OUTSECT *) myalloc(sizeof(OUTSECT)); ! 48: tvspec.tvosptr->oshdr.s_size = ((long) spare) * TVENTSZ; ! 49: if ( aflag ) { ! 50: /* ! 51: * Define the Output Section which will be used to ! 52: * contain the tv ! 53: */ ! 54: tvspec.tvosptr->osflags = FILL; ! 55: tvspec.tvosptr->osalign = 16; ! 56: copy(tvspec.tvosptr->oshdr.s_name, _TV, 8); ! 57: tvspec.tvosptr->oshdr.s_paddr = -1L; /*none given */ ! 58: if (tvspec.tvrange[0]==0) /* leave slot 0 empty */ ! 59: tvspec.tvosptr->oshdr.s_size += TVENTSZ; ! 60: } ! 61: ! 62: #endif ! 63: } ! 64: ! 65: #if TRVEC ! 66: tvreloc() ! 67: { ! 68: ! 69: register INSECT *sptr; ! 70: register int numreloc; /* nbr of relocation entries */ ! 71: register SYMTAB *pglob; /* ptr to ld symbol entry */ ! 72: AUXTAB *paux; /* ptr to auxillary entry */ ! 73: AUXENT aux; /* auxillary entry */ ! 74: SYMENT lsym; /* local symbol table entry */ ! 75: SCNHDR shdr; /* section header */ ! 76: RELOC rentry; /* local relocation entry */ ! 77: LDFILE *rfd,rfdbuf, *ifd, ifdbuf; ! 78: INFILE *infl, *pnfl; ! 79: char *symname; ! 80: ! 81: /* ! 82: * the functions in DMERT's shared libraries have 0 in the tvndx ! 83: * field. To insure that all functions needing tv slots have P_TV ! 84: * in the tvndx field, scan all relocation entries for references ! 85: * to functions in shared libraries. ! 86: */ ! 87: ! 88: rfd = &rfdbuf; ! 89: ifd = &ifdbuf; ! 90: IOPTR(ifd) = NULL; ! 91: pnfl = NULL; ! 92: infl = (INFILE *)infilist.head; ! 93: while (infl != NULL) { ! 94: ! 95: OFFSET(ifd) = OFFSET(rfd) = infl->flfiloff; ! 96: if ( IOPTR(ifd) == NULL) { ! 97: if ((IOPTR(ifd) = fopen(infl->flname, "r")) == NULL || ! 98: (IOPTR(rfd) = fopen(infl->flname, "r")) == NULL ) ! 99: lderror(2,0,NULL, "Can't open %s", infl->flname); ! 100: if (infl->flfiloff == 0L) ! 101: TYPE(ifd) = TYPE(rfd) = 0; ! 102: else ! 103: TYPE(ifd) = TYPE(rfd) = USH_ARTYPE; ! 104: } ! 105: if (TYPE(ifd) == ARTYPE) { ! 106: if (FSEEK(ifd, 0L, BEGINNING) != OKFSEEK) ! 107: lderror(2,0,NULL, "internal error: fail to seek to the member of %s", ! 108: infl->flname); ! 109: } ! 110: if (FREAD(&(HEADER(ifd)),FILHSZ,1,ifd) != 1 ) ! 111: lderror(2,0,NULL, "fail to read file header of %s", infl->flname); ! 112: if (HEADER(ifd).f_flags & F_RELFLG) { ! 113: pnfl = infl; ! 114: infl = infl->flnext; ! 115: continue; ! 116: } ! 117: ! 118: HEADER(rfd) = HEADER(ifd); ! 119: ! 120: for( sptr = infl->flishead; sptr != NULL; sptr = sptr->isnext ) { ! 121: if( (numreloc = sptr->ishdr.s_nreloc) > 0 ) { ! 122: if (FSEEK(rfd,(long) (FILHSZ+HEADER(rfd).f_opthdr+ ! 123: (sptr->isecnum-1) * SCNHSZ),BEGINNING) != OKFSEEK || ! 124: FREAD(&shdr,SCNHSZ,1,rfd) != 1 || ! 125: FSEEK(rfd,shdr.s_relptr,BEGINNING) != OKFSEEK) { ! 126: lderror(1,0,NULL, "Seek to relocation entries for section %.8s in file %s failed", ! 127: sptr->ishdr.s_name, infl->flname); ! 128: numreloc = 0; ! 129: } ! 130: } ! 131: while( numreloc-- ) { ! 132: if (fread(&rentry, RELSZ, 1, IOPTR(rfd)) != 1) ! 133: lderror(2,0,NULL,"fail to read reloc entries of file %s", ! 134: infl->flname); ! 135: if( ! (ISTVRELOC(rentry.r_type)) ) ! 136: continue; ! 137: if (FSEEK(ifd,HEADER(ifd).f_symptr+ ! 138: rentry.r_symndx * SYMESZ,BEGINNING) != OKFSEEK || ! 139: FREAD(&lsym,SYMESZ,1,ifd) != 1) ! 140: lderror(2,0,NULL,"fail to read symtb entry %ld of file %s", ! 141: rentry.r_symndx,infl->flname); ! 142: if ( lsym.n_sclass != C_EXT ) ! 143: continue; /* ignore statics */ ! 144: ! 145: symname = SYMNAME( lsym ); ! 146: pglob = findsym( symname ); ! 147: ! 148: if ( pglob->sment.n_scnum > 0) { ! 149: if( pglob->sment.n_numaux > 0 ) { ! 150: paux = getaux(pglob->smauxid); ! 151: if (paux->axent.x_sym.x_tvndx == 0) { ! 152: paux->axent.x_sym.x_tvndx = P_TV; ! 153: tvspec.tvosptr->oshdr.s_size += TVENTSZ; ! 154: PUTAUX(paux, 1); ! 155: } ! 156: else ! 157: PUTAUX(paux, 0); ! 158: PUTSYM( pglob, 0 ); ! 159: } else { ! 160: zero(&aux, AUXESZ); ! 161: aux.x_sym.x_tvndx = P_TV; ! 162: tvspec.tvosptr->oshdr.s_size += TVENTSZ; ! 163: putaux( makeaux(pglob, &aux, 0), 1); ! 164: PUTSYM( pglob, 1 ); ! 165: } ! 166: ! 167: } else ! 168: PUTSYM( pglob, 0 ); ! 169: } ! 170: } ! 171: ! 172: pnfl = infl; ! 173: infl = infl->flnext; ! 174: ! 175: /* see if next input is from the same archive */ ! 176: if ((pnfl->flfiloff > 0L) && (infl != NULL)) ! 177: if (strcmp(pnfl->flname, infl->flname) == 0 && ! 178: (pnfl->flfiloff < infl->flfiloff)) ! 179: continue; ! 180: ! 181: fclose(IOPTR(ifd)); ! 182: fclose(IOPTR(rfd)); ! 183: IOPTR(ifd) = NULL; ! 184: } ! 185: ! 186: } ! 187: #endif ! 188: ! 189: ! 190: ! 191: tvupdat() ! 192: { ! 193: #if TRVEC ! 194: /* ! 195: * If _TV section is not user-defined but needs to ! 196: * be, add it to the list of output sections ! 197: * ! 198: * Check if _TV section needs to be bonded. If so, add it to ! 199: * the bondlist ! 200: */ ! 201: ! 202: OUTSECT *osptr; ! 203: ! 204: if ( (osptr = fndoutsec(_TV)) != NULL ) { ! 205: ++usrdeftv; ! 206: /* redo work done in tvspecdef() */ ! 207: free( tvspec.tvosptr ); ! 208: tvspec.tvosptr = osptr; ! 209: tvspec.tvosptr->osflags = FILL; ! 210: tvspec.tvosptr->osalign = 16; ! 211: tvspec.tvosptr->oshdr.s_paddr = -1L; ! 212: } else { ! 213: /* ! 214: * User defined no .tv output section but .tv ! 215: * input sections may be present ! 216: */ ! 217: if ( ! aflag ) ! 218: return; ! 219: if ( usrdeftv ) /* there are .tv input sections */ ! 220: if ( tvspec.tvrange[0] == 0 ) ! 221: tvspec.tvosptr->oshdr.s_size -= TVENTSZ; ! 222: ++numoutsc; ! 223: listadd(l_OS, &outsclst, tvspec.tvosptr); ! 224: ! 225: if( tvspec.tvbndadr != -1L ) { ! 226: register ACTITEM *aptr; ! 227: ! 228: aptr = (ACTITEM *) myalloc(sizeof(ACTITEM)); ! 229: aptr->bond.aitype = AIBOND; ! 230: aptr->bond.aiinflnm = tvspec.tvinflnm; ! 231: aptr->bond.aiinlnno = tvspec.tvinlnno; ! 232: aptr->bond.aioutsec = tvspec.tvosptr; ! 233: aptr->bond.aiadrbnd = tvspec.tvbndadr; ! 234: listadd(l_AI, &bondlist, aptr); ! 235: } ! 236: } ! 237: #endif ! 238: } ! 239: /*eject*/ ! 240: tvupdt2() ! 241: { ! 242: #if TRVEC ! 243: OUTSECT *osptr; ! 244: long *lptr; ! 245: ! 246: if ( usrdeftv ) { ! 247: osptr = fndoutsec(_TV); ! 248: /* ! 249: * Assume RANGE(0,N) ! 250: */ ! 251: tvspec.tvlength = osptr->oshdr.s_size / TVENTSZ; ! 252: if ( tvspec.tvrange[1] == 0 ) /* no RANGE directive */ ! 253: tvspec.tvrange[1] = tvspec.tvlength - 1; ! 254: } else { ! 255: /* ! 256: * Make sure that TV directive is adequate ! 257: * and fill in missing spaces ! 258: */ ! 259: ! 260: lptr = &tvspec.tvosptr->oshdr.s_size; ! 261: if ((tvspec.tvrange[1]!=0) ! 262: &&((long)((tvspec.tvrange[1]-tvspec.tvrange[0]+(tvspec.tvrange[0]? 1 : 2))*TVENTSZ)<*lptr)) ! 263: lderror(2,0,tvspec.tvinflnm, "tv range allows %d entries; %d needed", ! 264: tvspec.tvrange[1]-tvspec.tvrange[0]+1, ! 265: (int) (*lptr/TVENTSZ)); ! 266: if( (((long) tvspec.tvlength) * TVENTSZ) >= *lptr ) ! 267: *lptr = ((long) tvspec.tvlength) * TVENTSZ; ! 268: else if( tvspec.tvlength == 0 ) ! 269: tvspec.tvlength = *lptr / TVENTSZ; ! 270: else ! 271: lderror(1,0,NULL, "tv needs %ld entries; only %d allowed", ! 272: *lptr/TVENTSZ, tvspec.tvlength); ! 273: if (tvspec.tvrange[1] == 0) ! 274: tvspec.tvrange[1] = tvspec.tvlength - 1; ! 275: } ! 276: #endif ! 277: } ! 278: /*eject*/ ! 279: tvinit() ! 280: { ! 281: #if TRVEC ! 282: ! 283: /* ! 284: * Initialize for writing the transfer vector ! 285: */ ! 286: ! 287: register SYMTAB *pglob; ! 288: register AUXTAB *paux; ! 289: register int indx; ! 290: SCNHDR *psect; ! 291: TVENTRY outslot; ! 292: AUXENT aux; ! 293: long offset; /* where to write slot */ ! 294: int changed; ! 295: ! 296: ! 297: if( (tvstream = fopen(outfilnm, "r+")) == NULL ) ! 298: lderror(2,0,NULL, "can't open %s to write the tv", ! 299: outfilnm); ! 300: #if AR16WR ! 301: tvbuf = myalloc( BUFSIZ ); ! 302: setbuf( tvstream, tvbuf ); ! 303: #endif ! 304: ! 305: fseek(tvstream, tvspec.tvosptr->oshdr.s_scnptr, 0); ! 306: for ( indx = tvspec.tvrange[0]; indx <= tvspec.tvrange[1]; ++indx) ! 307: fwrite(&tvspec.tvfill, TVENTSZ, 1, tvstream); ! 308: ! 309: /* ! 310: * For each tv slot assignment directive, write out that slot ! 311: * if it is legal and update the ld symbol table appropriately. ! 312: * ! 313: * TV slot assignment directives are of the form "func=n" where ! 314: * func is a function name and n is a transfer vector index. Another ! 315: * directive specifies a RANGE for the current load, meaning that ! 316: * all functions defined in this load are to be assigned slots within ! 317: * the given range. Slot assignment directives for functions outside ! 318: * the given range are for use in resolving references to functions ! 319: * defined in another subsystem. Ld depends on the veracity and ! 320: * competence of the user to insure that this is, after all, the ! 321: * slot index assigned to this function in another subsystem load. ! 322: * ! 323: * Certain conditions result in errors. ! 324: * 1) If the user specifies a LENGTH for the total transfer vector, ! 325: * a) if more slots are required than the given LENGTH allows, ! 326: * or b) if an ASSIGN directive is issued which lies beyond the ! 327: * specified LENGTH ! 328: * then ERROR ! 329: * 2) If the user ASSIGNs a slot S to a function which is undefined ! 330: * in the current load, then ! 331: * if R1 <= S <= R2 ! 332: * then ERROR ! 333: * {where R1 is n in the directive RANGE(n,m) or 0; ! 334: * R2 is m in the directive RANGE(n,m) or LENGTH; } ! 335: * 3) If the user ASSIGNs a slot to a function which is defined ! 336: * in the current load, then ! 337: * if NOT R1 <= S <= R2 ! 338: * then ERROR ! 339: * ! 340: * Otherwise the assigned function slot is either used to update ! 341: * the ld symbol table and/or written to the a.out file or, if the ! 342: * assigned function is unreferenced in the current load, ignored. ! 343: */ ! 344: ! 345: #if ONEPROC ! 346: while (tvslot1) { ! 347: #else ! 348: tvslot1 = (TVASSIGN *) myalloc(sizeof(TVASSIGN)); ! 349: ! 350: while( tvslotcnt-- ) { ! 351: fread( tvslot1, sizeof(TVASSIGN), 1, trnfdes); ! 352: #endif ! 353: ! 354: /* ! 355: * If the symbol has never been referenced, ignore ! 356: * the ASSIGN command ! 357: */ ! 358: if( (pglob = findsym(tvslot1->funname)) == NULL ) { ! 359: #if ONEPROC ! 360: tvslot1 = tvslot1->nxtslot; ! 361: #endif ! 362: continue; ! 363: } ! 364: ! 365: changed = 0; ! 366: if( pglob->sment.n_scnum == 0 ) { ! 367: /* ! 368: * The symbol is referenced but not defined ! 369: */ ! 370: if( (tvslot1->slot >= tvspec.tvrange[0]) && ! 371: (tvslot1->slot <= tvspec.tvrange[1]) ) { ! 372: PUTSYM(pglob, 0); ! 373: lderror(2,0,tvspec.tvinflnm, ! 374: "Undefined symbol assigned a tv slot within tv range"); ! 375: } ! 376: else { ! 377: if( pglob->sment.n_numaux == 0 ) { ! 378: zero(&aux, AUXESZ); ! 379: paux = makeaux(pglob, &aux, 0); ! 380: changed = 1; ! 381: } else { ! 382: paux = getaux(pglob->smauxid); ! 383: } ! 384: paux->axent.x_sym.x_tvndx = P_TV; ! 385: PUTAUX(paux, 1); ! 386: } ! 387: } ! 388: else { ! 389: /* ! 390: * The symbol is defined ! 391: */ ! 392: if( (tvslot1->slot < tvspec.tvrange[0]) || ! 393: (tvslot1->slot > tvspec.tvrange[1]) ) { ! 394: PUTSYM(pglob, 0); ! 395: lderror(2,0,tvspec.tvinflnm, ! 396: "Defined symbol assigned a tv slot outside tv range"); ! 397: } ! 398: } ! 399: ! 400: /* ! 401: * Update ld symbol table aux entry ! 402: */ ! 403: ! 404: if (pglob->sment.n_numaux <= 0) { ! 405: if (pglob->sment.n_type == 0) { ! 406: zero( &aux, AUXESZ ); ! 407: paux = makeaux(pglob, &aux, 0); ! 408: changed = 1; ! 409: paux->axent.x_sym.x_tvndx = N_TV; ! 410: } else ! 411: lderror(2,0,tvspec.tvinflnm, ! 412: "attempt to assign tv slot to illegal symbol"); ! 413: } else ! 414: paux = getaux(pglob->smauxid); ! 415: /* ! 416: * If a function has been defined but never referenced ! 417: * through a tv, then the tvndx is still N_TV, not P_TV ! 418: * thus we need to test for both as the user may be ! 419: * defining the function for use in another subsystem ! 420: * and this code would otherwise generate an error message ! 421: */ ! 422: if( paux->axent.x_sym.x_tvndx != P_TV && paux->axent.x_sym.x_tvndx != N_TV ) { ! 423: PUTAUX(paux,0); ! 424: PUTSYM(pglob, changed); ! 425: lderror(2,0,tvspec.tvinflnm, ! 426: "Two tv slot assignments for function %.8s: %d and %d", ! 427: SYMNAME( pglob->sment ), ! 428: paux->axent.x_sym.x_tvndx, ! 429: tvslot1->slot); ! 430: } else { ! 431: paux->axent.x_sym.x_tvndx = tvslot1->slot; ! 432: PUTAUX(paux, 1); ! 433: } ! 434: ! 435: /* ! 436: * Determine if it is necessary to actually write the ! 437: * tv slot to the output file: does the slot fall ! 438: * within the specified tv range ! 439: */ ! 440: ! 441: if( (tvslot1->slot < tvspec.tvrange[0]) || ! 442: (tvslot1->slot > tvspec.tvrange[1]) ) { ! 443: PUTSYM(pglob, changed); ! 444: #if ONEPROC ! 445: tvslot1 = tvslot1->nxtslot; ! 446: #endif ! 447: continue; ! 448: } ! 449: ! 450: offset = (long) (tvspec.tvosptr->oshdr.s_scnptr + (TVENTSZ * ! 451: (tvslot1->slot - tvspec.tvrange[0]))); ! 452: fseek(tvstream, offset-ftell(tvstream), 1); ! 453: ! 454: setslot(pglob, psect, &outslot); ! 455: ! 456: PUTSYM(pglob, changed); ! 457: fwrite(&outslot, TVENTSZ, 1, tvstream); ! 458: #if ONEPROC ! 459: tvslot1 = tvslot1->nxtslot; ! 460: #endif ! 461: } ! 462: ! 463: fflush(tvstream); ! 464: ! 465: /* ! 466: * Don't use slot 0 as it is illegal in C to have any ! 467: * type of valid pointer with a zero value ! 468: */ ! 469: ! 470: tvnxt = (tvspec.tvrange[0] != 0) ? tvspec.tvrange[0] : 1; ! 471: ! 472: /* ! 473: * Position tv file pointers: ! 474: * tvstream : start of the tv (range) ! 475: * tvread : start of first legal tv slot ! 476: */ ! 477: if( (tvread=fopen(outfilnm,"r")) == NULL ) ! 478: lderror(2,0,NULL,"Cannot open %s to read tv",outfilnm); ! 479: fseek(tvstream, tvspec.tvosptr->oshdr.s_scnptr, 0); ! 480: fseek(tvread, ((long)(tvspec.tvosptr->oshdr.s_scnptr + ! 481: (tvspec.tvrange[0] ? 0 : TVENTSZ))), 0); ! 482: ! 483: return; ! 484: ! 485: #endif ! 486: } ! 487: /*eject*/ ! 488: tvslot(pglob, psym, infile, cs) ! 489: SYMTAB *pglob; /* symbol is in ld symbol table entry */ ! 490: struct syment *psym; /* symtab entry is from input file */ ! 491: FILE *infile; /* input file stream */ ! 492: unsigned short cs; /* segment value; used only for psym */ ! 493: { ! 494: ! 495: /* ! 496: * Check whether the given symbol needs a slot ! 497: * in the tv. If it does and one has not be assigned, ! 498: * assign the symbol a slot and write that entry to the ! 499: * tv in the output file ! 500: * ! 501: * The symbol is passed in either a gsym or syment symbol table ! 502: * entry data structure. For a gsym, look in the aux entry; for a ! 503: * syment, read the next syment from the input file. ! 504: * In the latter case, reseek the input file pointer to the original ! 505: * position ! 506: * ! 507: * The return value is: ! 508: * ! 509: * -1 symbol doesn't need tv slot ! 510: * 0 symbol needs tv slot, but this is ! 511: * not an absolute load ! 512: * >0 tv slot needed and assigned ! 513: */ ! 514: ! 515: int ret; ! 516: long offset; /* where to write next */ ! 517: AUXTAB *paux; ! 518: TVENTRY tvent; ! 519: AUXENT aux; ! 520: ! 521: if( ! tvflag ) ! 522: return ( -1 ); ! 523: ! 524: #if TRVEC ! 525: if( pglob != NULL ) ! 526: psym = &pglob->sment; ! 527: ! 528: /* ! 529: * We are assured that all symbols needing tv slots have already ! 530: * been detected in loadobjf() and their tvndx set to P_TV. ! 531: * Except for static functions which are detected in psymtab ! 532: * but their tvndx left at N_TV ! 533: */ ! 534: ! 535: if( psym->n_numaux == 0 ) ! 536: return ( -1 ); ! 537: ! 538: if( pglob != NULL ) { ! 539: /* ! 540: * This routine was given an ld symbol table entry ! 541: */ ! 542: paux = getaux(pglob->smauxid); ! 543: if (paux->axent.x_sym.x_tvndx == 0 ) { ! 544: PUTAUX(paux, 0); ! 545: return ( -1 ); ! 546: } ! 547: if( paux->axent.x_sym.x_tvndx == P_TV ) { ! 548: /* ! 549: * This symbol is referenced through a tv: ! 550: * ! 551: * tvndx == P_TV ! 552: */ ! 553: if( ! aflag ) { ! 554: PUTAUX(paux, 0); ! 555: return ( 0 ); ! 556: } ! 557: if( pglob->smscnptr != NULL ) { ! 558: ! 559: slotassign(&tvent, pglob, &cs); ! 560: ! 561: } ! 562: else { ! 563: /* ! 564: * tv ref to undefined symbol ! 565: */ ! 566: PUTAUX(paux, 0); ! 567: return( -1 ); ! 568: } ! 569: if ( (offset = gettvnxt()) == 0L) ! 570: lderror(2,0,NULL,"Internal error: out of tv slots"); ! 571: fseek(tvstream, offset-ftell(tvstream), 1); ! 572: paux->axent.x_sym.x_tvndx = tvnxt; ! 573: PUTAUX(paux, 1); ! 574: } ! 575: else { ! 576: if( paux->axent.x_sym.x_tvndx == N_TV ) ! 577: ret = 0; ! 578: else ! 579: /* ! 580: * The symbol already has a tv assigned: ! 581: * ! 582: * tvndx > 0 ! 583: */ ! 584: ret = paux->axent.x_sym.x_tvndx; ! 585: PUTAUX(paux, 0); ! 586: return ( ret ); ! 587: } ! 588: } ! 589: else { ! 590: /* ! 591: * This routine was given an input symbol table entry ! 592: */ ! 593: fread(&aux, AUXESZ, 1, infile); ! 594: fseek(infile, (long) -AUXESZ, 1); ! 595: if( aux.x_sym.x_tvndx != N_TV ) ! 596: return ( -1 ); ! 597: if( ! aflag ) ! 598: return ( 0 ); ! 599: if ( (offset = gettvnxt()) == 0L) ! 600: lderror(2,0,NULL,"Internal error: out of tv slots"); ! 601: fseek(tvstream, offset-ftell(tvstream), 1); ! 602: ! 603: settventry(&tvent, psym, &cs); ! 604: } ! 605: ! 606: fwrite(&tvent, TVENTSZ, 1, tvstream); ! 607: ! 608: return ( tvnxt++ ); ! 609: ! 610: #endif ! 611: } ! 612: /*eject*/ ! 613: long ! 614: gettvnxt() ! 615: { ! 616: #if TRVEC ! 617: ! 618: /* ! 619: * This routine is called only when it is certain that we need to write ! 620: * out a tv entry. tvinit() has written assigned slots and filled all ! 621: * empty slots with 0. The first time this routine is called tvnxt equals ! 622: * tvspec.tvrange[0], tvread is open for reading, the read/write ! 623: * pointer is at the beginning of the transfer vector. ! 624: * ! 625: * It begins reading transfer vector entries until it finds ! 626: * one which is unused. It then seeks TVENTSZ backwards and returns ! 627: * the file offset of the available slot. It increments tvnxt whenever ! 628: * it finds an unavailable slot. When next called, it will be in a position ! 629: * to proceed reading slots, being positioned correctly and knowing ! 630: * the value of tvnxt. ! 631: */ ! 632: ! 633: long inslot; ! 634: ! 635: for( ; tvnxt <= tvspec.tvrange[1]; ++tvnxt ) { ! 636: fread(&inslot, TVENTSZ, 1, tvread); ! 637: if( inslot == -1L ) ! 638: return( (long)(ftell(tvread)-TVENTSZ) ); ! 639: } ! 640: ! 641: return(0); ! 642: #endif ! 643: } ! 644: /*eject*/ ! 645: tvfinish() ! 646: { ! 647: #if TRVEC ! 648: long offset; ! 649: SYMTAB *psym; ! 650: ! 651: if( tvspec.tvfnfill[0] != '\0' ) { ! 652: if( (psym = findsym(tvspec.tvfnfill)) == NULL ) ! 653: lderror(1, tvspec.tvinlnno, tvspec.tvinflnm, ! 654: "tv fill symbol %s does not exist", tvspec.tvfnfill); ! 655: else { ! 656: ! 657: filltvassign(psym); ! 658: ! 659: PUTSYM(psym, 0); ! 660: ! 661: /* ! 662: * update x_tvfill in .tv aux entry ! 663: */ ! 664: if ( (psym=findsym(_TV)) == NULL) ! 665: lderror(0,0,NULL,"No .tv in symbol table"); ! 666: else { ! 667: AUXTAB *paux; ! 668: union { ! 669: TVENTRY ent; ! 670: long l; ! 671: } fill; ! 672: ! 673: fill.ent = tvspec.tvfill; ! 674: paux = getaux(psym->smauxid); ! 675: paux->axent.x_tv.x_tvfill = fill.l; ! 676: PUTAUX(paux, 1); ! 677: PUTSYM(psym, 0); ! 678: } ! 679: ! 680: if ( tvspec.tvrange[0] == 0 ) { /* fill slot 0 */ ! 681: fseek(tvstream, tvspec.tvosptr->oshdr.s_scnptr, 0); ! 682: fwrite(&tvspec.tvfill, TVENTSZ, 1, tvstream); ! 683: } ! 684: ! 685: for( offset = gettvnxt(); tvnxt <= tvspec.tvrange[1]; ) { ! 686: fseek(tvstream, offset-ftell(tvstream), 1); ! 687: fwrite(&tvspec.tvfill, TVENTSZ, 1, tvstream); ! 688: ++tvnxt; ! 689: offset = gettvnxt(); ! 690: } /* for */ ! 691: } /* else */ ! 692: } /* if tvfnfill[0] */ ! 693: ! 694: fclose(tvstream); ! 695: #if AR16WR ! 696: free( tvbuf ); ! 697: #endif ! 698: fclose(tvread); ! 699: ! 700: #endif ! 701: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.