/********************************************
copyright 1991, Michael D. Brennan
This is a source file for mawk, an implementation of
the AWK programming language.
Mawk is distributed without warranty under the terms of
the GNU General Public License, version 2, 1991.
********************************************/
* Revision 5.1 91/12/05 07:55:57 brennan
CELL field
[FBANK_SZ
+NUM_PFIELDS
] ;
CELL
*fbank
[NUM_FBANK
] = {field
} ;
static int max_field
= MAX_SPLIT
; /* maximum field actually created*/
static void PROTO( build_field0
, (void) ) ;
static void PROTO( set_rs_shadow
, (void) ) ;
static void PROTO( load_pfield
, (char*, CELL
*)) ;
static void PROTO( load_field_ov
, (void)) ;
/* a description of how to split based on RS.
If RS is changed, so is rs_shadow */
SEPARATOR rs_shadow
= {SEP_CHAR
, '\n'} ;
/* a splitting CELL version of FS */
CELL fs_shadow
= {C_SPACE
} ;
/* nf holds the true value of NF. If nf < 0 , then
NF has not been computed, i.e., $0 has not been split
static void set_rs_shadow()
if ( posix_space_flag
&& mawk_state
== EXECUTION
)
scan_code
['\n'] = SC_UNEXPECTED
;
if ( rs_shadow
.type
== SEP_STR
) free_STRING((STRING
*) rs_shadow
.ptr
) ;
cast_for_split( cellcpy(&c
, RS
) ) ;
if ( s
= is_string_split(c
.ptr
, &len
) )
{ rs_shadow
.type
= SEP_CHAR
;
{ rs_shadow
.type
= SEP_STR
;
rs_shadow
.ptr
= (PTR
) new_STRING(s
) ;
{ rs_shadow
.type
= SEP_RE
;
rs_shadow
.type
= SEP_CHAR
;
case C_SNULL
: /* RS becomes one or more blank lines */
if ( mawk_state
== EXECUTION
) scan_code
['\n'] = SC_SPACE
;
rs_shadow
.type
= SEP_MLR
;
sval
= new_STRING( "\n\n+" ) ;
rs_shadow
.ptr
= re_compile(sval
) ;
default : bozo("bad cell in set_rs_shadow") ;
static void load_pfield(name
, cp
)
stp
= insert(name
) ; stp
->type
= ST_FIELD
;
/* initialize $0 and the pseudo fields */
field
[0].type
= C_STRING
;
field
[0].ptr
= (PTR
) & null_str
;
RS
->ptr
= (PTR
) new_STRING( "\n" ) ;
/* rs_shadow already set */
FS
->ptr
= (PTR
) new_STRING( " " ) ;
/* fs_shadow is already set */
load_pfield("OFMT", OFMT
) ;
OFMT
->ptr
= (PTR
) new_STRING( "%.6g" ) ;
load_pfield("CONVFMT", CONVFMT
) ;
CONVFMT
->type
= C_STRING
;
CONVFMT
->ptr
= OFMT
->ptr
;
string(OFMT
)->ref_cnt
++ ;
cell_destroy( & field
[0] ) ;
field
[0].type
= C_MBSTRN
;
field
[0].ptr
= (PTR
) new_STRING( (char *) 0, len
) ;
(void) memcpy( string(&field
[0])->str
, s
, SIZE_T(len
) ) ;
field
[0].type
= C_STRING
;
field
[0].ptr
= (PTR
) &null_str
;
/* split field[0] into $1, $2 ... and set NF */
CELL c
; /* copy field[0] here if not string */
if ( field
[0].type
< C_STRING
)
{ cast1_to_s(cellcpy(&c
, field
+0)) ;
if ( string(cp
)->len
== 0 ) nf
= 0 ;
case C_SNULL
: /* FS == "" */
field
[1].type
= C_MBSTRN
;
if ( cp
== field
) string(cp
)->ref_cnt
++ ;
/* else we gain one ref_cnt and lose one for a wash */
nf
= space_split(string(cp
)->str
, string(cp
)->len
) ;
nf
= re_split(string(cp
)->str
, fs_shadow
.ptr
) ;
cnt
= MAX_SPLIT
; load_field_ov() ;
cell_destroy(field
+cnt
) ;
field
[cnt
].ptr
= (PTR
) split_buff
[cnt
-1] ;
field
[cnt
--].type
= C_MBSTRN
;
if ( cp
== &c
) free_STRING( string(cp
) ) ;
assign CELL *cp to field or pseudo field
and take care of all side effects
void field_assign( fp
, cp
)
/* the most common case first */
/* its not important to do any of this fast */
if ( nf
< 0 ) split_field0() ;
if ( !SAMESEG(fp
,field
) ) goto lm_dos_label
;
switch( i
= (fp
- field
) )
(void) cellcpy(NF
, cellcpy(&c
,cp
) ) ;
if ( c
.type
!= C_DOUBLE
) cast1_to_d(&c
) ;
if ( (j
= (int) c
.dval
) < 0 )
rt_error("negative value assigned to NF") ;
for ( i
= nf
+1 ; i
<= j
; i
++ )
cp
->ptr
= (PTR
) &null_str
;
cast_for_split( cellcpy(&fs_shadow
, cellcpy(FS
, cp
)) ) ;
/* If the user does something stupid with OFMT or CONVFMT,
We'll make an attempt to protect ourselves here. This is
why OFMT and CONVFMT are pseudo fields.
The ptrs of OFMT and CONVFMT always have a valid STRING,
even if assigned a DOUBLE or NOINIT
free_STRING( string(fp
) ) ;
if ( fp
->type
< C_STRING
) /* !! */
fp
->ptr
= (PTR
) new_STRING( "%.6g" ) ;
/* It's a string, but if it's really goofy and CONVFMT,
it could still damage us. Test it .
(void) sprintf(string_buff
,
string(fp
)->str
, 3.1459) ;
rt_error("CONVFMT assigned unusable value") ;
default: /* $1 or $2 or ... */
if ( i
< 0 || i
> MAX_SPLIT
) i
= field_addr_to_index(fp
) ;
{ for ( j
= nf
+1 ; j
< i
; j
++ )
cp
->ptr
= (PTR
) &null_str
;
/* construct field[0] from the other fields */
static void build_field0()
bozo("nf <0 in build_field0") ;
cell_destroy( field
+0 ) ;
{ field
[0].type
= C_STRING
;
field
[0].ptr
= (PTR
) &null_str
;
if ( nf
== 1 ) (void) cellcpy(field
, field
+1) ;
cast1_to_s(cellcpy(&c
,OFS
)) ;
cast1_to_s(cellcpy(&c
, field_ptr(nf
))) ;
tail
= (STRING
*) c
.ptr
;
len
= cnt
*ofs
->len
+ tail
->len
;
fbp
= fbank
; cp_limit
= field
+ FBANK_SZ
;
if ( cp
->type
< C_STRING
)
{ /* use the string field temporarily */
if ( cp
->type
== C_NOINIT
)
{ cp
->ptr
= (PTR
) &null_str
;
if ( (double)(ival
= (int)cp
->dval
) == cp
->dval
)
(void) sprintf(string_buff
, "%d", ival
) ;
(void) sprintf(string_buff
,
string(CONVFMT
)->str
, cp
->dval
) ;
cp
->ptr
= (PTR
) new_STRING(string_buff
) ;
{ cp
= * ++fbp
; cp_limit
= cp
+ FBANK_SZ
; }
field
[0].type
= C_STRING
;
field
[0].ptr
= (PTR
) new_STRING((char *) 0, len
) ;
/* walk it again , putting things together */
cnt
= nf
-1 ; fbp
= fbank
;
cp
= field
+1 ; cp_limit
= field
+ FBANK_SZ
;
(void) memcpy(p
, string(cp
)->str
,SIZE_T(string(cp
)->len
)) ;
/* if not really string, free temp use of ptr */
if ( cp
->type
< C_STRING
) free_STRING(string(cp
)) ;
{ cp
= * ++fbp
; cp_limit
= cp
+ FBANK_SZ
; }
q
= ofs
->str
; while( *q
) *p
++ = *q
++ ;
/* tack tail on the end */
(void) memcpy(p
, tail
->str
, SIZE_T(tail
->len
)) ;
free_STRING(tail
) ; free_STRING(ofs
) ;
/* We are assigning to a CELL and we aren't sure if its
void slow_cell_assign(target
, source
)
#if LM_DOS /* the dreaded segment nonsense */
target
>= field
&& target
<= LAST_PFIELD
)
field_assign(target
, source
) ;
target
>= *p
&& target
< *p
+ FBANK_SZ
)
field_assign(target
, source
) ;
(void) cellcpy(target
, source
) ;
int field_addr_to_index(cp
)
cp
< *p
|| cp
>= *p
+ FBANK_SZ
) p
++ ;
return ((p
-fbank
)<<FB_SHIFT
) + (cp
- *p
) ;
/*------- more than 1 fbank needed ------------*/
compute the address of a field with index
rt_overflow("maximum number of fields", MAX_FIELD
) ;
j
= 1 ; while( fbank
[j
] ) j
++ ;
fbank
[j
] = (CELL
*)zmalloc(sizeof(CELL
)*FBANK_SZ
) ;
(void) memset(fbank
[j
], 0, SIZE_T(sizeof(CELL
)*FBANK_SZ
)) ;
while ( i
> max_field
) ;
return & fbank
[i
>>FB_SHIFT
][i
& (FBANK_SZ
-1)] ;
$0 split into more than MAX_SPLIT fields,
$(MAX_FIELD+1) ... are on the split_ov_list.
Copy into fields which start at fbank[1]
static void load_field_ov()
register SPLIT_OV
*p
; /* walks split_ov_list */
register CELL
*cp
; /* target of copy */
int j
; /* current fbank[] */
CELL
*cp_limit
; /* change fbank[] */
SPLIT_OV
*q
; /* trails p */
/* make sure the fields are allocated */
(void) slow_field_ptr(nf
) ;
p
= split_ov_list
; split_ov_list
= (SPLIT_OV
*) 0 ;
j
= 1 ; cp
= fbank
[j
] ; cp_limit
= cp
+ FBANK_SZ
;
cp
->ptr
= (PTR
) p
->sval
;
cp
= fbank
[++j
] ; cp_limit
= cp
+ FBANK_SZ
;
q
= p
; p
= p
->link
; ZFREE(q
) ;
#if MSDOS && NO_BINMODE==0
int binmode() /* read current value of BINMODE */
cast1_to_d(cellcpy(&c
, BINMODE
)) ;
/* set BINMODE and RS and ORS
from environment or -W binmode= */
c
.ptr
= (PTR
) new_STRING ( (x
&1) ? "\r\n" : "\n" ) ;
free_STRING(string(&c
)) ;
ORS
->ptr
= (PTR
) new_STRING( (x
&2) ? "\r\n" : "\n") ;
BINMODE
->type
= C_DOUBLE
;
BINMODE
->dval
= (double) x
;