*** empty log message ***

This commit is contained in:
hyung-hwan 2006-10-03 14:38:26 +00:00
parent 9a78805acc
commit bf93fe4452
6 changed files with 111 additions and 551 deletions

View File

@ -223,6 +223,10 @@ SOURCE=.\parse.c
# End Source File
# Begin Source File
SOURCE=.\rec.c
# End Source File
# Begin Source File
SOURCE=.\rex.c
# End Source File
# Begin Source File

View File

@ -1,5 +1,5 @@
/*
* $Id: awk.h,v 1.119 2006-10-02 14:53:44 bacon Exp $
* $Id: awk.h,v 1.120 2006-10-03 14:38:26 bacon Exp $
*/
#ifndef _XP_AWK_AWK_H_
@ -9,6 +9,7 @@
#include <xp/macros.h>
typedef struct xp_awk_t xp_awk_t;
typedef struct xp_awk_run_t xp_awk_run_t;
typedef struct xp_awk_val_t xp_awk_val_t;
typedef struct xp_awk_extio_t xp_awk_extio_t;
@ -40,14 +41,6 @@ struct xp_awk_extio_t
xp_awk_extio_t* next;
};
/*
struct xp_awk_thrlks_t
{
xp_awk_lk_t lock;
xp_awk_lk_t unlock;
void* custom_data;
};
*/
struct xp_awk_syscas_t
{
/* memory */
@ -339,22 +332,21 @@ int xp_awk_parse (xp_awk_t* awk, xp_awk_srcios_t* srcios);
int xp_awk_run (xp_awk_t* awk,
xp_awk_runios_t* runios, xp_awk_runcbs_t* runcbs);
int xp_awk_stop (xp_awk_t* awk, void* run);
int xp_awk_stop (xp_awk_t* awk, xp_awk_run_t* run);
void xp_awk_stopall (xp_awk_t* awk);
int xp_awk_getrunerrnum (xp_awk_t* awk, void* run, int* errnum);
int xp_awk_getrunerrnum (xp_awk_t* awk, xp_awk_run_t* run, int* errnum);
/* functions to access internal stack structure */
xp_size_t xp_awk_getnargs (void* run);
xp_awk_val_t* xp_awk_getarg (void* run, xp_size_t idx);
xp_awk_val_t* xp_awk_getglobal (void* run, xp_size_t idx);
int xp_awk_setglobal (void* run, xp_size_t idx, xp_awk_val_t* val);
void xp_awk_seterrnum (void* run, int errnum);
void xp_awk_setretval (void* run, xp_awk_val_t* val);
xp_size_t xp_awk_getnargs (xp_awk_run_t* run);
xp_awk_val_t* xp_awk_getarg (xp_awk_run_t* run, xp_size_t idx);
xp_awk_val_t* xp_awk_getglobal (xp_awk_run_t* run, xp_size_t idx);
int xp_awk_setglobal (xp_awk_run_t* run, xp_size_t idx, xp_awk_val_t* val);
void xp_awk_seterrnum (xp_awk_run_t* run, int errnum);
void xp_awk_setretval (xp_awk_run_t* run, xp_awk_val_t* val);
int xp_awk_setrecord (
void* run, const xp_char_t* str, xp_size_t len);
int xp_awk_setfield (
void* run, xp_size_t idx, const xp_char_t* str, xp_size_t len);
/* record and field functions */
int xp_awk_clrrec (xp_awk_run_t* run, xp_bool_t skip_inrec_line);
int xp_awk_setrec (xp_awk_run_t* run, xp_size_t idx, const xp_char_t* str, xp_size_t len);
/* utility functions exported by awk.h */
xp_long_t xp_awk_strtolong (

View File

@ -1,12 +1,11 @@
/*
* $Id: awk_i.h,v 1.61 2006-09-29 11:18:13 bacon Exp $
* $Id: awk_i.h,v 1.62 2006-10-03 14:38:26 bacon Exp $
*/
#ifndef _XP_AWK_AWKI_H_
#define _XP_AWK_AWKI_H_
typedef struct xp_awk_chain_t xp_awk_chain_t;
typedef struct xp_awk_run_t xp_awk_run_t;
typedef struct xp_awk_tree_t xp_awk_tree_t;
#include <xp/awk/awk.h>

View File

@ -1,5 +1,5 @@
/*
* $Id: func.c,v 1.55 2006-10-02 14:53:44 bacon Exp $
* $Id: func.c,v 1.56 2006-10-03 14:38:26 bacon Exp $
*/
#include <xp/awk/awk_i.h>
@ -1042,7 +1042,7 @@ static int __substitute (xp_awk_t* awk, void* run, xp_long_t max_count)
{
if (a2 == XP_NULL)
{
if (xp_awk_setrecord (run,
if (xp_awk_setrec (run, 0,
XP_AWK_STR_BUF(&new), XP_AWK_STR_LEN(&new)) == -1)
{
xp_awk_str_close (&new);
@ -1053,19 +1053,10 @@ static int __substitute (xp_awk_t* awk, void* run, xp_long_t max_count)
else if (((xp_awk_val_ref_t*)a2)->id == XP_AWK_VAL_REF_POS)
{
int n;
xp_size_t idx;
idx = (xp_size_t)((xp_awk_val_ref_t*)a2)->adr;
if (idx == 0)
{
n = xp_awk_setrecord (run,
XP_AWK_STR_BUF(&new), XP_AWK_STR_LEN(&new));
}
else
{
n = xp_awk_setfield (run, idx,
XP_AWK_STR_BUF(&new), XP_AWK_STR_LEN(&new));
}
n = xp_awk_setrec (
run, (xp_size_t)((xp_awk_val_ref_t*)a2)->adr,
XP_AWK_STR_BUF(&new), XP_AWK_STR_LEN(&new));
if (n == -1)
{

View File

@ -1,6 +1,6 @@
SRCS = \
awk.c err.c tree.c str.c tab.c map.c parse.c \
run.c val.c func.c misc.c extio.c rex.c
run.c rec.c val.c func.c misc.c extio.c rex.c
OBJS = $(SRCS:.c=.obj)
OUT = xpawk

View File

@ -1,5 +1,5 @@
/*
* $Id: run.c,v 1.216 2006-10-02 14:53:44 bacon Exp $
* $Id: run.c,v 1.217 2006-10-03 14:38:26 bacon Exp $
*/
#include <xp/awk/awk_i.h>
@ -194,13 +194,6 @@ static int __raw_push (xp_awk_run_t* run, void* val);
static void __raw_pop_times (xp_awk_run_t* run, xp_size_t times);
static int __read_record (xp_awk_run_t* run);
static int __set_record (
xp_awk_run_t* run, const xp_char_t* str, xp_size_t len);
static int __split_record (xp_awk_run_t* run);
static int __clear_record (xp_awk_run_t* run, xp_bool_t noline);
static int __recomp_record_fields (
xp_awk_run_t* run, xp_size_t lv,
const xp_char_t* str, xp_size_t len);
static int __shorten_record (xp_awk_run_t* run, xp_size_t nflds);
static xp_char_t* __idxnde_to_str (
@ -219,31 +212,29 @@ static int __printval (xp_awk_pair_t* pair, void* arg)
return 0;
}
xp_size_t xp_awk_getnargs (void* run)
xp_size_t xp_awk_getnargs (xp_awk_run_t* run)
{
return (xp_size_t) STACK_NARGS ((xp_awk_run_t*)run);
return (xp_size_t) STACK_NARGS (run);
}
xp_awk_val_t* xp_awk_getarg (void* run, xp_size_t idx)
xp_awk_val_t* xp_awk_getarg (xp_awk_run_t* run, xp_size_t idx)
{
return STACK_ARG ((xp_awk_run_t*)run, idx);
return STACK_ARG (run, idx);
}
xp_awk_val_t* xp_awk_getglobal (void* run, xp_size_t idx)
xp_awk_val_t* xp_awk_getglobal (xp_awk_run_t* run, xp_size_t idx)
{
return STACK_GLOBAL(((xp_awk_run_t*)run),idx);
return STACK_GLOBAL (run, idx);
}
int xp_awk_setglobal (void* run, xp_size_t idx, xp_awk_val_t* val)
int xp_awk_setglobal (xp_awk_run_t* run, xp_size_t idx, xp_awk_val_t* val)
{
xp_awk_run_t* r = (xp_awk_run_t*)run;
xp_awk_val_t* old = STACK_GLOBAL(r,idx);
xp_awk_val_t* old = STACK_GLOBAL (run, idx);
if (old->type == XP_AWK_VAL_MAP)
{
/* once a variable becomes an array,
* it cannot be changed to a scalar variable */
PANIC_I (r, XP_AWK_EMAPTOSCALAR);
PANIC_I (run, XP_AWK_EMAPTOSCALAR);
}
/* TODO: is this correct?? */
@ -252,7 +243,7 @@ int xp_awk_setglobal (void* run, xp_size_t idx, xp_awk_val_t* val)
idx != XP_AWK_GLOBAL_ARGV)
{
/* TODO: better error code */
PANIC_I (r, XP_AWK_ESCALARTOMAP);
PANIC_I (run, XP_AWK_ESCALARTOMAP);
}
if (idx == XP_AWK_GLOBAL_FS)
@ -283,26 +274,22 @@ int xp_awk_setglobal (void* run, xp_size_t idx, xp_awk_val_t* val)
/* compile the regular expression */
/* TODO: use safebuild */
rex = xp_awk_buildrex (
((xp_awk_run_t*)run)->awk,
fs_ptr, fs_len, &r->errnum);
run->awk, fs_ptr, fs_len, &run->errnum);
if (rex == XP_NULL)
{
if (val->type != XP_AWK_VAL_STR)
XP_AWK_FREE (((xp_awk_run_t*)run)->awk, fs_ptr);
XP_AWK_FREE (run->awk, fs_ptr);
return -1;
}
if (r->global.fs != XP_NULL)
if (run->global.fs != XP_NULL)
{
xp_awk_freerex (
((xp_awk_run_t*)run)->awk,
r->global.fs);
xp_awk_freerex (run->awk, run->global.fs);
}
r->global.fs = rex;
run->global.fs = rex;
}
if (val->type != XP_AWK_VAL_STR)
XP_AWK_FREE (((xp_awk_run_t*)run)->awk, fs_ptr);
if (val->type != XP_AWK_VAL_STR) XP_AWK_FREE (run->awk, fs_ptr);
}
else if (idx == XP_AWK_GLOBAL_IGNORECASE)
{
@ -313,11 +300,11 @@ int xp_awk_setglobal (void* run, xp_size_t idx, xp_awk_val_t* val)
(val->type == XP_AWK_VAL_STR &&
((xp_awk_val_str_t*)val)->len == 0))
{
((xp_awk_run_t*)run)->global.ignorecase = 0;
run->global.ignorecase = 0;
}
else
{
((xp_awk_run_t*)run)->global.ignorecase = 1;
run->global.ignorecase = 1;
}
}
else if (idx == XP_AWK_GLOBAL_NF)
@ -330,9 +317,9 @@ int xp_awk_setglobal (void* run, xp_size_t idx, xp_awk_val_t* val)
if (n == -1) return -1;
if (n == 1) lv = (xp_long_t)rv;
if (lv < r->inrec.nflds)
if (lv < run->inrec.nflds)
{
if (__shorten_record (r, (xp_size_t)lv) == -1) return -1;
if (__shorten_record (run, (xp_size_t)lv) == -1) return -1;
}
}
else if (idx == XP_AWK_GLOBAL_OFMT)
@ -344,8 +331,8 @@ int xp_awk_setglobal (void* run, xp_size_t idx, xp_awk_val_t* val)
run, val, xp_true, XP_NULL, &ofmt_len);
if (ofmt_ptr == XP_NULL) return -1;
r->global.ofmt.ptr = ofmt_ptr;
r->global.ofmt.len = ofmt_len;
run->global.ofmt.ptr = ofmt_ptr;
run->global.ofmt.len = ofmt_len;
}
else if (idx == XP_AWK_GLOBAL_OFS)
{
@ -356,8 +343,8 @@ int xp_awk_setglobal (void* run, xp_size_t idx, xp_awk_val_t* val)
run, val, xp_true, XP_NULL, &ofs_len);
if (ofs_ptr == XP_NULL) return -1;
r->global.ofs.ptr = ofs_ptr;
r->global.ofs.len = ofs_len;
run->global.ofs.ptr = ofs_ptr;
run->global.ofs.len = ofs_len;
}
else if (idx == XP_AWK_GLOBAL_ORS)
{
@ -368,8 +355,8 @@ int xp_awk_setglobal (void* run, xp_size_t idx, xp_awk_val_t* val)
run, val, xp_true, XP_NULL, &ors_len);
if (ors_ptr == XP_NULL) return -1;
r->global.ors.ptr = ors_ptr;
r->global.ors.len = ors_len;
run->global.ors.ptr = ors_ptr;
run->global.ors.len = ors_len;
}
else if (idx == XP_AWK_GLOBAL_RS)
{
@ -399,26 +386,22 @@ int xp_awk_setglobal (void* run, xp_size_t idx, xp_awk_val_t* val)
/* compile the regular expression */
/* TODO: use safebuild */
rex = xp_awk_buildrex (
((xp_awk_run_t*)run)->awk,
rs_ptr, rs_len, &r->errnum);
run->awk, rs_ptr, rs_len, &run->errnum);
if (rex == XP_NULL)
{
if (val->type != XP_AWK_VAL_STR)
XP_AWK_FREE (((xp_awk_run_t*)run)->awk, rs_ptr);
XP_AWK_FREE (run->awk, rs_ptr);
return -1;
}
if (r->global.rs != XP_NULL)
if (run->global.rs != XP_NULL)
{
xp_awk_freerex (
((xp_awk_run_t*)run)->awk,
r->global.rs);
xp_awk_freerex (run->awk, run->global.rs);
}
r->global.rs = rex;
run->global.rs = rex;
}
if (val->type != XP_AWK_VAL_STR)
XP_AWK_FREE (((xp_awk_run_t*)run)->awk, rs_ptr);
if (val->type != XP_AWK_VAL_STR) XP_AWK_FREE (run->awk, rs_ptr);
}
else if (idx == XP_AWK_GLOBAL_SUBSEP)
{
@ -429,28 +412,26 @@ int xp_awk_setglobal (void* run, xp_size_t idx, xp_awk_val_t* val)
run, val, xp_true, XP_NULL, &subsep_len);
if (subsep_ptr == XP_NULL) return -1;
r->global.subsep.ptr = subsep_ptr;
r->global.subsep.len = subsep_len;
run->global.subsep.ptr = subsep_ptr;
run->global.subsep.len = subsep_len;
}
xp_awk_refdownval (r, old);
STACK_GLOBAL(r,idx) = val;
xp_awk_refdownval (run, old);
STACK_GLOBAL(run,idx) = val;
xp_awk_refupval (val);
return 0;
}
void xp_awk_seterrnum (void* run, int errnum)
void xp_awk_seterrnum (xp_awk_run_t* run, int errnum)
{
xp_awk_run_t* r = (xp_awk_run_t*)run;
r->errnum = errnum;
run->errnum = errnum;
}
void xp_awk_setretval (void* run, xp_awk_val_t* val)
void xp_awk_setretval (xp_awk_run_t* run, xp_awk_val_t* val)
{
xp_awk_run_t* r = (xp_awk_run_t*)run;
xp_awk_refdownval (r, STACK_RETVAL(r));
STACK_RETVAL(r) = val;
xp_awk_refdownval (run, STACK_RETVAL(run));
STACK_RETVAL(run) = val;
/* should use the same trick as __run_return_statement */
xp_awk_refupval (val);
}
@ -509,7 +490,7 @@ int xp_awk_run (xp_awk_t* awk, xp_awk_runios_t* runios, xp_awk_runcbs_t* runcbs)
return n;
}
int xp_awk_stop (xp_awk_t* awk, void* run)
int xp_awk_stop (xp_awk_t* awk, xp_awk_run_t* run)
{
xp_awk_run_t* r;
int n = 0;
@ -554,7 +535,7 @@ void xp_awk_stopall (xp_awk_t* awk)
XP_AWK_UNLOCK (awk);
}
int xp_awk_getrunerrnum (xp_awk_t* awk, void* run, int* errnum)
int xp_awk_getrunerrnum (xp_awk_t* awk, xp_awk_run_t* run, int* errnum)
{
xp_awk_run_t* r;
int n = 0;
@ -624,8 +605,7 @@ static void __del_run (xp_awk_t* awk, xp_awk_run_t* run)
XP_AWK_UNLOCK (awk);
}
static int __init_run (
xp_awk_run_t* run, xp_awk_runios_t* runios, int* errnum)
static int __init_run (xp_awk_run_t* run, xp_awk_runios_t* runios, int* errnum)
{
run->stack = XP_NULL;
run->stack_top = 0;
@ -747,10 +727,10 @@ static void __deinit_run (xp_awk_run_t* run)
run->global.subsep.len = 0;
}
/* destroy input record. __clear_record should be called
/* destroy input record. xp_awk_clrrec should be called
* before the run stack has been destroyed because it may try
* to change the value to XP_AWK_GLOBAL_NF. */
__clear_record (run, xp_false);
xp_awk_clrrec (run, xp_false);
if (run->inrec.flds != XP_NULL)
{
XP_AWK_FREE (run->awk, run->inrec.flds);
@ -2445,7 +2425,7 @@ static xp_awk_val_t* __do_assignment_pos (
xp_real_t rv;
xp_char_t* str;
xp_size_t len;
int n, errnum;
int n;
/* get the position number */
v = __eval_expression (run, pos->val);
@ -2459,24 +2439,45 @@ static xp_awk_val_t* __do_assignment_pos (
if (n == 1) lv = (xp_long_t)rv;
if (!IS_VALID_POSIDX(lv)) PANIC (run, XP_AWK_EPOSIDX);
if (val->type == XP_AWK_VAL_STR)
{
str = ((xp_awk_val_str_t*)val)->buf;
len = ((xp_awk_val_str_t*)val)->len;
}
else
{
str = xp_awk_valtostr (run, val, xp_true, XP_NULL, &len);
if (str == XP_NULL) return XP_NULL;
}
n = xp_awk_setrec (run, (xp_size_t)lv, str, len);
if (val->type != XP_AWK_VAL_STR) XP_AWK_FREE (run->awk, str);
if (n == -1) return XP_NULL;
return (lv == 0)? run->inrec.d0: run->inrec.flds[lv-1].val;
#if 0
/* convert the value to the string */
str = xp_awk_valtostr (run, val, xp_true, XP_NULL, &len);
if (str == XP_NULL) return XP_NULL;
if (lv == 0)
{
if (__clear_record (run, xp_false) == -1)
if (xp_awk_clrrec (run, xp_false) == -1)
{
XP_AWK_FREE (run->awk, str);
if (val->type != XP_AWK_VAL_STR)
XP_AWK_FREE (run->awk, str);
return XP_NULL;
}
if (xp_awk_str_ncpy (&run->inrec.line, str, len) == (xp_size_t)-1)
{
XP_AWK_FREE (run->awk, str);
if (val->type != XP_AWK_VAL_STR)
XP_AWK_FREE (run->awk, str);
PANIC (run, XP_AWK_ENOMEM);
}
XP_AWK_FREE (run->awk, str);
if (val->type == XP_AWK_VAL_STR)
{
@ -2486,13 +2487,15 @@ static xp_awk_val_t* __do_assignment_pos (
}
else
{
XP_AWK_FREE (run->awk, str);
v = xp_awk_makestrval (
run,
XP_AWK_STR_BUF(&run->inrec.line),
XP_AWK_STR_LEN(&run->inrec.line));
if (v == XP_NULL)
{
__clear_record (run, xp_false);
xp_awk_clrrec (run, xp_false);
PANIC (run, XP_AWK_ENOMEM);
}
@ -2506,7 +2509,7 @@ static xp_awk_val_t* __do_assignment_pos (
if (__split_record (run) == -1)
{
errnum = run->errnum;
__clear_record (run, xp_false);
xp_awk_clrrec (run, xp_false);
run->errnum = errnum;
return XP_NULL;
}
@ -2517,7 +2520,7 @@ static xp_awk_val_t* __do_assignment_pos (
{
errnum = run->errnum;
XP_AWK_FREE (run->awk, str);
__clear_record (run, xp_false);
xp_awk_clrrec (run, xp_false);
run->errnum = errnum;
return XP_NULL;
}
@ -2530,7 +2533,7 @@ static xp_awk_val_t* __do_assignment_pos (
XP_AWK_STR_LEN(&run->inrec.line));
if (v == XP_NULL)
{
__clear_record (run, xp_false);
xp_awk_clrrec (run, xp_false);
PANIC (run, XP_AWK_ENOMEM);
}
@ -2543,6 +2546,7 @@ static xp_awk_val_t* __do_assignment_pos (
}
return val;
#endif
}
static xp_awk_val_t* __eval_binary (xp_awk_run_t* run, xp_awk_nde_t* nde)
@ -4726,8 +4730,8 @@ static xp_awk_val_t* __eval_getline (xp_awk_run_t* run, xp_awk_nde_t* nde)
if (p->var == XP_NULL)
{
/* set $0 with the input value */
if (xp_awk_setrecord (run,
XP_AWK_STR_BUF(&buf),
if (xp_awk_setrec (run, 0,
XP_AWK_STR_BUF(&buf),
XP_AWK_STR_LEN(&buf)) == -1)
{
xp_awk_str_close (&buf);
@ -4742,12 +4746,10 @@ static xp_awk_val_t* __eval_getline (xp_awk_run_t* run, xp_awk_nde_t* nde)
v = xp_awk_makestrval (
run, XP_AWK_STR_BUF(&buf), XP_AWK_STR_LEN(&buf));
xp_awk_str_close (&buf);
if (v == XP_NULL) PANIC (run, XP_AWK_ENOMEM);
xp_awk_refupval (v);
if (__do_assignment(run, p->var, v) == XP_NULL)
{
xp_awk_refdownval (run, v);
@ -4762,7 +4764,7 @@ static xp_awk_val_t* __eval_getline (xp_awk_run_t* run, xp_awk_nde_t* nde)
}
skip_read:
res = xp_awk_makeintval (run, n);
res = xp_awk_makeintval (run, n);
if (res == XP_NULL) PANIC (run, XP_AWK_ENOMEM);
return res;
@ -4816,14 +4818,14 @@ static int __read_record (xp_awk_run_t* run)
{
xp_ssize_t n;
if (__clear_record (run, xp_false) == -1) return -1;
if (xp_awk_clrrec (run, xp_false) == -1) return -1;
n = xp_awk_readextio (
run, XP_AWK_IN_CONSOLE, XP_T(""), &run->inrec.line);
if (n < 0)
{
int errnum = run->errnum;
__clear_record (run, xp_false);
xp_awk_clrrec (run, xp_false);
run->errnum =
(errnum == XP_AWK_EIOHANDLER)?
XP_AWK_ECONINDATA: errnum;
@ -4835,441 +4837,13 @@ static int __read_record (xp_awk_run_t* run)
return 0;
}
if (__set_record (run,
if (xp_awk_setrec (run, 0,
XP_AWK_STR_BUF(&run->inrec.line),
XP_AWK_STR_LEN(&run->inrec.line)) == -1) return -1;
return 1;
}
int xp_awk_setrecord (void* run, const xp_char_t* str, xp_size_t len)
{
xp_awk_run_t* r = (xp_awk_run_t*)run;
if (__clear_record (r, xp_false) == -1) return -1;
if (xp_awk_str_ncpy (&r->inrec.line, str, len) == (xp_size_t)-1)
{
__clear_record (run, xp_false);
r->errnum = XP_AWK_ENOMEM;
return -1;
}
return __set_record (run, str, len);
}
int xp_awk_setfield (
void* run, xp_size_t idx, const xp_char_t* str, xp_size_t len)
{
xp_awk_run_t* r = (xp_awk_run_t*)run;
xp_awk_val_t* v;
int errnum;
if (!IS_VALID_POSIDX(idx))
{
r->errnum = XP_AWK_EPOSIDX;
return -1;
}
if (idx == 0) return xp_awk_setrecord (run, str, len);
if (__recomp_record_fields (r, idx, str, len) == -1)
{
errnum = r->errnum;
__clear_record (r, xp_false);
r->errnum = errnum;
return -1;
}
/* recompose $0 */
v = xp_awk_makestrval (r,
XP_AWK_STR_BUF(&r->inrec.line),
XP_AWK_STR_LEN(&r->inrec.line));
if (v == XP_NULL)
{
__clear_record (run, xp_false);
r->errnum = XP_AWK_ENOMEM;
return -1;
}
xp_awk_refdownval (run, r->inrec.d0);
r->inrec.d0 = v;
xp_awk_refupval (v);
return 0;
}
static int __set_record (
xp_awk_run_t* run, const xp_char_t* str, xp_size_t len)
{
xp_awk_val_t* v;
int errnum;
v = xp_awk_makestrval (run, str, len);
if (v == XP_NULL)
{
__clear_record (run, xp_false);
PANIC_I (run, XP_AWK_ENOMEM);
}
xp_assert (run->inrec.d0->type == XP_AWK_VAL_NIL);
/* the record should be clear cleared before this function is called
* as it doesn't call xp_awk_refdownval on run->inrec.d0 */
run->inrec.d0 = v;
xp_awk_refupval (v);
if (__split_record (run) == -1)
{
errnum = run->errnum;
__clear_record (run, xp_false);
run->errnum = errnum;
return -1;
}
return 0; /* success */
}
static int __split_record (xp_awk_run_t* run)
{
xp_char_t* p, * tok;
xp_size_t len, tok_len, nflds;
xp_awk_val_t* v, * fs;
xp_char_t* fs_ptr, * fs_free;
xp_size_t fs_len;
int errnum;
/* inrec should be cleared before __split_record is called */
xp_assert (run->inrec.nflds == 0);
/* get FS */
fs = xp_awk_getglobal (run, XP_AWK_GLOBAL_FS);
if (fs->type == XP_AWK_VAL_NIL)
{
fs_ptr = XP_T(" ");
fs_len = 1;
fs_free = XP_NULL;
}
else if (fs->type == XP_AWK_VAL_STR)
{
fs_ptr = ((xp_awk_val_str_t*)fs)->buf;
fs_len = ((xp_awk_val_str_t*)fs)->len;
fs_free = XP_NULL;
}
else
{
fs_ptr = xp_awk_valtostr (
run, fs, xp_true, XP_NULL, &fs_len);
if (fs_ptr == XP_NULL) return -1;
fs_free = fs_ptr;
}
/* scan the input record to count the fields */
p = XP_AWK_STR_BUF(&run->inrec.line);
len = XP_AWK_STR_LEN(&run->inrec.line);
nflds = 0;
while (p != XP_NULL)
{
if (fs_len <= 1)
{
p = xp_awk_strxntok (run,
p, len, fs_ptr, fs_len, &tok, &tok_len);
}
else
{
p = xp_awk_strxntokbyrex (run, p, len,
run->global.fs, &tok, &tok_len, &errnum);
if (p == XP_NULL && errnum != XP_AWK_ENOERR)
{
if (fs_free != XP_NULL)
XP_AWK_FREE (run->awk, fs_free);
PANIC_I (run, errnum);
}
}
if (nflds == 0 && p == XP_NULL && tok_len == 0)
{
/* there are no fields. it can just return here
* as __clear_record has been called before this */
if (fs_free != XP_NULL) XP_AWK_FREE (run->awk, fs_free);
return 0;
}
xp_assert ((tok != XP_NULL && tok_len > 0) || tok_len == 0);
nflds++;
len = XP_AWK_STR_LEN(&run->inrec.line) -
(p - XP_AWK_STR_BUF(&run->inrec.line));
}
/* allocate space */
if (nflds > run->inrec.maxflds)
{
void* tmp = XP_AWK_MALLOC (
run->awk, xp_sizeof(*run->inrec.flds) * nflds);
if (tmp == XP_NULL)
{
if (fs_free != XP_NULL) XP_AWK_FREE (run->awk, fs_free);
PANIC_I (run, XP_AWK_ENOMEM);
}
if (run->inrec.flds != XP_NULL)
XP_AWK_FREE (run->awk, run->inrec.flds);
run->inrec.flds = tmp;
run->inrec.maxflds = nflds;
}
/* scan again and split it */
p = XP_AWK_STR_BUF(&run->inrec.line);
len = XP_AWK_STR_LEN(&run->inrec.line);
while (p != XP_NULL)
{
if (fs_len <= 1)
{
p = xp_awk_strxntok (
run, p, len, fs_ptr, fs_len, &tok, &tok_len);
}
else
{
p = xp_awk_strxntokbyrex (run, p, len,
run->global.fs, &tok, &tok_len, &errnum);
if (p == XP_NULL && errnum != XP_AWK_ENOERR)
{
if (fs_free != XP_NULL)
XP_AWK_FREE (run->awk, fs_free);
PANIC_I (run, errnum);
}
}
xp_assert ((tok != XP_NULL && tok_len > 0) || tok_len == 0);
run->inrec.flds[run->inrec.nflds].ptr = tok;
run->inrec.flds[run->inrec.nflds].len = tok_len;
run->inrec.flds[run->inrec.nflds].val =
xp_awk_makestrval (run, tok, tok_len);
if (run->inrec.flds[run->inrec.nflds].val == XP_NULL)
{
if (fs_free != XP_NULL) XP_AWK_FREE (run->awk, fs_free);
PANIC_I (run, XP_AWK_ENOMEM);
}
xp_awk_refupval (run->inrec.flds[run->inrec.nflds].val);
run->inrec.nflds++;
len = XP_AWK_STR_LEN(&run->inrec.line) -
(p - XP_AWK_STR_BUF(&run->inrec.line));
}
if (fs_free != XP_NULL) XP_AWK_FREE (run->awk, fs_free);
/* set the number of fields */
v = xp_awk_makeintval (run, (xp_long_t)nflds);
if (v == XP_NULL) PANIC_I (run, XP_AWK_ENOMEM);
if (xp_awk_setglobal (run, XP_AWK_GLOBAL_NF, v) == -1) return -1;
xp_assert (nflds == run->inrec.nflds);
return 0;
}
static int __clear_record (xp_awk_run_t* run, xp_bool_t noline)
{
xp_size_t i;
int n = 0;
xp_awk_refdownval (run, run->inrec.d0);
run->inrec.d0 = xp_awk_val_nil;
if (run->inrec.nflds > 0)
{
xp_assert (run->inrec.flds != XP_NULL);
for (i = 0; i < run->inrec.nflds; i++)
{
xp_assert (run->inrec.flds[i].val != XP_NULL);
xp_awk_refdownval (run, run->inrec.flds[i].val);
}
run->inrec.nflds = 0;
if (xp_awk_setglobal (
run, XP_AWK_GLOBAL_NF, xp_awk_val_zero) == -1)
{
/* first of all, this should never happen.
* if it happened, it would return an error
* after all the clearance tasks */
n = -1;
}
}
xp_assert (run->inrec.nflds == 0);
if (!noline) xp_awk_str_clear (&run->inrec.line);
return n;
}
static int __recomp_record_fields (
xp_awk_run_t* run, xp_size_t lv,
const xp_char_t* str, xp_size_t len)
{
xp_awk_val_t* v;
xp_size_t max, i, nflds;
/* recomposes the record and the fields when $N has been assigned
* a new value and recomputes NF accordingly */
xp_assert (lv > 0);
max = (lv > run->inrec.nflds)? lv: run->inrec.nflds;
nflds = run->inrec.nflds;
if (max > run->inrec.maxflds)
{
void* tmp;
/* if the given field number is greater than the maximum
* number of fields that the current record can hold,
* the field spaces are resized */
if (run->awk->syscas->realloc != XP_NULL)
{
tmp = XP_AWK_REALLOC (
run->awk, run->inrec.flds,
xp_sizeof(*run->inrec.flds) * max);
if (tmp == XP_NULL)
{
run->errnum = XP_AWK_ENOMEM;
return -1;
}
}
else
{
tmp = XP_AWK_MALLOC (
run->awk, xp_sizeof(*run->inrec.flds) * max);
if (tmp == XP_NULL)
{
run->errnum = XP_AWK_ENOMEM;
return -1;
}
if (run->inrec.flds != XP_NULL)
{
XP_AWK_MEMCPY (run->awk, tmp, run->inrec.flds,
xp_sizeof(*run->inrec.flds) * run->inrec.maxflds);
XP_AWK_FREE (run->awk, run->inrec.flds);
}
}
run->inrec.flds = tmp;
run->inrec.maxflds = max;
}
lv = lv - 1; /* adjust the value to 0-based index */
xp_awk_str_clear (&run->inrec.line);
for (i = 0; i < max; i++)
{
if (i > 0)
{
if (xp_awk_str_ncat (
&run->inrec.line,
run->global.ofs.ptr,
run->global.ofs.len) == (xp_size_t)-1)
{
run->errnum = XP_AWK_ENOMEM;
return -1;
}
}
if (i == lv)
{
xp_awk_val_t* tmp;
run->inrec.flds[i].ptr =
XP_AWK_STR_BUF(&run->inrec.line) +
XP_AWK_STR_LEN(&run->inrec.line);
run->inrec.flds[i].len = len;
if (xp_awk_str_ncat (
&run->inrec.line, str, len) == (xp_size_t)-1)
{
run->errnum = XP_AWK_ENOMEM;
return -1;
}
tmp = xp_awk_makestrval (run, str,len);
if (tmp == XP_NULL)
{
run->errnum = XP_AWK_ENOMEM;
return -1;
}
if (i < nflds)
xp_awk_refdownval (run, run->inrec.flds[i].val);
else run->inrec.nflds++;
run->inrec.flds[i].val = tmp;
xp_awk_refupval (tmp);
}
else if (i >= nflds)
{
run->inrec.flds[i].ptr =
XP_AWK_STR_BUF(&run->inrec.line) +
XP_AWK_STR_LEN(&run->inrec.line);
run->inrec.flds[i].len = 0;
if (xp_awk_str_cat (
&run->inrec.line, XP_T("")) == (xp_size_t)-1)
{
run->errnum = XP_AWK_ENOMEM;
return -1;
}
/* xp_awk_refdownval should not be called over
* run->inrec.flds[i].val as it is not initialized
* to any valid values */
/*xp_awk_refdownval (run, run->inrec.flds[i].val);*/
run->inrec.flds[i].val = xp_awk_val_zls;
xp_awk_refupval (xp_awk_val_zls);
run->inrec.nflds++;
}
else
{
xp_awk_val_str_t* tmp;
tmp = (xp_awk_val_str_t*)run->inrec.flds[i].val;
run->inrec.flds[i].ptr =
XP_AWK_STR_BUF(&run->inrec.line) +
XP_AWK_STR_LEN(&run->inrec.line);
run->inrec.flds[i].len = tmp->len;
if (xp_awk_str_ncat (&run->inrec.line,
tmp->buf, tmp->len) == (xp_size_t)-1)
{
run->errnum = XP_AWK_ENOMEM;
return -1;
}
}
}
v = STACK_GLOBAL(run, XP_AWK_GLOBAL_NF);
xp_assert (v->type == XP_AWK_VAL_INT);
if (((xp_awk_val_int_t*)v)->val != max)
{
v = xp_awk_makeintval (run, (xp_long_t)max);
if (v == XP_NULL)
{
run->errnum = XP_AWK_ENOMEM;
return -1;
}
if (xp_awk_setglobal (
run, XP_AWK_GLOBAL_NF, v) == -1) return -1;
}
return 0;
}
static int __shorten_record (xp_awk_run_t* run, xp_size_t nflds)
{
xp_awk_val_t* v;