148116Sbostic /*-
2*62205Sbostic * Copyright (c) 1980, 1993
3*62205Sbostic * The Regents of the University of California. All rights reserved.
448116Sbostic *
548116Sbostic * %sccs.include.redist.c%
622078Sdist */
722078Sdist
822078Sdist #ifndef lint
9*62205Sbostic static char sccsid[] = "@(#)clas.c 8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
1148116Sbostic
12747Speter #include "whoami.h"
13747Speter #include "0.h"
14747Speter #include "tree.h"
1514728Sthien #include "tree_ty.h"
16747Speter
17747Speter /*
18747Speter * This is the array of class
19747Speter * names for the classes returned
20747Speter * by classify. The order of the
21747Speter * classes is the same as the base
22747Speter * of the namelist, with special
23747Speter * negative index entries for structures,
24747Speter * scalars, pointers, sets and strings
25747Speter * to be collapsed into.
26747Speter */
27747Speter char *clnxxxx[] =
28747Speter {
29747Speter "file", /* -7 TFILE */
30747Speter "record", /* -6 TREC */
31747Speter "array", /* -5 TARY */
32747Speter "scalar", /* -4 TSCAL */
33747Speter "pointer", /* -3 TPTR */
34747Speter "set", /* -2 TSET */
35747Speter "string", /* -1 TSTR */
36747Speter "SNARK", /* 0 NIL */
37747Speter "Boolean", /* 1 TBOOL */
38747Speter "char", /* 2 TCHAR */
39747Speter "integer", /* 3 TINT */
40747Speter "real", /* 4 TREAL */
41747Speter "\"nil\"", /* 5 TNIL */
42747Speter };
43747Speter
44747Speter char **clnames = &clnxxxx[-(TFIRST)];
45747Speter
46747Speter /*
47747Speter * Classify takes a pointer
48747Speter * to a type and returns one
49747Speter * of several interesting group
50747Speter * classifications for easy use.
51747Speter */
52747Speter classify(p1)
53747Speter struct nl *p1;
54747Speter {
55747Speter register struct nl *p;
56747Speter
57747Speter p = p1;
58747Speter swit:
5914728Sthien if (p == NLNIL) {
60747Speter nocascade();
61747Speter return (NIL);
62747Speter }
63747Speter if (p == &nl[TSTR])
64747Speter return (TSTR);
65747Speter if ( p == &nl[ TSET ] ) {
66747Speter return TSET;
67747Speter }
68747Speter switch (p->class) {
69747Speter case PTR:
70747Speter return (TPTR);
71747Speter case ARRAY:
72747Speter if (p->type == nl+T1CHAR)
73747Speter return (TSTR);
74747Speter return (TARY);
75747Speter case STR:
76747Speter return (TSTR);
77747Speter case SET:
78747Speter return (TSET);
7915975Smckusick case CRANGE:
80747Speter case RANGE:
81747Speter p = p->type;
82747Speter goto swit;
83747Speter case TYPE:
84747Speter if (p <= nl+TLAST)
85747Speter return (p - nl);
86747Speter panic("clas2");
87747Speter case FILET:
88747Speter return (TFILE);
89747Speter case RECORD:
90747Speter return (TREC);
91747Speter case SCAL:
92747Speter return (TSCAL);
93747Speter default:
9414728Sthien {
9514728Sthien panic("clas");
9614728Sthien return(NIL);
9714728Sthien }
98747Speter }
99747Speter }
100747Speter
101747Speter #ifndef PI0
102747Speter /*
103747Speter * Is p a text file?
104747Speter */
105747Speter text(p)
106747Speter struct nl *p;
107747Speter {
108747Speter
109747Speter return (p != NIL && p->class == FILET && p->type == nl+T1CHAR);
110747Speter }
111747Speter #endif
112747Speter
113747Speter /*
114747Speter * Scalar returns a pointer to
115747Speter * the the base scalar type of
116747Speter * its argument if its argument
117747Speter * is a SCALar else NIL.
118747Speter */
11914728Sthien struct nl *
scalar(p1)120747Speter scalar(p1)
121747Speter struct nl *p1;
122747Speter {
123747Speter register struct nl *p;
124747Speter
125747Speter p = p1;
12614728Sthien if (p == NLNIL)
12714728Sthien return (NLNIL);
12815975Smckusick if (p->class == RANGE || p->class == CRANGE)
129747Speter p = p->type;
13014728Sthien if (p == NLNIL)
13114728Sthien return (NLNIL);
13214728Sthien return (p->class == SCAL ? p : NLNIL);
133747Speter }
134747Speter
135747Speter /*
136747Speter * Isa tells whether p
137747Speter * is one of a group of
138747Speter * namelist classes. The
139747Speter * classes wanted are specified
140747Speter * by the characters in s.
141747Speter * (Note that s would more efficiently,
142747Speter * if less clearly, be given by a mask.)
143747Speter */
isa(p,s)144747Speter isa(p, s)
145747Speter register struct nl *p;
146747Speter char *s;
147747Speter {
148747Speter register i;
149747Speter register char *cp;
150747Speter
151747Speter if (p == NIL)
152747Speter return (NIL);
153747Speter /*
154747Speter * map ranges down to
155747Speter * the base type
156747Speter */
15715975Smckusick if (p->class == RANGE) {
158747Speter p = p->type;
15915975Smckusick }
160747Speter /*
161747Speter * the following character/class
162747Speter * associations are made:
163747Speter *
164747Speter * s scalar
165747Speter * b Boolean
166747Speter * c character
167747Speter * i integer
168747Speter * d double (real)
169747Speter * t set
170747Speter */
171747Speter switch (p->class) {
172747Speter case SET:
173747Speter i = TDOUBLE+1;
174747Speter break;
175747Speter case SCAL:
176747Speter i = 0;
177747Speter break;
17815975Smckusick case CRANGE:
17915975Smckusick /*
18015975Smckusick * find the base type of a conformant array range
18115975Smckusick */
18215975Smckusick switch (classify(p->type)) {
18315975Smckusick case TBOOL: i = 1; break;
18415975Smckusick case TCHAR: i = 2; break;
18515975Smckusick case TINT: i = 3; break;
18615975Smckusick case TSCAL: i = 0; break;
18715975Smckusick default:
18815975Smckusick panic( "isa" );
18915975Smckusick }
19015975Smckusick break;
191747Speter default:
192747Speter i = p - nl;
193747Speter }
194747Speter if (i >= 0 && i <= TDOUBLE+1) {
195747Speter i = "sbcidt"[i];
196747Speter cp = s;
197747Speter while (*cp)
198747Speter if (*cp++ == i)
199747Speter return (1);
200747Speter }
201747Speter return (NIL);
202747Speter }
203747Speter
204747Speter /*
205747Speter * Isnta is !isa
206747Speter */
207747Speter isnta(p, s)
20814728Sthien struct nl *p;
20914728Sthien char *s;
210747Speter {
211747Speter
212747Speter return (!isa(p, s));
213747Speter }
214747Speter
215747Speter /*
216747Speter * "shorthand"
217747Speter */
21814728Sthien char *
nameof(p)219747Speter nameof(p)
22014728Sthien struct nl *p;
221747Speter {
222747Speter
223747Speter return (clnames[classify(p)]);
224747Speter }
225747Speter
226747Speter #ifndef PI0
22714728Sthien /* find out for sure what kind of node this is being passed
22814728Sthien possibly several different kinds of node are passed to it */
nowexp(r)22914728Sthien int nowexp(r)
23014728Sthien struct tnode *r;
231747Speter {
23214728Sthien if (r->tag == T_WEXP) {
23314728Sthien if (r->var_node.cptr == NIL)
234747Speter error("Oct/hex allowed only on writeln/write calls");
235747Speter else
236747Speter error("Width expressions allowed only in writeln/write calls");
237747Speter return (1);
238747Speter }
239747Speter return (NIL);
240747Speter }
241747Speter #endif
2423276Smckusic
2433276Smckusic /*
2443825Speter * is a variable a local, a formal parameter, or a global?
2453276Smckusic * all this from just the offset:
2463825Speter * globals are at levels 0 or 1
2473276Smckusic * positives are parameters
2483276Smckusic * negative evens are locals
2493276Smckusic */
25014728Sthien /*ARGSUSED*/
whereis(offset,other_flags)25114728Sthien whereis( offset , other_flags )
2523825Speter int offset;
2537920Smckusick char other_flags;
2543276Smckusic {
2553276Smckusic
2563825Speter # ifdef OBJ
2573825Speter return ( offset >= 0 ? PARAMVAR : LOCALVAR );
2583825Speter # endif OBJ
2593825Speter # ifdef PC
2609127Smckusick switch ( other_flags & ( NGLOBAL | NPARAM | NLOCAL | NNLOCAL) ) {
26114728Sthien default:
26214728Sthien panic( "whereis" );
2633825Speter case NGLOBAL:
2643825Speter return GLOBALVAR;
2653825Speter case NPARAM:
2663825Speter return PARAMVAR;
2679127Smckusick case NNLOCAL:
2689127Smckusick return NAMEDLOCALVAR;
2693825Speter case NLOCAL:
2703825Speter return LOCALVAR;
2713825Speter }
2723825Speter # endif PC
2733276Smckusic }
274