Thu Jan 20 21:26:20 2011 UTC ()
fix bug introduced in rev. 1.3: need to set the string before
converting it into a numerical value, otherwise we might get junk or crash


(drochner)
diff -r1.3 -r1.4 src/external/historical/nawk/dist/tran.c

cvs diff -r1.3 -r1.4 src/external/historical/nawk/dist/tran.c (switch to unified diff)

--- src/external/historical/nawk/dist/tran.c 2010/11/07 22:55:26 1.3
+++ src/external/historical/nawk/dist/tran.c 2011/01/20 21:26:20 1.4
@@ -1,486 +1,487 @@ @@ -1,486 +1,487 @@
1/**************************************************************** 1/****************************************************************
2Copyright (C) Lucent Technologies 1997 2Copyright (C) Lucent Technologies 1997
3All Rights Reserved 3All Rights Reserved
4 4
5Permission to use, copy, modify, and distribute this software and 5Permission to use, copy, modify, and distribute this software and
6its documentation for any purpose and without fee is hereby 6its documentation for any purpose and without fee is hereby
7granted, provided that the above copyright notice appear in all 7granted, provided that the above copyright notice appear in all
8copies and that both that the copyright notice and this 8copies and that both that the copyright notice and this
9permission notice and warranty disclaimer appear in supporting 9permission notice and warranty disclaimer appear in supporting
10documentation, and that the name Lucent Technologies or any of 10documentation, and that the name Lucent Technologies or any of
11its entities not be used in advertising or publicity pertaining 11its entities not be used in advertising or publicity pertaining
12to distribution of the software without specific, written prior 12to distribution of the software without specific, written prior
13permission. 13permission.
14 14
15LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 16INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 17IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 20IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 21ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22THIS SOFTWARE. 22THIS SOFTWARE.
23****************************************************************/ 23****************************************************************/
24 24
25#if HAVE_NBTOOL_CONFIG_H 25#if HAVE_NBTOOL_CONFIG_H
26#include "nbtool_config.h" 26#include "nbtool_config.h"
27#endif 27#endif
28 28
29#define DEBUG 29#define DEBUG
30#include <stdio.h> 30#include <stdio.h>
31#include <math.h> 31#include <math.h>
32#include <ctype.h> 32#include <ctype.h>
33#include <string.h> 33#include <string.h>
34#include <stdlib.h> 34#include <stdlib.h>
35#include "awk.h" 35#include "awk.h"
36#include "awkgram.h" 36#include "awkgram.h"
37 37
38#define FULLTAB 2 /* rehash when table gets this x full */ 38#define FULLTAB 2 /* rehash when table gets this x full */
39#define GROWTAB 4 /* grow table by this factor */ 39#define GROWTAB 4 /* grow table by this factor */
40 40
41Array *symtab; /* main symbol table */ 41Array *symtab; /* main symbol table */
42 42
43char **FS; /* initial field sep */ 43char **FS; /* initial field sep */
44char **RS; /* initial record sep */ 44char **RS; /* initial record sep */
45char **OFS; /* output field sep */ 45char **OFS; /* output field sep */
46char **ORS; /* output record sep */ 46char **ORS; /* output record sep */
47char **OFMT; /* output format for numbers */ 47char **OFMT; /* output format for numbers */
48char **CONVFMT; /* format for conversions in getsval */ 48char **CONVFMT; /* format for conversions in getsval */
49Awkfloat *NF; /* number of fields in current record */ 49Awkfloat *NF; /* number of fields in current record */
50Awkfloat *NR; /* number of current record */ 50Awkfloat *NR; /* number of current record */
51Awkfloat *FNR; /* number of current record in current file */ 51Awkfloat *FNR; /* number of current record in current file */
52char **FILENAME; /* current filename argument */ 52char **FILENAME; /* current filename argument */
53Awkfloat *ARGC; /* number of arguments from command line */ 53Awkfloat *ARGC; /* number of arguments from command line */
54char **SUBSEP; /* subscript separator for a[i,j,k]; default \034 */ 54char **SUBSEP; /* subscript separator for a[i,j,k]; default \034 */
55Awkfloat *RSTART; /* start of re matched with ~; origin 1 (!) */ 55Awkfloat *RSTART; /* start of re matched with ~; origin 1 (!) */
56Awkfloat *RLENGTH; /* length of same */ 56Awkfloat *RLENGTH; /* length of same */
57 57
58Cell *fsloc; /* FS */ 58Cell *fsloc; /* FS */
59Cell *nrloc; /* NR */ 59Cell *nrloc; /* NR */
60Cell *nfloc; /* NF */ 60Cell *nfloc; /* NF */
61Cell *fnrloc; /* FNR */ 61Cell *fnrloc; /* FNR */
62Array *ARGVtab; /* symbol table containing ARGV[...] */ 62Array *ARGVtab; /* symbol table containing ARGV[...] */
63Array *ENVtab; /* symbol table containing ENVIRON[...] */ 63Array *ENVtab; /* symbol table containing ENVIRON[...] */
64Cell *rstartloc; /* RSTART */ 64Cell *rstartloc; /* RSTART */
65Cell *rlengthloc; /* RLENGTH */ 65Cell *rlengthloc; /* RLENGTH */
66Cell *symtabloc; /* SYMTAB */ 66Cell *symtabloc; /* SYMTAB */
67 67
68Cell *nullloc; /* a guaranteed empty cell */ 68Cell *nullloc; /* a guaranteed empty cell */
69Node *nullnode; /* zero&null, converted into a node for comparisons */ 69Node *nullnode; /* zero&null, converted into a node for comparisons */
70Cell *literal0; 70Cell *literal0;
71 71
72extern Cell **fldtab; 72extern Cell **fldtab;
73 73
74void syminit(void) /* initialize symbol table with builtin vars */ 74void syminit(void) /* initialize symbol table with builtin vars */
75{ 75{
76 literal0 = setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab); 76 literal0 = setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab);
77 /* this is used for if(x)... tests: */ 77 /* this is used for if(x)... tests: */
78 nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab); 78 nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab);
79 nullnode = celltonode(nullloc, CCON); 79 nullnode = celltonode(nullloc, CCON);
80 80
81 fsloc = setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab); 81 fsloc = setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab);
82 FS = &fsloc->sval; 82 FS = &fsloc->sval;
83 RS = &setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab)->sval; 83 RS = &setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
84 OFS = &setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab)->sval; 84 OFS = &setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab)->sval;
85 ORS = &setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab)->sval; 85 ORS = &setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
86 OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval; 86 OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
87 CONVFMT = &setsymtab("CONVFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval; 87 CONVFMT = &setsymtab("CONVFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
88 FILENAME = &setsymtab("FILENAME", "", 0.0, STR|DONTFREE, symtab)->sval; 88 FILENAME = &setsymtab("FILENAME", "", 0.0, STR|DONTFREE, symtab)->sval;
89 nfloc = setsymtab("NF", "", 0.0, NUM, symtab); 89 nfloc = setsymtab("NF", "", 0.0, NUM, symtab);
90 NF = &nfloc->fval; 90 NF = &nfloc->fval;
91 nrloc = setsymtab("NR", "", 0.0, NUM, symtab); 91 nrloc = setsymtab("NR", "", 0.0, NUM, symtab);
92 NR = &nrloc->fval; 92 NR = &nrloc->fval;
93 fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab); 93 fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab);
94 FNR = &fnrloc->fval; 94 FNR = &fnrloc->fval;
95 SUBSEP = &setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab)->sval; 95 SUBSEP = &setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab)->sval;
96 rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab); 96 rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab);
97 RSTART = &rstartloc->fval; 97 RSTART = &rstartloc->fval;
98 rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab); 98 rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab);
99 RLENGTH = &rlengthloc->fval; 99 RLENGTH = &rlengthloc->fval;
100 symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab); 100 symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab);
101 symtabloc->sval = (char *) symtab; 101 symtabloc->sval = (char *) symtab;
102} 102}
103 103
104void arginit(int ac, char **av) /* set up ARGV and ARGC */ 104void arginit(int ac, char **av) /* set up ARGV and ARGC */
105{ 105{
106 Cell *cp; 106 Cell *cp;
107 int i; 107 int i;
108 char temp[50]; 108 char temp[50];
109 109
110 ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval; 110 ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval;
111 cp = setsymtab("ARGV", "", 0.0, ARR, symtab); 111 cp = setsymtab("ARGV", "", 0.0, ARR, symtab);
112 ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */ 112 ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */
113 cp->sval = (char *) ARGVtab; 113 cp->sval = (char *) ARGVtab;
114 for (i = 0; i < ac; i++) { 114 for (i = 0; i < ac; i++) {
115 snprintf(temp, sizeof(temp), "%d", i); 115 snprintf(temp, sizeof(temp), "%d", i);
116 if (is_number(*av)) 116 if (is_number(*av))
117 setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab); 117 setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab);
118 else 118 else
119 setsymtab(temp, *av, 0.0, STR, ARGVtab); 119 setsymtab(temp, *av, 0.0, STR, ARGVtab);
120 av++; 120 av++;
121 } 121 }
122} 122}
123 123
124void envinit(char **envp) /* set up ENVIRON variable */ 124void envinit(char **envp) /* set up ENVIRON variable */
125{ 125{
126 Cell *cp; 126 Cell *cp;
127 char *p; 127 char *p;
128 128
129 cp = setsymtab("ENVIRON", "", 0.0, ARR, symtab); 129 cp = setsymtab("ENVIRON", "", 0.0, ARR, symtab);
130 ENVtab = makesymtab(NSYMTAB); 130 ENVtab = makesymtab(NSYMTAB);
131 cp->sval = (char *) ENVtab; 131 cp->sval = (char *) ENVtab;
132 for ( ; *envp; envp++) { 132 for ( ; *envp; envp++) {
133 if ((p = strchr(*envp, '=')) == NULL) 133 if ((p = strchr(*envp, '=')) == NULL)
134 continue; 134 continue;
135 if( p == *envp ) /* no left hand side name in env string */ 135 if( p == *envp ) /* no left hand side name in env string */
136 continue; 136 continue;
137 *p++ = 0; /* split into two strings at = */ 137 *p++ = 0; /* split into two strings at = */
138 if (is_number(p)) 138 if (is_number(p))
139 setsymtab(*envp, p, atof(p), STR|NUM, ENVtab); 139 setsymtab(*envp, p, atof(p), STR|NUM, ENVtab);
140 else 140 else
141 setsymtab(*envp, p, 0.0, STR, ENVtab); 141 setsymtab(*envp, p, 0.0, STR, ENVtab);
142 p[-1] = '='; /* restore in case env is passed down to a shell */ 142 p[-1] = '='; /* restore in case env is passed down to a shell */
143 } 143 }
144} 144}
145 145
146Array *makesymtab(int n) /* make a new symbol table */ 146Array *makesymtab(int n) /* make a new symbol table */
147{ 147{
148 Array *ap; 148 Array *ap;
149 Cell **tp; 149 Cell **tp;
150 150
151 ap = malloc(sizeof(*ap)); 151 ap = malloc(sizeof(*ap));
152 tp = calloc(n, sizeof(*tp)); 152 tp = calloc(n, sizeof(*tp));
153 if (ap == NULL || tp == NULL) 153 if (ap == NULL || tp == NULL)
154 FATAL("out of space in makesymtab"); 154 FATAL("out of space in makesymtab");
155 ap->nelem = 0; 155 ap->nelem = 0;
156 ap->size = n; 156 ap->size = n;
157 ap->tab = tp; 157 ap->tab = tp;
158 return(ap); 158 return(ap);
159} 159}
160 160
161void freesymtab(Cell *ap) /* free a symbol table */ 161void freesymtab(Cell *ap) /* free a symbol table */
162{ 162{
163 Cell *cp, *temp; 163 Cell *cp, *temp;
164 Array *tp; 164 Array *tp;
165 int i; 165 int i;
166 166
167 if (!isarr(ap)) 167 if (!isarr(ap))
168 return; 168 return;
169 tp = (Array *) ap->sval; 169 tp = (Array *) ap->sval;
170 if (tp == NULL) 170 if (tp == NULL)
171 return; 171 return;
172 for (i = 0; i < tp->size; i++) { 172 for (i = 0; i < tp->size; i++) {
173 for (cp = tp->tab[i]; cp != NULL; cp = temp) { 173 for (cp = tp->tab[i]; cp != NULL; cp = temp) {
174 xfree(cp->nval); 174 xfree(cp->nval);
175 if (freeable(cp)) 175 if (freeable(cp))
176 xfree(cp->sval); 176 xfree(cp->sval);
177 temp = cp->cnext; /* avoids freeing then using */ 177 temp = cp->cnext; /* avoids freeing then using */
178 free(cp);  178 free(cp);
179 tp->nelem--; 179 tp->nelem--;
180 } 180 }
181 tp->tab[i] = 0; 181 tp->tab[i] = 0;
182 } 182 }
183 if (tp->nelem != 0) 183 if (tp->nelem != 0)
184 WARNING("can't happen: inconsistent element count freeing %s", ap->nval); 184 WARNING("can't happen: inconsistent element count freeing %s", ap->nval);
185 free(tp->tab); 185 free(tp->tab);
186 free(tp); 186 free(tp);
187} 187}
188 188
189void freeelem(Cell *ap, const char *s) /* free elem s from ap (i.e., ap["s"] */ 189void freeelem(Cell *ap, const char *s) /* free elem s from ap (i.e., ap["s"] */
190{ 190{
191 Array *tp; 191 Array *tp;
192 Cell *p, *prev = NULL; 192 Cell *p, *prev = NULL;
193 int h; 193 int h;
194  194
195 tp = (Array *) ap->sval; 195 tp = (Array *) ap->sval;
196 h = hash(s, tp->size); 196 h = hash(s, tp->size);
197 for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext) 197 for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext)
198 if (strcmp(s, p->nval) == 0) { 198 if (strcmp(s, p->nval) == 0) {
199 if (prev == NULL) /* 1st one */ 199 if (prev == NULL) /* 1st one */
200 tp->tab[h] = p->cnext; 200 tp->tab[h] = p->cnext;
201 else /* middle somewhere */ 201 else /* middle somewhere */
202 prev->cnext = p->cnext; 202 prev->cnext = p->cnext;
203 if (freeable(p)) 203 if (freeable(p))
204 xfree(p->sval); 204 xfree(p->sval);
205 free(p->nval); 205 free(p->nval);
206 free(p); 206 free(p);
207 tp->nelem--; 207 tp->nelem--;
208 return; 208 return;
209 } 209 }
210} 210}
211 211
212Cell *setsymtab(const char *n, const char *s, Awkfloat f, unsigned t, Array *tp) 212Cell *setsymtab(const char *n, const char *s, Awkfloat f, unsigned t, Array *tp)
213{ 213{
214 int h; 214 int h;
215 Cell *p; 215 Cell *p;
216 216
217 if (n == NULL) 217 if (n == NULL)
218 n = ""; 218 n = "";
219 219
220 if ((p = lookup(n, tp)) != NULL) { 220 if ((p = lookup(n, tp)) != NULL) {
221 dprintf( ("setsymtab found %p: n=%s s=\"%s\" f=%g t=%o\n", 221 dprintf( ("setsymtab found %p: n=%s s=\"%s\" f=%g t=%o\n",
222 p, NN(p->nval), NN(p->sval), p->fval, p->tval) ); 222 p, NN(p->nval), NN(p->sval), p->fval, p->tval) );
223 return(p); 223 return(p);
224 } 224 }
225 p = malloc(sizeof(*p)); 225 p = malloc(sizeof(*p));
226 if (p == NULL) 226 if (p == NULL)
227 FATAL("out of space for symbol table at %s", n); 227 FATAL("out of space for symbol table at %s", n);
228 p->nval = tostring(n); 228 p->nval = tostring(n);
229 p->sval = s ? tostring(s) : tostring(""); 229 p->sval = s ? tostring(s) : tostring("");
230 p->fval = f; 230 p->fval = f;
231 p->tval = t; 231 p->tval = t;
232 p->csub = CUNK; 232 p->csub = CUNK;
233 p->ctype = OCELL; 233 p->ctype = OCELL;
234 tp->nelem++; 234 tp->nelem++;
235 if (tp->nelem > FULLTAB * tp->size) 235 if (tp->nelem > FULLTAB * tp->size)
236 rehash(tp); 236 rehash(tp);
237 h = hash(n, tp->size); 237 h = hash(n, tp->size);
238 p->cnext = tp->tab[h]; 238 p->cnext = tp->tab[h];
239 tp->tab[h] = p; 239 tp->tab[h] = p;
240 dprintf( ("setsymtab set %p: n=%s s=\"%s\" f=%g t=%o\n", 240 dprintf( ("setsymtab set %p: n=%s s=\"%s\" f=%g t=%o\n",
241 p, p->nval, p->sval, p->fval, p->tval) ); 241 p, p->nval, p->sval, p->fval, p->tval) );
242 return(p); 242 return(p);
243} 243}
244 244
245int hash(const char *s, int n) /* form hash value for string s */ 245int hash(const char *s, int n) /* form hash value for string s */
246{ 246{
247 unsigned hashval; 247 unsigned hashval;
248 248
249 for (hashval = 0; *s != '\0'; s++) 249 for (hashval = 0; *s != '\0'; s++)
250 hashval = (*s + 31 * hashval); 250 hashval = (*s + 31 * hashval);
251 return hashval % n; 251 return hashval % n;
252} 252}
253 253
254void rehash(Array *tp) /* rehash items in small table into big one */ 254void rehash(Array *tp) /* rehash items in small table into big one */
255{ 255{
256 int i, nh, nsz; 256 int i, nh, nsz;
257 Cell *cp, *op, **np; 257 Cell *cp, *op, **np;
258 258
259 nsz = GROWTAB * tp->size; 259 nsz = GROWTAB * tp->size;
260 np = calloc(nsz, sizeof(*np)); 260 np = calloc(nsz, sizeof(*np));
261 if (np == NULL) /* can't do it, but can keep running. */ 261 if (np == NULL) /* can't do it, but can keep running. */
262 return; /* someone else will run out later. */ 262 return; /* someone else will run out later. */
263 for (i = 0; i < tp->size; i++) { 263 for (i = 0; i < tp->size; i++) {
264 for (cp = tp->tab[i]; cp; cp = op) { 264 for (cp = tp->tab[i]; cp; cp = op) {
265 op = cp->cnext; 265 op = cp->cnext;
266 nh = hash(cp->nval, nsz); 266 nh = hash(cp->nval, nsz);
267 cp->cnext = np[nh]; 267 cp->cnext = np[nh];
268 np[nh] = cp; 268 np[nh] = cp;
269 } 269 }
270 } 270 }
271 free(tp->tab); 271 free(tp->tab);
272 tp->tab = np; 272 tp->tab = np;
273 tp->size = nsz; 273 tp->size = nsz;
274} 274}
275 275
276Cell *lookup(const char *s, Array *tp) /* look for s in tp */ 276Cell *lookup(const char *s, Array *tp) /* look for s in tp */
277{ 277{
278 Cell *p; 278 Cell *p;
279 int h; 279 int h;
280 280
281 h = hash(s, tp->size); 281 h = hash(s, tp->size);
282 for (p = tp->tab[h]; p != NULL; p = p->cnext) 282 for (p = tp->tab[h]; p != NULL; p = p->cnext)
283 if (strcmp(s, p->nval) == 0) 283 if (strcmp(s, p->nval) == 0)
284 return(p); /* found it */ 284 return(p); /* found it */
285 return(NULL); /* not found */ 285 return(NULL); /* not found */
286} 286}
287 287
288Awkfloat setfval(Cell *vp, Awkfloat f) /* set float val of a Cell */ 288Awkfloat setfval(Cell *vp, Awkfloat f) /* set float val of a Cell */
289{ 289{
290 int fldno; 290 int fldno;
291 291
292 f += 0.0; /* normalise negative zero to positive zero */ 292 f += 0.0; /* normalise negative zero to positive zero */
293 if ((vp->tval & (NUM | STR)) == 0)  293 if ((vp->tval & (NUM | STR)) == 0)
294 funnyvar(vp, "assign to"); 294 funnyvar(vp, "assign to");
295 if (isfld(vp)) { 295 if (isfld(vp)) {
296 donerec = 0; /* mark $0 invalid */ 296 donerec = 0; /* mark $0 invalid */
297 fldno = atoi(vp->nval); 297 fldno = atoi(vp->nval);
298 if (fldno > *NF) 298 if (fldno > *NF)
299 newfld(fldno); 299 newfld(fldno);
300 dprintf( ("setting field %d to %g\n", fldno, f) ); 300 dprintf( ("setting field %d to %g\n", fldno, f) );
301 } else if (&vp->fval == NF) { 301 } else if (&vp->fval == NF) {
302 donerec = 0; /* mark $0 invalid */ 302 donerec = 0; /* mark $0 invalid */
303 setlastfld(f); 303 setlastfld(f);
304 dprintf( ("setting NF to %g\n", f) ); 304 dprintf( ("setting NF to %g\n", f) );
305 } else if (isrec(vp)) { 305 } else if (isrec(vp)) {
306 donefld = 0; /* mark $1... invalid */ 306 donefld = 0; /* mark $1... invalid */
307 donerec = 1; 307 donerec = 1;
308 } 308 }
309 if (freeable(vp)) 309 if (freeable(vp))
310 xfree(vp->sval); /* free any previous string */ 310 xfree(vp->sval); /* free any previous string */
311 vp->tval &= ~STR; /* mark string invalid */ 311 vp->tval &= ~STR; /* mark string invalid */
312 vp->tval |= NUM; /* mark number ok */ 312 vp->tval |= NUM; /* mark number ok */
313 dprintf( ("setfval %p: %s = %g, t=%o\n", vp, NN(vp->nval), f, vp->tval) ); 313 dprintf( ("setfval %p: %s = %g, t=%o\n", vp, NN(vp->nval), f, vp->tval) );
314 return vp->fval = f; 314 return vp->fval = f;
315} 315}
316 316
317void funnyvar(Cell *vp, const char *rw) 317void funnyvar(Cell *vp, const char *rw)
318{ 318{
319 if (isarr(vp)) 319 if (isarr(vp))
320 FATAL("can't %s %s; it's an array name.", rw, vp->nval); 320 FATAL("can't %s %s; it's an array name.", rw, vp->nval);
321 if (vp->tval & FCN) 321 if (vp->tval & FCN)
322 FATAL("can't %s %s; it's a function.", rw, vp->nval); 322 FATAL("can't %s %s; it's a function.", rw, vp->nval);
323 WARNING("funny variable %p: n=%s s=\"%s\" f=%g t=%o", 323 WARNING("funny variable %p: n=%s s=\"%s\" f=%g t=%o",
324 vp, vp->nval, vp->sval, vp->fval, vp->tval); 324 vp, vp->nval, vp->sval, vp->fval, vp->tval);
325} 325}
326 326
327char *setsval(Cell *vp, const char *s) /* set string val of a Cell */ 327char *setsval(Cell *vp, const char *s) /* set string val of a Cell */
328{ 328{
329 char *t; 329 char *t;
330 int fldno; 330 int fldno;
331 Awkfloat f; 331 Awkfloat f;
332 332
333 dprintf( ("starting setsval %p: %s = \"%s\", t=%o, r,f=%d,%d\n",  333 dprintf( ("starting setsval %p: %s = \"%s\", t=%o, r,f=%d,%d\n",
334 vp, NN(vp->nval), s, vp->tval, donerec, donefld) ); 334 vp, NN(vp->nval), s, vp->tval, donerec, donefld) );
335 if ((vp->tval & (NUM | STR)) == 0) 335 if ((vp->tval & (NUM | STR)) == 0)
336 funnyvar(vp, "assign to"); 336 funnyvar(vp, "assign to");
337 if (isfld(vp)) { 337 if (isfld(vp)) {
338 donerec = 0; /* mark $0 invalid */ 338 donerec = 0; /* mark $0 invalid */
339 fldno = atoi(vp->nval); 339 fldno = atoi(vp->nval);
340 if (fldno > *NF) 340 if (fldno > *NF)
341 newfld(fldno); 341 newfld(fldno);
342 dprintf( ("setting field %d to %s (%p)\n", fldno, s, s) ); 342 dprintf( ("setting field %d to %s (%p)\n", fldno, s, s) );
343 } else if (isrec(vp)) { 343 } else if (isrec(vp)) {
344 donefld = 0; /* mark $1... invalid */ 344 donefld = 0; /* mark $1... invalid */
345 donerec = 1; 345 donerec = 1;
346 } 346 }
347 t = tostring(s); /* in case it's self-assign */ 347 t = tostring(s); /* in case it's self-assign */
348 if (freeable(vp)) 348 if (freeable(vp))
349 xfree(vp->sval); 349 xfree(vp->sval);
350 vp->tval &= ~NUM; 350 vp->tval &= ~NUM;
351 vp->tval |= STR; 351 vp->tval |= STR;
352 vp->tval &= ~DONTFREE; 352 vp->tval &= ~DONTFREE;
353 dprintf( ("setsval %p: %s = \"%s (%p) \", t=%o r,f=%d,%d\n",  353 dprintf( ("setsval %p: %s = \"%s (%p) \", t=%o r,f=%d,%d\n",
354 vp, NN(vp->nval), t,t, vp->tval, donerec, donefld) ); 354 vp, NN(vp->nval), t,t, vp->tval, donerec, donefld) );
355 355
 356 vp->sval = t;
356 if (&vp->fval == NF) { 357 if (&vp->fval == NF) {
357 donerec = 0; /* mark $0 invalid */ 358 donerec = 0; /* mark $0 invalid */
358 f = getfval(vp); 359 f = getfval(vp);
359 setlastfld(f); 360 setlastfld(f);
360 dprintf( ("setting NF to %g\n", f) ); 361 dprintf( ("setting NF to %g\n", f) );
361 } 362 }
362 363
363 return(vp->sval = t); 364 return(vp->sval);
364} 365}
365 366
366Awkfloat getfval(Cell *vp) /* get float val of a Cell */ 367Awkfloat getfval(Cell *vp) /* get float val of a Cell */
367{ 368{
368 if ((vp->tval & (NUM | STR)) == 0) 369 if ((vp->tval & (NUM | STR)) == 0)
369 funnyvar(vp, "read value of"); 370 funnyvar(vp, "read value of");
370 if (isfld(vp) && donefld == 0) 371 if (isfld(vp) && donefld == 0)
371 fldbld(); 372 fldbld();
372 else if (isrec(vp) && donerec == 0) 373 else if (isrec(vp) && donerec == 0)
373 recbld(); 374 recbld();
374 if (!isnum(vp)) { /* not a number */ 375 if (!isnum(vp)) { /* not a number */
375 vp->fval = atof(vp->sval); /* best guess */ 376 vp->fval = atof(vp->sval); /* best guess */
376 if (is_number(vp->sval) && !(vp->tval&CON)) 377 if (is_number(vp->sval) && !(vp->tval&CON))
377 vp->tval |= NUM; /* make NUM only sparingly */ 378 vp->tval |= NUM; /* make NUM only sparingly */
378 } 379 }
379 dprintf( ("getfval %p: %s = %g, t=%o\n", vp, NN(vp->nval), vp->fval, vp->tval) ); 380 dprintf( ("getfval %p: %s = %g, t=%o\n", vp, NN(vp->nval), vp->fval, vp->tval) );
380 return(vp->fval); 381 return(vp->fval);
381} 382}
382 383
383static char *get_str_val(Cell *vp, char **fmt) /* get string val of a Cell */ 384static char *get_str_val(Cell *vp, char **fmt) /* get string val of a Cell */
384{ 385{
385 char s[100]; 386 char s[100];
386 double dtemp; 387 double dtemp;
387 388
388 if ((vp->tval & (NUM | STR)) == 0) 389 if ((vp->tval & (NUM | STR)) == 0)
389 funnyvar(vp, "read value of"); 390 funnyvar(vp, "read value of");
390 if (isfld(vp) && donefld == 0) 391 if (isfld(vp) && donefld == 0)
391 fldbld(); 392 fldbld();
392 else if (isrec(vp) && donerec == 0) 393 else if (isrec(vp) && donerec == 0)
393 recbld(); 394 recbld();
394 if (isstr(vp) == 0) { 395 if (isstr(vp) == 0) {
395 if (freeable(vp)) 396 if (freeable(vp))
396 xfree(vp->sval); 397 xfree(vp->sval);
397 if (modf(vp->fval, &dtemp) == 0) /* it's integral */ 398 if (modf(vp->fval, &dtemp) == 0) /* it's integral */
398 snprintf(s, sizeof(s), "%.30g", vp->fval); 399 snprintf(s, sizeof(s), "%.30g", vp->fval);
399 else 400 else
400 snprintf(s, sizeof(s), *fmt, vp->fval); 401 snprintf(s, sizeof(s), *fmt, vp->fval);
401 vp->sval = tostring(s); 402 vp->sval = tostring(s);
402 vp->tval &= ~DONTFREE; 403 vp->tval &= ~DONTFREE;
403 vp->tval |= STR; 404 vp->tval |= STR;
404 } 405 }
405 dprintf( ("getsval %p: %s = \"%s (%p)\", t=%o\n", vp, NN(vp->nval), vp->sval, vp->sval, vp->tval) ); 406 dprintf( ("getsval %p: %s = \"%s (%p)\", t=%o\n", vp, NN(vp->nval), vp->sval, vp->sval, vp->tval) );
406 return(vp->sval); 407 return(vp->sval);
407} 408}
408 409
409char *getsval(Cell *vp) /* get string val of a Cell */ 410char *getsval(Cell *vp) /* get string val of a Cell */
410{ 411{
411 return get_str_val(vp, CONVFMT); 412 return get_str_val(vp, CONVFMT);
412} 413}
413 414
414char *getpssval(Cell *vp) /* get string val of a Cell for print */ 415char *getpssval(Cell *vp) /* get string val of a Cell for print */
415{ 416{
416 return get_str_val(vp, OFMT); 417 return get_str_val(vp, OFMT);
417} 418}
418 419
419 420
420char *tostring(const char *s) /* make a copy of string s */ 421char *tostring(const char *s) /* make a copy of string s */
421{ 422{
422 char *p; 423 char *p;
423 424
424 p = strdup(s); 425 p = strdup(s);
425 if (p == NULL) 426 if (p == NULL)
426 FATAL("out of space in tostring on %s", s); 427 FATAL("out of space in tostring on %s", s);
427 return(p); 428 return(p);
428} 429}
429 430
430char *tostringN(const char *s, size_t n) /* make a copy of string s */ 431char *tostringN(const char *s, size_t n) /* make a copy of string s */
431{ 432{
432 char *p; 433 char *p;
433 434
434 p = malloc(n); 435 p = malloc(n);
435 if (p == NULL) 436 if (p == NULL)
436 FATAL("out of space in tostring on %s", s); 437 FATAL("out of space in tostring on %s", s);
437 strcpy(p, s); 438 strcpy(p, s);
438 return(p); 439 return(p);
439} 440}
440 441
441char *qstring(const char *is, int delim) /* collect string up to next delim */ 442char *qstring(const char *is, int delim) /* collect string up to next delim */
442{ 443{
443 const char *os = is; 444 const char *os = is;
444 int c, n; 445 int c, n;
445 const uschar *s = (const uschar *) is; 446 const uschar *s = (const uschar *) is;
446 uschar *buf, *bp; 447 uschar *buf, *bp;
447 448
448 if ((buf = malloc(strlen(is)+3)) == NULL) 449 if ((buf = malloc(strlen(is)+3)) == NULL)
449 FATAL( "out of space in qstring(%s)", s); 450 FATAL( "out of space in qstring(%s)", s);
450 for (bp = buf; (c = *s) != delim; s++) { 451 for (bp = buf; (c = *s) != delim; s++) {
451 if (c == '\n') 452 if (c == '\n')
452 SYNTAX( "newline in string %.20s...", os ); 453 SYNTAX( "newline in string %.20s...", os );
453 else if (c != '\\') 454 else if (c != '\\')
454 *bp++ = c; 455 *bp++ = c;
455 else { /* \something */ 456 else { /* \something */
456 c = *++s; 457 c = *++s;
457 if (c == 0) { /* \ at end */ 458 if (c == 0) { /* \ at end */
458 *bp++ = '\\'; 459 *bp++ = '\\';
459 break; /* for loop */ 460 break; /* for loop */
460 }  461 }
461 switch (c) { 462 switch (c) {
462 case '\\': *bp++ = '\\'; break; 463 case '\\': *bp++ = '\\'; break;
463 case 'n': *bp++ = '\n'; break; 464 case 'n': *bp++ = '\n'; break;
464 case 't': *bp++ = '\t'; break; 465 case 't': *bp++ = '\t'; break;
465 case 'b': *bp++ = '\b'; break; 466 case 'b': *bp++ = '\b'; break;
466 case 'f': *bp++ = '\f'; break; 467 case 'f': *bp++ = '\f'; break;
467 case 'r': *bp++ = '\r'; break; 468 case 'r': *bp++ = '\r'; break;
468 default: 469 default:
469 if (!isdigit(c)) { 470 if (!isdigit(c)) {
470 *bp++ = c; 471 *bp++ = c;
471 break; 472 break;
472 } 473 }
473 n = c - '0'; 474 n = c - '0';
474 if (isdigit(s[1])) { 475 if (isdigit(s[1])) {
475 n = 8 * n + *++s - '0'; 476 n = 8 * n + *++s - '0';
476 if (isdigit(s[1])) 477 if (isdigit(s[1]))
477 n = 8 * n + *++s - '0'; 478 n = 8 * n + *++s - '0';
478 } 479 }
479 *bp++ = n; 480 *bp++ = n;
480 break; 481 break;
481 } 482 }
482 } 483 }
483 } 484 }
484 *bp++ = 0; 485 *bp++ = 0;
485 return (char *) buf; 486 return (char *) buf;
486} 487}