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:
hyung-hwan 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);

View File

@ -49,9 +49,9 @@
*/
enum qse_awk_parsestd_type_t
{
QSE_AWK_PARSESTD_NULL = 0, /**< invalid type */
QSE_AWK_PARSESTD_FILE = 1, /**< file */
QSE_AWK_PARSESTD_STR = 2 /**< length-bounded string */
QSE_AWK_PARSESTD_NULL = 0, /**< invalid type */
QSE_AWK_PARSESTD_FILE = 1, /**< files */
QSE_AWK_PARSESTD_STR = 2 /**< length-bounded string */
};
typedef enum qse_awk_parsestd_type_t qse_awk_parsestd_type_t;
@ -65,18 +65,10 @@ struct qse_awk_parsestd_t
union
{
/**
* You can create a sio stream in advance and pass it to
* qse_awk_parsestd() via this field. */
qse_sio_t* sio;
struct
{
/** file path to open. QSE_NULL or '-' for stdin/stdout. */
const qse_char_t* path;
/* the streams created with the file path is set with this
* cmgr if it is not #QSE_NULL. */
qse_cmgr_t* cmgr;
const qse_char_t* path;
} file;
/**
@ -91,6 +83,10 @@ struct qse_awk_parsestd_t
*/
qse_xstr_t str;
} u;
/* the streams created with the file path is set with this
* cmgr if it is not #QSE_NULL. */
qse_cmgr_t* cmgr;
};
typedef struct qse_awk_parsestd_t qse_awk_parsestd_t;
@ -134,14 +130,15 @@ QSE_EXPORT void* qse_awk_getxtnstd (
* and deparses it out to a buffer 'buf'.
* @code
* int n;
* qse_awk_parsestd_t in;
* qse_awk_parsestd_t in[2];
* qse_awk_parsestd_t out;
*
* in.type = QSE_AWK_PARSESTD_STR;
* in.u.str.ptr = QSE_T("BEGIN { print 10; }");
* in.u.str.len = qse_strlen(in.u.str.ptr);
* in[0].type = QSE_AWK_PARSESTD_STR;
* in[0].u.str.ptr = QSE_T("BEGIN { print 10; }");
* in[0].u.str.len = qse_strlen(in.u.str.ptr);
* in[1].type = QSE_AWK_PARSESTD_NULL;
* out.type = QSE_AWK_PARSESTD_STR;
* n = qse_awk_parsestd (awk, &in, &out);
* n = qse_awk_parsestd (awk, in, &out);
* if (n >= 0)
* {
* qse_printf (QSE_T("%s\n"), out.u.str.ptr);
@ -151,7 +148,7 @@ QSE_EXPORT void* qse_awk_getxtnstd (
*/
QSE_EXPORT int qse_awk_parsestd (
qse_awk_t* awk,
qse_awk_parsestd_t* in,
qse_awk_parsestd_t in[],
qse_awk_parsestd_t* out
);

View File

@ -496,12 +496,19 @@ static int fnc_length (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
else
{
v = qse_awk_rtx_getarg (rtx, 0);
if (v->type == QSE_AWK_VAL_STR)
if (v->type == QSE_AWK_VAL_MAP)
{
/* map size */
len = QSE_HTB_SIZE(((qse_awk_val_map_t*)v)->map);
}
else if (v->type == QSE_AWK_VAL_STR)
{
/* string length */
len = ((qse_awk_val_str_t*)v)->val.len;
}
else
{
/* convert to string and get length */
str = qse_awk_rtx_valtostrdup (rtx, v, &len);
if (str == QSE_NULL) return -1;
QSE_AWK_FREE (rtx->awk, str);

View File

@ -255,11 +255,11 @@ static kwent_t kwtab[] =
{
/* keep this table in sync with the kw_t enums in <parse.h>.
* also keep it sorted by the first field for binary search */
{ { QSE_T("@abort"), 6 }, TOK_XABORT, QSE_AWK_EXTRAKWS },
{ { QSE_T("@global"), 7 }, TOK_XGLOBAL, QSE_AWK_EXTRAKWS },
{ { QSE_T("@include"), 8 }, TOK_XINCLUDE, QSE_AWK_EXTRAKWS },
{ { QSE_T("@local"), 6 }, TOK_XLOCAL, QSE_AWK_EXTRAKWS },
{ { QSE_T("@reset"), 6 }, TOK_XRESET, QSE_AWK_EXTRAKWS },
{ { QSE_T("@abort"), 6 }, TOK_XABORT, 0 },
{ { QSE_T("@global"), 7 }, TOK_XGLOBAL, 0 },
{ { QSE_T("@include"), 8 }, TOK_XINCLUDE, 0 },
{ { QSE_T("@local"), 6 }, TOK_XLOCAL, 0 },
{ { QSE_T("@reset"), 6 }, TOK_XRESET, 0 },
{ { QSE_T("BEGIN"), 5 }, TOK_BEGIN, QSE_AWK_PABLOCK },
{ { QSE_T("END"), 3 }, TOK_END, QSE_AWK_PABLOCK },
{ { QSE_T("break"), 5 }, TOK_BREAK, 0 },
@ -522,60 +522,53 @@ static int parse (qse_awk_t* awk)
adjust_static_globals (awk);
/* the user io handler for the source code input returns 0 when
* it doesn't have any files to open. this is the same condition
* as the source code file is empty. so it will perform the parsing
* when op is positive, which means there are something to parse */
if (op > 0)
/* get the first character and the first token */
if (get_char (awk) <= -1 || get_token (awk)) goto oops;
while (1)
{
/* get the first character and the first token */
if (get_char (awk) <= -1 || get_token (awk)) goto oops;
while (1)
while (MATCH(awk,TOK_NEWLINE))
{
while (MATCH(awk,TOK_NEWLINE))
{
if (get_token (awk) <= -1) goto oops;
}
if (MATCH(awk,TOK_EOF)) break;
if (parse_progunit (awk) <= -1) goto oops;
if (get_token (awk) <= -1) goto oops;
}
if (MATCH(awk,TOK_EOF)) break;
if (!(awk->opt.trait & QSE_AWK_IMPLICIT))
if (parse_progunit (awk) <= -1) goto oops;
}
if (!(awk->opt.trait & QSE_AWK_IMPLICIT))
{
/* ensure that all functions called are defined
* in the EXPLICIT-only mode */
qse_htb_pair_t* p;
qse_size_t buckno;
p = qse_htb_getfirstpair (awk->parse.funs, &buckno);
while (p != QSE_NULL)
{
/* ensure that all functions called are defined
* in the EXPLICIT-only mode */
qse_htb_pair_t* p;
qse_size_t buckno;
p = qse_htb_getfirstpair (awk->parse.funs, &buckno);
while (p != QSE_NULL)
if (qse_htb_search (awk->tree.funs,
QSE_HTB_KPTR(p), QSE_HTB_KLEN(p)) == QSE_NULL)
{
if (qse_htb_search (awk->tree.funs,
QSE_HTB_KPTR(p), QSE_HTB_KLEN(p)) == QSE_NULL)
{
qse_awk_nde_t* nde;
qse_awk_nde_t* nde;
/* see parse_fncall() for what is
* stored into awk->tree.funs */
nde = (qse_awk_nde_t*)QSE_HTB_VPTR(p);
/* see parse_fncall() for what is
* stored into awk->tree.funs */
nde = (qse_awk_nde_t*)QSE_HTB_VPTR(p);
SETERR_ARG_LOC (
awk,
QSE_AWK_EFUNNF,
QSE_HTB_KPTR(p),
QSE_HTB_KLEN(p),
&nde->loc
);
SETERR_ARG_LOC (
awk,
QSE_AWK_EFUNNF,
QSE_HTB_KPTR(p),
QSE_HTB_KLEN(p),
&nde->loc
);
goto oops;
}
p = qse_htb_getnextpair (awk->parse.funs, p, &buckno);
goto oops;
}
p = qse_htb_getnextpair (awk->parse.funs, p, &buckno);
}
}
@ -759,18 +752,6 @@ static int begin_include (qse_awk_t* awk)
goto oops;
}
if (op == 0)
{
CLRERR (awk);
op = awk->sio.inf (awk, QSE_AWK_SIO_CLOSE, arg, QSE_NULL, 0);
if (op != 0)
{
if (ISNOERR(awk)) SETERR_TOK (awk, QSE_AWK_ECLOSE);
else awk->errinf.loc = awk->tok.loc;
goto oops;
}
}
arg->next = awk->sio.inp;
awk->sio.inp = arg;
awk->parse.depth.incl++;
@ -6109,23 +6090,6 @@ static int deparse (qse_awk_t* awk)
return -1;
}
if (op == 0)
{
/* the result of the open operation indicates that the
* file has been open but reached the end. so it has to
* skip the entire deparsing procedure as it can't write
* any single characters on such an io handler. but note
* that this is not really an error for the parse and deparser.
*
* in fact, there are two ways to skip deparsing.
* 1. set awk->sio.inf to NULL.
* 2. set awk->sio.inf to a normal handler but
* make it return 0 on the OPEN request.
*/
n = 0;
goto exit_deparse;
}
#define EXIT_DEPARSE() do { n = -1; goto exit_deparse; } while(0)
if (awk->tree.ngbls > awk->tree.ngbls_base)

View File

@ -182,13 +182,6 @@ static int find_rio_in (
/* chain it */
p->next = run->rio.chain;
run->rio.chain = p;
/* usually, x == 0 indicates that it has reached the end
* of the input. the user I/O handler can return 0 for the
* open request if it doesn't have any files to open. One
* advantage of doing this would be that you can skip the
* entire pattern-block matching and execution. */
if (x == 0) p->in.eos = 1;
}
*rio = p;
@ -761,17 +754,6 @@ int qse_awk_rtx_writeio_str (
/* chain it */
p->next = run->rio.chain;
run->rio.chain = p;
/* usually, n == 0 indicates that it has reached the end
* of the input. the user I/O handler can return 0 for the
* open request if it doesn't have any files to open. One
* advantage of doing this would be that you can skip the
* entire pattern-block matching and execution. */
if (n == 0)
{
p->out.eos = 1;
return 0;
}
}
if (p->out.eos)

View File

@ -80,6 +80,8 @@ typedef struct xtn_t
struct
{
qse_awk_parsestd_t* x;
qse_size_t xindex;
union
{
struct
@ -649,58 +651,84 @@ static qse_sio_t* open_sio_std_rtx (qse_awk_rtx_t* rtx, qse_sio_std_t std, int f
}
/*** PARSESTD ***/
static int open_parsestd (qse_awk_t* awk, xtn_t* xtn, qse_size_t index)
{
qse_awk_parsestd_t* psin = &xtn->s.in.x[index];
switch (psin->type)
{
/* normal source files */
case QSE_AWK_PARSESTD_FILE:
if (psin->u.file.path == QSE_NULL ||
(psin->u.file.path[0] == QSE_T('-') &&
psin->u.file.path[1] == QSE_T('\0')))
{
/* special file name '-' */
qse_sio_t* tmp;
tmp = open_sio_std (awk, QSE_SIO_STDIN, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR);
if (tmp == QSE_NULL) return -1;
if (index >= 1 && xtn->s.in.x[index-1].type == QSE_AWK_PARSESTD_FILE)
qse_sio_close (xtn->s.in.u.file.sio);
xtn->s.in.u.file.sio = tmp;
}
else
{
qse_sio_t* tmp;
const qse_char_t* base;
tmp = open_sio (awk, psin->u.file.path, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR);
if (tmp == QSE_NULL) return -1;
if (index >= 1 && xtn->s.in.x[index-1].type == QSE_AWK_PARSESTD_FILE)
qse_sio_close (xtn->s.in.u.file.sio);
xtn->s.in.u.file.sio = tmp;
base = qse_basename (psin->u.file.path);
if (base != psin->u.file.path)
{
xtn->s.in.u.file.dir.ptr = psin->u.file.path;
xtn->s.in.u.file.dir.len = base - psin->u.file.path;
}
}
if (psin->cmgr) qse_sio_setcmgr (xtn->s.in.u.file.sio, psin->cmgr);
return 0;
case QSE_AWK_PARSESTD_STR:
if (index >= 1 && xtn->s.in.x[index-1].type == QSE_AWK_PARSESTD_FILE)
qse_sio_close (xtn->s.in.u.file.sio);
xtn->s.in.u.str.ptr = psin->u.str.ptr;
xtn->s.in.u.str.end = psin->u.str.ptr + psin->u.str.len;
return 0;
default:
qse_awk_seterrnum (awk, QSE_AWK_EINTERN, QSE_NULL);
return -1;
}
}
static qse_ssize_t sf_in_open (
qse_awk_t* awk, qse_awk_sio_arg_t* arg, xtn_t* xtn)
{
if (arg == QSE_NULL || arg->name == QSE_NULL)
{
switch (xtn->s.in.x->type)
{
case QSE_AWK_PARSESTD_FILE:
if (xtn->s.in.x->u.file.path == QSE_NULL ||
(xtn->s.in.x->u.file.path[0] == QSE_T('-') &&
xtn->s.in.x->u.file.path[1] == QSE_T('\0')))
{
/* special file name '-' */
xtn->s.in.u.file.sio = open_sio_std (
awk, QSE_SIO_STDIN, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR);
if (xtn->s.in.u.file.sio == QSE_NULL) return -1;
}
else
{
const qse_char_t* base;
xtn->s.in.u.file.sio = open_sio (
awk, xtn->s.in.x->u.file.path,
QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR
);
if (xtn->s.in.u.file.sio == QSE_NULL) return -1;
base = qse_basename (xtn->s.in.x->u.file.path);
if (base != xtn->s.in.x->u.file.path)
{
xtn->s.in.u.file.dir.ptr = xtn->s.in.x->u.file.path;
xtn->s.in.u.file.dir.len = base - xtn->s.in.x->u.file.path;
}
}
if (xtn->s.in.x->u.file.cmgr)
qse_sio_setcmgr (xtn->s.in.u.file.sio, xtn->s.in.x->u.file.cmgr);
return 1;
case QSE_AWK_PARSESTD_STR:
xtn->s.in.u.str.ptr = xtn->s.in.x->u.str.ptr;
xtn->s.in.u.str.end = xtn->s.in.x->u.str.ptr + xtn->s.in.x->u.str.len;
return 1;
default:
/* this should never happen */
qse_awk_seterrnum (awk, QSE_AWK_EINTERN, QSE_NULL);
return -1;
}
/* handle normal source input streams specified
* to qse_awk_parsestd() */
qse_ssize_t x;
x = open_parsestd (awk, xtn, 0);
if (x >= 0) xtn->s.in.xindex = 0; /* update the current stream index */
return x;
}
else
{
/* handle the included source file - @include */
const qse_char_t* file = arg->name;
qse_char_t fbuf[64];
qse_char_t* dbuf = QSE_NULL;
@ -733,7 +761,7 @@ static qse_ssize_t sf_in_open (
awk->mmgr, 0, file, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR
);
if (dbuf != QSE_NULL) QSE_MMGR_FREE (awk->mmgr, dbuf);
if (dbuf) QSE_MMGR_FREE (awk->mmgr, dbuf);
if (arg->handle == QSE_NULL)
{
qse_cstr_t ea;
@ -743,7 +771,7 @@ static qse_ssize_t sf_in_open (
return -1;
}
return 1;
return 0;
}
}
@ -752,12 +780,12 @@ static qse_ssize_t sf_in_close (
{
if (arg == QSE_NULL || arg->name == QSE_NULL)
{
switch (xtn->s.in.x->type)
switch (xtn->s.in.x[xtn->s.in.xindex].type)
{
case QSE_AWK_PARSESTD_FILE:
qse_sio_close (xtn->s.in.u.file.sio);
break;
case QSE_AWK_PARSESTD_STR:
/* nothing to close */
break;
@ -769,6 +797,7 @@ static qse_ssize_t sf_in_close (
}
else
{
/* handle the included source file - @include */
QSE_ASSERT (arg->handle != QSE_NULL);
qse_sio_close (arg->handle);
}
@ -780,22 +809,23 @@ static qse_ssize_t sf_in_read (
qse_awk_t* awk, qse_awk_sio_arg_t* arg,
qse_char_t* data, qse_size_t size, xtn_t* xtn)
{
if (arg == QSE_NULL || arg->name == QSE_NULL)
{
switch (xtn->s.in.x->type)
qse_ssize_t n;
again:
switch (xtn->s.in.x[xtn->s.in.xindex].type)
{
case QSE_AWK_PARSESTD_FILE:
{
qse_ssize_t n;
QSE_ASSERT (xtn->s.in.u.file.sio != QSE_NULL);
n = qse_sio_getstrn (xtn->s.in.u.file.sio, data, size);
if (n <= -1)
{
qse_cstr_t ea;
if (xtn->s.in.x->u.file.path)
if (xtn->s.in.x[xtn->s.in.xindex].u.file.path)
{
ea.ptr = xtn->s.in.x->u.file.path;
ea.ptr = xtn->s.in.x[xtn->s.in.xindex].u.file.path;
ea.len = qse_strlen(ea.ptr);
}
else
@ -805,28 +835,45 @@ static qse_ssize_t sf_in_read (
}
qse_awk_seterrnum (awk, QSE_AWK_EREAD, &ea);
}
return n;
}
break;
case QSE_AWK_PARSESTD_STR:
{
qse_size_t n = 0;
n = 0;
while (n < size && xtn->s.in.u.str.ptr < xtn->s.in.u.str.end)
{
data[n++] = *xtn->s.in.u.str.ptr++;
}
return n;
}
break;
default:
/* this should never happen */
qse_awk_seterrnum (awk, QSE_AWK_EINTERN, QSE_NULL);
return -1;
n = -1;
break;
}
if (n == 0)
{
/* reached end of the current stream. */
qse_size_t next = xtn->s.in.xindex + 1;
if (xtn->s.in.x[next].type != QSE_AWK_PARSESTD_NULL)
{
/* open the next stream if available. */
if (open_parsestd (awk, xtn, next) <= -1) n = -1;
else
{
/* if successful, close the current stream */
xtn->s.in.xindex = next; /* update the next to the current */
goto again;
}
}
}
return n;
}
else
{
/* handle the included source file - @include */
qse_ssize_t n;
QSE_ASSERT (arg->handle != QSE_NULL);
@ -899,8 +946,8 @@ static qse_ssize_t sf_out (
if (xtn->s.out.u.file.sio == QSE_NULL) return -1;
}
if (xtn->s.out.x->u.file.cmgr)
qse_sio_setcmgr (xtn->s.out.u.file.sio, xtn->s.out.x->u.file.cmgr);
if (xtn->s.out.x->cmgr)
qse_sio_setcmgr (xtn->s.out.u.file.sio, xtn->s.out.x->cmgr);
return 1;
case QSE_AWK_PARSESTD_STR:
@ -988,25 +1035,20 @@ static qse_ssize_t sf_out (
}
int qse_awk_parsestd (
qse_awk_t* awk, qse_awk_parsestd_t* in, qse_awk_parsestd_t* out)
qse_awk_t* awk, qse_awk_parsestd_t in[], qse_awk_parsestd_t* out)
{
qse_awk_sio_t sio;
xtn_t* xtn = (xtn_t*) QSE_XTN (awk);
int n;
if (in == QSE_NULL)
if (in == QSE_NULL || (in[0].type != QSE_AWK_PARSESTD_FILE &&
in[0].type != QSE_AWK_PARSESTD_STR))
{
/* the input is a must */
qse_awk_seterrnum (awk, QSE_AWK_EINVAL, QSE_NULL);
return -1;
}
if (in->type != QSE_AWK_PARSESTD_FILE &&
in->type != QSE_AWK_PARSESTD_STR)
{
qse_awk_seterrnum (awk, QSE_AWK_EINVAL, QSE_NULL);
return -1;
}
sio.in = sf_in;
xtn->s.in.x = in;

View File

@ -234,7 +234,7 @@ int qse_tio_attachout (
}
tio->errnum = QSE_TIO_ENOERR;
if (output (tio, QSE_TIO_OPEN, QSE_NULL, 0) == -1)
if (output (tio, QSE_TIO_OPEN, QSE_NULL, 0) <= -1)
{
if (tio->errnum == QSE_TIO_ENOERR) tio->errnum = QSE_TIO_EOTHER;
if (xbufptr != bufptr) QSE_MMGR_FREE (tio->mmgr, xbufptr);

View File

@ -383,16 +383,8 @@ static int open_script_stream (qse_sed_t* sed)
sed->src.loc.line = 1;
sed->src.loc.colm = 0;
if (n == 0)
{
sed->src.eof = 1;
return 0; /* end of file */
}
else
{
sed->src.eof = 0;
return 1;
}
sed->src.eof = 0;
return 0;
}
static int close_script_stream (qse_sed_t* sed)
@ -2516,16 +2508,6 @@ static int write_str_to_file (
else sed->errloc = cmd->loc;
return -1;
}
if (n == 0)
{
/* EOF is returned upon opening a write stream.
* it is also an error as it can't write
* a requested string */
sed->e.out.fun (sed, QSE_SED_IO_CLOSE, ap, QSE_NULL, 0);
ap->handle = QSE_NULL;
SETERR1 (sed, QSE_SED_EIOFIL, path, plen, &cmd->loc);
return -1;
}
}
while (len > 0)
@ -2582,12 +2564,6 @@ static int write_file (
/* it is ok if it is not able to open a file */
return 0;
}
if (n == 0)
{
/* EOF - no data */
sed->e.in.fun (sed, QSE_SED_IO_CLOSE, &arg, QSE_NULL, 0);
return 0;
}
while (1)
{
@ -3983,12 +3959,6 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_impl_t inf, qse_sed_io_impl_t outf)
SETERR0 (sed, QSE_SED_EIOUSR, QSE_NULL);
goto done3;
}
if (n == 0)
{
/* EOF reached upon opening an input stream.
* no data to process. this is success */
goto done2;
}
sed->errnum = QSE_SED_ENOERR;
sed->e.out.arg.path = QSE_NULL;
@ -4000,12 +3970,6 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_impl_t inf, qse_sed_io_impl_t outf)
SETERR0 (sed, QSE_SED_EIOUSR, QSE_NULL);
goto done2;
}
if (n == 0)
{
/* still don't know if we will write something.
* just mark EOF on the output stream and continue */
sed->e.out.eof = 1;
}
if (init_all_commands_for_exec (sed) <= -1)
{