* fixed a bug of not setting an error code upon a few cases of QSE_AWK_STRXDUP failures

* added a new memory debugging facility to qseawk
This commit is contained in:
hyung-hwan 2011-08-14 10:04:14 +00:00
parent e833fdff6f
commit 4527bf0a34
11 changed files with 107 additions and 34 deletions

View File

@ -1,5 +1,5 @@
/* /*
* $Id: awk.c 516 2011-07-23 09:03:48Z hyunghwan.chung $ * $Id: awk.c 547 2011-08-13 16:04:14Z 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.
@ -78,6 +78,9 @@ struct arg_t
int opton; int opton;
int optoff; int optoff;
qse_ulong_t memlimit; qse_ulong_t memlimit;
#if defined(QSE_BUILD_DEBUG)
qse_ulong_t failmalloc;
#endif
}; };
struct gvmv_t struct gvmv_t
@ -425,6 +428,9 @@ static void print_usage (QSE_FILE* out, const qse_char_t* argv0)
qse_fprintf (out, QSE_T(" -F/--field-separator string set a field separator(FS)\n")); qse_fprintf (out, QSE_T(" -F/--field-separator string set a field separator(FS)\n"));
qse_fprintf (out, QSE_T(" -v/--assign var=value add a global variable with a value\n")); qse_fprintf (out, QSE_T(" -v/--assign var=value add a global variable with a value\n"));
qse_fprintf (out, QSE_T(" -m/--memory-limit number limit the memory usage (bytes)\n")); qse_fprintf (out, QSE_T(" -m/--memory-limit number limit the memory usage (bytes)\n"));
#if defined(QSE_BUILD_DEBUG)
qse_fprintf (out, QSE_T(" -X number fail the number'th memory allocation\n"));
#endif
for (j = 0; opttab[j].name != QSE_NULL; j++) for (j = 0; opttab[j].name != QSE_NULL; j++)
{ {
@ -467,7 +473,11 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg)
static qse_opt_t opt = static qse_opt_t opt =
{ {
#if defined(QSE_BUILD_DEBUG)
QSE_T("dc:f:F:o:v:m:X:h"),
#else
QSE_T("dc:f:F:o:v:m:h"), QSE_T("dc:f:F:o:v:m:h"),
#endif
lng lng
}; };
@ -598,6 +608,14 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg)
break; break;
} }
#if defined(QSE_BUILD_DEBUG)
case QSE_T('X'):
{
arg->failmalloc = qse_strtoulong (opt.arg);
break;
}
#endif
case QSE_T('\0'): case QSE_T('\0'):
{ {
/* a long option with no corresponding short option */ /* a long option with no corresponding short option */
@ -774,6 +792,39 @@ static qse_mmgr_t xma_mmgr =
QSE_NULL QSE_NULL
}; };
#if defined(QSE_BUILD_DEBUG)
static qse_ulong_t debug_mmgr_count = 0;
static void* debug_mmgr_alloc (void* ctx, qse_size_t size)
{
struct arg_t* arg = (struct arg_t*)ctx;
debug_mmgr_count++;
if (debug_mmgr_count % arg->failmalloc == 0) return QSE_NULL;
return malloc (size);
}
static void* debug_mmgr_realloc (void* ctx, void* ptr, qse_size_t size)
{
struct arg_t* arg = (struct arg_t*)ctx;
debug_mmgr_count++;
if (debug_mmgr_count % arg->failmalloc == 0) return QSE_NULL;
return realloc (ptr, size);
}
static void debug_mmgr_free (void* ctx, void* ptr)
{
free (ptr);
}
static qse_mmgr_t debug_mmgr =
{
debug_mmgr_alloc,
debug_mmgr_realloc,
debug_mmgr_free,
QSE_NULL
};
#endif
static int awk_main (int argc, qse_char_t* argv[]) static int awk_main (int argc, qse_char_t* argv[])
{ {
qse_awk_t* awk = QSE_NULL; qse_awk_t* awk = QSE_NULL;
@ -810,6 +861,14 @@ static int awk_main (int argc, qse_char_t* argv[])
psout.u.file = arg.osf; psout.u.file = arg.osf;
} }
#if defined(QSE_BUILD_DEBUG)
if (arg.failmalloc > 0)
{
debug_mmgr.udd = &arg;
mmgr = &debug_mmgr;
}
else
#endif
if (arg.memlimit > 0) if (arg.memlimit > 0)
{ {
xma_mmgr.udd = qse_xma_open (QSE_NULL, 0, arg.memlimit); xma_mmgr.udd = qse_xma_open (QSE_NULL, 0, arg.memlimit);

View File

@ -38,7 +38,8 @@ PROJECT_NUMBER = @VERSION@
# If a relative path is entered, it will be relative to the location # If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used. # where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = ./qse-@VERSION@ #OUTPUT_DIRECTORY = ./qse-@VERSION@
OUTPUT_DIRECTORY = @abs_top_srcdir@/doc/qse-@VERSION@
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output # 4096 sub-directories (in 2 levels) under the output directory of each output
@ -564,7 +565,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories # directories like "/usr/src/myproject". Separate the files or directories
# with spaces. # with spaces.
INPUT = @abs_top_srcdir@/include ./page INPUT = @abs_top_srcdir@/include @abs_top_srcdir@/doc/page
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@ -621,7 +622,7 @@ EXCLUDE_SYMBOLS =
# directories that contain example code fragments that are included (see # directories that contain example code fragments that are included (see
# the \include command). # the \include command).
EXAMPLE_PATH = ../samples ../cmd EXAMPLE_PATH = @abs_top_srcdir@/samples @abs_top_srcdir@/cmd
# If the value of the EXAMPLE_PATH tag contains directories, you can use the # If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
@ -823,14 +824,14 @@ GENERATE_DOCSET = NO
# documentation sets from a single provider (such as a company or product suite) # documentation sets from a single provider (such as a company or product suite)
# can be grouped. # can be grouped.
DOCSET_FEEDNAME = "Doxygen generated docs" DOCSET_FEEDNAME = "QSE Documentation"
# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
# should uniquely identify the documentation set bundle. This should be a # should uniquely identify the documentation set bundle. This should be a
# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
# will append .docset to the name. # will append .docset to the name.
DOCSET_BUNDLE_ID = org.hyunghwan.qse DOCSET_BUNDLE_ID = net.abiyo.qse
# If the GENERATE_HTMLHELP tag is set to YES, additional index files # If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the # will be generated that can be used as input for tools like the

View File

@ -3,5 +3,7 @@ AUTOMAKE_OPTIONS = no-dependencies
EXTRA_DIST = \ EXTRA_DIST = \
main.doc \ main.doc \
mem.doc \
io.doc \
awk.doc \ awk.doc \
sed.doc sed.doc

View File

@ -195,6 +195,8 @@ top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = no-dependencies AUTOMAKE_OPTIONS = no-dependencies
EXTRA_DIST = \ EXTRA_DIST = \
main.doc \ main.doc \
mem.doc \
io.doc \
awk.doc \ awk.doc \
sed.doc sed.doc

View File

@ -1,10 +0,0 @@
/** @page cmn COMMON FUNCTIONS
@section xma MEMORY ALLOCATOR
- QSE provides a memory allocator #qse_xma_t for private heap management.
- QSE provides a fixed-size block memory allocator #qse_fma_t.
@section rex REGULAR EXPRESSION
QSE provides a regular expression processor #qse_rex_t.
*/

8
qse/doc/page/io.doc Normal file
View File

@ -0,0 +1,8 @@
/** @page io I/O Handling
@section io_stream Stream
- Generic text stream interface #qse_tio_t
- Simple text stream over a file #qse_sio_t
- Pipe stream to/from a process #qse_pio_t
*/

View File

@ -95,9 +95,8 @@ foundation for other modules. Specialized functions and data structures are
organized to dedicated modules. See relevant subpages for more information organized to dedicated modules. See relevant subpages for more information
on each module. on each module.
- @subpage cmn "Common Functions" - @subpage mem "Memory Management"
-# xma.h variable-size block memory allocator - @subpage io "I/O Handling"
-# fma.h fixed-size block memory allocator
- @subpage awk "AWK Interpreter" - @subpage awk "AWK Interpreter"
- @subpage cut "CUT Text Cutter" - @subpage cut "CUT Text Cutter"
- @subpage sed "SED Stream Editor" - @subpage sed "SED Stream Editor"

6
qse/doc/page/mem.doc Normal file
View File

@ -0,0 +1,6 @@
/** @page mem Memory Management
@section mem_alloc Memory Allocator
- Private heap allocator #qse_xma_t
- Fixed-size block allocator #qse_fma_t
*/

View File

@ -1,5 +1,5 @@
/* /*
* $Id: sio.h 441 2011-04-22 14:28:43Z hyunghwan.chung $ * $Id: sio.h 547 2011-08-13 16:04:14Z 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.
@ -50,6 +50,10 @@ enum qse_sio_open_flag_t
typedef qse_fio_off_t qse_sio_pos_t; typedef qse_fio_off_t qse_sio_pos_t;
typedef qse_fio_hnd_t qse_sio_hnd_t; typedef qse_fio_hnd_t qse_sio_hnd_t;
/**
* The qse_sio_t type defines a simple text stream over a file. It also
* provides predefined streams for standard input, output, and error.
*/
typedef struct qse_sio_t qse_sio_t; typedef struct qse_sio_t qse_sio_t;
struct qse_sio_t struct qse_sio_t
@ -145,7 +149,7 @@ qse_ssize_t qse_sio_putsn (
); );
/** /**
* The get_sio_getpos() gets the current position in a stream. * The qse_sio_getpos() gets the current position in a stream.
* Note that it may not return the desired postion due to buffering. * Note that it may not return the desired postion due to buffering.
* @return 0 on success, -1 on failure * @return 0 on success, -1 on failure
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* $Id: tio.h 441 2011-04-22 14:28:43Z hyunghwan.chung $ * $Id: tio.h 547 2011-08-13 16:04:14Z 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.
@ -51,12 +51,12 @@ typedef enum qse_tio_errnum_t qse_tio_errnum_t;
enum enum
{ {
/* the size of input buffer should be at least equal to or greater /* the size of input buffer should be at least equal to or greater
* than the maximum sequence length of the qse_mchar_t string. * than the maximum sequence length of the qse_mchar_t string.
* (i.e. 6 for utf8) * (i.e. 6 for utf8)
*/ */
QSE_TIO_MAX_INBUF_LEN = 4096, QSE_TIO_MAX_INBUF_LEN = 4096,
QSE_TIO_MAX_OUTBUF_LEN = 4096 QSE_TIO_MAX_OUTBUF_LEN = 4096
}; };
enum enum
@ -98,12 +98,12 @@ struct qse_tio_t
/* for housekeeping */ /* for housekeeping */
int input_status; int input_status;
qse_size_t inbuf_curp; qse_size_t inbuf_curp;
qse_size_t inbuf_len; qse_size_t inbuf_len;
qse_size_t outbuf_len; qse_size_t outbuf_len;
qse_mchar_t inbuf[QSE_TIO_MAX_INBUF_LEN]; qse_mchar_t inbuf[QSE_TIO_MAX_INBUF_LEN];
qse_mchar_t outbuf[QSE_TIO_MAX_OUTBUF_LEN]; qse_mchar_t outbuf[QSE_TIO_MAX_OUTBUF_LEN];
}; };
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,5 +1,5 @@
/* /*
* $Id: parse.c 541 2011-08-12 14:16:05Z hyunghwan.chung $ * $Id: parse.c 547 2011-08-13 16:04:14Z 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.
@ -4255,6 +4255,7 @@ static qse_awk_nde_t* parse_primary_nogetline (
if (nde->str == QSE_NULL) if (nde->str == QSE_NULL)
{ {
QSE_AWK_FREE (awk, nde); QSE_AWK_FREE (awk, nde);
SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc);
return QSE_NULL; return QSE_NULL;
} }
nde->len = QSE_STR_LEN(awk->tok.name); nde->len = QSE_STR_LEN(awk->tok.name);
@ -4295,6 +4296,7 @@ static qse_awk_nde_t* parse_primary_nogetline (
if (nde->str == QSE_NULL) if (nde->str == QSE_NULL)
{ {
QSE_AWK_FREE (awk, nde); QSE_AWK_FREE (awk, nde);
SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc);
return QSE_NULL; return QSE_NULL;
} }
nde->len = QSE_STR_LEN(awk->tok.name); nde->len = QSE_STR_LEN(awk->tok.name);