From fed0a952ab65e7b0b0e349e242ef196eb9414a83 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Tue, 17 Feb 2009 19:41:53 +0000 Subject: [PATCH] fixed a bug in qse_awk_rtx_call() --- qse/README | 2 +- qse/doc/robodoc.rc | 5 ++++- qse/include/qse/awk/awk.h | 34 +++++++++++++++++++---------- qse/lib/awk/err.c | 5 +++-- qse/lib/awk/run.c | 32 +++++++++++++++++---------- qse/test/awk/awk03.c | 46 +++++++++++++++++++++++++++++---------- 6 files changed, 85 insertions(+), 39 deletions(-) diff --git a/qse/README b/qse/README index 895f88fb..bfeb7178 100644 --- a/qse/README +++ b/qse/README @@ -12,4 +12,4 @@ Cross compiling for WIN32 with MINGW32 Generate the API documents with robodoc. - robodoc --rc doc/robodoc.rc --css doc/robodoc.css --src include/qse --doc ./doc/qse --multidoc --index --html --source_line_numbers --nopre + robodoc --rc doc/robodoc.rc --css doc/robodoc.css --src include/qse --src test --doc ./doc/qse --multidoc --index --html --source_line_numbers --nopre diff --git a/qse/doc/robodoc.rc b/qse/doc/robodoc.rc index ccf57c20..23150212 100644 --- a/qse/doc/robodoc.rc +++ b/qse/doc/robodoc.rc @@ -1,6 +1,7 @@ items: NAME SYNOPSIS + SOURCE DESCRIPTION INPUT INPUTS @@ -30,6 +31,7 @@ item order: NOTES BUGS SEE ALSO + SOURCE remark begin markers: /* remark end markers: @@ -37,7 +39,8 @@ remark end markers: ignore files: .svn headertypes: - o "Overview" robo_overview 10 + o "Overview" robo_overview 10 + S "Sample Code" robo_sample 11 options: --cmode --nopre diff --git a/qse/include/qse/awk/awk.h b/qse/include/qse/awk/awk.h index f776f212..c8df6e15 100644 --- a/qse/include/qse/awk/awk.h +++ b/qse/include/qse/awk/awk.h @@ -165,6 +165,7 @@ struct qse_awk_riod_t qse_awk_riod_t* next; }; +/******/ struct qse_awk_prm_t { @@ -558,6 +559,8 @@ enum qse_awk_parse_ist_t QSE_AWK_PARSE_STRING = 1 }; +typedef enum qse_awk_errnum_t qse_awk_errnum_t; + typedef struct qse_awk_val_nil_t qse_awk_val_nil_t; typedef struct qse_awk_val_int_t qse_awk_val_int_t; typedef struct qse_awk_val_real_t qse_awk_val_real_t; @@ -774,11 +777,16 @@ qse_awk_prm_t* qse_awk_getprm ( /****f* AWK/qse_awk_getccls * NAME - * qse_awk_getcclas - get the character classifier + * qse_awk_getccls - get the character classifier + * DESCRIPTION + * The qse_awk_getccls() function returns the character classifier composed + * from the primitive functions in a call to qse_awk_open(). The data field + * is set to the awk object. The classifier returned is valid while the + * associated awk object is alive. * SYNOPSIS */ qse_ccls_t* qse_awk_getccls ( - qse_awk_t* ccls + qse_awk_t* awk ); /******/ @@ -807,8 +815,8 @@ int qse_awk_clear ( * SYNOPSIS */ const qse_char_t* qse_awk_geterrstr ( - qse_awk_t* awk, - int num + qse_awk_t* awk, + qse_awk_errnum_t num ); /******/ @@ -823,7 +831,7 @@ const qse_char_t* qse_awk_geterrstr ( */ int qse_awk_seterrstr ( qse_awk_t* awk, - int num, + qse_awk_errnum_t num, const qse_char_t* str ); /******/ @@ -1518,14 +1526,16 @@ qse_char_t* qse_awk_rtx_valtostr ( * The qse_awk_rtx_valtonum() function returns -1 on error, 0 if the converted * number is a long number and 1 if it is a real number. * EXAMPLES - * qse_long_t l; - * qse_real_t r; - * int n; + * The following example show how to convert a value to a number and + * determine if it is an integer or a floating-point number. + * qse_long_t l; + * qse_real_t r; + * int n; * - * n = qse_awk_rtx_valtonum (v, &l, &r); - * if (n == -1) error (); - * else if (n == 0) do_long (l); - * else if (n == 1) do_real (r); + * n = qse_awk_rtx_valtonum (v, &l, &r); + * if (n == -1) error (); + * else if (n == 0) do_long (l); + * else if (n == 1) do_real (r); * SYNOPSIS */ int qse_awk_rtx_valtonum ( diff --git a/qse/lib/awk/err.c b/qse/lib/awk/err.c index 7027e7ac..70a456d7 100644 --- a/qse/lib/awk/err.c +++ b/qse/lib/awk/err.c @@ -172,14 +172,15 @@ static const qse_char_t* __geterrstr (int errnum) return QSE_T("unknown error"); } -const qse_char_t* qse_awk_geterrstr (qse_awk_t* awk, int num) +const qse_char_t* qse_awk_geterrstr (qse_awk_t* awk, qse_awk_errnum_t num) { if (awk != QSE_NULL && awk->errstr[num] != QSE_NULL) return awk->errstr[num]; return __geterrstr (num); } -int qse_awk_seterrstr (qse_awk_t* awk, int num, const qse_char_t* str) +int qse_awk_seterrstr ( + qse_awk_t* awk, qse_awk_errnum_t num, const qse_char_t* str) { qse_char_t* dup; diff --git a/qse/lib/awk/run.c b/qse/lib/awk/run.c index 9d4a4335..abff5657 100644 --- a/qse/lib/awk/run.c +++ b/qse/lib/awk/run.c @@ -1474,7 +1474,7 @@ int qse_awk_rtx_call ( qse_awk_rtx_t* rtx, const qse_char_t* name, qse_awk_val_t** args, qse_size_t nargs) { - int ret; + int ret = 0; qse_map_pair_t* pair; qse_awk_fun_t* fun; struct capture_retval_data_t crdata; @@ -1543,29 +1543,37 @@ int qse_awk_rtx_call ( if (crdata.val == QSE_NULL) { QSE_ASSERT (rtx->errnum != QSE_AWK_ENOERR); + v = qse_awk_val_nil; /* defaults to nil */ ret = -1; } else { if (rtx->errnum == QSE_AWK_ENOERR) { - if (rtx->rcb.on_exit != QSE_NULL) - rtx->rcb.on_exit (rtx, crdata.val, rtx->rcb.data); + /* exiting with exit() */ + v = crdata.val; + /* no need to ref-up as it is done in + * capture_retval_on_exit() */ + } + else + { + v = qse_awk_val_nil; /* defaults to nil */ + ret = -1; } - else ret = -1; - qse_awk_rtx_refdownval(rtx, crdata.val); } } - else - { + else + { + /* the reference count of crdata.val is updated in + * capture_retval_on_exit(). update reference count of + * v here to balance it */ qse_awk_rtx_refupval (rtx, v); - - if (rtx->rcb.on_exit != QSE_NULL) - rtx->rcb.on_exit (rtx, v, rtx->rcb.data); - - qse_awk_rtx_refdownval (rtx, v); } + if (rtx->rcb.on_exit != QSE_NULL) + rtx->rcb.on_exit (rtx, v, rtx->rcb.data); + qse_awk_rtx_refdownval (rtx, v); + return ret; } diff --git a/qse/test/awk/awk03.c b/qse/test/awk/awk03.c index e0cdcb22..eb920697 100644 --- a/qse/test/awk/awk03.c +++ b/qse/test/awk/awk03.c @@ -1,26 +1,44 @@ +/****S* Sample/AWK + * DESCRIPTION + * This program demonstrates how to use qse_awk_rtx_call(). + * SOURCE + */ + #include #include const qse_char_t* src = QSE_T( "function init() { a = 20; }" "function main() { a++; }" - "function fini() { output (a); }" - "function output(x) { print x; }" + "function fini() { print a; }" ); +const qse_char_t* f[] = +{ + QSE_T("init"), + QSE_T("main"), + QSE_T("main"), + QSE_T("main"), + QSE_T("main"), + QSE_T("fini"), +}; + int main () { qse_awk_t* awk = QSE_NULL; qse_awk_rtx_t* rtx = QSE_NULL; - int ret; + int ret, i; awk = qse_awk_opensimple (); if (awk == QSE_NULL) { qse_fprintf (QSE_STDERR, QSE_T("error: cannot open awk\n")); - goto oops; + ret = -1; goto oops; } + /* don't allow BEGIN, END, pattern-action blocks */ + qse_awk_setoption (awk, qse_awk_getoption(awk) & ~QSE_AWK_PABLOCK); + ret = qse_awk_parsesimple ( awk, QSE_AWK_PARSE_STRING, src, /* parse AWK source in a string */ @@ -41,17 +59,23 @@ int main () { qse_fprintf (QSE_STDERR, QSE_T("error: %s\n"), qse_awk_geterrmsg(awk)); - goto oops; + ret = -1; goto oops; } - qse_awk_rtx_call (rtx, QSE_T("init"), QSE_NULL, 0); - qse_awk_rtx_call (rtx, QSE_T("main"), QSE_NULL, 0); - qse_awk_rtx_call (rtx, QSE_T("main"), QSE_NULL, 0); - qse_awk_rtx_call (rtx, QSE_T("main"), QSE_NULL, 0); - qse_awk_rtx_call (rtx, QSE_T("fini"), QSE_NULL, 0); + for (i = 0; i < QSE_COUNTOF(f); i++) + { + ret = qse_awk_rtx_call (rtx, f[i], QSE_NULL, 0); + if (ret == -1) + { + qse_fprintf (QSE_STDERR, QSE_T("%d error: %s\n"), + i, qse_awk_rtx_geterrmsg(rtx)); + goto oops; + } + } oops: if (rtx != QSE_NULL) qse_awk_rtx_close (rtx); if (awk != QSE_NULL) qse_awk_close (awk); - return -1; + return ret; } +/******/