xref: /csrg-svn/usr.bin/pascal/src/type.c (revision 62221)
148116Sbostic /*-
2*62221Sbostic  * Copyright (c) 1980, 1993
3*62221Sbostic  *	The Regents of the University of California.  All rights reserved.
448116Sbostic  *
548116Sbostic  * %sccs.include.redist.c%
622200Sdist  */
7780Speter 
818353Smckusick #ifndef lint
9*62221Sbostic static char sccsid[] = "@(#)type.c	8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
11780Speter 
12780Speter #include "whoami.h"
13780Speter #include "0.h"
14780Speter #include "tree.h"
15780Speter #include "objfmt.h"
1618353Smckusick #include "tree_ty.h"
17780Speter 
18780Speter /*
19780Speter  * Type declaration part
20780Speter  */
2118353Smckusick /*ARGSUSED*/
typebeg(lineofytype,r)227951Speter typebeg( lineofytype , r )
237951Speter     int	lineofytype;
24780Speter {
257951Speter     static bool	type_order = FALSE;
267951Speter     static bool	type_seen = FALSE;
27780Speter 
28780Speter /*
29836Speter  * this allows for multiple
30780Speter  * declaration parts unless
31780Speter  * standard option has been
32780Speter  * specified.
33780Speter  * If routine segment is being
34780Speter  * compiled, do level one processing.
35780Speter  */
36780Speter 
37780Speter #ifndef PI1
38836Speter 	if (!progseen)
39836Speter 		level1();
407951Speter 	line = lineofytype;
41836Speter 	if ( parts[ cbn ] & ( VPRT | RPRT ) ) {
42836Speter 	    if ( opt( 's' ) ) {
43780Speter 		standard();
447951Speter 		error("Type declarations should precede var and routine declarations");
45836Speter 	    } else {
467951Speter 		if ( !type_order ) {
477951Speter 		    type_order = TRUE;
487951Speter 		    warning();
497951Speter 		    error("Type declarations should precede var and routine declarations");
507951Speter 		}
51836Speter 	    }
52780Speter 	}
53836Speter 	if (parts[ cbn ] & TPRT) {
54836Speter 	    if ( opt( 's' ) ) {
55780Speter 		standard();
567951Speter 		error("All types should be declared in one type part");
57836Speter 	    } else {
587951Speter 		if ( !type_seen ) {
597951Speter 		    type_seen = TRUE;
607951Speter 		    warning();
617951Speter 		    error("All types should be declared in one type part");
627951Speter 		}
63836Speter 	    }
64780Speter 	}
65836Speter 	parts[ cbn ] |= TPRT;
66780Speter #endif
67780Speter 	/*
68780Speter 	 * Forechain is the head of a list of types that
69780Speter 	 * might be self referential.  We chain them up and
70780Speter 	 * process them later.
71780Speter 	 */
72780Speter 	forechain = NIL;
73780Speter #ifdef PI0
74780Speter 	send(REVTBEG);
75780Speter #endif
76780Speter }
77780Speter 
type(tline,tid,tdecl)78780Speter type(tline, tid, tdecl)
79780Speter 	int tline;
80780Speter 	char *tid;
8118353Smckusick 	register struct tnode *tdecl;
82780Speter {
83780Speter 	register struct nl *np;
8418352Smckusick 	struct nl *tnp;
85780Speter 
86780Speter 	np = gtype(tdecl);
87780Speter 	line = tline;
8818352Smckusick 	tnp = defnl(tid, TYPE, np, 0);
89780Speter #ifndef PI0
9018353Smckusick 	enter(tnp)->nl_flags |= (char) NMOD;
91780Speter #else
9218353Smckusick 	(void) enter(tnp);
93780Speter 	send(REVTYPE, tline, tid, tdecl);
94780Speter #endif
95780Speter 
96780Speter #ifdef PC
97827Speter 	if (cbn == 1) {
9818352Smckusick 	    stabgtype(tid, np, line);
9918352Smckusick 	} else {
10018352Smckusick 	    stabltype(tid, np);
101827Speter 	}
102780Speter #endif PC
103780Speter 
104780Speter #	ifdef PTREE
105780Speter 	    {
106780Speter 		pPointer Type = TypeDecl( tid , tdecl );
107780Speter 		pPointer *Types;
108780Speter 
109780Speter 		pSeize( PorFHeader[ nesting ] );
110780Speter 		Types = &( pDEF( PorFHeader[ nesting ] ).PorFTypes );
111780Speter 		*Types = ListAppend( *Types , Type );
112780Speter 		pRelease( PorFHeader[ nesting ] );
113780Speter 	    }
114780Speter #	endif
115780Speter }
116780Speter 
typeend()117780Speter typeend()
118780Speter {
119780Speter 
120780Speter #ifdef PI0
121780Speter 	send(REVTEND);
122780Speter #endif
123780Speter 	foredecl();
124780Speter }
125780Speter 
126780Speter /*
127780Speter  * Return a type pointer (into the namelist)
128780Speter  * from a parse tree for a type, building
129780Speter  * namelist entries as needed.
130780Speter  */
131780Speter struct nl *
gtype(r)132780Speter gtype(r)
13318353Smckusick 	register struct tnode *r;
134780Speter {
135780Speter 	register struct nl *np;
1363081Smckusic 	register int oline;
13718353Smckusick #ifdef OBJ
1383081Smckusic 	long w;
13918353Smckusick #endif
140780Speter 
14118353Smckusick 	if (r == TR_NIL)
14218353Smckusick 		return (NLNIL);
143780Speter 	oline = line;
14418353Smckusick 	if (r->tag != T_ID)
14518353Smckusick 		oline = line = r->lined.line_no;
14618353Smckusick 	switch (r->tag) {
147780Speter 		default:
148780Speter 			panic("type");
149780Speter 		case T_TYID:
15018353Smckusick 			r = (struct tnode *) (&(r->tyid_node.line_no));
151780Speter 		case T_ID:
15218353Smckusick 			np = lookup(r->char_const.cptr);
15318353Smckusick 			if (np == NLNIL)
154780Speter 				break;
155780Speter 			if (np->class != TYPE) {
156780Speter #ifndef PI1
15718353Smckusick 				error("%s is a %s, not a type as required", r->char_const.cptr, classes[np->class]);
158780Speter #endif
15918353Smckusick 				np = NLNIL;
160780Speter 				break;
161780Speter 			}
162780Speter 			np = np->type;
163780Speter 			break;
164780Speter 		case T_TYSCAL:
165780Speter 			np = tyscal(r);
166780Speter 			break;
16718353Smckusick 		case T_TYCRANG:
16818353Smckusick 			np = tycrang(r);
16918353Smckusick 			break;
170780Speter 		case T_TYRANG:
171780Speter 			np = tyrang(r);
172780Speter 			break;
173780Speter 		case T_TYPTR:
17418353Smckusick 			np = defnl((char *) 0, PTR, NLNIL, 0 );
17518353Smckusick 			np -> ptr[0] = ((struct nl *) r->ptr_ty.id_node);
176780Speter 			np->nl_next = forechain;
177780Speter 			forechain = np;
178780Speter 			break;
179780Speter 		case T_TYPACK:
18018353Smckusick 			np = gtype(r->comp_ty.type);
181780Speter 			break;
18218353Smckusick 		case T_TYCARY:
183780Speter 		case T_TYARY:
184780Speter 			np = tyary(r);
185780Speter 			break;
186780Speter 		case T_TYREC:
18718353Smckusick 			np = tyrec(r->comp_ty.type, 0);
188780Speter #			ifdef PTREE
189780Speter 				/*
190780Speter 				 * mung T_TYREC[3] to point to the record
191780Speter 				 * for RecTCopy
192780Speter 				 */
19318353Smckusick 			    r->comp_ty.nl_entry = np;
194780Speter #			endif
195780Speter 			break;
196780Speter 		case T_TYFILE:
19718353Smckusick 			np = gtype(r->comp_ty.type);
19818353Smckusick 			if (np == NLNIL)
199780Speter 				break;
200780Speter #ifndef PI1
201780Speter 			if (np->nl_flags & NFILES)
202780Speter 				error("Files cannot be members of files");
203780Speter #endif
20418353Smckusick 			np = defnl((char *) 0, FILET, np, 0);
205780Speter 			np->nl_flags |= NFILES;
206780Speter 			break;
207780Speter 		case T_TYSET:
20818353Smckusick 			np = gtype(r->comp_ty.type);
20918353Smckusick 			if (np == NLNIL)
210780Speter 				break;
211780Speter 			if (np->type == nl+TDOUBLE) {
212780Speter #ifndef PI1
213780Speter 				error("Set of real is not allowed");
214780Speter #endif
21518353Smckusick 				np = NLNIL;
216780Speter 				break;
217780Speter 			}
218780Speter 			if (np->class != RANGE && np->class != SCAL) {
219780Speter #ifndef PI1
220780Speter 				error("Set type must be range or scalar, not %s", nameof(np));
221780Speter #endif
22218353Smckusick 				np = NLNIL;
223780Speter 				break;
224780Speter 			}
225780Speter #ifndef PI1
226780Speter 			if (width(np) > 2)
227780Speter 				error("Implementation restriction: sets must be indexed by 16 bit quantities");
228780Speter #endif
22918353Smckusick 			np = defnl((char *) 0, SET, np, 0);
230780Speter 			break;
231780Speter 	}
232780Speter 	line = oline;
23318353Smckusick #ifndef PC
23418352Smckusick 	w = lwidth(np);
235780Speter 	if (w >= TOOMUCH) {
2363081Smckusic 		error("Storage requirement of %s exceeds the implementation limit of %D by %D bytes",
23718353Smckusick 			nameof(np), (char *) (long)(TOOMUCH-1), (char *) (long)(w-TOOMUCH+1));
23818353Smckusick 		np = NLNIL;
239780Speter 	}
2401815Speter #endif
241780Speter 	return (np);
242780Speter }
243780Speter 
244780Speter /*
245780Speter  * Scalar (enumerated) types
246780Speter  */
24718353Smckusick struct nl *
tyscal(r)248780Speter tyscal(r)
24918353Smckusick 	struct tnode *r;	/* T_TYSCAL */
250780Speter {
251780Speter 	register struct nl *np, *op, *zp;
25218353Smckusick 	register struct tnode *v;
253780Speter 	int i;
254780Speter 
25518353Smckusick 	np = defnl((char *) 0, SCAL, NLNIL, 0);
256780Speter 	np->type = np;
25718353Smckusick 	v = r->comp_ty.type;
25818353Smckusick 	if (v == TR_NIL)
25918353Smckusick 		return (NLNIL);
260780Speter 	i = -1;
261780Speter 	zp = np;
26218353Smckusick 	for (; v != TR_NIL; v = v->list_node.next) {
26318353Smckusick 		op = enter(defnl((char *) v->list_node.list, CONST, np, ++i));
264780Speter #ifndef PI0
265780Speter 		op->nl_flags |= NMOD;
266780Speter #endif
267780Speter 		op->value[1] = i;
268780Speter 		zp->chain = op;
269780Speter 		zp = op;
270780Speter 	}
271780Speter 	np->range[1] = i;
272780Speter 	return (np);
273780Speter }
274780Speter 
275780Speter /*
27618353Smckusick  * Declare a subrange for conformant arrays.
27718353Smckusick  */
27818353Smckusick struct nl *
tycrang(r)27918353Smckusick tycrang(r)
28018353Smckusick 	register struct tnode *r;
28118353Smckusick {
28218353Smckusick 	register struct nl *p, *op, *tp;
28318353Smckusick 
28418353Smckusick 	tp = gtype(r->crang_ty.type);
28518353Smckusick 	if ( tp == NLNIL )
28618353Smckusick 		return (NLNIL);
28718353Smckusick 	/*
28818353Smckusick 	 * Just make a new type -- the lower and upper bounds must be
28918353Smckusick 	 * set by params().
29018353Smckusick 	 */
29118353Smckusick 	p = defnl ( 0, CRANGE, tp, 0 );
29218353Smckusick 	return(p);
29318353Smckusick }
29418353Smckusick 
29518353Smckusick /*
296780Speter  * Declare a subrange.
297780Speter  */
29818353Smckusick struct nl *
tyrang(r)299780Speter tyrang(r)
30018353Smckusick 	register struct tnode *r;  /* T_TYRANG */
301780Speter {
302780Speter 	register struct nl *lp, *hp;
303780Speter 	double high;
304780Speter 	int c, c1;
305780Speter 
30618353Smckusick 	gconst(r->rang_ty.const2);
307780Speter 	hp = con.ctype;
308780Speter 	high = con.crval;
30918353Smckusick 	gconst(r->rang_ty.const1);
310780Speter 	lp = con.ctype;
31118353Smckusick 	if (lp == NLNIL || hp == NLNIL)
31218353Smckusick 		return (NLNIL);
313780Speter 	if (norange(lp) || norange(hp))
31418353Smckusick 		return (NLNIL);
315780Speter 	c = classify(lp);
316780Speter 	c1 = classify(hp);
317780Speter 	if (c != c1) {
318780Speter #ifndef PI1
319780Speter 		error("Can't mix %ss and %ss in subranges", nameof(lp), nameof(hp));
320780Speter #endif
32118353Smckusick 		return (NLNIL);
322780Speter 	}
323780Speter 	if (c == TSCAL && scalar(lp) != scalar(hp)) {
324780Speter #ifndef PI1
325780Speter 		error("Scalar types must be identical in subranges");
326780Speter #endif
32718353Smckusick 		return (NLNIL);
328780Speter 	}
329780Speter 	if (con.crval > high) {
330780Speter #ifndef PI1
331780Speter 		error("Range lower bound exceeds upper bound");
332780Speter #endif
33318353Smckusick 		return (NLNIL);
334780Speter 	}
33518353Smckusick 	lp = defnl((char *) 0, RANGE, hp->type, 0);
336780Speter 	lp->range[0] = con.crval;
337780Speter 	lp->range[1] = high;
338780Speter 	return (lp);
339780Speter }
340780Speter 
norange(p)341780Speter norange(p)
342780Speter 	register struct nl *p;
343780Speter {
344780Speter 	if (isa(p, "d")) {
345780Speter #ifndef PI1
346780Speter 		error("Subrange of real is not allowed");
347780Speter #endif
348780Speter 		return (1);
349780Speter 	}
350780Speter 	if (isnta(p, "bcsi")) {
351780Speter #ifndef PI1
352780Speter 		error("Subrange bounds must be Boolean, character, integer or scalar, not %s", nameof(p));
353780Speter #endif
354780Speter 		return (1);
355780Speter 	}
356780Speter 	return (0);
357780Speter }
358780Speter 
359780Speter /*
360780Speter  * Declare arrays and chain together the dimension specification
361780Speter  */
362780Speter struct nl *
tyary(r)363780Speter tyary(r)
36418353Smckusick 	struct tnode *r;
365780Speter {
366780Speter 	struct nl *np;
36718353Smckusick 	register struct tnode *tl, *s;
368780Speter 	register struct nl *tp, *ltp;
36918353Smckusick 	int i, n;
370780Speter 
37118353Smckusick 	s = r;
37218353Smckusick 	/* Count the dimensions */
37318353Smckusick 	for (n = 0; s->tag == T_TYARY || s->tag == T_TYCARY;
37418353Smckusick 					s = s->ary_ty.type, n++)
37518353Smckusick 		/* NULL STATEMENT */;
37618353Smckusick 	tp = gtype(s);
37718353Smckusick 	if (tp == NLNIL)
37818353Smckusick 		return (NLNIL);
37918353Smckusick 	np = defnl((char *) 0, ARRAY, tp, 0);
380780Speter 	np->nl_flags |= (tp->nl_flags) & NFILES;
381780Speter 	ltp = np;
382780Speter 	i = 0;
38318353Smckusick 	for (s = r; s->tag == T_TYARY || s->tag == T_TYCARY;
38418353Smckusick 					s = s->ary_ty.type) {
38518353Smckusick 	    for (tl = s->ary_ty.type_list; tl != TR_NIL; tl=tl->list_node.next){
38618353Smckusick 		tp = gtype(tl->list_node.list);
38718353Smckusick 		if (tp == NLNIL) {
38818353Smckusick 			np = NLNIL;
389780Speter 			continue;
390780Speter 		}
39118353Smckusick 		if ((tp->class == RANGE || tp->class == CRANGE) &&
39218353Smckusick 		    tp->type == nl+TDOUBLE) {
393780Speter #ifndef PI1
394780Speter 			error("Index type for arrays cannot be real");
395780Speter #endif
39618353Smckusick 			np = NLNIL;
397780Speter 			continue;
398780Speter 		}
39918353Smckusick 		if (tp->class != RANGE && tp->class != SCAL && tp->class !=CRANGE){
400780Speter #ifndef PI1
401780Speter 			error("Array index type is a %s, not a range or scalar as required", classes[tp->class]);
402780Speter #endif
40318353Smckusick 			np = NLNIL;
404780Speter 			continue;
405780Speter 		}
4061815Speter #ifndef PC
407780Speter 		if (tp->class == RANGE && bytes(tp->range[0], tp->range[1]) > 2) {
408780Speter #ifndef PI1
409780Speter 			error("Value of dimension specifier too large or small for this implementation");
410780Speter #endif
411780Speter 			continue;
412780Speter 		}
4131815Speter #endif
41418353Smckusick 		if (tp->class != CRANGE)
41518353Smckusick 			tp = nlcopy(tp);
416780Speter 		i++;
417780Speter 		ltp->chain = tp;
418780Speter 		ltp = tp;
41918353Smckusick 	    }
420780Speter 	}
42118353Smckusick 	if (np != NLNIL)
422780Speter 		np->value[0] = i;
423780Speter 	return (np);
424780Speter }
425780Speter 
426780Speter /*
427780Speter  * Delayed processing for pointers to
428780Speter  * allow self-referential and mutually
429780Speter  * recursive pointer constructs.
430780Speter  */
foredecl()431780Speter foredecl()
432780Speter {
43318353Smckusick 	register struct nl *p;
434780Speter 
43518353Smckusick 	for (p = forechain; p != NLNIL; p = p->nl_next) {
436780Speter 		if (p->class == PTR && p -> ptr[0] != 0)
437780Speter 		{
43818353Smckusick 			p->type = gtype((struct tnode *) p -> ptr[0]);
439780Speter #			ifdef PTREE
440780Speter 			{
441780Speter 			    if ( pUSE( p -> inTree ).PtrTType == pNIL ) {
442780Speter 				pPointer	PtrTo = tCopy( p -> ptr[0] );
443780Speter 
444780Speter 				pDEF( p -> inTree ).PtrTType = PtrTo;
445780Speter 			    }
446780Speter 			}
447780Speter #			endif
44818352Smckusick #			ifdef PC
44918352Smckusick 			    fixfwdtype(p);
45018352Smckusick #			endif
451780Speter 			p -> ptr[0] = 0;
452780Speter 		}
453780Speter 	}
454780Speter }
455