|
|
1.1 root 1: /*
2: * Initialization and error routines.
3: */
4:
5: #include "../h/rt.h"
6: #include "../h/version.h"
7: #include "gc.h"
8: #include "../h/header.h"
9: #include <signal.h>
10: #include <ctype.h>
11: #ifndef VMS
12: #ifndef MSDOS
13: #include <sys/types.h>
14: #include <sys/times.h>
15: #else MSDOS
16: #ifdef LATTICE
17: #include <fcntl.h>
18: #include <time.h>
19: #endif LATTICE
20: #ifdef MSoft
21: #include <sys/types.h>
22: #include <fcntl.h>
23: #include SysTime
24: #endif MSoft
25: #endif MSDOS
26: #else VMS
27: #include <types.h>
28: struct tms {
29: time_t tms_utime; /* user time */
30: time_t tms_stime; /* system time */
31: time_t tms_cutime; /* user time, children */
32: time_t tms_cstime; /* system time, children */
33: };
34: #endif VMS
35:
36: /*
37: * A number of important variables follow.
38: */
39:
40: #ifndef MaxHeader
41: #define MaxHeader MaxHdr
42: #endif MaxHeader
43:
44: extern putpos(); /* assignment function for &pos */
45: extern putran(); /* assignment function for &random */
46: extern putsub(); /* assignment function for &subject */
47: extern puttrc(); /* assignment function for &trace */
48:
49: word *stack; /* interpreter stack */
50: int line = 0; /* source program line number */
51: int k_level = 0; /* &level */
52: struct descrip k_main; /* &main */
53: char *code; /* interpreter code buffer */
54: word *records; /* pointer to record procedure blocks */
55: word *ftab; /* pointer to record/field table */
56: struct descrip *globals, *eglobals; /* pointer to global variables */
57: struct descrip *gnames, *egnames; /* pointer to global variable names */
58: struct descrip *statics, *estatics; /* pointer to static variables */
59: char *ident; /* pointer to identifier table */
60:
61: int numbufs = NumBuf; /* number of i/o buffers */
62: char (*bufs)[BUFSIZ]; /* pointer to buffers */
63: FILE **bufused; /* pointer to buffer use markers */
64:
65: word tallybin[16]; /* counters for tallying */
66: int tallyopt = 0; /* want tally results output? */
67:
68: int mstksize = MStackSize; /* initial size of main stack */
69: int stksize = StackSize; /* co-expression stack size */
70: struct b_coexpr *stklist; /* base of co-expression block list */
71:
72: word statsize = MaxStatSize; /* size of static region */
73: word statincr = MaxStatSize/4; /* increment for static region */
74: char *statbase; /* start of static space */
75: char *statend; /* end of static space */
76: char *statfree; /* static space free pointer */
77:
78: word ssize = MaxStrSpace; /* initial string space size (bytes) */
79: char *strbase; /* start of string space */
80: char *strend; /* end of string space */
81: char *strfree; /* string space free pointer */
82: char *currend; /* current end of memory region */
83:
84: word abrsize = MaxAbrSize; /* initial size of allocated block
85: region (bytes) */
86: char *blkbase; /* start of block region */
87: char *maxblk; /* end of allocated blocks */
88: char *blkfree; /* block region free pointer */
89:
90: uword statneed; /* stated need for static space */
91: uword strneed; /* stated need for string space */
92: uword blkneed; /* stated need for block space */
93:
94: struct descrip **quallist; /* string qualifier list */
95: struct descrip **qualfree; /* qualifier list free pointer */
96: struct descrip **equallist; /* end of qualifier list */
97:
98: int dodump; /* if non-zero, core dump on error */
99: int noerrbuf; /* if non-zero, do not buffer stderr */
100:
101: struct descrip current; /* current expression stack pointer */
102: struct descrip maps2; /* second cached argument of map */
103: struct descrip maps3; /* third cached argument of map */
104:
105: int ntended = 0; /* number of active tended descrips */
106: long starttime; /* start time of job in milliseconds */
107:
108: /*
109: * Next there are several structures for built-in values. Parts of some
110: * of these structures are initialized later.
111: */
112:
113: /*
114: * Built-in csets
115: */
116:
117: /*
118: * &ascii; 128 bits on, second 128 bits off.
119: */
120: struct b_cset k_ascii = {
121: T_Cset,
122: 128,
123: cset_display(~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
124: 0, 0, 0, 0, 0, 0, 0, 0)
125: };
126:
127: /*
128: * &cset; all 256 bits on.
129: */
130: struct b_cset k_cset = {
131: T_Cset,
132: 256,
133: cset_display(~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
134: ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0)
135: };
136:
137:
138:
139: /*
140: * Cset for &lcase; bits corresponding to lowercase letters are on.
141: */
142: struct b_cset k_lcase = {
143: T_Cset,
144: 26,
145: cset_display( 0, 0, 0, 0, 0, 0, ~01, 03777,
146: 0, 0, 0, 0, 0, 0, 0, 0)
147: };
148:
149: /*
150: * &ucase; bits corresponding to uppercase characters are on.
151: */
152: struct b_cset k_ucase = {
153: T_Cset,
154: 26,
155: cset_display(0, 0, 0, 0, ~01, 03777, 0, 0,
156: 0, 0, 0, 0, 0, 0, 0, 0)
157: };
158:
159: /*
160: * Built-in files.
161: */
162:
163: struct b_file k_errout; /* &errout */
164: struct b_file k_input; /* &input */
165: struct b_file k_output; /* &outout */
166:
167: /*
168: * Keyword trapped variables.
169: */
170:
171: /*
172: * &pos.
173: */
174: struct b_tvkywd tvky_pos = {
175: T_Tvkywd,
176: /* putpos, */
177: /* D_Integer, */
178: /* 1, */
179: /* 4, */
180: /* "&pos" */
181: };
182:
183: /*
184: * &random.
185: */
186: struct b_tvkywd tvky_ran = {
187: T_Tvkywd,
188: /* putran, */
189: /* D_Integer, */
190: /* 0, */
191: /* 7, */
192: /* "&random" */
193: };
194:
195: /*
196: * &subject.
197: */
198: struct b_tvkywd tvky_sub = {
199: T_Tvkywd,
200: /* putsub, */
201: /* 0, */
202: /* 0, */
203: /* 8, */
204: /* "&subject" */
205: };
206:
207: /*
208: * &trace.
209: */
210: struct b_tvkywd tvky_trc = {
211: T_Tvkywd,
212: /* puttrc, */
213: /* D_Integer, */
214: /* 0, */
215: /* 6, */
216: /* "&trace" */
217: };
218:
219: /*
220: * Co-expression block header for &main.
221: */
222:
223: static struct b_coexpr *mainhead;
224:
225: #if IntSize == 16
226: /*
227: * Long integer block for &random.
228: */
229: struct b_int long_ran = {
230: T_Longint,
231: 0L
232: };
233: #endif IntSize == 16
234:
235: /*
236: * Various constant descriptors.
237: */
238:
239: struct descrip blank = {1, /*" "*/};
240: struct descrip emptystr = {0, /*""*/};
241: struct descrip errout = {D_File, /*&k_errout*/};
242: struct descrip input = {D_File, /*&k_input*/};
243: struct descrip lcase = {26, /*lowercase*/};
244: struct descrip letr = {1, /*"r"*/};
245: struct descrip nulldesc = {D_Null, /*0*/};
246: struct descrip onedesc = {D_Integer, /*1*/};
247: struct descrip ucase = {26, /*uppercase*/};
248: struct descrip zerodesc = {D_Integer, /*0*/};
249:
250: #ifdef RunStats
251: #endif RunStats
252:
253: /*
254: * init - initialize memory and prepare for Icon execution.
255: */
256:
257: init(name)
258: char *name;
259: {
260: register int i;
261: word cbread;
262: int f;
263: char c, *p;
264: struct descrip *dp;
265: struct header hdr;
266: #ifndef MSDOS
267: struct tms tp;
268: extern char *brk(), *sbrk(), *index();
269: #else MSDOS
270: #ifdef LPTR
271: long longread();
272: #endif LPTR
273: #endif MSDOS
274: extern fpetrap(), segvtrap();
275:
276: /*
277: * Catch floating point traps and memory faults.
278: */
279: #ifndef MSoft
280: signal(SIGFPE, fpetrap);
281: #endif MSoft
282: #ifndef MSDOS
283: #ifdef PYRAMID
284: {
285: struct sigvec a;
286:
287: a.sv_handler = fpetrap;
288: a.sv_mask = 0;
289: a.sv_onstack = 0;
290: sigvec(SIGFPE, &a, 0);
291: sigsetmask(1 << SIGFPE);
292: }
293: #else PYRAMID
294: signal(SIGFPE, fpetrap);
295: #endif PYRAMID
296: #endif MSDOS
297:
298: /*
299: * Initializations that cannot be performed statically (at least for
300: * some compilers).
301: */
302:
303: k_errout.title = T_File;
304: k_errout.fd = stderr;
305: k_errout.status = Fs_Write;
306: k_errout.fname.dword = 7;
307: StrLoc(k_errout.fname) = "&errout";
308:
309: k_input.title = T_File;
310: k_input.fd = stdin;
311: k_input.status = Fs_Read;
312: k_input.fname.dword = 6;
313: StrLoc(k_input.fname) = "&input";
314:
315: k_output.title = T_File;
316: k_output.fd = stdout;
317: k_output.status = Fs_Write;
318: k_output.fname.dword = 7;
319: StrLoc(k_output.fname) = "&output";
320:
321: tvky_pos.putval = putpos;
322: ((tvky_pos.kyval).dword) = D_Integer;
323: IntVal(tvky_pos.kyval) = 1;
324: StrLen(tvky_pos.kyname) = 4;
325: StrLoc(tvky_pos.kyname) = "&pos";
326:
327: tvky_ran.putval = putran;
328: #if IntSize == 16
329: ((tvky_ran.kyval).dword) = D_Longint;
330: #else IntSize == 16
331: ((tvky_ran.kyval).dword) = D_Integer;
332: #endif IntSize == 16
333: StrLen(tvky_ran.kyname) = 7;
334: StrLoc(tvky_ran.kyname) = "&random";
335:
336: tvky_sub.putval = putsub;
337: StrLen(tvky_sub.kyval) = 0;
338: StrLen(tvky_sub.kyname) = 8;
339: StrLoc(tvky_sub.kyname) = "&subject";
340:
341: tvky_trc.putval = puttrc;
342: ((tvky_trc.kyval).dword) = D_Integer;
343: StrLen(tvky_trc.kyname) = 6;
344: StrLoc(tvky_trc.kyname) = "&trace";
345: #if IntSize == 16
346: BlkLoc(tvky_ran.kyval) = (union block *) &long_ran;
347: #else IntSize == 16
348: IntVal(tvky_ran.kyval) = 0;
349: #endif IntSize == 16
350: IntVal(tvky_trc.kyval) = 0;
351: StrLoc(tvky_sub.kyval) = "";
352:
353:
354: StrLoc(k_subject) = "";
355: IntVal(nulldesc) = 0;
356: maps2 = nulldesc;
357: maps3 = nulldesc;
358: IntVal(zerodesc) = 0;
359: IntVal(onedesc) = 1;
360: StrLoc(emptystr) = "";
361: StrLoc(blank) = " ";
362: StrLoc(letr) = "r";
363: BlkLoc(input) = (union block *) &k_input;
364: BlkLoc(errout) = (union block *) &k_errout;
365: StrLoc(lcase) = "abcdefghijklmnopqrstuvwxyz";
366: StrLoc(ucase) = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
367:
368: /*
369: * Open the icode file and read the header.
370: */
371: i = strlen(name);
372: #ifndef MSDOS
373: f = open(name, 0);
374: #else MSDOS
375: #ifdef LATTICE
376: f = open(name,O_RDONLY | O_RAW);
377: #endif LATTICE
378: #ifdef MSoft
379: f = open(name,O_RDONLY | O_BINARY);
380: #endif MSoft
381: #endif MSDOS
382: if (f < 0)
383: error("can't open interpreter file");
384: #ifndef NoHeader
385: lseek(f, (long)MaxHeader, 0);
386: #endif NoHeader
387: if (read(f, (char *)&hdr, sizeof(hdr)) != sizeof(hdr))
388: error("can't read interpreter file header");
389:
390: /*
391: * Establish pointers to data regions.
392: */
393: code = (char *)sbrk((word)0);
394: k_trace = hdr.trace;
395: records = (word *) (word)(code + hdr.records);
396: ftab = (word *) (word)(code + hdr.ftab);
397: globals = (struct descrip *) (code + hdr.globals);
398: gnames = eglobals = (struct descrip *) (code + hdr.gnames);
399: statics = egnames = (struct descrip *) (code + hdr.statics);
400: estatics = (struct descrip *) (code + hdr.ident);
401: ident = (char *) estatics;
402:
403: /*
404: * Examine the environment and make appropriate settings.
405: */
406: envlook();
407:
408: /*
409: * Convert stack sizes from words to bytes.
410: */
411: stksize *= WordSize;
412: mstksize *= WordSize;
413:
414: /*
415: * Set up allocated memory. The regions are:
416: *
417: * Static memory region
418: * Allocated string region
419: * Allocate block region
420: * String qualifier list
421: */
422: /*
423: * Align bufs on a word boundary
424: */
425: bufs = (char **)((word)(code + hdr.hsize + 3) & ~03);
426: bufused = (FILE **) (bufs + numbufs);
427: statfree = statbase = (char *)(((word)(bufused + numbufs) + 63) & ~077);
428: statend = statbase + mstksize + statsize;
429: strfree = strbase = (char *)((word)(statend + 63) & ~077);
430: blkfree = blkbase = strend = (char *)((word)(strbase + ssize + 63) & ~077);
431: quallist = qualfree = equallist =
432: (struct descrip **)(maxblk = (char *)((word)(blkbase + abrsize + 63) & ~077));
433:
434: /*
435: * Try to move the break back to the end of memory to allocate (the
436: * end of the string qualifier list) and die if the space isn't
437: * available.
438: */
439: if ((int)brk(equallist) == -1)
440: error("insufficient memory");
441: currend = sbrk(0); /* keep track of end of memory */
442:
443: /*
444: * Allocate stack and initialize &main.
445: */
446: stack = (word *)malloc(mstksize);
447: mainhead = (struct b_coexpr *)stack;
448: mainhead->title = T_Coexpr;
449: mainhead->activator.dword = D_Coexpr;
450: BlkLoc(mainhead->activator) = (union block *)mainhead;
451: mainhead->size = 0;
452: mainhead->freshblk = nulldesc; /* &main has no refresh block. */
453: /* This really is a bug. */
454:
455: /*
456: * Point &main at the stack for the main procedure and set current,
457: * the pointer to the current co-expression to &main.
458: */
459: k_main.dword = D_Coexpr;
460: BlkLoc(k_main) = (union block *) mainhead;
461: current = k_main;
462:
463: /*
464: * Read the interpretable code and data into memory.
465: */
466: #ifndef MSDOS
467: if ((cbread = read(f, code, hdr.hsize)) != hdr.hsize) {
468: #else MSDOS
469: #ifdef SPTR
470: if ((cbread = read(f, code, hdr.hsize)) != hdr.hsize) {
471: #else /* Handle the case where hdr.hsize is long */
472: if ((cbread = longread(f, code, hdr.hsize)) != hdr.hsize) {
473: #endif SPTR
474: #endif MSDOS
475: fprintf(stderr,"Tried to read %ld bytes of code, and got %ld\n",
476: (long)hdr.hsize,(long)cbread);
477: error("can't read interpreter code");
478: }
479: close(f);
480:
481: /*
482: * Make sure the version number of the icode matches the interpreter version.
483: */
484:
485: if (strcmp((char *)hdr.config,IVersion)) {
486: fprintf(stderr,"icode version mismatch\n");
487: fprintf(stderr,"\ticode version: %s\n",(char *)hdr.config);
488: fprintf(stderr,"\texpected version: %s\n",IVersion);
489: fflush(stderr);
490: if (dodump)
491: abort();
492: c_exit(ErrorExit);
493: }
494:
495: /*
496: * Resolve references from icode to runtime system.
497: */
498: resolve();
499:
500: /*
501: * Mark all buffers as available.
502: */
503: c = (char) NULL;
504: for (i = 0; i < numbufs; i++)
505: bufused[i] = (FILE *) c;
506:
507: /*
508: * Buffer stdin if a buffer is available.
509: */
510: #ifndef VMS
511: if (numbufs >= 1) {
512: setbuf(stdin, bufs[0]);
513: bufused[0] = stdin;
514: }
515: else
516: setbuf(stdin, NULL);
517:
518: /*
519: * Buffer stdout if a buffer is available.
520: */
521: if (numbufs >= 2) {
522: setbuf(stdout, bufs[1]);
523: bufused[1] = stdout;
524: }
525: else
526: setbuf(stdout, NULL);
527:
528: /*
529: * Buffer stderr if a buffer is available.
530: */
531: if (numbufs >= 3 && !noerrbuf) {
532: setbuf(stderr, bufs[2]);
533: bufused[2] = stderr;
534: }
535: else
536: setbuf(stderr, NULL);
537: #endif VMS
538:
539: /*
540: * Initialize memory monitoring if enabled.
541: */
542: MMInit();
543:
544: /*
545: * Get startup time.
546: */
547: #ifndef MSDOS
548: times(&tp);
549: starttime = tp.tms_utime;
550: #else MSDOS
551: time(&starttime);
552: #endif MSDOS
553: }
554:
555: /*
556: * Check for environment variables that Icon uses and set system
557: * values as is appropriate.
558: */
559: envlook()
560: {
561: register char *p;
562: extern char *getenv();
563:
564: if ((p = getenv("TRACE")) != NULL && *p != '\0')
565: k_trace = atoi(p);
566: if ((p = getenv("NBUFS")) != NULL && *p != '\0')
567: numbufs = atoi(p);
568: if ((p = getenv("COEXPSIZE")) != NULL && *p != '\0')
569: stksize = atoi(p);
570: if ((p = getenv("STRSIZE")) != NULL && *p != '\0')
571: ssize = atoi(p);
572: if ((p = getenv("HEAPSIZE")) != NULL && *p != '\0')
573: abrsize = atoi(p);
574: if ((p = getenv("STATSIZE")) != NULL && *p != '\0')
575: statsize = atoi(p);
576: if ((p = getenv("STATINCR")) != NULL && *p != '\0')
577: statincr = atoi(p);
578: if ((p = getenv("MSTKSIZE")) != NULL && *p != '\0')
579: mstksize = atoi(p);
580: if ((p = getenv("ICONCORE")) != NULL && *p != '\0') {
581: #ifndef MSoft
582: signal(SIGFPE, SIG_DFL);
583: #endif MSoft
584: #ifndef MSDOS
585: signal(SIGSEGV, SIG_DFL);
586: #endif MSDOS
587: dodump++;
588: }
589: if ((p = getenv("NOERRBUF")) != NULL)
590: noerrbuf++;
591: }
592:
593: /*
594: * Produce run-time error 204 on floating point traps.
595: */
596: #ifdef PYRAMID
597: fpetrap(code, subcode, sp)
598: int code, subcode, sp;
599: {
600: runerr(subcode == FPE_wordOVF_EXC ? 203 : 204, NULL);
601: }
602: #else PYRAMID
603: fpetrap()
604: {
605: runerr(204, NULL);
606: }
607: #endif PYRAMID
608:
609: /*
610: * Produce run-time error 302 on segmentation faults.
611: */
612: segvtrap()
613: {
614: runerr(302, NULL);
615: }
616:
617: /*
618: * error - print error message s; used only in startup code.
619: */
620: error(s)
621: char *s;
622: {
623: fprintf(stderr, "error in startup code\n%s\n", s);
624: fflush(stderr);
625: if (dodump)
626: abort();
627: c_exit(ErrorExit);
628: }
629:
630: /*
631: * syserr - print s as a system error.
632: */
633: syserr(s)
634: char *s;
635: {
636: struct b_proc *bp;
637:
638: bp = (struct b_proc *)BlkLoc(argp[0]);
639: if (line > 0)
640: fprintf(stderr, "System error at line %ld in %s\n%s\n", (long)line,
641: bp->filename, s);
642: else
643: fprintf(stderr, "System error in startup code\n%s\n", s);
644: fflush(stderr);
645: if (dodump)
646: abort();
647: c_exit(ErrorExit);
648: }
649:
650: /*
651: * errtab maps run-time error numbers into messages.
652: */
653: struct errtab {
654: int errno;
655: char *errmsg;
656: } errtab[] = {
657: 101, "integer expected",
658: 102, "numeric expected",
659: 103, "string expected",
660: 104, "cset expected",
661: 105, "file expected",
662: 106, "procedure or integer expected",
663: 107, "record expected",
664: 108, "list expected",
665: 109, "string or file expected",
666: 110, "string or list expected",
667: 111, "variable expected",
668: 112, "invalid type to size operation",
669: 113, "invalid type to random operation",
670: 114, "invalid type to subscript operation",
671: 115, "list or table expected",
672: 116, "invalid type to element generator",
673: 117, "missing main procedure",
674: 118, "co-expression expected",
675: 119, "set expected",
676:
677: 201, "division by zero",
678: 202, "remaindering by zero",
679: 203, "integer overflow",
680: 204, "real overflow, underflow, or division by zero",
681: 205, "value out of range",
682: 206, "negative first operand to real exponentiation",
683: 207, "invalid field name",
684: 208, "second and third arguments to map of unequal length",
685: 209, "invalid second argument to open",
686: 210, "argument to system function too long",
687: 211, "by clause equal to zero",
688: 212, "attempt to read file not open for reading",
689: 213, "attempt to write file not open for writing",
690: 214, "recursive co-expression activation",
691:
692: 301, "interpreter stack overflow",
693: 302, "C stack overflow",
694: 303, "unable to expand memory region",
695: 304, "memory region size changed",
696:
697: 0, 0
698: };
699:
700: /*
701: * runerr - print message corresponding to error n and if v is nonnull,
702: * print it as the offending value.
703: */
704: #ifdef PCIX
705: /*
706: * For PC/IX, runerr is an assembly language routine that jumps into this
707: * xruner procedure past the call to csv which occurs at the beginning of
708: * all C procedures. This is necessary to defeat the stack data collision
709: * testing which is done in csv in pc/ix and which would cause a loop,
710: * since one of the possible reasons for calling runerr in the first place
711: * might be stack/data collision.
712: */
713: xruner(n, v)
714: #else PCIX
715: runerr(n, v)
716: #endif PCIX
717: register int n;
718: struct descrip *v;
719: {
720: register struct errtab *p;
721: struct b_proc *bp;
722:
723: if (line > 0) {
724: bp = (struct b_proc *)BlkLoc(argp[0]);
725: fprintf(stderr, "Run-time error %d at line %ld in %s\n", n,
726: (long)line, bp->filename);
727: }
728: else
729: fprintf(stderr, "Run-time error %d in startup code\n", n);
730: for (p = errtab; p->errno > 0; p++)
731: if (p->errno == n) {
732: fprintf(stderr, "%s\n", p->errmsg);
733: break;
734: }
735: if (v != NULL) {
736: fprintf(stderr, "offending value: ");
737: outimage(stderr, v, 0);
738: putc('\n', stderr);
739: }
740: fflush(stderr);
741: if (dodump)
742: abort();
743: c_exit(ErrorExit);
744: }
745:
746: /*
747: * resolve - perform various fixups on the data read from the interpretable
748: * file.
749: */
750: resolve()
751: {
752: register word i;
753: register struct b_proc *pp;
754: register struct descrip *dp;
755: extern mkrec();
756: extern struct b_proc *functab[];
757:
758: /*
759: * Scan the global variable list for procedures and fill in appropriate
760: * addresses.
761: */
762: for (dp = globals; dp < eglobals; dp++) {
763: if ((*dp).dword != D_Proc)
764: continue;
765: /*
766: * The second word of the descriptor for procedure variables tells
767: * where the procedure is. Negative values are used for built-in
768: * procedures and positive values are used for Icon procedures.
769: */
770: i = IntVal(*dp);
771: if (i < 0) {
772: /*
773: * *dp names a built-in function, negate i and use it as an index
774: * into functab to get the location of the procedure block.
775: */
776: BlkLoc(*dp) = (union block *) functab[-i-1];
777: }
778: else {
779: /*
780: * *dp names an Icon procedure or a record. i is an offset to
781: * location of the procedure block in the code section. Point
782: * pp at the block and replace BlkLoc(*dp).
783: */
784: pp = (struct b_proc *) (code + i);
785: BlkLoc(*dp) = (union block *) pp;
786: /*
787: * Relocate the address of the name of the procedure.
788: */
789: StrLoc(pp->pname) += (word)ident;
790: if (pp->ndynam == -2)
791: /*
792: * This procedure is a record constructor. Make its entry point
793: * be the entry point of mkrec().
794: */
795: pp->entryp.ccode = mkrec;
796: else {
797: /*
798: * This is an Icon procedure. Relocate the entry point and
799: * the names of the parameters, locals, and static variables.
800: */
801: pp->entryp.icode = code + (word)pp->entryp.icode;
802: if (pp->ndynam >= 0)
803: pp->filename += (word)ident;
804: for (i = 0; i < pp->nparam+pp->ndynam+pp->nstatic; i++)
805: StrLoc(pp->lnames[i]) += (word)ident;
806: }
807: }
808: }
809: /*
810: * Relocate the names of the global variables.
811: */
812: for (dp = gnames; dp < egnames; dp++)
813: StrLoc(*dp) += (word)ident;
814: }
815:
816:
817: /*
818: * c_exit(i) - flush all buffers and exit with status i.
819: */
820: c_exit(i)
821: int i;
822: {
823: int j;
824:
825: #ifdef MemMon
826: MMTerm();
827: #endif MemMon
828: if (tallyopt) {
829: fprintf(stderr,"tallies: ");
830: for (j=0; j<16; j++)
831: fprintf(stderr," %ld", (long)tallybin[j]);
832: fprintf(stderr,"\n");
833: }
834: exit(i);
835: }
836:
837: err()
838: {
839: syserr("call to 'err'\n");
840: }
841:
842: #ifdef MSDOS
843: #ifdef LPTR
844: /* Write a long string in 32k chunks */
845: long longread(file,s,len)
846: int file;
847: char *s;
848: long int len;
849: {
850: long int loopnum;
851: long int leftover;
852: long int tally;
853: unsigned i;
854: char *p;
855:
856: tally = 0;
857: leftover = len % 32768;
858: for(p = s, loopnum = len/32768;loopnum;loopnum--) {
859: i = read(file,p,32768);
860: tally += i;
861: if (i != 32768) return tally;
862: p += 32768;
863: }
864: if(leftover) tally += read(file,p,leftover);
865: return tally;
866: }
867: #endif LPTR
868: #endif MSDOS
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.