diff --git a/ase/awk/descrip.mms b/ase/awk/descrip.mms index 8ded2483..ccbcc6e9 100644 --- a/ase/awk/descrip.mms +++ b/ase/awk/descrip.mms @@ -1,4 +1,4 @@ -objects = awk.obj,err.obj,extio.obj,func.obj,map.obj,misc.obj,parse.obj,rex.obj,run.obj,sa.obj,tab.obj,tree.obj,val.obj +objects = awk.obj,err.obj,extio.obj,func.obj,map.obj,misc.obj,parse.obj,rex.obj,run.obj,rec.obj,sa.obj,tab.obj,tree.obj,val.obj CFLAGS = /pointer_size=long /define=XP_AWK_STAND_ALONE LIBRFLAGS = @@ -16,6 +16,7 @@ misc.obj depends_on misc.c parse.obj depends_on parse.c rex.obj depends_on rex.c run.obj depends_on run.c +rec.obj depends_on rec.c sa.obj depends_on sa.c tab.obj depends_on tab.c tree.obj depends_on tree.c diff --git a/ase/awk/makefile.ntddk b/ase/awk/makefile.ntddk deleted file mode 100644 index 5acbbd24..00000000 --- a/ase/awk/makefile.ntddk +++ /dev/null @@ -1 +0,0 @@ -!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/ase/awk/rec.c b/ase/awk/rec.c new file mode 100644 index 00000000..32ad6014 --- /dev/null +++ b/ase/awk/rec.c @@ -0,0 +1,440 @@ +/* + * $Id: rec.c,v 1.1 2006-10-03 14:57:01 bacon Exp $ + */ + +#include + +static int __split_record (xp_awk_run_t* run); +static int __recomp_record_fields ( + xp_awk_run_t* run, xp_size_t lv, + const xp_char_t* str, xp_size_t len); + +int xp_awk_setrec ( + xp_awk_run_t* run, xp_size_t idx, const xp_char_t* str, xp_size_t len) +{ + xp_awk_val_t* v; + int errnum; + + if (idx == 0) + { + if (str == XP_AWK_STR_BUF(&run->inrec.line) && + len == XP_AWK_STR_LEN(&run->inrec.line)) + { + if (xp_awk_clrrec (run, xp_true) == -1) return -1; + } + else + { + if (xp_awk_clrrec (run, xp_false) == -1) return -1; + + if (xp_awk_str_ncpy (&run->inrec.line, str, len) == (xp_size_t)-1) + { + xp_awk_clrrec (run, xp_false); + run->errnum = XP_AWK_ENOMEM; + return -1; + } + } + + v = xp_awk_makestrval (run, str, len); + if (v == XP_NULL) + { + xp_awk_clrrec (run, xp_false); + run->errnum = XP_AWK_ENOMEM; + return -1; + } + + xp_assert (run->inrec.d0->type == XP_AWK_VAL_NIL); + /* d0 should be cleared before the next line is reached + * 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; + xp_awk_clrrec (run, xp_false); + run->errnum = errnum; + return -1; + } + } + else + { + if (__recomp_record_fields (run, idx, str, len) == -1) + { + errnum = run->errnum; + xp_awk_clrrec (run, xp_false); + run->errnum = errnum; + return -1; + } + + /* recompose $0 */ + v = xp_awk_makestrval (run, + XP_AWK_STR_BUF(&run->inrec.line), + XP_AWK_STR_LEN(&run->inrec.line)); + if (v == XP_NULL) + { + xp_awk_clrrec (run, xp_false); + run->errnum = XP_AWK_ENOMEM; + return -1; + } + + xp_awk_refdownval (run, run->inrec.d0); + run->inrec.d0 = v; + xp_awk_refupval (v); + } + + return 0; +} + +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); + run->errnum = errnum; + return -1; + } + } + + if (nflds == 0 && p == XP_NULL && tok_len == 0) + { + /* there are no fields. it can just return here + * as xp_awk_clrrec 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); + run->errnum = XP_AWK_ENOMEM; + return -1; + } + + 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); + run->errnum = errnum; + return -1; + } + } + + 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); + run->errnum = XP_AWK_ENOMEM; + return -1; + } + + 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) + { + run->errnum = XP_AWK_ENOMEM; + return -1; + } + + if (xp_awk_setglobal (run, XP_AWK_GLOBAL_NF, v) == -1) return -1; + + xp_assert (nflds == run->inrec.nflds); + return 0; +} + +int xp_awk_clrrec (xp_awk_run_t* run, xp_bool_t skip_inrec_line) +{ + xp_size_t i; + int n = 0; + + if (run->inrec.d0 != xp_awk_val_nil) + { + 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 (!skip_inrec_line) 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 = xp_awk_getglobal (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; +} + diff --git a/ase/awk/sources b/ase/awk/sources deleted file mode 100644 index cbfb8a1c..00000000 --- a/ase/awk/sources +++ /dev/null @@ -1,8 +0,0 @@ -TARGETNAME=xpawk -TARGETPATH=obj -TARGETTYPE=DRIVER_LIBRARY - -SOURCES=rex.c err.c - -C_DEFINES=-D_UNICODE -DXP_AWK_STAND_ALONE -DXP_AWK_NTDDK -INCLUDES=..\.. diff --git a/ase/test/awk/t11.awk b/ase/test/awk/t11.awk index 28b56773..b78f07e4 100644 --- a/ase/test/awk/t11.awk +++ b/ase/test/awk/t11.awk @@ -1,5 +1,4 @@ -BEGIN -{ +BEGIN { print "this is only a test"; print; print 1, 2, (3 >> 10);