* fixed a rounding bug of reallocation size in _realloc_merge of qse_xma_t.
* replaced rex with tre in qse_sed_t * added submatch reference for the 's' command into qse_sed_t * changed some options and functions for tre integration in qse_sed_t
This commit is contained in:
		| @ -137,7 +137,7 @@ static void print_usage (QSE_FILE* out, int argc, qse_char_t* argv[]) | ||||
| 	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(" -a        perform strict address check\n")); | ||||
| 	qse_fprintf (out, QSE_T(" -r        allow {n,m} in a regular expression\n")); | ||||
| 	qse_fprintf (out, QSE_T(" -r        use the extended regular expression\n")); | ||||
| 	qse_fprintf (out, QSE_T(" -s        allow text on the same line as c, a, i\n")); | ||||
| 	qse_fprintf (out, QSE_T(" -l        ensure a newline at text end\n")); | ||||
| 	qse_fprintf (out, QSE_T(" -f file   specify a script file\n")); | ||||
| @ -190,7 +190,7 @@ static int handle_args (int argc, qse_char_t* argv[]) | ||||
| 				break; | ||||
|  | ||||
| 			case QSE_T('r'): | ||||
| 				g_option |= QSE_SED_REXBOUND; | ||||
| 				g_option |= QSE_SED_EXTENDEDREX; | ||||
| 				break; | ||||
|  | ||||
| 			case QSE_T('s'): | ||||
| @ -237,26 +237,25 @@ qse_char_t* load_script_file (const qse_char_t* file) | ||||
| 	fp = qse_fopen (file, QSE_T("r")); | ||||
| 	if (fp == QSE_NULL) return QSE_NULL; | ||||
|  | ||||
| 	if (qse_str_init (&script, QSE_MMGR_GETDFL(), 1024) == QSE_NULL) | ||||
| 	if (qse_str_init (&script, QSE_MMGR_GETDFL(), 1024) <= -1) | ||||
| 	{ | ||||
| 		qse_fclose (fp); | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	while ((c = qse_fgetc (fp)) != QSE_CHAR_EOF) | ||||
| 	{ | ||||
| 		if (qse_str_ccat (&script, c) == (qse_size_t)-1) | ||||
| 		{ | ||||
| 			qse_fclose (fp); | ||||
| 			qse_str_fini (&script); | ||||
| 			qse_fclose (fp); | ||||
| 			return QSE_NULL; | ||||
| 		}		 | ||||
| 	} | ||||
|  | ||||
| 	qse_fclose (fp); | ||||
| 	qse_str_yield (&script, &xstr, 0); | ||||
| 	qse_str_fini (&script); | ||||
| 	qse_fclose (fp); | ||||
|  | ||||
| 	return xstr.ptr; | ||||
| } | ||||
| @ -293,7 +292,7 @@ int sed_main (int argc, qse_char_t* argv[]) | ||||
| 	 | ||||
| 	qse_sed_setoption (sed, g_option); | ||||
|  | ||||
| 	if (g_script_file != QSE_NULL) | ||||
| 	if (g_script_file) | ||||
| 	{ | ||||
| 		QSE_ASSERT (g_script == QSE_NULL); | ||||
|  | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: Sed.hpp 507 2011-07-15 15:53:49Z hyunghwan.chung $ | ||||
|  * $Id: Sed.hpp 558 2011-09-02 15:27:44Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2011 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -54,8 +54,10 @@ public: | ||||
| 	typedef qse_sed_io_arg_t io_arg_t; | ||||
| 	/// The option_t type redefines an option type | ||||
| 	typedef qse_sed_option_t option_t; | ||||
| #if 0 | ||||
| 	/// The depth_t type redefines an depth IDs | ||||
| 	typedef qse_sed_depth_t depth_t; | ||||
| #endif | ||||
|  | ||||
| 	/// | ||||
| 	/// The Stream class is a base class for I/O operation during | ||||
| @ -214,6 +216,7 @@ public: | ||||
| 		int opt ///< option code | ||||
| 	); | ||||
|  | ||||
| #if 0 | ||||
| 	/// | ||||
| 	/// The getMaxDepth() function gets the maximum processing depth for | ||||
| 	/// an operation type identified by @a id. | ||||
| @ -229,6 +232,7 @@ public: | ||||
| 		int    ids,  ///< 0 or a number OR'ed of depth_t values | ||||
| 		size_t depth ///< 0 maximum depth | ||||
| 	); | ||||
| #endif | ||||
|  | ||||
| 	/// | ||||
| 	/// The getErrorMessage() function gets the description of the last  | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: sed.h 507 2011-07-15 15:53:49Z hyunghwan.chung $ | ||||
|  * $Id: sed.h 558 2011-09-02 15:27:44Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2011 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -137,23 +137,11 @@ enum qse_sed_option_t | ||||
| 	QSE_SED_QUIET       = (1 << 3), /**< do not print pattern space */ | ||||
| 	QSE_SED_STRICT      = (1 << 4), /**< do strict address check */ | ||||
| 	QSE_SED_STARTSTEP   = (1 << 5), /**< allow start~step */ | ||||
| 	QSE_SED_REXBOUND  = (1 << 6), /**< allow {n,m} in regular expression */ | ||||
| 	QSE_SED_EXTENDEDREX = (1 << 6), /**< allow {n,m} in regular expression */ | ||||
| 	QSE_SED_SAMELINE    = (1 << 7), /**< allow text on the same line as c, a, i */ | ||||
| }; | ||||
| typedef enum qse_sed_option_t qse_sed_option_t; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * The qse_sed_depth_t type defines IDs for qse_sed_getmaxdepth() and  | ||||
|  * qse_sed_setmaxdepth(). | ||||
|  */ | ||||
| enum qse_sed_depth_t | ||||
| { | ||||
| 	QSE_SED_DEPTH_REX_BUILD = (1 << 0), | ||||
| 	QSE_SED_DEPTH_REX_MATCH = (1 << 1) | ||||
| }; | ||||
| typedef enum qse_sed_depth_t qse_sed_depth_t; | ||||
|  | ||||
| /** | ||||
|  * The qse_sed_io_cmd_t type defines I/O command codes. The code indicates  | ||||
|  * the action to take in an I/O handler. | ||||
| @ -246,23 +234,6 @@ void qse_sed_setoption ( | ||||
| 	int        opt  /**< 0 or a number OR'ed of #qse_sed_option_t values */ | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_sed_getmaxdepth() gets the maximum processing depth. | ||||
|  */ | ||||
| qse_size_t qse_sed_getmaxdepth ( | ||||
| 	qse_sed_t*      sed, /**< stream editor */ | ||||
| 	qse_sed_depth_t id   /**< one of qse_sed_depth_t values */ | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_sed_setmaxdepth() sets the maximum processing depth. | ||||
|  */ | ||||
| void qse_sed_setmaxdepth ( | ||||
| 	qse_sed_t* sed,  /**< stream editor */ | ||||
| 	int        ids,  /**< 0 or a number OR'ed of #qse_sed_depth_t values */ | ||||
| 	qse_size_t depth /**< maximum depth level */ | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_sed_geterrstr() gets an error string getter. | ||||
|  */ | ||||
|  | ||||
| @ -47,7 +47,7 @@ qse_tre_t* qse_tre_open (qse_mmgr_t* mmgr, qse_size_t xtnsize) | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	return QSE_NULL; | ||||
| 	return tre; | ||||
| } | ||||
|  | ||||
| void qse_tre_close (qse_tre_t* tre) | ||||
|  | ||||
| @ -49,8 +49,8 @@ struct qse_xma_blk_t | ||||
|  | ||||
| 	struct | ||||
| 	{ | ||||
| 		qse_xma_blk_t* prev; /**< link to the previous block */ | ||||
| 		qse_xma_blk_t* next; /**< link to the next block */ | ||||
| 		qse_xma_blk_t* prev; /**< link to the previous adjacent block */ | ||||
| 		qse_xma_blk_t* next; /**< link to the next adjacent block */ | ||||
| 	} b; | ||||
| }; | ||||
|  | ||||
| @ -379,7 +379,7 @@ void* qse_xma_alloc (qse_xma_t* xma, qse_size_t size) | ||||
| 			for (++xfi; xfi < XFIMAX(xma) - 1; xfi++) | ||||
| 			{ | ||||
| 				free = alloc_from_freelist (xma, xfi, size); | ||||
| 				if (free != QSE_NULL) break; | ||||
| 				if (free) break; | ||||
| 			} | ||||
| 			if (free == QSE_NULL) return QSE_NULL; | ||||
| 		} | ||||
| @ -392,16 +392,20 @@ static void* _realloc_merge (qse_xma_t* xma, void* b, qse_size_t size) | ||||
| { | ||||
| 	qse_xma_blk_t* blk = USR_TO_SYS(b); | ||||
|  | ||||
| 	/* rounds up 'size' to be multiples of ALIGN */  | ||||
| 	size = ((size + ALIGN - 1) / ALIGN) * ALIGN; | ||||
|  | ||||
| 	if (size > blk->size) | ||||
| 	{ | ||||
| 		/*  | ||||
| 		 * grow the current block | ||||
| 		 */ | ||||
|  | ||||
| 		qse_size_t req = size - blk->size; | ||||
| 		qse_size_t req; | ||||
| 		qse_xma_blk_t* n; | ||||
| 		qse_size_t rem; | ||||
| 		 | ||||
| 		req = size - blk->size; | ||||
|  | ||||
| 		n = blk->b.next; | ||||
|  | ||||
| 		/* check if the next adjacent block is available */ | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: Sed.cpp 441 2011-04-22 14:28:43Z hyunghwan.chung $ | ||||
|  * $Id: Sed.cpp 558 2011-09-02 15:27:44Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2011 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -80,6 +80,7 @@ void Sed::setOption (int opt) | ||||
| 	qse_sed_setoption (sed, opt); | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| Sed::size_t Sed::getMaxDepth (depth_t id) const | ||||
| { | ||||
| 	QSE_ASSERT (sed != QSE_NULL); | ||||
| @ -91,6 +92,7 @@ void Sed::setMaxDepth (int ids, size_t depth) | ||||
| 	QSE_ASSERT (sed != QSE_NULL); | ||||
| 	qse_sed_setmaxdepth (sed, ids, depth); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| const Sed::char_t* Sed::getErrorMessage () const | ||||
| { | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: sed.c 557 2011-09-01 14:45:06Z hyunghwan.chung $ | ||||
|  * $Id: sed.c 558 2011-09-02 15:27:44Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2011 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -20,17 +20,19 @@ | ||||
|  | ||||
| #include "sed.h" | ||||
| #include "../cmn/mem.h" | ||||
| #include <qse/cmn/rex.h> | ||||
| #include <qse/cmn/chr.h> | ||||
|  | ||||
| #ifdef USE_REX | ||||
| #	include <qse/cmn/rex.h> | ||||
| #else | ||||
| #	include <qse/cmn/tre.h> | ||||
| #endif | ||||
|  | ||||
| QSE_IMPLEMENT_COMMON_FUNCTIONS (sed) | ||||
|  | ||||
| static void free_command (qse_sed_t* sed, qse_sed_cmd_t* cmd); | ||||
| static void free_all_command_blocks (qse_sed_t* sed); | ||||
|  | ||||
| static int qse_sed_init (qse_sed_t* sed, qse_mmgr_t* mmgr); | ||||
| static void qse_sed_fini (qse_sed_t* sed); | ||||
|  | ||||
| #define SETERR0(sed,num,loc) \ | ||||
| do { qse_sed_seterror (sed, num, QSE_NULL, loc); } while (0) | ||||
|  | ||||
| @ -73,7 +75,7 @@ void qse_sed_close (qse_sed_t* sed) | ||||
| 	QSE_MMGR_FREE (sed->mmgr, sed); | ||||
| } | ||||
|  | ||||
| static int qse_sed_init (qse_sed_t* sed, qse_mmgr_t* mmgr) | ||||
| int qse_sed_init (qse_sed_t* sed, qse_mmgr_t* mmgr) | ||||
| { | ||||
| 	if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL(); | ||||
|  | ||||
| @ -121,7 +123,7 @@ oops_1: | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static void qse_sed_fini (qse_sed_t* sed) | ||||
| void qse_sed_fini (qse_sed_t* sed) | ||||
| { | ||||
| 	free_all_command_blocks (sed); | ||||
|  | ||||
| @ -145,6 +147,8 @@ int qse_sed_getoption (qse_sed_t* sed) | ||||
| 	return sed->option; | ||||
| } | ||||
|  | ||||
|  | ||||
| #ifdef USE_REX | ||||
| qse_size_t qse_sed_getmaxdepth (qse_sed_t* sed, qse_sed_depth_t id) | ||||
| { | ||||
| 	return (id & QSE_SED_DEPTH_REX_BUILD)? sed->depth.rex.build: | ||||
| @ -156,6 +160,75 @@ void qse_sed_setmaxdepth (qse_sed_t* sed, int ids, qse_size_t depth) | ||||
| 	if (ids & QSE_SED_DEPTH_REX_BUILD) sed->depth.rex.build = depth; | ||||
| 	if (ids & QSE_SED_DEPTH_REX_MATCH) sed->depth.rex.match = depth; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static qse_tre_t* maketre ( | ||||
| 	qse_sed_t* sed, const qse_cstr_t* str, const qse_sed_loc_t* loc) | ||||
| { | ||||
| 	qse_tre_t* tre; | ||||
|  | ||||
| 	tre = qse_tre_open (sed->mmgr, 0); | ||||
| 	if (tre == QSE_NULL) | ||||
| 	{ | ||||
| 		SETERR0 (sed, QSE_SED_ENOMEM, loc); | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	if (qse_tre_compx (tre, str->ptr, str->len, QSE_NULL,  | ||||
| 		((sed->option & QSE_SED_EXTENDEDREX)? QSE_TRE_EXTENDED: 0)) <= -1) | ||||
| 	{ | ||||
| 		SETERR1 (sed, QSE_SED_EREXBL, str->ptr, str->len, loc); | ||||
| 		qse_tre_close (tre); | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	return tre; | ||||
| } | ||||
|  | ||||
| static QSE_INLINE void freetre (qse_sed_t* sed, qse_tre_t* tre) | ||||
| { | ||||
| 	qse_tre_close (tre); | ||||
| } | ||||
|  | ||||
| static int matchtre ( | ||||
| 	qse_sed_t* sed, qse_tre_t* tre, int opt,  | ||||
| 	const qse_cstr_t* str, qse_cstr_t* mat, | ||||
| 	qse_cstr_t submat[9], const qse_sed_loc_t* loc) | ||||
| { | ||||
| 	int n; | ||||
| 	qse_tre_match_t match[10]; | ||||
|  | ||||
| 	n = qse_tre_execx (tre, str->ptr, str->len, match, 10, opt); | ||||
| 	if (n <= -1) | ||||
| 	{ | ||||
| 		if (QSE_TRE_ERRNUM(tre) == QSE_TRE_ENOMATCH) return 0; | ||||
| 		SETERR0 (sed, QSE_SED_EREXMA, loc); | ||||
| 		return -1;	 | ||||
| 	} | ||||
| 	 | ||||
| 	QSE_ASSERT (match[0].rm_so != -1); | ||||
| 	if (mat) | ||||
| 	{ | ||||
| 		mat->ptr = &str->ptr[match[0].rm_so]; | ||||
| 		mat->len = match[0].rm_eo - match[0].rm_so; | ||||
| 	} | ||||
|  | ||||
| 	if (submat) | ||||
| 	{ | ||||
| 		int i; | ||||
|  | ||||
| 		/* you must intialize submat before you pass into this  | ||||
| 		 * function because it can abort filling */ | ||||
| 		for (i = 1; i <= 10; i++) | ||||
| 		{ | ||||
| 			if (match[i].rm_so == -1) break; | ||||
| 			submat[i-1].ptr = &str->ptr[match[i].rm_so]; | ||||
| 			submat[i-1].len = match[i].rm_eo - match[i].rm_so; | ||||
| 		} | ||||
| 	} | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* check if c is a space character */ | ||||
| #define IS_SPACE(c) ((c) == QSE_T(' ') || (c) == QSE_T('\t') || (c) == QSE_T('\r')) | ||||
| @ -200,13 +273,15 @@ static void free_address (qse_sed_t* sed, qse_sed_cmd_t* cmd) | ||||
| 	if (cmd->a2.type == QSE_SED_ADR_REX) | ||||
| 	{ | ||||
| 		QSE_ASSERT (cmd->a2.u.rex != QSE_NULL); | ||||
| 		qse_freerex (sed->mmgr, cmd->a2.u.rex); | ||||
| 		/*qse_freerex (sed->mmgr, cmd->a2.u.rex);*/ | ||||
| 		freetre (sed, cmd->a2.u.rex); | ||||
| 		cmd->a2.type = QSE_SED_ADR_NONE; | ||||
| 	} | ||||
| 	if (cmd->a1.type == QSE_SED_ADR_REX) | ||||
| 	{ | ||||
| 		QSE_ASSERT (cmd->a1.u.rex != QSE_NULL); | ||||
| 		qse_freerex (sed->mmgr, cmd->a1.u.rex); | ||||
| 		/*qse_freerex (sed->mmgr, cmd->a1.u.rex);*/ | ||||
| 		freetre (sed, cmd->a1.u.rex); | ||||
| 		cmd->a1.type = QSE_SED_ADR_NONE; | ||||
| 	} | ||||
| } | ||||
| @ -285,7 +360,8 @@ static void free_command (qse_sed_t* sed, qse_sed_cmd_t* cmd) | ||||
| 			if (cmd->u.subst.rpl.ptr) | ||||
| 				QSE_MMGR_FREE (sed->mmgr, cmd->u.subst.rpl.ptr); | ||||
| 			if (cmd->u.subst.rex) | ||||
| 				qse_freerex (sed->mmgr, cmd->u.subst.rex); | ||||
| 				/*qse_freerex (sed->mmgr, cmd->u.subst.rex);*/ | ||||
| 				freetre (sed, cmd->u.subst.rex); | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_SED_CMD_TRANSLATE: | ||||
| @ -300,7 +376,9 @@ static void free_command (qse_sed_t* sed, qse_sed_cmd_t* cmd) | ||||
|  | ||||
| static void* compile_rex (qse_sed_t* sed, qse_char_t rxend) | ||||
| { | ||||
| #ifdef USE_REX | ||||
| 	void* code; | ||||
| #endif | ||||
| 	qse_cint_t c; | ||||
|  | ||||
| 	qse_str_clear (&sed->tmp.rex); | ||||
| @ -346,43 +424,11 @@ static void* compile_rex (qse_sed_t* sed, qse_char_t rxend) | ||||
| 		} | ||||
| 	}  | ||||
|  | ||||
|  | ||||
| #if 0 | ||||
| { | ||||
| 	qse_tre_t* tre; | ||||
|  | ||||
| 	tre = qse_tre_open (sed->mmgr, 0); | ||||
| 	if (tre) | ||||
| 	{ | ||||
| 		if (qse_tre_comp (tre, | ||||
| 			QSE_STR_PTR(&sed->tmp.rex),  | ||||
| 			QSE_STR_LEN(&sed->tmp.rex), | ||||
| 			QSE_NULL, | ||||
| 			QSE_TRE_EXTENDED) <= -1) | ||||
| 		{ | ||||
| 			qse_tre_close (tre); | ||||
| 			goto fail: | ||||
| 		} | ||||
| 		return tre; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		SETERR1 ( | ||||
| 			sed, QSE_SED_EREXBL, | ||||
| 			QSE_STR_PTR(&sed->tmp.rex), | ||||
| 			QSE_STR_LEN(&sed->tmp.rex), | ||||
| 			&sed->src.loc | ||||
| 		); | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #ifdef USE_REX | ||||
| 	code = qse_buildrex ( | ||||
| 		sed->mmgr, | ||||
| 		sed->depth.rex.build, | ||||
| 		((sed->option&QSE_SED_REXBOUND)? 0:QSE_REX_NOBOUND), | ||||
| 		((sed->option&QSE_SED_EXTENDEDREX)? 0:QSE_REX_NOBOUND), | ||||
| 		QSE_STR_PTR(&sed->tmp.rex),  | ||||
| 		QSE_STR_LEN(&sed->tmp.rex),  | ||||
| 		QSE_NULL | ||||
| @ -399,6 +445,10 @@ static void* compile_rex (qse_sed_t* sed, qse_char_t rxend) | ||||
| 	} | ||||
|  | ||||
| 	return code; | ||||
|  | ||||
| #else | ||||
| 	return maketre (sed, QSE_STR_CSTR(&sed->tmp.rex), &sed->src.loc); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static qse_sed_adr_t* get_address (qse_sed_t* sed, qse_sed_adr_t* a) | ||||
| @ -809,12 +859,14 @@ static int get_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) | ||||
| 		{ | ||||
| 			CHECK_CMDIC (sed, cmd, c, goto oops); | ||||
|  | ||||
| #if 0 | ||||
| 			if (c == QSE_T('\\')) | ||||
| 			{ | ||||
| 				c = NXTSC (sed); | ||||
| 				CHECK_CMDIC (sed, cmd, c, goto oops); | ||||
| 				if (c == QSE_T('n')) c = QSE_T('\n'); | ||||
| 			} | ||||
| #endif | ||||
|  | ||||
| 			if (qse_str_ccat (t[i], c) == (qse_size_t)-1) | ||||
| 			{ | ||||
| @ -895,10 +947,12 @@ static int get_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) | ||||
| 	    terminate_command (sed) <= -1) goto oops; | ||||
|  | ||||
| 	QSE_ASSERT (cmd->u.subst.rex == QSE_NULL); | ||||
|  | ||||
| #ifdef USE_REX | ||||
| 	cmd->u.subst.rex = qse_buildrex ( | ||||
| 		sed->mmgr, | ||||
| 		sed->depth.rex.build, | ||||
| 		((sed->option&QSE_SED_REXBOUND)? 0:QSE_REX_NOBOUND), | ||||
| 		((sed->option&QSE_SED_EXTENDEDREX)? 0:QSE_REX_NOBOUND), | ||||
| 		QSE_STR_PTR(t[0]), | ||||
| 		QSE_STR_LEN(t[0]), | ||||
| 		QSE_NULL | ||||
| @ -913,6 +967,10 @@ static int get_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) | ||||
| 		); | ||||
| 		goto oops; | ||||
| 	}	 | ||||
| #else | ||||
| 	cmd->u.subst.rex = maketre (sed, QSE_STR_CSTR(t[0]), &sed->src.loc); | ||||
| 	if (cmd->u.subst.rex == QSE_NULL) goto oops; | ||||
| #endif | ||||
|  | ||||
| 	qse_str_yield (t[1], &cmd->u.subst.rpl, 0); | ||||
| 	if (cmd->u.subst.g == 0 && cmd->u.subst.occ == 0) cmd->u.subst.occ = 1; | ||||
| @ -1833,7 +1891,9 @@ static int do_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) | ||||
| { | ||||
| 	qse_cstr_t mat, pmat; | ||||
| 	int opt = 0, repl = 0, n; | ||||
| #ifdef USE_REX | ||||
| 	qse_rex_errnum_t errnum; | ||||
| #endif | ||||
|  | ||||
| 	qse_cstr_t str, cur; | ||||
| 	const qse_char_t* str_end; | ||||
| @ -1842,7 +1902,11 @@ static int do_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) | ||||
| 	QSE_ASSERT (cmd->type == QSE_SED_CMD_SUBSTITUTE); | ||||
|  | ||||
| 	qse_str_clear (&sed->e.txt.subst); | ||||
| #ifdef USE_REX | ||||
| 	if (cmd->u.subst.i) opt = QSE_REX_IGNORECASE; | ||||
| #else | ||||
| 	if (cmd->u.subst.i) opt = QSE_TRE_IGNORECASE; | ||||
| #endif | ||||
|  | ||||
| 	str.ptr = QSE_STR_PTR(&sed->e.in.line); | ||||
| 	str.len = QSE_STR_LEN(&sed->e.in.line); | ||||
| @ -1863,6 +1927,7 @@ static int do_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) | ||||
| 	 * end of string($) needs to be tested */ | ||||
| 	while (cur.ptr <= str_end) | ||||
| 	{ | ||||
| #ifdef USE_REX | ||||
| 		if (max_count == 0 || sub_count < max_count) | ||||
| 		{ | ||||
| 			n = qse_matchrex ( | ||||
| @ -1871,14 +1936,29 @@ static int do_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) | ||||
| 				cmd->u.subst.rex, opt, | ||||
| 				&str, &cur, &mat, &errnum | ||||
| 			); | ||||
| 		} | ||||
| 		else n = 0; | ||||
|  | ||||
| 			if (n <= -1) | ||||
| 			{ | ||||
| 				SETERR0 (sed, QSE_SED_EREXMA, &cmd->loc); | ||||
| 				return -1; | ||||
| 			} | ||||
| 		} | ||||
| 		else n = 0; | ||||
| #else | ||||
| 		qse_cstr_t submat[9]; | ||||
|  | ||||
| 		QSE_MEMSET (submat, 0, QSE_SIZEOF(submat)); | ||||
| 		if (max_count == 0 || sub_count < max_count) | ||||
| 		{ | ||||
| 			n = matchtre ( | ||||
| 				sed, | ||||
| 				cmd->u.subst.rex, | ||||
| 				((str.ptr == cur.ptr)? opt: (opt | QSE_TRE_NOTBOL)), | ||||
| 				&cur, &mat, submat, &cmd->loc | ||||
| 			); | ||||
| 			if (n <= -1) return -1; | ||||
| 		} | ||||
| 		else n = 0; | ||||
| #endif | ||||
|  | ||||
| 		if (n == 0)  | ||||
| 		{ | ||||
| @ -1930,11 +2010,49 @@ static int do_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) | ||||
| 			for (i = 0; i < cmd->u.subst.rpl.len; i++) | ||||
| 			{ | ||||
| 				if ((i+1) < cmd->u.subst.rpl.len &&  | ||||
| 				    cmd->u.subst.rpl.ptr[i] == QSE_T('\\') &&  | ||||
| 				    cmd->u.subst.rpl.ptr[i+1] == QSE_T('&')) | ||||
| 				    cmd->u.subst.rpl.ptr[i] == QSE_T('\\')) | ||||
| 				{ | ||||
| 					m = qse_str_ccat ( | ||||
| 						&sed->e.txt.subst, QSE_T('&')); | ||||
| 					qse_char_t nc = cmd->u.subst.rpl.ptr[i+1]; | ||||
|  | ||||
| #ifndef USE_REX | ||||
| 					if (nc >= QSE_T('1') && nc <= QSE_T('9')) | ||||
| 					{ | ||||
| 						int smi = nc - QSE_T('1'); | ||||
| 						m = qse_str_ncat (&sed->e.txt.subst, submat[smi].ptr, submat[smi].len); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| #endif | ||||
| 						switch (nc) | ||||
| 						{ | ||||
| 							case QSE_T('n'): | ||||
| 								nc = QSE_T('\n'); | ||||
| 								break; | ||||
| 							case QSE_T('r'): | ||||
| 								nc = QSE_T('\r'); | ||||
| 								break; | ||||
| 							case QSE_T('t'): | ||||
| 								nc = QSE_T('\t'); | ||||
| 								break; | ||||
| 							case QSE_T('f'): | ||||
| 								nc = QSE_T('\f'); | ||||
| 								break; | ||||
| 							case QSE_T('b'): | ||||
| 								nc = QSE_T('\b'); | ||||
| 								break; | ||||
| 							case QSE_T('v'): | ||||
| 								nc = QSE_T('\v'); | ||||
| 								break; | ||||
| 							case QSE_T('a'): | ||||
| 								nc = QSE_T('\a'); | ||||
| 								break; | ||||
| #ifndef USE_REX | ||||
| 						} | ||||
| #endif | ||||
|  | ||||
| 						m = qse_str_ccat (&sed->e.txt.subst, nc); | ||||
| 					} | ||||
|  | ||||
| 					i++; | ||||
| 				} | ||||
| 				else if (cmd->u.subst.rpl.ptr[i] == QSE_T('&')) | ||||
| @ -2032,10 +2150,12 @@ static int match_a (qse_sed_t* sed, qse_sed_cmd_t* cmd, qse_sed_adr_t* a) | ||||
|  | ||||
| 		case QSE_SED_ADR_REX: | ||||
| 		{ | ||||
| #ifdef USE_REX | ||||
| 			int n; | ||||
| 			qse_cstr_t match; | ||||
| 			qse_cstr_t line; | ||||
| 			qse_rex_errnum_t errnum; | ||||
| 			qse_cstr_t match; | ||||
| #endif | ||||
| 			qse_cstr_t line; | ||||
|  | ||||
| 			QSE_ASSERT (a->u.rex != QSE_NULL); | ||||
|  | ||||
| @ -2045,6 +2165,7 @@ static int match_a (qse_sed_t* sed, qse_sed_cmd_t* cmd, qse_sed_adr_t* a) | ||||
| 			if (line.len > 0 && | ||||
| 			    line.ptr[line.len-1] == QSE_T('\n')) line.len--; | ||||
|  | ||||
| #ifdef USE_REX | ||||
| 			n = qse_matchrex ( | ||||
| 				sed->mmgr,  | ||||
| 				sed->depth.rex.match, | ||||
| @ -2058,6 +2179,10 @@ static int match_a (qse_sed_t* sed, qse_sed_cmd_t* cmd, qse_sed_adr_t* a) | ||||
| 			}			 | ||||
|  | ||||
| 			return n; | ||||
| #else | ||||
| 			return matchtre (sed, a->u.rex, 0, &line, QSE_NULL, QSE_NULL, &cmd->loc); | ||||
| #endif | ||||
|  | ||||
| 		} | ||||
| 		case QSE_SED_ADR_DOL: | ||||
| 		{ | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: sed.h 441 2011-04-22 14:28:43Z hyunghwan.chung $ | ||||
|  * $Id: sed.h 558 2011-09-02 15:27:44Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2011 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -28,6 +28,23 @@ | ||||
| #define QSE_MAP_AS_RBT | ||||
| #include <qse/cmn/map.h> | ||||
|  | ||||
|  | ||||
| /*  | ||||
|  * Define USE_REX to use rex.h on behalf of tre.h  | ||||
|  * rex.h currently does not support backreference. | ||||
|  */ | ||||
| #ifdef USE_REX | ||||
| enum qse_sed_depth_t | ||||
| { | ||||
|      QSE_SED_DEPTH_REX_BUILD = (1 << 0), | ||||
|      QSE_SED_DEPTH_REX_MATCH = (1 << 1) | ||||
| }; | ||||
| typedef enum qse_sed_depth_t qse_sed_depth_t | ||||
| #endif | ||||
|  | ||||
| #define QSE_SED_CMD_NOOP            QSE_T('\0') | ||||
| #define QSE_SED_CMD_QUIT            QSE_T('q') | ||||
|  | ||||
| typedef struct qse_sed_adr_t qse_sed_adr_t;  | ||||
| typedef struct qse_sed_cmd_t qse_sed_cmd_t; | ||||
| typedef struct qse_sed_cmd_blk_t qse_sed_cmd_blk_t; | ||||
| @ -50,8 +67,6 @@ struct qse_sed_adr_t | ||||
| 	} u; | ||||
| }; | ||||
|  | ||||
| #define QSE_SED_CMD_NOOP            QSE_T('\0') | ||||
| #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') | ||||
| @ -262,7 +277,39 @@ struct qse_sed_t | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| const qse_char_t* qse_sed_dflerrstr (qse_sed_t* sed, qse_sed_errnum_t errnum); | ||||
| int qse_sed_init ( | ||||
| 	qse_sed_t* sed,  | ||||
| 	qse_mmgr_t* mmgr | ||||
| ); | ||||
|  | ||||
| void qse_sed_fini ( | ||||
| 	qse_sed_t* sed | ||||
| ); | ||||
|  | ||||
| const qse_char_t* qse_sed_dflerrstr ( | ||||
| 	qse_sed_t* sed,  | ||||
| 	qse_sed_errnum_t errnum | ||||
| ); | ||||
|  | ||||
|  | ||||
| #ifdef USE_REX | ||||
| /** | ||||
|  * The qse_sed_getmaxdepth() gets the maximum processing depth. | ||||
|  */ | ||||
| qse_size_t qse_sed_getmaxdepth ( | ||||
| 	qse_sed_t*      sed, /**< stream editor */ | ||||
| 	qse_sed_depth_t id   /**< one of qse_sed_depth_t values */ | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_sed_setmaxdepth() sets the maximum processing depth. | ||||
|  */ | ||||
| void qse_sed_setmaxdepth ( | ||||
| 	qse_sed_t* sed,  /**< stream editor */ | ||||
| 	int        ids,  /**< 0 or a number OR'ed of #qse_sed_depth_t values */ | ||||
| 	qse_size_t depth /**< maximum depth level */ | ||||
| ); | ||||
| #endif | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user