/* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)type.c 5.1 (Berkeley) 6/5/85"; #endif not lint #include "whoami.h" #include "0.h" #include "tree.h" #include "objfmt.h" #include "tree_ty.h" /* * Type declaration part */ /*ARGSUSED*/ typebeg( lineofytype , r ) int lineofytype; { static bool type_order = FALSE; static bool type_seen = FALSE; /* * this allows for multiple * declaration parts unless * standard option has been * specified. * If routine segment is being * compiled, do level one processing. */ #ifndef PI1 if (!progseen) level1(); line = lineofytype; if ( parts[ cbn ] & ( VPRT | RPRT ) ) { if ( opt( 's' ) ) { standard(); error("Type declarations should precede var and routine declarations"); } else { if ( !type_order ) { type_order = TRUE; warning(); error("Type declarations should precede var and routine declarations"); } } } if (parts[ cbn ] & TPRT) { if ( opt( 's' ) ) { standard(); error("All types should be declared in one type part"); } else { if ( !type_seen ) { type_seen = TRUE; warning(); error("All types should be declared in one type part"); } } } parts[ cbn ] |= TPRT; #endif /* * Forechain is the head of a list of types that * might be self referential. We chain them up and * process them later. */ forechain = NIL; #ifdef PI0 send(REVTBEG); #endif } type(tline, tid, tdecl) int tline; char *tid; register struct tnode *tdecl; { register struct nl *np; struct nl *tnp; np = gtype(tdecl); line = tline; tnp = defnl(tid, TYPE, np, 0); #ifndef PI0 enter(tnp)->nl_flags |= (char) NMOD; #else (void) enter(tnp); send(REVTYPE, tline, tid, tdecl); #endif #ifdef PC if (cbn == 1) { stabgtype(tid, np, line); } else { stabltype(tid, np); } #endif PC # ifdef PTREE { pPointer Type = TypeDecl( tid , tdecl ); pPointer *Types; pSeize( PorFHeader[ nesting ] ); Types = &( pDEF( PorFHeader[ nesting ] ).PorFTypes ); *Types = ListAppend( *Types , Type ); pRelease( PorFHeader[ nesting ] ); } # endif } typeend() { #ifdef PI0 send(REVTEND); #endif foredecl(); } /* * Return a type pointer (into the namelist) * from a parse tree for a type, building * namelist entries as needed. */ struct nl * gtype(r) register struct tnode *r; { register struct nl *np; register int oline; #ifdef OBJ long w; #endif if (r == TR_NIL) return (NLNIL); oline = line; if (r->tag != T_ID) oline = line = r->lined.line_no; switch (r->tag) { default: panic("type"); case T_TYID: r = (struct tnode *) (&(r->tyid_node.line_no)); case T_ID: np = lookup(r->char_const.cptr); if (np == NLNIL) break; if (np->class != TYPE) { #ifndef PI1 error("%s is a %s, not a type as required", r->char_const.cptr, classes[np->class]); #endif np = NLNIL; break; } np = np->type; break; case T_TYSCAL: np = tyscal(r); break; case T_TYCRANG: np = tycrang(r); break; case T_TYRANG: np = tyrang(r); break; case T_TYPTR: np = defnl((char *) 0, PTR, NLNIL, 0 ); np -> ptr[0] = ((struct nl *) r->ptr_ty.id_node); np->nl_next = forechain; forechain = np; break; case T_TYPACK: np = gtype(r->comp_ty.type); break; case T_TYCARY: case T_TYARY: np = tyary(r); break; case T_TYREC: np = tyrec(r->comp_ty.type, 0); # ifdef PTREE /* * mung T_TYREC[3] to point to the record * for RecTCopy */ r->comp_ty.nl_entry = np; # endif break; case T_TYFILE: np = gtype(r->comp_ty.type); if (np == NLNIL) break; #ifndef PI1 if (np->nl_flags & NFILES) error("Files cannot be members of files"); #endif np = defnl((char *) 0, FILET, np, 0); np->nl_flags |= NFILES; break; case T_TYSET: np = gtype(r->comp_ty.type); if (np == NLNIL) break; if (np->type == nl+TDOUBLE) { #ifndef PI1 error("Set of real is not allowed"); #endif np = NLNIL; break; } if (np->class != RANGE && np->class != SCAL) { #ifndef PI1 error("Set type must be range or scalar, not %s", nameof(np)); #endif np = NLNIL; break; } #ifndef PI1 if (width(np) > 2) error("Implementation restriction: sets must be indexed by 16 bit quantities"); #endif np = defnl((char *) 0, SET, np, 0); break; } line = oline; #ifndef PC w = lwidth(np); if (w >= TOOMUCH) { error("Storage requirement of %s exceeds the implementation limit of %D by %D bytes", nameof(np), (char *) (long)(TOOMUCH-1), (char *) (long)(w-TOOMUCH+1)); np = NLNIL; } #endif return (np); } /* * Scalar (enumerated) types */ struct nl * tyscal(r) struct tnode *r; /* T_TYSCAL */ { register struct nl *np, *op, *zp; register struct tnode *v; int i; np = defnl((char *) 0, SCAL, NLNIL, 0); np->type = np; v = r->comp_ty.type; if (v == TR_NIL) return (NLNIL); i = -1; zp = np; for (; v != TR_NIL; v = v->list_node.next) { op = enter(defnl((char *) v->list_node.list, CONST, np, ++i)); #ifndef PI0 op->nl_flags |= NMOD; #endif op->value[1] = i; zp->chain = op; zp = op; } np->range[1] = i; return (np); } /* * Declare a subrange for conformant arrays. */ struct nl * tycrang(r) register struct tnode *r; { register struct nl *p, *op, *tp; tp = gtype(r->crang_ty.type); if ( tp == NLNIL ) return (NLNIL); /* * Just make a new type -- the lower and upper bounds must be * set by params(). */ p = defnl ( 0, CRANGE, tp, 0 ); return(p); } /* * Declare a subrange. */ struct nl * tyrang(r) register struct tnode *r; /* T_TYRANG */ { register struct nl *lp, *hp; double high; int c, c1; gconst(r->rang_ty.const2); hp = con.ctype; high = con.crval; gconst(r->rang_ty.const1); lp = con.ctype; if (lp == NLNIL || hp == NLNIL) return (NLNIL); if (norange(lp) || norange(hp)) return (NLNIL); c = classify(lp); c1 = classify(hp); if (c != c1) { #ifndef PI1 error("Can't mix %ss and %ss in subranges", nameof(lp), nameof(hp)); #endif return (NLNIL); } if (c == TSCAL && scalar(lp) != scalar(hp)) { #ifndef PI1 error("Scalar types must be identical in subranges"); #endif return (NLNIL); } if (con.crval > high) { #ifndef PI1 error("Range lower bound exceeds upper bound"); #endif return (NLNIL); } lp = defnl((char *) 0, RANGE, hp->type, 0); lp->range[0] = con.crval; lp->range[1] = high; return (lp); } norange(p) register struct nl *p; { if (isa(p, "d")) { #ifndef PI1 error("Subrange of real is not allowed"); #endif return (1); } if (isnta(p, "bcsi")) { #ifndef PI1 error("Subrange bounds must be Boolean, character, integer or scalar, not %s", nameof(p)); #endif return (1); } return (0); } /* * Declare arrays and chain together the dimension specification */ struct nl * tyary(r) struct tnode *r; { struct nl *np; register struct tnode *tl, *s; register struct nl *tp, *ltp; int i, n; s = r; /* Count the dimensions */ for (n = 0; s->tag == T_TYARY || s->tag == T_TYCARY; s = s->ary_ty.type, n++) /* NULL STATEMENT */; tp = gtype(s); if (tp == NLNIL) return (NLNIL); np = defnl((char *) 0, ARRAY, tp, 0); np->nl_flags |= (tp->nl_flags) & NFILES; ltp = np; i = 0; for (s = r; s->tag == T_TYARY || s->tag == T_TYCARY; s = s->ary_ty.type) { for (tl = s->ary_ty.type_list; tl != TR_NIL; tl=tl->list_node.next){ tp = gtype(tl->list_node.list); if (tp == NLNIL) { np = NLNIL; continue; } if ((tp->class == RANGE || tp->class == CRANGE) && tp->type == nl+TDOUBLE) { #ifndef PI1 error("Index type for arrays cannot be real"); #endif np = NLNIL; continue; } if (tp->class != RANGE && tp->class != SCAL && tp->class !=CRANGE){ #ifndef PI1 error("Array index type is a %s, not a range or scalar as required", classes[tp->class]); #endif np = NLNIL; continue; } #ifndef PC if (tp->class == RANGE && bytes(tp->range[0], tp->range[1]) > 2) { #ifndef PI1 error("Value of dimension specifier too large or small for this implementation"); #endif continue; } #endif if (tp->class != CRANGE) tp = nlcopy(tp); i++; ltp->chain = tp; ltp = tp; } } if (np != NLNIL) np->value[0] = i; return (np); } /* * Delayed processing for pointers to * allow self-referential and mutually * recursive pointer constructs. */ foredecl() { register struct nl *p; for (p = forechain; p != NLNIL; p = p->nl_next) { if (p->class == PTR && p -> ptr[0] != 0) { p->type = gtype((struct tnode *) p -> ptr[0]); # ifdef PTREE { if ( pUSE( p -> inTree ).PtrTType == pNIL ) { pPointer PtrTo = tCopy( p -> ptr[0] ); pDEF( p -> inTree ).PtrTType = PtrTo; } } # endif # ifdef PC fixfwdtype(p); # endif p -> ptr[0] = 0; } } }