|
|
1.1 ! root 1: #ifndef lint ! 2: static char *rcsid = ! 3: "$Header: fasl.c,v 1.11 87/12/14 16:49:06 sklower Exp $"; ! 4: #endif ! 5: ! 6: /* -[Thu Jun 2 21:44:26 1983 by jkf]- ! 7: * fasl.c $Locker: $ ! 8: * compiled lisp loader ! 9: * ! 10: * (c) copyright 1982, Regents of the University of California ! 11: */ ! 12: ! 13: #include "global.h" ! 14: #include <sys/types.h> ! 15: #include "lispo.h" ! 16: #include "chkrtab.h" ! 17: #include "structs.h" ! 18: #include "frame.h" ! 19: ! 20: /* fasl - fast loader j.k.foderaro ! 21: * this loader is tuned for the lisp fast loading application ! 22: * any changes in the system loading procedure will require changes ! 23: * to this file ! 24: * ! 25: * The format of the object file we read as input: ! 26: * text segment: ! 27: * 1) program text - this comes first. ! 28: * 2) binder table - one word entries, see struct bindage ! 29: * begins with symbol: bind_org ! 30: * 3) litterals - exploded lisp objects. ! 31: * begins with symbol: lit_org ! 32: * ends with symbol: lit_end ! 33: * data segment: ! 34: * not used ! 35: * ! 36: * ! 37: * these segments are created permanently in memory: ! 38: * code segment - contains machine codes to evaluate lisp functions. ! 39: * linker segment - a list of pointers to lispvals. This allows the ! 40: * compiled code to reference constant lisp objects. ! 41: * The first word of the linker segment is a gc link ! 42: * pointer and does not point to a literal. The ! 43: * symbol binder is assumed to point to the second ! 44: * longword in this segment. The last word in the ! 45: * table is -1 as a sentinal to the gc marker. ! 46: * The number of real entries in the linker segment ! 47: * is given as the value of the linker_size symbol. ! 48: * Taking into account the 2 words required for the ! 49: * gc, there are 4*linker_size + 8 bytes in this segment. ! 50: * transfer segment - this is a transfer table block. It is used to ! 51: * allow compiled code to call other functions ! 52: * quickly. The number of entries in the transfer table is ! 53: * given as the value of the trans_size symbol. ! 54: * ! 55: * the following segments are set up in memory temporarily then flushed ! 56: * binder segment - a list of struct bindage entries. They describe ! 57: * what to do with the literals read from the literal ! 58: * table. The binder segment begins in the file ! 59: * following the bindorg symbol. ! 60: * literal segment - a list of characters which _Lread will read to ! 61: * create the lisp objects. The order of the literals ! 62: * is: ! 63: * linker literals - used to fill the linker segment. ! 64: * transfer table literals - used to fill the ! 65: * transfer segment ! 66: * binder literals - these include names of functions ! 67: * to bind interspersed with forms to evaluate. ! 68: * The meanings of the binder literals is given by ! 69: * the values in the binder segment. ! 70: * string segment - this is the string table from the file. We have ! 71: * to allocate space for it in core to speed up ! 72: * symbol referencing. ! 73: * ! 74: */ ! 75: ! 76: ! 77: /* external functions called or referenced */ ! 78: ! 79: lispval qcons(),qlinker(),qget(); ! 80: int _qf0(), _qf1(), _qf2(), _qf3(), _qf4(), _qfuncl(), svkludg(),qnewint(); ! 81: int qnewdoub(),qoneplus(),qoneminus(), wnaerr(); ! 82: lispval Lread(), Lcons(), Lminus(), Ladd1(), Lsub1(), Lplist(), Lputprop(); ! 83: lispval Lprint(), Lpatom(), Lconcat(), Lget(), Lmapc(), Lmapcan(); ! 84: lispval Llist(), Ladd(), Lgreaterp(), Lequal(), Ltimes(), Lsub(), Ipurcopy(); ! 85: lispval Lncons(), Ibindvars(), Iunbindvars(),error(); ! 86: int Inonlocalgo(); ! 87: lispval Istsrch(); ! 88: int mcount(), qpushframe(); ! 89: extern int mcnts[],mcntp,doprof; ! 90: ! 91: extern lispval *tynames[]; ! 92: extern struct frame *errp; ! 93: extern char _erthrow[]; ! 94: ! 95: extern int initflag; /* when TRUE, inhibits gc */ ! 96: ! 97: char *alloca(); /* stack space allocator */ ! 98: ! 99: /* mini symbol table, contains the only external symbols compiled code ! 100: is allowed to reference ! 101: */ ! 102: ! 103: ! 104: struct ssym { char *fnam; /* pointer to string containing name */ ! 105: int floc; /* address of symbol */ ! 106: int ord; /* ordinal number within cur sym tab */ ! 107: ! 108: } Symbtb[] ! 109: = { ! 110: "trantb", 0, -1, /* must be first */ ! 111: "linker", 0, -1, /* must be second */ ! 112: "mcount", (int) mcount, -1, ! 113: "mcnts", (int) mcnts, -1, ! 114: "_wnaerr", (int) wnaerr, -1, ! 115: "_qnewint", (int) qnewint, -1, ! 116: "_qnewdoub", (int) qnewdoub, -1, ! 117: "_qcons", (int) qcons, -1, ! 118: "_qoneplus", (int) qoneplus, -1, ! 119: "_qoneminus", (int) qoneminus, -1, ! 120: "_typetable", (int) typetable, -1, ! 121: "_tynames", (int) tynames, -1, ! 122: "_qget", (int) qget, -1, ! 123: "_errp", (int) &errp, -1, ! 124: "_Inonlocalgo", (int) Inonlocalgo, -1, ! 125: "__erthrow", (int) _erthrow, -1, ! 126: "_error", (int) error, -1, ! 127: "_qpushframe", (int) qpushframe, -1, ! 128: "_retval", (int)&retval, -1, ! 129: "_lispretval", (int)&lispretval,-1, ! 130: #ifndef NPINREG ! 131: "_np", (int) &np, -1, ! 132: "_lbot", (int) &lbot, -1, ! 133: #endif ! 134: #ifndef NILIS0 ! 135: "_nilatom", (int) &nilatom, -1, ! 136: #endif ! 137: "_bnp", (int) &bnp, -1, ! 138: "_Ibindvars", (int) Ibindvars, -1, ! 139: "_Iunbindvars", (int) Iunbindvars, -1 ! 140: }; ! 141: ! 142: #define SYMMAX ((sizeof Symbtb) / (sizeof (struct ssym))) ! 143: ! 144: #define roundup(x) (char *)(((int)x + 3) & ~3) /* round to longword boundary */ ! 145: ! 146: struct nlist syml; /* to read a.out symb tab */ ! 147: extern int *bind_lists; /* gc binding lists */ ! 148: ! 149: /* bindage structure: ! 150: * the bindage structure describes the linkages of functions and name, ! 151: * and tells which functions should be evaluated. It is mainly used ! 152: * for the non-fasl'ing of files, we only use one of the fields in fasl ! 153: */ ! 154: struct bindage ! 155: { ! 156: int b_type; /* type code, as described below */ ! 157: }; ! 158: ! 159: /* the possible values of b_type ! 160: * -1 - this is the end of the bindage entries ! 161: * 0 - this is a lambda function ! 162: * 1 - this is a nlambda function ! 163: * 2 - this is a macro function ! 164: * 99 - evaluate the string ! 165: * ! 166: */ ! 167: ! 168: ! 169: extern struct trtab *trhead; /* head of list of transfer tables */ ! 170: extern struct trent *trcur; /* next entry to allocate */ ! 171: extern int trleft; /* # of entries left in this transfer table */ ! 172: ! 173: struct trent *gettran(); /* function to allocate entries */ ! 174: ! 175: /* maximum number of functions */ ! 176: #define MAXFNS 2000 ! 177: ! 178: lispval Lfasl() ! 179: { ! 180: extern int holend,usehole; ! 181: extern int uctolc; ! 182: extern char *curhbeg; ! 183: struct argent *svnp; ! 184: struct exec exblk; /* stores a.out header */ ! 185: FILE *filp, *p, *map, *fstopen(); /* file pointer */ ! 186: int domap,note_redef; ! 187: lispval handy,debugmode; ! 188: struct relocation_info reloc; ! 189: struct trent *tranloc; ! 190: int trsize; ! 191: int i,j,times, *iptr; ! 192: int funloc[MAXFNS]; /* addresses of functions rel to txt org */ ! 193: int funcnt = 0; ! 194: ! 195: /* symbols whose values are taken from symbol table of .o file */ ! 196: int bind_org = 0; /* beginning of bind table */ ! 197: int lit_org = 0; /* beginning of literal table */ ! 198: int lit_end; /* end of literal table */ ! 199: int trans_size = 0; /* size in entries of transfer table */ ! 200: int linker_size; /* size in bytes of linker table ! 201: (not counting gc ptr) */ ! 202: ! 203: /* symbols which hold the locations of the segments in core and ! 204: * in the file ! 205: */ ! 206: char *code_core_org, /* beginning of code segment */ ! 207: *lc_org, /* beginning of linker segment */ ! 208: *lc_end, /* last word in linker segment */ ! 209: *literal_core_org, /* beginning of literal table */ ! 210: *binder_core_org, /* beginning of binder table */ ! 211: *string_core_org; ! 212: ! 213: int /*string_file_org, /* location of string table in file */ ! 214: string_size, /* number of chars in string table */ ! 215: segsiz; /* size of permanent incore segment */ ! 216: ! 217: char *symbol_name; ! 218: struct bindage *curbind; ! 219: lispval rdform, *linktab; ! 220: int ouctolc; ! 221: int debug = 0; ! 222: lispval currtab,curibase; ! 223: char ch,*filnm,*nfilnm; ! 224: char tempfilbf[100]; ! 225: char *strcat(); ! 226: long lseek(); ! 227: Keepxs(); ! 228: ! 229: ! 230: switch(np-lbot) { ! 231: case 0: ! 232: protect(nil); ! 233: case 1: ! 234: protect(nil); ! 235: case 2: ! 236: protect(nil); ! 237: case 3: ! 238: break; ! 239: default: ! 240: argerr("fasl"); ! 241: } ! 242: filnm = (char *) verify(lbot->val,"fasl: non atom arg"); ! 243: ! 244: ! 245: domap = FALSE; ! 246: /* debugging */ ! 247: debugmode = Istsrch(matom("debugging"))->d.cdr->d.cdr->d.cdr; ! 248: if (debugmode != nil) debug = 1; ! 249: /* end debugging */ ! 250: ! 251: ! 252: /* insure that the given file name ends in .o ! 253: if it doesnt, copy to a new buffer and add a .o ! 254: but Allow non .o file names (5mar80 jkf) ! 255: */ ! 256: tempfilbf[0] = '\0'; ! 257: nfilnm = filnm; /* same file name for now */ ! 258: if( (i = strlen(filnm)) < 2 || ! 259: strcmp(filnm+i-2,".o") != 0) ! 260: { ! 261: strncat(tempfilbf,filnm,96); ! 262: strcat(tempfilbf,".o"); ! 263: nfilnm = tempfilbf; ! 264: } ! 265: ! 266: if ( (filp = fopen(nfilnm,"r")) == NULL) ! 267: if ((filnm == nfilnm) || ((filp = fopen(filnm,"r")) == NULL)) ! 268: errorh1(Vermisc,"Can't open file",nil,FALSE,9797,lbot->val); ! 269: ! 270: if ((handy = (lbot+1)->val) != nil ) ! 271: { ! 272: if((TYPE(handy) != ATOM ) || ! 273: (map = fopen(handy->a.pname, ! 274: (Istsrch(matom("appendmap"))->d.cdr->d.cdr->d.cdr == nil ! 275: ? "w" : "a"))) == NULL) ! 276: error("fasl: can't open map file",FALSE); ! 277: else ! 278: { domap = TRUE; ! 279: /* fprintf(map,"Map of file %s\n",lbot->val->a.pname); */ ! 280: } ! 281: } ! 282: ! 283: /* set the note redefinition flag */ ! 284: if((lbot+2)->val != nil) note_redef = TRUE; ! 285: else note_redef = FALSE; ! 286: ! 287: /* if nil don't print fasl message */ ! 288: if ( Vldprt->a.clb != nil ) { ! 289: printf("[fasl %s]",filnm); ! 290: fflush(stdout); ! 291: } ! 292: svnp = np; ! 293: ! 294: ! 295: ! 296: /* clear the ords in the symbol table */ ! 297: for(i=0 ; i < SYMMAX ; i++) Symbtb[i].ord = -1; ! 298: ! 299: if( read(fileno(filp),(char *)&exblk,sizeof(struct exec)) ! 300: != sizeof(struct exec)) ! 301: error("fasl: header read failed",FALSE); ! 302: ! 303: /* check that the magic number is valid */ ! 304: ! 305: if(exblk.a_magic != 0407) ! 306: errorh1(Vermisc,"fasl: file is not a lisp object file (bad magic number): ", ! 307: nil,FALSE,0,lbot->val); ! 308: ! 309: /* read in string table */ ! 310: lseek(fileno(filp),(long)(/*string_file_org =*/N_STROFF(exblk)),0); ! 311: if( read(fileno(filp), (char *)&string_size , 4) != 4) ! 312: error("fasl: string table read error, probably old fasl format", FALSE); ! 313: ! 314: lbot = np; /* set up base for later calls */ ! 315: /* allocate space for string table on the stack */ ! 316: string_core_org = alloca(string_size - 4); ! 317: ! 318: if( read(fileno(filp), string_core_org , string_size - 4) ! 319: != string_size -4) error("fasl: string table read error ",FALSE); ! 320: /* read in symbol table and set the ordinal values */ ! 321: ! 322: fseek(filp,(long) (N_SYMOFF(exblk)),0); ! 323: ! 324: times = exblk.a_syms/sizeof(struct nlist); ! 325: if(debug) printf(" %d symbols in symbol table\n",times); ! 326: ! 327: for(i=0; i < times ; i++) ! 328: { ! 329: if( fread((char *)&syml,sizeof(struct nlist),1,filp) != 1) ! 330: error("fasl: Symb tab read error",FALSE); ! 331: ! 332: symbol_name = syml.n_un.n_strx - 4 + string_core_org; ! 333: if(debug) printf("symbol %s\n read\n",symbol_name); ! 334: if (syml.n_type == N_EXT) ! 335: { ! 336: for(j=0; j< SYMMAX; j++) ! 337: { ! 338: if((Symbtb[j].ord < 0) ! 339: && strcmp(Symbtb[j].fnam,symbol_name)==0) ! 340: { Symbtb[j].ord = i; ! 341: if(debug)printf("symbol %s ord is %d\n",symbol_name,i); ! 342: break; ! 343: }; ! 344: ! 345: }; ! 346: ! 347: if( j>=SYMMAX ) printf("Unknown symbol %s\n",symbol_name); ! 348: } ! 349: else if (((ch = symbol_name[0]) == 's') ! 350: || (ch == 'L') ! 351: || (ch == '.') ) ; /* skip this */ ! 352: else if (symbol_name[0] == 'F') ! 353: { ! 354: if(funcnt >= MAXFNS) ! 355: error("fasl: too many function in file",FALSE); ! 356: funloc[funcnt++] = syml.n_value; /* seeing function */ ! 357: } ! 358: else if (!bind_org && (strcmp(symbol_name, "bind_org") == 0)) ! 359: bind_org = syml.n_value; ! 360: else if (strcmp(symbol_name, "lit_org") == 0) ! 361: lit_org = syml.n_value; ! 362: else if (strcmp(symbol_name, "lit_end") == 0) ! 363: lit_end = syml.n_value; ! 364: else if (strcmp(symbol_name, "trans_size") == 0) ! 365: trans_size = syml.n_value; ! 366: else if (strcmp(symbol_name, "linker_size") == 0) ! 367: linker_size = syml.n_value; ! 368: } ! 369: ! 370: #if m_68k ! 371: /* 68k only, on the vax the symbols appear in the correct order */ ! 372: { int compar(); ! 373: qsort(funloc,funcnt,sizeof(int),compar); ! 374: } ! 375: #endif ! 376: ! 377: if (debug) ! 378: printf("lit_org %x, lit_end %x, bind_org %x, linker_size %x\n", ! 379: lit_org, lit_end, bind_org, linker_size); ! 380: /* check to make sure we are working with the right format */ ! 381: if((lit_org == 0) || (lit_end == 0)) ! 382: errorh1(Vermisc,"File not in new fasl format",nil,FALSE,0,lbot->val); ! 383: ! 384: /*----------------*/ ! 385: ! 386: /* read in text segment up to beginning of binder table */ ! 387: ! 388: segsiz = bind_org + 4*linker_size + 8 + 3; /* size is core segment size ! 389: * plus linker table size ! 390: * plus 2 for gc list ! 391: * plus 3 to round up to word ! 392: */ ! 393: ! 394: lseek(fileno(filp),(long)sizeof(struct exec),0); ! 395: code_core_org = (char *) csegment(OTHER,segsiz,TRUE); ! 396: if(read(fileno(filp),code_core_org,bind_org) != bind_org) ! 397: error("Read error in text ",FALSE); ! 398: ! 399: if(debug) { ! 400: printf("Read %d bytes of text into 0x%x\n",bind_org,code_core_org); ! 401: printf(" incore segment size: %d (0x%x)\n",segsiz,segsiz); ! 402: } ! 403: ! 404: /* linker table is 2 entries (8 bytes) larger than the number of ! 405: * entries given by linker_size . There must be a gc word at ! 406: * the beginning and a -1 at the end ! 407: */ ! 408: lc_org = roundup(code_core_org + bind_org); ! 409: lc_end = lc_org + 4*linker_size + 4; ! 410: /* address of gc sentinal last */ ! 411: ! 412: if(debug)printf("lin_cor_org: %x, link_cor_end %x\n", ! 413: lc_org, ! 414: lc_end); ! 415: Symbtb[1].floc = (int) (lc_org + 4); ! 416: ! 417: /* set the linker table to all -1's so we can put in the gc table */ ! 418: for( iptr = (int *)(lc_org + 4 ); ! 419: iptr <= (int *)(lc_end); ! 420: iptr++) ! 421: *iptr = -1; ! 422: ! 423: ! 424: /* link our table into the gc tables */ ! 425: /* only do so if we will not purcopy these tables */ ! 426: if(Vpurcopylits->a.clb == nil) ! 427: { ! 428: *(int *)lc_org = (int)bind_lists; /* point to current */ ! 429: bind_lists = (int *) (lc_org + 4); /* point to first ! 430: item */ ! 431: } ! 432: ! 433: /* read the binder table and literals onto the stack */ ! 434: ! 435: binder_core_org = alloca(lit_end - bind_org); ! 436: read(fileno(filp),binder_core_org,lit_end-bind_org); ! 437: ! 438: literal_core_org = binder_core_org + lit_org - bind_org; ! 439: ! 440: /* check if there is a transfer table required for this ! 441: * file, and if so allocate one of the necessary size ! 442: */ ! 443: ! 444: if(trans_size > 0) ! 445: { ! 446: tranloc = gettran(trans_size); ! 447: Symbtb[0].floc = (int) tranloc; ! 448: } ! 449: ! 450: /* now relocate the necessary symbols in the text segment */ ! 451: ! 452: fseek(filp,(long)(sizeof(struct exec) + exblk.a_text + exblk.a_data),0); ! 453: times = (exblk.a_trsize)/sizeof(struct relocation_info); ! 454: ! 455: /* the only symbols we will relocate are references to ! 456: external symbols. They are recognized by ! 457: extern and pcrel set. ! 458: */ ! 459: ! 460: for( i=1; i<=times ; i++) ! 461: { ! 462: if( fread((char *)&reloc,sizeof(struct relocation_info),1,filp) != 1) ! 463: error("Bad text reloc read",FALSE); ! 464: if(reloc.r_extern) ! 465: { ! 466: for(j=0; j < SYMMAX; j++) ! 467: { ! 468: ! 469: if(Symbtb[j].ord == reloc.r_symbolnum) /* look for this sym */ ! 470: { ! 471: #define offset(p) (((p).r_pcrel) ? ((int) code_core_org): 0) ! 472: if(debug) printf("Relocating %d (ord %d) at %x\n", ! 473: j, Symbtb[j].ord, reloc.r_address); ! 474: if (Symbtb[j].floc == (int) mcnts) { ! 475: add_offset((int *)(code_core_org + reloc.r_address), ! 476: mcntp - offset(reloc)); ! 477: if(doprof){ ! 478: if (mcntp == (int) &mcnts[NMCOUNT-2]) ! 479: printf("Ran out of counters; increas NMCOUNT in fasl.c\n"); ! 480: if (mcntp < (int) &mcnts[NMCOUNT-1]) ! 481: mcntp += 4; ! 482: } ! 483: } else ! 484: add_offset((int *)(code_core_org + reloc.r_address), ! 485: Symbtb[j].floc - offset(reloc)); ! 486: ! 487: break; ! 488: ! 489: } ! 490: }; ! 491: if( j >= SYMMAX) if(debug) printf("Couldnt find ord # %d\n", ! 492: reloc.r_symbolnum); ! 493: } ! 494: ! 495: } ! 496: ! 497: if ( Vldprt->a.clb != nil ) { ! 498: putchar('\n'); ! 499: fflush(stdout); ! 500: } ! 501: ! 502: /* set up a fake port so we can read from core */ ! 503: /* first find a free port */ ! 504: ! 505: p = fstopen((char *) literal_core_org, lit_end - lit_org, "r"); ! 506: ! 507: if(debug)printf("lit_org %d, charstrt %d\n",lit_org, p->_base); ! 508: /* the first forms we wish to read are those literals in the ! 509: * literal table, that is those forms referenced by an offset ! 510: * from r8 in compiled code ! 511: */ ! 512: ! 513: /* to read in the forms correctly, we must set up the read table ! 514: */ ! 515: currtab = Vreadtable->a.clb; ! 516: Vreadtable->a.clb = strtab; /* standard read table */ ! 517: curibase = ibase->a.clb; ! 518: ibase->a.clb = inewint(10); /* read in decimal */ ! 519: ouctolc = uctolc; /* remember value of uctolc flag */ ! 520: ! 521: PUSHDOWN(gcdis,tatom); /* turn off gc */ ! 522: ! 523: i = 1; ! 524: linktab = (lispval *)(lc_org +4); ! 525: while (linktab < (lispval *)lc_end) ! 526: { ! 527: np = svnp; ! 528: protect(P(p)); ! 529: uctolc = FALSE; ! 530: handy = (lispval)Lread(); ! 531: if (Vpurcopylits->a.clb != nil) { ! 532: handy = Ipurcopy(handy); ! 533: } ! 534: uctolc = ouctolc; ! 535: getc(p); /* eat trailing blank */ ! 536: if(debugmode != nil) ! 537: { printf("form %d read: ",i++); ! 538: printr(handy,stdout); ! 539: putchar('\n'); ! 540: fflush(stdout); ! 541: } ! 542: *linktab++ = handy; ! 543: } ! 544: ! 545: /* process the transfer table if one is used */ ! 546: trsize = trans_size; ! 547: while(trsize--) ! 548: { ! 549: np = svnp; ! 550: protect(P(p)); ! 551: uctolc = FALSE; ! 552: handy = Lread(); /* get function name */ ! 553: uctolc = ouctolc; ! 554: getc(p); ! 555: tranloc->name = handy; ! 556: tranloc->fcn = qlinker; /* initially go to qlinker */ ! 557: tranloc++; ! 558: } ! 559: ! 560: ! 561: ! 562: /* now process the binder table, which contains pointers to ! 563: functions to link in and forms to evaluate. ! 564: */ ! 565: funcnt = 0; ! 566: ! 567: curbind = (struct bindage *) binder_core_org; ! 568: for( ; curbind->b_type != -1 ; curbind++) ! 569: { ! 570: np = svnp; ! 571: protect(P(p)); ! 572: uctolc = FALSE; /* inhibit uctolc conversion */ ! 573: rdform = Lread(); ! 574: /* debugging */ ! 575: if(debugmode != nil) { printf("link form read: "); ! 576: printr(rdform,stdout); ! 577: printf(" ,type: %d\n", ! 578: curbind->b_type); ! 579: fflush(stdout); ! 580: } ! 581: /* end debugging */ ! 582: uctolc = ouctolc; /* restore previous state */ ! 583: getc(p); /* eat trailing null */ ! 584: protect(rdform); ! 585: if(curbind->b_type <= 2) /* if function type */ ! 586: { ! 587: handy = newfunct(); ! 588: if (note_redef && (rdform->a.fnbnd != nil)) ! 589: { ! 590: printr(rdform,stdout); ! 591: printf(" redefined\n"); ! 592: } ! 593: rdform->a.fnbnd = handy; ! 594: handy->bcd.start = (lispval (*)())(code_core_org + funloc[funcnt++]); ! 595: handy->bcd.discipline = ! 596: (curbind->b_type == 0 ? lambda : ! 597: curbind->b_type == 1 ? nlambda : ! 598: macro); ! 599: if(domap) { ! 600: fprintf(map,"%s\n%x\n",rdform->a.pname,handy->bcd.start); ! 601: } ! 602: } ! 603: else { ! 604: Vreadtable->a.clb = currtab; ! 605: ibase->a.clb = curibase; ! 606: ! 607: /* debugging */ ! 608: if(debugmode != nil) { ! 609: printf("Eval: "); ! 610: printr(rdform,stdout); ! 611: printf("\n"); ! 612: fflush(stdout); ! 613: }; ! 614: /* end debugging */ ! 615: ! 616: eval(rdform); /* otherwise eval it */ ! 617: ! 618: if(uctolc) ouctolc = TRUE; /* if changed by eval, remember */ ! 619: curibase = ibase->a.clb; ! 620: ibase->a.clb = inewint(10); ! 621: Vreadtable->a.clb = strtab; ! 622: } ! 623: }; ! 624: ! 625: fclose(p); /* give up file descriptor */ ! 626: ! 627: POP; /* restore state of gcdisable variable */ ! 628: ! 629: Vreadtable->a.clb = currtab; ! 630: chkrtab(currtab); ! 631: ibase->a.clb = curibase; ! 632: ! 633: fclose(filp); ! 634: if(domap) fclose(map); ! 635: Freexs(); ! 636: return(tatom); ! 637: } ! 638: ! 639: #if m_68k ! 640: /* function used in qsort for 68k version only */ ! 641: compar(arg1,arg2) ! 642: int *arg1,*arg2; ! 643: { ! 644: if(*arg1 < *arg2) return (-1); ! 645: else if (*arg1 == *arg2) return (0); ! 646: else return(1); ! 647: } ! 648: #endif ! 649: ! 650: /* gettran :: allocate a segment of transfer table of the given size */ ! 651: ! 652: struct trent * ! 653: gettran(size) ! 654: { ! 655: struct trtab *trp; ! 656: struct trent *retv; ! 657: int ousehole; ! 658: extern int usehole; ! 659: ! 660: if(size > TRENTS) ! 661: error("transfer table too large",FALSE); ! 662: ! 663: if(size > trleft) ! 664: { ! 665: /* allocate a new transfer table */ ! 666: /* must not allocate in the hole or we cant modify it */ ! 667: ousehole = usehole; /* remember old value */ ! 668: usehole = FALSE; ! 669: trp = (struct trtab *)csegment(OTHER,sizeof(struct trtab),FALSE); ! 670: usehole = ousehole; ! 671: ! 672: trp->sentinal = 0; /* make sure the sentinal is 0 */ ! 673: trp->nxtt = trhead; /* link at beginning of table */ ! 674: trhead = trp; ! 675: trcur = &(trp->trentrs[0]); /* begin allocating here */ ! 676: trleft = TRENTS; ! 677: } ! 678: ! 679: trleft = trleft - size; ! 680: retv = trcur; ! 681: trcur = trcur + size; ! 682: return(retv); ! 683: } ! 684: ! 685: /* clrtt :: clear transfer tables, or link them all up; ! 686: * this has two totally opposite functions: ! 687: * 1) all transfer tables are reset so that all function calls will go ! 688: * through qlinker ! 689: * 2) as many transfer tables are set up to point to bcd functions ! 690: * as possible ! 691: */ ! 692: clrtt(flag) ! 693: { ! 694: /* flag = 0 :: set to qlinker ! 695: * flag = 1 :: set to function bcd binding if possible ! 696: */ ! 697: register struct trtab *temptt; ! 698: register struct trent *tement; ! 699: register lispval fnb; ! 700: ! 701: for (temptt = trhead; temptt != 0 ; temptt = temptt->nxtt) ! 702: { ! 703: for(tement = &temptt->trentrs[0] ; tement->fcn != 0 ; tement++) ! 704: { if(flag == 0 || TYPE(fnb=tement->name->a.fnbnd) != BCD ! 705: || TYPE(fnb->bcd.discipline) == STRNG) ! 706: tement->fcn = qlinker; ! 707: else tement->fcn = fnb->bcd.start; ! 708: } ! 709: } ! 710: } ! 711: ! 712: /* chktt - builds a list of transfer table entries which don't yet have ! 713: a function associated with them, i.e if this transfer table entry ! 714: were used, an undefined function error would result ! 715: */ ! 716: lispval ! 717: chktt() ! 718: { ! 719: register struct trtab *temptt; ! 720: register struct trent *tement; ! 721: register lispval retlst,curv; ! 722: Savestack(4); ! 723: ! 724: retlst = newdot(); /* build list of undef functions */ ! 725: protect(retlst); ! 726: for (temptt = trhead; temptt != 0 ; temptt = temptt->nxtt) ! 727: { ! 728: for(tement = &temptt->trentrs[0] ; tement->fcn != 0 ; tement++) ! 729: { ! 730: if(tement->name->a.fnbnd == nil) ! 731: { ! 732: curv= newdot(); ! 733: curv->d.car = tement->name; ! 734: curv->d.cdr = retlst->d.cdr; ! 735: retlst->d.cdr = curv; ! 736: } ! 737: } ! 738: } ! 739: Restorestack(); ! 740: return(retlst->d.cdr); ! 741: } ! 742: ! 743: /* since the tahoe machine is picky about word/longword alignment ! 744: ** when it is doing data access but not when doing instruction fetches, ! 745: ** we have to add the relocation offset in a slightly different manner. ! 746: */ ! 747: #ifdef tahoe ! 748: add_offset(addr, relocoffset) ! 749: register int *addr; ! 750: {register int r11, r10, r9, r8; ! 751: asm(" cvtbl (r12), r0"); ! 752: asm(" cvtbl 8(fp), r1"); ! 753: asm(" cvtbl 1(r12), r8"); ! 754: asm(" cvtbl 9(fp), r9"); ! 755: asm(" cvtbl 2(r12), r10"); ! 756: asm(" cvtbl 10(fp), r11"); ! 757: asm(" addb2 11(fp), 3(r12)"); /* add least sig. bytes */ ! 758: asm(" adwc r11, r10"); ! 759: asm(" adwc r9, r8"); ! 760: asm(" adwc r1, r0"); ! 761: asm(" cvtlb r10, 2(r12)"); ! 762: asm(" cvtlb r8, 1(r12)"); ! 763: asm(" cvtlb r0,(r12)"); ! 764: } ! 765: #else ! 766: add_offset(addr, relocoffset) ! 767: register int *addr; ! 768: { ! 769: *addr += relocoffset; ! 770: } ! 771: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.