added error handling after reading from script streams.
changed qse_sed_compstd() to return the number of opened stream resources via a parameter. relocated qse_sed_cmd_t and qse_sed_adr_to to the public sed.h header file.
This commit is contained in:
		| @ -64,6 +64,7 @@ static qse_char_t* g_output_file = QSE_NULL; | |||||||
| static int g_infile_pos = 0; | static int g_infile_pos = 0; | ||||||
| static int g_option = 0; | static int g_option = 0; | ||||||
| static int g_separate = 0; | static int g_separate = 0; | ||||||
|  | static int g_trace = 0; | ||||||
| static qse_ulong_t g_memlimit = 0; | static qse_ulong_t g_memlimit = 0; | ||||||
| static qse_sed_t* g_sed = QSE_NULL; | static qse_sed_t* g_sed = QSE_NULL; | ||||||
|  |  | ||||||
| @ -188,9 +189,9 @@ static int handle_args (int argc, qse_char_t* argv[]) | |||||||
| 	static qse_opt_t opt =  | 	static qse_opt_t opt =  | ||||||
| 	{ | 	{ | ||||||
| #if defined(QSE_BUILD_DEBUG) | #if defined(QSE_BUILD_DEBUG) | ||||||
| 		QSE_T("hne:f:o:rRsawxym:X:"), | 		QSE_T("hne:f:o:rRsawxytm:X:"), | ||||||
| #else | #else | ||||||
| 		QSE_T("hne:f:o:rRsawxym:"), | 		QSE_T("hne:f:o:rRsawxytm:"), | ||||||
| #endif | #endif | ||||||
| 		QSE_NULL | 		QSE_NULL | ||||||
| 	}; | 	}; | ||||||
| @ -268,6 +269,10 @@ static int handle_args (int argc, qse_char_t* argv[]) | |||||||
| 				g_option |= QSE_SED_ENSURENL; | 				g_option |= QSE_SED_ENSURENL; | ||||||
| 				break; | 				break; | ||||||
|  |  | ||||||
|  | 			case QSE_T('t'): | ||||||
|  | 				g_trace = 1; | ||||||
|  | 				break; | ||||||
|  |   | ||||||
| 			case QSE_T('m'): | 			case QSE_T('m'): | ||||||
| 				g_memlimit = qse_strtoulong (opt.arg); | 				g_memlimit = qse_strtoulong (opt.arg); | ||||||
| 				break; | 				break; | ||||||
| @ -445,21 +450,24 @@ static void unset_intr_run (void) | |||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| static void trace (qse_sed_t* sed, qse_sed_exec_op_t op, const qse_sed_cmd_t* cmd) | static void trace_exec (qse_sed_t* sed, qse_sed_exec_op_t op, const qse_sed_cmd_t* cmd) | ||||||
| { | { | ||||||
| 	switch (op) | 	switch (op) | ||||||
| 	{ | 	{ | ||||||
|  | #if 0 | ||||||
| 		case QSE_SED_EXEC_READ: | 		case QSE_SED_EXEC_READ: | ||||||
| 			qse_printf (QSE_T("reading...\n")); | 			qse_printf (QSE_T("reading...\n")); | ||||||
| 			break; | 			break; | ||||||
| 		case QSE_SED_EXEC_WRITE: | 		case QSE_SED_EXEC_WRITE: | ||||||
| 			qse_printf (QSE_T("wrting...\n")); | 			qse_printf (QSE_T("wrting...\n")); | ||||||
| 			break; | 			break; | ||||||
|  | #endif | ||||||
| 		case QSE_SED_EXEC_MATCH: | 		case QSE_SED_EXEC_MATCH: | ||||||
| 			qse_printf (QSE_T("matching...\n")); | 			qse_printf (QSE_T("matching address for [%c] at line %lu\n"), cmd->type, (unsigned long)cmd->loc.line); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case QSE_SED_EXEC_EXEC: | 		case QSE_SED_EXEC_EXEC: | ||||||
| 			qse_printf (QSE_T("executing...\n")); | 			qse_printf (QSE_T("executing [%c] at line %lu\n"), cmd->type, (unsigned long)cmd->loc.line); | ||||||
| 			break; | 			break; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @ -468,6 +476,7 @@ int sed_main (int argc, qse_char_t* argv[]) | |||||||
| { | { | ||||||
| 	qse_mmgr_t* mmgr = QSE_NULL; | 	qse_mmgr_t* mmgr = QSE_NULL; | ||||||
| 	qse_sed_t* sed = QSE_NULL; | 	qse_sed_t* sed = QSE_NULL; | ||||||
|  | 	qse_size_t script_count; | ||||||
| 	int ret = -1; | 	int ret = -1; | ||||||
|  |  | ||||||
| 	ret = handle_args (argc, argv); | 	ret = handle_args (argc, argv); | ||||||
| @ -504,13 +513,30 @@ int sed_main (int argc, qse_char_t* argv[]) | |||||||
| 	 | 	 | ||||||
| 	qse_sed_setoption (sed, g_option); | 	qse_sed_setoption (sed, g_option); | ||||||
|  |  | ||||||
| 	if (qse_sed_compstd (sed, g_script.io) == -1) | 	if (qse_sed_compstd (sed, g_script.io, &script_count) <= -1) | ||||||
| 	{ | 	{ | ||||||
| 		const qse_sed_loc_t* errloc = qse_sed_geterrloc(sed); | 		const qse_sed_loc_t* errloc = qse_sed_geterrloc(sed); | ||||||
|  | 		const qse_char_t* target; | ||||||
|  | 		qse_char_t exprbuf[128]; | ||||||
|  | 	 | ||||||
|  | 		if (g_script.io[script_count].type == QSE_SED_IOSTD_FILE) | ||||||
|  | 		{ | ||||||
|  | 			target = g_script.io[script_count].u.file; | ||||||
|  | 		} | ||||||
|  | 		else  | ||||||
|  | 		{ | ||||||
|  | 			/* i dont' use QSE_SED_IOSTD_SIO for input */	 | ||||||
|  | 			QSE_ASSERT (g_script.io[script_count].type == QSE_SED_IOSTD_MEM); | ||||||
|  | 			qse_sprintf (exprbuf, QSE_COUNTOF(exprbuf),  | ||||||
|  | 				QSE_T("expression #%lu"), (unsigned long)script_count); | ||||||
|  | 			target = exprbuf; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		if (errloc->line > 0 || errloc->colm > 0) | 		if (errloc->line > 0 || errloc->colm > 0) | ||||||
| 		{ | 		{ | ||||||
| 			qse_fprintf (QSE_STDERR,  | 			qse_fprintf (QSE_STDERR,  | ||||||
| 				QSE_T("cannot compile - %s at line %lu column %lu\n"), | 				QSE_T("cannot compile %s - %s at line %lu column %lu\n"), | ||||||
|  | 				target, | ||||||
| 				qse_sed_geterrmsg(sed), | 				qse_sed_geterrmsg(sed), | ||||||
| 				(unsigned long)errloc->line, | 				(unsigned long)errloc->line, | ||||||
| 				(unsigned long)errloc->colm | 				(unsigned long)errloc->colm | ||||||
| @ -519,16 +545,15 @@ int sed_main (int argc, qse_char_t* argv[]) | |||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			qse_fprintf (QSE_STDERR,  | 			qse_fprintf (QSE_STDERR,  | ||||||
| 				QSE_T("cannot compile - %s\n"), | 				QSE_T("cannot compile %s - %s\n"), | ||||||
|  | 				target, | ||||||
| 				qse_sed_geterrmsg(sed) | 				qse_sed_geterrmsg(sed) | ||||||
| 			); | 			); | ||||||
| 		} | 		} | ||||||
| 		goto oops; | 		goto oops; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| #if 0 | 	if (g_trace) qse_sed_setexectracer (sed, trace_exec); | ||||||
| if (g_trace) qse_sed_setexechook (sed, trace); |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| 	if (g_separate && g_infile_pos > 0) | 	if (g_separate && g_infile_pos > 0) | ||||||
| 	{ | 	{ | ||||||
|  | |||||||
| @ -65,6 +65,8 @@ | |||||||
|  */ |  */ | ||||||
| typedef struct qse_sed_t qse_sed_t; | typedef struct qse_sed_t qse_sed_t; | ||||||
|  |  | ||||||
|  | typedef struct qse_sed_loc_t qse_sed_loc_t; | ||||||
|  | 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_t qse_sed_cmd_t; | ||||||
|  |  | ||||||
| /**  | /**  | ||||||
| @ -75,7 +77,111 @@ struct qse_sed_loc_t | |||||||
| 	qse_size_t line; /**< line  */ | 	qse_size_t line; /**< line  */ | ||||||
| 	qse_size_t colm; /**< column */ | 	qse_size_t colm; /**< column */ | ||||||
| }; | }; | ||||||
| typedef struct qse_sed_loc_t qse_sed_loc_t; |  | ||||||
|  | struct qse_sed_adr_t | ||||||
|  | { | ||||||
|  | 	enum | ||||||
|  | 	{ | ||||||
|  | 		QSE_SED_ADR_NONE,     /* no address */ | ||||||
|  | 		QSE_SED_ADR_DOL,      /* $ - last line */ | ||||||
|  | 		QSE_SED_ADR_LINE,     /* specified line */ | ||||||
|  | 		QSE_SED_ADR_REX,      /* lines matching regular expression */ | ||||||
|  | 		QSE_SED_ADR_STEP,     /* line steps - only in the second address */ | ||||||
|  | 		QSE_SED_ADR_RELLINE,  /* relative line - only in second address */ | ||||||
|  | 		QSE_SED_ADR_RELLINEM  /* relative line in the multiples - only in second address */ | ||||||
|  | 	} type; | ||||||
|  |  | ||||||
|  | 	union  | ||||||
|  | 	{ | ||||||
|  | 		qse_size_t lno; | ||||||
|  | 		void*      rex; | ||||||
|  | 	} 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') | ||||||
|  | #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') | ||||||
|  | #define QSE_SED_CMD_CLEAR_PATTERN   QSE_T('z') | ||||||
|  |  | ||||||
|  | struct qse_sed_cmd_t | ||||||
|  | { | ||||||
|  | 	qse_char_t type; | ||||||
|  | 	qse_sed_loc_t loc; | ||||||
|  |  | ||||||
|  | 	int negated; | ||||||
|  |  | ||||||
|  | 	qse_sed_adr_t a1; /* optional start address */ | ||||||
|  | 	qse_sed_adr_t a2; /* optional end address */ | ||||||
|  |  | ||||||
|  | 	union | ||||||
|  | 	{ | ||||||
|  | 		/* text for the a, i, c commands */ | ||||||
|  | 		qse_xstr_t text;   | ||||||
|  |  | ||||||
|  | 		/* file name for r, w, R, W */ | ||||||
|  | 		qse_xstr_t file; | ||||||
|  |  | ||||||
|  | 		/* data for the s command */ | ||||||
|  | 		struct | ||||||
|  | 		{ | ||||||
|  | 			void* rex; /* regular expression */ | ||||||
|  | 			qse_xstr_t rpl;  /* replacement */ | ||||||
|  |  | ||||||
|  | 			/* flags */ | ||||||
|  | 			qse_xstr_t file; /* file name for w */ | ||||||
|  | 			unsigned short occ; | ||||||
|  | 			unsigned short g: 1; /* global */ | ||||||
|  | 			unsigned short p: 1; /* print */ | ||||||
|  | 			unsigned short i: 1; /* case insensitive */ | ||||||
|  | 		} subst; | ||||||
|  |  | ||||||
|  | 		/* translation set for the y command */ | ||||||
|  | 		qse_xstr_t transet; | ||||||
|  |  | ||||||
|  | 		/* branch target for b and t */ | ||||||
|  | 		struct | ||||||
|  | 		{ | ||||||
|  | 			qse_xstr_t label; | ||||||
|  | 			qse_sed_cmd_t* target; | ||||||
|  | 		} branch; | ||||||
|  | 	} u;	 | ||||||
|  |  | ||||||
|  | 	struct | ||||||
|  | 	{ | ||||||
|  | 		int a1_matched; | ||||||
|  | 		qse_size_t a1_match_line; | ||||||
|  |  | ||||||
|  | 		int c_ready; | ||||||
|  |  | ||||||
|  | 		/* points to the next command for fast traversal and  | ||||||
|  | 		 * fast random jumps */ | ||||||
|  | 		qse_sed_cmd_t* next;  | ||||||
|  | 	} state; | ||||||
|  | }; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * the qse_sed_errnum_t type defines error numbers. |  * the qse_sed_errnum_t type defines error numbers. | ||||||
| @ -204,7 +310,7 @@ enum qse_sed_exec_op_t | |||||||
| }; | }; | ||||||
| typedef enum qse_sed_exec_op_t qse_sed_exec_op_t; | typedef enum qse_sed_exec_op_t qse_sed_exec_op_t; | ||||||
|  |  | ||||||
| typedef void (*qse_sed_exec_hook_t) ( | typedef void (*qse_sed_exec_tracer_t) ( | ||||||
| 	qse_sed_t*           sed, | 	qse_sed_t*           sed, | ||||||
| 	qse_sed_exec_op_t    op, | 	qse_sed_exec_op_t    op, | ||||||
| 	const qse_sed_cmd_t* cmd | 	const qse_sed_cmd_t* cmd | ||||||
| @ -431,13 +537,13 @@ void qse_sed_setlinnum ( | |||||||
| 	qse_size_t num    /**< a line number */ | 	qse_size_t num    /**< a line number */ | ||||||
| ); | ); | ||||||
|  |  | ||||||
| qse_sed_exec_hook_t qse_sed_getexechook ( | qse_sed_exec_tracer_t qse_sed_getexectracer ( | ||||||
| 	qse_sed_t* sed | 	qse_sed_t* sed | ||||||
| ); | ); | ||||||
|  |  | ||||||
| void qse_sed_setexechook ( | void qse_sed_setexectracer ( | ||||||
| 	qse_sed_t*            sed, | 	qse_sed_t*            sed, | ||||||
| 	qse_sed_exec_hook_t hook | 	qse_sed_exec_tracer_t tracer | ||||||
| ); | ); | ||||||
|  |  | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
|  | |||||||
| @ -96,21 +96,29 @@ void* qse_sed_getxtnstd ( | |||||||
|  |  | ||||||
| /** | /** | ||||||
|  * The qse_sed_compstd() function compiles sed scripts specified in |  * The qse_sed_compstd() function compiles sed scripts specified in | ||||||
|  * a null-terminated array of stream resources. |  * an array of stream resources. The end of the array is indicated | ||||||
|  |  * by an element whose type is #QSE_SED_IOSTD_NULL. However, the type | ||||||
|  |  * of the first element shall not be #QSE_SED_IOSTD_NULL. The output  | ||||||
|  |  * parameter @a count is set to the count of stream resources  | ||||||
|  |  * opened on both success and failure. You can pass #QSE_NULL to @a | ||||||
|  |  * count if the count is not needed. | ||||||
|  |  * | ||||||
|  * @return 0 on success, -1 on failure |  * @return 0 on success, -1 on failure | ||||||
|  */ |  */ | ||||||
| int qse_sed_compstd ( | int qse_sed_compstd ( | ||||||
| 	qse_sed_t*        sed,  /**< stream editor */ | 	qse_sed_t*        sed,  /**< stream editor */ | ||||||
| 	qse_sed_iostd_t   in[] /**< input scripts */ | 	qse_sed_iostd_t   in[], /**< input scripts */ | ||||||
|  | 	qse_size_t*       count /**< number of input scripts opened */ | ||||||
| ); | ); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * The qse_sed_execstd() function executes a compiled script |  * The qse_sed_execstd() function executes a compiled script | ||||||
|  * over input streams @a in and an output stream @a out. |  * over input streams @a in and an output stream @a out. | ||||||
|  * |  * | ||||||
|  * If @a in is not #QSE_NULL, it must point to a null-terminated array |  * If @a in is not #QSE_NULL, it must point to an array of stream  | ||||||
|  * of stream resources. if in[0].type is QSE_SED_IOSTD_NULL, this  |  * resources whose end is indicated by an element with #QSE_SED_IOSTD_NULL | ||||||
|  * function returns failure, requiring at least 1 valid resource to be  |  * type. However, the type of the first element @ in[0].type show not | ||||||
|  |  * be #QSE_SED_IOSTD_NULL. It requires at least 1 valid resource to be  | ||||||
|  * included in the array. |  * included in the array. | ||||||
|  * |  * | ||||||
|  * If @a in is #QSE_NULL, the standard console input is used. |  * If @a in is #QSE_NULL, the standard console input is used. | ||||||
|  | |||||||
| @ -344,8 +344,12 @@ static int matchtre ( | |||||||
| #define IS_LABCHAR(c) (!IS_CMDTERM(c) && !IS_WSPACE(c)) | #define IS_LABCHAR(c) (!IS_CMDTERM(c) && !IS_WSPACE(c)) | ||||||
|  |  | ||||||
| #define CURSC(sed) ((sed)->src.cc) | #define CURSC(sed) ((sed)->src.cc) | ||||||
| #define NXTSC(sed) getnextsc(sed) | #define NXTSC(sed,c,errret) \ | ||||||
| #define PEEPNXTSC(sed) peepnextsc(sed) | 	do { if (getnextsc(sed,&(c)) <= -1) return (errret); } while (0) | ||||||
|  | #define NXTSC_GOTO(sed,c,label) \ | ||||||
|  | 	do { if (getnextsc(sed,&(c)) <= -1) goto label; } while (0) | ||||||
|  | #define PEEPNXTSC(sed,c,errret) \ | ||||||
|  | 	do { if (peepnextsc(sed,&(c)) <= -1) return (errret); } while (0) | ||||||
|  |  | ||||||
| static int open_script_stream (qse_sed_t* sed) | static int open_script_stream (qse_sed_t* sed) | ||||||
| { | { | ||||||
| @ -407,21 +411,23 @@ static int read_script_stream (qse_sed_t* sed) | |||||||
| 	{ | 	{ | ||||||
| 		if (sed->errnum == QSE_SED_ENOERR) | 		if (sed->errnum == QSE_SED_ENOERR) | ||||||
| 			SETERR0 (sed, QSE_SED_EIOUSR, QSE_NULL); | 			SETERR0 (sed, QSE_SED_EIOUSR, QSE_NULL); | ||||||
| 		return -1; | 		return -1; /* error */ | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (n == 0) | 	if (n == 0) | ||||||
| 	{ | 	{ | ||||||
|  | 		/* don't change sed->src.cur and sed->src.end. | ||||||
|  | 		 * they remain the same on eof  */ | ||||||
| 		sed->src.eof = 1; | 		sed->src.eof = 1; | ||||||
| 		return 0; | 		return 0; /* eof */ | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	sed->src.cur = sed->src.buf; | 	sed->src.cur = sed->src.buf; | ||||||
| 	sed->src.end = sed->src.buf + n; | 	sed->src.end = sed->src.buf + n; | ||||||
| 	return 1; | 	return 1; /* read something */ | ||||||
| } | } | ||||||
|  |  | ||||||
| static qse_cint_t getnextsc (qse_sed_t* sed) | static int getnextsc (qse_sed_t* sed, qse_cint_t* c) | ||||||
| { | { | ||||||
| 	/* adjust the line and column number of the next | 	/* adjust the line and column number of the next | ||||||
| 	 * character based on the current character */ | 	 * character based on the current character */ | ||||||
| @ -451,10 +457,11 @@ static qse_cint_t getnextsc (qse_sed_t* sed) | |||||||
| 		(sed->src.cur < sed->src.end)?  | 		(sed->src.cur < sed->src.end)?  | ||||||
| 		(*sed->src.cur++): QSE_CHAR_EOF; | 		(*sed->src.cur++): QSE_CHAR_EOF; | ||||||
|  |  | ||||||
| 	return sed->src.cc; | 	*c = sed->src.cc; | ||||||
|  | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static qse_cint_t peepnextsc (qse_sed_t* sed) | static int peepnextsc (qse_sed_t* sed, qse_cint_t* c) | ||||||
| { | { | ||||||
| 	if (sed->src.cur >= sed->src.end && !sed->src.eof)  | 	if (sed->src.cur >= sed->src.end && !sed->src.eof)  | ||||||
| 	{ | 	{ | ||||||
| @ -466,9 +473,8 @@ static qse_cint_t peepnextsc (qse_sed_t* sed) | |||||||
|  |  | ||||||
| 	/* no changes in line nubmers, the 'cur' pointer, and | 	/* no changes in line nubmers, the 'cur' pointer, and | ||||||
| 	 * most importantly 'cc' unlike getnextsc(). */ | 	 * most importantly 'cc' unlike getnextsc(). */ | ||||||
| 	return | 	*c = (sed->src.cur < sed->src.end)?  (*sed->src.cur): QSE_CHAR_EOF; | ||||||
| 		(sed->src.cur < sed->src.end)?  | 	return 0; | ||||||
| 		(*sed->src.cur): QSE_CHAR_EOF; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static void free_address (qse_sed_t* sed, qse_sed_cmd_t* cmd) | static void free_address (qse_sed_t* sed, qse_sed_cmd_t* cmd) | ||||||
| @ -584,7 +590,7 @@ static QSE_INLINE int xdigit_to_num (qse_cint_t c) | |||||||
| 	       (c >= QSE_T('a') && c <= QSE_T('f'))? (c - QSE_T('a') + 10): -1; | 	       (c >= QSE_T('a') && c <= QSE_T('f'))? (c - QSE_T('a') + 10): -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| static qse_cint_t trans_escaped (qse_sed_t* sed, qse_cint_t c, int* xamp) | static int trans_escaped (qse_sed_t* sed, qse_cint_t c, qse_cint_t* ec, int* xamp) | ||||||
| { | { | ||||||
| 	if (xamp) *xamp = 0; | 	if (xamp) *xamp = 0; | ||||||
|  |  | ||||||
| @ -619,15 +625,18 @@ Omitted for clash with regular expression \b. | |||||||
| 		{ | 		{ | ||||||
| 			/* \xnn */ | 			/* \xnn */ | ||||||
| 			int cc; | 			int cc; | ||||||
|  | 			qse_cint_t peeped; | ||||||
|  |  | ||||||
| 			cc = xdigit_to_num(PEEPNXTSC(sed)); | 			PEEPNXTSC (sed, peeped, -1); | ||||||
|  | 			cc = xdigit_to_num (peeped); | ||||||
| 			if (cc <= -1) break; | 			if (cc <= -1) break; | ||||||
| 			NXTSC(sed); | 			NXTSC (sed, peeped, -1); /* consume the character peeped */ | ||||||
| 			c = cc; | 			c = cc; | ||||||
|  |  | ||||||
| 			cc = xdigit_to_num(PEEPNXTSC(sed)); | 			PEEPNXTSC (sed, peeped, -1); | ||||||
|  | 			cc = xdigit_to_num (peeped); | ||||||
| 			if (cc <= -1) break; | 			if (cc <= -1) break; | ||||||
| 			NXTSC(sed); | 			NXTSC (sed, peeped, -1); /* consume the character peeped */ | ||||||
| 			c = (c << 4) | cc; | 			c = (c << 4) | cc; | ||||||
|  |  | ||||||
| 			/* let's indicate that '&' is built from \x26. */ | 			/* let's indicate that '&' is built from \x26. */ | ||||||
| @ -640,17 +649,20 @@ Omitted for clash with regular expression \b. | |||||||
| 		{ | 		{ | ||||||
| 			/* \Xnnnn or \Xnnnnnnnn for wchar_t */ | 			/* \Xnnnn or \Xnnnnnnnn for wchar_t */ | ||||||
| 			int cc, i; | 			int cc, i; | ||||||
|  | 			qse_cint_t peeped; | ||||||
|  |  | ||||||
| 			cc = xdigit_to_num(PEEPNXTSC(sed)); | 			PEEPNXTSC (sed, peeped, -1); | ||||||
|  | 			cc = xdigit_to_num (peeped); | ||||||
| 			if (cc <= -1) break; | 			if (cc <= -1) break; | ||||||
| 			NXTSC(sed); | 			NXTSC (sed, peeped, -1); /* consume the character peeped */ | ||||||
| 			c = cc; | 			c = cc; | ||||||
|  |  | ||||||
| 			for (i = 1; i < QSE_SIZEOF(qse_char_t) * 2; i++) | 			for (i = 1; i < QSE_SIZEOF(qse_char_t) * 2; i++) | ||||||
| 			{ | 			{ | ||||||
| 				cc = xdigit_to_num(PEEPNXTSC(sed)); | 				PEEPNXTSC (sed, peeped, -1); | ||||||
|  | 				cc = xdigit_to_num (peeped); | ||||||
| 				if (cc <= -1) break; | 				if (cc <= -1) break; | ||||||
| 				NXTSC(sed); | 				NXTSC (sed, peeped, -1); /* consume the character peeped */ | ||||||
| 				c = (c << 4) | cc; | 				c = (c << 4) | cc; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| @ -661,7 +673,8 @@ Omitted for clash with regular expression \b. | |||||||
| #endif | #endif | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return c; | 	*ec = c; | ||||||
|  | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int pickup_rex ( | static int pickup_rex ( | ||||||
| @ -681,7 +694,7 @@ static int pickup_rex ( | |||||||
|  |  | ||||||
| 	while (1) | 	while (1) | ||||||
| 	{ | 	{ | ||||||
| 		c = NXTSC (sed); | 		NXTSC (sed, c, -1); | ||||||
|  |  | ||||||
| 	shortcut: | 	shortcut: | ||||||
| 		if (c == QSE_CHAR_EOF || IS_LINTERM(c)) | 		if (c == QSE_CHAR_EOF || IS_LINTERM(c)) | ||||||
| @ -711,7 +724,7 @@ static int pickup_rex ( | |||||||
| 		{ | 		{ | ||||||
| 			qse_cint_t nc; | 			qse_cint_t nc; | ||||||
|  |  | ||||||
| 			nc = NXTSC (sed); | 			NXTSC (sed, nc, -1); | ||||||
| 			if (nc == QSE_CHAR_EOF /*|| IS_LINTERM(nc)*/) | 			if (nc == QSE_CHAR_EOF /*|| IS_LINTERM(nc)*/) | ||||||
| 			{ | 			{ | ||||||
| 				if (cmd) | 				if (cmd) | ||||||
| @ -755,7 +768,7 @@ static int pickup_rex ( | |||||||
| 				qse_cint_t ec; | 				qse_cint_t ec; | ||||||
| 				int xamp; | 				int xamp; | ||||||
|  |  | ||||||
| 				ec = trans_escaped (sed, nc, &xamp); | 				if (trans_escaped (sed, nc, &ec, &xamp) <= -1) return -1; | ||||||
| 				if (ec == nc || (xamp && replacement)) | 				if (ec == nc || (xamp && replacement)) | ||||||
| 				{ | 				{ | ||||||
| 					/* if the character after a backslash is not special  | 					/* if the character after a backslash is not special  | ||||||
| @ -790,7 +803,9 @@ static int pickup_rex ( | |||||||
| 				} | 				} | ||||||
| 				else if (bracket_state == 1) | 				else if (bracket_state == 1) | ||||||
| 				{ | 				{ | ||||||
| 					qse_cint_t nc = NXTSC (sed); | 					qse_cint_t nc; | ||||||
|  |  | ||||||
|  | 					NXTSC (sed, nc, -1); | ||||||
| 					if (nc == QSE_T(':')) bracket_state = 2; | 					if (nc == QSE_T(':')) bracket_state = 2; | ||||||
|  |  | ||||||
| 					if (qse_str_ccat (buf, c) == (qse_size_t)-1) | 					if (qse_str_ccat (buf, c) == (qse_size_t)-1) | ||||||
| @ -834,6 +849,7 @@ static int pickup_rex ( | |||||||
| static QSE_INLINE void* compile_rex_address (qse_sed_t* sed, qse_char_t rxend) | static QSE_INLINE void* compile_rex_address (qse_sed_t* sed, qse_char_t rxend) | ||||||
| { | { | ||||||
| 	int ignorecase = 0; | 	int ignorecase = 0; | ||||||
|  | 	qse_cint_t peeped; | ||||||
|  |  | ||||||
| 	if (pickup_rex (sed, rxend, 0, QSE_NULL, &sed->tmp.rex) <= -1) | 	if (pickup_rex (sed, rxend, 0, QSE_NULL, &sed->tmp.rex) <= -1) | ||||||
| 		return QSE_NULL; | 		return QSE_NULL; | ||||||
| @ -842,10 +858,11 @@ static QSE_INLINE void* compile_rex_address (qse_sed_t* sed, qse_char_t rxend) | |||||||
|  |  | ||||||
| 	/* handle a modifer after having handled an empty regex. | 	/* handle a modifer after having handled an empty regex. | ||||||
| 	 * so a modifier is naturally disallowed for an empty regex. */ | 	 * so a modifier is naturally disallowed for an empty regex. */ | ||||||
| 	if (PEEPNXTSC(sed) == QSE_T('I'))  | 	PEEPNXTSC (sed, peeped, QSE_NULL); | ||||||
|  | 	if (peeped == QSE_T('I'))  | ||||||
| 	{ | 	{ | ||||||
| 		ignorecase = 1; | 		ignorecase = 1; | ||||||
| 		NXTSC(sed); | 		NXTSC (sed, peeped, QSE_NULL); /* consume the character peeped */ | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return build_rex (sed, QSE_STR_CSTR(&sed->tmp.rex), ignorecase, &sed->src.loc); | 	return build_rex (sed, QSE_STR_CSTR(&sed->tmp.rex), ignorecase, &sed->src.loc); | ||||||
| @ -859,7 +876,7 @@ static qse_sed_adr_t* get_address (qse_sed_t* sed, qse_sed_adr_t* a, int extende | |||||||
| 	if (c == QSE_T('$')) | 	if (c == QSE_T('$')) | ||||||
| 	{ | 	{ | ||||||
| 		a->type = QSE_SED_ADR_DOL; | 		a->type = QSE_SED_ADR_DOL; | ||||||
| 		NXTSC (sed); | 		NXTSC (sed, c, QSE_NULL); | ||||||
| 	} | 	} | ||||||
| 	else if (c >= QSE_T('0') && c <= QSE_T('9')) | 	else if (c >= QSE_T('0') && c <= QSE_T('9')) | ||||||
| 	{ | 	{ | ||||||
| @ -867,9 +884,9 @@ static qse_sed_adr_t* get_address (qse_sed_t* sed, qse_sed_adr_t* a, int extende | |||||||
| 		do | 		do | ||||||
| 		{ | 		{ | ||||||
| 			lno = lno * 10 + c - QSE_T('0'); | 			lno = lno * 10 + c - QSE_T('0'); | ||||||
| 			NXTSC (sed); | 			NXTSC (sed, c, QSE_NULL); | ||||||
| 		} | 		} | ||||||
| 		while ((c = CURSC(sed)) >= QSE_T('0') && c <= QSE_T('9')); | 		while (c >= QSE_T('0') && c <= QSE_T('9')); | ||||||
|  |  | ||||||
| 		a->type = QSE_SED_ADR_LINE; | 		a->type = QSE_SED_ADR_LINE; | ||||||
| 		a->u.lno = lno; | 		a->u.lno = lno; | ||||||
| @ -880,12 +897,12 @@ static qse_sed_adr_t* get_address (qse_sed_t* sed, qse_sed_adr_t* a, int extende | |||||||
| 		a->u.rex = compile_rex_address (sed, c); | 		a->u.rex = compile_rex_address (sed, c); | ||||||
| 		if (a->u.rex == QSE_NULL) return QSE_NULL; | 		if (a->u.rex == QSE_NULL) return QSE_NULL; | ||||||
| 		a->type = QSE_SED_ADR_REX; | 		a->type = QSE_SED_ADR_REX; | ||||||
| 		NXTSC (sed); | 		NXTSC (sed, c, QSE_NULL); | ||||||
| 	} | 	} | ||||||
| 	else if (c == QSE_T('\\')) | 	else if (c == QSE_T('\\')) | ||||||
| 	{ | 	{ | ||||||
| 		/* \cREGEXc */ | 		/* \cREGEXc */ | ||||||
| 		c = NXTSC (sed); | 		NXTSC (sed, c, QSE_NULL); | ||||||
| 		if (c == QSE_CHAR_EOF || IS_LINTERM(c)) | 		if (c == QSE_CHAR_EOF || IS_LINTERM(c)) | ||||||
| 		{ | 		{ | ||||||
| 			SETERR1 (sed, QSE_SED_EREXIC,  | 			SETERR1 (sed, QSE_SED_EREXIC,  | ||||||
| @ -896,7 +913,7 @@ static qse_sed_adr_t* get_address (qse_sed_t* sed, qse_sed_adr_t* a, int extende | |||||||
| 		a->u.rex = compile_rex_address (sed, c); | 		a->u.rex = compile_rex_address (sed, c); | ||||||
| 		if (a->u.rex == QSE_NULL) return QSE_NULL; | 		if (a->u.rex == QSE_NULL) return QSE_NULL; | ||||||
| 		a->type = QSE_SED_ADR_REX; | 		a->type = QSE_SED_ADR_REX; | ||||||
| 		NXTSC (sed); | 		NXTSC (sed, c, QSE_NULL); | ||||||
| 	} | 	} | ||||||
| 	else if (extended && (c == QSE_T('+') || c == QSE_T('~'))) | 	else if (extended && (c == QSE_T('+') || c == QSE_T('~'))) | ||||||
| 	{ | 	{ | ||||||
| @ -904,8 +921,8 @@ static qse_sed_adr_t* get_address (qse_sed_t* sed, qse_sed_adr_t* a, int extende | |||||||
|  |  | ||||||
| 		a->type = (c == QSE_T('+'))? QSE_SED_ADR_RELLINE: QSE_SED_ADR_RELLINEM; | 		a->type = (c == QSE_T('+'))? QSE_SED_ADR_RELLINE: QSE_SED_ADR_RELLINEM; | ||||||
|  |  | ||||||
| 		NXTSC (sed); | 		NXTSC (sed, c, QSE_NULL); | ||||||
| 		if (!((c = CURSC(sed)) >= QSE_T('0') && c <= QSE_T('9'))) | 		if (!(c >= QSE_T('0') && c <= QSE_T('9'))) | ||||||
| 		{ | 		{ | ||||||
| 			SETERR0 (sed, QSE_SED_EA2MOI, &sed->src.loc); | 			SETERR0 (sed, QSE_SED_EA2MOI, &sed->src.loc); | ||||||
| 			return QSE_NULL; | 			return QSE_NULL; | ||||||
| @ -914,9 +931,9 @@ static qse_sed_adr_t* get_address (qse_sed_t* sed, qse_sed_adr_t* a, int extende | |||||||
| 		do | 		do | ||||||
| 		{ | 		{ | ||||||
| 			lno = lno * 10 + c - QSE_T('0'); | 			lno = lno * 10 + c - QSE_T('0'); | ||||||
| 			NXTSC (sed); | 			NXTSC (sed, c, QSE_NULL); | ||||||
| 		} | 		} | ||||||
| 		while ((c = CURSC(sed)) >= QSE_T('0') && c <= QSE_T('9')); | 		while (c >= QSE_T('0') && c <= QSE_T('9')); | ||||||
|  |  | ||||||
| 		a->u.lno = lno; | 		a->u.lno = lno; | ||||||
| 	} | 	} | ||||||
| @ -952,14 +969,14 @@ do { \ | |||||||
| 	t = qse_str_open (sed->mmgr, 0, 128); | 	t = qse_str_open (sed->mmgr, 0, 128); | ||||||
| 	if (t == QSE_NULL) goto oops; | 	if (t == QSE_NULL) goto oops; | ||||||
|  |  | ||||||
| 	do  |  | ||||||
| 	{ |  | ||||||
| 	c = CURSC (sed); | 	c = CURSC (sed); | ||||||
|  |  | ||||||
|  | 	do  | ||||||
|  | 	{ | ||||||
| 		if (sed->option & QSE_SED_STRIPLS) | 		if (sed->option & QSE_SED_STRIPLS) | ||||||
| 		{ | 		{ | ||||||
| 			/* get the first non-space character */ | 			/* get the first non-space character */ | ||||||
| 			while (IS_SPACE(c)) c = NXTSC (sed); | 			while (IS_SPACE(c)) NXTSC_GOTO (sed, c, oops); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		while (c != QSE_CHAR_EOF) | 		while (c != QSE_CHAR_EOF) | ||||||
| @ -968,27 +985,35 @@ do { \ | |||||||
|  |  | ||||||
| 			if (c == QSE_T('\\')) | 			if (c == QSE_T('\\')) | ||||||
| 			{ | 			{ | ||||||
| 				c = NXTSC (sed); | 				NXTSC_GOTO (sed, c, oops); | ||||||
| 				if (c == QSE_CHAR_EOF)  | 				if (c == QSE_CHAR_EOF)  | ||||||
| 				{ | 				{ | ||||||
| 					if (sed->option & QSE_SED_KEEPTBS)  | 					if (sed->option & QSE_SED_KEEPTBS)  | ||||||
| 						ADD (sed, t, QSE_T('\\'), oops); | 						ADD (sed, t, QSE_T('\\'), oops); | ||||||
|  |  | ||||||
| 					break; | 					break; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			else if (c == QSE_T('\n')) nl = 1; | 			else if (c == QSE_T('\n')) nl = 1; /* unescaped newline */ | ||||||
|  |  | ||||||
| 			ADD (sed, t, c, oops); | 			ADD (sed, t, c, oops); | ||||||
|  |  | ||||||
| 			if (c == QSE_T('\n')) | 			if (c == QSE_T('\n')) | ||||||
| 			{ | 			{ | ||||||
| 				NXTSC (sed); | 				if (nl) | ||||||
| 				if (nl) goto done; | 				{ | ||||||
|  | 					/* if newline is not escaped, stop */ | ||||||
|  | 					qse_cint_t dump; | ||||||
|  | 					/* let's not pollute 'c' for ENSURELN check after done: */ | ||||||
|  | 					NXTSC_GOTO (sed, dump, oops); | ||||||
|  | 					goto done; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				/* else carry on reading the next line */ | ||||||
|  | 				NXTSC_GOTO (sed, c, oops); | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			c = NXTSC (sed); | 			NXTSC_GOTO (sed, c, oops); | ||||||
| 		}  | 		}  | ||||||
| 	} | 	} | ||||||
| 	while (c != QSE_CHAR_EOF); | 	while (c != QSE_CHAR_EOF); | ||||||
| @ -1017,7 +1042,7 @@ static int get_label (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
|  |  | ||||||
| 	/* skip white spaces */ | 	/* skip white spaces */ | ||||||
| 	c = CURSC (sed); | 	c = CURSC (sed); | ||||||
| 	while (IS_SPACE(c)) c = NXTSC (sed); | 	while (IS_SPACE(c)) NXTSC (sed, c, -1); | ||||||
|  |  | ||||||
| 	if (!IS_LABCHAR(c)) | 	if (!IS_LABCHAR(c)) | ||||||
| 	{ | 	{ | ||||||
| @ -1041,7 +1066,7 @@ static int get_label (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
| 				SETERR0 (sed, QSE_SED_ENOMEM, QSE_NULL); | 				SETERR0 (sed, QSE_SED_ENOMEM, QSE_NULL); | ||||||
| 				return -1; | 				return -1; | ||||||
| 			}  | 			}  | ||||||
| 			c = NXTSC (sed); | 			NXTSC (sed, c, -1); | ||||||
| 		} | 		} | ||||||
| 		while (IS_LABCHAR(c)); | 		while (IS_LABCHAR(c)); | ||||||
|  |  | ||||||
| @ -1070,13 +1095,13 @@ static int get_label (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
|  |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	while (IS_SPACE(c)) c = NXTSC (sed); | 	while (IS_SPACE(c)) NXTSC (sed, c, -1); | ||||||
|  |  | ||||||
| 	if (IS_CMDTERM(c))  | 	if (IS_CMDTERM(c))  | ||||||
| 	{ | 	{ | ||||||
| 		if (c != QSE_T('}') &&  | 		if (c != QSE_T('}') &&  | ||||||
| 		    c != QSE_T('#') && | 		    c != QSE_T('#') && | ||||||
| 		    c != QSE_CHAR_EOF) NXTSC (sed);	 | 		    c != QSE_CHAR_EOF) NXTSC (sed, c, -1);	 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| @ -1087,7 +1112,7 @@ static int terminate_command (qse_sed_t* sed) | |||||||
| 	qse_cint_t c; | 	qse_cint_t c; | ||||||
|  |  | ||||||
| 	c = CURSC (sed); | 	c = CURSC (sed); | ||||||
| 	while (IS_SPACE(c)) c = NXTSC (sed); | 	while (IS_SPACE(c)) NXTSC (sed, c, -1); | ||||||
| 	if (!IS_CMDTERM(c)) | 	if (!IS_CMDTERM(c)) | ||||||
| 	{ | 	{ | ||||||
| 		SETERR0 (sed, QSE_SED_ESCEXP, &sed->src.loc); | 		SETERR0 (sed, QSE_SED_ESCEXP, &sed->src.loc); | ||||||
| @ -1100,7 +1125,7 @@ static int terminate_command (qse_sed_t* sed) | |||||||
| 	if (c != QSE_T('#') &&  | 	if (c != QSE_T('#') &&  | ||||||
| 	    c != QSE_T('{') && | 	    c != QSE_T('{') && | ||||||
| 	    c != QSE_T('}') &&  | 	    c != QSE_T('}') &&  | ||||||
| 	    c != QSE_CHAR_EOF) NXTSC (sed);	 | 	    c != QSE_CHAR_EOF) NXTSC (sed, c, -1);	 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -1112,7 +1137,7 @@ static int get_branch_target (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
|  |  | ||||||
| 	/* skip white spaces */ | 	/* skip white spaces */ | ||||||
| 	c = CURSC(sed); | 	c = CURSC(sed); | ||||||
| 	while (IS_SPACE(c)) c = NXTSC (sed); | 	while (IS_SPACE(c)) NXTSC (sed, c, -1); | ||||||
|  |  | ||||||
| 	if (IS_CMDTERM(c)) | 	if (IS_CMDTERM(c)) | ||||||
| 	{ | 	{ | ||||||
| @ -1141,7 +1166,7 @@ static int get_branch_target (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
| 			goto oops; | 			goto oops; | ||||||
| 		}  | 		}  | ||||||
|  |  | ||||||
| 		c = NXTSC (sed); | 		NXTSC_GOTO (sed, c, oops); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (terminate_command (sed) <= -1) goto oops; | 	if (terminate_command (sed) <= -1) goto oops; | ||||||
| @ -1176,7 +1201,7 @@ static int get_file (qse_sed_t* sed, qse_xstr_t* xstr) | |||||||
|  |  | ||||||
| 	/* skip white spaces */ | 	/* skip white spaces */ | ||||||
| 	c = CURSC(sed); | 	c = CURSC(sed); | ||||||
| 	while (IS_SPACE(c)) c = NXTSC (sed); | 	while (IS_SPACE(c)) NXTSC (sed, c, -1); | ||||||
|  |  | ||||||
| 	if (IS_CMDTERM(c)) | 	if (IS_CMDTERM(c)) | ||||||
| 	{ | 	{ | ||||||
| @ -1205,7 +1230,7 @@ static int get_file (qse_sed_t* sed, qse_xstr_t* xstr) | |||||||
|  |  | ||||||
| 		if (c == QSE_T('\\')) | 		if (c == QSE_T('\\')) | ||||||
| 		{ | 		{ | ||||||
| 			c = NXTSC (sed); | 			NXTSC_GOTO (sed, c, oops); | ||||||
| 			if (c == QSE_T('\0') || c == QSE_CHAR_EOF || IS_LINTERM(c)) | 			if (c == QSE_T('\0') || c == QSE_CHAR_EOF || IS_LINTERM(c)) | ||||||
| 			{ | 			{ | ||||||
| 				SETERR0 (sed, QSE_SED_EFILIL, &sed->src.loc); | 				SETERR0 (sed, QSE_SED_EFILIL, &sed->src.loc); | ||||||
| @ -1221,7 +1246,7 @@ static int get_file (qse_sed_t* sed, qse_xstr_t* xstr) | |||||||
| 			goto oops; | 			goto oops; | ||||||
| 		}  | 		}  | ||||||
|  |  | ||||||
| 		c = NXTSC (sed); | 		NXTSC_GOTO (sed, c, oops); | ||||||
| 	} | 	} | ||||||
| 	while (!IS_CMDTERM(c)); | 	while (!IS_CMDTERM(c)); | ||||||
|  |  | ||||||
| @ -1291,7 +1316,7 @@ static int get_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
| 	if (pickup_rex (sed, delim, 1, cmd, t[1]) <= -1) goto oops; | 	if (pickup_rex (sed, delim, 1, cmd, t[1]) <= -1) goto oops; | ||||||
|  |  | ||||||
| 	/* skip spaces before options */ | 	/* skip spaces before options */ | ||||||
| 	do { c = NXTSC(sed); } while (IS_SPACE(c)); | 	do { NXTSC_GOTO (sed, c, oops); } while (IS_SPACE(c)); | ||||||
|  |  | ||||||
| 	/* get options */ | 	/* get options */ | ||||||
| 	do | 	do | ||||||
| @ -1299,17 +1324,17 @@ static int get_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
| 		if (c == QSE_T('p'))  | 		if (c == QSE_T('p'))  | ||||||
| 		{ | 		{ | ||||||
| 			cmd->u.subst.p = 1; | 			cmd->u.subst.p = 1; | ||||||
| 			c = NXTSC (sed); | 			NXTSC_GOTO (sed, c, oops); | ||||||
| 		} | 		} | ||||||
| 		else if (c == QSE_T('i') || c == QSE_T('I'))  | 		else if (c == QSE_T('i') || c == QSE_T('I'))  | ||||||
| 		{ | 		{ | ||||||
| 			cmd->u.subst.i = 1; | 			cmd->u.subst.i = 1; | ||||||
| 			c = NXTSC (sed); | 			NXTSC_GOTO (sed, c, oops); | ||||||
| 		} | 		} | ||||||
| 		else if (c == QSE_T('g'))  | 		else if (c == QSE_T('g'))  | ||||||
| 		{ | 		{ | ||||||
| 			cmd->u.subst.g = 1; | 			cmd->u.subst.g = 1; | ||||||
| 			c = NXTSC (sed); | 			NXTSC_GOTO (sed, c, oops); | ||||||
| 		} | 		} | ||||||
| 		else if (c >= QSE_T('0') && c <= QSE_T('9')) | 		else if (c >= QSE_T('0') && c <= QSE_T('9')) | ||||||
| 		{ | 		{ | ||||||
| @ -1331,7 +1356,7 @@ static int get_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
| 					SETERR0 (sed, QSE_SED_EOCSTL, &sed->src.loc); | 					SETERR0 (sed, QSE_SED_EOCSTL, &sed->src.loc); | ||||||
| 					goto oops; | 					goto oops; | ||||||
| 				} | 				} | ||||||
| 				c = NXTSC (sed);  | 				NXTSC_GOTO (sed, c, oops); | ||||||
| 			} | 			} | ||||||
| 			while (c >= QSE_T('0') && c <= QSE_T('9')); | 			while (c >= QSE_T('0') && c <= QSE_T('9')); | ||||||
|  |  | ||||||
| @ -1345,7 +1370,7 @@ static int get_subst (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
| 		} | 		} | ||||||
| 		else if (c == QSE_T('w')) | 		else if (c == QSE_T('w')) | ||||||
| 		{ | 		{ | ||||||
| 			NXTSC (sed); | 			NXTSC_GOTO (sed, c, oops); | ||||||
| 			if (get_file (sed, &cmd->u.subst.file) <= -1) goto oops; | 			if (get_file (sed, &cmd->u.subst.file) <= -1) goto oops; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -1404,7 +1429,7 @@ static int get_transet (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
| 		goto oops; | 		goto oops; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	c = NXTSC (sed); | 	NXTSC_GOTO (sed, c, oops); | ||||||
| 	while (c != delim) | 	while (c != delim) | ||||||
| 	{ | 	{ | ||||||
| 		qse_char_t b[2]; | 		qse_char_t b[2]; | ||||||
| @ -1413,9 +1438,9 @@ static int get_transet (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
|  |  | ||||||
| 		if (c == QSE_T('\\')) | 		if (c == QSE_T('\\')) | ||||||
| 		{ | 		{ | ||||||
| 			c = NXTSC (sed); | 			NXTSC_GOTO (sed, c, oops); | ||||||
| 			CHECK_CMDIC_ESCAPED (sed, cmd, c, goto oops); | 			CHECK_CMDIC_ESCAPED (sed, cmd, c, goto oops); | ||||||
| 			c = trans_escaped (sed, c, QSE_NULL); | 			if (trans_escaped (sed, c, &c, QSE_NULL) <= -1) goto oops; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		b[0] = c; | 		b[0] = c; | ||||||
| @ -1425,19 +1450,19 @@ static int get_transet (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
| 			goto oops; | 			goto oops; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		c = NXTSC (sed); | 		NXTSC_GOTO (sed, c, oops); | ||||||
| 	}	 | 	}	 | ||||||
|  |  | ||||||
| 	c = NXTSC (sed); | 	NXTSC_GOTO (sed, c, oops); | ||||||
| 	for (pos = 1; c != delim; pos += 2) | 	for (pos = 1; c != delim; pos += 2) | ||||||
| 	{ | 	{ | ||||||
| 		CHECK_CMDIC (sed, cmd, c, goto oops); | 		CHECK_CMDIC (sed, cmd, c, goto oops); | ||||||
|  |  | ||||||
| 		if (c == QSE_T('\\')) | 		if (c == QSE_T('\\')) | ||||||
| 		{ | 		{ | ||||||
| 			c = NXTSC (sed); | 			NXTSC_GOTO (sed, c, oops); | ||||||
| 			CHECK_CMDIC_ESCAPED (sed, cmd, c, goto oops); | 			CHECK_CMDIC_ESCAPED (sed, cmd, c, goto oops); | ||||||
| 			c = trans_escaped (sed, c, QSE_NULL); | 			if (trans_escaped (sed, c, &c, QSE_NULL) <= -1) goto oops; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (pos >= QSE_STR_LEN(t)) | 		if (pos >= QSE_STR_LEN(t)) | ||||||
| @ -1448,7 +1473,7 @@ static int get_transet (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		QSE_STR_CHAR(t,pos) = c; | 		QSE_STR_CHAR(t,pos) = c; | ||||||
| 		c = NXTSC (sed); | 		NXTSC_GOTO (sed, c, oops); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (pos < QSE_STR_LEN(t)) | 	if (pos < QSE_STR_LEN(t)) | ||||||
| @ -1458,7 +1483,7 @@ static int get_transet (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
| 		goto oops; | 		goto oops; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	NXTSC (sed); | 	NXTSC_GOTO (sed, c, oops); | ||||||
| 	if (terminate_command (sed) <= -1) goto oops; | 	if (terminate_command (sed) <= -1) goto oops; | ||||||
|  |  | ||||||
| 	qse_str_yield (t, &cmd->u.transet, 0); | 	qse_str_yield (t, &cmd->u.transet, 0); | ||||||
| @ -1504,11 +1529,11 @@ static int get_command (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
|  |  | ||||||
| 			cmd->type = QSE_SED_CMD_NOOP; | 			cmd->type = QSE_SED_CMD_NOOP; | ||||||
|  |  | ||||||
| 			c = NXTSC (sed); | 			NXTSC (sed, c, -1); | ||||||
| 			if (get_label (sed, cmd) <= -1) return -1; | 			if (get_label (sed, cmd) <= -1) return -1; | ||||||
|  |  | ||||||
| 			c = CURSC (sed); | 			c = CURSC (sed); | ||||||
| 			while (IS_SPACE(c)) c = NXTSC(sed); | 			while (IS_SPACE(c)) NXTSC (sed, c, -1); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case QSE_T('{'): | 		case QSE_T('{'): | ||||||
| @ -1527,7 +1552,7 @@ static int get_command (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			sed->tmp.grp.cmd[sed->tmp.grp.level++] = cmd; | 			sed->tmp.grp.cmd[sed->tmp.grp.level++] = cmd; | ||||||
| 			NXTSC (sed); | 			NXTSC (sed, c, -1); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case QSE_T('}'): | 		case QSE_T('}'): | ||||||
| @ -1556,7 +1581,7 @@ static int get_command (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
| 			tc = sed->tmp.grp.cmd[--sed->tmp.grp.level]; | 			tc = sed->tmp.grp.cmd[--sed->tmp.grp.level]; | ||||||
| 			tc->u.branch.target = cmd; | 			tc->u.branch.target = cmd; | ||||||
|  |  | ||||||
| 			NXTSC (sed); | 			NXTSC (sed, c, -1); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @ -1573,7 +1598,7 @@ static int get_command (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
| 				return -1; | 				return -1; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			NXTSC (sed); | 			NXTSC (sed, c, -1); | ||||||
| 			if (terminate_command (sed) <= -1) return -1; | 			if (terminate_command (sed) <= -1) return -1; | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| @ -1593,8 +1618,8 @@ static int get_command (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
| 		{ | 		{ | ||||||
| 			cmd->type = c; | 			cmd->type = c; | ||||||
|  |  | ||||||
| 			c = NXTSC (sed); | 			NXTSC (sed, c, -1); | ||||||
| 			while (IS_SPACE(c)) c = NXTSC (sed); | 			while (IS_SPACE(c)) NXTSC (sed, c, -1); | ||||||
|  |  | ||||||
| 			if (c != QSE_T('\\')) | 			if (c != QSE_T('\\')) | ||||||
| 			{ | 			{ | ||||||
| @ -1610,8 +1635,8 @@ static int get_command (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
| 				return -1; | 				return -1; | ||||||
| 			} | 			} | ||||||
| 		 | 		 | ||||||
| 			c = NXTSC (sed); | 			NXTSC (sed, c, -1); | ||||||
| 			while (IS_SPACE(c)) c = NXTSC (sed); | 			while (IS_SPACE(c)) NXTSC (sed, c, -1); | ||||||
|  |  | ||||||
| 			if (c != QSE_CHAR_EOF && c != QSE_T('\n')) | 			if (c != QSE_CHAR_EOF && c != QSE_T('\n')) | ||||||
| 			{ | 			{ | ||||||
| @ -1626,7 +1651,7 @@ static int get_command (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
| 				return -1; | 				return -1; | ||||||
| 			} | 			} | ||||||
| 			 | 			 | ||||||
| 			NXTSC (sed); /* skip the new line */ | 			NXTSC (sed, c, -1); /* skip the new line */ | ||||||
|  |  | ||||||
| 		sameline_ok: | 		sameline_ok: | ||||||
| 			/* get_text() starts from the next line */ | 			/* get_text() starts from the next line */ | ||||||
| @ -1665,14 +1690,14 @@ static int get_command (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
|  |  | ||||||
| 		case QSE_T('z'): | 		case QSE_T('z'): | ||||||
| 			cmd->type = c; | 			cmd->type = c; | ||||||
| 			NXTSC (sed); | 			NXTSC (sed, c, -1);  | ||||||
| 			if (terminate_command (sed) <= -1) return -1; | 			if (terminate_command (sed) <= -1) return -1; | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case QSE_T('b'): | 		case QSE_T('b'): | ||||||
| 		case QSE_T('t'): | 		case QSE_T('t'): | ||||||
| 			cmd->type = c; | 			cmd->type = c; | ||||||
| 			NXTSC (sed); | 			NXTSC (sed, c, -1);  | ||||||
| 			if (get_branch_target (sed, cmd) <= -1) return -1; | 			if (get_branch_target (sed, cmd) <= -1) return -1; | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| @ -1681,19 +1706,19 @@ static int get_command (qse_sed_t* sed, qse_sed_cmd_t* cmd) | |||||||
| 		case QSE_T('w'): | 		case QSE_T('w'): | ||||||
| 		case QSE_T('W'): | 		case QSE_T('W'): | ||||||
| 			cmd->type = c; | 			cmd->type = c; | ||||||
| 			NXTSC (sed); | 			NXTSC (sed, c, -1);  | ||||||
| 			if (get_file (sed, &cmd->u.file) <= -1) return -1; | 			if (get_file (sed, &cmd->u.file) <= -1) return -1; | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case QSE_T('s'): | 		case QSE_T('s'): | ||||||
| 			cmd->type = c; | 			cmd->type = c; | ||||||
| 			NXTSC (sed); | 			NXTSC (sed, c, -1);  | ||||||
| 			if (get_subst (sed, cmd) <= -1) return -1; | 			if (get_subst (sed, cmd) <= -1) return -1; | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case QSE_T('y'): | 		case QSE_T('y'): | ||||||
| 			cmd->type = c; | 			cmd->type = c; | ||||||
| 			NXTSC (sed); | 			NXTSC (sed, c, -1);  | ||||||
| 			if (get_transet (sed, cmd) <= -1) return -1; | 			if (get_transet (sed, cmd) <= -1) return -1; | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| @ -1722,7 +1747,7 @@ int qse_sed_comp (qse_sed_t* sed, qse_sed_io_fun_t inf) | |||||||
| 	sed->src.loc.colm = 0; | 	sed->src.loc.colm = 0; | ||||||
| 	sed->src.cc = QSE_CHAR_EOF; | 	sed->src.cc = QSE_CHAR_EOF; | ||||||
| 	 | 	 | ||||||
| 	c = NXTSC (sed); | 	NXTSC_GOTO (sed, c, oops); | ||||||
|  |  | ||||||
| 	/* free all the commands previously compiled */ | 	/* free all the commands previously compiled */ | ||||||
| 	free_all_command_blocks (sed); | 	free_all_command_blocks (sed); | ||||||
| @ -1740,7 +1765,7 @@ int qse_sed_comp (qse_sed_t* sed, qse_sed_io_fun_t inf) | |||||||
| 		int n; | 		int n; | ||||||
|  |  | ||||||
| 		/* skip spaces including newlines */ | 		/* skip spaces including newlines */ | ||||||
| 		while (IS_WSPACE(c)) c = NXTSC (sed); | 		while (IS_WSPACE(c)) NXTSC_GOTO (sed, c, oops); | ||||||
|  |  | ||||||
| 		/* check if the end has been reached */ | 		/* check if the end has been reached */ | ||||||
| 		if (c == QSE_CHAR_EOF) break; | 		if (c == QSE_CHAR_EOF) break; | ||||||
| @ -1748,16 +1773,16 @@ int qse_sed_comp (qse_sed_t* sed, qse_sed_io_fun_t inf) | |||||||
| 		/* check if the line is commented out */ | 		/* check if the line is commented out */ | ||||||
| 		if (c == QSE_T('#')) | 		if (c == QSE_T('#')) | ||||||
| 		{ | 		{ | ||||||
| 			do c = NXTSC (sed);  | 			do NXTSC_GOTO (sed, c, oops);  | ||||||
| 			while (!IS_LINTERM(c) && c != QSE_CHAR_EOF) ; | 			while (!IS_LINTERM(c) && c != QSE_CHAR_EOF) ; | ||||||
| 			c = NXTSC (sed); | 			NXTSC_GOTO (sed, c, oops); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (c == QSE_T(';'))  | 		if (c == QSE_T(';'))  | ||||||
| 		{ | 		{ | ||||||
| 			/* semicolon without a address-command pair */ | 			/* semicolon without a address-command pair */ | ||||||
| 			c = NXTSC (sed); | 			NXTSC_GOTO (sed, c, oops); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @ -1777,7 +1802,7 @@ int qse_sed_comp (qse_sed_t* sed, qse_sed_io_fun_t inf) | |||||||
| 		c = CURSC (sed); | 		c = CURSC (sed); | ||||||
| 		if (cmd->a1.type != QSE_SED_ADR_NONE) | 		if (cmd->a1.type != QSE_SED_ADR_NONE) | ||||||
| 		{ | 		{ | ||||||
| 			while (IS_SPACE(c)) c = NXTSC (sed); | 			while (IS_SPACE(c)) NXTSC_GOTO (sed, c, oops); | ||||||
|  |  | ||||||
| 			if (c == QSE_T(',') || | 			if (c == QSE_T(',') || | ||||||
| 			    ((sed->option & QSE_SED_EXTENDEDADR) && c == QSE_T('~'))) | 			    ((sed->option & QSE_SED_EXTENDEDADR) && c == QSE_T('~'))) | ||||||
| @ -1785,7 +1810,7 @@ int qse_sed_comp (qse_sed_t* sed, qse_sed_io_fun_t inf) | |||||||
| 				qse_char_t delim = c; | 				qse_char_t delim = c; | ||||||
|  |  | ||||||
| 				/* maybe an address range */ | 				/* maybe an address range */ | ||||||
| 				do { c = NXTSC (sed); } while (IS_SPACE(c)); | 				do { NXTSC_GOTO (sed, c, oops); } while (IS_SPACE(c)); | ||||||
|  |  | ||||||
| 				if (get_address (sed, &cmd->a2, (sed->option & QSE_SED_EXTENDEDADR)) == QSE_NULL)  | 				if (get_address (sed, &cmd->a2, (sed->option & QSE_SED_EXTENDEDADR)) == QSE_NULL)  | ||||||
| 				{ | 				{ | ||||||
| @ -1863,18 +1888,18 @@ int qse_sed_comp (qse_sed_t* sed, qse_sed_io_fun_t inf) | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		/* skip white spaces */ | 		/* skip white spaces */ | ||||||
| 		while (IS_SPACE(c)) c = NXTSC (sed); | 		while (IS_SPACE(c)) NXTSC_GOTO (sed, c, oops); | ||||||
|  |  | ||||||
| 		if (c == QSE_T('!')) | 		if (c == QSE_T('!')) | ||||||
| 		{ | 		{ | ||||||
| 			/* allow any number of the negation indicators */ | 			/* allow any number of the negation indicators */ | ||||||
| 			do {  | 			do {  | ||||||
| 				cmd->negated = !cmd->negated;  | 				cmd->negated = !cmd->negated;  | ||||||
| 				c = NXTSC(sed); | 				NXTSC_GOTO (sed, c, oops); | ||||||
| 			}  | 			}  | ||||||
| 			while (c == QSE_T('!')); | 			while (c == QSE_T('!')); | ||||||
|  |  | ||||||
| 			while (IS_SPACE(c)) c = NXTSC (sed); | 			while (IS_SPACE(c)) NXTSC_GOTO (sed, c, oops); | ||||||
| 		} | 		} | ||||||
| 	 | 	 | ||||||
| 		n = get_command (sed, cmd); | 		n = get_command (sed, cmd); | ||||||
| @ -3507,7 +3532,7 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf) | |||||||
|  |  | ||||||
| 	while (!sed->e.stopreq) | 	while (!sed->e.stopreq) | ||||||
| 	{ | 	{ | ||||||
| 		if (sed->e.hook) sed->e.hook (sed, QSE_SED_EXEC_READ, QSE_NULL); | 		if (sed->e.tracer) sed->e.tracer (sed, QSE_SED_EXEC_READ, QSE_NULL); | ||||||
|  |  | ||||||
| 		n = read_line (sed, 0); | 		n = read_line (sed, 0); | ||||||
| 		if (n <= -1) { ret = -1; goto done; } | 		if (n <= -1) { ret = -1; goto done; } | ||||||
| @ -3526,7 +3551,7 @@ 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) | 			while (c != &sed->cmd.over) | ||||||
| 			{ | 			{ | ||||||
| 				if (sed->e.hook) sed->e.hook (sed, QSE_SED_EXEC_MATCH, c); | 				if (sed->e.tracer) sed->e.tracer (sed, QSE_SED_EXEC_MATCH, c); | ||||||
|  |  | ||||||
| 				n = match_address (sed, c); | 				n = match_address (sed, c); | ||||||
| 				if (n <= -1) { ret = -1; goto done; } | 				if (n <= -1) { ret = -1; goto done; } | ||||||
| @ -3538,8 +3563,7 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf) | |||||||
| 					continue; | 					continue; | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				if (sed->e.hook) sed->e.hook (sed, QSE_SED_EXEC_EXEC, c); | 				if (sed->e.tracer) sed->e.tracer (sed, QSE_SED_EXEC_EXEC, c); | ||||||
|  |  | ||||||
| 				j = exec_cmd (sed, c); | 				j = exec_cmd (sed, c); | ||||||
| 				if (j == QSE_NULL) { ret = -1; goto done; } | 				if (j == QSE_NULL) { ret = -1; goto done; } | ||||||
| 				if (j == &sed->cmd.quit_quiet) goto done; | 				if (j == &sed->cmd.quit_quiet) goto done; | ||||||
| @ -3556,7 +3580,7 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf) | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (sed->e.hook) sed->e.hook (sed, QSE_SED_EXEC_WRITE, QSE_NULL); | 		if (sed->e.tracer) sed->e.tracer (sed, QSE_SED_EXEC_WRITE, QSE_NULL); | ||||||
| 		if (emit_output (sed, 0) <= -1) { ret = -1; goto done; } | 		if (emit_output (sed, 0) <= -1) { ret = -1; goto done; } | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @ -3601,12 +3625,12 @@ void qse_sed_setlinnum (qse_sed_t* sed, qse_size_t num) | |||||||
| 	sed->e.in.num = num; | 	sed->e.in.num = num; | ||||||
| } | } | ||||||
|  |  | ||||||
| qse_sed_exec_hook_t qse_sed_getexechook (qse_sed_t* sed) | qse_sed_exec_tracer_t qse_sed_getexectracer (qse_sed_t* sed) | ||||||
| { | { | ||||||
| 	return sed->e.hook; | 	return sed->e.tracer; | ||||||
| } | } | ||||||
|  |  | ||||||
| void qse_sed_setexechook (qse_sed_t* sed, qse_sed_exec_hook_t hook) | void qse_sed_setexectracer (qse_sed_t* sed, qse_sed_exec_tracer_t tracer) | ||||||
| { | { | ||||||
| 	sed->e.hook = hook; | 	sed->e.tracer = tracer; | ||||||
| } | } | ||||||
|  | |||||||
| @ -40,32 +40,6 @@ enum qse_sed_depth_t | |||||||
| typedef enum qse_sed_depth_t qse_sed_depth_t; | typedef enum qse_sed_depth_t qse_sed_depth_t; | ||||||
| #endif | #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_blk_t qse_sed_cmd_blk_t; |  | ||||||
|  |  | ||||||
| struct qse_sed_adr_t |  | ||||||
| { |  | ||||||
| 	enum |  | ||||||
| 	{ |  | ||||||
| 		QSE_SED_ADR_NONE,     /* no address */ |  | ||||||
| 		QSE_SED_ADR_DOL,      /* $ - last line */ |  | ||||||
| 		QSE_SED_ADR_LINE,     /* specified line */ |  | ||||||
| 		QSE_SED_ADR_REX,      /* lines matching regular expression */ |  | ||||||
| 		QSE_SED_ADR_STEP,     /* line steps - only in the second address */ |  | ||||||
| 		QSE_SED_ADR_RELLINE,  /* relative line - only in second address */ |  | ||||||
| 		QSE_SED_ADR_RELLINEM  /* relative line in the multiples - only in second address */ |  | ||||||
| 	} type; |  | ||||||
|  |  | ||||||
| 	union  |  | ||||||
| 	{ |  | ||||||
| 		qse_size_t lno; |  | ||||||
| 		void*      rex; |  | ||||||
| 	} u; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| typedef struct qse_sed_app_t qse_sed_app_t; | typedef struct qse_sed_app_t qse_sed_app_t; | ||||||
| struct qse_sed_app_t | struct qse_sed_app_t | ||||||
| { | { | ||||||
| @ -73,89 +47,7 @@ struct qse_sed_app_t | |||||||
| 	qse_sed_app_t* next; | 	qse_sed_app_t* next; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define QSE_SED_CMD_QUIT_QUIET      QSE_T('Q') | typedef struct qse_sed_cmd_blk_t qse_sed_cmd_blk_t; | ||||||
| #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') |  | ||||||
| #define QSE_SED_CMD_CLEAR_PATTERN   QSE_T('z') |  | ||||||
|  |  | ||||||
| struct qse_sed_cmd_t |  | ||||||
| { |  | ||||||
| 	qse_char_t type; |  | ||||||
| 	qse_sed_loc_t loc; |  | ||||||
|  |  | ||||||
| 	int negated; |  | ||||||
|  |  | ||||||
| 	qse_sed_adr_t a1; /* optional start address */ |  | ||||||
| 	qse_sed_adr_t a2; /* optional end address */ |  | ||||||
|  |  | ||||||
| 	union |  | ||||||
| 	{ |  | ||||||
| 		/* text for the a, i, c commands */ |  | ||||||
| 		qse_xstr_t text;   |  | ||||||
|  |  | ||||||
| 		/* file name for r, w, R, W */ |  | ||||||
| 		qse_xstr_t file; |  | ||||||
|  |  | ||||||
| 		/* data for the s command */ |  | ||||||
| 		struct |  | ||||||
| 		{ |  | ||||||
| 			void* rex; /* regular expression */ |  | ||||||
| 			qse_xstr_t rpl;  /* replacement */ |  | ||||||
|  |  | ||||||
| 			/* flags */ |  | ||||||
| 			qse_xstr_t file; /* file name for w */ |  | ||||||
| 			unsigned short occ; |  | ||||||
| 			unsigned short g: 1; /* global */ |  | ||||||
| 			unsigned short p: 1; /* print */ |  | ||||||
| 			unsigned short i: 1; /* case insensitive */ |  | ||||||
| 		} subst; |  | ||||||
|  |  | ||||||
| 		/* translation set for the y command */ |  | ||||||
| 		qse_xstr_t transet; |  | ||||||
|  |  | ||||||
| 		/* branch target for b and t */ |  | ||||||
| 		struct |  | ||||||
| 		{ |  | ||||||
| 			qse_xstr_t label; |  | ||||||
| 			qse_sed_cmd_t* target; |  | ||||||
| 		} branch; |  | ||||||
| 	} u;	 |  | ||||||
|  |  | ||||||
| 	struct |  | ||||||
| 	{ |  | ||||||
| 		int a1_matched; |  | ||||||
| 		qse_size_t a1_match_line; |  | ||||||
|  |  | ||||||
| 		int c_ready; |  | ||||||
|  |  | ||||||
| 		/* points to the next command for fast traversal and  |  | ||||||
| 		 * fast random jumps */ |  | ||||||
| 		qse_sed_cmd_t* next;  |  | ||||||
| 	} state; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct qse_sed_cmd_blk_t | struct qse_sed_cmd_blk_t | ||||||
| { | { | ||||||
| 	qse_size_t         len;	 | 	qse_size_t         len;	 | ||||||
| @ -298,8 +190,8 @@ struct qse_sed_t | |||||||
| 		/** stop requested */ | 		/** stop requested */ | ||||||
| 		int stopreq; | 		int stopreq; | ||||||
|  |  | ||||||
| 		/** hook function */ | 		/** trace function */ | ||||||
| 		qse_sed_exec_hook_t hook; | 		qse_sed_exec_tracer_t tracer; | ||||||
| 	} e; | 	} e; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | |||||||
| @ -175,14 +175,15 @@ static int open_input_stream ( | |||||||
| 			/* don't store anything to arg->handle */ | 			/* don't store anything to arg->handle */ | ||||||
| 			base->mempos = 0; | 			base->mempos = 0; | ||||||
| 			break; | 			break; | ||||||
| 	} |  | ||||||
|  |  | ||||||
| #if 0 | 		default: | ||||||
| 	if (base == &xtn->s.in) | 			QSE_ASSERTX ( | ||||||
| 	{ | 				!"should never happen", | ||||||
| 		qse_sed_setscriptname (sed, ....); | 				"io-type must be one of SIO,FILE,MEM" | ||||||
|  | 			); | ||||||
|  | 			qse_sed_seterrnum (sed, QSE_SED_EINTERN, QSE_NULL); | ||||||
|  | 			return -1; | ||||||
| 	} | 	} | ||||||
| #endif |  | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| @ -235,6 +236,14 @@ static int open_output_stream (qse_sed_t* sed, qse_sed_io_arg_t* arg, qse_sed_io | |||||||
| 				return -1; | 				return -1; | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
|  | 		default: | ||||||
|  | 			QSE_ASSERTX ( | ||||||
|  | 				!"should never happen", | ||||||
|  | 				"io-type must be one of SIO,FILE,MEM" | ||||||
|  | 			); | ||||||
|  | 			qse_sed_seterrnum (sed, QSE_SED_EINTERN, QSE_NULL); | ||||||
|  | 			return -1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| @ -615,9 +624,10 @@ static qse_ssize_t x_out ( | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| int qse_sed_compstd (qse_sed_t* sed, qse_sed_iostd_t in[]) | int qse_sed_compstd (qse_sed_t* sed, qse_sed_iostd_t in[], qse_size_t* count) | ||||||
| { | { | ||||||
| 	xtn_t* xtn = (xtn_t*) QSE_XTN (sed); | 	xtn_t* xtn = (xtn_t*) QSE_XTN (sed); | ||||||
|  | 	int ret; | ||||||
|  |  | ||||||
| 	if (in == QSE_NULL) | 	if (in == QSE_NULL) | ||||||
| 	{ | 	{ | ||||||
| @ -631,7 +641,11 @@ int qse_sed_compstd (qse_sed_t* sed, qse_sed_iostd_t in[]) | |||||||
| 	xtn->s.in.ptr = in; | 	xtn->s.in.ptr = in; | ||||||
| 	xtn->s.in.cur = in; | 	xtn->s.in.cur = in; | ||||||
|  |  | ||||||
| 	return qse_sed_comp (sed, s_in); | 	ret = qse_sed_comp (sed, s_in); | ||||||
|  |  | ||||||
|  | 	if (count) *count = xtn->s.in.cur - xtn->s.in.ptr; | ||||||
|  |  | ||||||
|  | 	return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| int qse_sed_execstd ( | int qse_sed_execstd ( | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user