added -v var=val to cmd/awk/awk.c

This commit is contained in:
hyung-hwan 2009-06-21 06:47:34 +00:00
parent cf606b6819
commit e66a372119
10 changed files with 348 additions and 346 deletions

View File

@ -1,5 +1,5 @@
/* /*
* $Id: awk.c 204 2009-06-18 12:08:06Z hyunghwan.chung $ * $Id: awk.c 205 2009-06-20 12:47:34Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -42,10 +42,10 @@
# include <errno.h> # include <errno.h>
#endif #endif
static qse_awk_rtx_t* app_rtx = NULL; static qse_awk_rtx_t* app_rtx = QSE_NULL;
static int app_debug = 0; static int app_debug = 0;
struct argout_t struct arg_t
{ {
qse_awk_parsestd_type_t ist; /* input source type */ qse_awk_parsestd_type_t ist; /* input source type */
union union
@ -58,14 +58,19 @@ struct argout_t
qse_awk_parsestd_type_t ost; /* output source type */ qse_awk_parsestd_type_t ost; /* output source type */
qse_char_t* osf; /* output source file */ qse_char_t* osf; /* output source file */
qse_char_t** arg;
qse_char_t** icf; /* input console files */ qse_char_t** icf; /* input console files */
qse_size_t icfl; /* the number of input console files */ qse_size_t icfl; /* the number of input console files */
qse_map_t* vm; /* global variable map */ qse_map_t* gvm; /* global variable map */
qse_char_t* fs; /* field separator */ qse_char_t* fs; /* field separator */
}; };
struct gvmv_t
{
int idx;
qse_char_t* ptr;
qse_size_t len;
};
static void dprint (const qse_char_t* fmt, ...) static void dprint (const qse_char_t* fmt, ...)
{ {
if (app_debug) if (app_debug)
@ -185,16 +190,33 @@ static void on_run_statement (
/*dprint (L"running %d\n", (int)line);*/ /*dprint (L"running %d\n", (int)line);*/
} }
static qse_map_walk_t set_global (
qse_map_t* map, qse_map_pair_t* pair, void* arg)
{
qse_awk_val_t* v;
qse_awk_rtx_t* rtx = (qse_awk_rtx_t*)arg;
struct gvmv_t* gvmv = (struct gvmv_t*)QSE_MAP_VPTR(pair);
v = qse_awk_rtx_makenstrval (rtx, gvmv->ptr, gvmv->len);
if (v == QSE_NULL) return QSE_MAP_WALK_STOP;
qse_awk_rtx_refupval (rtx, v);
qse_awk_rtx_setgbl (rtx, gvmv->idx, v);
qse_awk_rtx_refdownval (rtx, v);
return QSE_MAP_WALK_FORWARD;
}
static int on_run_enter (qse_awk_rtx_t* rtx, void* data) static int on_run_enter (qse_awk_rtx_t* rtx, void* data)
{ {
struct argout_t* ao = (struct argout_t*)data; struct arg_t* arg = (struct arg_t*)data;
if (ao->fs != QSE_NULL) if (arg->fs != QSE_NULL)
{ {
qse_awk_val_t* fs; qse_awk_val_t* fs;
/* compose a string value to use to set FS to */ /* compose a string value to use to set FS to */
fs = qse_awk_rtx_makestrval0 (rtx, ao->fs); fs = qse_awk_rtx_makestrval0 (rtx, arg->fs);
if (fs == QSE_NULL) return -1; if (fs == QSE_NULL) return -1;
/* change FS according to the command line argument */ /* change FS according to the command line argument */
@ -203,6 +225,15 @@ static int on_run_enter (qse_awk_rtx_t* rtx, void* data)
qse_awk_rtx_refdownval (rtx, fs); qse_awk_rtx_refdownval (rtx, fs);
} }
if (arg->gvm != QSE_NULL)
{
/* set the value of user-defined global variables
* to a runtime context */
qse_awk_rtx_seterrnum (rtx, QSE_AWK_ENOERR);
qse_map_walk (arg->gvm, set_global, rtx);
if (qse_awk_rtx_geterrnum(rtx) != QSE_AWK_ENOERR) return -1;
}
return 0; return 0;
} }
@ -270,11 +301,12 @@ static void print_usage (const qse_char_t* argv0)
qse_printf (QSE_T(" -f/--file sourcefile set the source script file\n")); qse_printf (QSE_T(" -f/--file sourcefile set the source script file\n"));
qse_printf (QSE_T(" -o/--deparsed-file deparsedfile set the deparsing output file\n")); qse_printf (QSE_T(" -o/--deparsed-file deparsedfile set the deparsing output file\n"));
qse_printf (QSE_T(" -F/--field-separator string set a field separator(FS)\n")); qse_printf (QSE_T(" -F/--field-separator string set a field separator(FS)\n"));
qse_printf (QSE_T(" -v/--assign var=value add a global variable with a value\n"));
qse_printf (QSE_T("\nYou may specify the following options to change the behavior of the interpreter.\n")); qse_printf (QSE_T("\nYou may specify the following options to change the behavior of the interpreter.\n"));
for (j = 0; j < QSE_COUNTOF(otab); j++) for (j = 0; j < QSE_COUNTOF(otab); j++)
{ {
qse_printf (QSE_T(" -%-20s -no%-20s\n"), otab[j].name, otab[j].name); qse_printf (QSE_T(" --%-20s --no%-20s\n"), otab[j].name, otab[j].name);
} }
} }
@ -320,7 +352,7 @@ static void out_of_memory (void)
qse_fprintf (QSE_STDERR, QSE_T("Error: out of memory\n")); qse_fprintf (QSE_STDERR, QSE_T("Error: out of memory\n"));
} }
static int handle_args (int argc, qse_char_t* argv[], struct argout_t* ao) static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg)
{ {
static qse_opt_lng_t lng[] = static qse_opt_lng_t lng[] =
{ {
@ -331,11 +363,9 @@ static int handle_args (int argc, qse_char_t* argv[], struct argout_t* ao)
{ QSE_T("idiv"), 0 }, { QSE_T("idiv"), 0 },
{ QSE_T("extio"), 0 }, { QSE_T("extio"), 0 },
{ QSE_T("newline"), 0 }, { QSE_T("newline"), 0 },
{ QSE_T("baseone"), 0 },
{ QSE_T("stripspaces"), 0 }, { QSE_T("stripspaces"), 0 },
{ QSE_T("nextofile"), 0 }, { QSE_T("nextofile"), 0 },
{ QSE_T("crlf"), 0 }, { QSE_T("crlf"), 0 },
{ QSE_T("argstomain"), 0 },
{ QSE_T("reset"), 0 }, { QSE_T("reset"), 0 },
{ QSE_T("maptovar"), 0 }, { QSE_T("maptovar"), 0 },
{ QSE_T("pablock"), 0 }, { QSE_T("pablock"), 0 },
@ -368,42 +398,43 @@ static int handle_args (int argc, qse_char_t* argv[], struct argout_t* ao)
qse_char_t* osf = QSE_NULL; /* output source file */ qse_char_t* osf = QSE_NULL; /* output source file */
qse_char_t** icf = QSE_NULL; /* input console files */ qse_char_t** icf = QSE_NULL; /* input console files */
qse_map_t* vm = QSE_NULL; /* global variable map */ qse_map_t* gvm = QSE_NULL; /* global variable map */
qse_char_t* fs = QSE_NULL; /* field separator */ qse_char_t* fs = QSE_NULL; /* field separator */
memset (ao, 0, QSE_SIZEOF(*ao)); memset (arg, 0, QSE_SIZEOF(*arg));
isf = (qse_char_t**) malloc (QSE_SIZEOF(*isf) * isfc); isf = (qse_char_t**) malloc (QSE_SIZEOF(*isf) * isfc);
if (isf == QSE_NULL) if (isf == QSE_NULL)
{ {
out_of_memory (); out_of_memory ();
ABORT (oops); goto oops;
} }
vm = qse_map_open (QSE_NULL, 0, 30, 70); gvm = qse_map_open (QSE_NULL, 0, 30, 70);
if (vm == QSE_NULL) if (gvm == QSE_NULL)
{ {
out_of_memory (); out_of_memory ();
ABORT (oops); goto oops;
} }
qse_map_setcopier (vm, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); /*qse_map_setcopier (gvm, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE);*/
qse_map_setcopier (vm, QSE_MAP_VAL, QSE_MAP_COPIER_INLINE); qse_map_setscale (gvm, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t));
qse_map_setscale (vm, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); qse_map_setcopier (gvm, QSE_MAP_VAL, QSE_MAP_COPIER_INLINE);
qse_map_setscale (vm, QSE_MAP_VAL, QSE_SIZEOF(qse_char_t)); qse_map_setscale (gvm, QSE_MAP_VAL, QSE_SIZEOF(struct gvmv_t));
while ((c = qse_getopt (argc, argv, &opt)) != QSE_CHAR_EOF) while ((c = qse_getopt (argc, argv, &opt)) != QSE_CHAR_EOF)
{ {
switch (c) switch (c)
{ {
case 0: case 0:
/* TODO: handle long options ... */
qse_printf (QSE_T(">>> [%s] [%s]\n"), opt.lngopt, opt.arg); qse_printf (QSE_T(">>> [%s] [%s]\n"), opt.lngopt, opt.arg);
break; break;
case QSE_T('h'): case QSE_T('h'):
print_usage (argv[0]); print_usage (argv[0]);
if (isf != QSE_NULL) free (isf); if (isf != QSE_NULL) free (isf);
if (vm != QSE_NULL) qse_map_close (vm); if (gvm != QSE_NULL) qse_map_close (gvm);
return 1; return 0;
case QSE_T('d'): case QSE_T('d'):
{ {
@ -420,7 +451,7 @@ static int handle_args (int argc, qse_char_t* argv[], struct argout_t* ao)
if (tmp == QSE_NULL) if (tmp == QSE_NULL)
{ {
out_of_memory (); out_of_memory ();
ABORT (oops); goto oops;
} }
isf = tmp; isf = tmp;
@ -445,19 +476,26 @@ static int handle_args (int argc, qse_char_t* argv[], struct argout_t* ao)
case QSE_T('v'): case QSE_T('v'):
{ {
qse_char_t* eq = qse_strchr(opt.arg, QSE_T('=')); struct gvmv_t gvmv;
qse_char_t* eq;
eq = qse_strchr(opt.arg, QSE_T('='));
if (eq == QSE_NULL) if (eq == QSE_NULL)
{ {
/* INVALID VALUE... */ /* INVALID VALUE... */
ABORT (oops); goto oops;
} }
*eq = QSE_T('\0'); *eq = QSE_T('\0');
if (qse_map_upsert (vm, opt.arg, qse_strlen(opt.arg)+1, eq, qse_strlen(eq)+1) == QSE_NULL) gvmv.idx = -1;
gvmv.ptr = ++eq;
gvmv.len = qse_strlen(eq);
if (qse_map_upsert (gvm, opt.arg, qse_strlen(opt.arg), &gvmv, 1) == QSE_NULL)
{ {
out_of_memory (); out_of_memory ();
ABORT (oops); goto oops;
} }
break; break;
} }
@ -473,7 +511,7 @@ static int handle_args (int argc, qse_char_t* argv[], struct argout_t* ao)
qse_printf (QSE_T("Error: illegal option - %c\n"), opt.opt); qse_printf (QSE_T("Error: illegal option - %c\n"), opt.opt);
} }
ABORT (oops); goto oops;
} }
case QSE_T(':'): case QSE_T(':'):
@ -487,11 +525,11 @@ static int handle_args (int argc, qse_char_t* argv[], struct argout_t* ao)
qse_printf (QSE_T("Error: bad argument for %c\n"), opt.opt); qse_printf (QSE_T("Error: bad argument for %c\n"), opt.opt);
} }
ABORT (oops); goto oops;
} }
default: default:
ABORT (oops); goto oops;
} }
} }
@ -502,19 +540,19 @@ static int handle_args (int argc, qse_char_t* argv[], struct argout_t* ao)
if (opt.ind >= argc) if (opt.ind >= argc)
{ {
/* no source code specified */ /* no source code specified */
ABORT (oops); goto oops;
} }
/* the source code is the string, not from the file */ /* the source code is the string, not from the file */
ao->ist = QSE_AWK_PARSESTD_CP; arg->ist = QSE_AWK_PARSESTD_CP;
ao->isp.str = argv[opt.ind++]; arg->isp.str = argv[opt.ind++];
free (isf); free (isf);
} }
else else
{ {
ao->ist = QSE_AWK_PARSESTD_FILE; arg->ist = QSE_AWK_PARSESTD_FILE;
ao->isp.files = isf; arg->isp.files = isf;
} }
if (opt.ind < argc) if (opt.ind < argc)
@ -526,7 +564,7 @@ static int handle_args (int argc, qse_char_t* argv[], struct argout_t* ao)
if (icf == QSE_NULL) if (icf == QSE_NULL)
{ {
out_of_memory (); out_of_memory ();
ABORT (oops); goto oops;
} }
if (opt.ind >= argc) if (opt.ind >= argc)
@ -542,32 +580,105 @@ static int handle_args (int argc, qse_char_t* argv[], struct argout_t* ao)
icf[icfl] = QSE_NULL; icf[icfl] = QSE_NULL;
} }
ao->ost = QSE_AWK_PARSESTD_FILE; arg->ost = QSE_AWK_PARSESTD_FILE;
ao->osf = osf; arg->osf = osf;
ao->icf = icf; arg->icf = icf;
ao->icfl = icfl; arg->icfl = icfl;
ao->vm = vm; arg->gvm = gvm;
ao->fs = fs; arg->fs = fs;
return 0; return 1;
oops: oops:
if (vm != QSE_NULL) qse_map_close (vm); if (gvm != QSE_NULL) qse_map_close (gvm);
if (icf != QSE_NULL) free (icf); if (icf != QSE_NULL) free (icf);
if (isf != QSE_NULL) free (isf); if (isf != QSE_NULL) free (isf);
return -1; return -1;
} }
static qse_awk_t* open_awk (void) static void freearg (struct arg_t* arg)
{
if (arg->ist == QSE_AWK_PARSESTD_FILE &&
arg->isp.files != QSE_NULL) free (arg->isp.files);
/*if (arg->osf != QSE_NULL) free (arg->osf);*/
if (arg->icf != QSE_NULL) free (arg->icf);
if (arg->gvm != QSE_NULL) qse_map_close (arg->gvm);
}
static void print_awkerr (qse_awk_t* awk)
{
qse_printf (
QSE_T("ERROR: CODE [%d] LINE [%u] %s\n"),
qse_awk_geterrnum(awk),
(unsigned int)qse_awk_geterrlin(awk),
qse_awk_geterrmsg(awk)
);
}
static void print_rtxerr (qse_awk_rtx_t* rtx)
{
qse_printf (
QSE_T("ERROR: CODE [%d] LINE [%u] %s\n"),
qse_awk_rtx_geterrnum(rtx),
(unsigned int)qse_awk_rtx_geterrlin(rtx),
qse_awk_rtx_geterrmsg(rtx)
);
}
qse_map_walk_t add_global (qse_map_t* map, qse_map_pair_t* pair, void* arg)
{
qse_awk_t* awk = (qse_awk_t*)arg;
struct gvmv_t* gvmv = (struct gvmv_t*)QSE_MAP_VPTR(pair);
gvmv->idx = qse_awk_addgbl (awk, QSE_MAP_KPTR(pair), QSE_MAP_KLEN(pair));
if (gvmv->idx <= -1)
{
return QSE_MAP_WALK_STOP;
}
return QSE_MAP_WALK_FORWARD;
}
static int awk_main (int argc, qse_char_t* argv[])
{ {
qse_awk_t* awk; qse_awk_t* awk;
qse_awk_rtx_t* rtx;
qse_awk_rcb_t rcb;
int i;
struct arg_t arg;
int ret = -1;
/* TODO: change it to support multiple source files */
qse_awk_parsestd_in_t psin;
qse_awk_parsestd_out_t psout;
qse_memset (&arg, 0, QSE_SIZEOF(arg));
i = comparg (argc, argv, &arg);
if (i <= -1)
{
print_usage (argv[0]);
return -1;
}
if (i == 0) return 0;
psin.type = arg.ist;
if (arg.ist == QSE_AWK_PARSESTD_CP) psin.u.cp = arg.isp.str;
else psin.u.file = arg.isp.files[0];
if (arg.osf != QSE_NULL)
{
psout.type = arg.ost;
psout.u.file = arg.osf;
}
awk = qse_awk_openstd (0); awk = qse_awk_openstd (0);
if (awk == QSE_NULL) if (awk == QSE_NULL)
{ {
qse_printf (QSE_T("ERROR: cannot open awk\n")); qse_printf (QSE_T("ERROR: cannot open awk\n"));
return QSE_NULL; goto oops;
} }
/* TODO: get depth from command line */ /* TODO: get depth from command line */
@ -580,118 +691,55 @@ static qse_awk_t* open_awk (void)
QSE_T("sleep"), 5, 0, QSE_T("sleep"), 5, 0,
1, 1, QSE_NULL, fnc_sleep) == QSE_NULL) 1, 1, QSE_NULL, fnc_sleep) == QSE_NULL)
{ {
qse_awk_close (awk); print_awkerr (awk);
qse_printf (QSE_T("ERROR: cannot add function 'sleep'\n")); goto oops;
return QSE_NULL;
} }
return awk; qse_awk_seterrnum (awk, QSE_AWK_ENOERR);
} qse_map_walk (arg.gvm, add_global, awk);
if (qse_awk_geterrnum(awk) != QSE_AWK_ENOERR)
static int awk_main (int argc, qse_char_t* argv[])
{ {
qse_awk_t* awk; print_awkerr (awk);
qse_awk_rtx_t* rtx; goto oops;
qse_awk_rcb_t rcb;
int i;
int runarg_count = 0;
qse_cstr_t runarg[128];
struct argout_t ao;
int ret = 0;
/* TODO: change it to support multiple source files */
qse_awk_parsestd_in_t psin;
qse_awk_parsestd_out_t psout;
qse_memset (&ao, 0, QSE_SIZEOF(ao));
i = handle_args (argc, argv, &ao);
if (i == -1)
{
print_usage (argv[0]);
return -1;
}
if (i == 1) return 0;
runarg[runarg_count].ptr = NULL;
runarg[runarg_count].len = 0;
awk = open_awk ();
if (awk == QSE_NULL) return -1;
psin.type = ao.ist;
if (ao.ist == QSE_AWK_PARSESTD_CP) psin.u.cp = ao.isp.str;
else psin.u.file = ao.isp.files[0];
if (ao.osf != QSE_NULL)
{
psout.type = ao.ost;
psout.u.file = ao.osf;
} }
if (qse_awk_parsestd (awk, &psin, if (qse_awk_parsestd (awk, &psin,
((ao.osf == QSE_NULL)? QSE_NULL: &psout)) == -1) ((arg.osf == QSE_NULL)? QSE_NULL: &psout)) == -1)
{ {
qse_printf ( print_awkerr (awk);
QSE_T("PARSE ERROR: CODE [%d] LINE [%u] %s\n"),
qse_awk_geterrnum(awk),
(unsigned int)qse_awk_geterrlin(awk),
qse_awk_geterrmsg(awk)
);
ret = -1;
goto oops; goto oops;
} }
rcb.on_enter = on_run_enter; rcb.on_enter = on_run_enter;
rcb.on_statement = on_run_statement; rcb.on_statement = on_run_statement;
rcb.on_exit = on_run_exit; rcb.on_exit = on_run_exit;
rcb.data = &ao; rcb.data = &arg;
rtx = qse_awk_rtx_openstd (awk, 0, QSE_T("qseawk"), ao.icf, QSE_NULL); rtx = qse_awk_rtx_openstd (awk, 0, QSE_T("qseawk"), arg.icf, QSE_NULL);
if (rtx == QSE_NULL) if (rtx == QSE_NULL)
{ {
qse_printf ( print_awkerr (awk);
QSE_T("PARSE ERROR: CODE [%d] LINE [%u] %s\n"), goto oops;
qse_awk_geterrnum(awk),
(unsigned int)qse_awk_geterrlin(awk),
qse_awk_geterrmsg(awk)
);
ret = -1;
} }
else
{
app_rtx = rtx; app_rtx = rtx;
set_intr_run ();
qse_awk_rtx_setrcb (rtx, &rcb); qse_awk_rtx_setrcb (rtx, &rcb);
ret = qse_awk_rtx_loop (rtx);
set_intr_run ();
ret = qse_awk_rtx_loop (rtx);
unset_intr_run (); unset_intr_run ();
if (ret == -1) if (ret == -1)
{ {
qse_printf (QSE_T("RUN ERROR: CODE [%d] LINE [%u] %s\n"), print_rtxerr (rtx);
(unsigned int)qse_awk_rtx_geterrnum(rtx), goto oops;
(unsigned int)qse_awk_rtx_geterrlin(rtx),
qse_awk_rtx_geterrmsg(rtx)
);
}
qse_awk_rtx_close (rtx);
} }
oops: oops:
qse_awk_close (awk); if (rtx != QSE_NULL) qse_awk_rtx_close (rtx);
if (awk != QSE_NULL) qse_awk_close (awk);
if (ao.ist == QSE_AWK_PARSESTD_FILE &&
ao.isp.files != QSE_NULL) free (ao.isp.files);
/*if (ao.osf != QSE_NULL) free (ao.osf);*/
if (ao.icf != QSE_NULL) free (ao.icf);
if (ao.vm != QSE_NULL) qse_map_close (ao.vm);
freearg (&arg);
return ret; return ret;
} }

View File

@ -1,5 +1,5 @@
/* /*
* $Id: Awk.hpp 204 2009-06-18 12:08:06Z hyunghwan.chung $ * $Id: Awk.hpp 205 2009-06-20 12:47:34Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -462,6 +462,7 @@ public:
ERR_BLKEND = QSE_AWK_EBLKEND, ERR_BLKEND = QSE_AWK_EBLKEND,
ERR_DUPBEG = QSE_AWK_EDUPBEG, ERR_DUPBEG = QSE_AWK_EDUPBEG,
ERR_DUPEND = QSE_AWK_EDUPEND, ERR_DUPEND = QSE_AWK_EDUPEND,
ERR_KWRED = QSE_AWK_EKWRED,
ERR_FNCRED = QSE_AWK_EFNCRED, ERR_FNCRED = QSE_AWK_EFNCRED,
ERR_FUNRED = QSE_AWK_EFUNRED, ERR_FUNRED = QSE_AWK_EFUNRED,
ERR_GBLRED = QSE_AWK_EGBLRED, ERR_GBLRED = QSE_AWK_EGBLRED,

View File

@ -1,5 +1,5 @@
/* /*
* $Id: awk.h 204 2009-06-18 12:08:06Z hyunghwan.chung $ * $Id: awk.h 205 2009-06-20 12:47:34Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -495,6 +495,7 @@ enum qse_awk_errnum_t
QSE_AWK_EBLKEND, /* END requires an action block */ QSE_AWK_EBLKEND, /* END requires an action block */
QSE_AWK_EDUPBEG, /* duplicate BEGIN */ QSE_AWK_EDUPBEG, /* duplicate BEGIN */
QSE_AWK_EDUPEND, /* duplicate END */ QSE_AWK_EDUPEND, /* duplicate END */
QSE_AWK_EKWRED, /* keyword redefined */
QSE_AWK_EFNCRED, /* intrinsic function redefined */ QSE_AWK_EFNCRED, /* intrinsic function redefined */
QSE_AWK_EFUNRED, /* function redefined */ QSE_AWK_EFUNRED, /* function redefined */
QSE_AWK_EGBLRED, /* global variable redefined */ QSE_AWK_EGBLRED, /* global variable redefined */
@ -1026,78 +1027,59 @@ void qse_awk_clrfnc (
/*****/ /*****/
/****f* AWK/qse_awk_parse /**
* NAME * The qse_awk_parse() function parses the source script.
* qse_awk_parse - parse source code * @return 0 on success, -1 on failure.
* SYNOPSIS
*/ */
int qse_awk_parse ( int qse_awk_parse (
qse_awk_t* awk, qse_awk_t* awk, /**< an awk object */
qse_awk_sio_t* sio qse_awk_sio_t* sio /**< source stream I/O handler */
); );
/******/
/****f* AWK/qse_awk_alloc /**
* NAME * The qse_awk_alloc() function allocates dynamic memory.
* qse_awk_alloc - allocate dynamic memory * @return a pointer to memory space allocated on success, QSE_NULL on failure
* RETURN
* the pointer to the memory space allocated on success, QSE_NULL on failure
* SYNOPSIS
*/ */
void* qse_awk_alloc ( void* qse_awk_alloc (
qse_awk_t* awk /* the pointer to a qse_awk_t instance */, qse_awk_t* awk, /**< an awk object */
qse_size_t size /* the size of memory to allocate in bytes */ qse_size_t size /**< size of memory to allocate in bytes */
); );
/******/
/****f* AWK/qse_awk_free /**
* NAME * The qse_awk_free() function frees dynamic memory allocated.
* qse_awk_free - free dynamic memory
* SYNOPSIS
*/ */
void qse_awk_free ( void qse_awk_free (
qse_awk_t* awk /* the pointer to a qse_awk_t instance */, qse_awk_t* awk, /**< an awk object */
void* ptr /* the pointer to the memory space to free */ void* ptr /**< memory space to free */
); );
/******/
/****f* AWK/qse_awk_strdup /**
* NAME
* qse_awk_strdup - duplicate a null-terminated string
* DESCRIPTION
* The qse_awk_strdup() function is used to duplicate a string using * The qse_awk_strdup() function is used to duplicate a string using
* the memory manager used by the associated qse_awk_t instance. * the memory manager used by the associated qse_awk_t instance.
* The new string should be freed using the qse_awk_free() function. * The new string should be freed using the qse_awk_free() function.
* RETURN *
* The qse_awk_strdup() function returns the pointer to a new string which * @return a pointer to a new string duplicated of @a s on success,
* is a duplicate of the string s. It returns QSE_NULL on failure. * QSE_NULL on failure.
* SYNOPSIS
*/ */
qse_char_t* qse_awk_strdup ( qse_char_t* qse_awk_strdup (
qse_awk_t* awk /* the pointer to a qse_awk_t instance */, qse_awk_t* awk, /**< an awk object */
const qse_char_t* str /* the pointer to a string */ const qse_char_t* str /**< a string pointer */
); );
/******/
/****f* AWK/qse_awk_strxdup /**
* NAME
* qse_awk_strxdup - duplicate a length-delimited string
* DESCRIPTION
* The qse_awk_strxdup() function is used to duplicate a string whose length * The qse_awk_strxdup() function is used to duplicate a string whose length
* is as long as len characters using the memory manager used by the * is as long as len characters using the memory manager used by the
* qse_awk_t instance. The new string should be freed using the qse_awk_free() * qse_awk_t instance. The new string should be freed using the qse_awk_free()
* function. * function.
* RETURN *
* The qse_awk_strxdup() function returns the pointer to a new string which * @return a pointer to a new string duplicated of @a s on success,
* is a duplicate of the string s on success. It returns QSE_NULL on failure. * QSE_NULL on failure.
* SYNOPSIS
*/ */
qse_char_t* qse_awk_strxdup ( qse_char_t* qse_awk_strxdup (
qse_awk_t* awk, qse_awk_t* awk, /**< an awk object */
const qse_char_t* str, const qse_char_t* str, /**< a string pointer */
qse_size_t len qse_size_t len /**< the number of character in a string */
); );
/******/
qse_long_t qse_awk_strxtolong ( qse_long_t qse_awk_strxtolong (
qse_awk_t* awk, qse_awk_t* awk,
@ -1476,6 +1458,12 @@ qse_awk_val_t* qse_awk_rtx_makestrval2 (
qse_size_t len2 qse_size_t len2
); );
qse_awk_val_t* qse_awk_rtx_makenstrval (
qse_awk_rtx_t* rtx,
const qse_char_t* str,
qse_size_t len
);
qse_awk_val_t* qse_awk_rtx_makerexval ( qse_awk_val_t* qse_awk_rtx_makerexval (
qse_awk_rtx_t* rtx, qse_awk_rtx_t* rtx,
const qse_char_t* buf, const qse_char_t* buf,

View File

@ -1,5 +1,5 @@
/* /*
* $Id: std.h 196 2009-06-11 07:44:44Z hyunghwan.chung $ * $Id: std.h 205 2009-06-20 12:47:34Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -22,9 +22,15 @@
#include <qse/awk/awk.h> #include <qse/awk/awk.h>
/** @file /** @file
* Standard AWK Interpreter * This file defines functions and data types that help you create
* an awk interpreter with less effort. It is designed to be as close
* to conventional awk implementations as possible.
*
* The source script handler does not evaluate a file name of the "var=val"
* form as an assignment expression. Instead, it just treats it as a
* normal file name.
*
* @todo * @todo
* - console name handling an empty string("") and assignment (v=yyyy)
* - StdAwk ARGV and console name handling * - StdAwk ARGV and console name handling
*/ */
@ -121,8 +127,8 @@ int qse_awk_parsestd (
/** /**
* The qse_awk_rtx_openstd() function creates a standard runtime context. * The qse_awk_rtx_openstd() function creates a standard runtime context.
* The caller should keep the contents of icf and ocf valid throughout * The caller should keep the contents of @a icf and @a ocf valid throughout
* the lifetime of the runtime context created. The runtime context * the lifetime of the runtime context created.
*/ */
qse_awk_rtx_t* qse_awk_rtx_openstd ( qse_awk_rtx_t* qse_awk_rtx_openstd (
qse_awk_t* awk, qse_awk_t* awk,
@ -132,15 +138,12 @@ qse_awk_rtx_t* qse_awk_rtx_openstd (
const qse_char_t*const* ocf const qse_char_t*const* ocf
); );
/****f* AWK/qse_awk_rtx_getxtnstd /**
* NAME * The qse_awk_rtx_getxtnstd() gets the pointer to extension space.
* qse_awk_rtx_getxtnstd - get the pointer to extension space
* SYNOPSIS
*/ */
void* qse_awk_rtx_getxtnstd ( void* qse_awk_rtx_getxtnstd (
qse_awk_rtx_t* rtx qse_awk_rtx_t* rtx
); );
/******/
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,5 +1,5 @@
/* /*
* $Id: map.h 101 2009-03-15 14:36:05Z hyunghwan.chung $ * $Id: map.h 205 2009-06-20 12:47:34Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -22,13 +22,9 @@
#include <qse/types.h> #include <qse/types.h>
#include <qse/macros.h> #include <qse/macros.h>
/****o* Common/Hash Map /**@file
* DESCRIPTION
* A hash map maintains buckets for key/value pairs with the same key hash * A hash map maintains buckets for key/value pairs with the same key hash
* chained under the same bucket. * chained under the same bucket.
*
* #include <qse/cmn/map.h>
******
*/ */
/* values that can be returned by qse_map_walker_t */ /* values that can be returned by qse_map_walker_t */
@ -49,29 +45,23 @@ typedef struct qse_map_pair_t qse_map_pair_t;
typedef enum qse_map_walk_t qse_map_walk_t; typedef enum qse_map_walk_t qse_map_walk_t;
typedef enum qse_map_id_t qse_map_id_t; typedef enum qse_map_id_t qse_map_id_t;
/****t* Common/qse_map_copier_t /**
* NAME * The qse_map_copier_t type defines a pair contruction callback
* qse_map_copier_t - define a pair contruction callback
* SYNOPSIS
*/ */
typedef void* (*qse_map_copier_t) ( typedef void* (*qse_map_copier_t) (
qse_map_t* map /* a map */, qse_map_t* map /* a map */,
void* dptr /* the pointer to a key or a value */, void* dptr /* the pointer to a key or a value */,
qse_size_t dlen /* the length of a key or a value */ qse_size_t dlen /* the length of a key or a value */
); );
/******/
/****t* Common/qse_map_freeer_t /**
* NAME * The qse_map_freeer_t defines a key/value destruction callback
* qse_map_freeer_t - define a key/value destruction callback
* SYNOPSIS
*/ */
typedef void (*qse_map_freeer_t) ( typedef void (*qse_map_freeer_t) (
qse_map_t* map /* a map */, qse_map_t* map /* a map */,
void* dptr /* the pointer to a key or a value */, void* dptr /* the pointer to a key or a value */,
qse_size_t dlen /* the length of a key or a value */ qse_size_t dlen /* the length of a key or a value */
); );
/******/
/* key hasher */ /* key hasher */
typedef qse_size_t (*qse_map_hasher_t) ( typedef qse_size_t (*qse_map_hasher_t) (
@ -80,108 +70,70 @@ typedef qse_size_t (*qse_map_hasher_t) (
qse_size_t klen /* the length of a key in bytes */ qse_size_t klen /* the length of a key in bytes */
); );
/****t* Common/qse_map_comper_t /**
* NAME
* qse_map_comper_t - define a key comparator
*
* DESCRIPTION
* The qse_map_comper_t type defines a key comparator that is called when * The qse_map_comper_t type defines a key comparator that is called when
* the map needs to compare keys. A map is created with a default comparator * the map needs to compare keys. A map is created with a default comparator
* which performs bitwise comparison between two keys. * which performs bitwise comparison between two keys.
* *
* The comparator should return 0 if the keys are the same and a non-zero * The comparator should return 0 if the keys are the same and a non-zero
* integer otherwise. * integer otherwise.
*
* SYNOPSIS
*/ */
typedef int (*qse_map_comper_t) ( typedef int (*qse_map_comper_t) (
qse_map_t* map /* a map */, qse_map_t* map, /**< a map */
const void* kptr1 /* the pointer to a key */, const void* kptr1, /**< the pointer to a key */
qse_size_t klen1 /* the length of a key */, qse_size_t klen1, /**< the length of a key */
const void* kptr2 /* the pointer to a key */, const void* kptr2, /**< the pointer to a key */
qse_size_t klen2 /* the length of a key */ qse_size_t klen2 /**< the length of a key */
); );
/******/
/****t* Common/qse_map_keeper_t /**
* NAME
* qse_map_keeper_t - define a value keeper
*
* DESCRIPTION
* The qse_map_keeper_t type defines a value keeper that is called when * The qse_map_keeper_t type defines a value keeper that is called when
* a value is retained in the context that it should be destroyed because * a value is retained in the context that it should be destroyed because
* it is identical to a new value. Two values are identical if their beginning * it is identical to a new value. Two values are identical if their beginning
* pointers and their lengths are equal. * pointers and their lengths are equal.
*
* SYNOPSIS
*/ */
typedef void (*qse_map_keeper_t) ( typedef void (*qse_map_keeper_t) (
qse_map_t* map /* a map */, qse_map_t* map, /**< a map */
void* vptr /* the pointer to a value */, void* vptr, /**< value pointer */
qse_size_t vlen /* the length of a value */ qse_size_t vlen /**< value length */
); );
/******/
/****t* Common/qse_map_sizer_t /**
* NAME
* qse_map_sizer_t - define a bucket size calculator
*
* DESCRIPTION
* The qse_map_sizer_T type defines a bucket size claculator that is called * The qse_map_sizer_T type defines a bucket size claculator that is called
* when a map should resize the bucket. The current bucket size +1 is passed * when a map should resize the bucket. The current bucket size +1 is passed
* as the hint. * as the hint.
*
* SYNOPSIS
*/ */
typedef qse_size_t (*qse_map_sizer_t) ( typedef qse_size_t (*qse_map_sizer_t) (
qse_map_t* map, /* a map */ qse_map_t* map, /**< a map */
qse_size_t hint /* a sizing hint */ qse_size_t hint /**< a sizing hint */
); );
/******/
/****t* Common/qse_map_walker_t /**
* NAME * The qse_map_walker_t defines a pair visitor.
* qse_map_walker_t - define a pair visitor
*
* SYNOPSIS
*/ */
typedef qse_map_walk_t (*qse_map_walker_t) ( typedef qse_map_walk_t (*qse_map_walker_t) (
qse_map_t* map /* a map */, qse_map_t* map, /**< a map */
qse_map_pair_t* pair /* the pointer to a key/value pair */, qse_map_pair_t* pair, /**< the pointer to a key/value pair */
void* arg /* the pointer to user-defined data */ void* arg /**< the pointer to user-defined data */
); );
/******/
/****s* Common/qse_map_pair_t /**
* NAME * The qse_map_pair_t type defines a map pair. A pair is composed of a key
* qse_map_pair_t - define a pair * and a value. It maintains pointers to the beginning of a key and a value
* * plus their length. The length is scaled down with the scale factor
* DESCRIPTION * specified in an owning map. Use macros defined in the
* A pair is composed of a key and a value. It maintains pointers to the
* beginning of a key and a value plus their length. The length is scaled
* down with the scale factor specified in an owning map. Use macros defined
* in the SEE ALSO section below to access individual fields.
*
* SEE ALSO
* QSE_MAP_KPTR, QSE_MAP_KLEN, QSE_MAP_VPTR, QSE_MAP_VLEN
*
* SYNOPSIS
*/ */
struct qse_map_pair_t struct qse_map_pair_t
{ {
void* kptr; /* the pointer to a key */ void* kptr; /**< the pointer to a key */
qse_size_t klen; /* the length of a key */ qse_size_t klen; /**< the length of a key */
void* vptr; /* the pointer to a value */ void* vptr; /**< the pointer to a value */
qse_size_t vlen; /* the length of a value */ qse_size_t vlen; /**< the length of a value */
qse_map_pair_t* next; /* the next pair under the same slot */ qse_map_pair_t* next; /**< the next pair under the same slot */
}; };
/*****/
/****s* Common/qse_map_t /**
* NAME * The qse_map_t type defines a hash map.
* qse_map_t - define a hash map
*
* SYNOPSIS
*/ */
struct qse_map_t struct qse_map_t
{ {
@ -201,7 +153,6 @@ struct qse_map_t
qse_size_t threshold; qse_size_t threshold;
qse_map_pair_t** bucket; qse_map_pair_t** bucket;
}; };
/******/
#define QSE_MAP_COPIER_SIMPLE ((qse_map_copier_t)1) #define QSE_MAP_COPIER_SIMPLE ((qse_map_copier_t)1)
#define QSE_MAP_COPIER_INLINE ((qse_map_copier_t)2) #define QSE_MAP_COPIER_INLINE ((qse_map_copier_t)2)

View File

@ -1,5 +1,5 @@
/* /*
* $Id: err.c 199 2009-06-14 08:40:52Z hyunghwan.chung $ * $Id: err.c 205 2009-06-20 12:47:34Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -88,6 +88,7 @@ const qse_char_t* qse_awk_dflerrstr (qse_awk_t* awk, qse_awk_errnum_t errnum)
QSE_T("END not followed by a left bracket on the same line"), QSE_T("END not followed by a left bracket on the same line"),
QSE_T("duplicate BEGIN"), QSE_T("duplicate BEGIN"),
QSE_T("duplicate END"), QSE_T("duplicate END"),
QSE_T("keyword '${0}' redefined"),
QSE_T("intrinsic function '${0}' redefined"), QSE_T("intrinsic function '${0}' redefined"),
QSE_T("function '${0}' redefined"), QSE_T("function '${0}' redefined"),
QSE_T("global variable '${0}' redefined"), QSE_T("global variable '${0}' redefined"),

View File

@ -1,5 +1,5 @@
/* /*
* $Id: parse.c 204 2009-06-18 12:08:06Z hyunghwan.chung $ * $Id: parse.c 205 2009-06-20 12:47:34Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -1403,12 +1403,10 @@ static void adjust_static_globals (qse_awk_t* awk)
if (gtab[id].valid != 0 && if (gtab[id].valid != 0 &&
(awk->option & gtab[id].valid) != gtab[id].valid) (awk->option & gtab[id].valid) != gtab[id].valid)
{ {
/*awk->parse.gbls.buf[id].name.len = 0;*/
QSE_LDA_DLEN(awk->parse.gbls,id) = 0; QSE_LDA_DLEN(awk->parse.gbls,id) = 0;
} }
else else
{ {
/*awk->parse.gbls.buf[id].name.len = gtab[id].name_len;*/
QSE_LDA_DLEN(awk->parse.gbls,id) = gtab[id].name_len; QSE_LDA_DLEN(awk->parse.gbls,id) = gtab[id].name_len;
} }
} }
@ -1487,6 +1485,15 @@ static int add_global (
{ {
qse_size_t ngbls; qse_size_t ngbls;
/* check if it is a keyword */
if (classify_ident (awk, name, len) != TOKEN_IDENT)
{
SETERRARG (
awk, QSE_AWK_EKWRED, awk->token.line,
name, len);
return -1;
}
/* check if it conflict with a builtin function name */ /* check if it conflict with a builtin function name */
if (qse_awk_getfnc (awk, name, len) != QSE_NULL) if (qse_awk_getfnc (awk, name, len) != QSE_NULL)
{ {
@ -1563,14 +1570,14 @@ int qse_awk_addgbl (
if (awk->tree.ngbls > awk->tree.ngbls_base) if (awk->tree.ngbls > awk->tree.ngbls_base)
{ {
/* this function is not allow after qse_awk_parse is called */ /* this function is not allowed after qse_awk_parse is called */
SETERR (awk, QSE_AWK_ENOPER); SETERR (awk, QSE_AWK_ENOPER);
return -1; return -1;
} }
n = add_global (awk, name, len, 0, 0); n = add_global (awk, name, len, 0, 0);
/* update the count of the static gbls. /* update the count of the static globals.
* the total global count has been updated inside add_global. */ * the total global count has been updated inside add_global. */
if (n >= 0) awk->tree.ngbls_base++; if (n >= 0) awk->tree.ngbls_base++;
@ -4662,7 +4669,7 @@ static int get_token (qse_awk_t* awk)
} }
*/ */
} }
else if (QSE_AWK_ISALPHA (awk, c) || c == QSE_T('_')) else if (c == QSE_T('_') || QSE_AWK_ISALPHA (awk, c))
{ {
int type; int type;
@ -4672,8 +4679,9 @@ static int get_token (qse_awk_t* awk)
ADD_TOKEN_CHAR (awk, c); ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c); GET_CHAR_TO (awk, c);
} }
while (QSE_AWK_ISALPHA (awk, c) || while (c == QSE_T('_') ||
c == QSE_T('_') || QSE_AWK_ISDIGIT(awk,c)); QSE_AWK_ISALPHA (awk, c) ||
QSE_AWK_ISDIGIT (awk, c));
type = classify_ident (awk, type = classify_ident (awk,
QSE_STR_PTR(awk->token.name), QSE_STR_PTR(awk->token.name),

View File

@ -1,5 +1,5 @@
/* /*
* $Id: rec.c 200 2009-06-14 13:22:00Z hyunghwan.chung $ * $Id: rec.c 205 2009-06-20 12:47:34Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -31,10 +31,6 @@ int qse_awk_rtx_setrec (
if (idx == 0) if (idx == 0)
{ {
qse_long_t l;
qse_real_t r;
int x;
if (str == QSE_STR_PTR(&run->inrec.line) && if (str == QSE_STR_PTR(&run->inrec.line) &&
len == QSE_STR_LEN(&run->inrec.line)) len == QSE_STR_LEN(&run->inrec.line))
{ {
@ -53,8 +49,7 @@ int qse_awk_rtx_setrec (
} }
} }
x = qse_awk_rtx_strtonum (run, 1, str, len, &l, &r); v = qse_awk_rtx_makenstrval (run, str, len);
v = qse_awk_rtx_makestrval (run, str, len);
if (v == QSE_NULL) if (v == QSE_NULL)
{ {
@ -62,14 +57,6 @@ int qse_awk_rtx_setrec (
return -1; return -1;
} }
if (x >= 0)
{
/* set the numeric string flag if a string
* can be converted to a number */
QSE_ASSERT (x == 0 || x == 1);
v->nstr = x + 1; /* long -> 1, real -> 2 */
}
QSE_ASSERT (run->inrec.d0->type == QSE_AWK_VAL_NIL); QSE_ASSERT (run->inrec.d0->type == QSE_AWK_VAL_NIL);
/* d0 should be cleared before the next line is reached /* d0 should be cleared before the next line is reached
* as it doesn't call qse_awk_rtx_refdownval on run->inrec.d0 */ * as it doesn't call qse_awk_rtx_refdownval on run->inrec.d0 */
@ -215,10 +202,6 @@ static int split_record (qse_awk_rtx_t* run)
while (p != QSE_NULL) while (p != QSE_NULL)
{ {
qse_long_t l;
qse_real_t r;
int x;
if (fs_len <= 1) if (fs_len <= 1)
{ {
p = qse_awk_rtx_strxntok ( p = qse_awk_rtx_strxntok (
@ -247,25 +230,18 @@ static int split_record (qse_awk_rtx_t* run)
run->inrec.flds[run->inrec.nflds].ptr = tok; run->inrec.flds[run->inrec.nflds].ptr = tok;
run->inrec.flds[run->inrec.nflds].len = tok_len; run->inrec.flds[run->inrec.nflds].len = tok_len;
x = qse_awk_rtx_strtonum (run, 1, tok, tok_len, &l, &r);
run->inrec.flds[run->inrec.nflds].val = run->inrec.flds[run->inrec.nflds].val =
qse_awk_rtx_makestrval (run, tok, tok_len); qse_awk_rtx_makenstrval (run, tok, tok_len);
if (run->inrec.flds[run->inrec.nflds].val == QSE_NULL) if (run->inrec.flds[run->inrec.nflds].val == QSE_NULL)
{ {
if (fs_free != QSE_NULL) QSE_AWK_FREE (run->awk, fs_free); if (fs_free != QSE_NULL)
QSE_AWK_FREE (run->awk, fs_free);
return -1; return -1;
} }
if (x >= 0) qse_awk_rtx_refupval (
{ run, run->inrec.flds[run->inrec.nflds].val);
/* set the numeric string flags if a string
* can be converted to a number */
QSE_ASSERT (x == 0 || x == 1);
run->inrec.flds[run->inrec.nflds].val->nstr = x + 1;
}
qse_awk_rtx_refupval (run, run->inrec.flds[run->inrec.nflds].val);
run->inrec.nflds++; run->inrec.nflds++;
len = QSE_STR_LEN(&run->inrec.line) - len = QSE_STR_LEN(&run->inrec.line) -

View File

@ -1,5 +1,5 @@
/* /*
* $Id: std.c 204 2009-06-18 12:08:06Z hyunghwan.chung $ * $Id: std.c 205 2009-06-20 12:47:34Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -599,6 +599,7 @@ static int open_rio_console (qse_awk_rtx_t* rtx, qse_awk_rio_arg_t* riod)
qse_sio_t* sio; qse_sio_t* sio;
const qse_char_t* file; const qse_char_t* file;
retry:
file = rxtn->c.in.files[rxtn->c.in.index]; file = rxtn->c.in.files[rxtn->c.in.index];
if (file == QSE_NULL) if (file == QSE_NULL)
@ -726,6 +727,7 @@ static qse_ssize_t awk_rio_console (
qse_sio_t* sio; qse_sio_t* sio;
const qse_char_t* file; const qse_char_t* file;
retry:
/* it has reached the end of the current file. /* it has reached the end of the current file.
* open the next file if available */ * open the next file if available */
if (rxtn->c.in.files == QSE_NULL || if (rxtn->c.in.files == QSE_NULL ||

View File

@ -1,5 +1,5 @@
/* /*
* $Id: val.c 200 2009-06-14 13:22:00Z hyunghwan.chung $ * $Id: val.c 205 2009-06-20 12:47:34Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -348,6 +348,30 @@ init:
return (qse_awk_val_t*)val; return (qse_awk_val_t*)val;
} }
qse_awk_val_t* qse_awk_rtx_makenstrval (
qse_awk_rtx_t* run, const qse_char_t* str, qse_size_t len)
{
int x;
qse_awk_val_t* v;
qse_long_t l;
qse_real_t r;
x = qse_awk_rtx_strtonum (run, 1, str, len, &l, &r);
v = qse_awk_rtx_makestrval (run, str, len);
if (v == QSE_NULL) return QSE_NULL;
if (x >= 0)
{
/* set the numeric string flag if a string
* can be converted to a number */
QSE_ASSERT (x == 0 || x == 1);
v->nstr = x + 1; /* long -> 1, real -> 2 */
}
return v;
}
qse_awk_val_t* qse_awk_rtx_makerexval ( qse_awk_val_t* qse_awk_rtx_makerexval (
qse_awk_rtx_t* run, const qse_char_t* buf, qse_size_t len, void* code) qse_awk_rtx_t* run, const qse_char_t* buf, qse_size_t len, void* code)
{ {