1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29 /* All Rights Reserved */ 30 31 #include "stdio.h" 32 #include "awk.def" 33 #include "awk.h" 34 #include <stdlib.h> 35 36 CELL *symtab[MAXSYM]; /* symbol table pointers */ 37 38 39 wchar_t **FS; /* initial field sep */ 40 wchar_t **RS; /* initial record sep */ 41 wchar_t **OFS; /* output field sep */ 42 wchar_t **ORS; /* output record sep */ 43 wchar_t **OFMT; /* output format for numbers */ 44 awkfloat *NF; /* number of fields in current record */ 45 awkfloat *NR; /* number of current record */ 46 wchar_t **FILENAME; /* current filename argument */ 47 48 49 CELL *recloc; /* location of record */ 50 CELL *nrloc; /* NR */ 51 CELL *nfloc; /* NF */ 52 53 void recbld(void); 54 55 void 56 syminit(void) 57 { 58 static wchar_t L_0[] = L"0"; 59 static wchar_t L_zeronull[] = L"$zero&null"; 60 static wchar_t L_record[] = L"$record"; 61 static wchar_t L_FS[] = L"FS"; 62 static wchar_t L_OFS[] = L"OFS"; 63 static wchar_t L_ORS[] = L"ORS"; 64 static wchar_t L_RS[] = L"RS"; 65 static wchar_t L_OFMT[] = L"OFMT"; 66 static wchar_t L_space[] = L" "; 67 static wchar_t L_newline[] = L"\n"; 68 static wchar_t L_dot6g[] = L"%.6g"; 69 static wchar_t L_FILENAME[] = L"FILENAME"; 70 static wchar_t L_NF[] = L"NF"; 71 static wchar_t L_NR[] = L"NR"; 72 73 74 setsymtab(L_0, tostring(L_0), 0.0, NUM|STR|CON|FLD, symtab); 75 /* this one is used for if (x)... tests: */ 76 setsymtab(L_zeronull, tostring(L_NULL), 0.0, NUM|STR|CON|FLD, symtab); 77 recloc = setsymtab(L_record, record, 0.0, STR|FLD, symtab); 78 dprintf("recloc %o lookup %o\n", 79 recloc, lookup(L_record, symtab, 0), NULL); 80 FS = &setsymtab(L_FS, tostring(L_space), 0.0, STR|FLD, symtab)->sval; 81 RS = &setsymtab(L_RS, tostring(L_newline), 0.0, STR|FLD, symtab)->sval; 82 OFS = &setsymtab(L_OFS, tostring(L_space), 0.0, STR|FLD, symtab)->sval; 83 ORS = &setsymtab(L_ORS, tostring(L_newline), 0.0, STR|FLD, 84 symtab)->sval; 85 OFMT = &setsymtab(L_OFMT, tostring(L_dot6g), 0.0, STR|FLD, 86 symtab)->sval; 87 FILENAME = &setsymtab(L_FILENAME, NULL, 0.0, STR|FLD, symtab)->sval; 88 nfloc = setsymtab(L_NF, NULL, 0.0, NUM, symtab); 89 NF = &nfloc->fval; 90 nrloc = setsymtab(L_NR, NULL, 0.0, NUM, symtab); 91 NR = &nrloc->fval; 92 } 93 94 95 CELL ** 96 makesymtab(void) 97 { 98 int i; 99 CELL **cp; 100 101 102 cp = (CELL **) malloc(MAXSYM * sizeof (CELL *)); 103 if (cp == NULL) 104 error(FATAL, "out of space in makesymtab"); 105 for (i = 0; i < MAXSYM; i++) 106 cp[i] = 0; 107 return (cp); 108 } 109 110 111 void 112 freesymtab(CELL *ap) /* free symbol table */ 113 { 114 CELL *cp, **tp, *next; 115 int i; 116 117 118 if (!(ap->tval & ARR)) 119 return; 120 tp = (CELL **) ap->sval; 121 for (i = 0; i < MAXSYM; i++) { 122 for (cp = tp[i]; cp != NULL; cp = next) { 123 next = cp->nextval; 124 xfree(cp->nval); 125 xfree(cp->sval); 126 free(cp); 127 } 128 } 129 xfree(tp); 130 } 131 132 133 CELL * 134 setsymtab(wchar_t *n, wchar_t *s, awkfloat f, unsigned t, CELL **tab) 135 { 136 int h; 137 CELL *p; 138 CELL *lookup(); 139 140 141 if (n != NULL && (p = lookup(n, tab, 0)) != NULL) { 142 xfree(s); 143 dprintf("setsymtab found %o: %ws\n", p, p->nval, NULL); 144 dprintf(" %ws %g %o\n", p->sval, p->fval, p->tval); 145 return (p); 146 } 147 p = (CELL *) malloc(sizeof (CELL)); 148 if (p == NULL) 149 error(FATAL, "symbol table overflow at %ws", n); 150 p->nval = tostring(n); 151 p->sval = s; 152 p->fval = f; 153 p->tval = t; 154 h = hash(n); 155 p->nextval = tab[h]; 156 tab[h] = p; 157 dprintf("setsymtab set %o: %ws\n", p, p->nval, NULL); 158 dprintf(" %ws %g %o\n", p->sval, p->fval, p->tval); 159 return (p); 160 } 161 162 163 int 164 hash(wchar_t *s) /* form hash value for string s */ 165 { 166 unsigned hashval; 167 168 169 for (hashval = 0; *s != '\0'; /* dummy */) 170 hashval += *s++; 171 return (hashval % MAXSYM); 172 } 173 174 175 CELL * 176 lookup(wchar_t *s, CELL **tab, int flag) 177 /* look for s in tab, flag must match */ 178 { 179 CELL *p; 180 181 182 for (p = tab[hash(s)]; p != NULL; p = p->nextval) 183 if (wscmp(s, p->nval) == 0 && 184 (flag == 0 || flag == p->tval)) 185 return (p); /* found it */ 186 return (NULL); /* not found */ 187 } 188 189 190 awkfloat 191 setfval(CELL *vp, awkfloat f) 192 { 193 dprintf("setfval: %o %g\n", vp, f, NULL); 194 /* imb */ 195 if (vp->tval & ARR) 196 error(FATAL, "illegal reference to array %s", vp->nval); 197 if ((vp->tval & (NUM | STR)) == 0) 198 error(FATAL, "funny variable %o: %ws %ws %g %o", vp, vp->nval, 199 vp->sval, vp->fval, vp->tval); 200 /* imb */ 201 if (vp == recloc) 202 error(FATAL, "can't set $0"); 203 vp->tval &= ~STR; /* mark string invalid */ 204 vp->tval |= NUM; /* mark number ok */ 205 if ((vp->tval & FLD) && vp->nval == 0) { 206 /* 207 * FLD really means that the string value was not 208 * "malloc"ed and should not be freed. All fields 209 * have this property, but not all cells with this 210 * property are fields. However, all cells with 211 * this property and with a NULL "nval" are fields. 212 * If we are setting the value of a field, indicate 213 * that the value of the record has to be recomputed, 214 * and if it's a higher field than the last one we 215 * assigned to, remember it for when we clear the 216 * fields out for the next record. 217 */ 218 donerec = 0; 219 if (vp > maxmfld) 220 maxmfld = vp; 221 } 222 return (vp->fval = f); 223 } 224 225 226 wchar_t * 227 setsval(CELL *vp, wchar_t *s) 228 { 229 dprintf("setsval: %o %ws\n", vp, s, NULL); 230 if (vp->tval & ARR) 231 error(FATAL, "illegal reference to array %ws", vp->nval); 232 if ((vp->tval & (NUM | STR)) == 0) 233 error(FATAL, "funny variable %o: %ws %ws %g %o", vp, vp->nval, 234 vp->sval, vp->fval, vp->tval); 235 if (vp == recloc) 236 error(FATAL, "can't set $0"); 237 vp->tval &= ~NUM; 238 vp->tval |= STR; 239 if ((vp->tval & FLD) && vp->nval == 0) { 240 /* 241 * See comment in "setfval". 242 */ 243 donerec = 0; 244 if (vp > maxmfld) 245 maxmfld = vp; 246 } 247 if (!(vp->tval&FLD)) 248 xfree(vp->sval); 249 vp->tval &= ~FLD; 250 return (vp->sval = tostring(s)); 251 } 252 253 254 awkfloat 255 getfval(CELL *vp) 256 { 257 258 259 if (vp->sval == record && donerec == 0) 260 recbld(); 261 dprintf("getfval: %o", vp, NULL, NULL); 262 if (vp->tval & ARR) 263 error(FATAL, "illegal reference to array %ws", vp->nval); 264 if ((vp->tval & (NUM | STR)) == 0) 265 error(FATAL, "funny variable %o: %ws %ws %g %o", vp, vp->nval, 266 vp->sval, vp->fval, vp->tval); 267 if ((vp->tval & NUM) == 0) { 268 /* the problem is to make non-numeric things */ 269 /* have unlikely numeric variables, so that */ 270 /* $1 == $2 comparisons sort of make sense when */ 271 /* one or the other is numeric */ 272 if (isanumber(vp->sval)) { 273 vp->fval = watof(vp->sval); 274 if (!(vp->tval & CON)) 275 /* don't change type of a constant */ 276 vp->tval |= NUM; 277 } 278 else 279 vp->fval = 0.0; /* not a very good idea */ 280 } 281 dprintf(" %g\n", vp->fval, NULL, NULL); 282 return (vp->fval); 283 } 284 285 286 wchar_t * 287 getsval(CELL *vp) 288 { 289 char s[100]; 290 wchar_t ws[100]; 291 292 293 if (vp->sval == record && donerec == 0) 294 recbld(); 295 dprintf("getsval: %o", vp, NULL, NULL); 296 if (vp->tval & ARR) 297 error(FATAL, "illegal reference to array %ws", vp->nval); 298 if ((vp->tval & (NUM | STR)) == 0) 299 error(FATAL, "funny variable %o: %ws %ws %g %o", vp, vp->nval, 300 vp->sval, vp->fval, vp->tval); 301 if ((vp->tval & STR) == 0) { 302 if (!(vp->tval&FLD)) 303 xfree(vp->sval); 304 if ((long long)vp->fval == vp->fval) 305 sprintf(s, "%.20g", vp->fval); 306 else 307 sprintf(s, toeuccode(*OFMT), vp->fval); 308 mbstowcs(ws, s, sizeof (ws) / sizeof (wchar_t)); 309 vp->sval = tostring(ws); 310 vp->tval &= ~FLD; 311 vp->tval |= STR; 312 } 313 dprintf(" %ws\n", vp->sval, NULL, NULL); 314 return (vp->sval); 315 } 316 317 318 wchar_t * 319 tostring(wchar_t *s) 320 { 321 wchar_t *p; 322 323 324 p = (wchar_t *) malloc((wslen(s)+1)*sizeof (wchar_t)); 325 if (p == NULL) 326 error(FATAL, "out of space in tostring on %ws", s); 327 wscpy(p, s); 328 return (p); 329 } 330 331 332 #ifndef yfree 333 yfree(char *a) 334 { 335 printf("%o\n", a); 336 free(a); 337 } 338 #endif 339