1*747Speter /* Copyright (c) 1979 Regents of the University of California */ 2*747Speter 3*747Speter static char sccsid[] = "@(#)clas.c 1.1 08/27/80"; 4*747Speter 5*747Speter #include "whoami.h" 6*747Speter #include "0.h" 7*747Speter #include "tree.h" 8*747Speter 9*747Speter /* 10*747Speter * This is the array of class 11*747Speter * names for the classes returned 12*747Speter * by classify. The order of the 13*747Speter * classes is the same as the base 14*747Speter * of the namelist, with special 15*747Speter * negative index entries for structures, 16*747Speter * scalars, pointers, sets and strings 17*747Speter * to be collapsed into. 18*747Speter */ 19*747Speter char *clnxxxx[] = 20*747Speter { 21*747Speter "file", /* -7 TFILE */ 22*747Speter "record", /* -6 TREC */ 23*747Speter "array", /* -5 TARY */ 24*747Speter "scalar", /* -4 TSCAL */ 25*747Speter "pointer", /* -3 TPTR */ 26*747Speter "set", /* -2 TSET */ 27*747Speter "string", /* -1 TSTR */ 28*747Speter "SNARK", /* 0 NIL */ 29*747Speter "Boolean", /* 1 TBOOL */ 30*747Speter "char", /* 2 TCHAR */ 31*747Speter "integer", /* 3 TINT */ 32*747Speter "real", /* 4 TREAL */ 33*747Speter "\"nil\"", /* 5 TNIL */ 34*747Speter }; 35*747Speter 36*747Speter char **clnames = &clnxxxx[-(TFIRST)]; 37*747Speter 38*747Speter /* 39*747Speter * Classify takes a pointer 40*747Speter * to a type and returns one 41*747Speter * of several interesting group 42*747Speter * classifications for easy use. 43*747Speter */ 44*747Speter classify(p1) 45*747Speter struct nl *p1; 46*747Speter { 47*747Speter register struct nl *p; 48*747Speter 49*747Speter p = p1; 50*747Speter swit: 51*747Speter if (p == NIL) { 52*747Speter nocascade(); 53*747Speter return (NIL); 54*747Speter } 55*747Speter if (p == &nl[TSTR]) 56*747Speter return (TSTR); 57*747Speter if ( p == &nl[ TSET ] ) { 58*747Speter return TSET; 59*747Speter } 60*747Speter switch (p->class) { 61*747Speter case PTR: 62*747Speter return (TPTR); 63*747Speter case ARRAY: 64*747Speter if (p->type == nl+T1CHAR) 65*747Speter return (TSTR); 66*747Speter return (TARY); 67*747Speter case STR: 68*747Speter return (TSTR); 69*747Speter case SET: 70*747Speter return (TSET); 71*747Speter case RANGE: 72*747Speter p = p->type; 73*747Speter goto swit; 74*747Speter case TYPE: 75*747Speter if (p <= nl+TLAST) 76*747Speter return (p - nl); 77*747Speter panic("clas2"); 78*747Speter case FILET: 79*747Speter return (TFILE); 80*747Speter case RECORD: 81*747Speter return (TREC); 82*747Speter case SCAL: 83*747Speter return (TSCAL); 84*747Speter default: 85*747Speter panic("clas"); 86*747Speter } 87*747Speter } 88*747Speter 89*747Speter #ifndef PI0 90*747Speter /* 91*747Speter * Is p a text file? 92*747Speter */ 93*747Speter text(p) 94*747Speter struct nl *p; 95*747Speter { 96*747Speter 97*747Speter return (p != NIL && p->class == FILET && p->type == nl+T1CHAR); 98*747Speter } 99*747Speter #endif 100*747Speter 101*747Speter /* 102*747Speter * Scalar returns a pointer to 103*747Speter * the the base scalar type of 104*747Speter * its argument if its argument 105*747Speter * is a SCALar else NIL. 106*747Speter */ 107*747Speter scalar(p1) 108*747Speter struct nl *p1; 109*747Speter { 110*747Speter register struct nl *p; 111*747Speter 112*747Speter p = p1; 113*747Speter if (p == NIL) 114*747Speter return (NIL); 115*747Speter if (p->class == RANGE) 116*747Speter p = p->type; 117*747Speter if (p == NIL) 118*747Speter return (NIL); 119*747Speter return (p->class == SCAL ? p : NIL); 120*747Speter } 121*747Speter 122*747Speter /* 123*747Speter * Isa tells whether p 124*747Speter * is one of a group of 125*747Speter * namelist classes. The 126*747Speter * classes wanted are specified 127*747Speter * by the characters in s. 128*747Speter * (Note that s would more efficiently, 129*747Speter * if less clearly, be given by a mask.) 130*747Speter */ 131*747Speter isa(p, s) 132*747Speter register struct nl *p; 133*747Speter char *s; 134*747Speter { 135*747Speter register i; 136*747Speter register char *cp; 137*747Speter 138*747Speter if (p == NIL) 139*747Speter return (NIL); 140*747Speter /* 141*747Speter * map ranges down to 142*747Speter * the base type 143*747Speter */ 144*747Speter if (p->class == RANGE) 145*747Speter p = p->type; 146*747Speter /* 147*747Speter * the following character/class 148*747Speter * associations are made: 149*747Speter * 150*747Speter * s scalar 151*747Speter * b Boolean 152*747Speter * c character 153*747Speter * i integer 154*747Speter * d double (real) 155*747Speter * t set 156*747Speter */ 157*747Speter switch (p->class) { 158*747Speter case SET: 159*747Speter i = TDOUBLE+1; 160*747Speter break; 161*747Speter case SCAL: 162*747Speter i = 0; 163*747Speter break; 164*747Speter default: 165*747Speter i = p - nl; 166*747Speter } 167*747Speter if (i >= 0 && i <= TDOUBLE+1) { 168*747Speter i = "sbcidt"[i]; 169*747Speter cp = s; 170*747Speter while (*cp) 171*747Speter if (*cp++ == i) 172*747Speter return (1); 173*747Speter } 174*747Speter return (NIL); 175*747Speter } 176*747Speter 177*747Speter /* 178*747Speter * Isnta is !isa 179*747Speter */ 180*747Speter isnta(p, s) 181*747Speter { 182*747Speter 183*747Speter return (!isa(p, s)); 184*747Speter } 185*747Speter 186*747Speter /* 187*747Speter * "shorthand" 188*747Speter */ 189*747Speter nameof(p) 190*747Speter { 191*747Speter 192*747Speter return (clnames[classify(p)]); 193*747Speter } 194*747Speter 195*747Speter #ifndef PI0 196*747Speter nowexp(r) 197*747Speter int *r; 198*747Speter { 199*747Speter if (r[0] == T_WEXP) { 200*747Speter if (r[2] == NIL) 201*747Speter error("Oct/hex allowed only on writeln/write calls"); 202*747Speter else 203*747Speter error("Width expressions allowed only in writeln/write calls"); 204*747Speter return (1); 205*747Speter } 206*747Speter return (NIL); 207*747Speter } 208*747Speter #endif 209