*** empty log message ***

This commit is contained in:
hyung-hwan 2006-11-13 15:08:54 +00:00
parent 0f7efc6263
commit 222db3c7a1
8 changed files with 458 additions and 455 deletions

View File

@ -1,5 +1,5 @@
/* /*
* $Id: awk_i.h,v 1.77 2006-11-12 15:09:14 bacon Exp $ * $Id: awk_i.h,v 1.78 2006-11-13 15:08:53 bacon Exp $
*/ */
#ifndef _ASE_AWK_AWKI_H_ #ifndef _ASE_AWK_AWKI_H_
@ -270,20 +270,10 @@ struct ase_awk_run_t
struct struct
{ {
struct ase_awk_str_t fmt;
{ ase_awk_str_t out;
ase_size_t len; ase_char_t tmp[4096];
ase_char_t buf[1024]; } sprintf;
} out;
struct
{
ase_size_t len;
ase_char_t buf[256];
} fmt;
ase_char_t buf[4096];
} format;
int errnum; int errnum;

View File

@ -1,5 +1,5 @@
/* /*
* $Id: map.c,v 1.30 2006-10-30 14:31:37 bacon Exp $ * $Id: map.c,v 1.31 2006-11-13 15:08:53 bacon Exp $
*/ */
#include <ase/awk/awk_i.h> #include <ase/awk/awk_i.h>
@ -76,8 +76,7 @@ void ase_awk_map_clear (ase_awk_map_t* map)
} }
ASE_AWK_ASSERTX (map->awk, map->size == 0, ASE_AWK_ASSERTX (map->awk, map->size == 0,
"the map should not contain any pairs of a key and a value" "the map should not contain any pairs of a key and a value after it has been cleared");
"after it has been cleared");
} }
ase_awk_pair_t* ase_awk_map_get ( ase_awk_pair_t* ase_awk_map_get (

View File

@ -1,5 +1,5 @@
/* /*
* $Id: misc.c,v 1.37 2006-11-13 09:02:23 bacon Exp $ * $Id: misc.c,v 1.38 2006-11-13 15:08:53 bacon Exp $
*/ */
#include <ase/awk/awk_i.h> #include <ase/awk/awk_i.h>
@ -1061,13 +1061,6 @@ exit_loop:
} }
} }
int ase_awk_sprintf (ase_awk_t* awk,
ase_char_t* buf, ase_size_t len, const ase_char_t* fmt, ...)
{
/* TODO: */
return -1;
}
int ase_awk_assertfail (ase_awk_t* awk, int ase_awk_assertfail (ase_awk_t* awk,
const ase_char_t* expr, const ase_char_t* desc, const ase_char_t* expr, const ase_char_t* desc,
const ase_char_t* file, int line) const ase_char_t* file, int line)
@ -1088,3 +1081,4 @@ int ase_awk_assertfail (ase_awk_t* awk,
awk->syscas.abort (); awk->syscas.abort ();
return 0; return 0;
} }

View File

@ -1,5 +1,5 @@
/* /*
* $Id: misc.h,v 1.9 2006-10-31 10:13:14 bacon Exp $ * $Id: misc.h,v 1.10 2006-11-13 15:08:54 bacon Exp $
*/ */
#ifndef _ASE_AWK_MISC_H_ #ifndef _ASE_AWK_MISC_H_
@ -38,9 +38,6 @@ ase_char_t* ase_awk_strxntokbyrex (
ase_awk_run_t* run, const ase_char_t* s, ase_size_t len, ase_awk_run_t* run, const ase_char_t* s, ase_size_t len,
void* rex, ase_char_t** tok, ase_size_t* tok_len, int* errnum); void* rex, ase_char_t** tok, ase_size_t* tok_len, int* errnum);
int ase_awk_sprintf (ase_awk_t* awk,
ase_char_t* buf, ase_size_t len, const ase_char_t* fmt, ...);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* $Id: parse.c,v 1.201 2006-11-13 09:02:23 bacon Exp $ * $Id: parse.c,v 1.202 2006-11-13 15:08:17 bacon Exp $
*/ */
#include <ase/awk/awk_i.h> #include <ase/awk/awk_i.h>
@ -3317,8 +3317,7 @@ static ase_awk_nde_t* __parse_print (ase_awk_t* awk, int type)
ASE_AWK_ASSERTX (awk, ASE_AWK_ASSERTX (awk,
type == ASE_AWK_NDE_PRINT || type == ASE_AWK_NDE_PRINTF, type == ASE_AWK_NDE_PRINT || type == ASE_AWK_NDE_PRINTF,
"the node type should be either ASE_AWK_NDE_PRINT or " "the node type should be either ASE_AWK_NDE_PRINT or ASE_AWK_NDE_PRINTF");
"ASE_AWK_NDE_PRINTF");
if (type == ASE_AWK_NDE_PRINTF && args == ASE_NULL) if (type == ASE_AWK_NDE_PRINTF && args == ASE_NULL)
{ {

View File

@ -1,5 +1,5 @@
/* /*
* $Id: run.c,v 1.257 2006-11-13 09:02:23 bacon Exp $ * $Id: run.c,v 1.258 2006-11-13 15:07:24 bacon Exp $
*/ */
#include <ase/awk/awk_i.h> #include <ase/awk/awk_i.h>
@ -661,9 +661,26 @@ static int __init_run (ase_awk_run_t* run, ase_awk_runios_t* runios, int* errnum
return -1; return -1;
} }
if (ase_awk_str_open (&run->sprintf.out, 256, run->awk) == ASE_NULL)
{
ase_awk_str_close (&run->inrec.line);
*errnum = ASE_AWK_ENOMEM;
return -1;
}
if (ase_awk_str_open (&run->sprintf.fmt, 256, run->awk) == ASE_NULL)
{
ase_awk_str_close (&run->sprintf.out);
ase_awk_str_close (&run->inrec.line);
*errnum = ASE_AWK_ENOMEM;
return -1;
}
if (ase_awk_map_open (&run->named, if (ase_awk_map_open (&run->named,
run, DEF_BUF_CAPA, __free_namedval, run->awk) == ASE_NULL) run, DEF_BUF_CAPA, __free_namedval, run->awk) == ASE_NULL)
{ {
ase_awk_str_close (&run->sprintf.fmt);
ase_awk_str_close (&run->sprintf.out);
ase_awk_str_close (&run->inrec.line); ase_awk_str_close (&run->inrec.line);
*errnum = ASE_AWK_ENOMEM; *errnum = ASE_AWK_ENOMEM;
return -1; return -1;
@ -676,6 +693,8 @@ static int __init_run (ase_awk_run_t* run, ase_awk_runios_t* runios, int* errnum
if (run->pattern_range_state == ASE_NULL) if (run->pattern_range_state == ASE_NULL)
{ {
ase_awk_map_close (&run->named); ase_awk_map_close (&run->named);
ase_awk_str_close (&run->sprintf.fmt);
ase_awk_str_close (&run->sprintf.out);
ase_awk_str_close (&run->inrec.line); ase_awk_str_close (&run->inrec.line);
*errnum = ASE_AWK_ENOMEM; *errnum = ASE_AWK_ENOMEM;
return -1; return -1;
@ -702,6 +721,7 @@ static int __init_run (ase_awk_run_t* run, ase_awk_runios_t* runios, int* errnum
static void __deinit_run (ase_awk_run_t* run) static void __deinit_run (ase_awk_run_t* run)
{ {
if (run->pattern_range_state != ASE_NULL) if (run->pattern_range_state != ASE_NULL)
ASE_AWK_FREE (run->awk, run->pattern_range_state); ASE_AWK_FREE (run->awk, run->pattern_range_state);
@ -761,6 +781,9 @@ static void __deinit_run (ase_awk_run_t* run)
run->global.subsep.len = 0; run->global.subsep.len = 0;
} }
ase_awk_str_close (&run->sprintf.fmt);
ase_awk_str_close (&run->sprintf.out);
/* destroy input record. ase_awk_clrrec should be called /* destroy input record. ase_awk_clrrec should be called
* before the run stack has been destroyed because it may try * before the run stack has been destroyed because it may try
* to change the value to ASE_AWK_GLOBAL_NF. */ * to change the value to ASE_AWK_GLOBAL_NF. */
@ -1963,9 +1986,7 @@ static int __run_delete (ase_awk_run_t* run, ase_awk_nde_delete_t* nde)
ASE_AWK_ASSERTX (run->awk, ASE_AWK_ASSERTX (run->awk,
(var->type == ASE_AWK_NDE_NAMED && var->idx == ASE_NULL) || (var->type == ASE_AWK_NDE_NAMED && var->idx == ASE_NULL) ||
(var->type == ASE_AWK_NDE_NAMEDIDX && var->idx != ASE_NULL), (var->type == ASE_AWK_NDE_NAMEDIDX && var->idx != ASE_NULL),
"if a named variable has an index part and " "if a named variable has an index part and a named indexed variable doesn't have an index part, the program is definitely wrong");
"a named indexed variable doesn't have an index "
"part, the program is definitely wrong");
pair = ase_awk_map_get ( pair = ase_awk_map_get (
&run->named, var->id.name, var->id.name_len); &run->named, var->id.name, var->id.name_len);
@ -2142,9 +2163,7 @@ static int __run_delete (ase_awk_run_t* run, ase_awk_nde_delete_t* nde)
{ {
ASE_AWK_ASSERTX (run->awk, ASE_AWK_ASSERTX (run->awk,
!"should never happen - wrong variable type for delete", !"should never happen - wrong variable type for delete",
"the delete statement cannot be called with other " "the delete statement cannot be called with other nodes than the variables such as a named variable, a named indexed variable, etc");
"nodes than the variables such as a named variable, "
"a named indexed variable, etc");
run->errnum = ASE_AWK_EINTERNAL; run->errnum = ASE_AWK_EINTERNAL;
return -1; return -1;
} }
@ -2296,23 +2315,12 @@ skip_write:
return 0; return 0;
} }
static int xxx__run_printf (ase_awk_run_t* run, ase_awk_nde_print_t* nde)
{
ASE_AWK_ASSERTX (run->awk, !"should never happen - not implemented",
"the runtime function for the printf statement has not been "
"implemented yet. please do not use printf until it is fully "
"implemented");
run->errnum = ASE_AWK_EINTERNAL;
return -1;
}
static int __run_printf (ase_awk_run_t* run, ase_awk_nde_print_t* nde) static int __run_printf (ase_awk_run_t* run, ase_awk_nde_print_t* nde)
{ {
ase_char_t* out = ASE_NULL; ase_char_t* out = ASE_NULL;
const ase_char_t* dst; const ase_char_t* dst;
ase_awk_val_t* v, * fmt; ase_awk_val_t* v;
ase_awk_nde_t* head, * np; ase_awk_nde_t* head;
int n; int n;
ASE_AWK_ASSERT (run->awk, ASE_AWK_ASSERT (run->awk,
@ -2370,8 +2378,7 @@ static int __run_printf (ase_awk_run_t* run, ase_awk_nde_print_t* nde)
dst = (out == ASE_NULL)? ASE_T(""): out; dst = (out == ASE_NULL)? ASE_T(""): out;
ASE_AWK_ASSERTX (run->awk, nde->args != ASE_NULL, ASE_AWK_ASSERTX (run->awk, nde->args != ASE_NULL,
"a valid printf statement should have at least one argument. " "a valid printf statement should have at least one argument. the parser must ensure this.");
"the parser must ensure this.");
if (nde->args->type == ASE_AWK_NDE_GRP) if (nde->args->type == ASE_AWK_NDE_GRP)
{ {
@ -2382,8 +2389,7 @@ static int __run_printf (ase_awk_run_t* run, ase_awk_nde_print_t* nde)
else head = nde->args; else head = nde->args;
ASE_AWK_ASSERTX (run->awk, head != ASE_NULL, ASE_AWK_ASSERTX (run->awk, head != ASE_NULL,
"a valid printf statement should have at least one argument. " "a valid printf statement should have at least one argument. the parser must ensure this.");
"the parser must ensure this.");
v = __eval_expression (run, head); v = __eval_expression (run, head);
if (v == ASE_NULL) if (v == ASE_NULL)
@ -2431,392 +2437,17 @@ static int __formatted_output (
ase_awk_run_t* run, int out_type, const ase_char_t* dst, ase_awk_run_t* run, int out_type, const ase_char_t* dst,
const ase_char_t* fmt, ase_size_t fmt_len, ase_awk_nde_t* args) const ase_char_t* fmt, ase_size_t fmt_len, ase_awk_nde_t* args)
{ {
ase_size_t i, j; ase_char_t* ptr;
ase_size_t len;
int n;
#define FLUSH() \ ptr = ase_awk_sprintf (run, fmt, fmt_len, args, &len);
do { \ if (ptr == ASE_NULL) return -1;
int n = ase_awk_writeextio_str ( \
run, out_type, dst, \
run->format.out.buf, run->format.out.len); \
if (n < 0 && run->errnum != ASE_AWK_EIOHANDLER) return -1; \
run->format.out.len = 0; \
} while (0)
#define OUTPUT_CHAR(c) \ n = ase_awk_writeextio_str (run, out_type, dst, ptr, len);
do { \ if (n < 0 && run->errnum != ASE_AWK_EIOHANDLER) return -1;
run->format.out.buf[run->format.out.len++] = (c); \
if (run->format.out.len >= \
ase_countof(run->format.out.buf)) FLUSH (); \
} while (0)
#define ADD_TO_FMTBUF(c) \ return 0;
do { \
if (run->format.fmt.len < ase_countof(run->format.fmt.buf)-1) \
{ \
run->format.fmt.buf[run->format.fmt.len++] = (c); \
run->format.fmt.buf[run->format.fmt.len] = ASE_T('\0'); \
} \
else \
{ \
run->errnum = ASE_AWK_EFMTSEQ; \
return -1; \
} \
} while (0)
run->format.out.len = 0;
run->format.fmt.len = 0;
for (i = 0; i < fmt_len; i++)
{
if (run->format.fmt.len == 0)
{
if (fmt[i] == ASE_T('%'))
{
run->format.fmt.buf[run->format.fmt.len++] = fmt[i];
}
else OUTPUT_CHAR (fmt[i]);
continue;
}
while (i < fmt_len &&
(fmt[i] == ASE_T(' ') || fmt[i] == ASE_T('#') ||
fmt[i] == ASE_T('0') || fmt[i] == ASE_T('+') ||
fmt[i] == ASE_T('-')))
{
ADD_TO_FMTBUF (fmt[i]); i++;
}
if (i < fmt_len && fmt[i] == ASE_T('*'))
{
ase_awk_val_t* v;
ase_long_t l;
ase_real_t r;
ase_char_t* p;
int n;
if (args == ASE_NULL)
{
run->errnum = ASE_AWK_EPRINTFARG;
return -1;
}
v = __eval_expression (run, args);
if (v == ASE_NULL) return -1;
ase_awk_refupval (v);
n = ase_awk_valtonum (run, v, &l, &r);
ase_awk_refdownval (run, v);
if (n == -1) return -1;
if (n == 1) l = (ase_long_t)r;
run->awk->syscas.sprintf (
run->format.buf,
ase_countof(run->format.buf),
ASE_T("%lld"), (long long)l);
p = run->format.buf;
while (*p != ASE_T('\0'))
{
ADD_TO_FMTBUF (*p);
p++;
}
args = args->next;
i++;
}
else
{
while (i < fmt_len && ASE_AWK_ISDIGIT(run->awk, fmt[i]))
{
ADD_TO_FMTBUF (fmt[i]); i++;
}
}
if (i < fmt_len && fmt[i] == ASE_T('.'))
{
ADD_TO_FMTBUF (fmt[i]); i++;
}
if (i < fmt_len && fmt[i] == ASE_T('*'))
{
ase_awk_val_t* v;
ase_long_t l;
ase_real_t r;
ase_char_t* p;
int n;
if (args == ASE_NULL)
{
run->errnum = ASE_AWK_EPRINTFARG;
return -1;
}
v = __eval_expression (run, args);
if (v == ASE_NULL) return -1;
ase_awk_refupval (v);
n = ase_awk_valtonum (run, v, &l, &r);
ase_awk_refdownval (run, v);
if (n == -1) return -1;
if (n == 1) l = (ase_long_t)r;
run->awk->syscas.sprintf (
run->format.buf,
ase_countof(run->format.buf),
ASE_T("%lld"), (long long)l);
p = run->format.buf;
while (*p != ASE_T('\0'))
{
ADD_TO_FMTBUF (*p);
p++;
}
args = args->next;
i++;
}
else
{
while (i < fmt_len && ASE_AWK_ISDIGIT(run->awk, fmt[i]))
{
ADD_TO_FMTBUF (fmt[i]); i++;
}
}
if (i >= fmt_len) break;
if (fmt[i] == ASE_T('d') || fmt[i] == ASE_T('i') ||
fmt[i] == ASE_T('x') || fmt[i] == ASE_T('X') ||
fmt[i] == ASE_T('o'))
{
ase_awk_val_t* v;
ase_long_t l;
ase_real_t r;
ase_char_t* p;
int n;
if (args == ASE_NULL)
{
run->errnum = ASE_AWK_EPRINTFARG;
return -1;
}
ADD_TO_FMTBUF (ASE_T('l'));
ADD_TO_FMTBUF (ASE_T('l'));
ADD_TO_FMTBUF (fmt[i]);
v = __eval_expression (run, args);
if (v == ASE_NULL) return -1;
ase_awk_refupval (v);
n = ase_awk_valtonum (run, v, &l, &r);
ase_awk_refdownval (run, v);
if (n == -1) return -1;
if (n == 1) l = (ase_long_t)r;
/* TODO: check the return value of syscas.sprintf and handle an error */
run->awk->syscas.sprintf (
run->format.buf,
ase_countof(run->format.buf),
run->format.fmt.buf, (long long)l);
p = run->format.buf;
while (*p != ASE_T('\0'))
{
OUTPUT_CHAR (*p);
p++;
}
}
else if (fmt[i] == ASE_T('e') || fmt[i] == ASE_T('E') ||
fmt[i] == ASE_T('g') || fmt[i] == ASE_T('G') ||
fmt[i] == ASE_T('f'))
{
ase_awk_val_t* v;
ase_long_t l;
ase_real_t r;
ase_char_t* p;
int n;
if (args == ASE_NULL)
{
run->errnum = ASE_AWK_EPRINTFARG;
return -1;
}
ADD_TO_FMTBUF (ASE_T('L'));
ADD_TO_FMTBUF (fmt[i]);
v = __eval_expression (run, args);
if (v == ASE_NULL) return -1;
ase_awk_refupval (v);
n = ase_awk_valtonum (run, v, &l, &r);
ase_awk_refdownval (run, v);
if (n == -1) return -1;
if (n == 0) r = (ase_real_t)l;
/* TODO: check the return value of syscas.sprintf and handle an error */
run->awk->syscas.sprintf (
run->format.buf,
ase_countof(run->format.buf),
run->format.fmt.buf, (long double)r);
p = run->format.buf;
while (*p != ASE_T('\0'))
{
OUTPUT_CHAR (*p);
p++;
}
}
else if (fmt[i] == ASE_T('c'))
{
ase_awk_val_t* v;
ase_char_t* p;
if (args == ASE_NULL)
{
run->errnum = ASE_AWK_EPRINTFARG;
return -1;
}
ADD_TO_FMTBUF (fmt[i]);
v = __eval_expression (run, args);
if (v == ASE_NULL) return -1;
ase_awk_refupval (v);
if (v->type == ASE_AWK_VAL_NIL)
{
run->format.buf[0] = ASE_T('\0');
}
else if (v->type == ASE_AWK_VAL_INT)
{
run->awk->syscas.sprintf (
run->format.buf,
ase_countof(run->format.buf),
run->format.fmt.buf,
(int)((ase_awk_val_int_t*)v)->val);
}
else if (v->type == ASE_AWK_VAL_REAL)
{
run->awk->syscas.sprintf (
run->format.buf,
ase_countof(run->format.buf),
run->format.fmt.buf,
(int)((ase_awk_val_real_t*)v)->val);
}
else if (v->type == ASE_AWK_VAL_STR)
{
ase_awk_val_str_t* str = (ase_awk_val_str_t*)v;
if (str->len > 0)
{
run->awk->syscas.sprintf (
run->format.buf,
ase_countof(run->format.buf),
run->format.fmt.buf, str->buf[0]);
}
else run->format.buf[0] = ASE_T('\0');
}
else
{
ase_awk_refdownval (run, v);
run->errnum = ASE_AWK_EVALTYPE;
return -1;
}
ase_awk_refdownval (run, v);
p = run->format.buf;
while (*p != ASE_T('\0'))
{
OUTPUT_CHAR (*p);
p++;
}
}
else if (fmt[i] == ASE_T('s'))
{
ase_awk_val_t* v;
ase_char_t* p;
if (args == ASE_NULL)
{
run->errnum = ASE_AWK_EPRINTFARG;
return -1;
}
ADD_TO_FMTBUF (fmt[i]);
v = __eval_expression (run, args);
if (v == ASE_NULL) return -1;
ase_awk_refupval (v);
if (v->type == ASE_AWK_VAL_NIL)
{
run->format.buf[0] = ASE_T('\0');
}
else if (v->type == ASE_AWK_VAL_STR)
{
/* TODO: handle a string contailing null characters */
/* TODO: handle error conditions of sprintf */
run->awk->syscas.sprintf (
run->format.buf,
ase_countof(run->format.buf),
run->format.fmt.buf,
((ase_awk_val_str_t*)v)->buf);
}
else
{
ase_char_t* str;
ase_size_t len;
str = ase_awk_valtostr (run, v, ASE_AWK_VALTOSTR_CLEAR, ASE_NULL, &len);
if (str == ASE_NULL)
{
ase_awk_refdownval (run, v);
return -1;
}
run->awk->syscas.sprintf (
run->format.buf,
ase_countof(run->format.buf),
run->format.fmt.buf, str);
ASE_AWK_FREE (run->awk, str);
}
ase_awk_refdownval (run, v);
p = run->format.buf;
while (*p != ASE_T('\0'))
{
OUTPUT_CHAR (*p);
p++;
}
}
else /*if (fmt[i] == ASE_T('%'))*/
{
for (j = 0; j < run->format.fmt.len; j++)
OUTPUT_CHAR (run->format.fmt.buf[j]);
OUTPUT_CHAR (fmt[i]);
}
args = args->next;
run->format.fmt.len = 0;
}
if (run->format.fmt.len > 0)
{
/* flush uncompleted formatting sequence */
for (j = 0; j < run->format.fmt.len; j++)
OUTPUT_CHAR (run->format.fmt.buf[j]);
}
FLUSH ();
} }
static ase_awk_val_t* __eval_expression (ase_awk_run_t* run, ase_awk_nde_t* nde) static ase_awk_val_t* __eval_expression (ase_awk_run_t* run, ase_awk_nde_t* nde)
@ -2842,9 +2473,7 @@ static ase_awk_val_t* __eval_expression (ase_awk_run_t* run, ase_awk_nde_t* nde)
{ {
ASE_AWK_ASSERTX (run->awk, ASE_AWK_ASSERTX (run->awk,
run->inrec.d0->type == ASE_AWK_VAL_STR, run->inrec.d0->type == ASE_AWK_VAL_STR,
"the internal value representing $0 should " "the internal value representing $0 should always be of the string type once it has been set/updated. it is nil initially.");
"always be of the string type once it has been "
"set/updated. it is nil initially.");
n = ase_awk_matchrex ( n = ase_awk_matchrex (
((ase_awk_run_t*)run)->awk, ((ase_awk_run_t*)run)->awk,
@ -4090,8 +3719,7 @@ static ase_awk_val_t* __eval_binop_exp (
ase_awk_val_t* res; ase_awk_val_t* res;
ASE_AWK_ASSERTX (run->awk, run->awk->syscas.pow != ASE_NULL, ASE_AWK_ASSERTX (run->awk, run->awk->syscas.pow != ASE_NULL,
"the pow function should be provided when the awk object " "the pow function should be provided when the awk object is created to make the exponentiation work properly.");
"is created to make the exponentiation work properly.");
n1 = ase_awk_valtonum (run, left, &l1, &r1); n1 = ase_awk_valtonum (run, left, &l1, &r1);
n2 = ase_awk_valtonum (run, right, &l2, &r2); n2 = ase_awk_valtonum (run, right, &l2, &r2);
@ -5873,3 +5501,391 @@ static ase_char_t* __idxnde_to_str (
return str; return str;
} }
ase_char_t* ase_awk_sprintf (
ase_awk_run_t* run, const ase_char_t* fmt,
ase_size_t fmt_len, ase_awk_nde_t* args, ase_size_t* len)
{
ase_size_t i, j;
#define OUT_CHAR(c) \
do { \
if (ase_awk_str_ccat (&run->sprintf.out, (c)) == -1) \
{ \
run->errnum = ASE_AWK_ENOMEM; \
return ASE_NULL; \
} \
} while (0)
#define FMT_CHAR(c) \
do { \
if (ase_awk_str_ccat (&run->sprintf.fmt, (c)) == -1) \
{ \
run->errnum = ASE_AWK_ENOMEM; \
return ASE_NULL; \
} \
} while (0)
ase_awk_str_clear (&run->sprintf.out);
ase_awk_str_clear (&run->sprintf.fmt);
for (i = 0; i < fmt_len; i++)
{
if (ASE_AWK_STR_LEN(&run->sprintf.fmt) == 0)
{
if (fmt[i] == ASE_T('%')) FMT_CHAR (fmt[i]);
else OUT_CHAR (fmt[i]);
continue;
}
while (i < fmt_len &&
(fmt[i] == ASE_T(' ') || fmt[i] == ASE_T('#') ||
fmt[i] == ASE_T('0') || fmt[i] == ASE_T('+') ||
fmt[i] == ASE_T('-')))
{
FMT_CHAR (fmt[i]); i++;
}
if (i < fmt_len && fmt[i] == ASE_T('*'))
{
ase_awk_val_t* v;
ase_long_t l;
ase_real_t r;
ase_char_t* p;
int n;
if (args == ASE_NULL)
{
run->errnum = ASE_AWK_EPRINTFARG;
return ASE_NULL;
}
v = __eval_expression (run, args);
if (v == ASE_NULL) return ASE_NULL;
ase_awk_refupval (v);
n = ase_awk_valtonum (run, v, &l, &r);
ase_awk_refdownval (run, v);
if (n == -1) return ASE_NULL;
if (n == 1) l = (ase_long_t)r;
run->awk->syscas.sprintf (
run->sprintf.tmp,
ase_countof(run->sprintf.tmp),
#ifdef _WIN32
ASE_T("%I64d"), (__int64)l);
#else
ASE_T("%lld"), (long long)l);
#endif
p = run->sprintf.tmp;
while (*p != ASE_T('\0'))
{
FMT_CHAR (*p);
p++;
}
args = args->next;
i++;
}
else
{
while (i < fmt_len && ASE_AWK_ISDIGIT(run->awk, fmt[i]))
{
FMT_CHAR (fmt[i]); i++;
}
}
if (i < fmt_len && fmt[i] == ASE_T('.'))
{
FMT_CHAR (fmt[i]); i++;
}
if (i < fmt_len && fmt[i] == ASE_T('*'))
{
ase_awk_val_t* v;
ase_long_t l;
ase_real_t r;
ase_char_t* p;
int n;
if (args == ASE_NULL)
{
run->errnum = ASE_AWK_EPRINTFARG;
return ASE_NULL;
}
v = __eval_expression (run, args);
if (v == ASE_NULL) return ASE_NULL;
ase_awk_refupval (v);
n = ase_awk_valtonum (run, v, &l, &r);
ase_awk_refdownval (run, v);
if (n == -1) return ASE_NULL;
if (n == 1) l = (ase_long_t)r;
run->awk->syscas.sprintf (
run->sprintf.tmp,
ase_countof(run->sprintf.tmp),
#ifdef _WIN32
ASE_T("%I64d"), (__int64)l);
#else
ASE_T("%lld"), (long long)l);
#endif
p = run->sprintf.tmp;
while (*p != ASE_T('\0'))
{
FMT_CHAR (*p);
p++;
}
args = args->next;
i++;
}
else
{
while (i < fmt_len && ASE_AWK_ISDIGIT(run->awk, fmt[i]))
{
FMT_CHAR (fmt[i]); i++;
}
}
if (i >= fmt_len) break;
if (fmt[i] == ASE_T('d') || fmt[i] == ASE_T('i') ||
fmt[i] == ASE_T('x') || fmt[i] == ASE_T('X') ||
fmt[i] == ASE_T('o'))
{
ase_awk_val_t* v;
ase_long_t l;
ase_real_t r;
ase_char_t* p;
int n;
if (args == ASE_NULL)
{
run->errnum = ASE_AWK_EPRINTFARG;
return ASE_NULL;
}
FMT_CHAR (ASE_T('l'));
FMT_CHAR (ASE_T('l'));
FMT_CHAR (fmt[i]);
v = __eval_expression (run, args);
if (v == ASE_NULL) return ASE_NULL;
ase_awk_refupval (v);
n = ase_awk_valtonum (run, v, &l, &r);
ase_awk_refdownval (run, v);
if (n == -1) return ASE_NULL;
if (n == 1) l = (ase_long_t)r;
/* TODO: check the return value of syscas.sprintf and handle an error */
run->awk->syscas.sprintf (
run->sprintf.tmp,
ase_countof(run->sprintf.tmp),
#ifdef _WIN32
run->sprintf.fmt.buf, (__int64)l);
#else
run->sprintf.fmt.buf, (long long)l);
#endif
p = run->sprintf.tmp;
while (*p != ASE_T('\0'))
{
OUT_CHAR (*p);
p++;
}
}
else if (fmt[i] == ASE_T('e') || fmt[i] == ASE_T('E') ||
fmt[i] == ASE_T('g') || fmt[i] == ASE_T('G') ||
fmt[i] == ASE_T('f'))
{
ase_awk_val_t* v;
ase_long_t l;
ase_real_t r;
ase_char_t* p;
int n;
if (args == ASE_NULL)
{
run->errnum = ASE_AWK_EPRINTFARG;
return ASE_NULL;
}
FMT_CHAR (ASE_T('L'));
FMT_CHAR (fmt[i]);
v = __eval_expression (run, args);
if (v == ASE_NULL) return ASE_NULL;
ase_awk_refupval (v);
n = ase_awk_valtonum (run, v, &l, &r);
ase_awk_refdownval (run, v);
if (n == -1) return ASE_NULL;
if (n == 0) r = (ase_real_t)l;
/* TODO: check the return value of syscas.sprintf and handle an error */
run->awk->syscas.sprintf (
run->sprintf.tmp,
ase_countof(run->sprintf.tmp),
run->sprintf.fmt.buf, (long double)r);
p = run->sprintf.tmp;
while (*p != ASE_T('\0'))
{
OUT_CHAR (*p);
p++;
}
}
else if (fmt[i] == ASE_T('c'))
{
ase_awk_val_t* v;
ase_char_t* p;
if (args == ASE_NULL)
{
run->errnum = ASE_AWK_EPRINTFARG;
return ASE_NULL;
}
FMT_CHAR (fmt[i]);
v = __eval_expression (run, args);
if (v == ASE_NULL) return ASE_NULL;
ase_awk_refupval (v);
if (v->type == ASE_AWK_VAL_NIL)
{
run->sprintf.tmp[0] = ASE_T('\0');
}
else if (v->type == ASE_AWK_VAL_INT)
{
run->awk->syscas.sprintf (
run->sprintf.tmp,
ase_countof(run->sprintf.tmp),
run->sprintf.fmt.buf,
(int)((ase_awk_val_int_t*)v)->val);
}
else if (v->type == ASE_AWK_VAL_REAL)
{
run->awk->syscas.sprintf (
run->sprintf.tmp,
ase_countof(run->sprintf.tmp),
run->sprintf.fmt.buf,
(int)((ase_awk_val_real_t*)v)->val);
}
else if (v->type == ASE_AWK_VAL_STR)
{
ase_awk_val_str_t* str = (ase_awk_val_str_t*)v;
if (str->len > 0)
{
run->awk->syscas.sprintf (
run->sprintf.tmp,
ase_countof(run->sprintf.tmp),
run->sprintf.fmt.buf, str->buf[0]);
}
else run->sprintf.tmp[0] = ASE_T('\0');
}
else
{
ase_awk_refdownval (run, v);
run->errnum = ASE_AWK_EVALTYPE;
return ASE_NULL;
}
ase_awk_refdownval (run, v);
p = run->sprintf.tmp;
while (*p != ASE_T('\0'))
{
OUT_CHAR (*p);
p++;
}
}
else if (fmt[i] == ASE_T('s'))
{
ase_awk_val_t* v;
ase_char_t* p;
if (args == ASE_NULL)
{
run->errnum = ASE_AWK_EPRINTFARG;
return ASE_NULL;
}
FMT_CHAR (fmt[i]);
v = __eval_expression (run, args);
if (v == ASE_NULL) return ASE_NULL;
ase_awk_refupval (v);
if (v->type == ASE_AWK_VAL_NIL)
{
run->sprintf.tmp[0] = ASE_T('\0');
}
else if (v->type == ASE_AWK_VAL_STR)
{
/* TODO: handle a string contailing null characters */
/* TODO: handle error conditions of sprintf */
run->awk->syscas.sprintf (
run->sprintf.tmp,
ase_countof(run->sprintf.tmp),
run->sprintf.fmt.buf,
((ase_awk_val_str_t*)v)->buf);
}
else
{
ase_size_t l;
p = ase_awk_valtostr (run, v,
ASE_AWK_VALTOSTR_CLEAR, ASE_NULL, &l);
if (p == ASE_NULL)
{
ase_awk_refdownval (run, v);
return ASE_NULL;
}
run->awk->syscas.sprintf (
run->sprintf.tmp,
ase_countof(run->sprintf.tmp),
run->sprintf.fmt.buf, p);
ASE_AWK_FREE (run->awk, p);
}
ase_awk_refdownval (run, v);
p = run->sprintf.tmp;
while (*p != ASE_T('\0'))
{
OUT_CHAR (*p);
p++;
}
}
else /*if (fmt[i] == ASE_T('%'))*/
{
for (j = 0; j < ASE_AWK_STR_LEN(&run->sprintf.fmt); j++)
OUT_CHAR (ASE_AWK_STR_CHAR(&run->sprintf.fmt,j));
OUT_CHAR (fmt[i]);
}
args = args->next;
ase_awk_str_clear (&run->sprintf.fmt);
}
/* flush uncompleted formatting sequence */
for (j = 0; j < ASE_AWK_STR_LEN(&run->sprintf.fmt); j++)
OUT_CHAR (ASE_AWK_STR_CHAR(&run->sprintf.fmt,j));
*len = ASE_AWK_STR_LEN(&run->sprintf.out);
return ASE_AWK_STR_BUF(&run->sprintf.out);
}

View File

@ -1,5 +1,5 @@
/* /*
* $Id: run.h,v 1.21 2006-10-24 04:10:12 bacon Exp $ * $Id: run.h,v 1.22 2006-11-13 15:08:54 bacon Exp $
*/ */
#ifndef _ASE_AWK_RUN_H_ #ifndef _ASE_AWK_RUN_H_
@ -100,4 +100,16 @@ enum
ASE_AWK_GLOBAL_SUBSEP ASE_AWK_GLOBAL_SUBSEP
}; };
#ifdef __cplusplus
extern "C" {
#endif
ase_char_t* ase_awk_sprintf (
ase_awk_run_t* run, const ase_char_t* fmt,
ase_size_t fmt_len, ase_awk_nde_t* args, ase_size_t* len);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* $Id: val.c,v 1.80 2006-10-30 14:31:37 bacon Exp $ * $Id: val.c,v 1.81 2006-11-13 15:08:54 bacon Exp $
*/ */
#include <ase/awk/awk_i.h> #include <ase/awk/awk_i.h>
@ -300,8 +300,7 @@ xp_printf (ASE_T("\n"));*/
{ {
ASE_AWK_ASSERTX (run->awk, ASE_AWK_ASSERTX (run->awk,
!"should never happen - invalid value type", !"should never happen - invalid value type",
"the type of a value should be one of ASE_AWK_VAL_XXX's" "the type of a value should be one of ASE_AWK_VAL_XXX's defined in val.h");
"defined in val.h");
} }
} }
@ -328,8 +327,7 @@ xp_printf (ASE_T("\n"));
*/ */
ASE_AWK_ASSERTX (run->awk, val->ref > 0, ASE_AWK_ASSERTX (run->awk, val->ref > 0,
"the reference count of a value should be greater than zero" "the reference count of a value should be greater than zero for it to be decremented. check the source code for any bugs");
"for it to be decremented. check the source code for any bugs");
val->ref--; val->ref--;
if (val->ref <= 0) if (val->ref <= 0)
@ -348,8 +346,7 @@ void ase_awk_refdownval_nofree (ase_awk_run_t* run, ase_awk_val_t* val)
if (ase_awk_isbuiltinval(val)) return; if (ase_awk_isbuiltinval(val)) return;
ASE_AWK_ASSERTX (run->awk, val->ref > 0, ASE_AWK_ASSERTX (run->awk, val->ref > 0,
"the reference count of a value should be greater than zero" "the reference count of a value should be greater than zero for it to be decremented. check the source code for any bugs");
"for it to be decremented. check the source code for any bugs");
val->ref--; val->ref--;
} }
@ -377,8 +374,7 @@ ase_bool_t ase_awk_valtobool (ase_awk_run_t* run, ase_awk_val_t* val)
ASE_AWK_ASSERTX (run->awk, ASE_AWK_ASSERTX (run->awk,
!"should never happen - invalid value type", !"should never happen - invalid value type",
"the type of a value should be one of ASE_AWK_VAL_XXX's" "the type of a value should be one of ASE_AWK_VAL_XXX's defined in val.h");
"defined in val.h");
return ase_false; return ase_false;
} }