added QSE_XLI_KEYTAG
This commit is contained in:
		| @ -138,7 +138,8 @@ static void print_usage (QSE_FILE* out, int argc, qse_char_t* argv[]) | |||||||
| 	qse_fprintf (out, QSE_T(" -d                        allow a leading digit in identifiers\n")); | 	qse_fprintf (out, QSE_T(" -d                        allow a leading digit in identifiers\n")); | ||||||
| 	qse_fprintf (out, QSE_T(" -n                        disallow nil\n")); | 	qse_fprintf (out, QSE_T(" -n                        disallow nil\n")); | ||||||
| 	qse_fprintf (out, QSE_T(" -l                        disallow lists\n")); | 	qse_fprintf (out, QSE_T(" -l                        disallow lists\n")); | ||||||
| 	qse_fprintf (out, QSE_T(" -T                        allow string tags\n")); | 	qse_fprintf (out, QSE_T(" -K                        allow key tags\n")); | ||||||
|  | 	qse_fprintf (out, QSE_T(" -S                        allow string tags\n")); | ||||||
| 	qse_fprintf (out, QSE_T(" -v                        perform validation\n")); | 	qse_fprintf (out, QSE_T(" -v                        perform validation\n")); | ||||||
| 	qse_fprintf (out, QSE_T(" -m                 number specify the maximum amount of memory to use in bytes\n")); | 	qse_fprintf (out, QSE_T(" -m                 number specify the maximum amount of memory to use in bytes\n")); | ||||||
| #if defined(QSE_BUILD_DEBUG) | #if defined(QSE_BUILD_DEBUG) | ||||||
| @ -166,9 +167,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("hi:o:uaftsdnlTvm:X:"), | 		QSE_T("hi:o:uaftsdnlKSvm:X:"), | ||||||
| #else | #else | ||||||
| 		QSE_T("hi:o:uaftsdnlTvm:"), | 		QSE_T("hi:o:uaftsdnlKSvm:"), | ||||||
| #endif | #endif | ||||||
| 		lng | 		lng | ||||||
| 	}; | 	}; | ||||||
| @ -242,7 +243,11 @@ static int handle_args (int argc, qse_char_t* argv[]) | |||||||
| 				g_trait |= QSE_XLI_NOLIST; | 				g_trait |= QSE_XLI_NOLIST; | ||||||
| 				break; | 				break; | ||||||
|  |  | ||||||
| 			case QSE_T('T'): | 			case QSE_T('K'): | ||||||
|  | 				g_trait |= QSE_XLI_KEYTAG; | ||||||
|  | 				break; | ||||||
|  |  | ||||||
|  | 			case QSE_T('S'): | ||||||
| 				g_trait |= QSE_XLI_STRTAG; | 				g_trait |= QSE_XLI_STRTAG; | ||||||
| 				break; | 				break; | ||||||
|  |  | ||||||
| @ -518,7 +523,7 @@ for (i = 0; i < QSE_COUNTOF(defs); i++) qse_xli_definepair (xli, defs[i].name, & | |||||||
| 			{ QSE_T("world"), 5 } | 			{ QSE_T("world"), 5 } | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
| 		if (qse_xli_insertpairwithstrs (xli, qse_xli_getroot(xli), QSE_NULL, QSE_T("test-key"), QSE_NULL, strs, QSE_COUNTOF(strs)) == QSE_NULL) | 		if (qse_xli_insertpairwithstrs (xli, qse_xli_getroot(xli), QSE_NULL, QSE_T("test-key"), QSE_NULL, QSE_NULL, strs, QSE_COUNTOF(strs)) == QSE_NULL) | ||||||
| 		{ | 		{ | ||||||
| 			qse_fprintf (QSE_STDERR,  | 			qse_fprintf (QSE_STDERR,  | ||||||
| 				QSE_T("ERROR: cannot insert a string pair - %s \n"), | 				QSE_T("ERROR: cannot insert a string pair - %s \n"), | ||||||
|  | |||||||
| @ -40,24 +40,25 @@ enum qse_xli_errnum_t | |||||||
| 	QSE_XLI_EIOFIL,  /**< io error with file '${0}' */ | 	QSE_XLI_EIOFIL,  /**< io error with file '${0}' */ | ||||||
| 	QSE_XLI_EIOUSR,  /**< i/o handler error */ | 	QSE_XLI_EIOUSR,  /**< i/o handler error */ | ||||||
|  |  | ||||||
| 	QSE_XLI_ESYNTAX, /**< syntax error */ | 	QSE_XLI_ESYNTAX,  /**< syntax error */ | ||||||
| 	QSE_XLI_ESCOLON, /**< semicolon expected in place of '${0}' */ | 	QSE_XLI_ESCOLON,  /**< semicolon expected in place of '${0}' */ | ||||||
| 	QSE_XLI_ELBREQ,  /**< { or = expected in place of '${0}' */ | 	QSE_XLI_ELBREQ,   /**< { or = expected in place of '${0}' */ | ||||||
| 	QSE_XLI_ERBRCE,  /**< } expected in place of '${0}' */ | 	QSE_XLI_ERBRCE,   /**< } expected in place of '${0}' */ | ||||||
| 	QSE_XLI_EPAVAL,  /**< pair value expected in place of '${0}' */ | 	QSE_XLI_EPAVAL,   /**< pair value expected in place of '${0}' */ | ||||||
| 	QSE_XLI_ESTRNC,  /**< string not closed */ | 	QSE_XLI_ESTRNC,   /**< string not closed */ | ||||||
| 	QSE_XLI_ETAGNC,  /**< string tag not closed */ | 	QSE_XLI_ETAGNC,   /**< string tag not closed */ | ||||||
| 	QSE_XLI_EINCLSTR,/**< '@include' not followed by a string */ | 	QSE_XLI_EINCLSTR ,/**< '@include' not followed by a string */ | ||||||
| 	QSE_XLI_ELXCHR,  /**< invalid character '${0} */ | 	QSE_XLI_ELXCHR,   /**< invalid character '${0} */ | ||||||
| 	QSE_XLI_ETAGCHR, /**< invalid tag character '${0} */ | 	QSE_XLI_ETAGCHR,  /**< invalid tag character '${0} */ | ||||||
| 	QSE_XLI_EXKWNR,  /**< @word '${0}' not recognized */ | 	QSE_XLI_EXKWNR,   /**< @word '${0}' not recognized */ | ||||||
| 	QSE_XLI_EXKWEM,  /**< @ not followed by a valid word  */ | 	QSE_XLI_EXKWEM,   /**< @ not followed by a valid word  */ | ||||||
| 	QSE_XLI_EIDENT,  /**< invalid identifier '${0}' */ | 	QSE_XLI_EIDENT,   /**< invalid identifier '${0}' */ | ||||||
| 	QSE_XLI_EUDKEY,  /**< undefined key '${0}' */ | 	QSE_XLI_ENOKEY,   /**< missing key after key tag */ | ||||||
| 	QSE_XLI_ENOALI,  /**< no alias for '${0}' */ | 	QSE_XLI_EUDKEY,   /**< undefined key '${0}' */ | ||||||
| 	QSE_XLI_EILVAL,  /**< illegal value for '${0}' */ | 	QSE_XLI_ENOALI,   /**< no alias for '${0}' */ | ||||||
| 	QSE_XLI_ENOVAL,  /**< no value for '${0}' */ | 	QSE_XLI_EILVAL,   /**< illegal value for '${0}' */ | ||||||
| 	QSE_XLI_ESTRSEG  /**< too many string segments for '${0}' */ | 	QSE_XLI_ENOVAL,   /**< no value for '${0}' */ | ||||||
|  | 	QSE_XLI_ESTRSEG   /**< too many string segments for '${0}' */ | ||||||
| }; | }; | ||||||
| typedef enum qse_xli_errnum_t qse_xli_errnum_t; | typedef enum qse_xli_errnum_t qse_xli_errnum_t; | ||||||
|  |  | ||||||
| @ -102,14 +103,19 @@ enum qse_xli_trait_t | |||||||
| 	QSE_XLI_NONIL     = (1 << 7),  | 	QSE_XLI_NONIL     = (1 << 7),  | ||||||
| 	QSE_XLI_NOLIST    = (1 << 8), | 	QSE_XLI_NOLIST    = (1 << 8), | ||||||
|  |  | ||||||
|  | 	/** enable a pair key tag. a pair key tag is a bracketed  | ||||||
|  | 	 *  word placed in front of a pair key. for example, | ||||||
|  | 	 *    [tg] A = "abc"; | ||||||
|  | 	 *  "tg" is stored into the tag field of qse_xli_pair_t. */ | ||||||
|  | 	QSE_XLI_KEYTAG    = (1 << 9), | ||||||
|  |  | ||||||
| 	/** enable a string tag. a string tag is a bracketed word  | 	/** enable a string tag. a string tag is a bracketed word  | ||||||
| 	 *  placed in front of a string value. for example,  | 	 *  placed in front of a string value. for example,  | ||||||
| 	 *    A = [tg] "abc";  | 	 *    A = [tg] "abc";  | ||||||
| 	 *  "tg" is stored into the tag field of qse_xli_str_t.  | 	 *  "tg" is stored into the tag field of qse_xli_str_t. */ | ||||||
| 	 */ | 	QSE_XLI_STRTAG    = (1 << 10),  | ||||||
| 	QSE_XLI_STRTAG    = (1 << 9),  |  | ||||||
|  |  | ||||||
| 	QSE_XLI_VALIDATE  = (1 << 10) | 	QSE_XLI_VALIDATE  = (1 << 11) | ||||||
| }; | }; | ||||||
| typedef enum qse_xli_trait_t qse_xli_trait_t; | typedef enum qse_xli_trait_t qse_xli_trait_t; | ||||||
|  |  | ||||||
| @ -187,6 +193,7 @@ struct qse_xli_pair_t | |||||||
| 	QSE_XLI_ATOM_HDR; | 	QSE_XLI_ATOM_HDR; | ||||||
| 	const qse_char_t* key; | 	const qse_char_t* key; | ||||||
| 	const qse_char_t* alias;  | 	const qse_char_t* alias;  | ||||||
|  | 	const qse_char_t* tag; | ||||||
| 	qse_xli_val_t*    val; | 	qse_xli_val_t*    val; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @ -207,7 +214,6 @@ struct qse_xli_eof_t | |||||||
| 	QSE_XLI_ATOM_HDR; | 	QSE_XLI_ATOM_HDR; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * The qse_xli_ecb_close_t type defines the callback function |  * The qse_xli_ecb_close_t type defines the callback function | ||||||
|  * called when an xli object is cloxli. |  * called when an xli object is cloxli. | ||||||
| @ -532,6 +538,7 @@ QSE_EXPORT qse_xli_pair_t* qse_xli_insertpair ( | |||||||
| 	qse_xli_atom_t*   peer, | 	qse_xli_atom_t*   peer, | ||||||
| 	const qse_char_t* key, | 	const qse_char_t* key, | ||||||
| 	const qse_char_t* alias, | 	const qse_char_t* alias, | ||||||
|  | 	const qse_char_t* keytag, | ||||||
| 	qse_xli_val_t*    val | 	qse_xli_val_t*    val | ||||||
| ); | ); | ||||||
|  |  | ||||||
| @ -540,7 +547,8 @@ QSE_EXPORT qse_xli_pair_t* qse_xli_insertpairwithemptylist ( | |||||||
| 	qse_xli_list_t*   list, | 	qse_xli_list_t*   list, | ||||||
| 	qse_xli_atom_t*   peer, | 	qse_xli_atom_t*   peer, | ||||||
| 	const qse_char_t* key, | 	const qse_char_t* key, | ||||||
| 	const qse_char_t* alias | 	const qse_char_t* alias, | ||||||
|  | 	const qse_char_t* keytag | ||||||
| ); | ); | ||||||
|  |  | ||||||
| QSE_EXPORT qse_xli_pair_t* qse_xli_insertpairwithstr ( | QSE_EXPORT qse_xli_pair_t* qse_xli_insertpairwithstr ( | ||||||
| @ -549,8 +557,9 @@ QSE_EXPORT qse_xli_pair_t* qse_xli_insertpairwithstr ( | |||||||
| 	qse_xli_atom_t*   peer, | 	qse_xli_atom_t*   peer, | ||||||
| 	const qse_char_t* key, | 	const qse_char_t* key, | ||||||
| 	const qse_char_t* alias, | 	const qse_char_t* alias, | ||||||
| 	const qse_char_t* tag, | 	const qse_char_t* keytag, | ||||||
| 	const qse_cstr_t* value | 	const qse_cstr_t* value, | ||||||
|  | 	const qse_char_t* strtag | ||||||
| ); | ); | ||||||
|  |  | ||||||
| QSE_EXPORT qse_xli_pair_t* qse_xli_insertpairwithstrs ( | QSE_EXPORT qse_xli_pair_t* qse_xli_insertpairwithstrs ( | ||||||
| @ -559,6 +568,7 @@ QSE_EXPORT qse_xli_pair_t* qse_xli_insertpairwithstrs ( | |||||||
| 	qse_xli_atom_t*   peer, | 	qse_xli_atom_t*   peer, | ||||||
| 	const qse_char_t* key, | 	const qse_char_t* key, | ||||||
| 	const qse_char_t* alias, | 	const qse_char_t* alias, | ||||||
|  | 	const qse_char_t* keytag, | ||||||
| 	const qse_cstr_t  value[], | 	const qse_cstr_t  value[], | ||||||
| 	qse_size_t        count | 	qse_size_t        count | ||||||
| ); | ); | ||||||
| @ -578,7 +588,7 @@ QSE_EXPORT qse_xli_file_t* qse_xli_insertfile ( | |||||||
| ); | ); | ||||||
|  |  | ||||||
| QSE_EXPORT qse_xli_eof_t* qse_xli_inserteof ( | QSE_EXPORT qse_xli_eof_t* qse_xli_inserteof ( | ||||||
|         qse_xli_t* xli, | 	qse_xli_t* xli, | ||||||
| 	qse_xli_list_t* parent, | 	qse_xli_list_t* parent, | ||||||
| 	qse_xli_atom_t* peer | 	qse_xli_atom_t* peer | ||||||
| ); | ); | ||||||
|  | |||||||
| @ -52,6 +52,7 @@ const qse_char_t* qse_xli_dflerrstr ( | |||||||
| 		QSE_T("'${0}' not recognized"), | 		QSE_T("'${0}' not recognized"), | ||||||
| 		QSE_T("@ not followed by a valid word"), | 		QSE_T("@ not followed by a valid word"), | ||||||
| 		QSE_T("invalid identifier '${0}'"), | 		QSE_T("invalid identifier '${0}'"), | ||||||
|  | 		QSE_T("missing key after key tag"), | ||||||
| 		QSE_T("undefined key '${0}'"), | 		QSE_T("undefined key '${0}'"), | ||||||
| 		QSE_T("no alias for '${0}'"), | 		QSE_T("no alias for '${0}'"), | ||||||
| 		QSE_T("illegal value for '${0}'"), | 		QSE_T("illegal value for '${0}'"), | ||||||
|  | |||||||
| @ -60,7 +60,7 @@ enum tok_t | |||||||
| 	TOK_NSTR, | 	TOK_NSTR, | ||||||
| 	TOK_IDENT, | 	TOK_IDENT, | ||||||
| 	TOK_TEXT, | 	TOK_TEXT, | ||||||
| 	TOK_STRTAG, | 	TOK_TAG, | ||||||
|  |  | ||||||
| 	__TOKEN_COUNT__ | 	__TOKEN_COUNT__ | ||||||
| }; | }; | ||||||
| @ -569,14 +569,14 @@ retry: | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else if ((xli->opt.trait & QSE_XLI_STRTAG) && c == QSE_T('[')) | 	else if ((xli->opt.trait & (QSE_XLI_KEYTAG | QSE_XLI_STRTAG)) && c == QSE_T('[')) | ||||||
| 	{ | 	{ | ||||||
| 		/* a string tag is a bracketed word placed in front of a string value. | 		/* a string tag is a bracketed word placed in front of a string value. | ||||||
| 		 *   A = [tg] "abc";  | 		 *   A = [tg] "abc";  | ||||||
| 		 * "tg" is stored into the tag field of qse_xli_str_t.  | 		 * "tg" is stored into the tag field of qse_xli_str_t.  | ||||||
| 		 */ | 		 */ | ||||||
|  |  | ||||||
| 		SET_TOKEN_TYPE (xli, tok, TOK_STRTAG); | 		SET_TOKEN_TYPE (xli, tok, TOK_TAG); | ||||||
| 		 | 		 | ||||||
| 		while (1) | 		while (1) | ||||||
| 		{ | 		{ | ||||||
| @ -596,7 +596,7 @@ retry: | |||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if (!QSE_ISALNUM(c)) | 			if (!QSE_ISALNUM(c) && c != QSE_T('-') && c != QSE_T('_')) | ||||||
| 			{ | 			{ | ||||||
| 				qse_char_t cc = (qse_char_t)c; | 				qse_char_t cc = (qse_char_t)c; | ||||||
| 				qse_cstr_t ea; | 				qse_cstr_t ea; | ||||||
| @ -658,7 +658,7 @@ static int get_token (qse_xli_t* xli) | |||||||
| 	return get_token_into (xli, &xli->tok); | 	return get_token_into (xli, &xli->tok); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int read_pair (qse_xli_t* xli) | static int read_pair (qse_xli_t* xli, const qse_char_t* keytag) | ||||||
| { | { | ||||||
| 	qse_xstr_t key; | 	qse_xstr_t key; | ||||||
| 	qse_xli_loc_t kloc; | 	qse_xli_loc_t kloc; | ||||||
| @ -666,14 +666,14 @@ static int read_pair (qse_xli_t* xli) | |||||||
| 	qse_xli_pair_t* pair; | 	qse_xli_pair_t* pair; | ||||||
| 	qse_xli_list_t* parlist; | 	qse_xli_list_t* parlist; | ||||||
| 	qse_size_t dotted_curkey_len; | 	qse_size_t dotted_curkey_len; | ||||||
| 	qse_char_t* tag; | 	qse_char_t* strtag; | ||||||
|  |  | ||||||
| 	qse_xli_scm_t* scm = QSE_NULL; | 	qse_xli_scm_t* scm = QSE_NULL; | ||||||
| 	int key_nodup = 0, key_alias = 0; | 	int key_nodup = 0, key_alias = 0; | ||||||
|  |  | ||||||
| 	key.ptr = QSE_NULL; | 	key.ptr = QSE_NULL; | ||||||
| 	name = QSE_NULL; | 	name = QSE_NULL; | ||||||
| 	tag = QSE_NULL; | 	strtag = QSE_NULL; | ||||||
| 	dotted_curkey_len = (qse_size_t)-1; | 	dotted_curkey_len = (qse_size_t)-1; | ||||||
|  |  | ||||||
| 	parlist = xli->parlink->list; | 	parlist = xli->parlink->list; | ||||||
| @ -742,7 +742,7 @@ static int read_pair (qse_xli_t* xli) | |||||||
|  |  | ||||||
| 	if (key_alias) | 	if (key_alias) | ||||||
| 	{ | 	{ | ||||||
| 		/* the name part must be unique for the same key(s) */ | 		/* the alias part must be unique for the same key(s) */ | ||||||
| 		if (MATCH (xli, TOK_IDENT) || MATCH (xli, TOK_DQSTR) || MATCH (xli, TOK_SQSTR) || MATCH(xli, TOK_NSTR)) | 		if (MATCH (xli, TOK_IDENT) || MATCH (xli, TOK_DQSTR) || MATCH (xli, TOK_SQSTR) || MATCH(xli, TOK_NSTR)) | ||||||
| 		{ | 		{ | ||||||
| 			qse_xli_atom_t* atom; | 			qse_xli_atom_t* atom; | ||||||
| @ -783,10 +783,10 @@ static int read_pair (qse_xli_t* xli) | |||||||
| 	{ | 	{ | ||||||
| 		if (get_token (xli) <= -1) goto oops; | 		if (get_token (xli) <= -1) goto oops; | ||||||
|  |  | ||||||
| 		if (MATCH (xli, TOK_STRTAG)) | 		if ((xli->opt.trait & QSE_XLI_STRTAG) && MATCH (xli, TOK_TAG)) | ||||||
| 		{ | 		{ | ||||||
| 			tag = qse_strxdup (QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name), xli->mmgr); | 			strtag = qse_strxdup (QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name), xli->mmgr); | ||||||
| 			if (tag == QSE_NULL) | 			if (strtag == QSE_NULL) | ||||||
| 			{ | 			{ | ||||||
| 				qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);  | 				qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);  | ||||||
| 				goto oops; | 				goto oops; | ||||||
| @ -808,7 +808,7 @@ static int read_pair (qse_xli_t* xli) | |||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			/* add a new pair with the initial string segment */ | 			/* add a new pair with the initial string segment */ | ||||||
| 			pair = qse_xli_insertpairwithstr (xli, parlist, QSE_NULL, key.ptr, name, tag, QSE_STR_CSTR(xli->tok.name)); | 			pair = qse_xli_insertpairwithstr (xli, parlist, QSE_NULL, key.ptr, name, keytag, QSE_STR_CSTR(xli->tok.name), strtag); | ||||||
| 			if (pair == QSE_NULL) goto oops; | 			if (pair == QSE_NULL) goto oops; | ||||||
|  |  | ||||||
| 			segcount++; | 			segcount++; | ||||||
| @ -822,16 +822,16 @@ static int read_pair (qse_xli_t* xli) | |||||||
| 				{ | 				{ | ||||||
| 					if (get_token (xli) <= -1) goto oops; /* skip the comma */ | 					if (get_token (xli) <= -1) goto oops; /* skip the comma */ | ||||||
|  |  | ||||||
| 					if (tag)  | 					if (strtag)  | ||||||
| 					{ | 					{ | ||||||
| 						QSE_MMGR_FREE (xli->mmgr, tag); | 						QSE_MMGR_FREE (xli->mmgr, strtag); | ||||||
| 						tag = QSE_NULL; | 						strtag = QSE_NULL; | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 					if (MATCH (xli, TOK_STRTAG)) | 					if ((xli->opt.trait & QSE_XLI_STRTAG) && MATCH (xli, TOK_TAG)) | ||||||
| 					{ | 					{ | ||||||
| 						tag = qse_strxdup (QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name), xli->mmgr); | 						strtag = qse_strxdup (QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name), xli->mmgr); | ||||||
| 						if (tag == QSE_NULL) | 						if (strtag == QSE_NULL) | ||||||
| 						{ | 						{ | ||||||
| 							qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);  | 							qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);  | ||||||
| 							goto oops; | 							goto oops; | ||||||
| @ -847,7 +847,7 @@ static int read_pair (qse_xli_t* xli) | |||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 					/* add an additional segment to the string */ | 					/* add an additional segment to the string */ | ||||||
| 					curstrseg = qse_xli_addsegtostr (xli, curstrseg, tag, QSE_STR_CSTR(xli->tok.name)); | 					curstrseg = qse_xli_addsegtostr (xli, curstrseg, strtag, QSE_STR_CSTR(xli->tok.name)); | ||||||
| 					if (curstrseg == QSE_NULL) goto oops; | 					if (curstrseg == QSE_NULL) goto oops; | ||||||
|  |  | ||||||
| 					segcount++; | 					segcount++; | ||||||
| @ -896,7 +896,7 @@ static int read_pair (qse_xli_t* xli) | |||||||
| 		xli->tok_status &= ~TOK_STATUS_ENABLE_NSTR; | 		xli->tok_status &= ~TOK_STATUS_ENABLE_NSTR; | ||||||
|  |  | ||||||
| 		/* insert a pair with an empty list */ | 		/* insert a pair with an empty list */ | ||||||
| 		pair = qse_xli_insertpairwithemptylist (xli, parlist, QSE_NULL, key.ptr, name); | 		pair = qse_xli_insertpairwithemptylist (xli, parlist, QSE_NULL, key.ptr, name, keytag); | ||||||
| 		if (pair == QSE_NULL) goto oops; | 		if (pair == QSE_NULL) goto oops; | ||||||
| 	 | 	 | ||||||
| 		if (read_list (xli, (qse_xli_list_t*)pair->val) <= -1) goto oops; | 		if (read_list (xli, (qse_xli_list_t*)pair->val) <= -1) goto oops; | ||||||
| @ -937,7 +937,7 @@ static int read_pair (qse_xli_t* xli) | |||||||
| 		xli->tok_status &= ~TOK_STATUS_ENABLE_NSTR; | 		xli->tok_status &= ~TOK_STATUS_ENABLE_NSTR; | ||||||
|  |  | ||||||
| 		/* no value has been specified for the pair */ | 		/* no value has been specified for the pair */ | ||||||
| 		pair = qse_xli_insertpair (xli, parlist, QSE_NULL, key.ptr, name, (qse_xli_val_t*)&xli->root->xnil); | 		pair = qse_xli_insertpair (xli, parlist, QSE_NULL, key.ptr, name, keytag, (qse_xli_val_t*)&xli->root->xnil); | ||||||
| 		if (pair == QSE_NULL) goto oops; | 		if (pair == QSE_NULL) goto oops; | ||||||
|  |  | ||||||
| 		/* skip the semicolon */ | 		/* skip the semicolon */ | ||||||
| @ -951,7 +951,7 @@ static int read_pair (qse_xli_t* xli) | |||||||
| 		goto oops;	 | 		goto oops;	 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (tag) QSE_MMGR_FREE (xli->mmgr, tag); | 	if (strtag) QSE_MMGR_FREE (xli->mmgr, strtag); | ||||||
| 	QSE_MMGR_FREE (xli->mmgr, name); | 	QSE_MMGR_FREE (xli->mmgr, name); | ||||||
| 	QSE_MMGR_FREE (xli->mmgr, key.ptr); | 	QSE_MMGR_FREE (xli->mmgr, key.ptr); | ||||||
| 	qse_str_setlen (xli->dotted_curkey, dotted_curkey_len); | 	qse_str_setlen (xli->dotted_curkey, dotted_curkey_len); | ||||||
| @ -959,7 +959,7 @@ static int read_pair (qse_xli_t* xli) | |||||||
| 	 | 	 | ||||||
| oops: | oops: | ||||||
| 	xli->tok_status &= ~TOK_STATUS_ENABLE_NSTR; | 	xli->tok_status &= ~TOK_STATUS_ENABLE_NSTR; | ||||||
| 	if (tag) QSE_MMGR_FREE (xli->mmgr, tag); | 	if (strtag) QSE_MMGR_FREE (xli->mmgr, strtag); | ||||||
| 	if (name) QSE_MMGR_FREE (xli->mmgr, name); | 	if (name) QSE_MMGR_FREE (xli->mmgr, name); | ||||||
| 	if (key.ptr) QSE_MMGR_FREE (xli->mmgr, key.ptr); | 	if (key.ptr) QSE_MMGR_FREE (xli->mmgr, key.ptr); | ||||||
| 	if (dotted_curkey_len != (qse_size_t)-1) | 	if (dotted_curkey_len != (qse_size_t)-1) | ||||||
| @ -1003,9 +1003,38 @@ static int __read_list (qse_xli_t* xli) | |||||||
|  |  | ||||||
| 			if (begin_include (xli) <= -1) return -1; | 			if (begin_include (xli) <= -1) return -1; | ||||||
| 		} | 		} | ||||||
|  | 		else if ((xli->opt.trait & QSE_XLI_KEYTAG) && MATCH (xli, TOK_TAG)) | ||||||
|  | 		{ | ||||||
|  | 			qse_char_t* keytag; | ||||||
|  | 			int x; | ||||||
|  |  | ||||||
|  | 			keytag = qse_strxdup (QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name), xli->mmgr); | ||||||
|  | 			if (keytag == QSE_NULL) | ||||||
|  | 			{ | ||||||
|  | 				qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);  | ||||||
|  | 				return -1; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if (get_token(xli) <= -1)  | ||||||
|  | 			{ | ||||||
|  | 				QSE_MMGR_FREE (xli->mmgr, keytag); | ||||||
|  | 				return -1; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if (!MATCH(xli,TOK_IDENT)) | ||||||
|  | 			{ | ||||||
|  | 				QSE_MMGR_FREE (xli->mmgr, keytag); | ||||||
|  | 				qse_xli_seterror (xli, QSE_XLI_ENOKEY, QSE_NULL, &xli->tok.loc); | ||||||
|  | 				return -1; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			x = read_pair (xli, keytag); | ||||||
|  | 			QSE_MMGR_FREE (xli->mmgr, keytag); | ||||||
|  | 			if (x <= -1) return -1; | ||||||
|  | 		} | ||||||
| 		else if (MATCH (xli, TOK_IDENT)) | 		else if (MATCH (xli, TOK_IDENT)) | ||||||
| 		{ | 		{ | ||||||
| 			if (read_pair (xli) <= -1) return -1; | 			if (read_pair (xli, QSE_NULL) <= -1) return -1; | ||||||
| 		} | 		} | ||||||
| 		else if (MATCH (xli, TOK_TEXT)) | 		else if (MATCH (xli, TOK_TEXT)) | ||||||
| 		{ | 		{ | ||||||
|  | |||||||
| @ -194,8 +194,16 @@ static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth) | |||||||
| 			{ | 			{ | ||||||
| 				qse_xli_pair_t* pair = (qse_xli_pair_t*)curatom; | 				qse_xli_pair_t* pair = (qse_xli_pair_t*)curatom; | ||||||
| 				 | 				 | ||||||
| 				if (write_indentation (xli, depth) <= -1 || | 				if (write_indentation (xli, depth) <= -1) return -1; | ||||||
| 				    write_to_current_stream (xli, pair->key, qse_strlen(pair->key), 0) <= -1) return -1; |  | ||||||
|  | 				if (pair->tag) | ||||||
|  | 				{ | ||||||
|  | 					if (write_to_current_stream (xli, QSE_T("["), 1, 0) <= -1 || | ||||||
|  | 					    write_to_current_stream (xli, pair->tag, qse_strlen(pair->tag), 0) <= -1 ||  | ||||||
|  | 					    write_to_current_stream (xli, QSE_T("]"), 1, 0) <= -1) return -1; | ||||||
|  | 				} | ||||||
|  | 						 | ||||||
|  | 				if (write_to_current_stream (xli, pair->key, qse_strlen(pair->key), 0) <= -1) return -1; | ||||||
|  |  | ||||||
| 				if (pair->alias)  | 				if (pair->alias)  | ||||||
| 				{ | 				{ | ||||||
|  | |||||||
| @ -225,18 +225,20 @@ static void insert_atom ( | |||||||
|  |  | ||||||
| static qse_xli_pair_t* insert_pair ( | static qse_xli_pair_t* insert_pair ( | ||||||
| 	qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer, | 	qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer, | ||||||
| 	const qse_cstr_t* key, const qse_cstr_t* alias, qse_xli_val_t* value) | 	const qse_cstr_t* key, const qse_cstr_t* alias, const qse_cstr_t* keytag, qse_xli_val_t* value) | ||||||
| { | { | ||||||
| 	qse_xli_pair_t* pair; | 	qse_xli_pair_t* pair; | ||||||
| 	qse_size_t alen; | 	qse_size_t alen, tlen; | ||||||
| 	qse_char_t* kptr, * nptr; | 	qse_char_t* kptr, * nptr; | ||||||
|  |  | ||||||
| 	alen = alias? alias->len: 0; | 	alen = alias? alias->len: 0; | ||||||
|  | 	tlen = keytag? keytag->len: 0; | ||||||
|  |  | ||||||
| 	pair = qse_xli_callocmem (xli,  | 	pair = qse_xli_callocmem (xli,  | ||||||
| 		QSE_SIZEOF(*pair) + xli->opt.pair_xtnsize + | 		QSE_SIZEOF(*pair) + xli->opt.pair_xtnsize + | ||||||
| 		((key->len + 1) * QSE_SIZEOF(*key->ptr)) +  | 		((key->len + 1) * QSE_SIZEOF(*key->ptr)) +  | ||||||
| 		((alen + 1) * QSE_SIZEOF(*alias->ptr))); | 		((alen + 1) * QSE_SIZEOF(*alias->ptr)) + | ||||||
|  | 		((tlen + 1) * QSE_SIZEOF(*keytag->ptr))); | ||||||
| 	if (pair == QSE_NULL) return QSE_NULL; | 	if (pair == QSE_NULL) return QSE_NULL; | ||||||
|  |  | ||||||
| 	kptr = (qse_char_t*)((qse_uint8_t*)(pair + 1) + xli->opt.pair_xtnsize); | 	kptr = (qse_char_t*)((qse_uint8_t*)(pair + 1) + xli->opt.pair_xtnsize); | ||||||
| @ -250,6 +252,12 @@ static qse_xli_pair_t* insert_pair ( | |||||||
| 		qse_strcpy (nptr, alias->ptr); | 		qse_strcpy (nptr, alias->ptr); | ||||||
| 		pair->alias = nptr; | 		pair->alias = nptr; | ||||||
| 	} | 	} | ||||||
|  | 	if (keytag) | ||||||
|  | 	{ | ||||||
|  | 		nptr = kptr + key->len + 1 + alen + 1; | ||||||
|  | 		qse_strcpy (nptr, keytag->ptr); | ||||||
|  | 		pair->tag = nptr; | ||||||
|  | 	} | ||||||
| 	pair->val = value; /* take note of no duplication here */ | 	pair->val = value; /* take note of no duplication here */ | ||||||
|  |  | ||||||
| 	insert_atom (xli, parent, peer, (qse_xli_atom_t*)pair); | 	insert_atom (xli, parent, peer, (qse_xli_atom_t*)pair); | ||||||
| @ -259,31 +267,35 @@ static qse_xli_pair_t* insert_pair ( | |||||||
|  |  | ||||||
| qse_xli_pair_t* qse_xli_insertpair ( | qse_xli_pair_t* qse_xli_insertpair ( | ||||||
| 	qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer, | 	qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer, | ||||||
| 	const qse_char_t* key, const qse_char_t* alias, qse_xli_val_t* value) | 	const qse_char_t* key, const qse_char_t* alias,  | ||||||
|  | 	const qse_char_t* keytag, qse_xli_val_t* value) | ||||||
| { | { | ||||||
| 	qse_cstr_t k; | 	qse_cstr_t k; | ||||||
|  | 	qse_cstr_t a, * ap = QSE_NULL; | ||||||
|  | 	qse_cstr_t t, * tp = QSE_NULL; | ||||||
|  |  | ||||||
| 	k.ptr = key; | 	k.ptr = key; | ||||||
| 	k.len = qse_strlen (key); | 	k.len = qse_strlen (key); | ||||||
|  |  | ||||||
| 	if (alias) | 	if (alias) | ||||||
| 	{ | 	{ | ||||||
| 		qse_cstr_t a; |  | ||||||
|  |  | ||||||
| 		a.ptr = alias; | 		a.ptr = alias; | ||||||
| 		a.len = qse_strlen (alias); | 		a.len = qse_strlen (alias); | ||||||
|  | 		ap = &a; | ||||||
| 		return insert_pair (xli, parent, peer, &k, &a, value); |  | ||||||
| 	} | 	} | ||||||
| 	else | 	if (keytag) | ||||||
| 	{ | 	{ | ||||||
| 		return insert_pair (xli, parent, peer, &k, QSE_NULL, value); | 		t.ptr = keytag; | ||||||
|  | 		t.len = qse_strlen (keytag); | ||||||
|  | 		tp = &t; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	return insert_pair (xli, parent, peer, &k, ap, tp, value); | ||||||
| } | } | ||||||
|  |  | ||||||
| qse_xli_pair_t* qse_xli_insertpairwithemptylist ( | qse_xli_pair_t* qse_xli_insertpairwithemptylist ( | ||||||
| 	qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer, | 	qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer, | ||||||
| 	const qse_char_t* key, const qse_char_t* alias) | 	const qse_char_t* key, const qse_char_t* alias, const qse_char_t* keytag) | ||||||
| { | { | ||||||
| 	qse_xli_list_t* val; | 	qse_xli_list_t* val; | ||||||
| 	qse_xli_pair_t* tmp; | 	qse_xli_pair_t* tmp; | ||||||
| @ -292,22 +304,22 @@ qse_xli_pair_t* qse_xli_insertpairwithemptylist ( | |||||||
| 	if (val == QSE_NULL) return QSE_NULL; | 	if (val == QSE_NULL) return QSE_NULL; | ||||||
|  |  | ||||||
| 	val->type = QSE_XLI_LIST; | 	val->type = QSE_XLI_LIST; | ||||||
| 	tmp = qse_xli_insertpair (xli, parent, peer, key, alias, (qse_xli_val_t*)val);	 | 	tmp = qse_xli_insertpair (xli, parent, peer, key, alias, keytag, (qse_xli_val_t*)val);	 | ||||||
| 	if (tmp == QSE_NULL) qse_xli_freemem (xli, val); | 	if (tmp == QSE_NULL) qse_xli_freemem (xli, val); | ||||||
| 	return tmp; | 	return tmp; | ||||||
| } | } | ||||||
|  |  | ||||||
| qse_xli_pair_t* qse_xli_insertpairwithstr ( | qse_xli_pair_t* qse_xli_insertpairwithstr ( | ||||||
| 	qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer, | 	qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer, | ||||||
| 	const qse_char_t* key, const qse_char_t* alias,  | 	const qse_char_t* key, const qse_char_t* alias, const qse_char_t* keytag, | ||||||
| 	const qse_char_t* tag, const qse_cstr_t* value) | 	const qse_cstr_t* value, const qse_char_t* strtag) | ||||||
| { | { | ||||||
| 	qse_xli_str_t* val; | 	qse_xli_str_t* val; | ||||||
| 	qse_xli_pair_t* tmp; | 	qse_xli_pair_t* tmp; | ||||||
| 	qse_size_t reqlen; | 	qse_size_t reqlen; | ||||||
|  |  | ||||||
| 	reqlen = QSE_SIZEOF(*val) + ((value->len + 1) * QSE_SIZEOF(*value->ptr)); | 	reqlen = QSE_SIZEOF(*val) + ((value->len + 1) * QSE_SIZEOF(*value->ptr)); | ||||||
| 	if (tag) reqlen += (qse_strlen (tag) + 1) * QSE_SIZEOF(*tag); | 	if (strtag) reqlen += (qse_strlen (strtag) + 1) * QSE_SIZEOF(*strtag); | ||||||
|  |  | ||||||
| 	val = qse_xli_callocmem (xli, reqlen); | 	val = qse_xli_callocmem (xli, reqlen); | ||||||
| 	if (val == QSE_NULL) return QSE_NULL; | 	if (val == QSE_NULL) return QSE_NULL; | ||||||
| @ -318,20 +330,20 @@ qse_xli_pair_t* qse_xli_insertpairwithstr ( | |||||||
| 	val->ptr = (const qse_char_t*)(val + 1); | 	val->ptr = (const qse_char_t*)(val + 1); | ||||||
| 	val->len = value->len; | 	val->len = value->len; | ||||||
|  |  | ||||||
| 	if (tag) | 	if (strtag) | ||||||
| 	{ | 	{ | ||||||
| 		val->tag = val->ptr + val->len + 1; | 		val->tag = val->ptr + val->len + 1; | ||||||
| 		qse_strcpy ((qse_char_t*)val->tag, tag); | 		qse_strcpy ((qse_char_t*)val->tag, strtag); | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	tmp = qse_xli_insertpair (xli, parent, peer, key, alias, (qse_xli_val_t*)val);	 | 	tmp = qse_xli_insertpair (xli, parent, peer, key, alias, keytag, (qse_xli_val_t*)val);	 | ||||||
| 	if (tmp == QSE_NULL) qse_xli_freemem (xli, val); | 	if (tmp == QSE_NULL) qse_xli_freemem (xli, val); | ||||||
| 	return tmp; | 	return tmp; | ||||||
| } | } | ||||||
|  |  | ||||||
| qse_xli_pair_t* qse_xli_insertpairwithstrs ( | qse_xli_pair_t* qse_xli_insertpairwithstrs ( | ||||||
| 	qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer, | 	qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer, | ||||||
| 	const qse_char_t* key, const qse_char_t* alias,  | 	const qse_char_t* key, const qse_char_t* alias, const qse_char_t* keytag, | ||||||
| 	const qse_cstr_t value[], qse_size_t count) | 	const qse_cstr_t value[], qse_size_t count) | ||||||
| { | { | ||||||
| 	qse_xli_pair_t* tmp; | 	qse_xli_pair_t* tmp; | ||||||
| @ -344,7 +356,7 @@ qse_xli_pair_t* qse_xli_insertpairwithstrs ( | |||||||
| 		return QSE_NULL; | 		return QSE_NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	tmp = qse_xli_insertpairwithstr (xli, parent, peer, key, alias, QSE_NULL, &value[0]); | 	tmp = qse_xli_insertpairwithstr (xli, parent, peer, key, alias, keytag, &value[0], QSE_NULL); | ||||||
| 	if (tmp == QSE_NULL) return QSE_NULL; | 	if (tmp == QSE_NULL) return QSE_NULL; | ||||||
|  |  | ||||||
| 	str = (qse_xli_str_t*)tmp->val; | 	str = (qse_xli_str_t*)tmp->val; | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user