added QSE_XLI_STRTAG and changed related functions and defintions
This commit is contained in:
		| @ -45,8 +45,10 @@ const qse_char_t* qse_xli_dflerrstr ( | ||||
| 		QSE_T("right-brace expected in place of '${0}'"), | ||||
| 		QSE_T("pair value expected in place of '${0}'"), | ||||
| 		QSE_T("string not closed"), | ||||
| 		QSE_T("string tag not closed"), | ||||
| 		QSE_T("'@include' not followed by a string"), | ||||
| 		QSE_T("invalid character '${0}'"), | ||||
| 		QSE_T("invalid tag character '${0}'"), | ||||
| 		QSE_T("'${0}' not recognized"), | ||||
| 		QSE_T("@ not followed by a valid word"), | ||||
| 		QSE_T("invalid identifier '${0}'"), | ||||
|  | ||||
| @ -60,6 +60,7 @@ enum tok_t | ||||
| 	TOK_NSTR, | ||||
| 	TOK_IDENT, | ||||
| 	TOK_TEXT, | ||||
| 	TOK_STRTAG, | ||||
|  | ||||
| 	__TOKEN_COUNT__ | ||||
| }; | ||||
| @ -431,7 +432,7 @@ retry: | ||||
| 		if (!QSE_ISALPHA (c)) | ||||
| 		{ | ||||
| 			/* this directive is empty, not followed by a valid word */ | ||||
| 			qse_xli_seterror (xli, QSE_XLI_EXKWEM, QSE_NULL, &xli->tok.loc); | ||||
| 			qse_xli_seterror (xli, QSE_XLI_EXKWEM, QSE_NULL, &tok->loc); | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| @ -448,7 +449,7 @@ retry: | ||||
| 		if (type == TOK_IDENT) | ||||
| 		{ | ||||
| 			/* this keyword/directive is not recognized */ | ||||
| 			qse_xli_seterror (xli, QSE_XLI_EXKWNR, QSE_STR_CSTR(xli->tok.name), &xli->tok.loc); | ||||
| 			qse_xli_seterror (xli, QSE_XLI_EXKWNR, QSE_STR_CSTR(tok->name), &tok->loc); | ||||
| 			return -1; | ||||
| 		} | ||||
| 		SET_TOKEN_TYPE (xli, tok, type); | ||||
| @ -484,7 +485,7 @@ retry: | ||||
| 		if (lead_digit && all_digits) | ||||
| 		{ | ||||
| 			/* if an identifier begins with a digit, it must contain a non-digits character */ | ||||
| 			qse_xli_seterror (xli, QSE_XLI_EIDENT, QSE_STR_CSTR(xli->tok.name), &xli->tok.loc); | ||||
| 			qse_xli_seterror (xli, QSE_XLI_EIDENT, QSE_STR_CSTR(tok->name), &tok->loc); | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| @ -512,7 +513,7 @@ retry: | ||||
| 			if (c == QSE_CHAR_EOF) | ||||
| 			{ | ||||
| 				/* the string is not closed */ | ||||
| 				qse_xli_seterror (xli, QSE_XLI_ESTRNC, QSE_NULL, &xli->tok.loc); | ||||
| 				qse_xli_seterror (xli, QSE_XLI_ESTRNC, QSE_NULL, &tok->loc); | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| @ -540,7 +541,7 @@ retry: | ||||
| 			if (c == QSE_CHAR_EOF) | ||||
| 			{ | ||||
| 				/* the string is not closed */ | ||||
| 				qse_xli_seterror (xli, QSE_XLI_ESTRNC, QSE_NULL, &xli->tok.loc); | ||||
| 				qse_xli_seterror (xli, QSE_XLI_ESTRNC, QSE_NULL, &tok->loc); | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| @ -568,6 +569,46 @@ retry: | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	else if ((xli->opt.trait & QSE_XLI_STRTAG) && c == QSE_T('[')) | ||||
| 	{ | ||||
| 		/* a string tag is a bracketed word placed in front of a string value. | ||||
| 		 *   A = [tg] "abc";  | ||||
| 		 * "tg" is stored into the tag field of qse_xli_str_t.  | ||||
| 		 */ | ||||
|  | ||||
| 		SET_TOKEN_TYPE (xli, tok, TOK_STRTAG); | ||||
| 		 | ||||
| 		while (1) | ||||
| 		{ | ||||
| 			GET_CHAR_TO (xli, c); | ||||
|  | ||||
| 			if (c == QSE_CHAR_EOF) | ||||
| 			{ | ||||
| 				/* the string tag is not closed */ | ||||
| 				qse_xli_seterror (xli, QSE_XLI_ETAGNC, QSE_NULL, &xli->tok.loc); | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| 			if (c == QSE_T(']')) | ||||
| 			{ | ||||
| 				/* terminating quote */ | ||||
| 				GET_CHAR (xli); | ||||
| 				break; | ||||
| 			} | ||||
|  | ||||
| 			if (!QSE_ISALNUM(c)) | ||||
| 			{ | ||||
| 				qse_char_t cc = (qse_char_t)c; | ||||
| 				qse_cstr_t ea; | ||||
| 				ea.ptr = &cc; | ||||
| 				ea.len = 1; | ||||
| 				qse_xli_seterror (xli, QSE_XLI_ETAGCHR, &ea, &tok->loc); | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| 			ADD_TOKEN_CHAR (xli, tok, c); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		n = get_symbols (xli, c, tok); | ||||
| @ -625,12 +666,14 @@ static int read_pair (qse_xli_t* xli) | ||||
| 	qse_xli_pair_t* pair; | ||||
| 	qse_xli_list_t* parlist; | ||||
| 	qse_size_t dotted_curkey_len; | ||||
| 	qse_char_t* tag; | ||||
|  | ||||
| 	qse_xli_scm_t* scm = QSE_NULL; | ||||
| 	int key_nodup = 0, key_alias = 0; | ||||
|  | ||||
| 	key.ptr = QSE_NULL; | ||||
| 	name = QSE_NULL; | ||||
| 	tag = QSE_NULL; | ||||
| 	dotted_curkey_len = (qse_size_t)-1; | ||||
|  | ||||
| 	parlist = xli->parlink->list; | ||||
| @ -740,6 +783,18 @@ static int read_pair (qse_xli_t* xli) | ||||
| 	{ | ||||
| 		if (get_token (xli) <= -1) goto oops; | ||||
|  | ||||
| 		if (MATCH (xli, TOK_STRTAG)) | ||||
| 		{ | ||||
| 			tag = qse_strxdup (QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name), xli->mmgr); | ||||
| 			if (tag == QSE_NULL) | ||||
| 			{ | ||||
| 				qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);  | ||||
| 				goto oops; | ||||
| 			} | ||||
|  | ||||
| 			if (get_token (xli) <= -1) goto oops; | ||||
| 		} | ||||
|  | ||||
| 		if (MATCH (xli, TOK_SQSTR) || MATCH (xli, TOK_DQSTR) || MATCH(xli, TOK_NSTR) || MATCH (xli, TOK_IDENT)) | ||||
| 		{ | ||||
| 			qse_xli_str_t* curstrseg; | ||||
| @ -753,7 +808,7 @@ static int read_pair (qse_xli_t* xli) | ||||
| 			} | ||||
|  | ||||
| 			/* add a new pair with the initial string segment */ | ||||
| 			pair = qse_xli_insertpairwithstr (xli, parlist, QSE_NULL, key.ptr, name, QSE_STR_CSTR(xli->tok.name)); | ||||
| 			pair = qse_xli_insertpairwithstr (xli, parlist, QSE_NULL, key.ptr, name, tag, QSE_STR_CSTR(xli->tok.name)); | ||||
| 			if (pair == QSE_NULL) goto oops; | ||||
|  | ||||
| 			segcount++; | ||||
| @ -767,6 +822,24 @@ static int read_pair (qse_xli_t* xli) | ||||
| 				{ | ||||
| 					if (get_token (xli) <= -1) goto oops; /* skip the comma */ | ||||
|  | ||||
| 					if (tag)  | ||||
| 					{ | ||||
| 						QSE_MMGR_FREE (xli->mmgr, tag); | ||||
| 						tag = QSE_NULL; | ||||
| 					} | ||||
|  | ||||
| 					if (MATCH (xli, TOK_STRTAG)) | ||||
| 					{ | ||||
| 						tag = qse_strxdup (QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name), xli->mmgr); | ||||
| 						if (tag == QSE_NULL) | ||||
| 						{ | ||||
| 							qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);  | ||||
| 							goto oops; | ||||
| 						} | ||||
| 						 | ||||
| 						if (get_token (xli) <= -1) goto oops;  | ||||
| 					} | ||||
|  | ||||
| 					if (!MATCH (xli, TOK_SQSTR) && !MATCH (xli, TOK_DQSTR) && !MATCH (xli, TOK_NSTR) && !MATCH (xli, TOK_IDENT)) | ||||
| 					{ | ||||
| 						qse_xli_seterror (xli, QSE_XLI_ESYNTAX, QSE_NULL, &xli->tok.loc); | ||||
| @ -774,7 +847,7 @@ static int read_pair (qse_xli_t* xli) | ||||
| 					} | ||||
|  | ||||
| 					/* add an additional segment to the string */ | ||||
| 					curstrseg = qse_xli_addsegtostr (xli, curstrseg, QSE_STR_CSTR(xli->tok.name)); | ||||
| 					curstrseg = qse_xli_addsegtostr (xli, curstrseg, tag, QSE_STR_CSTR(xli->tok.name)); | ||||
| 					if (curstrseg == QSE_NULL) goto oops; | ||||
|  | ||||
| 					segcount++; | ||||
| @ -878,6 +951,7 @@ static int read_pair (qse_xli_t* xli) | ||||
| 		goto oops;	 | ||||
| 	} | ||||
|  | ||||
| 	if (tag) QSE_MMGR_FREE (xli->mmgr, tag); | ||||
| 	QSE_MMGR_FREE (xli->mmgr, name); | ||||
| 	QSE_MMGR_FREE (xli->mmgr, key.ptr); | ||||
| 	qse_str_setlen (xli->dotted_curkey, dotted_curkey_len); | ||||
| @ -885,6 +959,7 @@ static int read_pair (qse_xli_t* xli) | ||||
| 	 | ||||
| oops: | ||||
| 	xli->tok_status &= ~TOK_STATUS_ENABLE_NSTR; | ||||
| 	if (tag) QSE_MMGR_FREE (xli->mmgr, tag); | ||||
| 	if (name) QSE_MMGR_FREE (xli->mmgr, name); | ||||
| 	if (key.ptr) QSE_MMGR_FREE (xli->mmgr, key.ptr); | ||||
| 	if (dotted_curkey_len != (qse_size_t)-1) | ||||
|  | ||||
| @ -217,6 +217,13 @@ static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth) | ||||
| 						if (write_to_current_stream (xli, QSE_T(" = "), 3, 0) <= -1) return -1; | ||||
| 						while (1) | ||||
| 						{ | ||||
| 							if (str->tag) | ||||
| 							{ | ||||
| 								if (write_to_current_stream (xli, QSE_T("["), 1, 0) <= -1 || | ||||
| 								    write_to_current_stream (xli, str->tag, qse_strlen(str->tag), 0) <= -1 ||  | ||||
| 								    write_to_current_stream (xli, QSE_T("]"), 1, 0) <= -1) return -1; | ||||
| 							} | ||||
| 						 | ||||
| 							if (write_to_current_stream (xli, QSE_T("\""), 1, 0) <= -1 || | ||||
| 							    write_to_current_stream (xli, str->ptr, str->len, 1) <= -1 || | ||||
| 							    write_to_current_stream (xli, QSE_T("\""), 1, 0) <= -1) return -1; | ||||
|  | ||||
| @ -299,12 +299,17 @@ qse_xli_pair_t* qse_xli_insertpairwithemptylist ( | ||||
|  | ||||
| qse_xli_pair_t* qse_xli_insertpairwithstr ( | ||||
| 	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_cstr_t* value) | ||||
| 	const qse_char_t* key, const qse_char_t* alias,  | ||||
| 	const qse_char_t* tag, const qse_cstr_t* value) | ||||
| { | ||||
| 	qse_xli_str_t* val; | ||||
| 	qse_xli_pair_t* tmp; | ||||
| 	qse_size_t reqlen; | ||||
|  | ||||
| 	val = qse_xli_callocmem (xli, 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); | ||||
|  | ||||
| 	val = qse_xli_callocmem (xli, reqlen); | ||||
| 	if (val == QSE_NULL) return QSE_NULL; | ||||
|  | ||||
| 	val->type = QSE_XLI_STR; | ||||
| @ -313,6 +318,12 @@ qse_xli_pair_t* qse_xli_insertpairwithstr ( | ||||
| 	val->ptr = (const qse_char_t*)(val + 1); | ||||
| 	val->len = value->len; | ||||
|  | ||||
| 	if (tag) | ||||
| 	{ | ||||
| 		val->tag = val->ptr + val->len + 1; | ||||
| 		qse_strcpy ((qse_char_t*)val->tag, tag); | ||||
| 	} | ||||
| 	 | ||||
| 	tmp = qse_xli_insertpair (xli, parent, peer, key, alias, (qse_xli_val_t*)val);	 | ||||
| 	if (tmp == QSE_NULL) qse_xli_freemem (xli, val); | ||||
| 	return tmp; | ||||
| @ -333,13 +344,13 @@ qse_xli_pair_t* qse_xli_insertpairwithstrs ( | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	tmp = qse_xli_insertpairwithstr (xli, parent, peer, key, alias, &value[0]); | ||||
| 	tmp = qse_xli_insertpairwithstr (xli, parent, peer, key, alias, QSE_NULL, &value[0]); | ||||
| 	if (tmp == QSE_NULL) return QSE_NULL; | ||||
|  | ||||
| 	str = (qse_xli_str_t*)tmp->val; | ||||
| 	for (i = 1; i < count; i++) | ||||
| 	{ | ||||
| 		str = qse_xli_addsegtostr (xli, str, &value[i]);			 | ||||
| 		str = qse_xli_addsegtostr (xli, str, QSE_NULL, &value[i]);			 | ||||
| 		if (str == QSE_NULL) | ||||
| 		{ | ||||
| 			free_atom (xli->root, (qse_xli_atom_t*)tmp); | ||||
| @ -811,19 +822,28 @@ noent: | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| qse_xli_str_t* qse_xli_addsegtostr ( | ||||
| 	qse_xli_t* xli, qse_xli_str_t* str, const qse_cstr_t* value) | ||||
| 	qse_xli_t* xli, qse_xli_str_t* str, const qse_char_t* tag, const qse_cstr_t* value) | ||||
| { | ||||
| 	qse_xli_str_t* val; | ||||
| 	qse_size_t reqlen; | ||||
|  | ||||
| 	val = qse_xli_callocmem (xli, 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); | ||||
|  | ||||
| 	val = qse_xli_callocmem (xli, reqlen); | ||||
| 	if (val == QSE_NULL) return QSE_NULL; | ||||
|  | ||||
| 	val->type = QSE_XLI_STR; | ||||
| 	qse_strncpy ((qse_char_t*)(val + 1), value->ptr, value->len); | ||||
| 	val->ptr = (const qse_char_t*)(val + 1); | ||||
| 	val->len = value->len; | ||||
|  | ||||
| 	if (tag) | ||||
| 	{ | ||||
| 		val->tag = val->ptr + val->len + 1; | ||||
| 		qse_strcpy ((qse_char_t*)val->tag, tag); | ||||
| 	} | ||||
| 		 | ||||
| 	val->next = str->next; | ||||
| 	str->next = val; | ||||
|  | ||||
		Reference in New Issue
	
	Block a user