diff --git a/qse/Makefile.in b/qse/Makefile.in index ac445d01..fd1fe0a1 100644 --- a/qse/Makefile.in +++ b/qse/Makefile.in @@ -34,7 +34,7 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = . -DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ +DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/README.in \ $(top_srcdir)/configure ac/config.guess ac/config.sub \ ac/depcomp ac/install-sh ac/ltmain.sh ac/missing diff --git a/qse/cmd/sed/sed.c b/qse/cmd/sed/sed.c index 63e236be..f4306696 100644 --- a/qse/cmd/sed/sed.c +++ b/qse/cmd/sed/sed.c @@ -64,7 +64,9 @@ static qse_char_t* g_output_file = QSE_NULL; static int g_infile_pos = 0; static int g_option = 0; static int g_separate = 0; +#if defined(QSE_ENABLE_SEDTRACER) static int g_trace = 0; +#endif static qse_ulong_t g_memlimit = 0; static qse_sed_t* g_sed = QSE_NULL; @@ -131,6 +133,9 @@ static void print_usage (QSE_FILE* out, int argc, qse_char_t* argv[]) qse_fprintf (out, QSE_T(" ,,,<0,/regex/>\n")); qse_fprintf (out, QSE_T(" -x allow text on the same line as c, a, i\n")); qse_fprintf (out, QSE_T(" -y ensure a newline at text end\n")); +#if defined(QSE_ENABLE_SEDTRACER) + qse_fprintf (out, QSE_T(" -t print command traces\n")); +#endif qse_fprintf (out, QSE_T(" -m number specify the maximum amount of memory to use in bytes\n")); #if defined(QSE_BUILD_DEBUG) qse_fprintf (out, QSE_T(" -X number fail the number'th memory allocation\n")); @@ -160,7 +165,9 @@ static int add_script (const qse_char_t* str, int mem) if (mem) { g_script.io[g_script.size].type = QSE_SED_IOSTD_MEM; - g_script.io[g_script.size].u.mem.ptr = str; + /* though its type is not qualified to be const, + * u.mem.ptr is actually const when used for input */ + g_script.io[g_script.size].u.mem.ptr = (qse_char_t*)str; g_script.io[g_script.size].u.mem.len = qse_strlen(str); } else @@ -270,8 +277,13 @@ static int handle_args (int argc, qse_char_t* argv[]) break; case QSE_T('t'): +#if defined(QSE_ENABLE_SEDTRACER) g_trace = 1; break; +#else + print_usage (QSE_STDERR, argc, argv); + goto oops; +#endif case QSE_T('m'): g_memlimit = qse_strtoulong (opt.arg); @@ -450,33 +462,39 @@ static void unset_intr_run (void) #endif } +#if defined(QSE_ENABLE_SEDTRACER) static void trace_exec (qse_sed_t* sed, qse_sed_exec_op_t op, const qse_sed_cmd_t* cmd) { switch (op) { #if 0 case QSE_SED_EXEC_READ: - qse_printf (QSE_T("reading...\n")); + qse_fprintf (QSE_STDERR, QSE_T("reading...\n")); break; case QSE_SED_EXEC_WRITE: - qse_printf (QSE_T("wrting...\n")); + qse_fprintf (QSE_STDERR, QSE_T("wrting...\n")); break; #endif + /* TODO: use function to get hold space and pattern space and print them */ + case QSE_SED_EXEC_MATCH: - qse_printf (QSE_T("matching address for [%c] in %s at line %lu\n"), - cmd->type, - (cmd->lid? cmd->lid: QSE_T("<>")), - (unsigned long)cmd->loc.line); + qse_fprintf (QSE_STDERR, QSE_T("%s:%lu [%c] MA\n"), + ((cmd->lid && cmd->lid[0])? cmd->lid: QSE_T("<>")), + (unsigned long)cmd->loc.line, + cmd->type + ); break; case QSE_SED_EXEC_EXEC: - qse_printf (QSE_T("executing [%c] in %s at line %lu\n"), - cmd->type, - (cmd->lid? cmd->lid: QSE_T("<>")), - (unsigned long)cmd->loc.line); + qse_fprintf (QSE_STDERR, QSE_T("%s:%lu [%c] EC\n"), + ((cmd->lid && cmd->lid[0])? cmd->lid: QSE_T("<>")), + (unsigned long)cmd->loc.line, + cmd->type + ); break; } } +#endif int sed_main (int argc, qse_char_t* argv[]) { @@ -559,7 +577,9 @@ int sed_main (int argc, qse_char_t* argv[]) goto oops; } +#if defined(QSE_ENABLE_SEDTRACER) if (g_trace) qse_sed_setexectracer (sed, trace_exec); +#endif if (g_separate && g_infile_pos > 0) { diff --git a/qse/configure b/qse/configure index dc3402d4..a653a5dc 100755 --- a/qse/configure +++ b/qse/configure @@ -902,6 +902,7 @@ enable_syscall enable_debug enable_cxx enable_reentrant +enable_sedtracer ' ac_precious_vars='build_alias host_alias @@ -1551,6 +1552,7 @@ Optional Features: --enable-cxx build the library for C++ if a C++ compiler is available (default. yes) --enable-reentrant define _REENTRANT (default. yes) + --enable-sedtracer enable qse_sed_setexectracer() (default. yes) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -5696,13 +5698,13 @@ if test "${lt_cv_nm_interface+set}" = set; then : else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:5699: $ac_compile\"" >&5) + (eval echo "\"\$as_me:5701: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:5702: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:5704: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:5705: output\"" >&5) + (eval echo "\"\$as_me:5707: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -6897,7 +6899,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 6900 "configure"' > conftest.$ac_ext + echo '#line 6902 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -8953,11 +8955,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8956: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8958: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:8960: \$? = $ac_status" >&5 + echo "$as_me:8962: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -9292,11 +9294,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9295: $lt_compile\"" >&5) + (eval echo "\"\$as_me:9297: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:9299: \$? = $ac_status" >&5 + echo "$as_me:9301: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -9397,11 +9399,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9400: $lt_compile\"" >&5) + (eval echo "\"\$as_me:9402: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:9404: \$? = $ac_status" >&5 + echo "$as_me:9406: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -9452,11 +9454,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9455: $lt_compile\"" >&5) + (eval echo "\"\$as_me:9457: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:9459: \$? = $ac_status" >&5 + echo "$as_me:9461: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -11836,7 +11838,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11839 "configure" +#line 11841 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11932,7 +11934,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11935 "configure" +#line 11937 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -13888,11 +13890,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13891: $lt_compile\"" >&5) + (eval echo "\"\$as_me:13893: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:13895: \$? = $ac_status" >&5 + echo "$as_me:13897: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -13987,11 +13989,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13990: $lt_compile\"" >&5) + (eval echo "\"\$as_me:13992: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:13994: \$? = $ac_status" >&5 + echo "$as_me:13996: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -14039,11 +14041,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14042: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14044: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:14046: \$? = $ac_status" >&5 + echo "$as_me:14048: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -17236,6 +17238,20 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" fi +# Check whether --enable-sedtracer was given. +if test "${enable_sedtracer+set}" = set; then : + enableval=$enable_sedtracer; enable_sedtracer_is=$enableval +else + enable_sedtracer_is=yes +fi + +if test "${enable_sedtracer_is}" = "yes" +then + +$as_echo "#define QSE_ENABLE_SEDTRACER /**/" >>confdefs.h + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t in sys/socket.h" >&5 $as_echo_n "checking for socklen_t in sys/socket.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext diff --git a/qse/configure.ac b/qse/configure.ac index b056434e..d0f7e398 100644 --- a/qse/configure.ac +++ b/qse/configure.ac @@ -228,6 +228,13 @@ then [CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"] fi +AC_ARG_ENABLE([sedtracer], [AS_HELP_STRING([--enable-sedtracer],[enable qse_sed_setexectracer() (default. yes)])], + enable_sedtracer_is=$enableval,enable_sedtracer_is=yes) +if test "${enable_sedtracer_is}" = "yes" +then + AC_DEFINE([QSE_ENABLE_SEDTRACER],[],[enable qse_sed_setexectracer()]) +fi + AC_MSG_CHECKING([for socklen_t in sys/socket.h]) AC_TRY_COMPILE([#define _POSIX_PII_SOCKET #include diff --git a/qse/include/qse/config.h.in b/qse/include/qse/config.h.in index 8d8d9555..812506d4 100644 --- a/qse/include/qse/config.h.in +++ b/qse/include/qse/config.h.in @@ -284,6 +284,9 @@ /* char is wchar */ #undef QSE_CHAR_IS_WCHAR +/* enable qse_sed_setexectracer() */ +#undef QSE_ENABLE_SEDTRACER + /* Big Endian */ #undef QSE_ENDIAN_BIG diff --git a/qse/include/qse/sed/sed.h b/qse/include/qse/sed/sed.h index 45cdc8d8..86a81d18 100644 --- a/qse/include/qse/sed/sed.h +++ b/qse/include/qse/sed/sed.h @@ -303,6 +303,7 @@ typedef int (*qse_sed_lformatter_t) ( int (*cwriter) (qse_sed_t*, qse_char_t) ); +#ifdef QSE_ENABLE_SEDTRACER enum qse_sed_exec_op_t { QSE_SED_EXEC_READ, @@ -317,6 +318,7 @@ typedef void (*qse_sed_exec_tracer_t) ( qse_sed_exec_op_t op, const qse_sed_cmd_t* cmd ); +#endif #ifdef __cplusplus extern "C" { @@ -561,14 +563,24 @@ void qse_sed_setlinenum ( qse_size_t num /**< a line number */ ); +#ifdef QSE_ENABLE_SEDTRACER +/** + * The qse_sed_getexectracer() function returns the execution tracer + * function. + */ qse_sed_exec_tracer_t qse_sed_getexectracer ( qse_sed_t* sed ); +/** + * The qse_sed_getexectracer() function sets a hook function via which + * you can trace commands being executed. + */ void qse_sed_setexectracer ( qse_sed_t* sed, qse_sed_exec_tracer_t tracer ); +#endif #ifdef __cplusplus } diff --git a/qse/lib/sed/sed.c b/qse/lib/sed/sed.c index 8e7609f9..cb0b6cec 100644 --- a/qse/lib/sed/sed.c +++ b/qse/lib/sed/sed.c @@ -586,6 +586,9 @@ static void free_command (qse_sed_t* sed, qse_sed_cmd_t* cmd) static void free_all_cids (qse_sed_t* sed) { + if (sed->src.cid == (qse_sed_cid_t*)&sed->src.unknown_cid) + sed->src.cid = sed->src.cid->next; + while (sed->src.cid) { qse_sed_cid_t* next = sed->src.cid->next; @@ -3542,7 +3545,9 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf) while (!sed->e.stopreq) { +#ifdef QSE_ENABLE_SEDTRACER if (sed->e.tracer) sed->e.tracer (sed, QSE_SED_EXEC_READ, QSE_NULL); +#endif n = read_line (sed, 0); if (n <= -1) { ret = -1; goto done; } @@ -3561,7 +3566,9 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf) while (c != &sed->cmd.over) { +#ifdef QSE_ENABLE_SEDTRACER if (sed->e.tracer) sed->e.tracer (sed, QSE_SED_EXEC_MATCH, c); +#endif n = match_address (sed, c); if (n <= -1) { ret = -1; goto done; } @@ -3573,7 +3580,9 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf) continue; } +#ifdef QSE_ENABLE_SEDTRACER if (sed->e.tracer) sed->e.tracer (sed, QSE_SED_EXEC_EXEC, c); +#endif j = exec_cmd (sed, c); if (j == QSE_NULL) { ret = -1; goto done; } if (j == &sed->cmd.quit_quiet) goto done; @@ -3590,7 +3599,9 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf) } } +#ifdef QSE_ENABLE_SEDTRACER if (sed->e.tracer) sed->e.tracer (sed, QSE_SED_EXEC_WRITE, QSE_NULL); +#endif if (emit_output (sed, 0) <= -1) { ret = -1; goto done; } } @@ -3635,14 +3646,29 @@ const qse_char_t* qse_sed_setcompid (qse_sed_t* sed, const qse_char_t* id) qse_sed_cid_t* cid; qse_size_t len; + if (sed->src.cid == (qse_sed_cid_t*)&sed->src.unknown_cid) + { + /* if an error has occurred in a previously, you can't set it + * any more */ + return (const qse_char_t*)(sed->src.cid + 1); + } + len = qse_strlen (id); - cid = QSE_MMGR_ALLOC (sed->mmgr, QSE_SIZEOF(*cid) + ((len + 1) * QSE_SIZEOF(*id))); - if (cid == QSE_NULL) return QSE_NULL; - + cid = QSE_MMGR_ALLOC (sed->mmgr, + QSE_SIZEOF(*cid) + ((len + 1) * QSE_SIZEOF(*id))); + if (cid == QSE_NULL) + { + /* mark that an error has occurred */ + sed->src.unknown_cid.buf[0] = QSE_T('\0'); + cid = (qse_sed_cid_t*)&sed->src.unknown_cid; + } + else + { + qse_strcpy ((qse_char_t*)(cid + 1), id); + } + cid->next = sed->src.cid; sed->src.cid = cid; - qse_strcpy ((qse_char_t*)(cid + 1), id); - return (const qse_char_t*)(cid + 1); } @@ -3656,6 +3682,7 @@ void qse_sed_setlinenum (qse_sed_t* sed, qse_size_t num) sed->e.in.num = num; } +#ifdef QSE_ENABLE_SEDTRACER qse_sed_exec_tracer_t qse_sed_getexectracer (qse_sed_t* sed) { return sed->e.tracer; @@ -3665,4 +3692,5 @@ void qse_sed_setexectracer (qse_sed_t* sed, qse_sed_exec_tracer_t tracer) { sed->e.tracer = tracer; } +#endif diff --git a/qse/lib/sed/sed.h b/qse/lib/sed/sed.h index 8227b0fa..75e71100 100644 --- a/qse/lib/sed/sed.h +++ b/qse/lib/sed/sed.h @@ -61,6 +61,13 @@ struct qse_sed_cid_t qse_sed_cid_t* next; }; +typedef struct qse_sed_unknown_cid_t qse_sed_unknown_cid_t; +struct qse_sed_unknown_cid_t +{ + qse_sed_cid_t* next; + qse_char_t buf[1]; +}; + /** * The qse_sed_t type defines a stream editor */ @@ -94,7 +101,9 @@ struct qse_sed_t qse_char_t buf[1024]; int eof; - qse_sed_cid_t* cid; + qse_sed_cid_t* cid; + qse_sed_unknown_cid_t unknown_cid; + qse_sed_loc_t loc; /**< location */ qse_cint_t cc; /**< last character read */ const qse_char_t* ptr; /**< beginning of the source text */ @@ -197,8 +206,10 @@ struct qse_sed_t /** stop requested */ int stopreq; +#ifdef QSE_ENABLE_SEDTRACER /** trace function */ qse_sed_exec_tracer_t tracer; +#endif } e; };