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