diff --git a/qse/configure b/qse/configure index 8a3edcb8..1a864cf3 100755 --- a/qse/configure +++ b/qse/configure @@ -21652,7 +21652,8 @@ fi -for ac_header in stddef.h wchar.h wctype.h errno.h sys/syscall.h + +for ac_header in stddef.h wchar.h wctype.h errno.h signal.h sys/syscall.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then diff --git a/qse/configure.ac b/qse/configure.ac index c2ed18c1..5355bde3 100644 --- a/qse/configure.ac +++ b/qse/configure.ac @@ -83,7 +83,7 @@ AC_SUBST(LIBM, $LIBM) dnl check header files. AC_HEADER_STDC -AC_CHECK_HEADERS([stddef.h wchar.h wctype.h errno.h sys/syscall.h]) +AC_CHECK_HEADERS([stddef.h wchar.h wctype.h errno.h signal.h sys/syscall.h]) dnl check data types AC_CHECK_TYPE([wchar_t], diff --git a/qse/doc/page/cmn.doc b/qse/doc/page/cmn.doc new file mode 100644 index 00000000..d845a09a --- /dev/null +++ b/qse/doc/page/cmn.doc @@ -0,0 +1,5 @@ +/** @page cmn COMMON FUNCTIONS + +@section rex REGULAR EXPRESSION +QSE provides regular expression handling functions. +*/ diff --git a/qse/doc/page/main.doc b/qse/doc/page/main.doc index 010d41bc..c4b3ac4b 100644 --- a/qse/doc/page/main.doc +++ b/qse/doc/page/main.doc @@ -94,7 +94,4 @@ on each module. - @subpage sed "SED Stream Editor" - @subpage awk "AWK Interpreter" -@section design_model DESIGN MODEL -The design of a data structure is derived from object-oriented model. -<>> */ diff --git a/qse/doc/page/sed.doc b/qse/doc/page/sed.doc index 5d0337be..91af0e4c 100644 --- a/qse/doc/page/sed.doc +++ b/qse/doc/page/sed.doc @@ -1,11 +1,70 @@ -/** @page sed SED +/** @page sed SED STREAM EDITOR -STREAM EDITOR -a stream editor is provided +@section sed_intro INTRODUCTION -@section COMMAND -- : label label for b and t commands. a label can be composed of an - alpha-numeric character, an underscope, and an underline. +The sed stream editor is a non-interactive text editing tool commonly used +on Unix environment. Sed reads text from an input stream, applies a set of +editing commands, and writes the results to an output stream. Typically, +the input and output streams are a console or a file. + +@b QSE provides an embeddable stream editor that supports most of +the conventional sed commands and implements input and output streams as a +callback function: + +- #qse_sed_t - C type that encapsulates a stream editor +- QSE::Sed - C++ class that wraps #qse_sed_t +- QSE::StdSed - C++ child class of QSE::Sed that implements standard input and output streams + +@section sed_command COMMAND + +A sed command is composed of: + +- line selector (optional) +- ! (optional) +- command code +- command arguments (optional, dependent on command code) + +A line selector selects input lines to apply a command to and has the following +forms: +- address - specify a single address +- address,address - specify an address range +- start~step - specify a starting line and a step + +An @b address is a line number, a regular expression, or a dollar sign ($) +while a @b start and a @b step is a line number. + +A regular expression for an address has the following form: +- /rex/ - a regular expression @b rex is enclosed in slashes +- \\CrexC - a regular expression @b rex is enclosed in @b \\C and @b C + where @b C can be any character. + +It treats the @b \\n sequence specially to match a newline character. + +Here are examples of line selectors: +- 10 - match the 10th line +- 10,20 - match lines from the 10th to the 20th. +- /^[[:space:]]*$/ - match an empty line +- /^abc$/,/^def$/ - match all lines between @b abc and @b def inclusive +- 10,$ - match the 10th line down to the last line. +- 3~4 - match every 4th line from the 3rd line. + +Note that an address range always selects the line matching the first address +regardless of the second address; For example, 8,6 selects the 8th line. + +The exclamation mark @b !, when used after the line selector and before +the command code, negates the line selection; For example, 1! selects all +lines except the first line. + +A command without a line selector is applied to all input lines; +A command with a single address is applied to an input line that matches +the address; A command with an address range is applied to all input +lines within the range, inclusive; A command with a starting line and +a step is applied to every @b step'th line starting from the line @b start. + +Here is the summary of the commands. + +- : label label for b and t commands. a label can be composed of letters, + digits, periods, hyphens, and underlines. - # comment - = print the current line number */ diff --git a/qse/include/qse/config.h.in b/qse/include/qse/config.h.in index ad53568b..93fa4514 100644 --- a/qse/include/qse/config.h.in +++ b/qse/include/qse/config.h.in @@ -87,6 +87,9 @@ /* Define to 1 if you have the `powl' function. */ #undef HAVE_POWL +/* Define to 1 if you have the header file. */ +#undef HAVE_SIGNAL_H + /* Define to 1 if you have the `sin' function. */ #undef HAVE_SIN diff --git a/qse/lib/cmn/assert.c b/qse/lib/cmn/assert.c index 675b7e10..c4d3ee9a 100644 --- a/qse/lib/cmn/assert.c +++ b/qse/lib/cmn/assert.c @@ -22,7 +22,50 @@ #ifndef NDEBUG #include -#include + +#ifdef _WIN32 +# include +#else +# include "syscall.h" +#endif + +#define NTOC(n) (((n) >= 10)? (((n) - 10) + QSE_T('A')): (n) + QSE_T('0')) +#define WRITE_CHAR(c) \ +do { \ + qse_char_t __xxx_c = c; \ + if (qse_sio_putsn (QSE_SIO_ERR, &__xxx_c, 1) != 1) return -1; \ +} while (0) + +static int write_num (qse_size_t x, int base) +{ + qse_size_t last = x % base; + qse_size_t y = 0; + int dig = 0; + + x = x / base; + + while (x > 0) + { + y = y * base + (x % base); + x = x / base; + dig++; + } + + while (y > 0) + { + WRITE_CHAR (NTOC(y % base)); + y = y / base; + dig--; + } + + while (dig > 0) + { + dig--; + WRITE_CHAR (QSE_T('0')); + } + WRITE_CHAR (NTOC(last)); + return 0; +} void qse_assert_failed ( const qse_char_t* expr, const qse_char_t* desc, @@ -32,9 +75,9 @@ void qse_assert_failed ( qse_sio_puts (QSE_SIO_ERR, QSE_T("FILE ")); qse_sio_puts (QSE_SIO_ERR, file); - qse_sio_puts (QSE_SIO_ERR, QSE_T("LINE ")); + qse_sio_puts (QSE_SIO_ERR, QSE_T(" LINE ")); -/*qse_sio_puts the number */ + write_num (line, 10); qse_sio_puts (QSE_SIO_ERR, QSE_T(": ")); qse_sio_puts (QSE_SIO_ERR, expr); @@ -47,8 +90,14 @@ void qse_assert_failed ( qse_sio_puts (QSE_SIO_ERR, QSE_T("\n")); } qse_sio_puts (QSE_SIO_ERR, QSE_T("================================================================================")); + qse_sio_flush (QSE_SIO_ERR); - abort (); +#ifdef _WIN32 + ExitProcess (1); +#else + QSE_KILL (QSE_GETPID(), SIGABRT); + QSE_EXIT (1); +#endif } #endif diff --git a/qse/lib/sed/sed.c b/qse/lib/sed/sed.c index 779cb370..95fb3a90 100644 --- a/qse/lib/sed/sed.c +++ b/qse/lib/sed/sed.c @@ -2676,7 +2676,7 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf) if (c->negated) n = !n; if (n == 0) { - c++; + c = c->state.next; continue; }