From 632a2a0a529fbffa17f4f531d3c6de1073845d7a Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Wed, 16 Jan 2008 21:46:08 +0000 Subject: [PATCH] --- ase/awk/awk_i.h | 13 ++-- ase/awk/run.c | 179 ++++++++++++++++++++++++++++++++---------------- ase/awk/val.c | 149 ++++++++++++++++++++++++++++++++++------ ase/awk/val.h | 3 +- 4 files changed, 255 insertions(+), 89 deletions(-) diff --git a/ase/awk/awk_i.h b/ase/awk/awk_i.h index 95e62e20..73d5b928 100644 --- a/ase/awk/awk_i.h +++ b/ase/awk/awk_i.h @@ -244,19 +244,20 @@ struct ase_awk_run_t ase_size_t stack_limit; int exit_level; - ase_awk_val_int_t* icache[128]; - ase_awk_val_real_t* rcache[128]; ase_awk_val_ref_t* fcache[128]; /*ase_awk_val_str_t* scache32[128]; ase_awk_val_str_t* scache64[128];*/ - ase_size_t icache_count; - ase_size_t rcache_count; ase_size_t fcache_count; /*ase_size_t scache32_count; ase_size_t scache64_count;*/ - ase_awk_val_int_t* ifree; - ase_awk_val_chunk_t* ichunk; + struct + { + ase_awk_val_int_t* ifree; + ase_awk_val_chunk_t* ichunk; + ase_awk_val_real_t* rfree; + ase_awk_val_chunk_t* rchunk; + } vmgr; ase_awk_nde_blk_t* active_block; ase_byte_t* pattern_range_state; diff --git a/ase/awk/run.c b/ase/awk/run.c index 52143343..ff3e7a25 100644 --- a/ase/awk/run.c +++ b/ase/awk/run.c @@ -14,6 +14,8 @@ #define DEF_BUF_CAPA 256 #define STACK_INCREMENT 512 +#define IDXBUFSIZE 64 + #define STACK_AT(run,n) ((run)->stack[(run)->stack_base+(n)]) #define STACK_NARGS(run) (STACK_AT(run,3)) #define STACK_ARG(run,n) STACK_AT(run,3+1+(n)) @@ -214,7 +216,7 @@ static int read_record (ase_awk_run_t* run); static int shorten_record (ase_awk_run_t* run, ase_size_t nflds); static ase_char_t* idxnde_to_str ( - ase_awk_run_t* run, ase_awk_nde_t* nde, ase_size_t* len); + ase_awk_run_t* run, ase_awk_nde_t* nde, ase_char_t* buf, ase_size_t* len); typedef ase_awk_val_t* (*binop_func_t) ( ase_awk_run_t* run, ase_awk_val_t* left, ase_awk_val_t* right); @@ -742,13 +744,13 @@ static int init_run ( run->exit_level = EXIT_NONE; - run->icache_count = 0; - run->rcache_count = 0; run->fcache_count = 0; /*run->scache32_count = 0; run->scache64_count = 0;*/ - run->ichunk = ASE_NULL; - run->ifree = ASE_NULL; + run->vmgr.ichunk = ASE_NULL; + run->vmgr.ifree = ASE_NULL; + run->vmgr.rchunk = ASE_NULL; + run->vmgr.rfree = ASE_NULL; run->errnum = ASE_AWK_ENOERR; run->errlin = 0; @@ -949,18 +951,6 @@ static void deinit_run (ase_awk_run_t* run) ase_awk_map_close (run->named); /* destroy values in free list */ - while (run->icache_count > 0) - { - ase_awk_val_int_t* tmp = run->icache[--run->icache_count]; - ase_awk_freeval (run, (ase_awk_val_t*)tmp, ase_false); - } - - while (run->rcache_count > 0) - { - ase_awk_val_real_t* tmp = run->rcache[--run->rcache_count]; - ase_awk_freeval (run, (ase_awk_val_t*)tmp, ase_false); - } - while (run->fcache_count > 0) { ase_awk_val_ref_t* tmp = run->fcache[--run->fcache_count]; @@ -979,11 +969,18 @@ static void deinit_run (ase_awk_run_t* run) ase_awk_freeval (run, (ase_awk_val_t*)tmp, ase_false); }*/ - while (run->ichunk != ASE_NULL) + while (run->vmgr.ichunk != ASE_NULL) { - ase_awk_val_chunk_t* next = run->ichunk->next; - ASE_AWK_FREE (run->awk, run->ichunk); - run->ichunk = next; + ase_awk_val_chunk_t* next = run->vmgr.ichunk->next; + ASE_AWK_FREE (run->awk, run->vmgr.ichunk); + run->vmgr.ichunk = next; + } + + while (run->vmgr.rchunk != ASE_NULL) + { + ase_awk_val_chunk_t* next = run->vmgr.rchunk->next; + ASE_AWK_FREE (run->awk, run->vmgr.rchunk); + run->vmgr.rchunk = next; } } @@ -2516,8 +2513,9 @@ static int run_delete (ase_awk_run_t* run, ase_awk_nde_delete_t* nde) if (var->type == ASE_AWK_NDE_NAMEDIDX) { ase_char_t* key; - ase_size_t key_len; + ase_size_t keylen; ase_awk_val_t* idx; + ase_char_t buf[IDXBUFSIZE]; ASE_ASSERT (var->idx != ASE_NULL); @@ -2525,9 +2523,20 @@ static int run_delete (ase_awk_run_t* run, ase_awk_nde_delete_t* nde) if (idx == ASE_NULL) return -1; ase_awk_refupval (run, idx); + + /* try with a fixed-size buffer */ + keylen = ASE_COUNTOF(buf); key = ase_awk_valtostr ( - run, idx, ASE_AWK_VALTOSTR_CLEAR, - ASE_NULL, &key_len); + run, idx, ASE_AWK_VALTOSTR_FIXED, + (ase_str_t*)buf, &keylen); + if (key == ASE_NULL) + { + /* if it doesn't work, switch to dynamic mode */ + key = ase_awk_valtostr ( + run, idx, ASE_AWK_VALTOSTR_CLEAR, + ASE_NULL, &keylen); + } + ase_awk_refdownval (run, idx); if (key == ASE_NULL) @@ -2537,8 +2546,8 @@ static int run_delete (ase_awk_run_t* run, ase_awk_nde_delete_t* nde) return -1; } - ase_awk_map_remove (map, key, key_len); - ASE_AWK_FREE (run->awk, key); + ase_awk_map_remove (map, key, keylen); + if (key != buf) ASE_AWK_FREE (run->awk, key); } else { @@ -2630,8 +2639,9 @@ static int run_delete (ase_awk_run_t* run, ase_awk_nde_delete_t* nde) var->type == ASE_AWK_NDE_ARGIDX) { ase_char_t* key; - ase_size_t key_len; + ase_size_t keylen; ase_awk_val_t* idx; + ase_char_t buf[IDXBUFSIZE]; ASE_ASSERT (var->idx != ASE_NULL); @@ -2639,9 +2649,20 @@ static int run_delete (ase_awk_run_t* run, ase_awk_nde_delete_t* nde) if (idx == ASE_NULL) return -1; ase_awk_refupval (run, idx); + + /* try with a fixed-size buffer */ + keylen = ASE_COUNTOF(buf); key = ase_awk_valtostr ( - run, idx, ASE_AWK_VALTOSTR_CLEAR, - ASE_NULL, &key_len); + run, idx, ASE_AWK_VALTOSTR_FIXED, + (ase_str_t*)buf, &keylen); + if (key == ASE_NULL) + { + /* if it doesn't work, switch to dynamic mode */ + key = ase_awk_valtostr ( + run, idx, ASE_AWK_VALTOSTR_CLEAR, + ASE_NULL, &keylen); + } + ase_awk_refdownval (run, idx); if (key == ASE_NULL) @@ -2649,9 +2670,8 @@ static int run_delete (ase_awk_run_t* run, ase_awk_nde_delete_t* nde) run->errlin = var->line; return -1; } - - ase_awk_map_remove (map, key, key_len); - ASE_AWK_FREE (run->awk, key); + ase_awk_map_remove (map, key, keylen); + if (key != buf) ASE_AWK_FREE (run->awk, key); } else { @@ -3398,6 +3418,7 @@ static ase_awk_val_t* do_assignment_map ( ase_awk_val_map_t* map; ase_char_t* str; ase_size_t len; + ase_char_t idxbuf[IDXBUFSIZE]; int n; ASE_ASSERT ( @@ -3492,8 +3513,13 @@ static ase_awk_val_t* do_assignment_map ( return ASE_NULL; } - str = idxnde_to_str (run, var->idx, &len); - if (str == ASE_NULL) return ASE_NULL; + len = ASE_COUNTOF(idxbuf); + str = idxnde_to_str (run, var->idx, idxbuf, &len); + if (str == ASE_NULL) + { + str = idxnde_to_str (run, var->idx, ASE_NULL, &len); + if (str == ASE_NULL) return ASE_NULL; + } #ifdef DEBUG_RUN ase_dprintf (ASE_T("**** index str=>%s, map->ref=%d, map->type=%d\n"), @@ -3503,12 +3529,12 @@ static ase_awk_val_t* do_assignment_map ( n = ase_awk_map_putx (map->map, str, len, val, ASE_NULL); if (n < 0) { - ASE_AWK_FREE (run->awk, str); + if (str != idxbuf) ASE_AWK_FREE (run->awk, str); ase_awk_setrunerror (run, ASE_AWK_ENOMEM, var->line, ASE_NULL, 0); return ASE_NULL; } - ASE_AWK_FREE (run->awk, str); + if (str != idxbuf) ASE_AWK_FREE (run->awk, str); ase_awk_refupval (run, val); return val; } @@ -3773,6 +3799,7 @@ static ase_awk_val_t* eval_binop_in ( ase_awk_val_t* rv; ase_char_t* str; ase_size_t len; + ase_char_t idxbuf[IDXBUFSIZE]; if (right->type != ASE_AWK_NDE_GLOBAL && right->type != ASE_AWK_NDE_LOCAL && @@ -3789,17 +3816,24 @@ static ase_awk_val_t* eval_binop_in ( } /* evaluate the left-hand side of the operator */ + len = ASE_COUNTOF(idxbuf); str = (left->type == ASE_AWK_NDE_GRP)? - idxnde_to_str (run, ((ase_awk_nde_grp_t*)left)->body, &len): - idxnde_to_str (run, left, &len); - if (str == ASE_NULL) return ASE_NULL; + idxnde_to_str (run, ((ase_awk_nde_grp_t*)left)->body, idxbuf, &len): + idxnde_to_str (run, left, idxbuf, &len); + if (str == ASE_NULL) + { + str = (left->type == ASE_AWK_NDE_GRP)? + idxnde_to_str (run, ((ase_awk_nde_grp_t*)left)->body, ASE_NULL, &len): + idxnde_to_str (run, left, ASE_NULL, &len); + if (str == ASE_NULL) return ASE_NULL; + } /* evaluate the right-hand side of the operator */ ASE_ASSERT (right->next == ASE_NULL); rv = eval_expression (run, right); if (rv == ASE_NULL) { - ASE_AWK_FREE (run->awk, str); + if (str != idxbuf) ASE_AWK_FREE (run->awk, str); return ASE_NULL; } @@ -3807,7 +3841,7 @@ static ase_awk_val_t* eval_binop_in ( if (rv->type == ASE_AWK_VAL_NIL) { - ASE_AWK_FREE (run->awk, str); + if (str != idxbuf) ASE_AWK_FREE (run->awk, str); ase_awk_refdownval (run, rv); return ase_awk_val_zero; } @@ -3820,13 +3854,13 @@ static ase_awk_val_t* eval_binop_in ( res = (ase_awk_map_get (map, str, len) == ASE_NULL)? ase_awk_val_zero: ase_awk_val_one; - ASE_AWK_FREE (run->awk, str); + if (str != idxbuf) ASE_AWK_FREE (run->awk, str); ase_awk_refdownval (run, rv); return res; } /* need a map */ - ASE_AWK_FREE (run->awk, str); + if (str != idxbuf) ASE_AWK_FREE (run->awk, str); ase_awk_refdownval (run, rv); ase_awk_setrunerror (run, ASE_AWK_ENOTMAPNILIN, right->line, ASE_NULL, 0); @@ -5839,6 +5873,7 @@ static ase_awk_val_t** get_reference_indexed ( ase_awk_pair_t* pair; ase_char_t* str; ase_size_t len; + ase_char_t idxbuf[IDXBUFSIZE]; ASE_ASSERT (val != ASE_NULL); @@ -5866,8 +5901,13 @@ static ase_awk_val_t** get_reference_indexed ( ASE_ASSERT (nde->idx != ASE_NULL); - str = idxnde_to_str (run, nde->idx, &len); - if (str == ASE_NULL) return ASE_NULL; + len = ASE_COUNTOF(idxbuf); + str = idxnde_to_str (run, nde->idx, idxbuf, &len); + if (str == ASE_NULL) + { + str = idxnde_to_str (run, nde->idx, ASE_NULL, &len); + if (str == ASE_NULL) return ASE_NULL; + } pair = ase_awk_map_get ((*(ase_awk_val_map_t**)val)->map, str, len); if (pair == ASE_NULL) @@ -5877,7 +5917,7 @@ static ase_awk_val_t** get_reference_indexed ( str, len, ase_awk_val_nil); if (pair == ASE_NULL) { - ASE_AWK_FREE (run->awk, str); + if (str != idxbuf) ASE_AWK_FREE (run->awk, str); ase_awk_setrunerror ( run, ASE_AWK_ENOMEM, nde->line, ASE_NULL, 0); return ASE_NULL; @@ -5886,7 +5926,7 @@ static ase_awk_val_t** get_reference_indexed ( ase_awk_refupval (run, pair->val); } - ASE_AWK_FREE (run->awk, str); + if (str != idxbuf) ASE_AWK_FREE (run->awk, str); return (ase_awk_val_t**)&pair->val; } @@ -5985,6 +6025,7 @@ static ase_awk_val_t* eval_indexed ( ase_awk_pair_t* pair; ase_char_t* str; ase_size_t len; + ase_char_t idxbuf[IDXBUFSIZE]; ASE_ASSERT (val != ASE_NULL); @@ -6012,11 +6053,16 @@ static ase_awk_val_t* eval_indexed ( ASE_ASSERT (nde->idx != ASE_NULL); - str = idxnde_to_str (run, nde->idx, &len); - if (str == ASE_NULL) return ASE_NULL; + len = ASE_COUNTOF(idxbuf); + str = idxnde_to_str (run, nde->idx, idxbuf, &len); + if (str == ASE_NULL) + { + str = idxnde_to_str (run, nde->idx, ASE_NULL, &len); + if (str == ASE_NULL) return ASE_NULL; + } pair = ase_awk_map_get ((*(ase_awk_val_map_t**)val)->map, str, len); - ASE_AWK_FREE (run->awk, str); + if (str != idxbuf) ASE_AWK_FREE (run->awk, str); return (pair == ASE_NULL)? ase_awk_val_nil: (ase_awk_val_t*)pair->val; } @@ -6397,7 +6443,7 @@ static int shorten_record (ase_awk_run_t* run, ase_size_t nflds) } static ase_char_t* idxnde_to_str ( - ase_awk_run_t* run, ase_awk_nde_t* nde, ase_size_t* len) + ase_awk_run_t* run, ase_awk_nde_t* nde, ase_char_t* buf, ase_size_t* len) { ase_char_t* str; ase_awk_val_t* idx; @@ -6412,14 +6458,28 @@ static ase_char_t* idxnde_to_str ( ase_awk_refupval (run, idx); - str = ase_awk_valtostr ( - run, idx, ASE_AWK_VALTOSTR_CLEAR, ASE_NULL, len); - if (str == ASE_NULL) + str = ASE_NULL; + + if (buf != ASE_NULL) { - ase_awk_refdownval (run, idx); - /* change error line */ - run->errlin = nde->line; - return ASE_NULL; + /* try with a fixed-size buffer */ + str = ase_awk_valtostr ( + run, idx, ASE_AWK_VALTOSTR_FIXED, (ase_str_t*)buf, len); + } + + if (str == ASE_NULL) + { + /* if it doen't work, switch to the dynamic mode */ + str = ase_awk_valtostr ( + run, idx, ASE_AWK_VALTOSTR_CLEAR, ASE_NULL, len); + + if (str == ASE_NULL) + { + ase_awk_refdownval (run, idx); + /* change error line */ + run->errlin = nde->line; + return ASE_NULL; + } } ase_awk_refdownval (run, idx); @@ -6430,8 +6490,7 @@ static ase_char_t* idxnde_to_str ( ase_str_t idxstr; if (ase_str_open ( - &idxstr, - DEF_BUF_CAPA, + &idxstr, DEF_BUF_CAPA, &run->awk->prmfns.mmgr) == ASE_NULL) { ase_awk_setrunerror ( diff --git a/ase/awk/val.c b/ase/awk/val.c index 1e2fcae1..d1576491 100644 --- a/ase/awk/val.c +++ b/ase/awk/val.c @@ -10,6 +10,8 @@ #include #endif +#define CHUNKSIZE 100 + static ase_char_t* str_to_str ( ase_awk_run_t* run, const ase_char_t* str, ase_size_t str_len, int opt, ase_str_t* buf, ase_size_t* len); @@ -84,9 +86,8 @@ ase_awk_val_t* ase_awk_makeintval (ase_awk_run_t* run, ase_long_t v) } } */ - ase_awk_val_int_t* f = run->ifree; - if (f = ASE_NULL) + if (run->vmgr.ifree == ASE_NULL) { ase_awk_val_chunk_t* c; ase_awk_val_int_t* x; @@ -94,25 +95,25 @@ ase_awk_val_t* ase_awk_makeintval (ase_awk_run_t* run, ase_long_t v) c = ASE_AWK_MALLOC (run->awk, ASE_SIZEOF(ase_awk_val_chunk_t)+ - ASE_SIZEOF(ase_awk_val_int_t)*100); + ASE_SIZEOF(ase_awk_val_int_t)*CHUNKSIZE); if (c == ASE_NULL) { ase_awk_setrunerrnum (run, ASE_AWK_ENOMEM); return ASE_NULL; } + c->next = run->vmgr.ichunk; + run->vmgr.ichunk = c; + x = (ase_awk_val_int_t*)(c + 1); - for (i = 0; i < 100-1; i++) + for (i = 0; i < CHUNKSIZE-1; i++) x[i].nde = (ase_awk_nde_int_t*)&x[i+1]; x[i].nde = ASE_NULL; - run->ifree = &x[0]; - c->next = run->ichunk; - run->ichunk = c; + run->vmgr.ifree = x; } - - val = run->ifree; - run->ifree = (ase_awk_val_int_t*)val->nde; + val = run->vmgr.ifree; + run->vmgr.ifree = (ase_awk_val_int_t*)val->nde; val->type = ASE_AWK_VAL_INT; val->ref = 0; @@ -129,6 +130,7 @@ ase_awk_val_t* ase_awk_makerealval (ase_awk_run_t* run, ase_real_t v) { ase_awk_val_real_t* val; + /* if (run->rcache_count > 0) { val = run->rcache[--run->rcache_count]; @@ -143,6 +145,35 @@ ase_awk_val_t* ase_awk_makerealval (ase_awk_run_t* run, ase_real_t v) return ASE_NULL; } } + */ + + if (run->vmgr.rfree == ASE_NULL) + { + ase_awk_val_chunk_t* c; + ase_awk_val_real_t* x; + ase_size_t i; + + c = ASE_AWK_MALLOC (run->awk, + ASE_SIZEOF(ase_awk_val_chunk_t)+ + ASE_SIZEOF(ase_awk_val_real_t)*CHUNKSIZE); + if (c == ASE_NULL) + { + ase_awk_setrunerrnum (run, ASE_AWK_ENOMEM); + return ASE_NULL; + } + + c->next = run->vmgr.rchunk; + run->vmgr.rchunk = c; + + x = (ase_awk_val_real_t*)(c + 1); + for (i = 0; i < CHUNKSIZE-1; i++) + x[i].nde = (ase_awk_nde_real_t*)&x[i+1]; + x[i].nde = ASE_NULL; + + run->vmgr.rfree = x; + } + val = run->vmgr.rfree; + run->vmgr.rfree = (ase_awk_val_real_t*)val->nde; val->type = ASE_AWK_VAL_REAL; val->ref = 0; @@ -425,17 +456,21 @@ void ase_awk_freeval (ase_awk_run_t* run, ase_awk_val_t* val, ase_bool_t cache) else ASE_AWK_FREE (run->awk, val); */ - ((ase_awk_val_int_t*)val)->nde = (ase_awk_nde_int_t*)run->ifree; - run->ifree = val; + ((ase_awk_val_int_t*)val)->nde = (ase_awk_nde_int_t*)run->vmgr.ifree; + run->vmgr.ifree = (ase_awk_val_int_t*)val; } else if (val->type == ASE_AWK_VAL_REAL) { + /* if (cache && run->rcache_count < ASE_COUNTOF(run->rcache)) { run->rcache[run->rcache_count++] = (ase_awk_val_real_t*)val; } else ASE_AWK_FREE (run->awk, val); + */ + ((ase_awk_val_real_t*)val)->nde = (ase_awk_nde_real_t*)run->vmgr.rfree; + run->vmgr.rfree = (ase_awk_val_real_t*)val; } else if (val->type == ASE_AWK_VAL_STR) { @@ -634,6 +669,21 @@ static ase_char_t* str_to_str ( if (len != ASE_NULL) *len = str_len; return tmp; } + else if (opt & ASE_AWK_VALTOSTR_FIXED) + { + ASE_ASSERT (buf != ASE_NULL && len != ASE_NULL); + + if (str_len >= *len) + { + ase_awk_setrunerror ( + run, ASE_AWK_EINVAL, 0, ASE_NULL, 0); + *len = str_len + 1; + return ASE_NULL; + } + + *len = ase_strncpy ((ase_char_t*)buf, str, str_len); + return (ase_char_t*)buf; + } else { ase_size_t n; @@ -658,7 +708,7 @@ static ase_char_t* val_int_to_str ( { ase_char_t* tmp; ase_long_t t; - ase_size_t l = 0; + ase_size_t rlen = 0; t = v->val; if (t == 0) @@ -680,6 +730,24 @@ static ase_char_t* val_int_to_str ( if (len != ASE_NULL) *len = 1; return tmp; } + else if (opt & ASE_AWK_VALTOSTR_FIXED) + { + ASE_ASSERT (buf != ASE_NULL && len != ASE_NULL); + + if (1 >= *len) + { + ase_awk_setrunerror ( + run, ASE_AWK_EINVAL, 0, ASE_NULL, 0); + *len = 2; /* buffer size required */ + return ASE_NULL; + } + + tmp = (ase_char_t*)buf; + tmp[0] = ASE_T('0'); + tmp[1] = ASE_T('\0'); + *len = 1; /* actual length */ + return tmp; + } else { if (opt & ASE_AWK_VALTOSTR_CLEAR) ase_str_clear (buf); @@ -696,13 +764,13 @@ static ase_char_t* val_int_to_str ( } /* non-zero values */ - if (t < 0) { t = -t; l++; } - while (t > 0) { l++; t /= 10; } + if (t < 0) { t = -t; rlen++; } + while (t > 0) { rlen++; t /= 10; } if (buf == ASE_NULL) { tmp = ASE_AWK_MALLOC ( - run->awk, (l + 1) * ASE_SIZEOF(ase_char_t)); + run->awk, (rlen + 1) * ASE_SIZEOF(ase_char_t)); if (tmp == ASE_NULL) { ase_awk_setrunerror ( @@ -710,8 +778,24 @@ static ase_char_t* val_int_to_str ( return ASE_NULL; } - tmp[l] = ASE_T('\0'); - if (len != ASE_NULL) *len = l; + tmp[rlen] = ASE_T('\0'); + if (len != ASE_NULL) *len = rlen; + } + else if (opt & ASE_AWK_VALTOSTR_FIXED) + { + ASE_ASSERT (buf != ASE_NULL && len != ASE_NULL); + + if (rlen >= *len) + { + ase_awk_setrunerror ( + run, ASE_AWK_EINVAL, 0, ASE_NULL, 0); + *len = rlen + 1; /* buffer size required */ + return ASE_NULL; + } + + tmp = (ase_char_t*)buf; + tmp[rlen] = ASE_T('\0'); + *len = rlen; /* actual length */ } else { @@ -722,7 +806,7 @@ static ase_char_t* val_int_to_str ( /* extend the buffer */ if (ase_str_nccat ( - buf, ASE_T(' '), l) == (ase_size_t)-1) + buf, ASE_T(' '), rlen) == (ase_size_t)-1) { ase_awk_setrunerror ( run, ASE_AWK_ENOMEM, 0, ASE_NULL, 0); @@ -735,13 +819,13 @@ static ase_char_t* val_int_to_str ( while (t > 0) { - tmp[--l] = (ase_char_t)(t % 10) + ASE_T('0'); + tmp[--rlen] = (ase_char_t)(t % 10) + ASE_T('0'); t /= 10; } - if (v->val < 0) tmp[--l] = ASE_T('-'); + if (v->val < 0) tmp[--rlen] = ASE_T('-'); - if (buf != ASE_NULL) + if (buf != ASE_NULL && !(opt & ASE_AWK_VALTOSTR_FIXED)) { tmp = ASE_STR_BUF(buf); if (len != ASE_NULL) *len = ASE_STR_LEN(buf); @@ -797,6 +881,27 @@ static ase_char_t* val_real_to_str ( ase_str_forfeit (&out); if (len != ASE_NULL) *len = tmp_len; } + else if (opt & ASE_AWK_VALTOSTR_FIXED) + { + ASE_ASSERT (buf != ASE_NULL && len != ASE_NULL); + + if (tmp_len >= *len) + { + ase_awk_setrunerror ( + run, ASE_AWK_EINVAL, 0, ASE_NULL, 0); + *len = tmp_len + 1; /* buffer size required */ + ase_str_close (&fbu); + ase_str_close (&out); + return ASE_NULL; + } + + ase_strncpy ((ase_char_t*)buf, tmp, tmp_len); + tmp = (ase_char_t*)buf; + *len = tmp_len; + + ase_str_close (&fbu); + ase_str_close (&out); + } else { if (opt & ASE_AWK_VALTOSTR_CLEAR) ase_str_clear (buf); diff --git a/ase/awk/val.h b/ase/awk/val.h index f47551b0..0f5789ca 100644 --- a/ase/awk/val.h +++ b/ase/awk/val.h @@ -48,7 +48,8 @@ enum ase_awk_val_ref_id_t enum ase_awk_valtostr_opt_t { ASE_AWK_VALTOSTR_CLEAR = (1 << 0), - ASE_AWK_VALTOSTR_PRINT = (1 << 1) + ASE_AWK_VALTOSTR_FIXED = (1 << 1),/* this overrides CLEAR */ + ASE_AWK_VALTOSTR_PRINT = (1 << 2) }; typedef struct ase_awk_val_nil_t ase_awk_val_nil_t;