GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/awk/tran.c Lines: 168 256 65.6 %
Date: 2016-12-06 Branches: 72 183 39.3 %

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