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:
parent
1ad89afa99
commit
f1f3080ab3
@ -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_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"));
|
||||
@ -622,8 +622,8 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg)
|
||||
{
|
||||
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,16 +801,45 @@ 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)
|
||||
{
|
||||
@ -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);
|
||||
|
@ -50,7 +50,7 @@
|
||||
enum qse_awk_parsestd_type_t
|
||||
{
|
||||
QSE_AWK_PARSESTD_NULL = 0, /**< invalid type */
|
||||
QSE_AWK_PARSESTD_FILE = 1, /**< file */
|
||||
QSE_AWK_PARSESTD_FILE = 1, /**< files */
|
||||
QSE_AWK_PARSESTD_STR = 2 /**< length-bounded string */
|
||||
};
|
||||
|
||||
@ -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;
|
||||
} 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
|
||||
);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,12 +522,6 @@ 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;
|
||||
|
||||
@ -577,7 +571,6 @@ static int parse (qse_awk_t* awk)
|
||||
p = qse_htb_getnextpair (awk->parse.funs, p, &buckno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QSE_ASSERT (awk->tree.ngbls == QSE_LDA_SIZE(awk->parse.gbls));
|
||||
ret = 0;
|
||||
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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,7 +780,7 @@ 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);
|
||||
@ -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)
|
||||
{
|
||||
case QSE_AWK_PARSESTD_FILE:
|
||||
{
|
||||
qse_ssize_t n;
|
||||
|
||||
again:
|
||||
switch (xtn->s.in.x[xtn->s.in.xindex].type)
|
||||
{
|
||||
case QSE_AWK_PARSESTD_FILE:
|
||||
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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user