1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)tran.c 4.7 (Berkeley) 05/26/93"; 10 #endif /* not lint */ 11 12 #include "stdio.h" 13 #include "awk.def" 14 #include "awk.h" 15 16 cell *symtab[MAXSYM]; /* symbol table pointers */ 17 18 char **FS; /* initial field sep */ 19 char **RS; /* initial record sep */ 20 char **OFS; /* output field sep */ 21 char **ORS; /* output record sep */ 22 char **OFMT; /*output format for numbers*/ 23 awkfloat *NF; /* number of fields in current record */ 24 awkfloat *NR; /* number of current record */ 25 char **FILENAME; /* current filename argument */ 26 27 cell *recloc; /* location of record */ 28 cell *nrloc; /* NR */ 29 cell *nfloc; /* NF */ 30 31 syminit() 32 { 33 setsymtab("0", tostring("0"), 0.0, NUM|STR|CON|FLD, symtab); 34 /* this one is used for if(x)... tests: */ 35 setsymtab("$zero&null", tostring(""), 0.0, NUM|STR|CON|FLD, symtab); 36 recloc = setsymtab("$record", record, 0.0, STR|FLD, symtab); 37 dprintf("recloc %o lookup %o\n", recloc, lookup("$record", symtab, 0), NULL); 38 FS = &setsymtab("FS", tostring(" "), 0.0, STR|FLD, symtab)->sval; 39 RS = &setsymtab("RS", tostring("\n"), 0.0, STR|FLD, symtab)->sval; 40 OFS = &setsymtab("OFS", tostring(" "), 0.0, STR|FLD, symtab)->sval; 41 ORS = &setsymtab("ORS", tostring("\n"), 0.0, STR|FLD, symtab)->sval; 42 OFMT = &setsymtab("OFMT", tostring("%.6g"), 0.0, STR|FLD, symtab)->sval; 43 FILENAME = &setsymtab("FILENAME", EMPTY, 0.0, STR|FLD, symtab)->sval; 44 nfloc = setsymtab("NF", EMPTY, 0.0, NUM, symtab); 45 NF = &nfloc->fval; 46 nrloc = setsymtab("NR", EMPTY, 0.0, NUM, symtab); 47 NR = &nrloc->fval; 48 } 49 50 cell **makesymtab() 51 { 52 int i; 53 cell **cp; 54 55 cp = (cell **) malloc(MAXSYM * sizeof(cell *)); 56 if (cp == NULL) 57 error(FATAL, "out of space in makesymtab"); 58 for (i = 0; i < MAXSYM; i++) 59 cp[i] = 0; 60 return(cp); 61 } 62 63 freesymtab(ap) /* free symbol table */ 64 cell *ap; 65 { 66 cell *cp, **tp; 67 int i; 68 69 if (!(ap->tval & ARR)) 70 return; 71 tp = (cell **) ap->sval; 72 for (i = 0; i < MAXSYM; i++) { 73 for (cp = tp[i]; cp != NULL; cp = cp->nextval) { 74 strfree(cp->nval); 75 strfree(cp->sval); 76 free(cp); 77 } 78 } 79 xfree(tp); 80 } 81 82 cell *setsymtab(n, s, f, t, tab) 83 char *n, *s; 84 awkfloat f; 85 unsigned t; 86 cell **tab; 87 { 88 register h; 89 register cell *p; 90 cell *lookup(); 91 92 if (n != NULL && (p = lookup(n, tab, 0)) != NULL) { 93 if (s != EMPTY ) xfree(s); /* careful here */ 94 dprintf("setsymtab found %o: %s", p, p->nval, NULL); 95 dprintf(" %s %g %o\n", p->sval, p->fval, p->tval); 96 return(p); 97 } 98 p = (cell *) malloc(sizeof(cell)); 99 if (p == NULL) 100 error(FATAL, "symbol table overflow at %s", n); 101 p->nval = tostring(n); 102 p->sval = s; 103 p->fval = f; 104 p->tval = t; 105 h = hash(n); 106 p->nextval = tab[h]; 107 tab[h] = p; 108 dprintf("setsymtab set %o: %s", p, p->nval, NULL); 109 dprintf(" %s %g %o\n", p->sval, p->fval, p->tval); 110 return(p); 111 } 112 113 hash(s) /* form hash value for string s */ 114 register unsigned char *s; 115 { 116 register int hashval; 117 118 for (hashval = 0; *s != '\0'; ) 119 hashval += *s++; 120 return(hashval % MAXSYM); 121 } 122 123 cell *lookup(s, tab, flag) /* look for s in tab, flag must match*/ 124 register char *s; 125 cell **tab; 126 { 127 register cell *p; 128 129 for (p = tab[hash(s)]; p != NULL; p = p->nextval) 130 if (strcmp(s, p->nval) == 0 && 131 (flag == 0 || flag == p->tval)) 132 return(p); /* found it */ 133 return(NULL); /* not found */ 134 } 135 136 awkfloat setfval(vp, f) 137 register cell *vp; 138 awkfloat f; 139 { 140 dprintf("setfval: %o %g\n", vp, f, NULL); 141 checkval(vp); 142 if (vp == recloc) 143 error(FATAL, "can't set $0"); 144 vp->tval &= ~STR; /* mark string invalid */ 145 vp->tval |= NUM; /* mark number ok */ 146 if ((vp->tval & FLD) && isnull(vp->nval)) 147 donerec = 0; 148 return(vp->fval = f); 149 } 150 151 char *setsval(vp, s) 152 register cell *vp; 153 char *s; 154 { 155 dprintf("setsval: %o %s\n", vp, s, NULL); 156 checkval(vp); 157 if (vp == recloc) 158 error(FATAL, "can't set $0"); 159 vp->tval &= ~NUM; 160 vp->tval |= STR; 161 if ((vp->tval & FLD) && isnull(vp->nval)) 162 donerec = 0; 163 if (!(vp->tval&FLD)) 164 strfree(vp->sval); 165 vp->tval &= ~FLD; 166 return(vp->sval = tostring(s)); 167 } 168 169 awkfloat getfval(vp) 170 register cell *vp; 171 { 172 173 if (vp->sval == record && donerec == 0) 174 recbld(); 175 dprintf("getfval: %o", vp, NULL, NULL); 176 checkval(vp); 177 if ((vp->tval & NUM) == 0) { 178 /* the problem is to make non-numeric things */ 179 /* have unlikely numeric variables, so that */ 180 /* $1 == $2 comparisons sort of make sense when */ 181 /* one or the other is numeric */ 182 if (isanumber(vp->sval)) { 183 vp->fval = atof(vp->sval); 184 if (!(vp->tval & CON)) /* don't change type of a constant */ 185 vp->tval |= NUM; 186 } 187 else 188 vp->fval = 0.0; /* not a very good idea */ 189 } 190 dprintf(" %g\n", vp->fval, NULL, NULL); 191 return(vp->fval); 192 } 193 194 char *getsval(vp) 195 register cell *vp; 196 { 197 char s[100]; 198 199 if (vp->sval == record && donerec == 0) 200 recbld(); 201 dprintf("getsval: %o", vp, NULL, NULL); 202 checkval(vp); 203 if ((vp->tval & STR) == 0) { 204 if (!(vp->tval&FLD)) 205 strfree(vp->sval); 206 if ((long)vp->fval==vp->fval) 207 (void)sprintf(s, "%.20g", vp->fval); 208 else 209 (void)sprintf(s, *OFMT, vp->fval); 210 vp->sval = tostring(s); 211 vp->tval &= ~FLD; 212 vp->tval |= STR; 213 } 214 dprintf(" %s\n", vp->sval, NULL, NULL); 215 return(vp->sval); 216 } 217 218 checkval(vp) 219 register cell *vp; 220 { 221 if (vp->tval & ARR) 222 error(FATAL, "illegal reference to array %s", vp->nval); 223 if ((vp->tval & (NUM | STR)) == 0) 224 error(FATAL, "funny variable %o: %s %s %g %o", vp, vp->nval, 225 vp->sval, vp->fval, vp->tval); 226 } 227 228 char *tostring(s) 229 register char *s; 230 { 231 register char *p; 232 233 if (s==NULL){ 234 p = malloc(1); 235 if (p == NULL) 236 error(FATAL, "out of space in tostring on %s", s); 237 *p = '\0'; 238 } else { 239 p = malloc(strlen(s)+1); 240 if (p == NULL) 241 error(FATAL, "out of space in tostring on %s", s); 242 strcpy(p, s); 243 } 244 return(p); 245 } 246 #ifndef yfree 247 yfree(a) char *a; 248 { 249 printf("%o\n", a); 250 free(a); 251 } 252 #endif 253 #ifdef malloc 254 #undef malloc 255 char *ymalloc(u) unsigned u; 256 { char *p; 257 p = malloc(u); 258 printf("%o %o\n", u, p); 259 return(p); 260 } 261 #endif 262