1*48116Sbostic /*- 2*48116Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48116Sbostic * All rights reserved. 4*48116Sbostic * 5*48116Sbostic * %sccs.include.redist.c% 622078Sdist */ 722078Sdist 822078Sdist #ifndef lint 9*48116Sbostic static char sccsid[] = "@(#)clas.c 5.3 (Berkeley) 04/16/91"; 10*48116Sbostic #endif /* not lint */ 11*48116Sbostic 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 * 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 */ 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 * 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 */ 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*/ 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