xref: /original-bsd/usr.bin/pascal/src/clas.c (revision a1c2194a)
1 /*-
2  * Copyright (c) 1980 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)clas.c	5.3 (Berkeley) 04/16/91";
10 #endif /* not lint */
11 
12 #include "whoami.h"
13 #include "0.h"
14 #include "tree.h"
15 #include "tree_ty.h"
16 
17 /*
18  * This is the array of class
19  * names for the classes returned
20  * by classify.  The order of the
21  * classes is the same as the base
22  * of the namelist, with special
23  * negative index entries for structures,
24  * scalars, pointers, sets and strings
25  * to be collapsed into.
26  */
27 char	*clnxxxx[] =
28 {
29 	"file",			/* -7	TFILE */
30 	"record",		/* -6	TREC */
31 	"array",		/* -5	TARY */
32 	"scalar",		/* -4	TSCAL */
33 	"pointer",		/* -3	TPTR */
34 	"set",			/* -2	TSET */
35 	"string",		/* -1	TSTR */
36 	"SNARK",		/*  0	NIL */
37 	"Boolean",		/*  1	TBOOL */
38 	"char",			/*  2	TCHAR */
39 	"integer",		/*  3	TINT */
40 	"real",			/*  4	TREAL */
41 	"\"nil\"",		/*  5	TNIL */
42 };
43 
44 char **clnames	= &clnxxxx[-(TFIRST)];
45 
46 /*
47  * Classify takes a pointer
48  * to a type and returns one
49  * of several interesting group
50  * classifications for easy use.
51  */
52 classify(p1)
53 	struct nl *p1;
54 {
55 	register struct nl *p;
56 
57 	p = p1;
58 swit:
59 	if (p == NLNIL) {
60 		nocascade();
61 		return (NIL);
62 	}
63 	if (p == &nl[TSTR])
64 		return (TSTR);
65 	if ( p == &nl[ TSET ] ) {
66 	    return TSET;
67 	}
68 	switch (p->class) {
69 		case PTR:
70 			return (TPTR);
71 		case ARRAY:
72 			if (p->type == nl+T1CHAR)
73 				return (TSTR);
74 			return (TARY);
75 		case STR:
76 			return (TSTR);
77 		case SET:
78 			return (TSET);
79 		case CRANGE:
80 		case RANGE:
81 			p = p->type;
82 			goto swit;
83 		case TYPE:
84 			if (p <= nl+TLAST)
85 				return (p - nl);
86 			panic("clas2");
87 		case FILET:
88 			return (TFILE);
89 		case RECORD:
90 			return (TREC);
91 		case SCAL:
92 			return (TSCAL);
93 		default:
94 			{
95 			    panic("clas");
96 			    return(NIL);
97 			}
98 	}
99 }
100 
101 #ifndef	PI0
102 /*
103  * Is p a text file?
104  */
105 text(p)
106 	struct nl *p;
107 {
108 
109 	return (p != NIL && p->class == FILET && p->type == nl+T1CHAR);
110 }
111 #endif
112 
113 /*
114  * Scalar returns a pointer to
115  * the the base scalar type of
116  * its argument if its argument
117  * is a SCALar else NIL.
118  */
119 struct nl *
120 scalar(p1)
121 	struct nl *p1;
122 {
123 	register struct nl *p;
124 
125 	p = p1;
126 	if (p == NLNIL)
127 		return (NLNIL);
128 	if (p->class == RANGE || p->class == CRANGE)
129 		p = p->type;
130 	if (p == NLNIL)
131 		return (NLNIL);
132 	return (p->class == SCAL ? p : NLNIL);
133 }
134 
135 /*
136  * Isa tells whether p
137  * is one of a group of
138  * namelist classes.  The
139  * classes wanted are specified
140  * by the characters in s.
141  * (Note that s would more efficiently,
142  * if less clearly, be given by a mask.)
143  */
144 isa(p, s)
145 	register struct nl *p;
146 	char *s;
147 {
148 	register i;
149 	register char *cp;
150 
151 	if (p == NIL)
152 		return (NIL);
153 	/*
154 	 * map ranges down to
155 	 * the base type
156 	 */
157 	if (p->class == RANGE) {
158 		p = p->type;
159 	}
160 	/*
161 	 * the following character/class
162 	 * associations are made:
163 	 *
164 	 *	s	scalar
165 	 *	b	Boolean
166 	 *	c	character
167 	 *	i	integer
168 	 *	d	double (real)
169 	 *	t	set
170 	 */
171 	switch (p->class) {
172 		case SET:
173 			i = TDOUBLE+1;
174 			break;
175 		case SCAL:
176 			i = 0;
177 			break;
178 		case CRANGE:
179 			/*
180 			 * find the base type of a conformant array range
181 			 */
182 			switch (classify(p->type)) {
183 				case TBOOL: i = 1; break;
184 				case TCHAR: i = 2; break;
185 				case TINT: i = 3; break;
186 				case TSCAL: i = 0; break;
187 				default:
188 					panic( "isa" );
189 			}
190 			break;
191 		default:
192 			i = p - nl;
193 	}
194 	if (i >= 0 && i <= TDOUBLE+1) {
195 		i = "sbcidt"[i];
196 		cp = s;
197 		while (*cp)
198 			if (*cp++ == i)
199 				return (1);
200 	}
201 	return (NIL);
202 }
203 
204 /*
205  * Isnta is !isa
206  */
207 isnta(p, s)
208     struct nl *p;
209     char *s;
210 {
211 
212 	return (!isa(p, s));
213 }
214 
215 /*
216  * "shorthand"
217  */
218 char *
219 nameof(p)
220 struct nl *p;
221 {
222 
223 	return (clnames[classify(p)]);
224 }
225 
226 #ifndef PI0
227 /* find out for sure what kind of node this is being passed
228    possibly several different kinds of node are passed to it */
229 int nowexp(r)
230 	struct tnode *r;
231 {
232 	if (r->tag == T_WEXP) {
233 		if (r->var_node.cptr == NIL)
234 			error("Oct/hex allowed only on writeln/write calls");
235 		else
236 			error("Width expressions allowed only in writeln/write calls");
237 		return (1);
238 	}
239 	return (NIL);
240 }
241 #endif
242 
243     /*
244      *	is a variable a local, a formal parameter, or a global?
245      *	all this from just the offset:
246      *	    globals are at levels 0 or 1
247      *	    positives are parameters
248      *	    negative evens are locals
249      */
250 /*ARGSUSED*/
251 whereis( offset , other_flags )
252     int		offset;
253     char	other_flags;
254 {
255 
256 #   ifdef OBJ
257 	return ( offset >= 0 ? PARAMVAR : LOCALVAR );
258 #   endif OBJ
259 #   ifdef PC
260 	switch ( other_flags & ( NGLOBAL | NPARAM | NLOCAL | NNLOCAL) ) {
261 	    default:
262 		panic( "whereis" );
263 	    case NGLOBAL:
264 		return GLOBALVAR;
265 	    case NPARAM:
266 		return PARAMVAR;
267 	    case NNLOCAL:
268 		return NAMEDLOCALVAR;
269 	    case NLOCAL:
270 		return LOCALVAR;
271 	}
272 #   endif PC
273 }
274