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