added qse_sed_io_std_t and related code

This commit is contained in:
hyung-hwan 2011-09-18 09:41:26 +00:00
parent 0d4ea6aab9
commit ecaed2c2b3
13 changed files with 513 additions and 237 deletions

View File

@ -18,7 +18,7 @@
License along with QSE. If not, see <http://www.gnu.org/licenses/>. License along with QSE. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <qse/sed/sed.h> #include <qse/sed/std.h>
#include <qse/cmn/str.h> #include <qse/cmn/str.h>
#include <qse/cmn/mem.h> #include <qse/cmn/mem.h>
#include <qse/cmn/chr.h> #include <qse/cmn/chr.h>
@ -31,8 +31,10 @@
static const qse_char_t* g_script_file = QSE_NULL; static const qse_char_t* g_script_file = QSE_NULL;
static qse_char_t* g_script = QSE_NULL; static qse_char_t* g_script = QSE_NULL;
static const qse_char_t* g_infile = QSE_NULL; static qse_char_t* g_output_file = QSE_NULL;
static int g_infile_pos = 0;
static int g_option = 0; static int g_option = 0;
static int g_separate = 0;
static qse_ulong_t g_memlimit = 0; static qse_ulong_t g_memlimit = 0;
static qse_mmgr_t xma_mmgr = static qse_mmgr_t xma_mmgr =
@ -43,91 +45,6 @@ static qse_mmgr_t xma_mmgr =
QSE_NULL QSE_NULL
}; };
static qse_ssize_t in (
qse_sed_t* sed, qse_sed_io_cmd_t cmd,
qse_sed_io_arg_t* arg, qse_char_t* buf, qse_size_t size)
{
switch (cmd)
{
case QSE_SED_IO_OPEN:
{
const qse_char_t* file;
if (arg->path == QSE_NULL || arg->path[0] == QSE_T('\0'))
{
file = (g_infile == QSE_NULL)? QSE_NULL: g_infile;
}
else file = arg->path;
if (file == QSE_NULL) arg->handle = qse_sio_in;
else
{
arg->handle = qse_sio_open (
qse_sed_getmmgr(sed),
0,
file,
QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR
);
if (arg->handle == QSE_NULL) return -1;
}
return 1;
}
case QSE_SED_IO_CLOSE:
if (arg->handle != qse_sio_in) qse_sio_close (arg->handle);
return 0;
case QSE_SED_IO_READ:
return qse_sio_getsn (arg->handle, buf, size);
default:
return -1;
}
}
static qse_ssize_t out (
qse_sed_t* sed, qse_sed_io_cmd_t cmd,
qse_sed_io_arg_t* arg, qse_char_t* data, qse_size_t len)
{
switch (cmd)
{
case QSE_SED_IO_OPEN:
if (arg->path == QSE_NULL || arg->path[0] == QSE_T('\0'))
{
arg->handle = qse_sio_out;
}
else
{
arg->handle = qse_sio_open (
qse_sed_getmmgr(sed),
0,
arg->path,
QSE_SIO_WRITE |
QSE_SIO_CREATE |
QSE_SIO_TRUNCATE |
QSE_SIO_IGNOREMBWCERR
);
if (arg->handle == QSE_NULL) return -1;
}
return 1;
case QSE_SED_IO_CLOSE:
qse_sio_flush (arg->handle);
if (arg->handle != qse_sio_out) qse_sio_close (arg->handle);
return 0;
case QSE_SED_IO_WRITE:
return qse_sio_putsn (arg->handle, data, len);
default:
return -1;
}
}
static void print_usage (QSE_FILE* out, int argc, qse_char_t* argv[]) static void print_usage (QSE_FILE* out, int argc, qse_char_t* argv[])
{ {
const qse_char_t* b = qse_basename (argv[0]); const qse_char_t* b = qse_basename (argv[0]);
@ -139,8 +56,10 @@ static void print_usage (QSE_FILE* out, int argc, qse_char_t* argv[])
qse_fprintf (out, QSE_T(" -h show this message\n")); qse_fprintf (out, QSE_T(" -h show this message\n"));
qse_fprintf (out, QSE_T(" -n disable auto-print\n")); qse_fprintf (out, QSE_T(" -n disable auto-print\n"));
qse_fprintf (out, QSE_T(" -f file specify a script file\n")); qse_fprintf (out, QSE_T(" -f file specify a script file\n"));
qse_fprintf (out, QSE_T(" -o file specify an output file\n"));
qse_fprintf (out, QSE_T(" -r use the extended regular expression\n")); qse_fprintf (out, QSE_T(" -r use the extended regular expression\n"));
qse_fprintf (out, QSE_T(" -R enable non-standard extensions to the regular expression\n")); qse_fprintf (out, QSE_T(" -R enable non-standard extensions to the regular expression\n"));
qse_fprintf (out, QSE_T(" -s processes input files separately\n"));
qse_fprintf (out, QSE_T(" -a perform strict address check\n")); qse_fprintf (out, QSE_T(" -a perform strict address check\n"));
qse_fprintf (out, QSE_T(" -w allow address format of start~step\n")); qse_fprintf (out, QSE_T(" -w allow address format of start~step\n"));
qse_fprintf (out, QSE_T(" -x allow text on the same line as c, a, i\n")); qse_fprintf (out, QSE_T(" -x allow text on the same line as c, a, i\n"));
@ -152,7 +71,7 @@ static int handle_args (int argc, qse_char_t* argv[])
{ {
static qse_opt_t opt = static qse_opt_t opt =
{ {
QSE_T("hnf:rRawxym:"), QSE_T("hnf:o:rRsawxym:"),
QSE_NULL QSE_NULL
}; };
qse_cint_t c; qse_cint_t c;
@ -193,6 +112,10 @@ static int handle_args (int argc, qse_char_t* argv[])
g_script_file = opt.arg; g_script_file = opt.arg;
break; break;
case QSE_T('o'):
g_output_file = opt.arg;
break;
case QSE_T('r'): case QSE_T('r'):
g_option |= QSE_SED_EXTENDEDREX; g_option |= QSE_SED_EXTENDEDREX;
break; break;
@ -201,6 +124,10 @@ static int handle_args (int argc, qse_char_t* argv[])
g_option |= QSE_SED_NONSTDEXTREX; g_option |= QSE_SED_NONSTDEXTREX;
break; break;
case QSE_T('s'):
g_separate = 1;
break;
case QSE_T('a'): case QSE_T('a'):
g_option |= QSE_SED_STRICT; g_option |= QSE_SED_STRICT;
break; break;
@ -225,10 +152,9 @@ static int handle_args (int argc, qse_char_t* argv[])
if (opt.ind < argc && g_script_file == QSE_NULL) if (opt.ind < argc && g_script_file == QSE_NULL)
g_script = argv[opt.ind++]; g_script = argv[opt.ind++];
if (opt.ind < argc) g_infile = argv[opt.ind++]; if (opt.ind < argc) g_infile_pos = opt.ind;
if ((g_script_file == QSE_NULL && g_script == QSE_NULL) || if (g_script_file == QSE_NULL && g_script == QSE_NULL)
opt.ind < argc)
{ {
print_usage (QSE_STDERR, argc, argv); print_usage (QSE_STDERR, argc, argv);
return -1; return -1;
@ -291,6 +217,27 @@ qse_char_t* load_script_file (qse_sed_t* sed, const qse_char_t* file)
return xstr.ptr; return xstr.ptr;
} }
void print_exec_error (qse_sed_t* sed)
{
const qse_sed_loc_t* errloc = qse_sed_geterrloc(sed);
if (errloc->line > 0 || errloc->colm > 0)
{
qse_fprintf (QSE_STDERR,
QSE_T("cannot execute - %s at line %lu column %lu\n"),
qse_sed_geterrmsg(sed),
(unsigned long)errloc->line,
(unsigned long)errloc->colm
);
}
else
{
qse_fprintf (QSE_STDERR,
QSE_T("cannot execute - %s\n"),
qse_sed_geterrmsg(sed)
);
}
}
int sed_main (int argc, qse_char_t* argv[]) int sed_main (int argc, qse_char_t* argv[])
{ {
qse_mmgr_t* mmgr = QSE_NULL; qse_mmgr_t* mmgr = QSE_NULL;
@ -314,7 +261,7 @@ int sed_main (int argc, qse_char_t* argv[])
mmgr = &xma_mmgr; mmgr = &xma_mmgr;
} }
sed = qse_sed_open (mmgr, 0); sed = qse_sed_openstdwithmmgr (mmgr, 0);
if (sed == QSE_NULL) if (sed == QSE_NULL)
{ {
qse_fprintf (QSE_STDERR, QSE_T("cannot open a stream editor\n")); qse_fprintf (QSE_STDERR, QSE_T("cannot open a stream editor\n"));
@ -331,7 +278,7 @@ int sed_main (int argc, qse_char_t* argv[])
if (g_script == QSE_NULL) goto oops; if (g_script == QSE_NULL) goto oops;
} }
if (qse_sed_comp (sed, g_script, qse_strlen(g_script)) == -1) if (qse_sed_compstd (sed, g_script) == -1)
{ {
const qse_sed_loc_t* errloc = qse_sed_geterrloc(sed); const qse_sed_loc_t* errloc = qse_sed_geterrloc(sed);
if (errloc->line > 0 || errloc->colm > 0) if (errloc->line > 0 || errloc->colm > 0)
@ -353,26 +300,101 @@ int sed_main (int argc, qse_char_t* argv[])
goto oops; goto oops;
} }
if (qse_sed_exec (sed, in, out) == -1) if (g_separate && g_infile_pos > 0)
{ {
const qse_sed_loc_t* errloc = qse_sed_geterrloc(sed); qse_sed_iostd_t out;
if (errloc->line > 0 || errloc->colm > 0) qse_sed_iostd_t* output = QSE_NULL;
if (g_output_file &&
qse_strcmp (g_output_file, QSE_T("-")) != 0)
{ {
qse_fprintf (QSE_STDERR, out.type = QSE_SED_IOSTD_SIO;
QSE_T("cannot execute - %s at line %lu column %lu\n"), out.u.sio = qse_sio_open (
qse_sed_geterrmsg(sed), qse_sed_getmmgr(sed),
(unsigned long)errloc->line, 0,
(unsigned long)errloc->colm g_output_file,
QSE_SIO_WRITE |
QSE_SIO_CREATE |
QSE_SIO_TRUNCATE |
QSE_SIO_IGNOREMBWCERR
); );
if (out.u.sio == QSE_NULL)
{
qse_fprintf (QSE_STDERR, QSE_T("cannot open %s\n"), g_output_file);
goto oops;
}
output = &out;
} }
else
while (g_infile_pos < argc)
{ {
qse_fprintf (QSE_STDERR, qse_sed_iostd_t in[2];
QSE_T("cannot execute - %s\n"),
qse_sed_geterrmsg(sed) in[0].type = QSE_SED_IOSTD_FILE;
); in[0].u.file =
(qse_strcmp (argv[g_infile_pos], QSE_T("-")) == 0)?
QSE_NULL: argv[g_infile_pos];
in[1].type = QSE_SED_IOSTD_NULL;
if (qse_sed_execstd (sed, in, output) <= -1)
{
if (output) qse_sio_close (output->u.sio);
print_exec_error (sed);
goto oops;
}
g_infile_pos++;
}
if (output) qse_sio_close (output->u.sio);
}
else
{
int xx;
qse_sed_iostd_t* in = QSE_NULL;
qse_sed_iostd_t out;
if (g_infile_pos > 0)
{
int i, num_ins;
num_ins = argc - g_infile_pos;
in = QSE_MMGR_ALLOC (qse_sed_getmmgr(sed), QSE_SIZEOF(*in) * (num_ins + 1));
if (in == QSE_NULL)
{
qse_fprintf (QSE_STDERR, QSE_T("out of memory\n"));
goto oops;
}
for (i = 0; i < num_ins; i++)
{
in[i].type = QSE_SED_IOSTD_FILE;
in[i].u.file =
(qse_strcmp (argv[g_infile_pos], QSE_T("-")) == 0)?
QSE_NULL: argv[g_infile_pos];
g_infile_pos++;
}
in[i].type = QSE_SED_IOSTD_NULL;
}
if (g_output_file)
{
out.type = QSE_SED_IOSTD_FILE;
out.u.file =
(qse_strcmp (g_output_file, QSE_T("-")) == 0)?
QSE_NULL: g_output_file;
}
xx = qse_sed_execstd (sed, in, (g_output_file? &out: QSE_NULL));
if (in) QSE_MMGR_FREE (qse_sed_getmmgr(sed), in);
if (xx <= -1)
{
print_exec_error (sed);
goto oops;
} }
goto oops;
} }
ret = 0; ret = 0;

View File

@ -1,5 +1,5 @@
/* /*
* $Id: awk.h 549 2011-08-14 09:07:31Z hyunghwan.chung $ * $Id: awk.h 568 2011-09-17 15:41:26Z hyunghwan.chung $
* *
Copyright 2006-2011 Chung, Hyung-Hwan. Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.
@ -827,11 +827,10 @@ typedef enum qse_awk_option_t qse_awk_option_t;
enum qse_awk_errnum_t enum qse_awk_errnum_t
{ {
QSE_AWK_ENOERR, /**< no error */ QSE_AWK_ENOERR, /**< no error */
QSE_AWK_EUNKNOWN,/**< unknown error */
/* common errors */ /* common errors */
QSE_AWK_EINVAL, /**< invalid parameter or data */
QSE_AWK_ENOMEM, /**< insufficient memory */ QSE_AWK_ENOMEM, /**< insufficient memory */
QSE_AWK_EINVAL, /**< invalid parameter or data */
QSE_AWK_ENOSUP, /**< not supported */ QSE_AWK_ENOSUP, /**< not supported */
QSE_AWK_ENOPER, /**< operation not allowed */ QSE_AWK_ENOPER, /**< operation not allowed */
QSE_AWK_ENOENT, /**< '${0}' not found */ QSE_AWK_ENOENT, /**< '${0}' not found */

View File

@ -1,5 +1,5 @@
/* /*
* $Id: sio.h 565 2011-09-11 02:48:21Z hyunghwan.chung $ * $Id: sio.h 568 2011-09-17 15:41:26Z hyunghwan.chung $
* *
Copyright 2006-2011 Chung, Hyung-Hwan. Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.
@ -32,20 +32,20 @@
enum qse_sio_open_flag_t enum qse_sio_open_flag_t
{ {
QSE_SIO_HANDLE = QSE_FIO_HANDLE, QSE_SIO_HANDLE = QSE_FIO_HANDLE,
QSE_SIO_IGNOREMBWCERR = QSE_FIO_IGNOREMBWCERR, QSE_SIO_IGNOREMBWCERR = QSE_FIO_IGNOREMBWCERR,
QSE_SIO_READ = QSE_FIO_READ, QSE_SIO_READ = QSE_FIO_READ,
QSE_SIO_WRITE = QSE_FIO_WRITE, QSE_SIO_WRITE = QSE_FIO_WRITE,
QSE_SIO_APPEND = QSE_FIO_APPEND, QSE_SIO_APPEND = QSE_FIO_APPEND,
QSE_SIO_CREATE = QSE_FIO_CREATE, QSE_SIO_CREATE = QSE_FIO_CREATE,
QSE_SIO_TRUNCATE = QSE_FIO_TRUNCATE, QSE_SIO_TRUNCATE = QSE_FIO_TRUNCATE,
QSE_SIO_EXCLUSIVE = QSE_FIO_EXCLUSIVE, QSE_SIO_EXCLUSIVE = QSE_FIO_EXCLUSIVE,
QSE_SIO_SYNC = QSE_FIO_SYNC, QSE_SIO_SYNC = QSE_FIO_SYNC,
QSE_SIO_NOSHRD = QSE_FIO_NOSHRD, QSE_SIO_NOSHRD = QSE_FIO_NOSHRD,
QSE_SIO_NOSHWR = QSE_FIO_NOSHWR QSE_SIO_NOSHWR = QSE_FIO_NOSHWR
}; };
typedef qse_fio_off_t qse_sio_pos_t; typedef qse_fio_off_t qse_sio_pos_t;

View File

@ -49,6 +49,7 @@ enum qse_cut_errnum_t
{ {
QSE_CUT_ENOERR, /**< no error */ QSE_CUT_ENOERR, /**< no error */
QSE_CUT_ENOMEM, /**< insufficient memory */ QSE_CUT_ENOMEM, /**< insufficient memory */
QSE_CUT_EINVAL, /**< invalid parameter or data */
QSE_CUT_ESELNV, /**< selector not valid */ QSE_CUT_ESELNV, /**< selector not valid */
QSE_CUT_EIOFIL, /**< io error with file '${0}'*/ QSE_CUT_EIOFIL, /**< io error with file '${0}'*/
QSE_CUT_EIOUSR /**< error returned by user io handler */ QSE_CUT_EIOUSR /**< error returned by user io handler */

View File

@ -1,5 +1,5 @@
/* /*
* $Id: sed.h 563 2011-09-08 07:49:53Z hyunghwan.chung $ * $Id: sed.h 568 2011-09-17 15:41:26Z hyunghwan.chung $
* *
Copyright 2006-2011 Chung, Hyung-Hwan. Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.
@ -82,6 +82,7 @@ enum qse_sed_errnum_t
{ {
QSE_SED_ENOERR, /**< no error */ QSE_SED_ENOERR, /**< no error */
QSE_SED_ENOMEM, /**< insufficient memory */ QSE_SED_ENOMEM, /**< insufficient memory */
QSE_SED_EINVAL, /**< invalid parameter or data */
QSE_SED_ECMDNR, /**< command '${0}' not recognized */ QSE_SED_ECMDNR, /**< command '${0}' not recognized */
QSE_SED_ECMDMS, /**< command code missing */ QSE_SED_ECMDMS, /**< command code missing */
QSE_SED_ECMDIC, /**< command '${0}' incomplete */ QSE_SED_ECMDIC, /**< command '${0}' incomplete */

View File

@ -22,6 +22,7 @@
#define _QSE_SED_STD_H_ #define _QSE_SED_STD_H_
#include <qse/sed/sed.h> #include <qse/sed/sed.h>
#include <qse/cmn/sio.h>
/** @file /** @file
* This file defines easier-to-use helper interface for a stream editor. * This file defines easier-to-use helper interface for a stream editor.
@ -35,6 +36,29 @@
* functions. * functions.
*/ */
/**
* The qse_sed_iostd_t type defines standard I/O resources.
*/
typedef struct qse_sed_iostd_t qse_sed_iostd_t;
struct qse_sed_iostd_t
{
enum
{
QSE_SED_IOSTD_NULL, /** invalid resource */
QSE_SED_IOSTD_SIO,
QSE_SED_IOSTD_FILE,
QSE_SED_IOSTD_MEM
} type;
union
{
qse_sio_t* sio;
const qse_char_t* file;
qse_xstr_t mem;
} u;
};
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -82,15 +106,22 @@ int qse_sed_compstd (
/** /**
* The qse_sed_execstd() function executes the compiled script * The qse_sed_execstd() function executes the compiled script
* over an input file @a infile and an output file @a outfile. * over input streams @a in and an output stream @a out.
* If @a infile is #QSE_NULL, the standard console input is used. *
* If @a outfile is #QSE_NULL, the standard console output is used. * If @a in is not #QSE_NULL, it must point to a null-terminated array
* of standard I/O resources. if in[0] is QSE_NULL, this function
* returns failure, requiring at least 1 valid resource to be included
* in the array.
*
* If @a in is #QSE_NULL, the standard console input is used.
* If @a out is #QSE_NULL, the standard console output is used.
*
* @return 0 on success, -1 on failure * @return 0 on success, -1 on failure
*/ */
int qse_sed_execstd ( int qse_sed_execstd (
qse_sed_t* sed, /**< stream editor */ qse_sed_t* sed,
const qse_char_t* infile, /**< input file */ qse_sed_iostd_t in[],
const qse_char_t* outfile /**< output file */ qse_sed_iostd_t* out
); );
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,5 +1,5 @@
/* /*
* $Id: err.c 441 2011-04-22 14:28:43Z hyunghwan.chung $ * $Id: err.c 568 2011-09-17 15:41:26Z hyunghwan.chung $
* *
Copyright 2006-2011 Chung, Hyung-Hwan. Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.
@ -25,10 +25,9 @@ const qse_char_t* qse_awk_dflerrstr (qse_awk_t* awk, qse_awk_errnum_t errnum)
static const qse_char_t* errstr[] = static const qse_char_t* errstr[] =
{ {
QSE_T("no error"), QSE_T("no error"),
QSE_T("unknown error"),
QSE_T("invalid parameter or data"),
QSE_T("insufficient memory"), QSE_T("insufficient memory"),
QSE_T("invalid parameter or data"),
QSE_T("not supported"), QSE_T("not supported"),
QSE_T("operation not allowed"), QSE_T("operation not allowed"),
QSE_T("'${0}' not found"), QSE_T("'${0}' not found"),

View File

@ -1,5 +1,5 @@
/* /*
* $Id: sio.c 566 2011-09-11 12:44:56Z hyunghwan.chung $ * $Id: sio.c 568 2011-09-17 15:41:26Z hyunghwan.chung $
* *
Copyright 2006-2011 Chung, Hyung-Hwan. Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.
@ -39,6 +39,7 @@ static qse_sio_t __sio_in =
{ {
QSE_NULL, /* mmgr */ QSE_NULL, /* mmgr */
0, /* errnum */ 0, /* errnum */
#if defined(_WIN32) #if defined(_WIN32)
(HANDLE)STD_INPUT_HANDLE, /* handle */ (HANDLE)STD_INPUT_HANDLE, /* handle */
#elif defined(__OS2__) #elif defined(__OS2__)
@ -48,6 +49,7 @@ static qse_sio_t __sio_in =
#else #else
0, /* handle */ 0, /* handle */
#endif #endif
0, /* flags */ 0, /* flags */
QSE_NULL /* tio */ QSE_NULL /* tio */
}, },
@ -81,6 +83,7 @@ static qse_sio_t __sio_out =
{ {
QSE_NULL, QSE_NULL,
0, 0,
#if defined(_WIN32) #if defined(_WIN32)
(HANDLE)STD_OUTPUT_HANDLE, (HANDLE)STD_OUTPUT_HANDLE,
#elif defined(__OS2__) #elif defined(__OS2__)
@ -90,6 +93,7 @@ static qse_sio_t __sio_out =
#else #else
1, 1,
#endif #endif
0, 0,
QSE_NULL QSE_NULL
}, },
@ -123,6 +127,7 @@ static qse_sio_t __sio_err =
{ {
QSE_NULL, QSE_NULL,
0, 0,
#if defined(_WIN32) #if defined(_WIN32)
(HANDLE)STD_ERROR_HANDLE, (HANDLE)STD_ERROR_HANDLE,
#elif defined(__OS2__) #elif defined(__OS2__)
@ -132,6 +137,7 @@ static qse_sio_t __sio_err =
#else #else
2, 2,
#endif #endif
0, 0,
QSE_NULL QSE_NULL
}, },

View File

@ -27,6 +27,7 @@ const qse_char_t* qse_cut_dflerrstr (qse_cut_t* cut, qse_cut_errnum_t errnum)
{ {
QSE_T("no error"), QSE_T("no error"),
QSE_T("insufficient memory"), QSE_T("insufficient memory"),
QSE_T("invalid parameter or data"),
QSE_T("selector not valid"), QSE_T("selector not valid"),
QSE_T("io error with file '${0}'"), QSE_T("io error with file '${0}'"),
QSE_T("error returned by user io handler") QSE_T("error returned by user io handler")

View File

@ -1,5 +1,5 @@
/* /*
* $Id: err.c 562 2011-09-07 15:36:08Z hyunghwan.chung $ * $Id: err.c 568 2011-09-17 15:41:26Z hyunghwan.chung $
* *
Copyright 2006-2011 Chung, Hyung-Hwan. Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.
@ -27,6 +27,7 @@ const qse_char_t* qse_sed_dflerrstr (qse_sed_t* sed, qse_sed_errnum_t errnum)
{ {
QSE_T("no error"), QSE_T("no error"),
QSE_T("insufficient memory"), QSE_T("insufficient memory"),
QSE_T("invalid parameter or data"),
QSE_T("command '${0}' not recognized"), QSE_T("command '${0}' not recognized"),
QSE_T("command code missing"), QSE_T("command code missing"),
QSE_T("command '${0}' incomplete"), QSE_T("command '${0}' incomplete"),

View File

@ -1,5 +1,5 @@
/* /*
* $Id: sed.c 567 2011-09-14 15:48:08Z hyunghwan.chung $ * $Id: sed.c 568 2011-09-17 15:41:26Z hyunghwan.chung $
* *
Copyright 2006-2011 Chung, Hyung-Hwan. Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.
@ -103,7 +103,7 @@ int qse_sed_init (qse_sed_t* sed, qse_mmgr_t* mmgr)
); );
if (qse_str_init (&sed->e.txt.appended, mmgr, 256) <= -1) goto oops_5; if (qse_str_init (&sed->e.txt.appended, mmgr, 256) <= -1) goto oops_5;
if (qse_str_init (&sed->e.txt.held, mmgr, 256) <= -1) goto oops_6; if (qse_str_init (&sed->e.txt.hold, mmgr, 256) <= -1) goto oops_6;
if (qse_str_init (&sed->e.txt.subst, mmgr, 256) <= -1) goto oops_7; if (qse_str_init (&sed->e.txt.subst, mmgr, 256) <= -1) goto oops_7;
/* on init, the last points to the first */ /* on init, the last points to the first */
@ -114,7 +114,7 @@ int qse_sed_init (qse_sed_t* sed, qse_mmgr_t* mmgr)
return 0; return 0;
oops_7: oops_7:
qse_str_fini (&sed->e.txt.held); qse_str_fini (&sed->e.txt.hold);
oops_6: oops_6:
qse_str_fini (&sed->e.txt.appended); qse_str_fini (&sed->e.txt.appended);
oops_5: oops_5:
@ -133,7 +133,7 @@ void qse_sed_fini (qse_sed_t* sed)
free_all_command_blocks (sed); free_all_command_blocks (sed);
qse_str_fini (&sed->e.txt.subst); qse_str_fini (&sed->e.txt.subst);
qse_str_fini (&sed->e.txt.held); qse_str_fini (&sed->e.txt.hold);
qse_str_fini (&sed->e.txt.appended); qse_str_fini (&sed->e.txt.appended);
qse_map_fini (&sed->tmp.labs); qse_map_fini (&sed->tmp.labs);
@ -1817,6 +1817,7 @@ static int flush (qse_sed_t* sed)
while (sed->e.out.len > 0) while (sed->e.out.len > 0)
{ {
sed->errnum = QSE_SED_ENOERR; sed->errnum = QSE_SED_ENOERR;
n = sed->e.out.fun ( n = sed->e.out.fun (
sed, QSE_SED_IO_WRITE, &sed->e.out.arg, sed, QSE_SED_IO_WRITE, &sed->e.out.arg,
&sed->e.out.buf[pos], sed->e.out.len); &sed->e.out.buf[pos], sed->e.out.len);
@ -2694,7 +2695,7 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
case QSE_SED_CMD_HOLD: case QSE_SED_CMD_HOLD:
/* copy the pattern space to the hold space */ /* copy the pattern space to the hold space */
if (qse_str_ncpy (&sed->e.txt.held, if (qse_str_ncpy (&sed->e.txt.hold,
QSE_STR_PTR(&sed->e.in.line), QSE_STR_PTR(&sed->e.in.line),
QSE_STR_LEN(&sed->e.in.line)) == (qse_size_t)-1) QSE_STR_LEN(&sed->e.in.line)) == (qse_size_t)-1)
{ {
@ -2705,7 +2706,7 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
case QSE_SED_CMD_HOLD_APPEND: case QSE_SED_CMD_HOLD_APPEND:
/* append the pattern space to the hold space */ /* append the pattern space to the hold space */
if (qse_str_ncat (&sed->e.txt.held, if (qse_str_ncat (&sed->e.txt.hold,
QSE_STR_PTR(&sed->e.in.line), QSE_STR_PTR(&sed->e.in.line),
QSE_STR_LEN(&sed->e.in.line)) == (qse_size_t)-1) QSE_STR_LEN(&sed->e.in.line)) == (qse_size_t)-1)
{ {
@ -2717,8 +2718,8 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
case QSE_SED_CMD_RELEASE: case QSE_SED_CMD_RELEASE:
/* copy the hold space to the pattern space */ /* copy the hold space to the pattern space */
if (qse_str_ncpy (&sed->e.in.line, if (qse_str_ncpy (&sed->e.in.line,
QSE_STR_PTR(&sed->e.txt.held), QSE_STR_PTR(&sed->e.txt.hold),
QSE_STR_LEN(&sed->e.txt.held)) == (qse_size_t)-1) QSE_STR_LEN(&sed->e.txt.hold)) == (qse_size_t)-1)
{ {
SETERR0 (sed, QSE_SED_ENOMEM, QSE_NULL); SETERR0 (sed, QSE_SED_ENOMEM, QSE_NULL);
return QSE_NULL; return QSE_NULL;
@ -2728,8 +2729,8 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
case QSE_SED_CMD_RELEASE_APPEND: case QSE_SED_CMD_RELEASE_APPEND:
/* append the hold space to the pattern space */ /* append the hold space to the pattern space */
if (qse_str_ncat (&sed->e.in.line, if (qse_str_ncat (&sed->e.in.line,
QSE_STR_PTR(&sed->e.txt.held), QSE_STR_PTR(&sed->e.txt.hold),
QSE_STR_LEN(&sed->e.txt.held)) == (qse_size_t)-1) QSE_STR_LEN(&sed->e.txt.hold)) == (qse_size_t)-1)
{ {
SETERR0 (sed, QSE_SED_ENOMEM, QSE_NULL); SETERR0 (sed, QSE_SED_ENOMEM, QSE_NULL);
return QSE_NULL; return QSE_NULL;
@ -2738,7 +2739,7 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
case QSE_SED_CMD_EXCHANGE: case QSE_SED_CMD_EXCHANGE:
/* exchange the pattern space and the hold space */ /* exchange the pattern space and the hold space */
qse_str_swap (&sed->e.in.line, &sed->e.txt.held); qse_str_swap (&sed->e.in.line, &sed->e.txt.hold);
break; break;
case QSE_SED_CMD_NEXT: case QSE_SED_CMD_NEXT:
@ -3042,8 +3043,8 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf)
sed->e.subst_done = 0; sed->e.subst_done = 0;
qse_str_clear (&sed->e.txt.appended); qse_str_clear (&sed->e.txt.appended);
qse_str_clear (&sed->e.txt.subst); qse_str_clear (&sed->e.txt.subst);
qse_str_clear (&sed->e.txt.held); qse_str_clear (&sed->e.txt.hold);
if (qse_str_ccat (&sed->e.txt.held, QSE_T('\n')) == (qse_size_t)-1) if (qse_str_ccat (&sed->e.txt.hold, QSE_T('\n')) == (qse_size_t)-1)
{ {
SETERR0 (sed, QSE_SED_ENOMEM, QSE_NULL); SETERR0 (sed, QSE_SED_ENOMEM, QSE_NULL);
return -1; return -1;

View File

@ -1,5 +1,5 @@
/* /*
* $Id: sed.h 564 2011-09-10 16:14:38Z hyunghwan.chung $ * $Id: sed.h 568 2011-09-17 15:41:26Z hyunghwan.chung $
* *
Copyright 2006-2011 Chung, Hyung-Hwan. Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.
@ -262,7 +262,7 @@ struct qse_sed_t
struct struct
{ {
qse_str_t appended; qse_str_t appended;
qse_str_t held; qse_str_t hold; /* hold space */
qse_str_t subst; qse_str_t subst;
} txt; } txt;

View File

@ -26,8 +26,15 @@
struct xtn_t struct xtn_t
{ {
const qse_char_t* infile; struct
const qse_char_t* outfile; {
qse_sed_iostd_t* in;
qse_sed_iostd_t* out;
qse_sed_iostd_t* in_cur;
qse_size_t in_mempos;
qse_str_t* out_memstr;
} e;
}; };
typedef struct xtn_t xtn_t; typedef struct xtn_t xtn_t;
@ -63,6 +70,166 @@ int qse_sed_compstd (qse_sed_t* sed, const qse_char_t* sptr)
return qse_sed_comp (sed, sptr, qse_strlen(sptr)); return qse_sed_comp (sed, sptr, qse_strlen(sptr));
} }
static qse_sio_t* open_sio (qse_sed_t* sed, const qse_char_t* file, int flags)
{
qse_sio_t* sio;
sio = qse_sio_open (sed->mmgr, 0, file, flags);
if (sio == QSE_NULL)
{
qse_cstr_t ea;
ea.ptr = file;
ea.len = qse_strlen (file);
qse_sed_seterrnum (sed, QSE_SED_EIOFIL, &ea);
}
return sio;
}
static void close_main_stream (
qse_sed_t* sed, qse_sed_io_arg_t* arg, qse_sed_iostd_t* io)
{
if (io->type == QSE_SED_IOSTD_FILE)
{
qse_sio_t* sio = (qse_sio_t*)arg->handle;
if (sio != qse_sio_in && sio != qse_sio_out && sio != qse_sio_err)
qse_sio_close (sio);
}
}
static int open_main_input_stream (qse_sed_t* sed, qse_sed_io_arg_t* arg, qse_sed_iostd_t* io)
{
xtn_t* xtn = (xtn_t*) QSE_XTN (sed);
QSE_ASSERT (io != QSE_NULL);
switch (io->type)
{
case QSE_SED_IOSTD_SIO:
arg->handle = io->u.sio;
break;
case QSE_SED_IOSTD_FILE:
if (io->u.file == QSE_NULL)
{
arg->handle = qse_sio_in;
}
else
{
qse_sio_t* sio;
sio = open_sio (sed, io->u.file, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR);
if (sio == QSE_NULL) return -1;
arg->handle = sio;
}
break;
case QSE_SED_IOSTD_MEM:
/* don't store anything to arg->handle */
xtn->e.in_mempos = 0;
break;
}
return 0;
}
static int open_main_output_stream (qse_sed_t* sed, qse_sed_io_arg_t* arg, qse_sed_iostd_t* io)
{
xtn_t* xtn = (xtn_t*) QSE_XTN (sed);
QSE_ASSERT (io != QSE_NULL);
switch (io->type)
{
case QSE_SED_IOSTD_SIO:
arg->handle = io->u.sio;
break;
case QSE_SED_IOSTD_FILE:
if (io->u.file == QSE_NULL)
{
arg->handle = qse_sio_out;
}
else
{
qse_sio_t* sio;
sio = open_sio (sed, io->u.file,
QSE_SIO_WRITE |
QSE_SIO_CREATE |
QSE_SIO_TRUNCATE |
QSE_SIO_IGNOREMBWCERR
);
if (sio == QSE_NULL) return -1;
arg->handle = sio;
}
break;
case QSE_SED_IOSTD_MEM:
/* don't store anything to arg->handle */
xtn->e.out_memstr = qse_str_open (sed->mmgr, 0, 512);
if (xtn->e.out_memstr == QSE_NULL)
{
qse_sed_seterrnum (sed, QSE_SED_ENOMEM, QSE_NULL);
return -1;
}
break;
}
return 0;
}
static qse_ssize_t read_main_input_stream (
qse_sed_t* sed, qse_sed_io_arg_t* arg, qse_char_t* buf, qse_size_t len)
{
xtn_t* xtn = (xtn_t*) QSE_XTN (sed);
qse_sed_iostd_t* io, * next;
void* old, * new;
qse_ssize_t n = 0;
if (len > QSE_TYPE_MAX(qse_ssize_t)) len = QSE_TYPE_MAX(qse_ssize_t);
do
{
io = xtn->e.in_cur;
QSE_ASSERT (io != QSE_NULL);
if (io->type == QSE_SED_IOSTD_MEM)
{
n = 0;
while (xtn->e.in_mempos < io->u.mem.len && n < len)
buf[n++] = io->u.mem.ptr[xtn->e.in_mempos++];
}
else n = qse_sio_getsn (arg->handle, buf, len);
if (n != 0) break;
/* end of file on the current input stream */
next = xtn->e.in_cur + 1;
if (next->type == QSE_SED_IOSTD_NULL)
{
/* no next stream available - return 0 */
break;
}
old = arg->handle;
/* try to open the next input stream */
if (open_main_input_stream (sed, arg, next) <= -1)
{
/* failed to open the next input stream */
n = -1;
break;
}
new = arg->handle;
arg->handle = old;
close_main_stream (sed, arg, io);
arg->handle = new;
xtn->e.in_cur++;
}
while (1);
return n;
}
static qse_ssize_t xin ( static qse_ssize_t xin (
qse_sed_t* sed, qse_sed_io_cmd_t cmd, qse_sed_io_arg_t* arg, qse_sed_t* sed, qse_sed_io_cmd_t cmd, qse_sed_io_arg_t* arg,
qse_char_t* buf, qse_size_t len) qse_char_t* buf, qse_size_t len)
@ -77,67 +244,53 @@ static qse_ssize_t xin (
if (arg->path == QSE_NULL) if (arg->path == QSE_NULL)
{ {
/* main data stream */ /* main data stream */
if (xtn->infile == QSE_NULL) sio = qse_sio_in; if (xtn->e.in == QSE_NULL) arg->handle = qse_sio_in;
else else
{ {
sio = qse_sio_open ( if (open_main_input_stream (sed, arg, xtn->e.in_cur) <= -1) return -1;
sed->mmgr,
0,
xtn->infile,
QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR
);
if (sio == QSE_NULL)
{
/* set the error message explicitly
* as the file name is different from
* the standard console name (NULL) */
qse_cstr_t ea;
ea.ptr = xtn->infile;
ea.len = qse_strlen (xtn->infile);
qse_sed_seterrnum (sed,QSE_SED_EIOFIL, &ea);
return -1;
}
} }
} }
else else
{ {
sio = qse_sio_open ( sio = open_sio (sed, arg->path, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR);
sed->mmgr, if (sio == QSE_NULL) return -1;
0, arg->handle = sio;
arg->path,
QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR
);
} }
if (sio == QSE_NULL) return -1;
arg->handle = sio;
return 1; return 1;
} }
case QSE_SED_IO_CLOSE: case QSE_SED_IO_CLOSE:
{ {
sio = (qse_sio_t*)arg->handle; if (arg->path == QSE_NULL)
if (sio != qse_sio_in && sio != qse_sio_out && sio != qse_sio_err) {
qse_sio_close (sio); /* main data stream */
if (xtn->e.in) close_main_stream (sed, arg, xtn->e.in_cur);
}
else
{
sio = (qse_sio_t*)arg->handle;
if (sio != qse_sio_in && sio != qse_sio_out && sio != qse_sio_err)
qse_sio_close (sio);
}
return 0; return 0;
} }
case QSE_SED_IO_READ: case QSE_SED_IO_READ:
{ {
qse_ssize_t n = qse_sio_getsn (arg->handle, buf, len); if (arg->path == QSE_NULL)
if (n == -1)
{ {
if (arg->path == QSE_NULL && xtn->infile != QSE_NULL) /* main data stream */
{ if (xtn->e.in == QSE_NULL)
qse_cstr_t ea; return qse_sio_getsn (arg->handle, buf, len);
ea.ptr = xtn->infile; else
ea.len = qse_strlen (xtn->infile); return read_main_input_stream (sed, arg, buf, len);
qse_sed_seterrnum (sed, QSE_SED_EIOFIL, &ea); }
} else
{
return qse_sio_getsn (arg->handle, buf, len);
} }
return n;
} }
default: default:
@ -149,8 +302,8 @@ static qse_ssize_t xout (
qse_sed_t* sed, qse_sed_io_cmd_t cmd, qse_sed_io_arg_t* arg, qse_sed_t* sed, qse_sed_io_cmd_t cmd, qse_sed_io_arg_t* arg,
qse_char_t* dat, qse_size_t len) qse_char_t* dat, qse_size_t len)
{ {
qse_sio_t* sio;
xtn_t* xtn = (xtn_t*) QSE_XTN (sed); xtn_t* xtn = (xtn_t*) QSE_XTN (sed);
qse_sio_t* sio;
switch (cmd) switch (cmd)
{ {
@ -158,74 +311,76 @@ static qse_ssize_t xout (
{ {
if (arg->path == QSE_NULL) if (arg->path == QSE_NULL)
{ {
if (xtn->outfile == QSE_NULL) sio = qse_sio_out; if (xtn->e.out == QSE_NULL) arg->handle = qse_sio_out;
else else
{ {
sio = qse_sio_open ( if (open_main_output_stream (sed, arg, xtn->e.out) <= -1) return -1;
sed->mmgr,
0,
xtn->outfile,
QSE_SIO_WRITE |
QSE_SIO_CREATE |
QSE_SIO_TRUNCATE |
QSE_SIO_IGNOREMBWCERR
);
if (sio == QSE_NULL)
{
/* set the error message explicitly
* as the file name is different from
* the standard console name (NULL) */
qse_cstr_t ea;
ea.ptr = xtn->outfile;
ea.len = qse_strlen (xtn->outfile);
qse_sed_seterrnum (sed, QSE_SED_EIOFIL, &ea);
return -1;
}
} }
} }
else else
{ {
sio = qse_sio_open ( sio = open_sio (
sed->mmgr, sed, arg->path,
0,
arg->path,
QSE_SIO_WRITE | QSE_SIO_WRITE |
QSE_SIO_CREATE | QSE_SIO_CREATE |
QSE_SIO_TRUNCATE | QSE_SIO_TRUNCATE |
QSE_SIO_IGNOREMBWCERR QSE_SIO_IGNOREMBWCERR
); );
if (sio == QSE_NULL) return -1;
arg->handle = sio;
} }
if (sio == QSE_NULL) return -1;
arg->handle = sio;
return 1; return 1;
} }
case QSE_SED_IO_CLOSE: case QSE_SED_IO_CLOSE:
{ {
sio = (qse_sio_t*)arg->handle; if (arg->path == QSE_NULL)
qse_sio_flush (sio); {
if (sio != qse_sio_in && sio != qse_sio_out && sio != qse_sio_err) if (xtn->e.out) close_main_stream (sed, arg, xtn->e.out);
qse_sio_close (sio); }
else
{
sio = (qse_sio_t*)arg->handle;
qse_sio_flush (sio);
if (sio != qse_sio_in && sio != qse_sio_out && sio != qse_sio_err)
qse_sio_close (sio);
}
return 0; return 0;
} }
case QSE_SED_IO_WRITE: case QSE_SED_IO_WRITE:
{ {
qse_ssize_t n = qse_sio_putsn (arg->handle, dat, len); if (arg->path == QSE_NULL)
if (n == -1)
{ {
if (arg->path == QSE_NULL && xtn->infile != QSE_NULL) /* main data stream */
if (xtn->e.out == QSE_NULL)
return qse_sio_putsn (arg->handle, dat, len);
else
{ {
qse_cstr_t ea; qse_sed_iostd_t* io = xtn->e.out;
ea.ptr = xtn->infile; if (io->type == QSE_SED_IOSTD_MEM)
ea.len = qse_strlen (xtn->infile); {
qse_sed_seterrnum (sed, QSE_SED_EIOFIL, &ea); if (len > QSE_TYPE_MAX(qse_ssize_t)) len = QSE_TYPE_MAX(qse_ssize_t);
if (qse_str_ncat (xtn->e.out_memstr, dat, len) == (qse_size_t)-1)
{
qse_sed_seterrnum (sed, QSE_SED_ENOMEM, QSE_NULL);
return -1;
}
return len;
}
else
{
return qse_sio_putsn (arg->handle, dat, len);
}
} }
} }
else
return n; {
return qse_sio_putsn (arg->handle, dat, len);
}
} }
default: default:
@ -233,10 +388,69 @@ static qse_ssize_t xout (
} }
} }
int qse_sed_execstd (qse_sed_t* sed, const qse_char_t* infile, const qse_char_t* outfile) int qse_sed_execstd (
qse_sed_t* sed, qse_sed_iostd_t in[], qse_sed_iostd_t* out)
{ {
int n;
xtn_t* xtn = (xtn_t*) QSE_XTN (sed); xtn_t* xtn = (xtn_t*) QSE_XTN (sed);
xtn->infile = infile;
xtn->outfile = outfile; if (in)
return qse_sed_exec (sed, xin, xout); {
qse_size_t i;
if (in[0].type == QSE_SED_IOSTD_NULL)
{
/* if 'in' is specified, it must contains at least one
* valid entry */
qse_sed_seterrnum (sed, QSE_SED_EINVAL, QSE_NULL);
return -1;
}
for (i = 0; in[i].type != QSE_SED_IOSTD_NULL; i++)
{
if (in[i].type != QSE_SED_IOSTD_SIO &&
in[i].type != QSE_SED_IOSTD_FILE &&
in[i].type != QSE_SED_IOSTD_MEM)
{
qse_sed_seterrnum (sed, QSE_SED_EINVAL, QSE_NULL);
return -1;
}
}
}
if (out)
{
if (out->type != QSE_SED_IOSTD_SIO &&
out->type != QSE_SED_IOSTD_FILE &&
out->type != QSE_SED_IOSTD_MEM)
{
qse_sed_seterrnum (sed, QSE_SED_EINVAL, QSE_NULL);
return -1;
}
}
QSE_MEMSET (&xtn->e, 0, QSE_SIZEOF(xtn->e));
xtn->e.in = in;
xtn->e.out = out;
xtn->e.in_cur = in;
n = qse_sed_exec (sed, xin, xout);
if (n >= 0 && out && out->type == QSE_SED_IOSTD_MEM)
{
QSE_ASSERT (xtn->e.out_memstr != QSE_NULL);
qse_str_yield (xtn->e.out_memstr, &out->u.mem, 0);
}
if (xtn->e.out_memstr) qse_str_close (xtn->e.out_memstr);
/* if some output without a newline is emitted before
* last flush, they can be lost because qse_sio_out
* is not explicitly closed() with qse_sio_close()
* which in turn calls qse_sio_flush(). let's call it
* here directly. I don't care whether some other
* threads could have written to this. */
qse_sio_flush (qse_sio_out);
return n;
} }