~vcs-imports/gawk/master

« back to all changes in this revision

Viewing changes to field.c

  • Committer: Arnold D. Robbins
  • Date: 2010-07-16 08:58:26 UTC
  • Revision ID: git-v1:765c7494b3dac62207e6cd57fb839997e237f292
Moving to 2.13.2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 */
4
4
 
5
5
/* 
6
 
 * Copyright (C) 1986, 1988, 1989 the Free Software Foundation, Inc.
 
6
 * Copyright (C) 1986, 1988, 1989, 1991 the Free Software Foundation, Inc.
7
7
 * 
8
8
 * This file is part of GAWK, the GNU implementation of the
9
9
 * AWK Progamming Language.
25
25
 
26
26
#include "awk.h"
27
27
 
28
 
extern void assoc_clear();
29
 
extern int a_get_three();
30
 
extern int get_rs();
31
 
 
32
 
static char *get_fs();
33
 
static int re_split();
34
 
static int parse_fields();
35
 
static void set_element();
36
 
 
37
 
char *line_buf = NULL;  /* holds current input line */
38
 
 
 
28
 
 
29
static int (*parse_field) P((int, char **, int, char *,
 
30
                             Regexp *, void (*)(), NODE *));
 
31
static void rebuild_record P((void));
 
32
static int re_parse_field P((int, char **, int, char *,
 
33
                             Regexp *, void (*)(), NODE *));
 
34
static int def_parse_field P((int, char **, int, char *,
 
35
                              Regexp *, void (*)(), NODE *));
 
36
static int sc_parse_field P((int, char **, int, char *,
 
37
                             Regexp *, void (*)(), NODE *));
 
38
static int fw_parse_field P((int, char **, int, char *,
 
39
                             Regexp *, void (*)(), NODE *));
 
40
static void set_element P((int, char *, int, NODE *));
 
41
 
 
42
static Regexp *FS_regexp = NULL;
39
43
static char *parse_extent;      /* marks where to restart parse of record */
40
44
static int parse_high_water=0;  /* field number that we have parsed so far */
41
 
static char f_empty[] = "";
42
 
static char *save_fs = " ";     /* save current value of FS when line is read,
 
45
static int nf_high_water = 0;   /* size of fields_arr */
 
46
static char f_empty[] = "\0";
 
47
static int resave_fs;
 
48
static NODE *save_FS;
 
49
static char *save_fs;           /* save current value of FS when line is read,
43
50
                                 * to be used in deferred parsing
44
51
                                 */
45
52
 
46
 
 
47
53
NODE **fields_arr;              /* array of pointers to the field nodes */
48
 
NODE node0;                     /* node for $0 which never gets free'd */
49
 
int node0_valid = 1;            /* $(>0) has not been changed yet */
 
54
int field0_valid = 1;           /* $(>0) has not been changed yet */
 
55
NODE *field0;
 
56
static NODE **nodes;            /* permanent repository of field nodes */
 
57
static int *FIELDWIDTHS = NULL;
50
58
 
51
59
void
52
60
init_fields()
53
61
{
54
62
        emalloc(fields_arr, NODE **, sizeof(NODE *), "init_fields");
55
 
        node0.type = Node_val;
56
 
        node0.stref = 0;
57
 
        node0.stptr = "";
58
 
        node0.flags = (STR|PERM);       /* never free buf */
59
 
        fields_arr[0] = &node0;
60
 
}
61
 
 
62
 
/*
63
 
 * Danger!  Must only be called for fields we know have just been blanked, or
64
 
 * fields we know don't exist yet.  
65
 
 */
 
63
        emalloc(nodes, NODE **, sizeof(NODE *), "init_fields");
 
64
        emalloc(field0, NODE *, sizeof(NODE), "init_fields");
 
65
        field0->type = Node_val;
 
66
        field0->stref = 0;
 
67
        field0->stptr = "";
 
68
        field0->flags = (STRING|STR|PERM);      /* never free buf */
 
69
        fields_arr[0] = field0;
 
70
        save_FS = dupnode(FS_node->var_value);
 
71
        save_fs = save_FS->stptr;
 
72
}
 
73
 
 
74
static void
 
75
grow_fields_arr(num)
 
76
int num;
 
77
{
 
78
        register int t;
 
79
        register NODE *n;
 
80
 
 
81
        erealloc(fields_arr, NODE **, (num + 1) * sizeof(NODE *), "set_field");
 
82
        erealloc(nodes, NODE **, (num+1) * sizeof(NODE *), "set_field");
 
83
        for (t = nf_high_water+1; t <= num; t++) {
 
84
                getnode(n);
 
85
                n->type = Node_val;
 
86
                nodes[t] = n;
 
87
                fields_arr[t] = nodes[t];
 
88
        }
 
89
        nf_high_water = num;
 
90
}
66
91
 
67
92
/*ARGSUSED*/
68
93
static void
72
97
int len;
73
98
NODE *dummy;    /* not used -- just to make interface same as set_element */
74
99
{
75
 
        NODE *n;
76
 
        int t;
77
 
        static int nf_high_water = 0;
 
100
        register NODE *n;
 
101
        register int t;
78
102
 
79
 
        if (num > nf_high_water) {
80
 
                erealloc(fields_arr, NODE **, (num + 1) * sizeof(NODE *), "set_field");
81
 
                nf_high_water = num;
82
 
        }
83
 
        /* fill in fields that don't exist */
84
 
        for (t = parse_high_water + 1; t < num; t++)
85
 
                fields_arr[t] = Nnull_string;
86
 
        n = make_string(str, len);
87
 
        (void) force_number(n);
 
103
        if (num > nf_high_water)
 
104
                grow_fields_arr(num);
 
105
        n = nodes[num];
 
106
        n->stptr = str;
 
107
        n->stlen = len;
 
108
        n->flags = (PERM|STR|STRING|MAYBE_NUM);
88
109
        fields_arr[num] = n;
89
 
        parse_high_water = num;
90
110
}
91
111
 
92
112
/* Someone assigned a value to $(something).  Fix up $0 to be right */
104
124
        tlen = 0;
105
125
        ofs = force_string(OFS_node->var_value);
106
126
        ofslen = ofs->stlen;
107
 
        ptr = &fields_arr[parse_high_water];
 
127
        ptr = &fields_arr[NF];
108
128
        while (ptr > &fields_arr[0]) {
109
129
                tmp = force_string(*ptr);
110
130
                tlen += tmp->stlen;
111
131
                ptr--;
112
132
        }
113
 
        tlen += (parse_high_water - 1) * ofslen;
114
 
        emalloc(ops, char *, tlen + 1, "fix_fields");
 
133
        tlen += (NF - 1) * ofslen;
 
134
        emalloc(ops, char *, tlen + 2, "fix_fields");
115
135
        cops = ops;
116
136
        ops[0] = '\0';
117
 
        for (ptr = &fields_arr[1]; ptr <= &fields_arr[parse_high_water]; ptr++) {
 
137
        for (ptr = &fields_arr[1]; ptr <= &fields_arr[NF]; ptr++) {
118
138
                tmp = *ptr;
119
139
                if (tmp->stlen == 1)
120
140
                        *cops++ = tmp->stptr[0];
122
142
                        memcpy(cops, tmp->stptr, tmp->stlen);
123
143
                        cops += tmp->stlen;
124
144
                }
125
 
                if (ptr != &fields_arr[parse_high_water]) {
 
145
                if (ptr != &fields_arr[NF]) {
126
146
                        if (ofslen == 1)
127
147
                                *cops++ = ofs->stptr[0];
128
148
                        else if (ofslen != 0) {
131
151
                        }
132
152
                }
133
153
        }
134
 
        tmp = make_string(ops, tlen);
135
 
        free(ops);
136
 
        deref = fields_arr[0];
137
 
        do_deref();
 
154
        tmp = make_str_node(ops, tlen, ALREADY_MALLOCED);
 
155
        unref(fields_arr[0]);
138
156
        fields_arr[0] = tmp;
 
157
        field0_valid = 1;
139
158
}
140
159
 
141
160
/*
143
162
 * or to NF.  At that point, parse only as much as necessary.
144
163
 */
145
164
void
146
 
set_record(buf, cnt)
 
165
set_record(buf, cnt, freeold)
147
166
char *buf;
148
167
int cnt;
 
168
int freeold;
149
169
{
150
170
        register int i;
151
171
 
152
 
        assign_number(&NF_node->var_value, (AWKNUM)-1);
 
172
        NF = -1;
153
173
        for (i = 1; i <= parse_high_water; i++) {
154
 
                deref = fields_arr[i];
155
 
                do_deref();
 
174
                unref(fields_arr[i]);
156
175
        }
157
176
        parse_high_water = 0;
158
 
        node0_valid = 1;
159
 
        if (buf == line_buf) {
160
 
                deref = fields_arr[0];
161
 
                do_deref();
162
 
                save_fs = get_fs();
163
 
                node0.type = Node_val;
164
 
                node0.stptr = buf;
165
 
                node0.stlen = cnt;
166
 
                node0.stref = 1;
167
 
                node0.flags = (STR|PERM);       /* never free buf */
168
 
                fields_arr[0] = &node0;
169
 
        }
 
177
        if (freeold) {
 
178
                unref(fields_arr[0]);
 
179
                if (resave_fs) {
 
180
                        resave_fs = 0;
 
181
                        unref(save_FS);
 
182
                        save_FS = dupnode(FS_node->var_value);
 
183
                        save_fs = save_FS->stptr;
 
184
                }
 
185
                field0->stptr = buf;
 
186
                field0->stlen = cnt;
 
187
                field0->stref = 1;
 
188
                field0->flags = (STRING|STR|PERM|MAYBE_NUM);
 
189
                fields_arr[0] = field0;
 
190
        }
 
191
        fields_arr[0]->flags |= MAYBE_NUM;
 
192
        field0_valid = 1;
 
193
}
 
194
 
 
195
void
 
196
reset_record()
 
197
{
 
198
        (void) force_string(fields_arr[0]);
 
199
        set_record(fields_arr[0]->stptr, fields_arr[0]->stlen, 0);
 
200
}
 
201
 
 
202
void
 
203
set_NF()
 
204
{
 
205
        NF = (int) force_number(NF_node->var_value);
 
206
        field0_valid = 0;
 
207
}
 
208
 
 
209
/*
 
210
 * this is called both from get_field() and from do_split()
 
211
 * via (*parse_field)().  This variation is for when FS is a regular
 
212
 * expression -- either user-defined or because RS=="" and FS==" "
 
213
 */
 
214
static int
 
215
re_parse_field(up_to, buf, len, fs, rp, set, n)
 
216
int up_to;      /* parse only up to this field number */
 
217
char **buf;     /* on input: string to parse; on output: point to start next */
 
218
int len;
 
219
register char *fs;
 
220
Regexp *rp;
 
221
void (*set) (); /* routine to set the value of the parsed field */
 
222
NODE *n;
 
223
{
 
224
        register char *scan = *buf;
 
225
        register int nf = parse_high_water;
 
226
        register char *field;
 
227
        register char *end = scan + len;
 
228
        char *cp;
 
229
 
 
230
        if (up_to == HUGE)
 
231
                nf = 0;
 
232
        if (len == 0)
 
233
                return nf;
 
234
 
 
235
        cp = FS_node->var_value->stptr;
 
236
        if (*RS == 0 && *cp == ' ' && *(cp+1) == '\0') {
 
237
                while (scan < end
 
238
                       && (*scan == '\n' || *scan == ' ' || *scan == '\t'))
 
239
                        scan++;
 
240
        }
 
241
        field = scan;
 
242
        while (scan < end
 
243
               && research(rp, scan, (int)(end - scan), 1) != -1
 
244
               && nf < up_to) {
 
245
                if (REEND(rp, scan) == RESTART(rp, scan)) {     /* null match */
 
246
                        scan++;
 
247
                        if (scan == end) {
 
248
                                (*set)(++nf, field, scan - field, n);
 
249
                                up_to = nf;
 
250
                                break;
 
251
                        }
 
252
                        continue;
 
253
                }
 
254
                (*set)(++nf, field, RESTART(rp, scan), n);
 
255
                scan += REEND(rp, scan);
 
256
                field = scan;
 
257
        }
 
258
        if (nf != up_to && *RS != 0 && scan < end) {
 
259
                (*set)(++nf, scan, (int)(end - scan), n);
 
260
                scan = end;
 
261
        }
 
262
        *buf = scan;
 
263
        return (nf);
 
264
}
 
265
 
 
266
/*
 
267
 * this is called both from get_field() and from do_split()
 
268
 * via (*parse_field)().  This variation is for when FS is a single space
 
269
 * character.
 
270
 */
 
271
static int
 
272
def_parse_field(up_to, buf, len, fs, rp, set, n)
 
273
int up_to;      /* parse only up to this field number */
 
274
char **buf;     /* on input: string to parse; on output: point to start next */
 
275
int len;
 
276
register char *fs;
 
277
Regexp *rp;
 
278
void (*set) (); /* routine to set the value of the parsed field */
 
279
NODE *n;
 
280
{
 
281
        register char *scan = *buf;
 
282
        register int nf = parse_high_water;
 
283
        register char *field;
 
284
        register char *end = scan + len;
 
285
 
 
286
        if (up_to == HUGE)
 
287
                nf = 0;
 
288
        if (len == 0)
 
289
                return nf;
 
290
 
 
291
        *end = ' ';     /* sentinel character */
 
292
        for (; nf < up_to; scan++) {
 
293
                /*
 
294
                 * special case:  fs is single space, strip leading whitespace 
 
295
                 */
 
296
                while (scan < end && (*scan == ' ' || *scan == '\t'))
 
297
                        scan++;
 
298
                if (scan >= end)
 
299
                        break;
 
300
                field = scan;
 
301
                while (*scan != ' ' && *scan != '\t')
 
302
                        scan++;
 
303
                (*set)(++nf, field, (int)(scan - field), n);
 
304
                if (scan == end)
 
305
                        break;
 
306
        }
 
307
        *buf = scan;
 
308
        return nf;
 
309
}
 
310
 
 
311
/*
 
312
 * this is called both from get_field() and from do_split()
 
313
 * via (*pase_field)().  This variation is for when FS is a single character
 
314
 * other than space.
 
315
 */
 
316
static int
 
317
sc_parse_field(up_to, buf, len, fs, rp, set, n)
 
318
int up_to;      /* parse only up to this field number */
 
319
char **buf;     /* on input: string to parse; on output: point to start next */
 
320
int len;
 
321
register char *fs;
 
322
Regexp *rp;
 
323
void (*set) (); /* routine to set the value of the parsed field */
 
324
NODE *n;
 
325
{
 
326
        register char *scan = *buf;
 
327
        register char fschar = *fs;
 
328
        register int nf = parse_high_water;
 
329
        register char *field;
 
330
        register char *end = scan + len;
 
331
 
 
332
        if (up_to == HUGE)
 
333
                nf = 0;
 
334
        if (len == 0)
 
335
                return nf;
 
336
        *end = fschar;  /* sentinel character */
 
337
        for (; nf < up_to; scan++) {
 
338
                field = scan;
 
339
                while (*scan++ != fschar)
 
340
                        ;
 
341
                scan--;
 
342
                (*set)(++nf, field, (int)(scan - field), n);
 
343
                if (scan == end)
 
344
                        break;
 
345
        }
 
346
        *buf = scan;
 
347
        return nf;
 
348
}
 
349
 
 
350
/*
 
351
 * this is called both from get_field() and from do_split()
 
352
 * via (*pase_field)().  This variation is for when FS is a single character
 
353
 * other than space.
 
354
 */
 
355
static int
 
356
fw_parse_field(up_to, buf, len, fs, rp, set, n)
 
357
int up_to;      /* parse only up to this field number */
 
358
char **buf;     /* on input: string to parse; on output: point to start next */
 
359
int len;
 
360
register char *fs;
 
361
Regexp *rp;
 
362
void (*set) (); /* routine to set the value of the parsed field */
 
363
NODE *n;
 
364
{
 
365
        register char *scan = *buf;
 
366
        register int nf = parse_high_water;
 
367
        register char *end = scan + len;
 
368
 
 
369
        if (up_to == HUGE)
 
370
                nf = 0;
 
371
        if (len == 0)
 
372
                return nf;
 
373
        for (; nf < up_to && (len = FIELDWIDTHS[nf+1]) != -1; ) {
 
374
                if (len > end - scan)
 
375
                        len = end - scan;
 
376
                (*set)(++nf, scan, len, n);
 
377
                scan += len;
 
378
        }
 
379
        if (len == -1)
 
380
                *buf = end;
 
381
        else
 
382
                *buf = scan;
 
383
        return nf;
170
384
}
171
385
 
172
386
NODE **
173
387
get_field(num, assign)
174
 
int num;
175
 
int assign;     /* this field is on the LHS of an assign */
 
388
register int num;
 
389
Func_ptr *assign;       /* this field is on the LHS of an assign */
176
390
{
177
391
        int n;
178
392
 
180
394
         * if requesting whole line but some other field has been altered,
181
395
         * then the whole line must be rebuilt
182
396
         */
183
 
        if (num == 0 && (node0_valid == 0 || assign)) {
184
 
                /* first, parse remainder of input record */
185
 
                if (NF_node->var_value->numbr == -1) {
186
 
                        if (parse_high_water == 0)
187
 
                                parse_extent = node0.stptr;
188
 
                        n = parse_fields(HUGE-1, &parse_extent,
189
 
                                node0.stlen - (parse_extent - node0.stptr),
190
 
                                save_fs, set_field, (NODE *)NULL);
191
 
                        assign_number(&NF_node->var_value, (AWKNUM)n);
192
 
                }
193
 
                if (node0_valid == 0)
 
397
        if (num == 0) {
 
398
                if (!field0_valid) {
 
399
                        /* first, parse remainder of input record */
 
400
                        if (NF == -1) {
 
401
                                NF = (*parse_field)(HUGE-1, &parse_extent,
 
402
                                        fields_arr[0]->stlen -
 
403
                                        (parse_extent - fields_arr[0]->stptr),
 
404
                                        save_fs, FS_regexp, set_field,
 
405
                                        (NODE *)NULL);
 
406
                                parse_high_water = NF;
 
407
                        }
194
408
                        rebuild_record();
 
409
                }
 
410
                if (assign)
 
411
                        *assign = reset_record;
195
412
                return &fields_arr[0];
196
413
        }
197
 
        if (num > 0 && assign)
198
 
                node0_valid = 0;
 
414
 
 
415
        /* assert(num > 0); */
 
416
 
 
417
        if (assign)
 
418
                field0_valid = 0;
199
419
        if (num <= parse_high_water)    /* we have already parsed this field */
200
420
                return &fields_arr[num];
201
 
        if (parse_high_water == 0 && num > 0)   /* starting at the beginning */
 
421
        if (parse_high_water == 0)      /* starting at the beginning */
202
422
                parse_extent = fields_arr[0]->stptr;
203
423
        /*
204
424
         * parse up to num fields, calling set_field() for each, and saving
205
425
         * in parse_extent the point where the parse left off
206
426
         */
207
 
        n = parse_fields(num, &parse_extent,
 
427
        n = (*parse_field)(num, &parse_extent,
208
428
                fields_arr[0]->stlen - (parse_extent-fields_arr[0]->stptr),
209
 
                save_fs, set_field, (NODE *)NULL);
 
429
                save_fs, FS_regexp, set_field, (NODE *)NULL);
 
430
        parse_high_water = n;
210
431
        if (num == HUGE-1)
211
432
                num = n;
212
 
        if (n < num) {  /* requested field number beyond end of record;
213
 
                         * set_field will just extend the number of fields,
214
 
                         * with empty fields
215
 
                         */
216
 
                set_field(num, f_empty, 0, (NODE *) NULL);
 
433
        if (n < num) {  /* requested field number beyond end of record; */
 
434
                register int i;
 
435
 
 
436
                if (num > nf_high_water)
 
437
                        grow_fields_arr(num);
 
438
 
 
439
                /* fill in fields that don't exist */
 
440
                for (i = n + 1; i <= num; i++)
 
441
                        fields_arr[i] = Nnull_string;
 
442
 
217
443
                /*
218
444
                 * if this field is onthe LHS of an assignment, then we want to
219
445
                 * set NF to this value, below
229
455
         * only gets set if the field is assigned to -- in this case n has
230
456
         * been set to num above
231
457
         */
232
 
        if (*parse_extent == '\0')
233
 
                assign_number(&NF_node->var_value, (AWKNUM)n);
 
458
        if (parse_extent == fields_arr[0]->stptr + fields_arr[0]->stlen)
 
459
                NF = n;
234
460
 
235
461
        return &fields_arr[num];
236
462
}
237
463
 
238
 
/*
239
 
 * this is called both from get_field() and from do_split()
240
 
 */
241
 
static int
242
 
parse_fields(up_to, buf, len, fs, set, n)
243
 
int up_to;      /* parse only up to this field number */
244
 
char **buf;     /* on input: string to parse; on output: point to start next */
 
464
static void
 
465
set_element(num, s, len, n)
 
466
int num;
 
467
char *s;
245
468
int len;
246
 
register char *fs;
247
 
void (*set) (); /* routine to set the value of the parsed field */
248
469
NODE *n;
249
470
{
250
 
        char *s = *buf;
251
 
        register char *field;
252
 
        register char *scan;
253
 
        register char *end = s + len;
254
 
        int NF = parse_high_water;
255
 
        char rs = get_rs();
256
 
 
257
 
 
258
 
        if (up_to == HUGE)
259
 
                NF = 0;
260
 
        if (*fs && *(fs + 1) != '\0') { /* fs is a regexp */
261
 
                struct re_registers reregs;
262
 
 
263
 
                scan = s;
264
 
                if (rs == 0 && STREQ(FS_node->var_value->stptr, " ")) {
265
 
                        while ((*scan == '\n' || *scan == ' ' || *scan == '\t')
266
 
                            && scan < end)
267
 
                                scan++;
268
 
                }
269
 
                s = scan;
270
 
                while (scan < end
271
 
                    && re_split(scan, (int)(end - scan), fs, &reregs) != -1
272
 
                    && NF < up_to) {
273
 
                        if (reregs.end[0] == 0) {       /* null match */
274
 
                                scan++;
275
 
                                if (scan == end) {
276
 
                                        (*set)(++NF, s, scan - s, n);
277
 
                                        up_to = NF;
278
 
                                        break;
279
 
                                }
280
 
                                continue;
281
 
                        }
282
 
                        (*set)(++NF, s, scan - s + reregs.start[0], n);
283
 
                        scan += reregs.end[0];
284
 
                        s = scan;
285
 
                }
286
 
                if (NF != up_to && scan <= end) {
287
 
                        if (!(rs == 0 && scan == end)) {
288
 
                                (*set)(++NF, scan, (int)(end - scan), n);
289
 
                                scan = end;
290
 
                        }
291
 
                }
292
 
                *buf = scan;
293
 
                return (NF);
294
 
        }
295
 
        for (scan = s; scan < end && NF < up_to; scan++) {
296
 
                /*
297
 
                 * special case:  fs is single space, strip leading
298
 
                 * whitespace 
299
 
                 */
300
 
                if (*fs == ' ') {
301
 
                        while ((*scan == ' ' || *scan == '\t') && scan < end)
302
 
                                scan++;
303
 
                        if (scan >= end)
304
 
                                break;
305
 
                }
306
 
                field = scan;
307
 
                if (*fs == ' ')
308
 
                        while (*scan != ' ' && *scan != '\t' && scan < end)
309
 
                                scan++;
310
 
                else {
311
 
                        while (*scan != *fs && scan < end)
312
 
                                scan++;
313
 
                        if (rs && scan == end-1 && *scan == *fs) {
314
 
                                (*set)(++NF, field, (int)(scan - field), n);
315
 
                                field = scan;
316
 
                        }
317
 
                }
318
 
                (*set)(++NF, field, (int)(scan - field), n);
319
 
                if (scan == end)
320
 
                        break;
321
 
        }
322
 
        *buf = scan;
323
 
        return NF;
324
 
}
325
 
 
326
 
static int
327
 
re_split(buf, len, fs, reregsp)
328
 
char *buf, *fs;
329
 
int len;
330
 
struct re_registers *reregsp;
331
 
{
332
 
        typedef struct re_pattern_buffer RPAT;
333
 
        static RPAT *rp;
334
 
        static char *last_fs = NULL;
335
 
 
336
 
        if ((last_fs != NULL && !STREQ(fs, last_fs))
337
 
            || (rp && ! strict && ((IGNORECASE_node->var_value->numbr != 0)
338
 
                         ^ (rp->translate != NULL))))
339
 
        {
340
 
                /* fs has changed or IGNORECASE has changed */
341
 
                free(rp->buffer);
342
 
                free(rp->fastmap);
343
 
                free((char *) rp);
344
 
                free(last_fs);
345
 
                last_fs = NULL;
346
 
        }
347
 
        if (last_fs == NULL) {  /* first time */
348
 
                emalloc(rp, RPAT *, sizeof(RPAT), "re_split");
349
 
                memset((char *) rp, 0, sizeof(RPAT));
350
 
                emalloc(rp->buffer, char *, 8, "re_split");
351
 
                rp->allocated = 8;
352
 
                emalloc(rp->fastmap, char *, 256, "re_split");
353
 
                emalloc(last_fs, char *, strlen(fs) + 1, "re_split");
354
 
                (void) strcpy(last_fs, fs);
355
 
                if (! strict && IGNORECASE_node->var_value->numbr != 0.0)
356
 
                        rp->translate = casetable;
357
 
                else
358
 
                        rp->translate = NULL;
359
 
                if (re_compile_pattern(fs, strlen(fs), rp) != NULL)
360
 
                        fatal("illegal regular expression for FS: `%s'", fs);
361
 
        }
362
 
        return re_search(rp, buf, len, 0, len, reregsp);
 
471
        register NODE *it;
 
472
 
 
473
        it = make_string(s, len);
 
474
        it->flags |= MAYBE_NUM;
 
475
        *assoc_lookup(n, tmp_number((AWKNUM) (num))) = it;
363
476
}
364
477
 
365
478
NODE *
366
479
do_split(tree)
367
480
NODE *tree;
368
481
{
369
 
        NODE *t1, *t2, *t3;
370
 
        register char *splitc;
 
482
        NODE *t1, *t2, *t3, *tmp;
 
483
        register char *splitc = "";
371
484
        char *s;
372
 
        NODE *n;
373
 
 
374
 
        if (a_get_three(tree, &t1, &t2, &t3) < 3)
375
 
                splitc = get_fs();
376
 
        else
377
 
                splitc = force_string(t3)->stptr;
378
 
 
379
 
        n = t2;
 
485
        int (*parseit)();
 
486
        Regexp *rp = NULL;
 
487
 
 
488
        t1 = tree_eval(tree->lnode);
 
489
        t2 = tree->rnode->lnode;
 
490
        t3 = tree->rnode->rnode->lnode;
 
491
 
 
492
        (void) force_string(t1);
 
493
 
380
494
        if (t2->type == Node_param_list)
381
 
                n = stack_ptr[t2->param_cnt];
382
 
        if (n->type != Node_var && n->type != Node_var_array)
 
495
                t2 = stack_ptr[t2->param_cnt];
 
496
        if (t2->type != Node_var && t2->type != Node_var_array)
383
497
                fatal("second argument of split is not a variable");
384
 
        assoc_clear(n);
385
 
 
386
 
        tree = force_string(t1);
387
 
 
388
 
        s = tree->stptr;
389
 
        return tmp_number((AWKNUM)
390
 
                parse_fields(HUGE, &s, tree->stlen, splitc, set_element, n));
 
498
        assoc_clear(t2);
 
499
 
 
500
        if (t3->re_flags & FS_DFLT) {
 
501
                parseit = parse_field;
 
502
                splitc = FS;
 
503
                rp = FS_regexp;
 
504
        } else {
 
505
                tmp = force_string(tree_eval(t3->re_exp));
 
506
                if (tmp->stlen == 1) {
 
507
                        if (tmp->stptr[0] == ' ') {
 
508
                                parseit = def_parse_field;
 
509
                        } else {
 
510
                                parseit = sc_parse_field;
 
511
                                splitc = tmp->stptr;
 
512
                        }
 
513
                } else {
 
514
                        parseit = re_parse_field;
 
515
                        rp = re_update(t3);
 
516
                }
 
517
                free_temp(tmp);
 
518
        }
 
519
 
 
520
        s = t1->stptr;
 
521
        tmp = tmp_number((AWKNUM) (*parseit)(HUGE, &s, t1->stlen,
 
522
                                             splitc, rp, set_element, t2));
 
523
        free_temp(t1);
 
524
        return tmp;
391
525
}
392
526
 
393
 
static char *
394
 
get_fs()
 
527
void
 
528
set_FS()
395
529
{
396
530
        register NODE *tmp;
397
531
        static char buf[10];
398
532
 
 
533
        if (FS_regexp) {
 
534
                refree(FS_regexp);
 
535
                FS_regexp = NULL;
 
536
        }
 
537
        parse_field = def_parse_field;
399
538
        tmp = force_string(FS_node->var_value);
400
 
        if (get_rs() == 0) {
 
539
        FS = tmp->stptr;
 
540
        if (*RS == 0) {
 
541
                parse_field = re_parse_field;
 
542
                FS = buf;
401
543
                if (tmp->stlen == 1) {
402
544
                        if (tmp->stptr[0] == ' ')
403
545
                                (void) strcpy(buf, "[   \n]+");
404
 
                        else
 
546
                        else if (tmp->stptr[0] != '\n')
405
547
                                sprintf(buf, "[%c\n]", tmp->stptr[0]);
 
548
                        else {
 
549
                                parse_field = sc_parse_field;
 
550
                                FS = tmp->stptr;
 
551
                        }
406
552
                } else if (tmp->stlen == 0) {
407
553
                        buf[0] = '\n';
408
554
                        buf[1] = '\0';
 
555
                        parse_field = sc_parse_field;
409
556
                } else
410
 
                        return tmp->stptr;
411
 
                return buf;
412
 
        }
413
 
        return tmp->stptr;
414
 
}
415
 
 
416
 
static void
417
 
set_element(num, s, len, n)
418
 
int num;
419
 
char *s;
420
 
int len;
421
 
NODE *n;
422
 
{
423
 
        *assoc_lookup(n, tmp_number((AWKNUM) (num))) = make_string(s, len);
 
557
                        FS = tmp->stptr;
 
558
        } else {
 
559
                if (tmp->stlen > 1)
 
560
                        parse_field = re_parse_field;
 
561
                else if (*FS != ' ' && tmp->stlen == 1)
 
562
                        parse_field = sc_parse_field;
 
563
        }
 
564
        if (parse_field == re_parse_field) {
 
565
                tmp = tmp_string(FS, strlen(FS));
 
566
                FS_regexp = make_regexp(tmp, 0, 1);
 
567
                free_temp(tmp);
 
568
        } else
 
569
                FS_regexp = NULL;
 
570
        resave_fs = 1;
 
571
}
 
572
 
 
573
void
 
574
set_RS()
 
575
{
 
576
        (void) force_string(RS_node->var_value);
 
577
        RS = RS_node->var_value->stptr;
 
578
        set_FS();
 
579
}
 
580
 
 
581
void
 
582
set_FIELDWIDTHS()
 
583
{
 
584
        register char *scan;
 
585
        char *end;
 
586
        register int i;
 
587
        static int fw_alloc = 1;
 
588
        static int warned = 0;
 
589
 
 
590
        if (do_lint && ! warned) {
 
591
                warned = 1;
 
592
                warning("use of FIELDWIDTHS is a gawk extension");
 
593
        }
 
594
        if (strict)     /* quick and dirty, does the trick */
 
595
                return;
 
596
 
 
597
        parse_field = fw_parse_field;
 
598
        scan = force_string(FIELDWIDTHS_node->var_value)->stptr;
 
599
        end = scan + 1;
 
600
        if (FIELDWIDTHS == NULL)
 
601
                emalloc(FIELDWIDTHS, int *, fw_alloc * sizeof(int), "set_FIELDWIDTHS");
 
602
        FIELDWIDTHS[0] = 0;
 
603
        for (i = 1; ; i++) {
 
604
                if (i >= fw_alloc) {
 
605
                        fw_alloc *= 2;
 
606
                        erealloc(FIELDWIDTHS, int *, fw_alloc * sizeof(int), "set_FIELDWIDTHS");
 
607
                }
 
608
                FIELDWIDTHS[i] = (int) strtol(scan, &end, 10);
 
609
                if (end == scan)
 
610
                        break;
 
611
                scan = end;
 
612
        }
 
613
        FIELDWIDTHS[i] = -1;
424
614
}