diff --git a/qse/doc/Doxyfile b/qse/doc/Doxyfile index e8074e85..319f04b5 100644 --- a/qse/doc/Doxyfile +++ b/qse/doc/Doxyfile @@ -581,7 +581,7 @@ INPUT_ENCODING = UTF-8 # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 -FILE_PATTERNS = *.h *.c +FILE_PATTERNS = *.h *.c *.hpp *.cpp # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. diff --git a/qse/include/qse/Mmgr.hpp b/qse/include/qse/Mmgr.hpp index 21b5504c..8374fa8f 100644 --- a/qse/include/qse/Mmgr.hpp +++ b/qse/include/qse/Mmgr.hpp @@ -26,6 +26,13 @@ QSE_BEGIN_NAMESPACE(QSE) ///////////////////////////////// +/** + * The Mmgr class defines a memory manager interface that can be inherited + * by a class in need of a memory manager as defined in the primitive + * qse_mmgr_t type. Using the class over the primitive type enables you to + * write code in more object-oriented fashion. An inheriting class should + * implement three pure virtual functions. + */ class Mmgr: public qse_mmgr_t { public: @@ -40,20 +47,54 @@ public: virtual ~Mmgr () {} protected: - virtual void* allocMem (qse_size_t n) throw () = 0; - virtual void* reallocMem (void* ptr, qse_size_t n) throw () = 0; - virtual void freeMem (void* ptr) throw () = 0; + /** + * The allocMem() function allocates a chunk of memory of the + * size \a n and return the pointer to the beginning of the chunk. + * If it fails to allocate memory, it should return QSE_NULL. + */ + virtual void* allocMem ( + qse_size_t n /**< the size of allocate in bytes */ + ) throw () = 0; + /** + * The reallocMem() function resizes a chunk of memory previously + * allocated with the allocMem() function. When resized, the contents + * of a surviving memory chunk is left untouched. If it fails to + * resize memory, it should return QSE_NULL. + */ + virtual void* reallocMem ( + void* ptr, /**< a pointer to a memory chunk to resize */ + qse_size_t n /**< new size in bytes */ + ) throw () = 0; + + /** + * The freeMem() function frees a chunk of memory allocated with + * the allocMem() function or resized with the reallocMem() function. + */ + virtual void freeMem ( + void* ptr /**< a pointer to a memory chunk to free */ + ) throw () = 0; + +protected: + /** + * a bridge function from the qse_mmgr_t type the allocMem() function. + */ static void* alloc_mem (void* data, qse_size_t n) throw () { return ((Mmgr*)data)->allocMem (n); } + /** + * a bridge function from the qse_mmgr_t type the reallocMem() function. + */ static void* realloc_mem (void* data, void* ptr, qse_size_t n) throw () { return ((Mmgr*)data)->reallocMem (ptr, n); } + /** + * a bridge function from the qse_mmgr_t type the freeMem() function. + */ static void free_mem (void* data, void* ptr) throw () { return ((Mmgr*)data)->freeMem (ptr); diff --git a/qse/include/qse/macros.h b/qse/include/qse/macros.h index 79bf46f1..4a8851e7 100644 --- a/qse/include/qse/macros.h +++ b/qse/include/qse/macros.h @@ -1,5 +1,5 @@ /* - * $Id: macros.h 140 2009-05-18 12:55:01Z hyunghwan.chung $ + * $Id: macros.h 150 2009-05-21 06:17:17Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -202,13 +202,23 @@ qse_mmgr_t* mmgr; /** - * The QSE_DEFINE_COMMON_FUNcTIONS() macro defines common object functions. + * The QSE_DEFINE_COMMON_FUNCTIONS() macro defines common object functions. + * - @code void qse_xxx_setmmgr (qse_xxx_t* xxx, qse_mmgr_t* mmgr); @endcode + * The qse_xxx_setmmgr() function change the memory manager of a relevant + * object. Take extreme care if you want to use this function. + * - @code qse_mmgr_t* qse_xxx_getmmgr (qse_xxx_t* xxx); @endcode + * The qse_xxx_getmmgr() function returns the memory manager of a relevant + * object. + * - @code void qse_xxx_getxtn (qse_xxx_t* xxx); @endcode + * The qse_xxx_getxtn() function returns the pointer to an extension area + * of a relevant object created with an extension size greater than 0. */ #define QSE_DEFINE_COMMON_FUNCTIONS(name) \ void qse_##name##_setmmgr (qse_##name##_t* name, qse_mmgr_t* mmgr); \ qse_mmgr_t* qse_##name##_getmmgr (qse_##name##_t* name); \ void* qse_##name##_getxtn (qse_##name##_t* name); + /** * The QSE_MMGR() macro gets the memory manager field from an object. */ diff --git a/qse/include/qse/sed/sed.h b/qse/include/qse/sed/sed.h index 2a32d2b7..df51eda0 100644 --- a/qse/include/qse/sed/sed.h +++ b/qse/include/qse/sed/sed.h @@ -65,7 +65,7 @@ enum qse_sed_errnum_t QSE_SED_ETMTXT, /**< too much text */ QSE_SED_ECMDNR, /**< a command is not recognized */ QSE_SED_ECMDMS, /**< a command is missing */ - QSE_SED_ECMDGB, /**< command garbled */ + QSE_SED_ECMDIC, /**< a command is incomplete */ QSE_SED_EREXBL, /**< regular expression build error */ QSE_SED_EREXMA, /**< regular expression match error */ QSE_SED_EA1PHB, /**< address 1 prohibited */ @@ -76,13 +76,11 @@ enum qse_sed_errnum_t QSE_SED_EBSDEL, /**< \ used a delimiter */ QSE_SED_EGBABS, /**< garbage after \ */ QSE_SED_ESCEXP, /**< ; is expected */ - QSE_SED_ELABTL, /**< label too long */ QSE_SED_ELABEM, /**< label name is empty */ QSE_SED_ELABDU, /**< duplicate label name */ QSE_SED_ELABNF, /**< label not found */ QSE_SED_EFILEM, /**< file name is empty */ QSE_SED_EFILIL, /**< illegal file name */ - QSE_SED_ENOTRM, /**< not terminated properly */ QSE_SED_ETSNSL, /**< translation set not the same length*/ QSE_SED_EGRNBA, /**< group brackets not balanced */ QSE_SED_EGRNTD, /**< group nested too deeply */ @@ -169,8 +167,15 @@ extern "C" { QSE_DEFINE_COMMON_FUNCTIONS (sed) /** - * The qse_sed_open() function creates a stream editor. - * @return A pointer to a stream editor on success, QSE_NULL on a failure + * The qse_sed_open() function creates a stream editor object. A memory + * manager provided is used to allocate and destory the object and any dynamic + * data through out its lifetime. An extension area is allocated if an + * extension size greater than 0 is specified. You can access it with the + * qse_sed_getxtn() function and use it to store arbitrary data associated + * with the object. See #QSE_DEFINE_COMMON_FUNCTIONS() for qse_sed_getxtn(). + * When done, you should destroy the object with the qse_sed_close() function + * to avoid any resource leaks including memory. + * @return A pointer to a stream editor on success, QSE_NULL on failure */ qse_sed_t* qse_sed_open ( qse_mmgr_t* mmgr, /**< a memory manager */ @@ -202,13 +207,54 @@ void qse_sed_setoption ( ); /** - * The qse_sed_geterrmsg() function retrieves an error message - * @return a pointer to a string describing an error occurred + * The qse_sed_geterrnum() function gets the number of the last error. + * @return the number of the last error + */ +int qse_sed_geterrnum ( + qse_sed_t* sed /**< a stream editor */ +); + +/** + * The qse_sed_geterrlin() function gets the number of the line where + * the last error has occurred. + * @return the line number of the last error + */ +qse_size_t qse_sed_geterrlin ( + qse_sed_t* sed /**< a stream editor */ +); + +/** + * The qse_sed_geterrmsg() function gets a string describing the last error. + * @return a pointer to an error message */ const qse_char_t* qse_sed_geterrmsg ( qse_sed_t* sed /**< a stream editor */ ); +/** + * The qse_sed_geterror() function gets an error number, an error line, and + * an error message. The information is set to the memory area pointed to by + * each parameter. + */ +void qse_sed_geterror ( + qse_sed_t* sed, /**< a stream editor */ + int* errnum, /**< a pointer to an error number holder */ + qse_size_t* errlin, /**< a pointer to an error line holder */ + const qse_char_t** errmsg /**< a pointer to an error message */ +); + +/** + * The qse_sed_seterror() function sets an error number, an error line, and + * an error message. An error string is composed of a formatting string + * and an array of formatting parameters. + */ +void qse_sed_seterror ( + qse_sed_t* sed, /**< a stream editor */ + int errnum, /**< an error number */ + qse_size_t errlin, /**< an error line */ + const qse_cstr_t* errarg /**< a string array for formatting an error message */ +); + /** * The qse_sed_comp() function compiles editing commands into an internal form. * @return 0 on success, -1 on error diff --git a/qse/include/qse/types.h b/qse/include/qse/types.h index 6665440e..2d9f90bb 100644 --- a/qse/include/qse/types.h +++ b/qse/include/qse/types.h @@ -1,5 +1,5 @@ /* - * $Id: types.h 127 2009-05-07 13:15:04Z hyunghwan.chung $ + * $Id: types.h 150 2009-05-21 06:17:17Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -404,16 +404,37 @@ struct qse_cstr_t typedef struct qse_cstr_t qse_cstr_t; /******/ -/****t* Base/qse_mmgr_t - * NAME - * qse_mmgr_t - define a memory manager - * SYNOPSIS +/** + * The qse_mmgr_t type defines a set type of functions for memory management. + * As the type is merely a structure, it is just used as a single container + * for memory management functions with a pointer to user-defined data. + * The user-defined \a data is passed to each memory management function + * whenever it is called. You can allocate, reallocate, and free a memory + * chunk. + * + * For example, a qse_xxx_open() function accepts a pointer of the qse_mmgr_t * + * type and the xxx object uses it to manage dynamic data within the object. */ struct qse_mmgr_t { + /** + * allocate a memory chunk of the size \a n. + * @return a pointer to a memory chunk on success, QSE_NULL on failure. + */ void* (*alloc) (void* data, qse_size_t n); + /** + * resize a memory chunk pointed to by \a ptr to the size \a n. + * @return a pointer to a memory chunk on success, QSE_NULL on failure. + */ void* (*realloc) (void* data, void* ptr, qse_size_t n); + /** + * frees a memory chunk pointed to by \a ptr. + */ void (*free) (void* data, void* ptr); + /** + * a pointer to user-defined data passed as the first parameter to + * alloc(), realloc(), and free(). + */ void* data; }; typedef struct qse_mmgr_t qse_mmgr_t; diff --git a/qse/lib/sed/Makefile.am b/qse/lib/sed/Makefile.am index 65767728..4ad6f90e 100644 --- a/qse/lib/sed/Makefile.am +++ b/qse/lib/sed/Makefile.am @@ -2,7 +2,7 @@ AM_CPPFLAGS = -I$(top_builddir)/include lib_LTLIBRARIES = libqsesed.la -libqsesed_la_SOURCES = sed.c sed.h +libqsesed_la_SOURCES = sed.c err.c sed.h libqsesed_la_LDFLAGS = -version-info 1:0:0 -no-undefined -L../cmn -L../utl libqsesed_la_LIBADD = -lqsecmn -lqseutl diff --git a/qse/lib/sed/Makefile.in b/qse/lib/sed/Makefile.in index 695ef353..e1ddd9e4 100644 --- a/qse/lib/sed/Makefile.in +++ b/qse/lib/sed/Makefile.in @@ -60,7 +60,7 @@ libqsesed___la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(CXXFLAGS) $(libqsesed___la_LDFLAGS) $(LDFLAGS) -o $@ @ENABLE_CXX_TRUE@am_libqsesed___la_rpath = -rpath $(libdir) libqsesed_la_DEPENDENCIES = -am_libqsesed_la_OBJECTS = sed.lo +am_libqsesed_la_OBJECTS = sed.lo err.lo libqsesed_la_OBJECTS = $(am_libqsesed_la_OBJECTS) libqsesed_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ @@ -219,7 +219,7 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_builddir)/include lib_LTLIBRARIES = libqsesed.la $(am__append_1) -libqsesed_la_SOURCES = sed.c sed.h +libqsesed_la_SOURCES = sed.c err.c sed.h libqsesed_la_LDFLAGS = -version-info 1:0:0 -no-undefined -L../cmn -L../utl libqsesed_la_LIBADD = -lqsecmn -lqseutl @ENABLE_CXX_TRUE@libqsesed___la_SOURCES = Sed.cpp StdSed.cpp @@ -298,6 +298,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Sed.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StdSed.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/err.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sed.Plo@am__quote@ .c.o: diff --git a/qse/lib/sed/err.c b/qse/lib/sed/err.c new file mode 100644 index 00000000..0380e9a2 --- /dev/null +++ b/qse/lib/sed/err.c @@ -0,0 +1,147 @@ +/* + * $Id: err.c 113 2009-03-25 14:53:10Z baconevi $ + * + Copyright 2006-2009 Chung, Hyung-Hwan. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "sed.h" + +static const qse_char_t* geterrstr (int errnum) +{ + static const qse_char_t* errstr[] = + { + QSE_T("no error"), + QSE_T("out of memory"), + QSE_T("too much text"), + QSE_T("command ${0} not recognized"), + QSE_T("command code missing"), + QSE_T("command ${0} not terminated properly"), + QSE_T("regular expression build error"), + QSE_T("regular expression match error"), + QSE_T("address 1 prohibited"), + QSE_T("address 2 prohibited"), + QSE_T("invalid step address"), + QSE_T("a new line expected"), + QSE_T("a backslash expected"), + QSE_T("a backslash used as a delimiter"), + QSE_T("garbage after a backslash"), + QSE_T("a semicolon expected"), + QSE_T("empty label name"), + QSE_T("duplicate label name ${0}"), + QSE_T("label ${0} not found"), + QSE_T("empty file name"), + QSE_T("illegal file name"), + QSE_T("strings in translation set not the same length"), + QSE_T("group brackets not balanced"), + QSE_T("group nesting too deep"), + QSE_T("multiple occurrence specifier"), + QSE_T("occurrence specifier is zero"), + QSE_T("occurrence specifier too large"), + QSE_T("error returned by user io handler") + }; + + return (errnum >= 0 && errnum < QSE_COUNTOF(errstr))? + errstr[errnum]: QSE_T("unknown error"); +} + +#if 0 +const qse_char_t* qse_sed_geterrstr (qse_sed_t* sed, qse_sed_errnum_t num) +{ + if (sed != QSE_NULL && + sed->errstr[num] != QSE_NULL) return sed->errstr[num]; + return geterrstr (num); +} + +int qse_sed_seterrstr ( + qse_sed_t* sed, qse_sed_errnum_t num, const qse_char_t* str) +{ + qse_char_t* dup; + + if (str == QSE_NULL) dup = QSE_NULL; + else + { + dup = QSE_AWK_STRDUP (sed, str); + if (dup == QSE_NULL) return -1; + } + + if (sed->errstr[num] != QSE_NULL) + QSE_AWK_FREE (sed, sed->errstr[num]); + else sed->errstr[num] = dup; + return 0; +} +#endif + +int qse_sed_geterrnum (qse_sed_t* sed) +{ + return sed->errnum; +} + +qse_size_t qse_sed_geterrlin (qse_sed_t* sed) +{ + return sed->errlin; +} + +const qse_char_t* qse_sed_geterrmsg (qse_sed_t* sed) +{ + if (sed->errmsg[0] == QSE_T('\0')) + /*return qse_sed_geterrstr (sed, sed->errnum);*/ + return geterrstr (sed->errnum); + return sed->errmsg; +} + +void qse_sed_geterror ( + qse_sed_t* sed, int* errnum, + qse_size_t* errlin, const qse_char_t** errmsg) +{ + if (errnum != QSE_NULL) *errnum = sed->errnum; + if (errlin != QSE_NULL) *errlin = sed->errlin; + if (errmsg != QSE_NULL) + { + *errmsg = (sed->errmsg[0] == QSE_T('\0'))? + /*qse_sed_geterrstr (sed, sed->errnum):*/ + geterrstr (sed->errnum): + sed->errmsg; + } +} + +void qse_sed_seterrnum (qse_sed_t* sed, int errnum) +{ + sed->errnum = errnum; + sed->errlin = 0; + sed->errmsg[0] = QSE_T('\0'); +} + +void qse_sed_seterrmsg (qse_sed_t* sed, + int errnum, qse_size_t errlin, const qse_char_t* errmsg) +{ + sed->errnum = errnum; + sed->errlin = errlin; + qse_strxcpy (sed->errmsg, QSE_COUNTOF(sed->errmsg), errmsg); +} + +void qse_sed_seterror ( + qse_sed_t* sed, int errnum, + qse_size_t errlin, const qse_cstr_t* errarg) +{ + const qse_char_t* errfmt; + + sed->errnum = errnum; + sed->errlin = errlin; + + errfmt = /*qse_sed_geterrstr (sed, errnum);*/ geterrstr (sed->errnum); + QSE_ASSERT (errfmt != QSE_NULL); + qse_strxfncpy (sed->errmsg, QSE_COUNTOF(sed->errmsg), errfmt, errarg); +} + diff --git a/qse/lib/sed/sed.c b/qse/lib/sed/sed.c index 363a6a98..9a181530 100644 --- a/qse/lib/sed/sed.c +++ b/qse/lib/sed/sed.c @@ -27,6 +27,16 @@ static void free_command (qse_sed_t* sed, qse_sed_cmd_t* cmd); static qse_sed_t* qse_sed_init (qse_sed_t* sed, qse_mmgr_t* mmgr); static void qse_sed_fini (qse_sed_t* sed); +#define SETERR0(sed,num,line) \ +do { qse_sed_seterror (sed, num, line, QSE_NULL); } while (0) + +#define SETERR1(sed,num,line,argp,argl) \ +do { \ + qse_cstr_t __qse__err__arg__; \ + __qse__err__arg__.ptr = argp; __qse__err__arg__.len = argl; \ + qse_sed_seterror (sed, num, line, &__qse__err__arg__); \ +} while (0) + qse_sed_t* qse_sed_open (qse_mmgr_t* mmgr, qse_size_t xtn) { qse_sed_t* sed; @@ -66,14 +76,14 @@ static qse_sed_t* qse_sed_init (qse_sed_t* sed, qse_mmgr_t* mmgr) if (qse_str_init (&sed->rexbuf, mmgr, 0) == QSE_NULL) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return QSE_NULL; } if (qse_map_init (&sed->labs, mmgr, 128, 70) == QSE_NULL) { qse_str_fini (&sed->rexbuf); - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return QSE_NULL; } qse_map_setcopier (&sed->labs, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); @@ -150,46 +160,6 @@ static void qse_sed_fini (qse_sed_t* sed) qse_str_fini (&sed->rexbuf); } -const qse_char_t* qse_sed_geterrmsg (qse_sed_t* sed) -{ - static const qse_char_t* errmsg[] = - { - QSE_T("no error"), - QSE_T("out of memory"), - QSE_T("too much text"), - QSE_T("command not recognized"), - QSE_T("command missing"), - QSE_T("command garbled"), - QSE_T("regular expression build error"), - QSE_T("regular expression match error"), - QSE_T("address 1 prohibited"), - QSE_T("address 2 prohibited"), - QSE_T("invalid step address"), - QSE_T("a new line expected"), - QSE_T("a backslash expected"), - QSE_T("a backslash used as a delimiter"), - QSE_T("garbage after a backslash"), - QSE_T("a semicolon expected"), - QSE_T("label name too long"), - QSE_T("empty label name"), - QSE_T("duplicate label name"), - QSE_T("label not found"), - QSE_T("empty file name"), - QSE_T("illegal file name"), - QSE_T("command not terminated properly"), - QSE_T("strings in translation set not the same length"), - QSE_T("group brackets not balanced"), - QSE_T("group nesting too deep"), - QSE_T("multiple occurrence specifier"), - QSE_T("occurrence specifier is zero"), - QSE_T("occurrence specifier too large"), - QSE_T("error returned by user io handler") - }; - - return (sed->errnum > 0 && sed->errnum < QSE_COUNTOF(errmsg))? - errmsg[sed->errnum]: QSE_T("unknown error"); -} - void qse_sed_setoption (qse_sed_t* sed, int option) { sed->option = option; @@ -314,7 +284,7 @@ static void* compile_rex (qse_sed_t* sed, qse_char_t rxend) if (qse_str_ccat (&sed->rexbuf, c) == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return QSE_NULL; } } @@ -405,7 +375,7 @@ static int get_text (qse_sed_t* sed, qse_sed_cmd_t* cmd) do { \ if (qse_str_ccat (str, c) == (qse_size_t)-1) \ { \ - sed->errnum = QSE_SED_ENOMEM; \ + SETERR0 (sed, QSE_SED_ENOMEM, 0); \ goto errlabel; \ } \ } while (0) @@ -497,7 +467,7 @@ static int get_label (qse_sed_t* sed, qse_sed_cmd_t* cmd) t = qse_str_open (sed->mmgr, 0, 32); if (t == QSE_NULL) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); goto oops; } @@ -505,7 +475,7 @@ static int get_label (qse_sed_t* sed, qse_sed_cmd_t* cmd) { if (qse_str_ccat (t, c) == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); goto oops; } c = NXTSC (sed); @@ -515,15 +485,16 @@ static int get_label (qse_sed_t* sed, qse_sed_cmd_t* cmd) if (qse_map_search ( &sed->labs, QSE_STR_PTR(t), QSE_STR_LEN(t)) != QSE_NULL) { - sed->errnum = QSE_SED_ELABDU; + SETERR1 (sed, QSE_SED_ELABDU, 0, + QSE_STR_PTR(t), QSE_STR_LEN(t)); goto oops; } if (qse_map_insert ( &sed->labs, QSE_STR_PTR(t), QSE_STR_LEN(t), cmd, 0) == QSE_NULL) { - sed->errnum = QSE_SED_ENOMEM; - goto oops;; + SETERR0 (sed, QSE_SED_ENOMEM, 0); + goto oops; } /* the label can be followed by a command on the same line without @@ -581,7 +552,7 @@ static int get_branch_target (qse_sed_t* sed, qse_sed_cmd_t* cmd) t = qse_str_open (sed->mmgr, 0, 32); if (t == QSE_NULL) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); goto oops; } @@ -589,7 +560,7 @@ static int get_branch_target (qse_sed_t* sed, qse_sed_cmd_t* cmd) { if (qse_str_ccat (t, c) == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); goto oops; } @@ -640,7 +611,7 @@ static int get_file (qse_sed_t* sed, qse_xstr_t* xstr) t = qse_str_open (sed->mmgr, 0, 32); if (t == QSE_NULL) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); goto oops; } @@ -672,7 +643,7 @@ static int get_file (qse_sed_t* sed, qse_xstr_t* xstr) if (qse_str_ccat (t, c) == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); goto oops; } @@ -706,7 +677,7 @@ static int get_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) if (c == QSE_CHAR_EOF || IS_LINTERM(c)) { /* not terminated properly */ - sed->errnum = QSE_SED_ENOTRM; + SETERR1 (sed, QSE_SED_ECMDIC, 0, &cmd->type, 1); goto oops; } @@ -723,7 +694,7 @@ static int get_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) t[i] = qse_str_open (sed->mmgr, 0, 32); if (t[i] == QSE_NULL) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); goto oops; } } @@ -737,7 +708,7 @@ static int get_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) { if (c == QSE_CHAR_EOF || IS_LINTERM(c)) { - sed->errnum = QSE_SED_ENOTRM; + SETERR1 (sed, QSE_SED_ECMDIC, 0, &cmd->type, 1); goto oops; } @@ -746,7 +717,7 @@ static int get_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) c = NXTSC (sed); if (c == QSE_CHAR_EOF || IS_LINTERM(c)) { - sed->errnum = QSE_SED_ENOTRM; + SETERR1 (sed, QSE_SED_ECMDIC, 0, &cmd->type, 1); goto oops; } @@ -755,7 +726,7 @@ static int get_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) if (qse_str_ccat (t[i], c) == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); goto oops; } @@ -868,7 +839,7 @@ static int get_transet (qse_sed_t* sed, qse_sed_cmd_t* cmd) if (c == QSE_CHAR_EOF || IS_LINTERM(c)) { /* translation set terminated prematurely*/ - sed->errnum = QSE_SED_ENOTRM; + SETERR1 (sed, QSE_SED_ECMDIC, 0, &cmd->type, 1); goto oops; } @@ -883,7 +854,7 @@ static int get_transet (qse_sed_t* sed, qse_sed_cmd_t* cmd) t = qse_str_open (sed->mmgr, 0, 32); if (t == QSE_NULL) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); goto oops; } @@ -894,7 +865,7 @@ static int get_transet (qse_sed_t* sed, qse_sed_cmd_t* cmd) if (c == QSE_CHAR_EOF || IS_LINTERM(c)) { - sed->errnum = QSE_SED_ENOTRM; + SETERR1 (sed, QSE_SED_ECMDIC, 0, &cmd->type, 1); goto oops; } @@ -903,7 +874,7 @@ static int get_transet (qse_sed_t* sed, qse_sed_cmd_t* cmd) c = NXTSC (sed); if (c == QSE_CHAR_EOF || IS_LINTERM(c)) { - sed->errnum = QSE_SED_ENOTRM; + SETERR1 (sed, QSE_SED_ECMDIC, 0, &cmd->type, 1); goto oops; } @@ -913,7 +884,7 @@ static int get_transet (qse_sed_t* sed, qse_sed_cmd_t* cmd) b[0] = c; if (qse_str_ncat (t, b, 2) == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); goto oops; } @@ -925,7 +896,7 @@ static int get_transet (qse_sed_t* sed, qse_sed_cmd_t* cmd) { if (c == QSE_CHAR_EOF || IS_LINTERM(c)) { - sed->errnum = QSE_SED_ENOTRM; + SETERR1 (sed, QSE_SED_ECMDIC, 0, &cmd->type, 1); goto oops; } @@ -934,7 +905,7 @@ static int get_transet (qse_sed_t* sed, qse_sed_cmd_t* cmd) c = NXTSC (sed); if (c == QSE_CHAR_EOF || IS_LINTERM(c)) { - sed->errnum = QSE_SED_ENOTRM; + SETERR1 (sed, QSE_SED_ECMDIC, 0, &cmd->type, 1); goto oops; } @@ -981,11 +952,14 @@ restart: switch (c) { default: - sed->errnum = QSE_SED_ECMDNR; + { + qse_char_t cc = c; + SETERR1 (sed, QSE_SED_ECMDNR, 0, &cc, 1); return -1; + } case QSE_CHAR_EOF: - sed->errnum = QSE_SED_ECMDMS; + SETERR0 (sed, QSE_SED_ECMDMS, 0); return -1; case QSE_T(':'): @@ -1264,7 +1238,7 @@ static int compile_source ( { /* TODO: too many commands. change errnum */ free_command (sed, cmd); - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return -1; } @@ -1372,7 +1346,7 @@ static int read_file (qse_sed_t* sed, const qse_char_t* path, int line) if (qse_str_ccat (&sed->e.txt.read, buf[i]) == (qse_size_t)-1) { sed->e.in.fun (sed, QSE_SED_IO_CLOSE, &arg); - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return -1; } @@ -1385,7 +1359,7 @@ static int read_file (qse_sed_t* sed, const qse_char_t* path, int line) if (qse_str_ncat (&sed->e.txt.read, buf, n) == (qse_size_t)-1) { sed->e.in.fun (sed, QSE_SED_IO_CLOSE, &arg); - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return -1; } } @@ -1429,7 +1403,7 @@ static int read_line (qse_sed_t* sed, int append) if (qse_str_ccat (&sed->e.in.line, c) == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return -1; } len++; @@ -1653,7 +1627,7 @@ static int write_str_to_file ( path, plen, &arg, QSE_SIZEOF(arg)); if (pair == QSE_NULL) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return -1; } } @@ -1761,7 +1735,7 @@ static int do_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) &sed->e.txt.subst, cur_ptr, cur_len) == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return -1; } break; @@ -1776,7 +1750,7 @@ static int do_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) if (m == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return -1; } } @@ -1788,7 +1762,7 @@ static int do_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) &sed->e.txt.subst, cur_ptr, mat.ptr-cur_ptr); if (m == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return -1; } @@ -1817,7 +1791,7 @@ static int do_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) if (m == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return -1; } } @@ -1834,7 +1808,7 @@ static int do_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) m = qse_str_ccat (&sed->e.txt.subst, QSE_T('\n')); if (m == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return -1; } } @@ -2053,7 +2027,7 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd) QSE_LDA_SIZE(&sed->e.txt.appended), &cmd->u.text, 0) == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return QSE_NULL; } break; @@ -2075,7 +2049,7 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd) QSE_STR_LEN(&cmd->u.text)); if (n == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return QSE_NULL; } } @@ -2167,7 +2141,7 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd) QSE_STR_PTR(&sed->e.in.line), QSE_STR_LEN(&sed->e.in.line)) == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return QSE_NULL; } break; @@ -2178,7 +2152,7 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd) QSE_STR_PTR(&sed->e.in.line), QSE_STR_LEN(&sed->e.in.line)) == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return QSE_NULL; } break; @@ -2189,7 +2163,7 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd) QSE_STR_PTR(&sed->e.txt.held), QSE_STR_LEN(&sed->e.txt.held)) == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return QSE_NULL; } break; @@ -2200,7 +2174,7 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd) QSE_STR_PTR(&sed->e.txt.held), QSE_STR_LEN(&sed->e.txt.held)) == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return QSE_NULL; } break; @@ -2308,7 +2282,10 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd) &sed->labs, lab->ptr, lab->len); if (pair == QSE_NULL) { - sed->errnum = QSE_SED_ELABNF; + SETERR1 ( + sed, QSE_SED_ELABNF, 0, + lab->ptr, lab->len + ); return QSE_NULL; } @@ -2384,7 +2361,7 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf) qse_str_clear (&sed->e.txt.held); if (qse_str_ccat (&sed->e.txt.held, QSE_T('\n')) == (qse_size_t)-1) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return -1; } @@ -2393,7 +2370,7 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf) sed->e.out.len = 0; if (qse_map_init (&sed->e.out.files, sed->mmgr, 128, 70) == QSE_NULL) { - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return -1; } *(qse_sed_t**)QSE_XTN(&sed->e.out.files) = sed; @@ -2414,7 +2391,7 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf) if (qse_str_init (&sed->e.in.line, QSE_MMGR(sed), 256) == QSE_NULL) { qse_map_fini (&sed->e.out.files); - sed->errnum = QSE_SED_ENOMEM; + SETERR0 (sed, QSE_SED_ENOMEM, 0); return -1; } diff --git a/qse/lib/sed/sed.h b/qse/lib/sed/sed.h index d49c3e6a..86fd2f8e 100644 --- a/qse/lib/sed/sed.h +++ b/qse/lib/sed/sed.h @@ -34,6 +34,9 @@ struct qse_sed_t QSE_DEFINE_COMMON_FIELDS (sed) qse_sed_errnum_t errnum; /**< stores an error number */ + qse_char_t errmsg[128]; /**< error message holder */ + qse_size_t errlin; /**< no of the line where an error occurred */ + int option; /**< stores options */ /** source text pointers */ @@ -139,46 +142,36 @@ struct qse_sed_adr_t } u; }; +#define QSE_SED_CMD_QUIT QSE_T('q') +#define QSE_SED_CMD_QUIT_QUIET QSE_T('Q') +#define QSE_SED_CMD_APPEND QSE_T('a') +#define QSE_SED_CMD_INSERT QSE_T('i') +#define QSE_SED_CMD_CHANGE QSE_T('c') +#define QSE_SED_CMD_DELETE QSE_T('d') +#define QSE_SED_CMD_DELETE_FIRSTLN QSE_T('D') +#define QSE_SED_CMD_PRINT_LNNUM QSE_T('=') +#define QSE_SED_CMD_PRINT QSE_T('p') +#define QSE_SED_CMD_PRINT_FIRSTLN QSE_T('P') +#define QSE_SED_CMD_PRINT_CLEARLY QSE_T('l') +#define QSE_SED_CMD_HOLD QSE_T('h') +#define QSE_SED_CMD_HOLD_APPEND QSE_T('H') +#define QSE_SED_CMD_RELEASE QSE_T('g') +#define QSE_SED_CMD_RELEASE_APPEND QSE_T('G') +#define QSE_SED_CMD_EXCHANGE QSE_T('x') +#define QSE_SED_CMD_NEXT QSE_T('n') +#define QSE_SED_CMD_NEXT_APPEND QSE_T('N') +#define QSE_SED_CMD_READ_FILE QSE_T('r') +#define QSE_SED_CMD_READ_FILELN QSE_T('R') +#define QSE_SED_CMD_WRITE_FILE QSE_T('w') +#define QSE_SED_CMD_WRITE_FILELN QSE_T('W') +#define QSE_SED_CMD_BRANCH QSE_T('b') +#define QSE_SED_CMD_BRANCH_COND QSE_T('t') +#define QSE_SED_CMD_SUBSTITUTE QSE_T('s') +#define QSE_SED_CMD_TRANSLATE QSE_T('y') + struct qse_sed_cmd_t { - enum - { - QSE_SED_CMD_QUIT = QSE_T('q'), - QSE_SED_CMD_QUIT_QUIET = QSE_T('Q'), - - QSE_SED_CMD_APPEND = QSE_T('a'), - QSE_SED_CMD_INSERT = QSE_T('i'), - QSE_SED_CMD_CHANGE = QSE_T('c'), - - QSE_SED_CMD_DELETE = QSE_T('d'), - QSE_SED_CMD_DELETE_FIRSTLN = QSE_T('D'), - - QSE_SED_CMD_PRINT_LNNUM = QSE_T('='), - QSE_SED_CMD_PRINT = QSE_T('p'), - QSE_SED_CMD_PRINT_FIRSTLN = QSE_T('P'), - QSE_SED_CMD_PRINT_CLEARLY = QSE_T('l'), - - QSE_SED_CMD_HOLD = QSE_T('h'), - QSE_SED_CMD_HOLD_APPEND = QSE_T('H'), - QSE_SED_CMD_RELEASE = QSE_T('g'), - QSE_SED_CMD_RELEASE_APPEND = QSE_T('G'), - QSE_SED_CMD_EXCHANGE = QSE_T('x'), - - QSE_SED_CMD_NEXT = QSE_T('n'), - QSE_SED_CMD_NEXT_APPEND = QSE_T('N'), - - QSE_SED_CMD_READ_FILE = QSE_T('r'), - QSE_SED_CMD_READ_FILELN = QSE_T('R'), - QSE_SED_CMD_WRITE_FILE = QSE_T('w'), - QSE_SED_CMD_WRITE_FILELN = QSE_T('W'), - - QSE_SED_CMD_BRANCH = QSE_T('b'), - QSE_SED_CMD_BRANCH_COND = QSE_T('t'), - - QSE_SED_CMD_SUBSTITUTE = QSE_T('s'), - QSE_SED_CMD_TRANSLATE = QSE_T('y') - - } type; + qse_char_t type; int negated;