added qse_sed_setcompid() and related code
fixed the way how it squeezes in a new line into a script stream not ending with a newline
This commit is contained in:
		| @ -463,11 +463,17 @@ static void trace_exec (qse_sed_t* sed, qse_sed_exec_op_t op, const qse_sed_cmd_ | ||||
| 			break; | ||||
| #endif | ||||
| 		case QSE_SED_EXEC_MATCH: | ||||
| 			qse_printf (QSE_T("matching address for [%c] at line %lu\n"), cmd->type, (unsigned long)cmd->loc.line); | ||||
| 			qse_printf (QSE_T("matching address for [%c] in %s at line %lu\n"),  | ||||
| 				cmd->type,  | ||||
| 				(cmd->lid? cmd->lid: QSE_T("<<UNKNOWN>>")),  | ||||
| 				(unsigned long)cmd->loc.line); | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_SED_EXEC_EXEC: | ||||
| 			qse_printf (QSE_T("executing [%c] at line %lu\n"), cmd->type, (unsigned long)cmd->loc.line); | ||||
| 			qse_printf (QSE_T("executing [%c] in %s at line %lu\n"),  | ||||
| 				cmd->type,  | ||||
| 				(cmd->lid? cmd->lid: QSE_T("<<UNKNOWN>>")),  | ||||
| 				(unsigned long)cmd->loc.line); | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -267,6 +267,12 @@ public: | ||||
| 		const loc_t*  loc = QSE_NULL   ///< error location | ||||
| 	); | ||||
|  | ||||
| 	const char_t* getCompileId () const; | ||||
|  | ||||
| 	const char_t* setCompileId ( | ||||
| 		const char_t* id | ||||
| 	); | ||||
|  | ||||
| 	/// | ||||
| 	/// The getConsoleLine() function returns the current line | ||||
| 	/// number from an input console.  | ||||
|  | ||||
| @ -130,7 +130,9 @@ struct qse_sed_adr_t | ||||
| struct qse_sed_cmd_t | ||||
| { | ||||
| 	qse_char_t type; | ||||
| 	qse_sed_loc_t loc; | ||||
|  | ||||
| 	const qse_char_t* lid; | ||||
| 	qse_sed_loc_t     loc; | ||||
|  | ||||
| 	int negated; | ||||
|  | ||||
| @ -521,18 +523,40 @@ void qse_sed_setlformatter ( | ||||
| 	qse_sed_lformatter_t lformatter /**< text formatter */ | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_sed_getcompid() function returns the latest | ||||
|  * identifier successfully set with qse_sed_setcompid().  | ||||
|  */ | ||||
| const qse_char_t* qse_sed_getcompid ( | ||||
| 	qse_sed_t* sed | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_sed_setcompid() functions duplicates a string | ||||
|  * pointed to by @a id and stores it internally to identify | ||||
|  * the script currently being compiled. The lid field of the  | ||||
|  * current command being compiled in the script is set to the  | ||||
|  * lastest identifer successfully set with this function. | ||||
|  * If this function fails, the location set in the command | ||||
|  * may be wrong. | ||||
|  */ | ||||
| const qse_char_t* qse_sed_setcompid ( | ||||
| 	qse_sed_t*        sed, | ||||
| 	const qse_char_t* id | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_sed_getlinnum() function gets the current input line number. | ||||
|  * @return current input line number | ||||
|  */ | ||||
| qse_size_t qse_sed_getlinnum ( | ||||
| qse_size_t qse_sed_getlinenum ( | ||||
| 	qse_sed_t* sed /**< stream editor */ | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_sed_setlinnum() function changes the current input line number. | ||||
|  * The qse_sed_setlinenum() function changes the current input line number. | ||||
|  */ | ||||
| void qse_sed_setlinnum ( | ||||
| void qse_sed_setlinenum ( | ||||
| 	qse_sed_t* sed,   /**< stream editor */ | ||||
| 	qse_size_t num    /**< a line number */ | ||||
| ); | ||||
|  | ||||
| @ -112,7 +112,8 @@ Sed::loc_t Sed::getErrorLocation () const | ||||
| 	if (sed == QSE_NULL)  | ||||
| 	{ | ||||
| 		loc_t loc; | ||||
| 		loc.line = 0; loc.colm = 0; | ||||
| 		loc.line = 0;  | ||||
| 		loc.colm = 0; | ||||
| 		return loc; | ||||
| 	} | ||||
| 	return *qse_sed_geterrloc (sed); | ||||
| @ -129,16 +130,26 @@ void Sed::setError (errnum_t err, const cstr_t* args, const loc_t* loc) | ||||
| 	qse_sed_seterror (sed, err, args, loc); | ||||
| } | ||||
|  | ||||
| const Sed::char_t* Sed::getCompileId () const | ||||
| { | ||||
| 	return qse_sed_getcompid (this->sed); | ||||
| } | ||||
|  | ||||
| const Sed::char_t* Sed::setCompileId (const char_t* id) | ||||
| { | ||||
| 	return qse_sed_setcompid (this->sed, id); | ||||
| } | ||||
|  | ||||
| Sed::size_t Sed::getConsoleLine () | ||||
| { | ||||
| 	QSE_ASSERT (sed != QSE_NULL); | ||||
| 	return qse_sed_getlinnum (sed); | ||||
| 	return qse_sed_getlinenum (this->sed); | ||||
| } | ||||
|  | ||||
| void Sed::setConsoleLine (size_t num) | ||||
| { | ||||
| 	QSE_ASSERT (sed != QSE_NULL); | ||||
| 	qse_sed_setlinnum (sed, num); | ||||
| 	qse_sed_setlinenum (this->sed, num); | ||||
| } | ||||
|  | ||||
| Sed::ssize_t Sed::sin ( | ||||
|  | ||||
| @ -38,6 +38,7 @@ 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 void free_all_cids (qse_sed_t* sed); | ||||
| static void free_appends (qse_sed_t* sed); | ||||
| static int emit_output (qse_sed_t* sed, int skipline); | ||||
|  | ||||
| @ -130,6 +131,7 @@ oops_1: | ||||
| void qse_sed_fini (qse_sed_t* sed) | ||||
| { | ||||
| 	free_all_command_blocks (sed); | ||||
| 	free_all_cids (sed); | ||||
|  | ||||
| 	qse_str_fini (&sed->e.txt.subst); | ||||
| 	qse_str_fini (&sed->e.txt.hold); | ||||
| @ -582,6 +584,15 @@ static void free_command (qse_sed_t* sed, qse_sed_cmd_t* cmd) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void free_all_cids (qse_sed_t* sed) | ||||
| { | ||||
| 	while (sed->src.cid) | ||||
| 	{ | ||||
| 		qse_sed_cid_t* next = sed->src.cid->next; | ||||
| 		QSE_MMGR_FREE (sed->mmgr, sed->src.cid); | ||||
| 		sed->src.cid = next; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static QSE_INLINE int xdigit_to_num (qse_cint_t c) | ||||
| { | ||||
| @ -1501,6 +1512,7 @@ static int get_command (qse_sed_t* sed, qse_sed_cmd_t* cmd) | ||||
| 	qse_cint_t c; | ||||
|  | ||||
| 	c = CURSC (sed); | ||||
| 	cmd->lid = sed->src.cid? ((const qse_char_t*)(sed->src.cid + 1)): QSE_NULL; | ||||
| 	cmd->loc = sed->src.loc; | ||||
| 	switch (c) | ||||
| 	{ | ||||
| @ -1739,20 +1751,13 @@ int qse_sed_comp (qse_sed_t* sed, qse_sed_io_fun_t inf) | ||||
| 		return -1;	 | ||||
| 	} | ||||
|  | ||||
| 	/* store the source code pointers */ | ||||
| 	sed->src.fun = inf; | ||||
| 	if (open_script_stream (sed) <= -1) return -1; | ||||
|  | ||||
| 	sed->src.loc.line = 1; | ||||
| 	sed->src.loc.colm = 0; | ||||
| 	sed->src.cc = QSE_CHAR_EOF; | ||||
| 	 | ||||
| 	NXTSC_GOTO (sed, c, oops); | ||||
|  | ||||
| 	/* free all the commands previously compiled */ | ||||
| 	free_all_command_blocks (sed); | ||||
| 	QSE_ASSERT (sed->cmd.lb == &sed->cmd.fb && sed->cmd.lb->len == 0); | ||||
|  | ||||
| 	/* free all the compilation identifiers */ | ||||
| 	free_all_cids (sed); | ||||
|  | ||||
| 	/* clear the label table */ | ||||
| 	qse_map_clear (&sed->tmp.labs); | ||||
|  | ||||
| @ -1760,6 +1765,11 @@ int qse_sed_comp (qse_sed_t* sed, qse_sed_io_fun_t inf) | ||||
| 	sed->tmp.grp.level = 0; | ||||
| 	qse_str_clear (&sed->tmp.rex); | ||||
|  | ||||
| 	/* open script */ | ||||
| 	sed->src.fun = inf; | ||||
| 	if (open_script_stream (sed) <= -1) return -1; | ||||
| 	NXTSC_GOTO (sed, c, oops); | ||||
|  | ||||
| 	while (1) | ||||
| 	{ | ||||
| 		int n; | ||||
| @ -3615,12 +3625,33 @@ void qse_sed_setlformatter (qse_sed_t* sed, qse_sed_lformatter_t lf) | ||||
| 	sed->lformatter = lf; | ||||
| } | ||||
|  | ||||
| qse_size_t qse_sed_getlinnum (qse_sed_t* sed) | ||||
| const qse_char_t* qse_sed_getcompid (qse_sed_t* sed) | ||||
| { | ||||
| 	return sed->src.cid? ((const qse_char_t*)(sed->src.cid + 1)): QSE_NULL; | ||||
| } | ||||
|  | ||||
| const qse_char_t* qse_sed_setcompid (qse_sed_t* sed, const qse_char_t* id) | ||||
| { | ||||
| 	qse_sed_cid_t* cid; | ||||
| 	qse_size_t len; | ||||
| 	 | ||||
| 	len = qse_strlen (id); | ||||
| 	cid = QSE_MMGR_ALLOC (sed->mmgr, QSE_SIZEOF(*cid) + ((len + 1) * QSE_SIZEOF(*id))); | ||||
| 	if (cid == QSE_NULL) return QSE_NULL; | ||||
| 	 | ||||
| 	cid->next = sed->src.cid; | ||||
| 	sed->src.cid = cid; | ||||
| 	qse_strcpy ((qse_char_t*)(cid + 1), id); | ||||
|  | ||||
| 	return (const qse_char_t*)(cid + 1); | ||||
| } | ||||
|  | ||||
| qse_size_t qse_sed_getlinenum (qse_sed_t* sed) | ||||
| { | ||||
| 	return sed->e.in.num; | ||||
| } | ||||
|  | ||||
| void qse_sed_setlinnum (qse_sed_t* sed, qse_size_t num) | ||||
| void qse_sed_setlinenum (qse_sed_t* sed, qse_size_t num) | ||||
| { | ||||
| 	sed->e.in.num = num; | ||||
| } | ||||
| @ -3634,3 +3665,4 @@ void qse_sed_setexectracer (qse_sed_t* sed, qse_sed_exec_tracer_t tracer) | ||||
| { | ||||
| 	sed->e.tracer = tracer; | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -55,6 +55,12 @@ struct qse_sed_cmd_blk_t | ||||
| 	qse_sed_cmd_blk_t* next; | ||||
| }; | ||||
|  | ||||
| typedef struct qse_sed_cid_t qse_sed_cid_t; | ||||
| struct qse_sed_cid_t | ||||
| { | ||||
| 	qse_sed_cid_t* next;		 | ||||
| }; | ||||
|  | ||||
| /**  | ||||
|  * The qse_sed_t type defines a stream editor  | ||||
|  */ | ||||
| @ -88,6 +94,7 @@ struct qse_sed_t | ||||
| 		qse_char_t        buf[1024]; | ||||
| 		int               eof; | ||||
|  | ||||
| 		qse_sed_cid_t*    cid; | ||||
| 		qse_sed_loc_t     loc; /**< location */ | ||||
| 		qse_cint_t        cc;  /**< last character read */ | ||||
| 		const qse_char_t* ptr; /**< beginning of the source text */ | ||||
|  | ||||
| @ -45,6 +45,8 @@ struct xtn_t | ||||
| 	struct | ||||
| 	{ | ||||
| 		xtn_in_t in; | ||||
| 		qse_char_t last; | ||||
| 		int newline_squeezed; | ||||
| 	} s; | ||||
| 	struct | ||||
| 	{ | ||||
| @ -54,6 +56,44 @@ struct xtn_t | ||||
| }; | ||||
|  | ||||
|  | ||||
| static int int_to_str (qse_size_t val, qse_char_t* buf, qse_size_t buflen) | ||||
| { | ||||
| 	qse_size_t t; | ||||
| 	qse_size_t rlen = 0; | ||||
|  | ||||
| 	t = val; | ||||
| 	if (t == 0) rlen++; | ||||
| 	else | ||||
| 	{ | ||||
| 		/* non-zero values */ | ||||
| 		if (t < 0) { t = -t; rlen++; } | ||||
| 		while (t > 0) { rlen++; t /= 10; } | ||||
| 	} | ||||
|  | ||||
| 	if (rlen >= buflen) return -1; /* buffer too small */ | ||||
|  | ||||
| 	buf[rlen] = QSE_T('\0'); | ||||
|  | ||||
| 	t = val; | ||||
| 	if (t == 0) buf[0] = QSE_T('0');  | ||||
| 	else | ||||
| 	{ | ||||
| 		if (t < 0) t = -t; | ||||
|  | ||||
| 		/* fill in the buffer with digits */ | ||||
| 		while (t > 0)  | ||||
| 		{ | ||||
| 			buf[--rlen] = (qse_char_t)(t % 10) + QSE_T('0'); | ||||
| 			t /= 10; | ||||
| 		} | ||||
|  | ||||
| 		/* insert the negative sign if necessary */ | ||||
| 		if (val < 0) buf[--rlen] = QSE_T('-'); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| qse_sed_t* qse_sed_openstd (qse_size_t xtnsize) | ||||
| { | ||||
| 	return qse_sed_openstdwithmmgr (QSE_MMGR_GETDFL(), xtnsize); | ||||
| @ -151,7 +191,7 @@ static void close_main_stream ( | ||||
| static int open_input_stream ( | ||||
| 	qse_sed_t* sed, qse_sed_io_arg_t* arg, qse_sed_iostd_t* io, xtn_in_t* base) | ||||
| { | ||||
| 	/*xtn_t* xtn = (xtn_t*) QSE_XTN (sed);*/ | ||||
| 	xtn_t* xtn = (xtn_t*) QSE_XTN (sed); | ||||
|  | ||||
| 	QSE_ASSERT (io != QSE_NULL); | ||||
| 	switch (io->type) | ||||
| @ -185,6 +225,25 @@ static int open_input_stream ( | ||||
| 			return -1; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	if (base == &xtn->s.in) | ||||
| 	{ | ||||
| 		/* reset script location */ | ||||
| 		if (io->type == QSE_SED_IOSTD_FILE)  | ||||
| 		{ | ||||
| 			qse_sed_setcompid (sed, io->u.file); | ||||
| 		} | ||||
| 		else  | ||||
| 		{ | ||||
| 			qse_char_t buf[64]; | ||||
| 			buf[0] = (io->type == QSE_SED_IOSTD_MEM)? QSE_T('M'): QSE_T('S'); | ||||
| 			buf[1] = QSE_T('#'); | ||||
| 			if (int_to_str (io - xtn->s.in.ptr, &buf[2], QSE_COUNTOF(buf) - 2) >= 0) | ||||
| 				qse_sed_setcompid (sed, buf); | ||||
| 		} | ||||
| 		sed->src.loc.line = 1;  | ||||
| 		sed->src.loc.colm = 1; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -257,7 +316,6 @@ static qse_ssize_t read_input_stream ( | ||||
| 	qse_sed_iostd_t* io, * next; | ||||
| 	void* old, * new; | ||||
| 	qse_ssize_t n = 0; | ||||
| 	int newline_forced = 0; | ||||
|  | ||||
| 	if (len > QSE_TYPE_MAX(qse_ssize_t)) len = QSE_TYPE_MAX(qse_ssize_t); | ||||
|  | ||||
| @ -265,7 +323,14 @@ static qse_ssize_t read_input_stream ( | ||||
| 	{ | ||||
| 		io = base->cur; | ||||
|  | ||||
| 		if (base == &xtn->s.in && xtn->s.newline_squeezed)  | ||||
| 		{ | ||||
| 			xtn->s.newline_squeezed = 0; | ||||
| 			goto open_next; | ||||
| 		} | ||||
|  | ||||
| 		QSE_ASSERT (io != QSE_NULL); | ||||
|  | ||||
| 		if (io->type == QSE_SED_IOSTD_MEM) | ||||
| 		{ | ||||
| 			n = 0; | ||||
| @ -285,15 +350,9 @@ static qse_ssize_t read_input_stream ( | ||||
| 					qse_sed_seterrnum (sed, QSE_SED_EIOFIL, &ea); | ||||
| 				} | ||||
| 			} | ||||
| 			else if (newline_forced) | ||||
| 			else if (base == &xtn->s.in) | ||||
| 			{ | ||||
| 				/* set the line number to 0 for the newline | ||||
| 				 * squeezed in. see the getnextsc() in sed.c  | ||||
| 				 * to know how line and column numbers are | ||||
| 				 * incremented */ | ||||
| 				sed->src.loc.line = 0;  | ||||
| 				sed->src.loc.colm = 0; | ||||
| 				n += newline_forced;  | ||||
| 				xtn->s.last = buf[n-1]; | ||||
| 			} | ||||
|  | ||||
| 			break; | ||||
| @ -303,6 +362,16 @@ static qse_ssize_t read_input_stream ( | ||||
| 		/* == end of file on the current input stream == */ | ||||
| 		/* ============================================= */ | ||||
|  | ||||
| 		if (base == &xtn->s.in && xtn->s.last != QSE_T('\n')) | ||||
| 		{ | ||||
| 			/* TODO: different line termination convension */ | ||||
| 			buf[0] = QSE_T('\n');  | ||||
| 			n = 1; | ||||
| 			xtn->s.newline_squeezed = 1; | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 	open_next: | ||||
| 		next = base->cur + 1; | ||||
| 		if (next->type == QSE_SED_IOSTD_NULL)  | ||||
| 		{ | ||||
| @ -327,25 +396,18 @@ static qse_ssize_t read_input_stream ( | ||||
| 			n = -1; | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		/* successfuly opened the next input stream */ | ||||
| 		new = arg->handle; | ||||
|  | ||||
| 		arg->handle = old; | ||||
|  | ||||
| 		/* close the previous stream */ | ||||
| 		close_main_stream (sed, arg, io); | ||||
|  | ||||
| 		arg->handle = new; | ||||
|  | ||||
| 		base->cur++; | ||||
|  | ||||
| 		if (base == &xtn->s.in && !newline_forced) | ||||
| 		{ | ||||
| 			/* == ONLY FOR A SCRIPT STREAM == | ||||
| 			 * squeeze in a new line in case the previous script  | ||||
| 			 * stream doesn't end with a line terminator.*/   | ||||
|  | ||||
| 			/* TODO: support different line terminator */  | ||||
| 			buf[0] = QSE_T('\n');  | ||||
| 			buf++; len--;	 | ||||
| 			newline_forced = 1; | ||||
| 		} | ||||
| 	} | ||||
| 	while (1); | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user