diff --git a/qse/cmd/sed/sed.c b/qse/cmd/sed/sed.c index bd6b7813..f18e892d 100644 --- a/qse/cmd/sed/sed.c +++ b/qse/cmd/sed/sed.c @@ -48,8 +48,18 @@ # include #endif -static const qse_char_t* g_script_file = QSE_NULL; -static qse_char_t* g_script = QSE_NULL; +static struct +{ + qse_sed_iostd_t* io; + qse_size_t capa; + qse_size_t size; +} g_script = +{ + QSE_NULL, + 0, + 0 +}; + static qse_char_t* g_output_file = QSE_NULL; static int g_infile_pos = 0; static int g_option = 0; @@ -104,10 +114,12 @@ static void print_usage (QSE_FILE* out, int argc, qse_char_t* argv[]) qse_fprintf (out, QSE_T("USAGE: %s [options] script [file]\n"), b); qse_fprintf (out, QSE_T(" %s [options] -f script-file [file]\n"), b); + qse_fprintf (out, QSE_T(" %s [options] -e script [file]\n"), b); qse_fprintf (out, QSE_T("options as follows:\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(" -e script specify a script. \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")); @@ -124,14 +136,61 @@ static void print_usage (QSE_FILE* out, int argc, qse_char_t* argv[]) #endif } +static int add_script (const qse_char_t* str, int mem) +{ + if (g_script.size >= g_script.capa) + { + qse_sed_iostd_t* tmp; + + tmp = QSE_MMGR_REALLOC ( + QSE_MMGR_GETDFL(), + g_script.io, + QSE_SIZEOF(*g_script.io) * (g_script.capa + 16 + 1)); + if (tmp == QSE_NULL) + { + qse_fprintf (QSE_STDERR, QSE_T("ERROR: out of memory while processing %s\n"), str); + return -1; + } + + g_script.io = tmp; + g_script.capa += 16; + } + + if (mem) + { + g_script.io[g_script.size].type = QSE_SED_IOSTD_MEM; + g_script.io[g_script.size].u.mem.ptr = str; + g_script.io[g_script.size].u.mem.len = qse_strlen(str); + } + else + { + g_script.io[g_script.size].type = QSE_SED_IOSTD_FILE; + g_script.io[g_script.size].u.file = + (qse_strcmp (str, QSE_T("-")) == 0)? QSE_NULL: str; + } + g_script.size++; + return 0; +} + +static void free_scripts (void) +{ + if (g_script.io) + { + QSE_MMGR_FREE (QSE_MMGR_GETDFL(), g_script.io); + g_script.io = QSE_NULL; + g_script.capa = 0; + g_script.size = 0; + } +} + static int handle_args (int argc, qse_char_t* argv[]) { static qse_opt_t opt = { #if defined(QSE_BUILD_DEBUG) - QSE_T("hnf:o:rRsawxym:X:"), + QSE_T("hne:f:o:rRsawxym:X:"), #else - QSE_T("hnf:o:rRsawxym:"), + QSE_T("hne:f:o:rRsawxym:"), #endif QSE_NULL }; @@ -143,7 +202,7 @@ static int handle_args (int argc, qse_char_t* argv[]) { default: print_usage (QSE_STDERR, argc, argv); - return -1; + goto oops; case QSE_T('?'): qse_fprintf (QSE_STDERR, @@ -151,7 +210,7 @@ static int handle_args (int argc, qse_char_t* argv[]) opt.opt ); print_usage (QSE_STDERR, argc, argv); - return -1; + goto oops; case QSE_T(':'): qse_fprintf (QSE_STDERR, @@ -159,18 +218,22 @@ static int handle_args (int argc, qse_char_t* argv[]) opt.opt ); print_usage (QSE_STDERR, argc, argv); - return -1; + goto oops; case QSE_T('h'): print_usage (QSE_STDOUT, argc, argv); - return 0; + goto done; case QSE_T('n'): g_option |= QSE_SED_QUIET; break; + case QSE_T('e'): + if (add_script (opt.arg, 1) <= -1) goto oops; + break; + case QSE_T('f'): - g_script_file = opt.arg; + if (add_script (opt.arg, 0) <= -1) goto oops; break; case QSE_T('o'): @@ -217,71 +280,28 @@ static int handle_args (int argc, qse_char_t* argv[]) } } - if (opt.ind < argc && g_script_file == QSE_NULL) - g_script = argv[opt.ind++]; + if (opt.ind < argc && g_script.size <= 0) + { + if (add_script (argv[opt.ind++], 1) <= -1) goto oops; + } if (opt.ind < argc) g_infile_pos = opt.ind; - if (g_script_file == QSE_NULL && g_script == QSE_NULL) + if (g_script.size <= 0) { print_usage (QSE_STDERR, argc, argv); - return -1; + goto oops; } - + g_script.io[g_script.size].type = QSE_SED_IOSTD_NULL; return 1; -} -qse_char_t* load_script_file (qse_sed_t* sed, const qse_char_t* file) -{ - qse_str_t script; - qse_sio_t* fp; - qse_xstr_t xstr; - qse_char_t buf[256]; +oops: + free_scripts (); + return -1; - fp = qse_sio_open ( - qse_sed_getmmgr(sed), 0, file, - QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR); - if (fp == QSE_NULL) - { - qse_fprintf (QSE_STDERR, QSE_T("ERROR: cannot open %s\n"), file); - return QSE_NULL; - } - - if (qse_str_init (&script, QSE_MMGR_GETDFL(), 1024) <= -1) - { - qse_sio_close (fp); - qse_fprintf (QSE_STDERR, QSE_T("ERROR: cannot load %s\n"), file); - return QSE_NULL; - } - - while (1) - { - qse_ssize_t n; - - n = qse_sio_gets (fp, buf, QSE_COUNTOF(buf)); - if (n == 0) break; - if (n <= -1) - { - qse_fprintf (QSE_STDERR, QSE_T("ERROR: cannot read %s\n"), file); - qse_str_fini (&script); - qse_sio_close (fp); - return QSE_NULL; - } - - if (qse_str_ncat (&script, buf, n) == (qse_size_t)-1) - { - qse_fprintf (QSE_STDERR, QSE_T("ERROR: out of memory\n")); - qse_str_fini (&script); - qse_sio_close (fp); - return QSE_NULL; - } - } - - qse_str_yield (&script, &xstr, 0); - qse_str_fini (&script); - qse_sio_close (fp); - - return xstr.ptr; +done: + free_scripts (); + return 0; } void print_exec_error (qse_sed_t* sed) @@ -484,15 +504,7 @@ int sed_main (int argc, qse_char_t* argv[]) qse_sed_setoption (sed, g_option); - if (g_script_file) - { - QSE_ASSERT (g_script == QSE_NULL); - - g_script = load_script_file (sed, g_script_file); - if (g_script == QSE_NULL) goto oops; - } - - if (qse_sed_compstd (sed, g_script) == -1) + if (qse_sed_compstd (sed, g_script.io) == -1) { const qse_sed_loc_t* errloc = qse_sed_geterrloc(sed); if (errloc->line > 0 || errloc->colm > 0) @@ -625,8 +637,7 @@ if (g_trace) qse_sed_setexechook (sed, trace); oops: if (sed) qse_sed_close (sed); if (xma_mmgr.ctx) qse_xma_close (xma_mmgr.ctx); - if (g_script_file != QSE_NULL && g_script != QSE_NULL) - QSE_MMGR_FREE (QSE_MMGR_GETDFL(), g_script); + free_scripts (); return ret; } diff --git a/qse/configure b/qse/configure index d735ccc5..dc3402d4 100755 --- a/qse/configure +++ b/qse/configure @@ -15507,7 +15507,8 @@ $as_echo_n "checking size of char... " >&6; } if test "${ac_cv_sizeof_char+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (char))" "ac_cv_sizeof_char" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (char))" "ac_cv_sizeof_char" " +"; then : else if test "$ac_cv_type_char" = yes; then @@ -15540,7 +15541,8 @@ $as_echo_n "checking size of short... " >&6; } if test "${ac_cv_sizeof_short+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" " +"; then : else if test "$ac_cv_type_short" = yes; then @@ -15573,7 +15575,8 @@ $as_echo_n "checking size of int... " >&6; } if test "${ac_cv_sizeof_int+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" " +"; then : else if test "$ac_cv_type_int" = yes; then @@ -15606,7 +15609,8 @@ $as_echo_n "checking size of long... " >&6; } if test "${ac_cv_sizeof_long+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" " +"; then : else if test "$ac_cv_type_long" = yes; then @@ -15639,7 +15643,8 @@ $as_echo_n "checking size of long long... " >&6; } if test "${ac_cv_sizeof_long_long+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" " +"; then : else if test "$ac_cv_type_long_long" = yes; then @@ -15672,7 +15677,8 @@ $as_echo_n "checking size of __int8... " >&6; } if test "${ac_cv_sizeof___int8+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int8))" "ac_cv_sizeof___int8" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int8))" "ac_cv_sizeof___int8" " +"; then : else if test "$ac_cv_type___int8" = yes; then @@ -15705,7 +15711,8 @@ $as_echo_n "checking size of __int16... " >&6; } if test "${ac_cv_sizeof___int16+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int16))" "ac_cv_sizeof___int16" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int16))" "ac_cv_sizeof___int16" " +"; then : else if test "$ac_cv_type___int16" = yes; then @@ -15738,7 +15745,8 @@ $as_echo_n "checking size of __int32... " >&6; } if test "${ac_cv_sizeof___int32+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int32))" "ac_cv_sizeof___int32" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int32))" "ac_cv_sizeof___int32" " +"; then : else if test "$ac_cv_type___int32" = yes; then @@ -15771,7 +15779,8 @@ $as_echo_n "checking size of __int64... " >&6; } if test "${ac_cv_sizeof___int64+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int64))" "ac_cv_sizeof___int64" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int64))" "ac_cv_sizeof___int64" " +"; then : else if test "$ac_cv_type___int64" = yes; then @@ -15804,7 +15813,8 @@ $as_echo_n "checking size of __int128... " >&6; } if test "${ac_cv_sizeof___int128+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int128))" "ac_cv_sizeof___int128" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int128))" "ac_cv_sizeof___int128" " +"; then : else if test "$ac_cv_type___int128" = yes; then @@ -15837,7 +15847,8 @@ $as_echo_n "checking size of __int8_t... " >&6; } if test "${ac_cv_sizeof___int8_t+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int8_t))" "ac_cv_sizeof___int8_t" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int8_t))" "ac_cv_sizeof___int8_t" " +"; then : else if test "$ac_cv_type___int8_t" = yes; then @@ -15870,7 +15881,8 @@ $as_echo_n "checking size of __int16_t... " >&6; } if test "${ac_cv_sizeof___int16_t+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int16_t))" "ac_cv_sizeof___int16_t" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int16_t))" "ac_cv_sizeof___int16_t" " +"; then : else if test "$ac_cv_type___int16_t" = yes; then @@ -15903,7 +15915,8 @@ $as_echo_n "checking size of __int32_t... " >&6; } if test "${ac_cv_sizeof___int32_t+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int32_t))" "ac_cv_sizeof___int32_t" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int32_t))" "ac_cv_sizeof___int32_t" " +"; then : else if test "$ac_cv_type___int32_t" = yes; then @@ -15936,7 +15949,8 @@ $as_echo_n "checking size of __int64_t... " >&6; } if test "${ac_cv_sizeof___int64_t+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int64_t))" "ac_cv_sizeof___int64_t" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int64_t))" "ac_cv_sizeof___int64_t" " +"; then : else if test "$ac_cv_type___int64_t" = yes; then @@ -15969,7 +15983,8 @@ $as_echo_n "checking size of __int128_t... " >&6; } if test "${ac_cv_sizeof___int128_t+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int128_t))" "ac_cv_sizeof___int128_t" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int128_t))" "ac_cv_sizeof___int128_t" " +"; then : else if test "$ac_cv_type___int128_t" = yes; then @@ -16002,7 +16017,8 @@ $as_echo_n "checking size of void *... " >&6; } if test "${ac_cv_sizeof_void_p+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" " +"; then : else if test "$ac_cv_type_void_p" = yes; then @@ -16035,7 +16051,8 @@ $as_echo_n "checking size of float... " >&6; } if test "${ac_cv_sizeof_float+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (float))" "ac_cv_sizeof_float" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (float))" "ac_cv_sizeof_float" " +"; then : else if test "$ac_cv_type_float" = yes; then @@ -16068,7 +16085,8 @@ $as_echo_n "checking size of double... " >&6; } if test "${ac_cv_sizeof_double+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (double))" "ac_cv_sizeof_double" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (double))" "ac_cv_sizeof_double" " +"; then : else if test "$ac_cv_type_double" = yes; then @@ -16101,7 +16119,8 @@ $as_echo_n "checking size of long double... " >&6; } if test "${ac_cv_sizeof_long_double+set}" = set; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long double))" "ac_cv_sizeof_long_double" "$ac_includes_default"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long double))" "ac_cv_sizeof_long_double" " +"; then : else if test "$ac_cv_type_long_double" = yes; then @@ -16125,6 +16144,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF + # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. @@ -17270,7 +17290,7 @@ QSE_PROJECT_AUTHOR="${PACKAGE_BUGREPORT}" QSE_PROJECT_URL="${PACKAGE_URL}" -ac_config_files="$ac_config_files Makefile README include/Makefile include/qse/Makefile include/qse/cmn/Makefile include/qse/awk/Makefile include/qse/cut/Makefile include/qse/sed/Makefile include/qse/stx/Makefile include/qse/net/Makefile lib/Makefile lib/cmn/Makefile lib/awk/Makefile lib/cut/Makefile lib/sed/Makefile lib/stx/Makefile lib/net/Makefile cmd/Makefile cmd/awk/Makefile cmd/cut/Makefile cmd/sed/Makefile cmd/stx/Makefile samples/Makefile samples/cmn/Makefile samples/awk/Makefile samples/cut/Makefile samples/sed/Makefile samples/net/Makefile regress/Makefile regress/awk/Makefile regress/awk/regress.sh regress/sed/Makefile regress/sed/regress.sh doc/Makefile doc/page/Makefile doc/Doxyfile" +ac_config_files="$ac_config_files Makefile README include/Makefile include/qse/Makefile include/qse/cmn/Makefile include/qse/awk/Makefile include/qse/cut/Makefile include/qse/sed/Makefile include/qse/stx/Makefile include/qse/net/Makefile lib/Makefile lib/cmn/Makefile lib/awk/Makefile lib/cut/Makefile lib/sed/Makefile lib/stx/Makefile lib/net/Makefile cmd/Makefile cmd/awk/Makefile cmd/cut/Makefile cmd/sed/Makefile cmd/stx/Makefile samples/Makefile samples/cmn/Makefile samples/awk/Makefile samples/cut/Makefile samples/sed/Makefile samples/net/Makefile regress/Makefile regress/awk/Makefile regress/awk/regress.sh regress/sed/Makefile regress/sed/regress.sh doc/Makefile doc/page/Makefile doc/image/Makefile doc/Doxyfile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -18396,6 +18416,7 @@ do "regress/sed/regress.sh") CONFIG_FILES="$CONFIG_FILES regress/sed/regress.sh" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "doc/page/Makefile") CONFIG_FILES="$CONFIG_FILES doc/page/Makefile" ;; + "doc/image/Makefile") CONFIG_FILES="$CONFIG_FILES doc/image/Makefile" ;; "doc/Doxyfile") CONFIG_FILES="$CONFIG_FILES doc/Doxyfile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;; diff --git a/qse/configure.ac b/qse/configure.ac index ba07539b..b056434e 100644 --- a/qse/configure.ac +++ b/qse/configure.ac @@ -109,31 +109,32 @@ AC_CHECK_FUNCS([powf fmodf sinf cosf tanf atanf atan2f logf expf sqrtf]) LIBS="$OLDLIBS" dnl check the size of primitive data types -AC_CHECK_SIZEOF(char) -AC_CHECK_SIZEOF(short) -AC_CHECK_SIZEOF(int) -AC_CHECK_SIZEOF(long) -AC_CHECK_SIZEOF(long long) -AC_CHECK_SIZEOF(__int8) -AC_CHECK_SIZEOF(__int16) -AC_CHECK_SIZEOF(__int32) -AC_CHECK_SIZEOF(__int64) -AC_CHECK_SIZEOF(__int128) -AC_CHECK_SIZEOF(__int8_t) -AC_CHECK_SIZEOF(__int16_t) -AC_CHECK_SIZEOF(__int32_t) -AC_CHECK_SIZEOF(__int64_t) -AC_CHECK_SIZEOF(__int128_t) +AC_CHECK_SIZEOF(char,,[[]]) +AC_CHECK_SIZEOF(short,,[[]]) +AC_CHECK_SIZEOF(int,,[[]]) +AC_CHECK_SIZEOF(long,,[[]]) +AC_CHECK_SIZEOF(long long,,[[]]) +AC_CHECK_SIZEOF(__int8,,[[]]) +AC_CHECK_SIZEOF(__int16,,[[]]) +AC_CHECK_SIZEOF(__int32,,[[]]) +AC_CHECK_SIZEOF(__int64,,[[]]) +AC_CHECK_SIZEOF(__int128,,[[]]) +AC_CHECK_SIZEOF(__int8_t,,[[]]) +AC_CHECK_SIZEOF(__int16_t,,[[]]) +AC_CHECK_SIZEOF(__int32_t,,[[]]) +AC_CHECK_SIZEOF(__int64_t,,[[]]) +AC_CHECK_SIZEOF(__int128_t,,[[]]) dnl AC_CHECK_SIZEOF doesn't work without white-space between void and * -AC_CHECK_SIZEOF(void *) -AC_CHECK_SIZEOF(float) -AC_CHECK_SIZEOF(double) -AC_CHECK_SIZEOF(long double) +AC_CHECK_SIZEOF(void *,,[[]]) +AC_CHECK_SIZEOF(float,,[[]]) +AC_CHECK_SIZEOF(double,,[[]]) +AC_CHECK_SIZEOF(long double,,[[]]) + AC_CHECK_SIZEOF(wchar_t) AC_CHECK_SIZEOF(off_t) AC_CHECK_SIZEOF(off64_t) -AC_CHECK_SIZEOF(mbstate_t,[],[#include ]) +AC_CHECK_SIZEOF(mbstate_t,,[#include ]) AX_CHECK_NUMVALOF(MB_LEN_MAX,[32],[#include ]) AC_DEFINE_UNQUOTED(QSE_SIZEOF_CHAR, ${ac_cv_sizeof_char}, [sizeof(char)]) @@ -286,6 +287,7 @@ AC_CONFIG_FILES([ regress/sed/regress.sh doc/Makefile doc/page/Makefile + doc/image/Makefile doc/Doxyfile ]) AC_OUTPUT diff --git a/qse/doc/Doxyfile.in b/qse/doc/Doxyfile.in index 8fd0890c..495a72eb 100644 --- a/qse/doc/Doxyfile.in +++ b/qse/doc/Doxyfile.in @@ -647,7 +647,7 @@ EXAMPLE_RECURSIVE = YES # directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = +IMAGE_PATH = @srcdir@/image # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program diff --git a/qse/doc/image/Makefile.am b/qse/doc/image/Makefile.am new file mode 100644 index 00000000..83178d89 --- /dev/null +++ b/qse/doc/image/Makefile.am @@ -0,0 +1,5 @@ + +AUTOMAKE_OPTIONS = no-dependencies + +EXTRA_DIST = \ + qse-logo.png diff --git a/qse/doc/image/Makefile.in b/qse/doc/image/Makefile.in new file mode 100644 index 00000000..9ab6a966 --- /dev/null +++ b/qse/doc/image/Makefile.in @@ -0,0 +1,387 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = doc/image +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_numval.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/include/qse/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +depcomp = +am__depfiles_maybe = +SOURCES = +DIST_SOURCES = +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_MODE = @BUILD_MODE@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHAR_MODE = @CHAR_MODE@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +HAVE_CXX = @HAVE_CXX@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QSE_PROJECT_AUTHOR = @QSE_PROJECT_AUTHOR@ +QSE_PROJECT_URL = @QSE_PROJECT_URL@ +QSE_SIZEOF_CHAR = @QSE_SIZEOF_CHAR@ +QSE_SIZEOF_DOUBLE = @QSE_SIZEOF_DOUBLE@ +QSE_SIZEOF_FLOAT = @QSE_SIZEOF_FLOAT@ +QSE_SIZEOF_INT = @QSE_SIZEOF_INT@ +QSE_SIZEOF_LONG = @QSE_SIZEOF_LONG@ +QSE_SIZEOF_LONG_DOUBLE = @QSE_SIZEOF_LONG_DOUBLE@ +QSE_SIZEOF_LONG_LONG = @QSE_SIZEOF_LONG_LONG@ +QSE_SIZEOF_SHORT = @QSE_SIZEOF_SHORT@ +QSE_SIZEOF_VOID_P = @QSE_SIZEOF_VOID_P@ +QSE_SIZEOF_WCHAR_T = @QSE_SIZEOF_WCHAR_T@ +RANLIB = @RANLIB@ +RM = @RM@ +RMDIR = @RMDIR@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TRUE = @TRUE@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = no-dependencies +EXTRA_DIST = \ + qse-logo.png + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/image/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/image/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/qse/doc/image/qse-logo.png b/qse/doc/image/qse-logo.png new file mode 100644 index 00000000..6970d5e0 Binary files /dev/null and b/qse/doc/image/qse-logo.png differ diff --git a/qse/doc/page/main.doc b/qse/doc/page/main.doc index 12bf0191..1682025a 100644 --- a/qse/doc/page/main.doc +++ b/qse/doc/page/main.doc @@ -1,9 +1,11 @@ /** @mainpage QSE +@image html qse-logo.png + @section qse_intro INTRODUCTION -The QSE library implements various Unix commands in an embeddable form and -defines data types, functions, and classes that you can use when you embed +The QSE library implements AWK, SED, and Unix commands in an embeddable form +and defines data types, functions, and classes that you can use when you embed them into an application. It also provides more fundamental data types and funtions needed when you deal with memory, streams, data structures. The interface has been designed to be flexible enough to access various diff --git a/qse/doc/page/mem.doc b/qse/doc/page/mem.doc index 45c5672a..1b4cc985 100644 --- a/qse/doc/page/mem.doc +++ b/qse/doc/page/mem.doc @@ -17,6 +17,11 @@ ends with @b _open, and accepts a memory manager as the first parameter. See qse_mbs_open() for instance. So you can customize memory management at the per-object level. +Three types of special memory allocators are provided in the library. +- #qse_xma_t - generaic private heap allocator +- #qse_fma_t - fixed-size block allocator +- #qse_pma_t - pool-based block allocator + @section mem_xma Priviate Heap While the default memory manager allocates memory from a system-wide heap, @@ -29,22 +34,20 @@ A typical usage is shown below: @code qse_mmgr_t mmgr; -/* Create a private heap using the default memory manager */ -heap = qse_xma_open (QSE_NULL, 0, 1024 * 1024); /* 1M heap */ +// Create a private heap using the default memory manager +heap = qse_xma_open (QSE_NULL, 0, 1024 * 1024); // 1M heap -/* Initialize a memory manager with the heap */ +// Initialize a memory manager with the heap mmgr.alloc = (qse_mmgr_alloc_t)qse_xma_alloc; mmgr.realloc = (qse_mmgr_realloc_t)qse_xma_realloc; mmgr.free = (qse_mmgr_free_t)qse_xma_realloc; mmgr.ctx = heap; -/* - * You can pass 'mmgr' when you create/initialize a different object. - */ +// You can pass 'mmgr' when you create/initialize a different object. .... .... -/* Destroy the private heap */ +// Destroy the private heap qse_xma_close (heap); @endcode @@ -54,12 +57,24 @@ global heap. This means that you can split a heap to smaller subheaps. @section mem_fma Fixed-size Block Allocator -If the size of memory blocks to allocate share the same size, you can use -#qse_fma_t for performance. +If memory blocks to allocate share the same size, you can use #qse_fma_t +for performance. It achieves fast memory allocation as it knows the block +size in advance. The blocks allocated with this memory allocator +don't outlive the memory allocator itself. That is, qse_fma_close() or +qse_fma_fini() invalidates all the pointers allocated with qse_fma_alloc(). + +@code +qse_fma_t* fma; int* ptr; +fma = qse_fma_open (QSE_NULL, 0, sizeof(int), 10, 0); // create an allocator +ptr = (int*)qse_fma_alloc (fma, sizeof(int)); // allocate a block +ptr = 20; // access the block +qse_fma_free (fma, ptr1); // free the block +qse_fma_close (fma); // destroy the allocator +@endcode @section mem_pma Simple Memory Pool Allocator -If you want to allocate blocks quickly but ok not to be able to resize or +If you want to allocate blocks quickly but don't want to resize or deallocate the blocks individually, you can use #qse_pma_t. */ diff --git a/qse/include/qse/cmn/fio.h b/qse/include/qse/cmn/fio.h index 848d1c78..a371dd47 100644 --- a/qse/include/qse/cmn/fio.h +++ b/qse/include/qse/cmn/fio.h @@ -32,27 +32,30 @@ enum qse_fio_open_flag_t { - /* request qse_char_io based IO */ + /** request qse_char_io based IO */ QSE_FIO_TEXT = (1 << 0), QSE_FIO_IGNOREMBWCERR = (1 << 1), - /* treat the file name pointer as a handle pointer */ + /** treat the file name pointer as a handle pointer */ QSE_FIO_HANDLE = (1 << 3), - QSE_FIO_READ = (1 << 8), - QSE_FIO_WRITE = (1 << 9), - QSE_FIO_APPEND = (1 << 10), + /** don't close an I/O handle in qse_fio_fini() and qse_fio_close() */ + QSE_FIO_NOCLOSE = (1 << 4), - QSE_FIO_CREATE = (1 << 11), - QSE_FIO_TRUNCATE = (1 << 12), - QSE_FIO_EXCLUSIVE = (1 << 13), - QSE_FIO_SYNC = (1 << 14), + QSE_FIO_READ = (1 << 8), + QSE_FIO_WRITE = (1 << 9), + QSE_FIO_APPEND = (1 << 10), + + QSE_FIO_CREATE = (1 << 11), + QSE_FIO_TRUNCATE = (1 << 12), + QSE_FIO_EXCLUSIVE = (1 << 13), + QSE_FIO_SYNC = (1 << 14), /* for WIN32 only. harmless(no effect) when used on other platforms */ - QSE_FIO_NOSHRD = (1 << 24), - QSE_FIO_NOSHWR = (1 << 25), - QSE_FIO_RANDOM = (1 << 26), /* hint that access be random */ - QSE_FIO_SEQUENTIAL = (1 << 27) /* hint that access is sequential */ + QSE_FIO_NOSHRD = (1 << 24), + QSE_FIO_NOSHWR = (1 << 25), + QSE_FIO_RANDOM = (1 << 26), /* hint that access be random */ + QSE_FIO_SEQUENTIAL = (1 << 27) /* hint that access is sequential */ }; enum qse_fio_std_t diff --git a/qse/include/qse/cmn/pma.h b/qse/include/qse/cmn/pma.h index ae9290da..683c84cd 100644 --- a/qse/include/qse/cmn/pma.h +++ b/qse/include/qse/cmn/pma.h @@ -29,6 +29,10 @@ #ifndef _QSE_CMN_PMA_H_ #define _QSE_CMN_PMA_H_ +/** @file + * This file defines a pool-based block allocator. + */ + #include #include @@ -42,6 +46,9 @@ struct qse_pma_blk_t qse_pma_blk_t* next; }; +/** + * The qse_pma_t type defines a pool-base block allocator. + */ typedef struct qse_pma_t qse_pma_t; struct qse_pma_t diff --git a/qse/include/qse/cmn/sio.h b/qse/include/qse/cmn/sio.h index d005b138..2b0267dc 100644 --- a/qse/include/qse/cmn/sio.h +++ b/qse/include/qse/cmn/sio.h @@ -33,6 +33,7 @@ enum qse_sio_open_flag_t { QSE_SIO_HANDLE = QSE_FIO_HANDLE, + QSE_SIO_NOCLOSE = QSE_FIO_NOCLOSE, QSE_SIO_IGNOREMBWCERR = QSE_FIO_IGNOREMBWCERR, QSE_SIO_READ = QSE_FIO_READ, diff --git a/qse/include/qse/sed/Sed.hpp b/qse/include/qse/sed/Sed.hpp index 0d176cd4..22f0c965 100644 --- a/qse/include/qse/sed/Sed.hpp +++ b/qse/include/qse/sed/Sed.hpp @@ -177,23 +177,11 @@ public: void close (); /// - /// The compile() function compiles a null-terminated string pointed - /// to by @a sptr. + /// The compile() function compiles a script from a stream + /// @a iostream. /// @return 0 on success, -1 on failure /// - int compile ( - const char_t* sptr ///< a pointer to a null-terminated string - ); - - /// - /// The compile() function compiles a string pointed to by @a sptr - /// and of the length @a slen. - /// @return 0 on success, -1 on failure - /// - int compile ( - const char_t* sptr, ///< a pointer to a string - size_t slen ///< the number of characters in the string - ); + int compile (Stream& sstream); /// /// The execute() function executes compiled commands over the I/O @@ -202,7 +190,6 @@ public: /// int execute (Stream& iostream); - /// /// The stop() function makes a request to break a running loop /// inside execute(). Note that this does not affect blocking @@ -310,11 +297,15 @@ protected: sed_t* sed; /// default error formatting string getter errstr_t dflerrstr; + /// Stream to read script from + Stream* sstream; /// I/O stream to read data from and write output to. Stream* iostream; private: + static ssize_t sin ( + sed_t* s, io_cmd_t cmd, io_arg_t* arg, char_t* buf, size_t len); static ssize_t xin ( sed_t* s, io_cmd_t cmd, io_arg_t* arg, char_t* buf, size_t len); static ssize_t xout ( diff --git a/qse/include/qse/sed/sed.h b/qse/include/qse/sed/sed.h index 9a9c6a19..42cc411a 100644 --- a/qse/include/qse/sed/sed.h +++ b/qse/include/qse/sed/sed.h @@ -369,8 +369,7 @@ void qse_sed_seterror ( */ int qse_sed_comp ( qse_sed_t* sed, /**< stream editor */ - const qse_char_t* ptr, /**< pointer to a string containing commands */ - qse_size_t len /**< the number of characters in the string */ + qse_sed_io_fun_t inf /**< script stream reader */ ); /** diff --git a/qse/include/qse/sed/std.h b/qse/include/qse/sed/std.h index 73823ec7..56fa0ded 100644 --- a/qse/include/qse/sed/std.h +++ b/qse/include/qse/sed/std.h @@ -95,13 +95,13 @@ void* qse_sed_getxtnstd ( ); /** - * The qse_sed_compstd() function compiles a null-terminated sed script. - * Call qse_sed_comp() for a length delimited script. + * The qse_sed_compstd() function compiles sed scripts specified in + * a null-terminated array of stream resources. * @return 0 on success, -1 on failure */ int qse_sed_compstd ( qse_sed_t* sed, /**< stream editor */ - const qse_char_t* str /**< null-terminated script */ + qse_sed_iostd_t in[] /**< input scripts */ ); /** @@ -109,7 +109,7 @@ int qse_sed_compstd ( * over input streams @a in and an output stream @a out. * * If @a in is not #QSE_NULL, it must point to a null-terminated array - * of standard I/O resources. if in[0].type is QSE_SED_IOSTD_NULL, this + * of stream resources. if in[0].type is QSE_SED_IOSTD_NULL, this * function returns failure, requiring at least 1 valid resource to be * included in the array. * diff --git a/qse/include/qse/types.h b/qse/include/qse/types.h index 86666201..16c21306 100644 --- a/qse/include/qse/types.h +++ b/qse/include/qse/types.h @@ -119,6 +119,7 @@ typedef enum qse_tri_t qse_tri_t; /** @typedef qse_ulong_t * The qse_ulong_t type defines the largest unsigned integer type supported */ +/* TODO: use qse_int128_t in defining qse_long_t */ #if QSE_SIZEOF_LONG >= QSE_SIZEOF_LONG_LONG typedef long qse_long_t; typedef unsigned long qse_ulong_t; diff --git a/qse/lib/cmn/fio.c b/qse/lib/cmn/fio.c index 3639e20c..534b13e1 100644 --- a/qse/lib/cmn/fio.c +++ b/qse/lib/cmn/fio.c @@ -406,15 +406,19 @@ int qse_fio_init ( void qse_fio_fini (qse_fio_t* fio) { if (fio->tio != QSE_NULL) qse_tio_close (fio->tio); + + if (!(fio->flags & QSE_FIO_NOCLOSE)) + { #if defined(_WIN32) - CloseHandle (fio->handle); + CloseHandle (fio->handle); #elif defined(__OS2__) - DosClose (fio->handle); + DosClose (fio->handle); #elif defined(__DOS__) - close (fio->handle); + close (fio->handle); #else - QSE_CLOSE (fio->handle); + QSE_CLOSE (fio->handle); #endif + } } qse_fio_hnd_t qse_fio_gethandle (qse_fio_t* fio) @@ -437,7 +441,10 @@ qse_fio_off_t qse_fio_seek ( FILE_CURRENT, FILE_END }; - LARGE_INTEGER x, y; + LARGE_INTEGER x; +#if 0 + LARGE_INTEGER y; +#endif QSE_ASSERT (QSE_SIZEOF(offset) <= QSE_SIZEOF(x.QuadPart)); @@ -856,13 +863,18 @@ static qse_ssize_t fio_output (qse_tio_cmd_t cmd, void* arg, void* buf, qse_size int qse_getstdfiohandle (qse_fio_std_t std, qse_fio_hnd_t* hnd) { +#if defined(_WIN32) + DWORD tab[] = + { + STD_INPUT_HANDLE, + STD_OUTPUT_HANDLE, + STD_ERROR_HANDLE + }; +#else + qse_fio_hnd_t tab[] = { -#if defined(_WIN32) - (HANDLE)STD_INPUT_HANDLE, - (HANDLE)STD_OUTPUT_HANDLE, - (HANDLE)STD_ERROR_HANDLE -#elif defined(__OS2__) +#if defined(__OS2__) (HFILE)0, (HFILE)1, (HFILE)2 #elif defined(__DOS__) 0, 1, 2 @@ -871,6 +883,8 @@ int qse_getstdfiohandle (qse_fio_std_t std, qse_fio_hnd_t* hnd) #endif }; +#endif + if (std < 0 || std >= QSE_COUNTOF(tab)) return -1; #if defined(_WIN32) diff --git a/qse/lib/cmn/pma.c b/qse/lib/cmn/pma.c index 87a22f70..fc6ef96c 100644 --- a/qse/lib/cmn/pma.c +++ b/qse/lib/cmn/pma.c @@ -43,8 +43,8 @@ /* Returns number of bytes to add to (char *)ptr to make it properly aligned for the type. */ #define ALIGN(ptr, type) \ - ((((long)ptr) % sizeof(type))? \ - (sizeof(type) - (((long)ptr) % QSE_SIZEOF(type))) : 0) + ((((qse_uintptr_t)ptr) % QSE_SIZEOF(type))? \ + (QSE_SIZEOF(type) - (((qse_uintptr_t)ptr) % QSE_SIZEOF(type))) : 0) QSE_IMPLEMENT_COMMON_FUNCTIONS (pma) @@ -133,7 +133,7 @@ void* qse_pma_alloc (qse_pma_t* pma, qse_size_t size) } /* Make sure the next pointer will be aligned. */ - size += ALIGN((long)(pma->ptr + size), long); + size += ALIGN((qse_uintptr_t)(pma->ptr + size), qse_uintptr_t); /* Allocate from current block. */ ptr = pma->ptr; diff --git a/qse/lib/cmn/sio.c b/qse/lib/cmn/sio.c index b1d84084..4f193b23 100644 --- a/qse/lib/cmn/sio.c +++ b/qse/lib/cmn/sio.c @@ -41,6 +41,8 @@ static qse_sio_t __sio_in = 0, /* errnum */ #if defined(_WIN32) + /* this is not a handle. it is adjusted to + * an actual handle in __sio_input () */ (HANDLE)STD_INPUT_HANDLE, /* handle */ #elif defined(__OS2__) (HFILE)0, /* handle */ @@ -85,6 +87,8 @@ static qse_sio_t __sio_out = 0, #if defined(_WIN32) + /* this is not a handle. it is adjusted to + * an actual handle in __sio_output () */ (HANDLE)STD_OUTPUT_HANDLE, #elif defined(__OS2__) (HFILE)1, @@ -129,6 +133,8 @@ static qse_sio_t __sio_err = 0, #if defined(_WIN32) + /* this is not a handle. it is adjusted to + * an actual handle in __sio_output () */ (HANDLE)STD_ERROR_HANDLE, #elif defined(__OS2__) (HFILE)2, @@ -200,7 +206,7 @@ qse_sio_t* qse_sio_openstd ( qse_fio_hnd_t hnd; if (qse_getstdfiohandle (std, &hnd) <= -1) return QSE_NULL; return qse_sio_open (mmgr, xtnsize, - (const qse_char_t*)&hnd, flags | QSE_SIO_HANDLE); + (const qse_char_t*)&hnd, flags | QSE_SIO_HANDLE /*| QSE_SIO_NOCLOSE*/); } void qse_sio_close (qse_sio_t* sio) diff --git a/qse/lib/cmn/tre-match-parallel.c b/qse/lib/cmn/tre-match-parallel.c index 321bf748..2eac0722 100644 --- a/qse/lib/cmn/tre-match-parallel.c +++ b/qse/lib/cmn/tre-match-parallel.c @@ -178,16 +178,16 @@ tre_tnfa_run_parallel(qse_mmgr_t* mmgr, const tre_tnfa_t *tnfa, const void *stri /* Get the various pointers within tmp_buf (properly aligned). */ tmp_tags = (void *)buf; tmp_buf = buf + tbytes; - tmp_buf += ALIGN(tmp_buf, long); + tmp_buf += ALIGN(tmp_buf, qse_uintptr_t); reach_next = (void *)tmp_buf; tmp_buf += rbytes; - tmp_buf += ALIGN(tmp_buf, long); + tmp_buf += ALIGN(tmp_buf, qse_uintptr_t); reach = (void *)tmp_buf; tmp_buf += rbytes; - tmp_buf += ALIGN(tmp_buf, long); + tmp_buf += ALIGN(tmp_buf, qse_uintptr_t); reach_pos = (void *)tmp_buf; tmp_buf += pbytes; - tmp_buf += ALIGN(tmp_buf, long); + tmp_buf += ALIGN(tmp_buf, qse_uintptr_t); for (i = 0; i < tnfa->num_states; i++) { reach[i].tags = (void *)tmp_buf; diff --git a/qse/lib/cmn/tre.h b/qse/lib/cmn/tre.h index 26cdb4b6..4624a9cc 100644 --- a/qse/lib/cmn/tre.h +++ b/qse/lib/cmn/tre.h @@ -281,8 +281,8 @@ typedef enum { STR_WIDE, STR_BYTE, STR_MBS, STR_USER } tre_str_type_t; /* Returns number of bytes to add to (char *)ptr to make it properly aligned for the type. */ #define ALIGN(ptr, type) \ - ((((long)ptr) % sizeof(type)) \ - ? (sizeof(type) - (((long)ptr) % sizeof(type))) \ + ((((qse_uintptr_t)ptr) % QSE_SIZEOF(type)) \ + ? (QSE_SIZEOF(type) - (((qse_uintptr_t)ptr) % QSE_SIZEOF(type))) \ : 0) #undef MAX diff --git a/qse/lib/sed/Sed.cpp b/qse/lib/sed/Sed.cpp index 6ce89cd6..7c925650 100644 --- a/qse/lib/sed/Sed.cpp +++ b/qse/lib/sed/Sed.cpp @@ -48,16 +48,12 @@ void Sed::close () } } -int Sed::compile (const char_t* sptr) +int Sed::compile (Stream& sstream) { QSE_ASSERT (sed != QSE_NULL); - return qse_sed_comp (sed, sptr, qse_strlen(sptr)); -} -int Sed::compile (const char_t* sptr, size_t slen) -{ - QSE_ASSERT (sed != QSE_NULL); - return qse_sed_comp (sed, sptr, slen); + this->sstream = &sstream; + return qse_sed_comp (sed, sin); } int Sed::execute (Stream& iostream) @@ -145,6 +141,33 @@ void Sed::setConsoleLine (size_t num) qse_sed_setlinnum (sed, num); } +Sed::ssize_t Sed::sin ( + sed_t* s, io_cmd_t cmd, io_arg_t* arg, char_t* buf, size_t len) +{ + Sed* sed = *(Sed**)QSE_XTN(s); + + Stream::Data iodata (sed, Stream::READ, arg); + + try + { + switch (cmd) + { + case QSE_SED_IO_OPEN: + return sed->sstream->open (iodata); + case QSE_SED_IO_CLOSE: + return sed->sstream->close (iodata); + case QSE_SED_IO_READ: + return sed->sstream->read (iodata, buf, len); + default: + return -1; + } + } + catch (...) + { + return -1; + } +} + Sed::ssize_t Sed::xin ( sed_t* s, io_cmd_t cmd, io_arg_t* arg, char_t* buf, size_t len) { diff --git a/qse/lib/sed/sed.c b/qse/lib/sed/sed.c index 22b882bd..a0c3aab2 100644 --- a/qse/lib/sed/sed.c +++ b/qse/lib/sed/sed.c @@ -347,8 +347,101 @@ static int matchtre ( #define NXTSC(sed) getnextsc(sed) #define PEEPNXTSC(sed) ((sed->src.cur < sed->src.end)? *sed->src.cur: QSE_CHAR_EOF) +static int open_script_stream (qse_sed_t* sed) +{ + qse_ssize_t n; + + sed->errnum = QSE_SED_ENOERR; + n = sed->src.fun (sed, QSE_SED_IO_OPEN, &sed->src.arg, QSE_NULL, 0); + if (n <= -1) + { + if (sed->errnum == QSE_SED_ENOERR) + SETERR0 (sed, QSE_SED_EIOUSR, QSE_NULL); + return -1; + } + + sed->src.cur = sed->src.buf; + sed->src.end = sed->src.buf; + sed->src.cc = QSE_CHAR_EOF; + 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; + } +} + +static int close_script_stream (qse_sed_t* sed) +{ + qse_ssize_t n; + + sed->errnum = QSE_SED_ENOERR; + n = sed->src.fun (sed, QSE_SED_IO_CLOSE, &sed->src.arg, QSE_NULL, 0); + if (n <= -1) + { + if (sed->errnum == QSE_SED_ENOERR) + SETERR0 (sed, QSE_SED_EIOUSR, QSE_NULL); + return -1; + } + + return 0; +} + +static int read_script_stream (qse_sed_t* sed, qse_size_t rem) +{ + qse_ssize_t n; + + sed->errnum = QSE_SED_ENOERR; + n = sed->src.fun ( + sed, QSE_SED_IO_READ, &sed->src.arg, + &sed->src.buf[rem], QSE_COUNTOF(sed->src.buf) - rem + ); + if (n <= -1) + { + if (sed->errnum == QSE_SED_ENOERR) + SETERR0 (sed, QSE_SED_EIOUSR, QSE_NULL); + return -1; + } + + if (n == 0) + { + sed->src.eof = 1; + return 0; + } + + sed->src.end = &sed->src.buf[rem] + n; + return 1; +} + static qse_cint_t getnextsc (qse_sed_t* sed) { + if (sed->src.cur + 1 >= sed->src.end && !sed->src.eof) + { + qse_size_t rem = sed->src.end - sed->src.cur; + if (sed->src.cur != sed->src.buf && rem > 0) + { + QSE_MEMCPY (sed->src.buf, sed->src.cur, rem * QSE_SIZEOF(qse_char_t)); + sed->src.cur = sed->src.buf; + sed->src.end = sed->src.buf + rem; + } + if (read_script_stream (sed, rem) <= -1) return -1; + + if (sed->src.cur + 1 >= sed->src.end && !sed->src.eof) + { + /* read again if it didn't read enough */ + qse_size_t rem = sed->src.end - sed->src.cur; + QSE_ASSERT (sed->src.buf == sed->src.cur); + if (read_script_stream (sed, rem) <= -1) return -1; + } + } + if (sed->src.cur < sed->src.end) { if (sed->src.cc == QSE_T('\n')) @@ -1598,16 +1691,22 @@ static int get_command (qse_sed_t* sed, qse_sed_cmd_t* cmd) return 0; } -int qse_sed_comp (qse_sed_t* sed, const qse_char_t* sptr, qse_size_t slen) +int qse_sed_comp (qse_sed_t* sed, qse_sed_io_fun_t inf) { qse_cint_t c; qse_sed_cmd_t* cmd = QSE_NULL; qse_sed_loc_t a1_loc; + if (inf == QSE_NULL) + { + qse_sed_seterrnum (sed, QSE_SED_EINVAL, QSE_NULL); + return -1; + } + /* store the source code pointers */ - sed->src.ptr = sptr; - sed->src.end = sptr + slen; - sed->src.cur = sptr; + sed->src.fun = inf; + if (open_script_stream (sed) <= -1) return -1; + sed->src.loc.line = 1; sed->src.loc.colm = 0; sed->src.cc = QSE_CHAR_EOF; @@ -1730,17 +1829,19 @@ int qse_sed_comp (qse_sed_t* sed, const qse_char_t* sptr, qse_size_t slen) if (cmd->a1.type == QSE_SED_ADR_LINE && cmd->a1.u.lno <= 0) { if (cmd->a2.type == QSE_SED_ADR_STEP || - ((sed->option & QSE_SED_EXTENDEDADR) && cmd->a2.type == QSE_SED_ADR_REX)) + ((sed->option & QSE_SED_EXTENDEDADR) && + cmd->a2.type == QSE_SED_ADR_REX)) { /* 0 as the first address is allowed in this two contexts. * 0~step * 0,/regex/ - * however, '0~0' is not allowed. but at this point '0~0' is - * already transformed to '0'. and disallowing it is achieved - * gratuitously. + * '0~0' is not allowed. but at this point '0~0' + * is already transformed to '0'. and disallowing it is + * achieved gratuitously. */ /* nothing to do - adding negation to the condition dropped - * code readability so i decided to write this part of code this way. + * code readability so i decided to write this part of code + * this way. */ } else @@ -1785,13 +1886,15 @@ int qse_sed_comp (qse_sed_t* sed, const qse_char_t* sptr, qse_size_t slen) if (sed->tmp.grp.level != 0) { SETERR0 (sed, QSE_SED_EGRNBA, &sed->src.loc); - return -1; + goto oops; } + close_script_stream (sed); return 0; oops: if (cmd) free_address (sed, cmd); + close_script_stream (sed); return -1; } @@ -2185,6 +2288,7 @@ static int write_file ( qse_char_t buf[512]; #endif + arg.handle = QSE_NULL; arg.path = cmd->u.file.ptr; sed->errnum = QSE_SED_ENOERR; n = sed->e.in.fun (sed, QSE_SED_IO_OPEN, &arg, QSE_NULL, 0); @@ -2304,7 +2408,10 @@ static int emit_append (qse_sed_t* sed, qse_sed_app_t* app) return write_file (sed, app->cmd, 1); default: - QSE_ASSERT (!"should never happen - app->cmd->type must be one of APPEND,READ_FILE,READ_FILELN"); + QSE_ASSERTX ( + !"should never happen", + "app->cmd->type must be one of APPEND,READ_FILE,READ_FILELN" + ); SETERR0 (sed, QSE_SED_EINTERN, &app->cmd->loc); return -1; } diff --git a/qse/lib/sed/sed.h b/qse/lib/sed/sed.h index d3c457b3..cc40e138 100644 --- a/qse/lib/sed/sed.h +++ b/qse/lib/sed/sed.h @@ -191,8 +191,13 @@ struct qse_sed_t /** source text pointers */ struct { - qse_sed_loc_t loc; /**< location */ - qse_cint_t cc; /**< last character read */ + qse_sed_io_fun_t fun; /**< input stream handler */ + qse_sed_io_arg_t arg; + qse_char_t buf[1024]; + int eof; + + qse_sed_loc_t loc; /**< location */ + qse_cint_t cc; /**< last character read */ const qse_char_t* ptr; /**< beginning of the source text */ const qse_char_t* end; /**< end of the source text */ const qse_char_t* cur; /**< current source text pointer */ diff --git a/qse/lib/sed/std.c b/qse/lib/sed/std.c index 63d32cff..26863738 100644 --- a/qse/lib/sed/std.c +++ b/qse/lib/sed/std.c @@ -24,20 +24,35 @@ #include #include "../cmn/mem.h" +typedef struct xtn_in_t xtn_in_t; +struct xtn_in_t +{ + qse_sed_iostd_t* ptr; + qse_sed_iostd_t* cur; + qse_size_t mempos; +}; + +typedef struct xtn_out_t xtn_out_t; +struct xtn_out_t +{ + qse_sed_iostd_t* ptr; + qse_str_t* memstr; +}; + +typedef struct xtn_t xtn_t; struct xtn_t { struct { - 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; + xtn_in_t in; + } s; + struct + { + xtn_in_t in; + xtn_out_t out; } e; }; -typedef struct xtn_t xtn_t; qse_sed_t* qse_sed_openstd (qse_size_t xtnsize) { @@ -65,9 +80,30 @@ void* qse_sed_getxtnstd (qse_sed_t* sed) return (void*)((xtn_t*)QSE_XTN(sed) + 1); } -int qse_sed_compstd (qse_sed_t* sed, const qse_char_t* sptr) +static int verify_iostd_in (qse_sed_t* sed, qse_sed_iostd_t in[]) { - return qse_sed_comp (sed, sptr, qse_strlen(sptr)); + 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; + } + } + + return 0; } static qse_sio_t* open_sio (qse_sed_t* sed, const qse_char_t* file, int flags) @@ -112,7 +148,8 @@ static void close_main_stream ( if (io->type == QSE_SED_IOSTD_FILE) qse_sio_close (arg->handle); } -static int open_console_input_stream (qse_sed_t* sed, qse_sed_io_arg_t* arg, qse_sed_iostd_t* io) +static int open_input_stream ( + qse_sed_t* sed, qse_sed_io_arg_t* arg, qse_sed_iostd_t* io, xtn_in_t* base) { xtn_t* xtn = (xtn_t*) QSE_XTN (sed); @@ -136,14 +173,21 @@ static int open_console_input_stream (qse_sed_t* sed, qse_sed_io_arg_t* arg, qse case QSE_SED_IOSTD_MEM: /* don't store anything to arg->handle */ - xtn->e.in_mempos = 0; + base->mempos = 0; break; } +#if 0 + if (base == &xtn->s.in) + { + qse_sed_setfilename (sed, ....); + } +#endif + return 0; } -static int open_console_output_stream (qse_sed_t* sed, qse_sed_io_arg_t* arg, qse_sed_iostd_t* io) +static int open_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); @@ -184,8 +228,8 @@ static int open_console_output_stream (qse_sed_t* sed, qse_sed_io_arg_t* arg, qs 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) + 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; @@ -196,34 +240,68 @@ static int open_console_output_stream (qse_sed_t* sed, qse_sed_io_arg_t* arg, qs 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) +static qse_ssize_t read_input_stream ( + qse_sed_t* sed, qse_sed_io_arg_t* arg, + qse_char_t* buf, qse_size_t len, xtn_in_t* base) { xtn_t* xtn = (xtn_t*) QSE_XTN (sed); qse_sed_iostd_t* io, * next; void* old, * new; qse_ssize_t n = 0; + int newline_forced = 0; if (len > QSE_TYPE_MAX(qse_ssize_t)) len = QSE_TYPE_MAX(qse_ssize_t); do { - io = xtn->e.in_cur; + io = base->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++]; + while (base->mempos < io->u.mem.len && n < len) + buf[n++] = io->u.mem.ptr[base->mempos++]; } else n = qse_sio_getsn (arg->handle, buf, len); - - if (n != 0) break; + if (n != 0) + { + if (n <= -1) + { + if (io->type == QSE_SED_IOSTD_FILE) + { + qse_cstr_t ea; + ea.ptr = io->u.file; + ea.len = qse_strlen (io->u.file); + qse_sed_seterrnum (sed, QSE_SED_EIOFIL, &ea); + } + } + else n += newline_forced; /* success */ + break; + } - /* end of file on the current input stream */ + /* ============================================= */ + /* == end of file on the current input stream == */ + /* ============================================= */ - next = xtn->e.in_cur + 1; + if (base == &xtn->s.in && !newline_forced) + { + /* == ONLY FOR A SCRIPT STREAM == + * squeeze in a new line in case the previous script + * stream doesn't end with a line terminator.*/ + + /* TODO: support different line terminator */ + buf[0] = QSE_T('\n'); + buf++; len--; + newline_forced = 1; + + /* set the line number to 0 for the newline + * squeezed in */ + sed->src.loc.line = 0; + sed->src.loc.colm = 0; + } + + next = base->cur + 1; if (next->type == QSE_SED_IOSTD_NULL) { /* no next stream available - return 0 */ @@ -233,9 +311,17 @@ static qse_ssize_t read_main_input_stream ( old = arg->handle; /* try to open the next input stream */ - if (open_console_input_stream (sed, arg, next) <= -1) + if (open_input_stream (sed, arg, next, base) <= -1) { /* failed to open the next input stream */ + if (next->type == QSE_SED_IOSTD_FILE) + { + qse_cstr_t ea; + ea.ptr = next->u.file; + ea.len = qse_strlen (next->u.file); + qse_sed_seterrnum (sed, QSE_SED_EIOFIL, &ea); + } + n = -1; break; } @@ -245,14 +331,51 @@ static qse_ssize_t read_main_input_stream ( close_main_stream (sed, arg, io); arg->handle = new; - xtn->e.in_cur++; + base->cur++; } while (1); return n; } -static qse_ssize_t xin ( +static qse_ssize_t s_in ( + qse_sed_t* sed, qse_sed_io_cmd_t cmd, qse_sed_io_arg_t* arg, + qse_char_t* buf, qse_size_t len) +{ + xtn_t* xtn = (xtn_t*) QSE_XTN (sed); + + switch (cmd) + { + case QSE_SED_IO_OPEN: + { + if (open_input_stream (sed, arg, xtn->s.in.cur, &xtn->s.in) <= -1) return -1; + return 1; + } + + case QSE_SED_IO_CLOSE: + { + close_main_stream (sed, arg, xtn->s.in.cur); + return 0; + } + + case QSE_SED_IO_READ: + { + return read_input_stream (sed, arg, buf, len, &xtn->s.in); + } + + default: + { + QSE_ASSERTX ( + !"should never happen", + "cmd must be one of OPEN,CLOSE,READ" + ); + qse_sed_seterrnum (sed, QSE_SED_EINTERN, QSE_NULL); + return -1; + } + } +} + +static qse_ssize_t x_in ( qse_sed_t* sed, qse_sed_io_cmd_t cmd, qse_sed_io_arg_t* arg, qse_char_t* buf, qse_size_t len) { @@ -265,8 +388,8 @@ static qse_ssize_t xin ( { if (arg->path == QSE_NULL) { - /* not file specified. console stream */ - if (xtn->e.in == QSE_NULL) + /* no file specified. console stream */ + if (xtn->e.in.ptr == QSE_NULL) { sio = open_sio_std ( sed, QSE_SIO_STDIN, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR); @@ -275,7 +398,7 @@ static qse_ssize_t xin ( } else { - if (open_console_input_stream (sed, arg, xtn->e.in_cur) <= -1) return -1; + if (open_input_stream (sed, arg, xtn->e.in.cur, &xtn->e.in) <= -1) return -1; } } else @@ -293,10 +416,10 @@ static qse_ssize_t xin ( if (arg->path == QSE_NULL) { /* main data stream */ - if (xtn->e.in == QSE_NULL) + if (xtn->e.in.ptr == QSE_NULL) qse_sio_close (arg->handle); else - close_main_stream (sed, arg, xtn->e.in_cur); + close_main_stream (sed, arg, xtn->e.in.cur); } else { @@ -311,23 +434,48 @@ static qse_ssize_t xin ( if (arg->path == QSE_NULL) { /* main data stream */ - if (xtn->e.in == QSE_NULL) - return qse_sio_getsn (arg->handle, buf, len); + if (xtn->e.in.ptr == QSE_NULL) + { + qse_ssize_t n; + n = qse_sio_getsn (arg->handle, buf, len); + if (n <= -1) + { + qse_cstr_t ea; + ea.ptr = QSE_T("stdin"); + ea.len = 5; + qse_sed_seterrnum (sed, QSE_SED_EIOFIL, &ea); + } + return n; + } else - return read_main_input_stream (sed, arg, buf, len); + return read_input_stream (sed, arg, buf, len, &xtn->e.in); } else { - return qse_sio_getsn (arg->handle, buf, len); + qse_ssize_t n; + n = qse_sio_getsn (arg->handle, buf, len); + if (n <= -1) + { + qse_cstr_t ea; + ea.ptr = arg->path; + ea.len = qse_strlen (arg->path); + qse_sed_seterrnum (sed, QSE_SED_EIOFIL, &ea); + } + return n; } } default: + QSE_ASSERTX ( + !"should never happen", + "cmd must be one of OPEN,CLOSE,READ" + ); + qse_sed_seterrnum (sed, QSE_SED_EINTERN, QSE_NULL); return -1; } } -static qse_ssize_t xout ( +static qse_ssize_t x_out ( qse_sed_t* sed, qse_sed_io_cmd_t cmd, qse_sed_io_arg_t* arg, qse_char_t* dat, qse_size_t len) { @@ -340,7 +488,7 @@ static qse_ssize_t xout ( { if (arg->path == QSE_NULL) { - if (xtn->e.out == QSE_NULL) + if (xtn->e.out.ptr== QSE_NULL) { sio = open_sio_std ( sed, QSE_SIO_STDOUT, @@ -354,7 +502,7 @@ static qse_ssize_t xout ( } else { - if (open_console_output_stream (sed, arg, xtn->e.out) <= -1) return -1; + if (open_output_stream (sed, arg, xtn->e.out.ptr) <= -1) return -1; } } else @@ -377,10 +525,10 @@ static qse_ssize_t xout ( { if (arg->path == QSE_NULL) { - if (xtn->e.out == QSE_NULL) + if (xtn->e.out.ptr== QSE_NULL) qse_sio_close (arg->handle); else - close_main_stream (sed, arg, xtn->e.out); + close_main_stream (sed, arg, xtn->e.out.ptr); } else { @@ -394,18 +542,27 @@ static qse_ssize_t xout ( if (arg->path == QSE_NULL) { /* main data stream */ - if (xtn->e.out == QSE_NULL) + if (xtn->e.out.ptr== QSE_NULL) { - return qse_sio_putsn (arg->handle, dat, len); + qse_ssize_t n; + n = qse_sio_putsn (arg->handle, dat, len); + if (n <= -1) + { + qse_cstr_t ea; + ea.ptr = QSE_T("stdin"); + ea.len = 5; + qse_sed_seterrnum (sed, QSE_SED_EIOFIL, &ea); + } + return n; } else { - qse_sed_iostd_t* io = xtn->e.out; + qse_sed_iostd_t* io = xtn->e.out.ptr; if (io->type == QSE_SED_IOSTD_MEM) { 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) + 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; @@ -415,50 +572,70 @@ static qse_ssize_t xout ( } else { - return qse_sio_putsn (arg->handle, dat, len); + qse_ssize_t n; + n = qse_sio_putsn (arg->handle, dat, len); + if (n <= -1) + { + qse_cstr_t ea; + ea.ptr = io->u.file; + ea.len = qse_strlen(io->u.file); + qse_sed_seterrnum (sed, QSE_SED_EIOFIL, &ea); + } + return n; } } } else { - return qse_sio_putsn (arg->handle, dat, len); + qse_ssize_t n; + n = qse_sio_putsn (arg->handle, dat, len); + if (n <= -1) + { + qse_cstr_t ea; + ea.ptr = arg->path; + ea.len = qse_strlen(arg->path); + qse_sed_seterrnum (sed, QSE_SED_EIOFIL, &ea); + } + return n; } } default: + QSE_ASSERTX ( + !"should never happen", + "cmd must be one of OPEN,CLOSE,WRITE" + ); + qse_sed_seterrnum (sed, QSE_SED_EINTERN, QSE_NULL); return -1; } } +int qse_sed_compstd (qse_sed_t* sed, qse_sed_iostd_t in[]) +{ + xtn_t* xtn = (xtn_t*) QSE_XTN (sed); + + if (in == QSE_NULL) + { + /* it requires a valid array unlike qse_sed_execstd(). */ + qse_sed_seterrnum (sed, QSE_SED_EINVAL, QSE_NULL); + return -1; + } + if (verify_iostd_in (sed, in) <= -1) return -1; + + QSE_MEMSET (&xtn->s, 0, QSE_SIZEOF(xtn->s)); + xtn->s.in.ptr = in; + xtn->s.in.cur = in; + + return qse_sed_comp (sed, s_in); +} + 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); - if (in) - { - 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 (in && verify_iostd_in (sed, in) <= -1) return -1; if (out) { @@ -472,18 +649,18 @@ int qse_sed_execstd ( } QSE_MEMSET (&xtn->e, 0, QSE_SIZEOF(xtn->e)); - xtn->e.in = in; - xtn->e.out = out; - xtn->e.in_cur = in; + xtn->e.in.ptr = in; + xtn->e.in.cur = in; + xtn->e.out.ptr= out; - n = qse_sed_exec (sed, xin, xout); + n = qse_sed_exec (sed, x_in, x_out); 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); + 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 (xtn->e.out.memstr) qse_str_close (xtn->e.out.memstr); return n; } diff --git a/qse/samples/Makefile.in b/qse/samples/Makefile.in index fd90816d..d5840adc 100644 --- a/qse/samples/Makefile.in +++ b/qse/samples/Makefile.in @@ -231,7 +231,7 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = cmn awk cut sed net +SUBDIRS = cmn awk cut sed all: all-recursive .SUFFIXES: diff --git a/qse/samples/sed/sed02.cpp b/qse/samples/sed/sed02.cpp index 043f2224..18a53c49 100644 --- a/qse/samples/sed/sed02.cpp +++ b/qse/samples/sed/sed02.cpp @@ -45,7 +45,9 @@ int sed_main (int argc, qse_char_t* argv[]) return -1; } - if (sed.compile (argv[1]) == -1) + + QSE::StdSed::StringStream sstream (argv[1]); + if (sed.compile (sstream) == -1) { xcout << QSE_T("ERR: cannot compile - ") << sed.getErrorMessage() << std::endl; sed.close (); @@ -54,9 +56,9 @@ int sed_main (int argc, qse_char_t* argv[]) qse_char_t* infile = (argc >= 3)? argv[2]: QSE_NULL; qse_char_t* outfile = (argc >= 4)? argv[3]: QSE_NULL; - QSE::StdSed::FileStream stream (infile, outfile); + QSE::StdSed::FileStream fstream (infile, outfile); - if (sed.execute (stream) == -1) + if (sed.execute (fstream) == -1) { xcout << QSE_T("ERR: cannot execute - ") << sed.getErrorMessage() << std::endl; sed.close (); diff --git a/qse/samples/sed/sed03.cpp b/qse/samples/sed/sed03.cpp index a739122b..0d4edc5d 100644 --- a/qse/samples/sed/sed03.cpp +++ b/qse/samples/sed/sed03.cpp @@ -49,7 +49,8 @@ public: void compile (const char_t* sptr) { - if (QSE::StdSed::compile (sptr) <= -1) + QSE::StdSed::StringStream stream(sptr); + if (QSE::StdSed::compile (stream) <= -1) throw Error (getErrorMessage()); }