date and time created 80/08/27 22:28:03 by peter
[unix-history] / usr / src / usr.bin / pascal / src / nl.c
CommitLineData
7dc17c60
PK
1/* Copyright (c) 1979 Regents of the University of California */
2
3static char sccsid[] = "@(#)nl.c 1.1 %G%";
4
5#include "whoami.h"
6#include "0.h"
7#include "opcode.h"
8#include "objfmt.h"
9
10/*
11 * NAMELIST SEGMENT DEFINITIONS
12 */
13struct nls {
14 struct nl *nls_low;
15 struct nl *nls_high;
16} ntab[MAXNL], *nlact;
17
18struct nl nl[INL];
19struct nl *nlp = nl;
20struct nls *nlact = ntab;
21\f
22 /*
23 * all these strings must be places where people can find them
24 * since lookup only looks at the string pointer, not the chars.
25 * see, for example, pTreeInit.
26 */
27
28 /*
29 * built in constants
30 */
31char *in_consts[] = {
32 "true" ,
33 "false" ,
34 "TRUE",
35 "FALSE",
36 "minint" ,
37 "maxint" ,
38 "minchar" ,
39 "maxchar" ,
40 "bell" ,
41 "tab" ,
42 0
43 };
44
45 /*
46 * built in simple types
47 */
48char *in_types[] =
49 {
50 "boolean",
51 "char",
52 "integer",
53 "real",
54 "_nil", /* dummy name */
55 0
56 };
57
58int in_rclasses[] =
59 {
60 TINT ,
61 TINT ,
62 TINT ,
63 TCHAR ,
64 TBOOL ,
65 TDOUBLE ,
66 0
67 };
68
69long in_ranges[] =
70 {
71 -128L , 128L ,
72 -32768L , 32767L ,
73 -2147483648L , 2147483647L ,
74 0L , 127L ,
75 0L , 1L ,
76 0L , 0L /* fake for reals */
77 };
78
79 /*
80 * built in constructed types
81 */
82char *in_ctypes[] = {
83 "Boolean" ,
84 "intset" ,
85 "alfa" ,
86 "text" ,
87 0
88 };
89
90 /*
91 * built in variables
92 */
93char *in_vars[] = {
94 "input" ,
95 "output" ,
96 0
97 };
98
99 /*
100 * built in functions
101 */
102char *in_funcs[] =
103 {
104 "abs" ,
105 "arctan" ,
106 "card" ,
107 "chr" ,
108 "clock" ,
109 "cos" ,
110 "eof" ,
111 "eoln" ,
112 "eos" ,
113 "exp" ,
114 "expo" ,
115 "ln" ,
116 "odd" ,
117 "ord" ,
118 "pred" ,
119 "round" ,
120 "sin" ,
121 "sqr" ,
122 "sqrt" ,
123 "succ" ,
124 "trunc" ,
125 "undefined" ,
126 /*
127 * Extensions
128 */
129 "argc" ,
130 "random" ,
131 "seed" ,
132 "wallclock" ,
133 "sysclock" ,
134 0
135 };
136
137 /*
138 * Built-in procedures
139 */
140char *in_procs[] =
141 {
142 "date" ,
143 "dispose" ,
144 "flush" ,
145 "get" ,
146 "getseg" ,
147 "halt" ,
148 "linelimit" ,
149 "message" ,
150 "new" ,
151 "pack" ,
152 "page" ,
153 "put" ,
154 "putseg" ,
155 "read" ,
156 "readln" ,
157 "remove" ,
158 "reset" ,
159 "rewrite" ,
160 "time" ,
161 "unpack" ,
162 "write" ,
163 "writeln" ,
164 /*
165 * Extensions
166 */
167 "argv" ,
168 "null" ,
169 "stlimit" ,
170 0
171 };
172
173#ifndef PI0
174 /*
175 * and their opcodes
176 */
177int in_fops[] =
178 {
179 O_ABS2,
180 O_ATAN,
181 O_CARD|NSTAND,
182 O_CHR2,
183 O_CLCK|NSTAND,
184 O_COS,
185 O_EOF,
186 O_EOLN,
187 0,
188 O_EXP,
189 O_EXPO|NSTAND,
190 O_LN,
191 O_ODD2,
192 O_ORD2,
193 O_PRED2,
194 O_ROUND,
195 O_SIN,
196 O_SQR2,
197 O_SQRT,
198 O_SUCC2,
199 O_TRUNC,
200 O_UNDEF|NSTAND,
201 /*
202 * Extensions
203 */
204 O_ARGC|NSTAND,
205 O_RANDOM|NSTAND,
206 O_SEED|NSTAND,
207 O_WCLCK|NSTAND,
208 O_SCLCK|NSTAND
209 };
210
211 /*
212 * Built-in procedures
213 */
214int in_pops[] =
215 {
216 O_DATE|NSTAND,
217 O_DISPOSE,
218 O_FLUSH|NSTAND,
219 O_GET,
220 0,
221 O_HALT|NSTAND,
222 O_LLIMIT|NSTAND,
223 O_MESSAGE|NSTAND,
224 O_NEW,
225 O_PACK,
226 O_PAGE,
227 O_PUT,
228 0,
229 O_READ4,
230 O_READLN,
231 O_REMOVE|NSTAND,
232 O_RESET,
233 O_REWRITE,
234 O_TIME|NSTAND,
235 O_UNPACK,
236 O_WRITEF,
237 O_WRITLN,
238 /*
239 * Extensions
240 */
241 O_ARGV|NSTAND,
242 O_ABORT|NSTAND,
243 O_STLIM|NSTAND
244 };
245#endif
246
247/*
248 * Initnl initializes the first namelist segment and then
249 * initializes the name list for block 0.
250 */
251initnl()
252 {
253 register char **cp;
254 register struct nl *np;
255 struct nl *fp;
256 int *ip;
257 long *lp;
258
259#ifdef DEBUG
260 if ( hp21mx )
261 {
262 MININT = -32768.;
263 MAXINT = 32767.;
264#ifndef PI0
265 genmx();
266#endif
267 }
268#endif
269 ntab[0].nls_low = nl;
270 ntab[0].nls_high = &nl[INL];
271 defnl ( 0 , 0 , 0 , 0 );
272
273 /*
274 * Types
275 */
276 for ( cp = in_types ; *cp != 0 ; cp ++ )
277 hdefnl ( *cp , TYPE , nlp , 0 );
278
279 /*
280 * Ranges
281 */
282 lp = in_ranges;
283 for ( ip = in_rclasses ; *ip != 0 ; ip ++ )
284 {
285 np = defnl ( 0 , RANGE , nl+(*ip) , 0 );
286 nl[*ip].type = np;
287 np -> range[0] = *lp ++ ;
288 np -> range[1] = *lp ++ ;
289
290 };
291
292 /*
293 * built in constructed types
294 */
295
296 cp = in_ctypes;
297 /*
298 * Boolean = boolean;
299 */
300 hdefnl ( *cp++ , TYPE , nl+T1BOOL , 0 );
301
302 /*
303 * intset = set of 0 .. 127;
304 */
305 intset = *cp++;
306 hdefnl( intset , TYPE , nlp+1 , 0 );
307 defnl ( 0 , SET , nlp+1 , 0 );
308 np = defnl ( 0 , RANGE , nl+TINT , 0 );
309 np -> range[0] = 0L;
310 np -> range[1] = 127L;
311
312 /*
313 * alfa = array [ 1 .. 10 ] of char;
314 */
315 np = defnl ( 0 , RANGE , nl+TINT , 0 );
316 np -> range[0] = 1L;
317 np -> range[1] = 10L;
318 defnl ( 0 , ARRAY , nl+T1CHAR , 1 ) -> chain = np;
319 hdefnl ( *cp++ , TYPE , nlp-1 , 0 );
320
321 /*
322 * text = file of char;
323 */
324 hdefnl ( *cp++ , TYPE , nlp+1 , 0 );
325 np = defnl ( 0 , FILET , nl+T1CHAR , 0 );
326 np -> nl_flags |= NFILES;
327
328 /*
329 * input,output : text;
330 */
331 cp = in_vars;
332# ifndef PI0
333 input = hdefnl ( *cp++ , VAR , np , INPUT_OFF );
334 output = hdefnl ( *cp++ , VAR , np , OUTPUT_OFF );
335# else
336 input = hdefnl ( *cp++ , VAR , np , 0 );
337 output = hdefnl ( *cp++ , VAR , np , 0 );
338# endif
339
340 /*
341 * built in constants
342 */
343 cp = in_consts;
344 np = hdefnl ( *cp++ , CONST , nl + TBOOL , 1 );
345 fp = hdefnl ( *cp++ , CONST , nl + TBOOL , 0 );
346 (nl + TBOOL)->chain = fp;
347 fp->chain = np;
348 np = hdefnl ( *cp++ , CONST , nl + TBOOL , 1 );
349 fp = hdefnl ( *cp++ , CONST , nl + TBOOL , 0 );
350 fp->chain = np;
351 if (opt('s'))
352 (nl + TBOOL)->chain = fp;
353 hdefnl ( *cp++ , CONST , nl + T4INT , 0 ) -> range[0] = MININT;
354 hdefnl ( *cp++ , CONST , nl + T4INT , 0 ) -> range[0] = MAXINT;
355 hdefnl ( *cp++ , CONST , nl + T1CHAR , 0 );
356 hdefnl ( *cp++ , CONST , nl + T1CHAR , 127 );
357 hdefnl ( *cp++ , CONST , nl + T1CHAR , '\007' );
358 hdefnl ( *cp++ , CONST , nl + T1CHAR , '\t' );
359
360 /*
361 * Built-in functions and procedures
362 */
363#ifndef PI0
364 ip = in_fops;
365 for ( cp = in_funcs ; *cp != 0 ; cp ++ )
366 hdefnl ( *cp , FUNC , 0 , * ip ++ );
367 ip = in_pops;
368 for ( cp = in_procs ; *cp != 0 ; cp ++ )
369 hdefnl ( *cp , PROC , 0 , * ip ++ );
370#else
371 for ( cp = in_funcs ; *cp != 0 ; cp ++ )
372 hdefnl ( *cp , FUNC , 0 , 0 );
373 for ( cp = in_procs ; *cp != 0 , cp ++ )
374 hdefnl ( *cp , PROC , 0 , 0 );
375#endif
376# ifdef PTREE
377 pTreeInit();
378# endif
379 }
380
381struct nl *
382hdefnl(sym, cls, typ, val)
383{
384 register struct nl *p;
385
386#ifndef PI1
387 if (sym)
388 hash(sym, 0);
389#endif
390 p = defnl(sym, cls, typ, val);
391 if (sym)
392 enter(p);
393 return (p);
394}
395
396/*
397 * Free up the name list segments
398 * at the end of a statement/proc/func
399 * All segments are freed down to the one in which
400 * p points.
401 */
402nlfree(p)
403 struct nl *p;
404{
405
406 nlp = p;
407 while (nlact->nls_low > nlp || nlact->nls_high < nlp) {
408 free(nlact->nls_low);
409 nlact->nls_low = NIL;
410 nlact->nls_high = NIL;
411 --nlact;
412 if (nlact < &ntab[0])
413 panic("nlfree");
414 }
415}
416\f
417
418char *VARIABLE = "variable";
419
420char *classes[ ] = {
421 "undefined",
422 "constant",
423 "type",
424 "variable", /* VARIABLE */
425 "array",
426 "pointer or file",
427 "record",
428 "field",
429 "procedure",
430 "function",
431 "variable", /* VARIABLE */
432 "variable", /* VARIABLE */
433 "pointer",
434 "file",
435 "set",
436 "subrange",
437 "label",
438 "withptr",
439 "scalar",
440 "string",
441 "program",
442 "improper"
443#ifdef DEBUG
444 ,"variant"
445#endif
446};
447
448char *snark = "SNARK";
449
450#ifdef PI
451#ifdef DEBUG
452char *ctext[] =
453{
454 "BADUSE",
455 "CONST",
456 "TYPE",
457 "VAR",
458 "ARRAY",
459 "PTRFILE",
460 "RECORD",
461 "FIELD",
462 "PROC",
463 "FUNC",
464 "FVAR",
465 "REF",
466 "PTR",
467 "FILET",
468 "SET",
469 "RANGE",
470 "LABEL",
471 "WITHPTR",
472 "SCAL",
473 "STR",
474 "PROG",
475 "IMPROPER",
476 "VARNT"
477};
478
479char *stars = "\t***";
480
481/*
482 * Dump the namelist from the
483 * current nlp down to 'to'.
484 * All the namelist is dumped if
485 * to is NIL.
486 */
487dumpnl(to, rout)
488 struct nl *to;
489{
490 register struct nl *p;
491 register int j;
492 struct nls *nlsp;
493 int i, v, head;
494
495 if (opt('y') == 0)
496 return;
497 if (to != NIL)
498 printf("\n\"%s\" Block=%d\n", rout, cbn);
499 nlsp = nlact;
500 head = NIL;
501 for (p = nlp; p != to;) {
502 if (p == nlsp->nls_low) {
503 if (nlsp == &ntab[0])
504 break;
505 nlsp--;
506 p = nlsp->nls_high;
507 }
508 p--;
509 if (head == NIL) {
510 printf("\tName\tClass Bn+Flags\tType\tVal\tChn\n");
511 head++;
512 }
513 printf("%3d:", nloff(p));
514 if (p->symbol)
515 printf("\t%.7s", p->symbol);
516 else
517 printf(stars);
518 if (p->class)
519 printf("\t%s", ctext[p->class]);
520 else
521 printf(stars);
522 if (p->nl_flags) {
523 pchr('\t');
524 if (p->nl_flags & 037)
525 printf("%d ", p->nl_flags & 037);
526#ifndef PI0
527 if (p->nl_flags & NMOD)
528 pchr('M');
529 if (p->nl_flags & NUSED)
530 pchr('U');
531#endif
532 if (p->nl_flags & NFILES)
533 pchr('F');
534 } else
535 printf(stars);
536 if (p->type)
537 printf("\t[%d]", nloff(p->type));
538 else
539 printf(stars);
540 v = p->value[0];
541 switch (p->class) {
542 case TYPE:
543 break;
544 case VARNT:
545 goto con;
546 case CONST:
547 switch (nloff(p->type)) {
548 default:
549 printf("\t%d", v);
550 break;
551 case TDOUBLE:
552 printf("\t%f", p->real);
553 break;
554 case TINT:
555 case T4INT:
556con:
557 printf("\t%ld", p->range[0]);
558 break;
559 case TSTR:
560 printf("\t'%s'", p->ptr[0]);
561 break;
562 }
563 break;
564 case VAR:
565 case REF:
566 case WITHPTR:
567 printf("\t%d,%d", cbn, v);
568 break;
569 case SCAL:
570 case RANGE:
571 printf("\t%ld..%ld", p->range[0], p->range[1]);
572 break;
573 case RECORD:
574 printf("\t%d(%d)", v, p->value[NL_FLDSZ]);
575 break;
576 case FIELD:
577 printf("\t%d", v);
578 break;
579 case STR:
580 printf("\t|%d|", p->value[0]);
581 break;
582 case FVAR:
583 case FUNC:
584 case PROC:
585 case PROG:
586 if (cbn == 0) {
587 printf("\t<%o>", p->value[0] & 0377);
588#ifndef PI0
589 if (p->value[0] & NSTAND)
590 printf("\tNSTAND");
591#endif
592 break;
593 }
594 v = p->value[1];
595 default:
596casedef:
597 if (v)
598 printf("\t<%d>", v);
599 else
600 printf(stars);
601 }
602 if (p->chain)
603 printf("\t[%d]", nloff(p->chain));
604 switch (p->class) {
605 case RECORD:
606 if (p->ptr[NL_VARNT])
607 printf("\tVARNT=[%d]", nloff(p->ptr[NL_VARNT]));
608 if (p->ptr[NL_TAG])
609 printf(" TAG=[%d]", nloff(p->ptr[NL_TAG]));
610 break;
611 case VARNT:
612 printf("\tVTOREC=[%d]", nloff(p->ptr[NL_VTOREC]));
613 break;
614 }
615# ifdef PTREE
616 pchr( '\t' );
617 pPrintPointer( stdout , "%s" , p -> inTree );
618# endif
619 pchr('\n');
620 }
621 if (head == 0)
622 printf("\tNo entries\n");
623}
624#endif
625
626\f
627/*
628 * Define a new name list entry
629 * with initial symbol, class, type
630 * and value[0] as given. A new name
631 * list segment is allocated to hold
632 * the next name list slot if necessary.
633 */
634struct nl *
635defnl(sym, cls, typ, val)
636 char *sym;
637 int cls;
638 struct nl *typ;
639 int val;
640{
641 register struct nl *p;
642 register int *q, i;
643 char *cp;
644
645 p = nlp;
646
647 /*
648 * Zero out this entry
649 */
650 q = p;
651 i = (sizeof *p)/(sizeof (int));
652 do
653 *q++ = 0;
654 while (--i);
655
656 /*
657 * Insert the values
658 */
659 p->symbol = sym;
660 p->class = cls;
661 p->type = typ;
662 p->nl_block = cbn;
663 p->value[0] = val;
664
665 /*
666 * Insure that the next namelist
667 * entry actually exists. This is
668 * really not needed here, it would
669 * suffice to do it at entry if we
670 * need the slot. It is done this
671 * way because, historically, nlp
672 * always pointed at the next namelist
673 * slot.
674 */
675 nlp++;
676 if (nlp >= nlact->nls_high) {
677 i = NLINC;
678 cp = malloc(NLINC * sizeof *nlp);
679 if (cp == -1) {
680 i = NLINC / 2;
681 cp = malloc((NLINC / 2) * sizeof *nlp);
682 }
683 if (cp == -1) {
684 error("Ran out of memory (defnl)");
685 pexit(DIED);
686 }
687 nlact++;
688 if (nlact >= &ntab[MAXNL]) {
689 error("Ran out of name list tables");
690 pexit(DIED);
691 }
692 nlp = cp;
693 nlact->nls_low = nlp;
694 nlact->nls_high = nlact->nls_low + i;
695 }
696 return (p);
697}
698
699/*
700 * Make a duplicate of the argument
701 * namelist entry for, e.g., type
702 * declarations of the form 'type a = b'
703 * and array indicies.
704 */
705struct nl *
706nlcopy(p)
707 struct nl *p;
708{
709 register int *p1, *p2, i;
710
711 p1 = p;
712 p = p2 = defnl(0, 0, 0, 0);
713 i = (sizeof *p)/(sizeof (int));
714 do
715 *p2++ = *p1++;
716 while (--i);
717 p->chain = NIL;
718 return (p);
719}
720
721/*
722 * Compute a namelist offset
723 */
724nloff(p)
725 struct nl *p;
726{
727
728 return (p - nl);
729}
730\f
731/*
732 * Enter a symbol into the block
733 * symbol table. Symbols are hashed
734 * 64 ways based on low 6 bits of the
735 * character pointer into the string
736 * table.
737 */
738struct nl *
739enter(np)
740 struct nl *np;
741{
742 register struct nl *rp, *hp;
743 register struct nl *p;
744 int i;
745
746 rp = np;
747 if (rp == NIL)
748 return (NIL);
749#ifndef PI1
750 if (cbn > 0)
751 if (rp->symbol == input->symbol || rp->symbol == output->symbol)
752 error("Pre-defined files input and output must not be redefined");
753#endif
754 i = rp->symbol;
755 i &= 077;
756 hp = disptab[i];
757 if (rp->class != BADUSE && rp->class != FIELD)
758 for (p = hp; p != NIL && (p->nl_block & 037) == cbn; p = p->nl_next)
759 if (p->symbol == rp->symbol && p->class != BADUSE && p->class != FIELD) {
760#ifndef PI1
761 error("%s is already defined in this block", rp->symbol);
762#endif
763 break;
764
765 }
766 rp->nl_next = hp;
767 disptab[i] = rp;
768 return (rp);
769}
770#endif