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