2 /********************************************
4 copyright 1991, Michael D. Brennan
6 This is a source file for mawk, an implementation of
7 the AWK programming language.
9 Mawk is distributed without warranty under the terms of
10 the GNU General Public License, version 2, 1991.
11 ********************************************/
14 * Revision 1.5 1995/06/18 19:17:47 mike
15 * Create a type Int which on most machines is an int, but on machines
16 * with 16bit ints, i.e., the PC is a long. This fixes implicit assumption
19 * Revision 1.4 1994/10/08 19:15:38 mike
22 * Revision 1.3 1993/07/14 12:32:39 mike
25 * Revision 1.2 1993/07/14 12:22:11 mike
26 * rm SIZE_T and (void) casts
28 * Revision 1.1.1.1 1993/07/03 18:58:12 mike
31 * Revision 5.7 1993/05/08 18:06:00 mike
34 * Revision 5.6 1993/02/13 21:57:25 mike
37 * Revision 5.5 1993/01/01 21:30:48 mike
38 * split new_STRING() into new_STRING and new_STRING0
40 * Revision 5.4.1.2 1993/01/20 12:53:08 mike
43 * Revision 5.4.1.1 1993/01/15 03:33:42 mike
44 * patch3: safer double to int conversion
46 * Revision 5.4 1992/11/29 22:52:11 mike
47 * double->string conversions uses long ints for 16/32 bit
49 * Fixed small LM_DOS bozo.
51 * Revision 5.3 1992/08/17 14:21:10 brennan
52 * patch2: After parsing, only bi_sprintf() uses string_buff.
54 * Revision 5.2 1992/07/10 16:17:10 brennan
55 * MsDOS: remove NO_BINMODE macro
57 * Revision 5.1 1991/12/05 07:55:57 brennan
74 CELL field[FBANK_SZ + NUM_PFIELDS] ;
76 CELL *fbank[NUM_FBANK] =
79 static int max_field = MAX_SPLIT ; /* maximum field actually created*/
81 static void PROTO(build_field0, (void)) ;
82 static void PROTO(set_rs_shadow, (void)) ;
83 static void PROTO(load_pfield, (char *, CELL *)) ;
84 static void PROTO(load_field_ov, (void)) ;
88 /* a description of how to split based on RS.
89 If RS is changed, so is rs_shadow */
92 /* a splitting CELL version of FS */
96 /* nf holds the true value of NF. If nf < 0 , then
97 NF has not been computed, i.e., $0 has not been split
108 if (posix_space_flag && mawk_state == EXECUTION)
109 scan_code['\n'] = SC_UNEXPECTED ;
111 if (rs_shadow.type == SEP_STR)
113 free_STRING((STRING *) rs_shadow.ptr) ;
116 cast_for_split(cellcpy(&c, RS)) ;
120 if ((s = is_string_split(c.ptr, &len)))
124 rs_shadow.type = SEP_CHAR ;
129 rs_shadow.type = SEP_STR ;
130 rs_shadow.ptr = (PTR) new_STRING(s) ;
135 rs_shadow.type = SEP_RE ;
136 rs_shadow.ptr = c.ptr ;
141 rs_shadow.type = SEP_CHAR ;
145 case C_SNULL: /* RS becomes one or more blank lines */
146 if (mawk_state == EXECUTION) scan_code['\n'] = SC_SPACE ;
147 rs_shadow.type = SEP_MLR ;
148 sval = new_STRING("\n\n+") ;
149 rs_shadow.ptr = re_compile(sval) ;
154 bozo("bad cell in set_rs_shadow") ;
159 load_pfield(name, cp)
165 stp = insert(name) ; stp->type = ST_FIELD ;
169 /* initialize $0 and the pseudo fields */
173 field[0].type = C_STRING ;
174 field[0].ptr = (PTR) & null_str ;
177 load_pfield("NF", NF) ;
178 NF->type = C_DOUBLE ;
181 load_pfield("RS", RS) ;
182 RS->type = C_STRING ;
183 RS->ptr = (PTR) new_STRING("\n") ;
184 /* rs_shadow already set */
186 load_pfield("FS", FS) ;
187 FS->type = C_STRING ;
188 FS->ptr = (PTR) new_STRING(" ") ;
189 /* fs_shadow is already set */
191 load_pfield("OFMT", OFMT) ;
192 OFMT->type = C_STRING ;
193 OFMT->ptr = (PTR) new_STRING("%.6g") ;
195 load_pfield("CONVFMT", CONVFMT) ;
196 CONVFMT->type = C_STRING ;
197 CONVFMT->ptr = OFMT->ptr ;
198 string(OFMT)->ref_cnt++ ;
208 cell_destroy(&field[0]) ;
213 field[0].type = C_MBSTRN ;
214 field[0].ptr = (PTR) new_STRING0(len) ;
215 memcpy(string(&field[0])->str, s, len) ;
219 field[0].type = C_STRING ;
220 field[0].ptr = (PTR) & null_str ;
227 /* split field[0] into $1, $2 ... and set NF */
234 CELL c ; /* copy field[0] here if not string */
237 if (field[0].type < C_STRING)
239 cast1_to_s(cellcpy(&c, field + 0)) ;
242 else cp = &field[0] ;
244 if (string(cp)->len == 0) nf = 0 ;
247 switch (fs_shadow.type)
249 case C_SNULL: /* FS == "" */
250 nf = null_split(string(cp)->str) ;
254 nf = space_split(string(cp)->str, string(cp)->len) ;
258 nf = re_split(string(cp)->str, fs_shadow.ptr) ;
265 NF->type = C_DOUBLE ;
266 NF->dval = (double) nf ;
270 cnt = MAX_SPLIT ; load_field_ov() ;
276 cell_destroy(field + cnt) ;
277 field[cnt].ptr = (PTR) split_buff[cnt - 1] ;
278 field[cnt--].type = C_MBSTRN ;
281 if (cp == &c) { free_STRING(string(cp)) ; }
285 assign CELL *cp to field or pseudo field
286 and take care of all side effects
297 /* the most common case first */
300 cell_destroy(field) ;
306 /* its not important to do any of this fast */
308 if (nf < 0) split_field0() ;
311 if (!SAMESEG(fp, field))
318 switch (i = (fp - field))
324 cellcpy(NF, cellcpy(&c, cp)) ;
325 if (c.type != C_DOUBLE) cast1_to_d(&c) ;
327 if ((j = d_to_i(c.dval)) < 0)
328 rt_error("negative value assigned to NF") ;
331 for (i = nf + 1; i <= j; i++)
335 cp->type = C_STRING ;
336 cp->ptr = (PTR) & null_str ;
352 cast_for_split(cellcpy(&fs_shadow, cellcpy(FS, cp))) ;
357 /* If the user does something stupid with OFMT or CONVFMT,
359 We'll make an attempt to protect ourselves here. This is
360 why OFMT and CONVFMT are pseudo fields.
362 The ptrs of OFMT and CONVFMT always have a valid STRING,
363 even if assigned a DOUBLE or NOINIT
366 free_STRING(string(fp)) ;
368 if (fp->type < C_STRING) /* !! */
369 fp->ptr = (PTR) new_STRING("%.6g") ;
370 else if (fp == CONVFMT)
372 /* It's a string, but if it's really goofy and CONVFMT,
373 it could still damage us. Test it .
378 sprintf(xbuff, string(fp)->str, 3.1459) ;
380 rt_error("CONVFMT assigned unusable value") ;
388 default: /* $1 or $2 or ... */
394 if (i < 0 || i > MAX_SPLIT) i = field_addr_to_index(fp) ;
398 for (j = nf + 1; j < i; j++)
402 cp->type = C_STRING ;
403 cp->ptr = (PTR) & null_str ;
408 NF->type = C_DOUBLE ;
409 NF->dval = (double) i ;
418 /* construct field[0] from the other fields */
426 if (nf < 0) bozo("nf <0 in build_field0") ;
429 cell_destroy(field + 0) ;
433 field[0].type = C_STRING ;
434 field[0].ptr = (PTR) & null_str ;
439 cellcpy(field, field + 1) ;
447 register char *p, *q ;
449 CELL **fbp, *cp_limit ;
452 cast1_to_s(cellcpy(&c, OFS)) ;
453 ofs = (STRING *) c.ptr ;
454 cast1_to_s(cellcpy(&c, field_ptr(nf))) ;
455 tail = (STRING *) c.ptr ;
458 len = cnt * ofs->len + tail->len ;
460 fbp = fbank ; cp_limit = field + FBANK_SZ ;
465 if (cp->type < C_STRING)
466 { /* use the string field temporarily */
467 if (cp->type == C_NOINIT)
469 cp->ptr = (PTR) & null_str ;
472 else /* its a double */
477 ival = d_to_I(cp->dval) ;
478 if (ival == cp->dval) sprintf(xbuff, INT_FMT, ival) ;
479 else sprintf(xbuff, string(CONVFMT)->str, cp->dval) ;
481 cp->ptr = (PTR) new_STRING(xbuff) ;
485 len += string(cp)->len ;
487 if (++cp == cp_limit)
490 cp_limit = cp + FBANK_SZ ;
495 field[0].type = C_STRING ;
496 field[0].ptr = (PTR) new_STRING0(len) ;
498 p = string(field)->str ;
500 /* walk it again , putting things together */
501 cnt = nf-1 ; fbp = fbank ;
502 cp = field+1 ; cp_limit = field + FBANK_SZ ;
505 memcpy(p, string(cp)->str, string(cp)->len) ;
506 p += string(cp)->len ;
507 /* if not really string, free temp use of ptr */
508 if (cp->type < C_STRING) { free_STRING(string(cp)) ; }
509 if (++cp == cp_limit)
512 cp_limit = cp + FBANK_SZ ;
514 /* add the separator */
515 q = ofs->str ; while( *q ) *p++ = *q++ ;
517 /* tack tail on the end */
518 memcpy(p, tail->str, tail->len) ;
521 free_STRING(tail) ; free_STRING(ofs) ;
525 /* We are assigning to a CELL and we aren't sure if its
529 slow_cell_assign(target, source)
530 register CELL *target ;
535 #ifdef MSDOS /* the dreaded segment nonsense */
536 SAMESEG(target, field) &&
538 target >= field && target <= LAST_PFIELD)
539 field_assign(target, source) ;
542 CELL **p = fbank + 1 ;
548 SAMESEG(target, *p) &&
550 target >= *p && target < *p + FBANK_SZ)
552 field_assign(target, source) ;
557 /* its not a field */
558 cell_destroy(target) ;
559 cellcpy(target, source) ;
564 field_addr_to_index(cp)
575 cp < *p || cp >= *p + FBANK_SZ)
578 return ((p - fbank) << FB_SHIFT) + (cp - *p) ;
581 /*------- more than 1 fbank needed ------------*/
584 compute the address of a field with index
598 rt_overflow("maximum number of fields", MAX_FIELD) ;
601 while (fbank[j]) j++ ;
605 fbank[j] = (CELL *) zmalloc(sizeof(CELL) * FBANK_SZ) ;
606 memset(fbank[j], 0, sizeof(CELL) * FBANK_SZ) ;
608 max_field += FBANK_SZ ;
610 while (i > max_field);
613 return &fbank[i >> FB_SHIFT][i & (FBANK_SZ - 1)] ;
617 $0 split into more than MAX_SPLIT fields,
618 $(MAX_FIELD+1) ... are on the split_ov_list.
619 Copy into fields which start at fbank[1]
625 register SPLIT_OV *p ; /* walks split_ov_list */
626 register CELL *cp ; /* target of copy */
627 int j ; /* current fbank[] */
628 CELL *cp_limit ; /* change fbank[] */
629 SPLIT_OV *q ; /* trails p */
631 /* make sure the fields are allocated */
634 p = split_ov_list ; split_ov_list = (SPLIT_OV*) 0 ;
635 j = 1 ; cp = fbank[j] ; cp_limit = cp + FBANK_SZ ;
639 cp->type = C_MBSTRN ;
640 cp->ptr = (PTR) p->sval ;
642 if (++cp == cp_limit)
644 cp = fbank[++j] ; cp_limit = cp + FBANK_SZ ;
647 q = p ; p = p->link ; ZFREE(q) ;
655 binmode() /* read current value of BINMODE */
659 cast1_to_d(cellcpy(&c, BINMODE)) ;
660 return d_to_i(c.dval) ;
663 /* set BINMODE and RS and ORS
664 from environment or -W binmode= */
674 c.ptr = (PTR) new_STRING((x & 1) ? "\r\n" : "\n") ;
675 field_assign(RS, &c) ;
676 free_STRING(string(&c)) ;
680 ORS->type = C_STRING ;
681 ORS->ptr = (PTR) new_STRING((x & 2) ? "\r\n" : "\n") ;
683 cell_destroy(BINMODE) ;
684 BINMODE->type = C_DOUBLE ;
685 BINMODE->dval = (double) x ;