|
|
1.1 root 1: #ifndef lint
2: static char *rcsid =
3: "$Header: fasl.c,v 1.10 85/03/24 11:03:34 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: struct nlist syml; /* to read a.out symb tab */
145: extern int *bind_lists; /* gc binding lists */
146:
147: /* bindage structure:
148: * the bindage structure describes the linkages of functions and name,
149: * and tells which functions should be evaluated. It is mainly used
150: * for the non-fasl'ing of files, we only use one of the fields in fasl
151: */
152: struct bindage
153: {
154: int b_type; /* type code, as described below */
155: };
156:
157: /* the possible values of b_type
158: * -1 - this is the end of the bindage entries
159: * 0 - this is a lambda function
160: * 1 - this is a nlambda function
161: * 2 - this is a macro function
162: * 99 - evaluate the string
163: *
164: */
165:
166:
167: extern struct trtab *trhead; /* head of list of transfer tables */
168: extern struct trent *trcur; /* next entry to allocate */
169: extern int trleft; /* # of entries left in this transfer table */
170:
171: struct trent *gettran(); /* function to allocate entries */
172:
173: /* maximum number of functions */
174: #define MAXFNS 2000
175:
176: lispval Lfasl()
177: {
178: extern int holend,usehole;
179: extern int uctolc;
180: extern char *curhbeg;
181: struct argent *svnp;
182: struct exec exblk; /* stores a.out header */
183: FILE *filp, *p, *map, *fstopen(); /* file pointer */
184: int domap,note_redef;
185: lispval handy,debugmode;
186: struct relocation_info reloc;
187: struct trent *tranloc;
188: int trsize;
189: int i,j,times, *iptr;
190: int funloc[MAXFNS]; /* addresses of functions rel to txt org */
191: int funcnt = 0;
192:
193: /* symbols whose values are taken from symbol table of .o file */
194: int bind_org = 0; /* beginning of bind table */
195: int lit_org = 0; /* beginning of literal table */
196: int lit_end; /* end of literal table */
197: int trans_size = 0; /* size in entries of transfer table */
198: int linker_size; /* size in bytes of linker table
199: (not counting gc ptr) */
200:
201: /* symbols which hold the locations of the segments in core and
202: * in the file
203: */
204: char *code_core_org, /* beginning of code segment */
205: *lc_org, /* beginning of linker segment */
206: *lc_end, /* last word in linker segment */
207: *literal_core_org, /* beginning of literal table */
208: *binder_core_org, /* beginning of binder table */
209: *string_core_org;
210:
211: int /*string_file_org, /* location of string table in file */
212: string_size, /* number of chars in string table */
213: segsiz; /* size of permanent incore segment */
214:
215: char *symbol_name;
216: struct bindage *curbind;
217: lispval rdform, *linktab;
218: int ouctolc;
219: int debug = 0;
220: lispval currtab,curibase;
221: char ch,*filnm,*nfilnm;
222: char tempfilbf[100];
223: char *strcat();
224: long lseek();
225: Keepxs();
226:
227:
228: switch(np-lbot) {
229: case 0:
230: protect(nil);
231: case 1:
232: protect(nil);
233: case 2:
234: protect(nil);
235: case 3:
236: break;
237: default:
238: argerr("fasl");
239: }
240: filnm = (char *) verify(lbot->val,"fasl: non atom arg");
241:
242:
243: domap = FALSE;
244: /* debugging */
245: debugmode = Istsrch(matom("debugging"))->d.cdr->d.cdr->d.cdr;
246: if (debugmode != nil) debug = 1;
247: /* end debugging */
248:
249:
250: /* insure that the given file name ends in .o
251: if it doesnt, copy to a new buffer and add a .o
252: but Allow non .o file names (5mar80 jkf)
253: */
254: tempfilbf[0] = '\0';
255: nfilnm = filnm; /* same file name for now */
256: if( (i = strlen(filnm)) < 2 ||
257: strcmp(filnm+i-2,".o") != 0)
258: {
259: strncat(tempfilbf,filnm,96);
260: strcat(tempfilbf,".o");
261: nfilnm = tempfilbf;
262: }
263:
264: if ( (filp = fopen(nfilnm,"r")) == NULL)
265: if ((filnm == nfilnm) || ((filp = fopen(filnm,"r")) == NULL))
266: errorh1(Vermisc,"Can't open file",nil,FALSE,9797,lbot->val);
267:
268: if ((handy = (lbot+1)->val) != nil )
269: {
270: if((TYPE(handy) != ATOM ) ||
271: (map = fopen(handy->a.pname,
272: (Istsrch(matom("appendmap"))->d.cdr->d.cdr->d.cdr == nil
273: ? "w" : "a"))) == NULL)
274: error("fasl: can't open map file",FALSE);
275: else
276: { domap = TRUE;
277: /* fprintf(map,"Map of file %s\n",lbot->val->a.pname); */
278: }
279: }
280:
281: /* set the note redefinition flag */
282: if((lbot+2)->val != nil) note_redef = TRUE;
283: else note_redef = FALSE;
284:
285: /* if nil don't print fasl message */
286: if ( Vldprt->a.clb != nil ) {
287: printf("[fasl %s]",filnm);
288: fflush(stdout);
289: }
290: svnp = np;
291:
292:
293:
294: /* clear the ords in the symbol table */
295: for(i=0 ; i < SYMMAX ; i++) Symbtb[i].ord = -1;
296:
297: if( read(fileno(filp),(char *)&exblk,sizeof(struct exec))
298: != sizeof(struct exec))
299: error("fasl: header read failed",FALSE);
300:
301: /* check that the magic number is valid */
302:
303: if(exblk.a_magic != 0407)
304: errorh1(Vermisc,"fasl: file is not a lisp object file (bad magic number): ",
305: nil,FALSE,0,lbot->val);
306:
307: /* read in string table */
308: lseek(fileno(filp),(long)(/*string_file_org =*/N_STROFF(exblk)),0);
309: if( read(fileno(filp), (char *)&string_size , 4) != 4)
310: error("fasl: string table read error, probably old fasl format", FALSE);
311:
312: lbot = np; /* set up base for later calls */
313: /* allocate space for string table on the stack */
314: string_core_org = alloca(string_size - 4);
315:
316: if( read(fileno(filp), string_core_org , string_size - 4)
317: != string_size -4) error("fasl: string table read error ",FALSE);
318: /* read in symbol table and set the ordinal values */
319:
320: fseek(filp,(long) (N_SYMOFF(exblk)),0);
321:
322: times = exblk.a_syms/sizeof(struct nlist);
323: if(debug) printf(" %d symbols in symbol table\n",times);
324:
325: for(i=0; i < times ; i++)
326: {
327: if( fread((char *)&syml,sizeof(struct nlist),1,filp) != 1)
328: error("fasl: Symb tab read error",FALSE);
329:
330: symbol_name = syml.n_un.n_strx - 4 + string_core_org;
331: if(debug) printf("symbol %s\n read\n",symbol_name);
332: if (syml.n_type == N_EXT)
333: {
334: for(j=0; j< SYMMAX; j++)
335: {
336: if((Symbtb[j].ord < 0)
337: && strcmp(Symbtb[j].fnam,symbol_name)==0)
338: { Symbtb[j].ord = i;
339: if(debug)printf("symbol %s ord is %d\n",symbol_name,i);
340: break;
341: };
342:
343: };
344:
345: if( j>=SYMMAX ) printf("Unknown symbol %s\n",symbol_name);
346: }
347: else if (((ch = symbol_name[0]) == 's')
348: || (ch == 'L')
349: || (ch == '.') ) ; /* skip this */
350: else if (symbol_name[0] == 'F')
351: {
352: if(funcnt >= MAXFNS)
353: error("fasl: too many function in file",FALSE);
354: funloc[funcnt++] = syml.n_value; /* seeing function */
355: }
356: else if (!bind_org && (strcmp(symbol_name, "bind_org") == 0))
357: bind_org = syml.n_value;
358: else if (strcmp(symbol_name, "lit_org") == 0)
359: lit_org = syml.n_value;
360: else if (strcmp(symbol_name, "lit_end") == 0)
361: lit_end = syml.n_value;
362: else if (strcmp(symbol_name, "trans_size") == 0)
363: trans_size = syml.n_value;
364: else if (strcmp(symbol_name, "linker_size") == 0)
365: linker_size = syml.n_value;
366: }
367:
368: #if m_68k
369: /* 68k only, on the vax the symbols appear in the correct order */
370: { int compar();
371: qsort(funloc,funcnt,sizeof(int),compar);
372: }
373: #endif
374:
375: if (debug)
376: printf("lit_org %x, lit_end %x, bind_org %x, linker_size %x\n",
377: lit_org, lit_end, bind_org, linker_size);
378: /* check to make sure we are working with the right format */
379: if((lit_org == 0) || (lit_end == 0))
380: errorh1(Vermisc,"File not in new fasl format",nil,FALSE,0,lbot->val);
381:
382: /*----------------*/
383:
384: /* read in text segment up to beginning of binder table */
385:
386: segsiz = bind_org + 4*linker_size + 8 + 3; /* size is core segment size
387: * plus linker table size
388: * plus 2 for gc list
389: * plus 3 to round up to word
390: */
391:
392: lseek(fileno(filp),(long)sizeof(struct exec),0);
393: code_core_org = (char *) csegment(OTHER,segsiz,TRUE);
394: if(read(fileno(filp),code_core_org,bind_org) != bind_org)
395: error("Read error in text ",FALSE);
396:
397: if(debug) {
398: printf("Read %d bytes of text into 0x%x\n",bind_org,code_core_org);
399: printf(" incore segment size: %d (0x%x)\n",segsiz,segsiz);
400: }
401:
402: /* linker table is 2 entries (8 bytes) larger than the number of
403: * entries given by linker_size . There must be a gc word at
404: * the beginning and a -1 at the end
405: */
406: lc_org = code_core_org + bind_org;
407: lc_end = lc_org + 4*linker_size + 4;
408: /* address of gc sentinal last */
409:
410: if(debug)printf("lin_cor_org: %x, link_cor_end %x\n",
411: lc_org,
412: lc_end);
413: Symbtb[1].floc = (int) (lc_org + 4);
414:
415: /* set the linker table to all -1's so we can put in the gc table */
416: for( iptr = (int *)(lc_org + 4 );
417: iptr <= (int *)(lc_end);
418: iptr++)
419: *iptr = -1;
420:
421:
422: /* link our table into the gc tables */
423: /* only do so if we will not purcopy these tables */
424: if(Vpurcopylits->a.clb == nil)
425: {
426: *(int *)lc_org = (int)bind_lists; /* point to current */
427: bind_lists = (int *) (lc_org + 4); /* point to first
428: item */
429: }
430:
431: /* read the binder table and literals onto the stack */
432:
433: binder_core_org = alloca(lit_end - bind_org);
434: read(fileno(filp),binder_core_org,lit_end-bind_org);
435:
436: literal_core_org = binder_core_org + lit_org - bind_org;
437:
438: /* check if there is a transfer table required for this
439: * file, and if so allocate one of the necessary size
440: */
441:
442: if(trans_size > 0)
443: {
444: tranloc = gettran(trans_size);
445: Symbtb[0].floc = (int) tranloc;
446: }
447:
448: /* now relocate the necessary symbols in the text segment */
449:
450: fseek(filp,(long)(sizeof(struct exec) + exblk.a_text + exblk.a_data),0);
451: times = (exblk.a_trsize)/sizeof(struct relocation_info);
452:
453: /* the only symbols we will relocate are references to
454: external symbols. They are recognized by
455: extern and pcrel set.
456: */
457:
458: for( i=1; i<=times ; i++)
459: {
460: if( fread((char *)&reloc,sizeof(struct relocation_info),1,filp) != 1)
461: error("Bad text reloc read",FALSE);
462: if(reloc.r_extern)
463: {
464: for(j=0; j < SYMMAX; j++)
465: {
466:
467: if(Symbtb[j].ord == reloc.r_symbolnum) /* look for this sym */
468: {
469: #define offset(p) (((p).r_pcrel) ? ((int) code_core_org): 0)
470: if(debug && FALSE) printf("Relocating %d (ord %d) at %x\n",
471: j, Symbtb[j].ord, reloc.r_address);
472: if (Symbtb[j].floc == (int) mcnts) {
473: *(int *)(code_core_org+reloc.r_address)
474: += mcntp - offset(reloc);
475: if(doprof){
476: if (mcntp == (int) &mcnts[NMCOUNT-2])
477: printf("Ran out of counters; increas NMCOUNT in fasl.c\n");
478: if (mcntp < (int) &mcnts[NMCOUNT-1])
479: mcntp += 4;
480: }
481: } else
482: *(int *)(code_core_org+reloc.r_address)
483: += Symbtb[j].floc - offset(reloc);
484:
485: break;
486:
487: }
488: };
489: if( j >= SYMMAX) if(debug) printf("Couldnt find ord # %d\n",
490: reloc.r_symbolnum);
491: }
492:
493: }
494:
495: if ( Vldprt->a.clb != nil ) {
496: putchar('\n');
497: fflush(stdout);
498: }
499:
500: /* set up a fake port so we can read from core */
501: /* first find a free port */
502:
503: p = fstopen((char *) literal_core_org, lit_end - lit_org, "r");
504:
505: if(debug)printf("lit_org %d, charstrt %d\n",lit_org, p->_base);
506: /* the first forms we wish to read are those literals in the
507: * literal table, that is those forms referenced by an offset
508: * from r8 in compiled code
509: */
510:
511: /* to read in the forms correctly, we must set up the read table
512: */
513: currtab = Vreadtable->a.clb;
514: Vreadtable->a.clb = strtab; /* standard read table */
515: curibase = ibase->a.clb;
516: ibase->a.clb = inewint(10); /* read in decimal */
517: ouctolc = uctolc; /* remember value of uctolc flag */
518:
519: PUSHDOWN(gcdis,tatom); /* turn off gc */
520:
521: i = 1;
522: linktab = (lispval *)(lc_org +4);
523: while (linktab < (lispval *)lc_end)
524: {
525: np = svnp;
526: protect(P(p));
527: uctolc = FALSE;
528: handy = (lispval)Lread();
529: if (Vpurcopylits->a.clb != nil) {
530: handy = Ipurcopy(handy);
531: }
532: uctolc = ouctolc;
533: getc(p); /* eat trailing blank */
534: if(debugmode != nil)
535: { printf("form %d read: ",i++);
536: printr(handy,stdout);
537: putchar('\n');
538: fflush(stdout);
539: }
540: *linktab++ = handy;
541: }
542:
543: /* process the transfer table if one is used */
544: trsize = trans_size;
545: while(trsize--)
546: {
547: np = svnp;
548: protect(P(p));
549: uctolc = FALSE;
550: handy = Lread(); /* get function name */
551: uctolc = ouctolc;
552: getc(p);
553: tranloc->name = handy;
554: tranloc->fcn = qlinker; /* initially go to qlinker */
555: tranloc++;
556: }
557:
558:
559:
560: /* now process the binder table, which contains pointers to
561: functions to link in and forms to evaluate.
562: */
563: funcnt = 0;
564:
565: curbind = (struct bindage *) binder_core_org;
566: for( ; curbind->b_type != -1 ; curbind++)
567: {
568: np = svnp;
569: protect(P(p));
570: uctolc = FALSE; /* inhibit uctolc conversion */
571: rdform = Lread();
572: /* debugging */
573: if(debugmode != nil) { printf("link form read: ");
574: printr(rdform,stdout);
575: printf(" ,type: %d\n",
576: curbind->b_type);
577: fflush(stdout);
578: }
579: /* end debugging */
580: uctolc = ouctolc; /* restore previous state */
581: getc(p); /* eat trailing null */
582: protect(rdform);
583: if(curbind->b_type <= 2) /* if function type */
584: {
585: handy = newfunct();
586: if (note_redef && (rdform->a.fnbnd != nil))
587: {
588: printr(rdform,stdout);
589: printf(" redefined\n");
590: }
591: rdform->a.fnbnd = handy;
592: handy->bcd.start = (lispval (*)())(code_core_org + funloc[funcnt++]);
593: handy->bcd.discipline =
594: (curbind->b_type == 0 ? lambda :
595: curbind->b_type == 1 ? nlambda :
596: macro);
597: if(domap) {
598: fprintf(map,"%s\n%x\n",rdform->a.pname,handy->bcd.start);
599: }
600: }
601: else {
602: Vreadtable->a.clb = currtab;
603: ibase->a.clb = curibase;
604:
605: /* debugging */
606: if(debugmode != nil) {
607: printf("Eval: ");
608: printr(rdform,stdout);
609: printf("\n");
610: fflush(stdout);
611: };
612: /* end debugging */
613:
614: eval(rdform); /* otherwise eval it */
615:
616: if(uctolc) ouctolc = TRUE; /* if changed by eval, remember */
617: curibase = ibase->a.clb;
618: ibase->a.clb = inewint(10);
619: Vreadtable->a.clb = strtab;
620: }
621: };
622:
623: fclose(p); /* give up file descriptor */
624:
625: POP; /* restore state of gcdisable variable */
626:
627: Vreadtable->a.clb = currtab;
628: chkrtab(currtab);
629: ibase->a.clb = curibase;
630:
631: fclose(filp);
632: if(domap) fclose(map);
633: Freexs();
634: return(tatom);
635: }
636:
637: #if m_68k
638: /* function used in qsort for 68k version only */
639: compar(arg1,arg2)
640: int *arg1,*arg2;
641: {
642: if(*arg1 < *arg2) return (-1);
643: else if (*arg1 == *arg2) return (0);
644: else return(1);
645: }
646: #endif
647:
648: /* gettran :: allocate a segment of transfer table of the given size */
649:
650: struct trent *
651: gettran(size)
652: {
653: struct trtab *trp;
654: struct trent *retv;
655: int ousehole;
656: extern int usehole;
657:
658: if(size > TRENTS)
659: error("transfer table too large",FALSE);
660:
661: if(size > trleft)
662: {
663: /* allocate a new transfer table */
664: /* must not allocate in the hole or we cant modify it */
665: ousehole = usehole; /* remember old value */
666: usehole = FALSE;
667: trp = (struct trtab *)csegment(OTHER,sizeof(struct trtab),FALSE);
668: usehole = ousehole;
669:
670: trp->sentinal = 0; /* make sure the sentinal is 0 */
671: trp->nxtt = trhead; /* link at beginning of table */
672: trhead = trp;
673: trcur = &(trp->trentrs[0]); /* begin allocating here */
674: trleft = TRENTS;
675: }
676:
677: trleft = trleft - size;
678: retv = trcur;
679: trcur = trcur + size;
680: return(retv);
681: }
682:
683: /* clrtt :: clear transfer tables, or link them all up;
684: * this has two totally opposite functions:
685: * 1) all transfer tables are reset so that all function calls will go
686: * through qlinker
687: * 2) as many transfer tables are set up to point to bcd functions
688: * as possible
689: */
690: clrtt(flag)
691: {
692: /* flag = 0 :: set to qlinker
693: * flag = 1 :: set to function bcd binding if possible
694: */
695: register struct trtab *temptt;
696: register struct trent *tement;
697: register lispval fnb;
698:
699: for (temptt = trhead; temptt != 0 ; temptt = temptt->nxtt)
700: {
701: for(tement = &temptt->trentrs[0] ; tement->fcn != 0 ; tement++)
702: { if(flag == 0 || TYPE(fnb=tement->name->a.fnbnd) != BCD
703: || TYPE(fnb->bcd.discipline) == STRNG)
704: tement->fcn = qlinker;
705: else tement->fcn = fnb->bcd.start;
706: }
707: }
708: }
709:
710: /* chktt - builds a list of transfer table entries which don't yet have
711: a function associated with them, i.e if this transfer table entry
712: were used, an undefined function error would result
713: */
714: lispval
715: chktt()
716: {
717: register struct trtab *temptt;
718: register struct trent *tement;
719: register lispval retlst,curv;
720: Savestack(4);
721:
722: retlst = newdot(); /* build list of undef functions */
723: protect(retlst);
724: for (temptt = trhead; temptt != 0 ; temptt = temptt->nxtt)
725: {
726: for(tement = &temptt->trentrs[0] ; tement->fcn != 0 ; tement++)
727: {
728: if(tement->name->a.fnbnd == nil)
729: {
730: curv= newdot();
731: curv->d.car = tement->name;
732: curv->d.cdr = retlst->d.cdr;
733: retlst->d.cdr = curv;
734: }
735: }
736: }
737: Restorestack();
738: return(retlst->d.cdr);
739: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.