added QSE_SIO_KEEPPATH and qse_sio_getpath().
fixed a file inclusion bug in awk and xli
This commit is contained in:
		| @ -1500,7 +1500,7 @@ int StdAwk::SourceFile::open (Data& io) | ||||
| { | ||||
| 	qse_sio_t* sio; | ||||
|  | ||||
| 	if (!(io.getFlags() & QSE_AWK_SIO_INCLUDED)) | ||||
| 	if (io.getName() == QSE_NULL) | ||||
| 	{ | ||||
| 		// open the main source file. | ||||
|  | ||||
| @ -1519,32 +1519,23 @@ int StdAwk::SourceFile::open (Data& io) | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			const qse_char_t* base; | ||||
|  | ||||
| 			sio = open_sio ( | ||||
| 				io, QSE_NULL, this->name, | ||||
| 				(io.getMode() == READ?  | ||||
| 					(QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR):  | ||||
| 					(QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR | QSE_SIO_KEEPPATH):  | ||||
| 					(QSE_SIO_WRITE | QSE_SIO_CREATE |  | ||||
| 					 QSE_SIO_TRUNCATE | QSE_SIO_IGNOREMBWCERR)) | ||||
| 			); | ||||
| 			if (sio == QSE_NULL) return -1; | ||||
|  | ||||
| 			if (this->cmgr) qse_sio_setcmgr (sio, this->cmgr); | ||||
| 			base = qse_basename (this->name); | ||||
| 			if (base != this->name) | ||||
| 			{ | ||||
| 				dir.ptr = this->name; | ||||
| 				dir.len = base - this->name; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		io.setName (this->name); | ||||
| 		if (this->cmgr) qse_sio_setcmgr (sio, this->cmgr); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		// open an included file | ||||
| 		const char_t* ioname, * file; | ||||
| 		const char_t* ioname, * file, * outer; | ||||
| 		char_t fbuf[64]; | ||||
| 		char_t* dbuf = QSE_NULL; | ||||
| 	 | ||||
| @ -1552,35 +1543,43 @@ int StdAwk::SourceFile::open (Data& io) | ||||
| 		QSE_ASSERT (ioname != QSE_NULL); | ||||
|  | ||||
| 		file = ioname; | ||||
| 		if (dir.len > 0 && ioname[0] != QSE_T('/')) | ||||
| 		outer = qse_sio_getpath ((qse_sio_t*)io.getPrevHandle()); | ||||
| 		if (outer) | ||||
| 		{ | ||||
| 			size_t tmplen, totlen; | ||||
| 			 | ||||
| 			totlen = qse_strlen(ioname) + dir.len; | ||||
| 			if (totlen >= QSE_COUNTOF(fbuf)) | ||||
| 			const qse_char_t* base; | ||||
|  | ||||
| 			base = qse_basename (outer); | ||||
| 			if (base != outer && ioname[0] != QSE_T('/')) | ||||
| 			{ | ||||
| 				dbuf = (qse_char_t*) QSE_MMGR_ALLOC ( | ||||
| 					((Awk*)io)->getMmgr(), | ||||
| 					QSE_SIZEOF(qse_char_t) * (totlen + 1) | ||||
| 				); | ||||
| 				if (dbuf == QSE_NULL) | ||||
| 				size_t tmplen, totlen, dirlen; | ||||
| 			 | ||||
| 				dirlen = base - outer; | ||||
| 				totlen = qse_strlen(ioname) + dirlen; | ||||
| 				if (totlen >= QSE_COUNTOF(fbuf)) | ||||
| 				{ | ||||
| 					((Awk*)io)->setError (QSE_AWK_ENOMEM); | ||||
| 					return -1; | ||||
| 					dbuf = (qse_char_t*) QSE_MMGR_ALLOC ( | ||||
| 						((Awk*)io)->getMmgr(), | ||||
| 						QSE_SIZEOF(qse_char_t) * (totlen + 1) | ||||
| 					); | ||||
| 					if (dbuf == QSE_NULL) | ||||
| 					{ | ||||
| 						((Awk*)io)->setError (QSE_AWK_ENOMEM); | ||||
| 						return -1; | ||||
| 					} | ||||
|  | ||||
| 					file = dbuf; | ||||
| 				} | ||||
| 				else file = fbuf; | ||||
|  | ||||
| 				file = dbuf; | ||||
| 				tmplen = qse_strncpy ((char_t*)file, outer, dirlen); | ||||
| 				qse_strcpy ((char_t*)file + tmplen, ioname); | ||||
| 			} | ||||
| 			else file = fbuf; | ||||
|  | ||||
| 			tmplen = qse_strncpy ((char_t*)file, dir.ptr, dir.len); | ||||
| 			qse_strcpy ((char_t*)file + tmplen, ioname); | ||||
| 		} | ||||
|  | ||||
| 		sio = open_sio ( | ||||
| 			io, QSE_NULL, file, | ||||
| 			(io.getMode() == READ?  | ||||
| 				(QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR):  | ||||
| 				(QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR | QSE_SIO_KEEPPATH):  | ||||
| 				(QSE_SIO_WRITE | QSE_SIO_CREATE |  | ||||
| 				 QSE_SIO_TRUNCATE | QSE_SIO_IGNOREMBWCERR)) | ||||
| 		); | ||||
| @ -1615,7 +1614,7 @@ int StdAwk::SourceString::open (Data& io) | ||||
| { | ||||
| 	qse_sio_t* sio; | ||||
|  | ||||
| 	if (!(io.getFlags() & QSE_AWK_SIO_INCLUDED)) | ||||
| 	if (io.getName() == QSE_NULL) | ||||
| 	{ | ||||
| 		// open the main source file. | ||||
| 		// SourceString does not support writing. | ||||
|  | ||||
| @ -151,15 +151,6 @@ qse_awk_t* qse_awk_open (qse_mmgr_t* mmgr, qse_size_t xtnsize, qse_awk_prm_t* pr | ||||
| 	if (init_token (mmgr, &awk->tok) == -1) goto oops; | ||||
| 	if (init_token (mmgr, &awk->ntok) == -1) goto oops; | ||||
|  | ||||
| 	awk->sio_names = qse_htb_open ( | ||||
| 		mmgr, QSE_SIZEOF(awk), 128, 70, QSE_SIZEOF(qse_char_t), 1 | ||||
| 	); | ||||
| 	if (awk->sio_names == QSE_NULL) goto oops; | ||||
| 	*(qse_awk_t**)QSE_XTN(awk->sio_names) = awk; | ||||
| 	qse_htb_setstyle (awk->sio_names,  | ||||
| 		qse_gethtbstyle(QSE_HTB_STYLE_INLINE_KEY_COPIER) | ||||
| 	); | ||||
|  | ||||
| 	/* TODO: initial map size?? */ | ||||
| 	awk->tree.funs = qse_htb_open ( | ||||
| 		mmgr, QSE_SIZEOF(awk), 512, 70, QSE_SIZEOF(qse_char_t), 1 | ||||
| @ -256,7 +247,6 @@ oops: | ||||
| 	if (awk->parse.named) qse_htb_close (awk->parse.named); | ||||
| 	if (awk->parse.funs) qse_htb_close (awk->parse.funs); | ||||
| 	if (awk->tree.funs) qse_htb_close (awk->tree.funs); | ||||
| 	if (awk->sio_names) qse_htb_close (awk->sio_names); | ||||
| 	fini_token (&awk->ntok); | ||||
| 	fini_token (&awk->tok); | ||||
| 	fini_token (&awk->ptok); | ||||
| @ -286,12 +276,13 @@ int qse_awk_close (qse_awk_t* awk) | ||||
| 	qse_htb_close (awk->parse.funs); | ||||
|  | ||||
| 	qse_htb_close (awk->tree.funs); | ||||
| 	qse_htb_close (awk->sio_names); | ||||
|  | ||||
| 	fini_token (&awk->ntok); | ||||
| 	fini_token (&awk->tok); | ||||
| 	fini_token (&awk->ptok); | ||||
|  | ||||
| 	qse_awk_clearsionames (awk); | ||||
|  | ||||
| 	/* destroy dynamically allocated options */ | ||||
| 	for (i = 0; i < QSE_COUNTOF(awk->opt.mod); i++) | ||||
| 	{ | ||||
| @ -391,9 +382,9 @@ int qse_awk_clear (qse_awk_t* awk) | ||||
| 	awk->tree.chain_size = 0; | ||||
|  | ||||
| 	/* this table must not be cleared here as there can be a reference | ||||
| 	 * to an entry of this table from errinf.fil when qse_awk_parse()  | ||||
| 	 * to an entry of this table from errinf.loc.file when qse_awk_parse()  | ||||
| 	 * failed. this table is cleared in qse_awk_parse(). | ||||
| 	 * qse_htb_clear (awk->sio_names); | ||||
| 	 * qse_awk_claersionames (awk); | ||||
| 	 */ | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -203,7 +203,7 @@ struct qse_awk_t | ||||
| 		qse_awk_sio_arg_t arg; /* for the top level source */ | ||||
| 		qse_awk_sio_arg_t* inp; /* current input argument. */ | ||||
| 	} sio; | ||||
| 	qse_htb_t* sio_names;  | ||||
| 	qse_link_t* sio_names; | ||||
|  | ||||
| 	/* previous token */ | ||||
| 	qse_awk_tok_t ptok; | ||||
|  | ||||
| @ -605,19 +605,19 @@ oops: | ||||
| 		 * closed. close them */ | ||||
| 		while (awk->sio.inp != &awk->sio.arg) | ||||
| 		{ | ||||
| 			qse_awk_sio_arg_t* next; | ||||
| 			qse_awk_sio_arg_t* prev; | ||||
|  | ||||
| 			/* nothing much to do about a close error */ | ||||
| 			awk->sio.inf ( | ||||
| 				awk, QSE_AWK_SIO_CLOSE,  | ||||
| 				awk->sio.inp, QSE_NULL, 0); | ||||
|  | ||||
| 			next = awk->sio.inp->next; | ||||
| 			prev = awk->sio.inp->prev; | ||||
|  | ||||
| 			QSE_ASSERT (awk->sio.inp->name != QSE_NULL); | ||||
| 			QSE_MMGR_FREE (awk->mmgr, awk->sio.inp); | ||||
|  | ||||
| 			awk->sio.inp = next; | ||||
| 			awk->sio.inp = prev; | ||||
| 		} | ||||
| 	} | ||||
| 	else if (ret == 0)  | ||||
| @ -649,6 +649,17 @@ oops: | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| void qse_awk_clearsionames (qse_awk_t* awk) | ||||
| { | ||||
| 	qse_link_t* cur; | ||||
| 	while (awk->sio_names) | ||||
| 	{ | ||||
| 		cur = awk->sio_names; | ||||
| 		awk->sio_names = cur->link; | ||||
| 		QSE_MMGR_FREE (awk->mmgr, cur); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int qse_awk_parse (qse_awk_t* awk, qse_awk_sio_t* sio) | ||||
| { | ||||
| 	int n; | ||||
| @ -667,7 +678,7 @@ int qse_awk_parse (qse_awk_t* awk, qse_awk_sio_t* sio) | ||||
| 	QSE_ASSERT (awk->parse.depth.expr == 0); | ||||
|  | ||||
| 	qse_awk_clear (awk); | ||||
| 	qse_htb_clear (awk->sio_names); | ||||
| 	qse_awk_clearsionames (awk); | ||||
|  | ||||
| 	QSE_MEMSET (&awk->sio, 0, QSE_SIZEOF(awk->sio)); | ||||
| 	awk->sio.inf = sio->in; | ||||
| @ -708,7 +719,7 @@ static int end_include (qse_awk_t* awk) | ||||
| 	 * awk->sio.inp again. */ | ||||
|  | ||||
| 	cur = awk->sio.inp; | ||||
| 	awk->sio.inp = awk->sio.inp->next; | ||||
| 	awk->sio.inp = awk->sio.inp->prev; | ||||
|  | ||||
| 	QSE_ASSERT (cur->name != QSE_NULL); | ||||
| 	QSE_MMGR_FREE (awk->mmgr, cur); | ||||
| @ -728,9 +739,8 @@ static int end_include (qse_awk_t* awk) | ||||
|  | ||||
| static int begin_include (qse_awk_t* awk) | ||||
| { | ||||
| 	qse_ssize_t op; | ||||
| 	qse_awk_sio_arg_t* arg = QSE_NULL; | ||||
| 	qse_htb_pair_t* pair = QSE_NULL; | ||||
| 	qse_link_t* link; | ||||
|  | ||||
| 	if (qse_strlen(QSE_STR_PTR(awk->tok.name)) != QSE_STR_LEN(awk->tok.name)) | ||||
| 	{ | ||||
| @ -746,50 +756,49 @@ static int begin_include (qse_awk_t* awk) | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	/* store the file name to awk->sio_names */ | ||||
| 	pair = qse_htb_ensert ( | ||||
| 		awk->sio_names,  | ||||
| 		QSE_STR_PTR(awk->tok.name), | ||||
| 		QSE_STR_LEN(awk->tok.name) + 1, /* to include '\0' */ | ||||
| 		QSE_NULL, 0 | ||||
| 	); | ||||
| 	if (pair == QSE_NULL) | ||||
| 	{ | ||||
| 		SETERR_LOC (awk, QSE_AWK_ENOMEM, &awk->ptok.loc); | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
| 	/*QSE_HTB_VPTR(pair) = QSE_HTB_KPTR(pair); | ||||
| 	QSE_HTB_VLEN(pair) = QSE_HTB_KLEN(pair);*/ | ||||
|  | ||||
| 	if (awk->opt.incldirs.ptr) | ||||
| 	{ | ||||
| 		/* include directory is set... */ | ||||
| /* TODO: */ | ||||
| 	} | ||||
|  | ||||
| 	arg = (qse_awk_sio_arg_t*) qse_awk_callocmem (awk, QSE_SIZEOF(*arg)); | ||||
| 	/* store the include-file name into a list | ||||
| 	 * and this list is not deleted after qse_awk_parse. | ||||
| 	 * the errinfo.loc.file can point to a string here. */ | ||||
| 	link = (qse_link_t*) qse_awk_callocmem (awk, QSE_SIZEOF(*link) +  | ||||
| 		QSE_SIZEOF(*arg) + QSE_SIZEOF(qse_char_t) * (QSE_STR_LEN(awk->tok.name) + 1)); | ||||
| 	if (link == QSE_NULL) | ||||
| 	{ | ||||
| 		ADJERR_LOC (awk, &awk->ptok.loc); | ||||
| 		goto oops; | ||||
| 	} | ||||
| 	qse_strncpy ((qse_char_t*)(link + 1), QSE_STR_PTR(awk->tok.name), QSE_STR_LEN(awk->tok.name)); | ||||
| 	link->link = awk->sio_names; | ||||
| 	awk->sio_names = link; | ||||
|  | ||||
| 	arg = (qse_awk_sio_arg_t*) qse_awk_callocmem (awk, QSE_SIZEOF(*awk)); | ||||
| 	if (arg == QSE_NULL) | ||||
| 	{ | ||||
| 		ADJERR_LOC (awk, &awk->ptok.loc); | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
| 	arg->flags = QSE_AWK_SIO_INCLUDED; | ||||
| 	arg->name = QSE_HTB_KPTR(pair); | ||||
| 	arg->name = (const qse_char_t*)(link + 1); | ||||
| 	arg->line = 1; | ||||
| 	arg->colm = 1; | ||||
|  | ||||
| 	/* let the argument's prev field point to the current */ | ||||
| 	arg->prev = awk->sio.inp; | ||||
|  | ||||
| 	CLRERR (awk); | ||||
| 	op = awk->sio.inf (awk, QSE_AWK_SIO_OPEN, arg, QSE_NULL, 0); | ||||
| 	if (op <= -1) | ||||
| 	if (awk->sio.inf (awk, QSE_AWK_SIO_OPEN, arg, QSE_NULL, 0) <= -1) | ||||
| 	{ | ||||
| 		if (ISNOERR(awk)) SETERR_TOK (awk, QSE_AWK_EOPEN); | ||||
| 		else awk->errinf.loc = awk->tok.loc; /* adjust error location */ | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
| 	arg->next = awk->sio.inp; | ||||
| 	/* i update the current pointer after opening is successful */ | ||||
| 	awk->sio.inp = arg; | ||||
| 	awk->parse.depth.incl++; | ||||
|  | ||||
| @ -807,6 +816,8 @@ static int begin_include (qse_awk_t* awk) | ||||
| 	return 0; | ||||
|  | ||||
| oops: | ||||
| 	/* i don't need to free 'link'  here since it's linked to awk->sio_names | ||||
| 	 * that's freed at the beginning of qse_awk_parse() or by qse_awk_close(). */ | ||||
| 	if (arg) QSE_MMGR_FREE (awk->mmgr, arg); | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| @ -84,6 +84,10 @@ int qse_awk_initgbls ( | ||||
| 	qse_awk_t* awk | ||||
| ); | ||||
|  | ||||
| void qse_awk_clearsionames ( | ||||
| 	qse_awk_t* awk | ||||
| ); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| @ -84,11 +84,8 @@ typedef struct xtn_t | ||||
|  | ||||
| 			union | ||||
| 			{ | ||||
| 				struct  | ||||
| 				{ | ||||
| 					qse_sio_t* sio; /* the handle to an open file */ | ||||
| 					qse_cstr_t dir; | ||||
| 				} file; | ||||
| 				/* nothing to maintain here for file */ | ||||
|  | ||||
| 				struct  | ||||
| 				{ | ||||
| 					const qse_char_t* ptr;	 | ||||
| @ -669,7 +666,7 @@ static qse_sio_t* open_sio_std_rtx (qse_awk_rtx_t* rtx, qse_sio_std_t std, int f | ||||
|  | ||||
| /*** PARSESTD ***/ | ||||
|  | ||||
| static int open_parsestd (qse_awk_t* awk, xtn_t* xtn, qse_size_t index) | ||||
| static int open_parsestd (qse_awk_t* awk, qse_awk_sio_arg_t* arg, xtn_t* xtn, qse_size_t index) | ||||
| { | ||||
| 	qse_awk_parsestd_t* psin = &xtn->s.in.x[index]; | ||||
|  | ||||
| @ -689,37 +686,27 @@ static int open_parsestd (qse_awk_t* awk, xtn_t* xtn, qse_size_t index) | ||||
| 				if (tmp == QSE_NULL) return -1; | ||||
|  | ||||
| 				if (index >= 1 && xtn->s.in.x[index-1].type == QSE_AWK_PARSESTD_FILE) | ||||
| 					qse_sio_close (xtn->s.in.u.file.sio); | ||||
| 					qse_sio_close (arg->handle); | ||||
|  | ||||
| 				xtn->s.in.u.file.sio = tmp; | ||||
| 				arg->handle = tmp; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				qse_sio_t* tmp; | ||||
| 				const qse_char_t* base; | ||||
|  | ||||
| 				tmp = open_sio (awk, psin->u.file.path, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR); | ||||
| 				tmp = open_sio (awk, psin->u.file.path, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR | QSE_SIO_KEEPPATH); | ||||
| 				if (tmp == QSE_NULL) return -1; | ||||
|  | ||||
| 				if (index >= 1 && xtn->s.in.x[index-1].type == QSE_AWK_PARSESTD_FILE) | ||||
| 					qse_sio_close (xtn->s.in.u.file.sio); | ||||
| 				xtn->s.in.u.file.sio = tmp; | ||||
|  | ||||
| 				base = qse_basename (psin->u.file.path); | ||||
| 				if (base != psin->u.file.path) | ||||
| 				{ | ||||
| 					xtn->s.in.u.file.dir.ptr = psin->u.file.path; | ||||
| 					xtn->s.in.u.file.dir.len = base - psin->u.file.path; | ||||
| 				} | ||||
|  | ||||
| 					qse_sio_close (arg->handle); | ||||
| 				arg->handle = tmp; | ||||
| 			} | ||||
| 			if (psin->u.file.cmgr)  | ||||
| 				qse_sio_setcmgr (xtn->s.in.u.file.sio, psin->u.file.cmgr); | ||||
| 			if (psin->u.file.cmgr) qse_sio_setcmgr (arg->handle, psin->u.file.cmgr); | ||||
| 			return 0; | ||||
|  | ||||
| 		case QSE_AWK_PARSESTD_STR: | ||||
| 			if (index >= 1 && xtn->s.in.x[index-1].type == QSE_AWK_PARSESTD_FILE) | ||||
| 				qse_sio_close (xtn->s.in.u.file.sio); | ||||
| 				qse_sio_close (arg->handle); | ||||
|  | ||||
| 			xtn->s.in.u.str.ptr = psin->u.str.ptr; | ||||
| 			xtn->s.in.u.str.end = psin->u.str.ptr + psin->u.str.len; | ||||
| @ -734,21 +721,23 @@ static int open_parsestd (qse_awk_t* awk, xtn_t* xtn, qse_size_t index) | ||||
| static qse_ssize_t sf_in_open ( | ||||
| 	qse_awk_t* awk, qse_awk_sio_arg_t* arg, xtn_t* xtn) | ||||
| { | ||||
| 	if (arg == QSE_NULL || !(arg->flags & QSE_AWK_SIO_INCLUDED))  | ||||
| 	if (arg->name == QSE_NULL) | ||||
| 	{ | ||||
| 		/* handle normal source input streams specified  | ||||
| 		 * to qse_awk_parsestd() */ | ||||
|  | ||||
| 		qse_ssize_t x; | ||||
| 		x = open_parsestd (awk, xtn, 0); | ||||
| 		x = open_parsestd (awk, arg, xtn, 0); | ||||
| 		if (x >= 0)  | ||||
| 		{ | ||||
| 			xtn->s.in.xindex = 0; /* update the current stream index */ | ||||
| #if 0 | ||||
| 			/* perform some manipulation about the top-level input information */ | ||||
| 			if (xtn->s.in.x[0].type == QSE_AWK_PARSESTD_FILE) | ||||
| 				awk->sio.arg.name = xtn->s.in.x[0].u.file.path; | ||||
| 			else | ||||
| 				awk->sio.arg.name = QSE_NULL; | ||||
| #endif | ||||
| 		} | ||||
|  | ||||
| 		return x; | ||||
| @ -756,39 +745,43 @@ static qse_ssize_t sf_in_open ( | ||||
| 	else | ||||
| 	{ | ||||
| 		/* handle the included source file - @include */ | ||||
| 		const qse_char_t* file; | ||||
| 		const qse_char_t* path, * outer; | ||||
| 		qse_char_t fbuf[64]; | ||||
| 		qse_char_t* dbuf = QSE_NULL; | ||||
| 	 | ||||
| 		QSE_ASSERT (arg->name != QSE_NULL); | ||||
|  | ||||
| 		file = arg->name; | ||||
| 		if (xtn->s.in.u.file.dir.len > 0 && arg->name[0] != QSE_T('/')) | ||||
| 		path = arg->name; | ||||
| 		outer = qse_sio_getpath (arg->prev->handle); | ||||
| 		if (outer) | ||||
| 		{ | ||||
| 			qse_size_t tmplen, totlen; | ||||
| 			 | ||||
| 			totlen = qse_strlen(arg->name) + xtn->s.in.u.file.dir.len; | ||||
| 			if (totlen >= QSE_COUNTOF(fbuf)) | ||||
| 			const qse_char_t* base; | ||||
|  | ||||
| 			base = qse_basename (outer); | ||||
| 			if (base != outer && arg->name[0] != QSE_T('/')) | ||||
| 			{ | ||||
| 				dbuf = qse_awk_allocmem ( | ||||
| 					awk, QSE_SIZEOF(qse_char_t) * (totlen + 1) | ||||
| 				); | ||||
| 				if (dbuf == QSE_NULL) return -1; | ||||
| 				qse_size_t tmplen, totlen, dirlen; | ||||
| 			 | ||||
| 				dirlen = base - outer; | ||||
| 				totlen = qse_strlen(arg->name) + dirlen; | ||||
| 				if (totlen >= QSE_COUNTOF(fbuf)) | ||||
| 				{ | ||||
| 					dbuf = qse_awk_allocmem ( | ||||
| 						awk, QSE_SIZEOF(qse_char_t) * (totlen + 1) | ||||
| 					); | ||||
| 					if (dbuf == QSE_NULL) return -1; | ||||
| 	 | ||||
| 					path = dbuf; | ||||
| 				} | ||||
| 				else path = fbuf; | ||||
|  | ||||
| 				file = dbuf; | ||||
| 				tmplen = qse_strncpy ((qse_char_t*)path, outer, dirlen); | ||||
| 				qse_strcpy ((qse_char_t*)path + tmplen, arg->name); | ||||
| 			} | ||||
| 			else file = fbuf; | ||||
|  | ||||
| 			tmplen = qse_strncpy ( | ||||
| 				(qse_char_t*)file, | ||||
| 				xtn->s.in.u.file.dir.ptr, | ||||
| 				xtn->s.in.u.file.dir.len | ||||
| 			); | ||||
| 			qse_strcpy ((qse_char_t*)file + tmplen, arg->name); | ||||
| 		} | ||||
|  | ||||
| 		arg->handle = qse_sio_open ( | ||||
| 			awk->mmgr, 0, file, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR | ||||
| 			awk->mmgr, 0, path, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR | QSE_SIO_KEEPPATH | ||||
| 		); | ||||
|  | ||||
| 		if (dbuf) QSE_MMGR_FREE (awk->mmgr, dbuf); | ||||
| @ -808,12 +801,13 @@ static qse_ssize_t sf_in_open ( | ||||
| static qse_ssize_t sf_in_close ( | ||||
| 	qse_awk_t* awk, qse_awk_sio_arg_t* arg, xtn_t* xtn) | ||||
| { | ||||
| 	if (arg == QSE_NULL || !(arg->flags & QSE_AWK_SIO_INCLUDED))  | ||||
| 	if (arg->name == QSE_NULL) | ||||
| 	{ | ||||
| 		switch (xtn->s.in.x[xtn->s.in.xindex].type) | ||||
| 		{ | ||||
| 			case QSE_AWK_PARSESTD_FILE: | ||||
| 				qse_sio_close (xtn->s.in.u.file.sio); | ||||
| 				QSE_ASSERT (arg->handle != QSE_NULL); | ||||
| 				qse_sio_close (arg->handle); | ||||
| 				break; | ||||
|  | ||||
| 			case QSE_AWK_PARSESTD_STR: | ||||
| @ -839,8 +833,7 @@ static qse_ssize_t sf_in_read ( | ||||
| 	qse_awk_t* awk, qse_awk_sio_arg_t* arg, | ||||
| 	qse_char_t* data, qse_size_t size, xtn_t* xtn) | ||||
| { | ||||
|  | ||||
| 	if (arg == QSE_NULL || !(arg->flags & QSE_AWK_SIO_INCLUDED))  | ||||
| 	if (arg->name == QSE_NULL) | ||||
| 	{ | ||||
| 		qse_ssize_t n; | ||||
|  | ||||
| @ -848,8 +841,8 @@ static qse_ssize_t sf_in_read ( | ||||
| 		switch (xtn->s.in.x[xtn->s.in.xindex].type) | ||||
| 		{ | ||||
| 			case QSE_AWK_PARSESTD_FILE: | ||||
| 				QSE_ASSERT (xtn->s.in.u.file.sio != QSE_NULL); | ||||
| 				n = qse_sio_getstrn (xtn->s.in.u.file.sio, data, size); | ||||
| 				QSE_ASSERT (arg->handle != QSE_NULL); | ||||
| 				n = qse_sio_getstrn (arg->handle, data, size); | ||||
| 				if (n <= -1) | ||||
| 				{ | ||||
| 					qse_cstr_t ea; | ||||
| @ -889,18 +882,11 @@ static qse_ssize_t sf_in_read ( | ||||
| 			if (xtn->s.in.x[next].type != QSE_AWK_PARSESTD_NULL) | ||||
| 			{ | ||||
| 				/* open the next stream if available. */ | ||||
| 				if (open_parsestd (awk, xtn, next) <= -1) n = -1; | ||||
| 				if (open_parsestd (awk, arg, xtn, next) <= -1) n = -1; | ||||
| 				else  | ||||
| 				{ | ||||
| 					/* if successful, close the current stream */	 | ||||
| 					xtn->s.in.xindex = next; /* update the next to the current */ | ||||
|  | ||||
| 					/* perform some manipulation about the top-level input information */ | ||||
| 					if (xtn->s.in.x[next].type == QSE_AWK_PARSESTD_FILE) | ||||
| 						awk->sio.arg.name = xtn->s.in.x[next].u.file.path; | ||||
| 					else | ||||
| 						awk->sio.arg.name = QSE_NULL; | ||||
|  | ||||
| 					goto again; | ||||
| 				} | ||||
| 			} | ||||
| @ -2536,11 +2522,8 @@ done: | ||||
|  | ||||
| 	if (ret >= 0) | ||||
| 	{ | ||||
| 		qse_awk_val_t* retv; | ||||
|  | ||||
| 		if (rv) | ||||
| 		{ | ||||
| 			int x; | ||||
| 			qse_awk_rtx_refupval (rtx, rv); | ||||
| 			ret = qse_awk_rtx_setrefval (rtx, qse_awk_rtx_getarg (rtx, 2), rv); | ||||
| 			qse_awk_rtx_refdownval (rtx, rv); | ||||
|  | ||||
| @ -119,6 +119,14 @@ qse_sio_t* qse_sio_openstd ( | ||||
| 	qse_sio_t* sio; | ||||
| 	qse_fio_hnd_t hnd; | ||||
|  | ||||
| 	/* Is this necessary? | ||||
| 	if (flags & QSE_SIO_KEEPATH) | ||||
| 	{ | ||||
| 		sio->errnum = QSE_SIO_EINVAL; | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
| 	*/ | ||||
|  | ||||
| 	if (qse_getstdfiohandle (std, &hnd) <= -1) return QSE_NULL; | ||||
|  | ||||
| 	sio = qse_sio_open (mmgr, xtnsize,  | ||||
| @ -146,7 +154,7 @@ void qse_sio_close (qse_sio_t* sio) | ||||
| } | ||||
|  | ||||
| int qse_sio_init ( | ||||
| 	qse_sio_t* sio, qse_mmgr_t* mmgr, const qse_char_t* file, int flags) | ||||
| 	qse_sio_t* sio, qse_mmgr_t* mmgr, const qse_char_t* path, int flags) | ||||
| { | ||||
| 	int mode; | ||||
| 	int topt = 0; | ||||
| @ -162,21 +170,30 @@ int qse_sio_init ( | ||||
| 	 * this function, a user can specify a sio flag enumerator not  | ||||
| 	 * present in the fio flag enumerator. mask off such an enumerator. */ | ||||
| 	if (qse_fio_init ( | ||||
| 		&sio->file, mmgr, file,  | ||||
| 		&sio->file, mmgr, path,  | ||||
| 		(flags & ~QSE_FIO_RESERVED), mode) <= -1)  | ||||
| 	{ | ||||
| 		sio->errnum = fio_errnum_to_sio_errnum (&sio->file); | ||||
| 		return -1; | ||||
| 		goto oops00; | ||||
| 	} | ||||
|  | ||||
| 	if (flags & QSE_SIO_IGNOREMBWCERR) topt |= QSE_TIO_IGNOREMBWCERR; | ||||
| 	if (flags & QSE_SIO_NOAUTOFLUSH) topt |= QSE_TIO_NOAUTOFLUSH; | ||||
|  | ||||
| 	if ((flags & QSE_SIO_KEEPPATH) && !(flags & QSE_SIO_HANDLE)) | ||||
| 	{ | ||||
| 		sio->path = qse_strdup (path, sio->mmgr); | ||||
| 		if (sio->path == QSE_NULL) | ||||
| 		{ | ||||
| 			sio->errnum = QSE_SIO_ENOMEM; | ||||
| 			goto oops01; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (qse_tio_init(&sio->tio.io, mmgr, topt) <= -1) | ||||
| 	{ | ||||
| 		sio->errnum = tio_errnum_to_sio_errnum (&sio->tio.io); | ||||
| 		qse_fio_fini (&sio->file); | ||||
| 		return -1; | ||||
| 		goto oops02; | ||||
| 	} | ||||
| 	/* store the back-reference to sio in the extension area.*/ | ||||
| 	QSE_ASSERT (QSE_XTN(&sio->tio.io) == &sio->tio.xtn); | ||||
| @ -187,12 +204,19 @@ int qse_sio_init ( | ||||
| 	{ | ||||
| 		if (sio->errnum == QSE_SIO_ENOERR)  | ||||
| 			sio->errnum = tio_errnum_to_sio_errnum (&sio->tio.io); | ||||
| 		qse_tio_fini (&sio->tio.io);	 | ||||
| 		qse_fio_fini (&sio->file); | ||||
| 		return -1; | ||||
| 		goto oops03; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
|  | ||||
| oops03: | ||||
| 	qse_tio_fini (&sio->tio.io);	 | ||||
| oops02: | ||||
| 	if (sio->path) QSE_MMGR_FREE (sio->mmgr, sio->path); | ||||
| oops01: | ||||
| 	qse_fio_fini (&sio->file); | ||||
| oops00: | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| int qse_sio_initstd ( | ||||
| @ -227,6 +251,7 @@ void qse_sio_fini (qse_sio_t* sio) | ||||
| 	qse_sio_flush (sio); | ||||
| 	qse_tio_fini (&sio->tio.io); | ||||
| 	qse_fio_fini (&sio->file); | ||||
| 	if (sio->path) QSE_MMGR_FREE (sio->mmgr, sio->path); | ||||
| } | ||||
|  | ||||
| qse_mmgr_t* qse_sio_getmmgr (qse_sio_t* sio) | ||||
| @ -265,6 +290,12 @@ qse_ubi_t qse_sio_gethandleasubi (const qse_sio_t* sio) | ||||
| 	return qse_fio_gethandleasubi (&sio->file); | ||||
| } | ||||
|  | ||||
| const qse_char_t* qse_sio_getpath (qse_sio_t* sio) | ||||
| { | ||||
| 	/* this path is valid if QSE_SIO_HANDLE is off and QSE_SIO_KEEPPATH is on */ | ||||
| 	return sio->path; | ||||
| } | ||||
|  | ||||
| qse_ssize_t qse_sio_flush (qse_sio_t* sio) | ||||
| { | ||||
| 	qse_ssize_t n; | ||||
| @ -636,3 +667,4 @@ static qse_ssize_t file_output ( | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -279,7 +279,7 @@ static int end_include (qse_xli_t* xli) | ||||
| 	 * xli->sio.inp again. */ | ||||
|  | ||||
| 	cur = xli->sio.inp; | ||||
| 	xli->sio.inp = xli->sio.inp->next; | ||||
| 	xli->sio.inp = xli->sio.inp->prev; | ||||
|  | ||||
| 	QSE_ASSERT (cur->name != QSE_NULL); | ||||
| 	QSE_MMGR_FREE (xli->mmgr, cur); | ||||
| @ -299,43 +299,35 @@ static int end_include (qse_xli_t* xli) | ||||
|  | ||||
| static int begin_include (qse_xli_t* xli) | ||||
| { | ||||
| 	qse_ssize_t op; | ||||
| 	qse_link_t* link; | ||||
| 	qse_xli_io_arg_t* arg = QSE_NULL; | ||||
| 	qse_htb_pair_t* pair = QSE_NULL; | ||||
|  | ||||
| 	/* store the file name to xli->sio_names */ | ||||
| 	pair = qse_htb_ensert ( | ||||
| 		xli->sio_names,  | ||||
| 		QSE_STR_PTR(xli->tok.name), | ||||
| 		QSE_STR_LEN(xli->tok.name) + 1, /* to include '\0' */ | ||||
| 		QSE_NULL, 0 | ||||
| 	); | ||||
| 	if (pair == QSE_NULL) | ||||
| 	{ | ||||
| 		qse_xli_seterror (xli, QSE_XLI_ENOMEM, QSE_NULL, &xli->tok.loc); | ||||
| 		goto oops; | ||||
| 	} | ||||
| 	link = (qse_xli_io_arg_t*) qse_xli_callocmem (xli,  | ||||
| 		QSE_SIZEOF(*link) + QSE_SIZEOF(qse_char_t) * (QSE_STR_LEN(xli->tok.name) + 1)); | ||||
| 	if (link == QSE_NULL) goto oops; | ||||
|  | ||||
| 	/*QSE_HTB_VPTR(pair) = QSE_HTB_KPTR(pair); | ||||
| 	QSE_HTB_VLEN(pair) = QSE_HTB_KLEN(pair);*/ | ||||
| 	qse_strncpy ((qse_char_t*)(link + 1), QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name)); | ||||
| 	link->link = xli->sio_names; | ||||
| 	xli->sio_names = link; | ||||
|  | ||||
| 	arg = (qse_xli_io_arg_t*) qse_xli_callocmem (xli, QSE_SIZEOF(*arg)); | ||||
| 	if (arg == QSE_NULL) goto oops; | ||||
|  | ||||
| 	arg->flags = QSE_XLI_IO_INCLUDED; | ||||
| 	arg->name = QSE_HTB_KPTR(pair); | ||||
| 	arg->name = (const qse_char_t*)(link + 1); | ||||
| 	arg->line = 1; | ||||
| 	arg->colm = 1; | ||||
|  | ||||
| 	op = xli->sio.inf (xli, QSE_XLI_IO_OPEN, arg, QSE_NULL, 0); | ||||
| 	if (op <= -1) | ||||
| 	/* let the argument's prev point field to the current */ | ||||
| 	arg->prev = xli->sio.inp;  | ||||
|  | ||||
| 	if (xli->sio.inf (xli, QSE_XLI_IO_OPEN, arg, QSE_NULL, 0) <= -1) | ||||
| 	{ | ||||
| 		if (xli->errnum == QSE_XLI_ENOERR) | ||||
| 			qse_xli_seterrnum (xli, QSE_XLI_EIOUSR, QSE_NULL);  | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
| 	arg->next = xli->sio.inp; | ||||
| 	/* i update the current pointer after opening is successful */ | ||||
| 	xli->sio.inp = arg; | ||||
| 	/* xli->parse.depth.incl++; */ | ||||
|  | ||||
| @ -353,6 +345,9 @@ static int begin_include (qse_xli_t* xli) | ||||
| 	return 0; | ||||
|  | ||||
| oops: | ||||
| 	/* i don't need to free 'link' since it's linked to | ||||
| 	 * xli->sio_names that's freed at the beginning of qse_xli_read() | ||||
| 	 * or by qse_xli_fini() */ | ||||
| 	if (arg) QSE_MMGR_FREE (xli->mmgr, arg); | ||||
| 	return -1; | ||||
| } | ||||
| @ -726,6 +721,17 @@ oops: | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| void qse_xli_clearsionames (qse_xli_t* xli) | ||||
| { | ||||
| 	qse_link_t* cur; | ||||
| 	while (xli->sio_names) | ||||
| 	{ | ||||
| 		cur = xli->sio_names; | ||||
| 		xli->sio_names = cur->link; | ||||
| 		QSE_MMGR_FREE (xli->mmgr, cur); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int qse_xli_read (qse_xli_t* xli, qse_xli_io_impl_t io) | ||||
| { | ||||
| 	qse_ssize_t n; | ||||
| @ -741,7 +747,7 @@ int qse_xli_read (qse_xli_t* xli, qse_xli_io_impl_t io) | ||||
| 	xli->sio.arg.line = 1; | ||||
| 	xli->sio.arg.colm = 1; | ||||
| 	xli->sio.inp = &xli->sio.arg; | ||||
| 	qse_htb_clear (xli->sio_names); | ||||
| 	qse_xli_clearsionames (xli); | ||||
|  | ||||
| 	n = xli->sio.inf (xli, QSE_XLI_IO_OPEN, xli->sio.inp, QSE_NULL, 0); | ||||
| 	if (n <= -1) | ||||
| @ -771,15 +777,15 @@ oops: | ||||
| 	 * closed. close them */ | ||||
| 	while (xli->sio.inp != &xli->sio.arg) | ||||
| 	{ | ||||
| 		qse_xli_io_arg_t* next; | ||||
| 		qse_xli_io_arg_t* prev; | ||||
|  | ||||
| 		/* nothing much to do about a close error */ | ||||
| 		close_stream (xli); | ||||
|  | ||||
| 		next = xli->sio.inp->next; | ||||
| 		prev = xli->sio.inp->prev; | ||||
| 		QSE_ASSERT (xli->sio.inp->name != QSE_NULL); | ||||
| 		QSE_MMGR_FREE (xli->mmgr, xli->sio.inp); | ||||
| 		xli->sio.inp = next; | ||||
| 		xli->sio.inp = prev; | ||||
| 	} | ||||
| 	 | ||||
| 	close_stream (xli); | ||||
|  | ||||
| @ -33,11 +33,10 @@ typedef struct xtn_t | ||||
|  | ||||
| 			union | ||||
| 			{ | ||||
| 				struct  | ||||
| 				{ | ||||
| 					qse_sio_t* sio; /* the handle to an open file */ | ||||
| 					qse_cstr_t dir; | ||||
| 				} file; | ||||
| 				/*  | ||||
| 					nothing to maintain for file here  | ||||
| 				 */ | ||||
|  | ||||
| 				struct  | ||||
| 				{ | ||||
| 					const qse_char_t* ptr;	 | ||||
| @ -150,118 +149,85 @@ static qse_sio_t* open_sio_std (qse_xli_t* xli, qse_sio_std_t std, int flags) | ||||
| 	return sio; | ||||
| } | ||||
|  | ||||
| static int open_readstd (qse_xli_t* xli, xtn_t* xtn) | ||||
| static qse_ssize_t sf_in_open (qse_xli_t* xli, qse_xli_io_arg_t* arg, xtn_t* xtn) | ||||
| { | ||||
| 	qse_xli_iostd_t* psin = xtn->s.in.x; | ||||
|  | ||||
| 	switch (psin->type) | ||||
| 	if (arg->name == QSE_NULL) | ||||
| 	{ | ||||
| 		/* normal source files */ | ||||
|  | ||||
| 		case QSE_XLI_IOSTD_FILE: | ||||
| 			if (psin->u.file.path == QSE_NULL || | ||||
| 			    (psin->u.file.path[0] == QSE_T('-') && | ||||
| 			     psin->u.file.path[1] == QSE_T('\0'))) | ||||
| 			{ | ||||
| 				/* no path name or - -> stdin */ | ||||
| 				qse_sio_t* tmp; | ||||
|  | ||||
| 				tmp = open_sio_std (xli, QSE_SIO_STDIN, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR); | ||||
| 				if (tmp == QSE_NULL) return -1; | ||||
|  | ||||
| 				xtn->s.in.u.file.sio = tmp; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				qse_sio_t* tmp; | ||||
| 				const qse_char_t* base; | ||||
|  | ||||
| 				tmp = open_sio (xli, psin->u.file.path, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR); | ||||
| 				if (tmp == QSE_NULL) return -1; | ||||
|  | ||||
| 				xtn->s.in.u.file.sio = tmp; | ||||
|  | ||||
| 				base = qse_basename (psin->u.file.path); | ||||
| 				if (base != psin->u.file.path) | ||||
| 				{ | ||||
| 					xtn->s.in.u.file.dir.ptr = psin->u.file.path; | ||||
| 					xtn->s.in.u.file.dir.len = base - psin->u.file.path; | ||||
| 				} | ||||
|  | ||||
| 			} | ||||
| 			if (psin->u.file.cmgr)  | ||||
| 				qse_sio_setcmgr (xtn->s.in.u.file.sio, psin->u.file.cmgr); | ||||
| 			return 0; | ||||
|  | ||||
| 		case QSE_XLI_IOSTD_STR: | ||||
| 			xtn->s.in.u.str.ptr = psin->u.str.ptr; | ||||
| 			xtn->s.in.u.str.end = psin->u.str.ptr + psin->u.str.len; | ||||
| 			return 0; | ||||
|  | ||||
| 		default: | ||||
| 			qse_xli_seterrnum (xli, QSE_XLI_EINTERN, QSE_NULL); | ||||
| 			return -1; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static qse_ssize_t sf_in_open ( | ||||
| 	qse_xli_t* xli, qse_xli_io_arg_t* arg, xtn_t* xtn) | ||||
| { | ||||
| 	if (arg == QSE_NULL || !(arg->flags & QSE_XLI_IO_INCLUDED))  | ||||
| 	{ | ||||
| 		/* handle normal source input streams specified  | ||||
| 		 * to qse_xli_readstd() */ | ||||
|  | ||||
| 		qse_ssize_t x; | ||||
|  | ||||
| 		x = open_readstd (xli, xtn); | ||||
| 		if (x >= 0)  | ||||
| 		qse_xli_iostd_t* psin = xtn->s.in.x; | ||||
| 	 | ||||
| 		switch (psin->type) | ||||
| 		{ | ||||
| 			/* perform some manipulation about the top-level input information */ | ||||
| 			if (xtn->s.in.x->type == QSE_XLI_IOSTD_FILE) | ||||
| 				xli->sio.arg.name = xtn->s.in.x->u.file.path; | ||||
| 			else | ||||
| 				xli->sio.arg.name = QSE_NULL; | ||||
| 			/* normal source files */ | ||||
| 			case QSE_XLI_IOSTD_FILE: | ||||
| 				if (psin->u.file.path == QSE_NULL || | ||||
| 				    (psin->u.file.path[0] == QSE_T('-') && | ||||
| 				     psin->u.file.path[1] == QSE_T('\0'))) | ||||
| 				{ | ||||
| 					/* no path name or - -> stdin */ | ||||
| 					arg->handle = open_sio_std (xli, QSE_SIO_STDIN, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					arg->handle = open_sio (xli, psin->u.file.path, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR | QSE_SIO_KEEPPATH); | ||||
| 				} | ||||
| 				if (arg->handle == QSE_NULL) return -1; | ||||
| 				if (psin->u.file.cmgr) qse_sio_setcmgr (arg->handle, psin->u.file.cmgr); | ||||
| 				return 0; | ||||
| 	 | ||||
| 			case QSE_XLI_IOSTD_STR: | ||||
| 				xtn->s.in.u.str.ptr = psin->u.str.ptr; | ||||
| 				xtn->s.in.u.str.end = psin->u.str.ptr + psin->u.str.len; | ||||
| 				return 0; | ||||
| 	 | ||||
| 			default: | ||||
| 				qse_xli_seterrnum (xli, QSE_XLI_EINTERN, QSE_NULL); | ||||
| 				return -1; | ||||
| 		} | ||||
|  | ||||
| 		return x; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		QSE_ASSERT (arg->prev != QSE_NULL); | ||||
|  | ||||
| 		/* handle the included file - @include */ | ||||
| 		const qse_char_t* file; | ||||
| 		const qse_char_t* path, * outer; | ||||
| 		qse_char_t fbuf[64]; | ||||
| 		qse_char_t* dbuf = QSE_NULL; | ||||
| 	 | ||||
| 		QSE_ASSERT (arg->name != QSE_NULL); | ||||
|  | ||||
| 		file = arg->name; | ||||
| 		if (xtn->s.in.u.file.dir.len > 0 && arg->name[0] != QSE_T('/')) | ||||
| 		path = arg->name; | ||||
| 		outer = qse_sio_getpath (arg->prev->handle); | ||||
| 		if (outer) | ||||
| 		{ | ||||
| 			qse_size_t tmplen, totlen; | ||||
| 			 | ||||
| 			totlen = qse_strlen(arg->name) + xtn->s.in.u.file.dir.len; | ||||
| 			if (totlen >= QSE_COUNTOF(fbuf)) | ||||
| 			const qse_char_t* base; | ||||
|  | ||||
| 			/* i'm being included from another file */ | ||||
| 			base = qse_basename (outer); | ||||
| 			if (base != outer && arg->name[0] != QSE_T('/')) | ||||
| 			{ | ||||
| 				dbuf = qse_xli_allocmem ( | ||||
| 					xli, QSE_SIZEOF(qse_char_t) * (totlen + 1) | ||||
| 				); | ||||
| 				if (dbuf == QSE_NULL) return -1; | ||||
| 				qse_size_t tmplen, totlen, dirlen; | ||||
|  | ||||
| 				file = dbuf; | ||||
| 				dirlen = base - outer;	 | ||||
| 				 | ||||
| 				totlen = qse_strlen(arg->name) + dirlen; | ||||
| 				if (totlen >= QSE_COUNTOF(fbuf)) | ||||
| 				{ | ||||
| 					dbuf = qse_xli_allocmem ( | ||||
| 						xli, QSE_SIZEOF(qse_char_t) * (totlen + 1) | ||||
| 					); | ||||
| 					if (dbuf == QSE_NULL) return -1; | ||||
| 	 | ||||
| 					path = dbuf; | ||||
| 				} | ||||
| 				else path = fbuf; | ||||
| 	 | ||||
| 				tmplen = qse_strncpy ((qse_char_t*)path, outer, dirlen); | ||||
| 				qse_strcpy ((qse_char_t*)path + tmplen, arg->name); | ||||
| 			} | ||||
| 			else file = fbuf; | ||||
|  | ||||
| 			tmplen = qse_strncpy ( | ||||
| 				(qse_char_t*)file, | ||||
| 				xtn->s.in.u.file.dir.ptr, | ||||
| 				xtn->s.in.u.file.dir.len | ||||
| 			); | ||||
| 			qse_strcpy ((qse_char_t*)file + tmplen, arg->name); | ||||
| 		} | ||||
|  | ||||
| 		arg->handle = qse_sio_open ( | ||||
| 			xli->mmgr, 0, file, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR | ||||
| 			xli->mmgr, 0, path, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR | QSE_SIO_KEEPPATH | ||||
| 		); | ||||
|  | ||||
| 		if (dbuf) QSE_MMGR_FREE (xli->mmgr, dbuf); | ||||
| @ -278,15 +244,17 @@ static qse_ssize_t sf_in_open ( | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| static qse_ssize_t sf_in_close ( | ||||
| 	qse_xli_t* xli, qse_xli_io_arg_t* arg, xtn_t* xtn) | ||||
| { | ||||
| 	if (arg == QSE_NULL || !(arg->flags & QSE_XLI_IO_INCLUDED))  | ||||
| 	if (arg->name == QSE_NULL) | ||||
| 	{ | ||||
| 		switch (xtn->s.in.x->type) | ||||
| 		{ | ||||
| 			case QSE_XLI_IOSTD_FILE: | ||||
| 				qse_sio_close (xtn->s.in.u.file.sio); | ||||
| 				QSE_ASSERT (arg->handle != QSE_NULL); | ||||
| 				qse_sio_close (arg->handle); | ||||
| 				break; | ||||
|  | ||||
| 			case QSE_XLI_IOSTD_STR: | ||||
| @ -312,16 +280,15 @@ static qse_ssize_t sf_in_read ( | ||||
| 	qse_xli_t* xli, qse_xli_io_arg_t* arg, | ||||
| 	qse_char_t* data, qse_size_t size, xtn_t* xtn) | ||||
| { | ||||
|  | ||||
| 	if (arg == QSE_NULL || !(arg->flags & QSE_XLI_IO_INCLUDED))  | ||||
| 	if (arg->name == QSE_NULL) | ||||
| 	{ | ||||
| 		qse_ssize_t n; | ||||
|  | ||||
| 		switch (xtn->s.in.x->type) | ||||
| 		{ | ||||
| 			case QSE_XLI_IOSTD_FILE: | ||||
| 				QSE_ASSERT (xtn->s.in.u.file.sio != QSE_NULL); | ||||
| 				n = qse_sio_getstrn (xtn->s.in.u.file.sio, data, size); | ||||
| 				QSE_ASSERT (arg->handle != QSE_NULL); | ||||
| 				n = qse_sio_getstrn (arg->handle, data, size); | ||||
| 				if (n <= -1) | ||||
| 				{ | ||||
| 					qse_cstr_t ea; | ||||
| @ -382,6 +349,8 @@ static qse_ssize_t sf_in ( | ||||
| { | ||||
| 	xtn_t* xtn = QSE_XTN (xli); | ||||
|  | ||||
| 	QSE_ASSERT (arg != QSE_NULL); | ||||
|  | ||||
| 	switch (cmd) | ||||
| 	{ | ||||
| 		case QSE_XLI_IO_OPEN: | ||||
|  | ||||
| @ -67,22 +67,12 @@ int qse_xli_init (qse_xli_t* xli, qse_mmgr_t* mmgr) | ||||
| 	xli->tok.name = qse_str_open (mmgr, 0, 128); | ||||
| 	if (xli->tok.name == QSE_NULL) goto oops; | ||||
|  | ||||
| 	xli->sio_names = qse_htb_open ( | ||||
| 		mmgr, QSE_SIZEOF(xli), 128, 70, QSE_SIZEOF(qse_char_t), 1 | ||||
| 	); | ||||
| 	if (xli->sio_names == QSE_NULL) goto oops; | ||||
| 	*(qse_xli_t**)QSE_XTN(xli->sio_names) = xli; | ||||
| 	qse_htb_setstyle (xli->sio_names,  | ||||
| 		qse_gethtbstyle(QSE_HTB_STYLE_INLINE_KEY_COPIER) | ||||
| 	); | ||||
| 	 | ||||
| 	xli->root.type = QSE_XLI_LIST; | ||||
| 	xli->xnil.type = QSE_XLI_NIL; | ||||
| 	return 0; | ||||
|  | ||||
| oops: | ||||
| 	qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL); | ||||
| 	if (xli->sio_names) qse_htb_close (xli->sio_names); | ||||
| 	if (xli->tok.name) qse_str_close (xli->tok.name); | ||||
| 	 | ||||
| 	for (i = QSE_COUNTOF(xli->tmp); i > 0; ) | ||||
| @ -97,13 +87,14 @@ void qse_xli_fini (qse_xli_t* xli) | ||||
| 	qse_size_t i; | ||||
|  | ||||
| 	qse_xli_clear (xli); | ||||
| 	qse_htb_close (xli->sio_names); | ||||
| 	qse_str_close (xli->tok.name); | ||||
|  | ||||
| 	for (i = QSE_COUNTOF(xli->tmp); i > 0; ) | ||||
| 	{ | ||||
| 		if (xli->tmp[--i]) qse_str_close (xli->tmp[i]); | ||||
| 	} | ||||
|  | ||||
| 	qse_xli_clearsionames (xli); | ||||
| } | ||||
|  | ||||
| qse_mmgr_t* qse_xli_getmmgr (qse_xli_t* xli) | ||||
|  | ||||
| @ -23,7 +23,6 @@ | ||||
|  | ||||
| #include <qse/xli/xli.h> | ||||
| #include <qse/cmn/str.h> | ||||
| #include <qse/cmn/htb.h> | ||||
| #include "../cmn/mem.h" | ||||
|  | ||||
| typedef struct qse_xli_tok_t qse_xli_tok_t; | ||||
| @ -63,7 +62,7 @@ struct qse_xli_t | ||||
| 		qse_xli_io_arg_t  arg; /* for top level */ | ||||
| 		qse_xli_io_arg_t* inp; /* current */ | ||||
| 	} sio; | ||||
| 	qse_htb_t* sio_names; | ||||
| 	qse_link_t* sio_names; | ||||
| }; | ||||
|  | ||||
|  | ||||
| @ -78,6 +77,8 @@ void qse_xli_fini (qse_xli_t* xli); | ||||
| const qse_char_t* qse_xli_dflerrstr ( | ||||
|      const qse_xli_t* xli, qse_xli_errnum_t errnum); | ||||
|  | ||||
| void qse_xli_clearsionames (qse_xli_t* xli); | ||||
|  | ||||
| #if defined(__cplusplus) | ||||
| } | ||||
| #endif | ||||
|  | ||||
		Reference in New Issue
	
	Block a user