make @word to be always on

simplified the return value of I/O handler's open function by eliminating the concept of EOF on opening.
enhanced qse_awk_parsestd() to accept an array of qse_awk_parsestd_t for input streams.
enhanced cmd/awk/awk.c to handle multiple -f's properly
This commit is contained in:
2012-11-25 16:16:44 +00:00
parent 1ad89afa99
commit f1f3080ab3
8 changed files with 248 additions and 266 deletions

View File

@ -74,14 +74,10 @@ struct xarg_t
struct arg_t
{
qse_awk_parsestd_type_t ist; /* input source type */
union
{
qse_char_t* str;
qse_char_t** files;
} isp;
qse_size_t isfl; /* the number of input source files */
int incl_conv;
qse_awk_parsestd_t* psin; /* input source streams */
qse_char_t* osf; /* output source file */
xarg_t icf; /* input console files */
qse_htb_t* gvm; /* global variable map */
@ -94,6 +90,7 @@ struct arg_t
unsigned int classic: 1;
int opton;
int optoff;
qse_ulong_t memlimit;
#if defined(QSE_BUILD_DEBUG)
qse_ulong_t failmalloc;
@ -378,7 +375,7 @@ struct opttab_t
} opttab[] =
{
{ QSE_T("implicit"), QSE_AWK_IMPLICIT, QSE_T("allow undeclared variables") },
{ QSE_T("extrakws"), QSE_AWK_EXTRAKWS, QSE_T("enable abort,reset,nextofile,OFILENAME,@include,@global,@local") },
{ QSE_T("extrakws"), QSE_AWK_EXTRAKWS, QSE_T("enable nextofile,OFILENAME") },
{ QSE_T("rio"), QSE_AWK_RIO, QSE_T("enable builtin I/O including getline & print") },
{ QSE_T("rwpipe"), QSE_AWK_RWPIPE, QSE_T("allow a dual-directional pipe") },
{ QSE_T("newline"), QSE_AWK_NEWLINE, QSE_T("enable a newline to terminate a statement") },
@ -566,10 +563,13 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg)
qse_cint_t c;
qse_size_t i;
qse_size_t isfc = 16; /* the capacity of isf */
qse_size_t isfl = 0; /* number of input source files */
qse_char_t** isf = QSE_NULL; /* input source files */
qse_char_t* osf = QSE_NULL; /* output source file */
qse_awk_parsestd_t* isf = QSE_NULL; /* input source files */
qse_char_t* osf = QSE_NULL; /* output source file */
qse_htb_t* gvm = QSE_NULL; /* global variable map */
qse_char_t* fs = QSE_NULL; /* field separator */
qse_char_t* call = QSE_NULL; /* function to call */
@ -577,7 +577,7 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg)
int oops_ret = -1;
int do_glob = 0;
isf = (qse_char_t**) malloc (QSE_SIZEOF(*isf) * isfc);
isf = (qse_char_t**) QSE_MMGR_ALLOC (arg->icf.mmgr, QSE_SIZEOF(*isf) * isfc);
if (isf == QSE_NULL)
{
print_error (QSE_T("out of memory\n"));
@ -620,10 +620,10 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg)
case QSE_T('f'):
{
if (isfl >= isfc-1) /* -1 for last QSE_NULL */
if (isfl >= isfc - 1) /* -1 for last QSE_NULL */
{
qse_char_t** tmp;
tmp = (qse_char_t**) realloc (isf, QSE_SIZEOF(*isf)*(isfc+16));
qse_awk_parsestd_t** tmp;
tmp = (qse_char_t**) QSE_MMGR_REALLOC (arg->icf.mmgr, isf, QSE_SIZEOF(*isf)*(isfc+16));
if (tmp == QSE_NULL)
{
print_error (QSE_T("out of memory\n"));
@ -634,7 +634,10 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg)
isfc = isfc + 16;
}
isf[isfl++] = opt.arg;
isf[isfl].type = QSE_AWK_PARSESTD_FILE;
isf[isfl].u.file.path = opt.arg;
isf[isfl].cmgr = QSE_NULL;
isfl++;
break;
}
@ -788,10 +791,9 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg)
}
}
isf[isfl] = QSE_NULL;
if (isfl <= 0)
{
/* no -f specified */
if (opt.ind >= argc)
{
/* no source code specified */
@ -799,17 +801,46 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg)
}
/* the source code is the string, not from the file */
arg->ist = QSE_AWK_PARSESTD_STR;
arg->isp.str = argv[opt.ind++];
isf[isfl].type = QSE_AWK_PARSESTD_STR;
isf[isfl].u.str.ptr = argv[opt.ind++];
isf[isfl].u.str.len = qse_strlen(isf[isfl].u.str.ptr);
free (isf);
isfl++;
}
else
else if (isfl >= 2)
{
arg->ist = QSE_AWK_PARSESTD_FILE;
arg->isp.files = isf;
/* if more than one -f has been specified, attempt to convert
* it to a single script containing @include statements. this way
* a parse error in a particular script file can be pin-pointed.
* qse_awk_parsestd() treats multiple QSE_AWK_PARSED_FILEs as
* a single stream concatenated. so this is a workaround. */
qse_str_t script;
if (qse_str_init (&script, arg->icf.mmgr, 256) >= 0)
{
for (i = 0; i < isfl; i++)
{
if (qse_str_cat (&script, QSE_T("@include \"")) == (qse_size_t)-1 ||
qse_str_cat (&script, isf[i].u.file.path) == (qse_size_t)-1 ||
qse_str_cat (&script, QSE_T("\";")) == (qse_size_t)-1)
{
goto incl_conv_oops;
}
}
qse_str_yield (&script, &isf[0].u.str, 0);
isf[0].type = QSE_AWK_PARSESTD_STR;
isfl = 1;
arg->incl_conv = 1;
incl_conv_oops:
qse_str_fini (&script);
}
}
for (i = 0; i < isfl ; i++) isf[isfl].cmgr = arg->script_cmgr;
isf[isfl].type = QSE_AWK_PARSESTD_NULL;
arg->psin = isf;
if (opt.ind < argc)
{
/* the remaining arguments are input console file names */
@ -830,14 +861,22 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg)
oops:
if (gvm != QSE_NULL) qse_htb_close (gvm);
purge_xarg (&arg->icf);
if (isf != QSE_NULL) free (isf);
if (isf)
{
if (arg->incl_conv) QSE_MMGR_FREE (arg->icf.mmgr, isf[0].u.str.ptr);
QSE_MMGR_FREE (arg->icf.mmgr, isf);
}
return oops_ret;
}
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->psin)
{
if (arg->incl_conv) QSE_MMGR_FREE (arg->icf.mmgr, arg->psin[0].u.str.ptr);
QSE_MMGR_FREE (arg->icf.mmgr, arg->psin);
}
/*if (arg->osf != QSE_NULL) free (arg->osf);*/
purge_xarg (&arg->icf);
if (arg->gvm != QSE_NULL) qse_htb_close (arg->gvm);
@ -961,7 +1000,6 @@ static int awk_main (int argc, qse_char_t* argv[])
#endif
/* TODO: change it to support multiple source files */
qse_awk_parsestd_t psin;
qse_awk_parsestd_t psout;
qse_mmgr_t* mmgr = QSE_MMGR_GETDFL();
@ -977,23 +1015,11 @@ static int awk_main (int argc, qse_char_t* argv[])
if (i == 2) return 0;
if (i == 3) return -1;
psin.type = arg.ist;
if (arg.ist == QSE_AWK_PARSESTD_STR)
{
psin.u.str.ptr = arg.isp.str;
psin.u.str.len = qse_strlen(arg.isp.str);
}
else
{
psin.u.file.path = arg.isp.files[0];
psin.u.file.cmgr = arg.script_cmgr;
}
if (arg.osf != QSE_NULL)
if (arg.osf)
{
psout.type = QSE_AWK_PARSESTD_FILE;
psout.u.file.path = arg.osf;
psout.u.file.cmgr = arg.script_cmgr;
psout.cmgr = arg.script_cmgr;
}
#if defined(QSE_BUILD_DEBUG)
@ -1051,7 +1077,7 @@ static int awk_main (int argc, qse_char_t* argv[])
goto oops;
}
if (qse_awk_parsestd (awk, &psin,
if (qse_awk_parsestd (awk, arg.psin,
((arg.osf == QSE_NULL)? QSE_NULL: &psout)) <= -1)
{
print_awkerr (awk);