Esempio n. 1
0
/**
 * Parse a string according to a property type, and allocate a raw value to the static memory
 *
 * @param action Action to initialize
 * @param node Current node we are parsing, only used for error message
 * @param property Type of the value to parse, if nullptr the string is not stored as string
 * @param string String value to parse
 * @return True if the action is initialized
 * @todo remove node param and catch error where we call that function
 */
bool UI_InitRawActionValue (uiAction_t* action, uiNode_t* node, const value_t* property, const char* string)
{
	if (property == nullptr) {
		action->type = EA_VALUE_STRING;
		action->d.terminal.d1.data = UI_AllocStaticString(string, 0);
		action->d.terminal.d2.integer = 0;
		return true;
	}

	if (property->type == V_UI_SPRITEREF) {
		uiSprite_t* sprite = UI_GetSpriteByName(string);
		if (sprite == nullptr) {
			Com_Printf("UI_ParseSetAction: sprite '%s' not found (%s)\n", string, UI_GetPath(node));
			return false;
		}
		action->type = EA_VALUE_RAW;
		action->d.terminal.d1.data = sprite;
		action->d.terminal.d2.integer = property->type;
		return true;
	} else {
		const int baseType = property->type & V_UI_MASK;
		if (baseType != 0 && baseType != V_UI_CVAR) {
			Com_Printf("UI_ParseRawValue: setter for property '%s' (type %d, 0x%X) is not supported (%s)\n", property->string, property->type, property->type, UI_GetPath(node));
			return false;
		}
		ui_global.curadata = (byte*) Com_AlignPtr(ui_global.curadata, (valueTypes_t) (property->type & V_BASETYPEMASK));
		action->type = EA_VALUE_RAW;
		action->d.terminal.d1.data = ui_global.curadata;
		action->d.terminal.d2.integer = property->type;
		/** @todo we should hide use of ui_global.curadata */
		ui_global.curadata += Com_EParseValue(ui_global.curadata, string, (valueTypes_t) (property->type & V_BASETYPEMASK), 0, property->size);
		return true;
	}
}
Esempio n. 2
0
/**
 * @brief Parse a property value
 * @todo don't read the next token (need to change the script language)
 */
static bool UI_ParseProperty (void* object, const value_t* property, const char* objectName, const char** text, const char** token)
{
	const char* errhead = "UI_ParseProperty: unexpected end of file (object";
	static const char* notWellFormedValue = "UI_ParseProperty: \"%s\" is not a well formed node name (it must be quoted, uppercase const, a number, or prefixed with '*')\n";
	size_t bytes;
	int result;
	const int specialType = property->type & V_UI_MASK;

	if (property->type == V_NULL) {
		return false;
	}

	switch (specialType) {
	case V_NOT_UI:	/* common type */

		*token = Com_EParse(text, errhead, objectName);
		if (!*text)
			return false;
		if (!UI_TokenIsValue(*token, Com_GetType(text) == TT_QUOTED_WORD)) {
			Com_Printf(notWellFormedValue, *token);
			return false;
		}

		if (property->type == V_TRANSLATION_STRING) {
			/* selectbox values are static arrays */
			char* const target = Com_GetValue<char[]>(object, property);
			const char* translatableToken = *token;
			assert(property->size);
			if (translatableToken[0] == '_')
				translatableToken++;
			Q_strncpyz(target, translatableToken, property->size);
		} else {
			result = Com_ParseValue(object, *token, property->type, property->ofs, property->size, &bytes);
			if (result != RESULT_OK) {
				Com_Printf("UI_ParseProperty: Invalid value for property '%s': %s\n", property->string, Com_GetLastParseError());
				return false;
			}
		}
		break;

	case V_UI_REF:
		*token = Com_EParse(text, errhead, objectName);
		if (!*text)
			return false;
		if (!UI_TokenIsValue(*token, Com_GetType(text) == TT_QUOTED_WORD)) {
			Com_Printf(notWellFormedValue, *token);
			return false;
		}

		/* a reference to data is handled like this */
		ui_global.curadata = (byte*) Com_AlignPtr(ui_global.curadata, (valueTypes_t) (property->type & V_BASETYPEMASK));
		Com_GetValue<byte*>(object, property) = ui_global.curadata;

		/** @todo check for the moment its not a cvar */
		assert((*token)[0] != '*');

		/* sanity check */
		if ((property->type & V_BASETYPEMASK) == V_STRING && strlen(*token) > MAX_VAR - 1) {
			Com_Printf("UI_ParseProperty: Value '%s' is too long (key %s)\n", *token, property->string);
			return false;
		}

		result = Com_ParseValue(ui_global.curadata, *token, (valueTypes_t) (property->type & V_BASETYPEMASK), 0, property->size, &bytes);
		if (result != RESULT_OK) {
			Com_Printf("UI_ParseProperty: Invalid value for property '%s': %s\n", property->string, Com_GetLastParseError());
			return false;
		}
		ui_global.curadata += bytes;

		break;

	case V_UI_CVAR:	/* common type */
		*token = Com_EParse(text, errhead, objectName);
		if (!*text)
			return false;
		if (!UI_TokenIsValue(*token, Com_GetType(text) == TT_QUOTED_WORD)) {
			Com_Printf(notWellFormedValue, *token);
			return false;
		}

		/* references are parsed as string */
		if ((*token)[0] == '*') {
			/* a reference to data */
			ui_global.curadata = (byte*) Com_AlignPtr(ui_global.curadata, V_STRING);
			Com_GetValue<byte*>(object, property) = ui_global.curadata;

			/* sanity check */
			if (strlen(*token) > MAX_VAR - 1) {
				Com_Printf("UI_ParseProperty: Value '%s' is too long (key %s)\n", *token, property->string);
				return false;
			}

			result = Com_ParseValue(ui_global.curadata, *token, V_STRING, 0, 0, &bytes);
			if (result != RESULT_OK) {
				Com_Printf("UI_ParseProperty: Invalid value for property '%s': %s\n", property->string, Com_GetLastParseError());
				return false;
			}
			ui_global.curadata += bytes;
		} else {
			/* a reference to data */
			ui_global.curadata = (byte*) Com_AlignPtr(ui_global.curadata, (valueTypes_t)(property->type & V_BASETYPEMASK));
			Com_GetValue<byte*>(object, property) = ui_global.curadata;

			/* sanity check */
			if ((property->type & V_BASETYPEMASK) == V_STRING && strlen(*token) > MAX_VAR - 1) {
				Com_Printf("UI_ParseProperty: Value '%s' is too long (key %s)\n", *token, property->string);
				return false;
			}

			result = Com_ParseValue(ui_global.curadata, *token, (valueTypes_t)(property->type & V_BASETYPEMASK), 0, property->size, &bytes);
			if (result != RESULT_OK) {
				Com_Printf("UI_ParseProperty: Invalid value for property '%s': %s\n", property->string, Com_GetLastParseError());
				return false;
			}
			ui_global.curadata += bytes;
		}
		break;

	case V_UI:

		switch ((int)property->type) {
		case V_UI_ACTION:
			result = UI_ParseEventProperty(static_cast<uiNode_t*>(object), property, text, token, errhead);
			if (!result)
				return false;
			break;

		case V_UI_EXCLUDERECT:
			result = UI_ParseExcludeRect(static_cast<uiNode_t*>(object), text, token, errhead);
			if (!result)
				return false;
			break;

		case V_UI_SPRITEREF:
			{
				*token = Com_EParse(text, errhead, objectName);
				if (!*text)
					return false;

				uiSprite_t const*& sprite = Com_GetValue<uiSprite_t const*>(object, property);
				sprite = UI_GetSpriteByName(*token);
				if (!sprite) {
					Com_Printf("UI_ParseProperty: sprite '%s' not found (object %s)\n", *token, objectName);
				}
			}
			break;

		case V_UI_IF:
			{
				*token = Com_EParse(text, errhead, objectName);
				if (!*text)
					return false;

				uiAction_t*& expression = Com_GetValue<uiAction_t*>(object, property);
				expression = UI_AllocStaticStringCondition(*token);
				if (!expression)
					return false;
			}
			break;

		case V_UI_DATAID:
			{
				*token = Com_EParse(text, errhead, objectName);
				if (!*text)
					return false;

				int& dataId = Com_GetValue<int>(object, property);
				dataId = UI_GetDataIDByName(*token);
				if (dataId < 0) {
					Com_Printf("UI_ParseProperty: Could not find shared data ID '%s' (%s@%s)\n",
							*token, objectName, property->string);
					return false;
				}
			}
			break;

		default:
			Com_Printf("UI_ParseProperty: unknown property type '%d' (0x%X) (%s@%s)\n",
					property->type, property->type, objectName, property->string);
			return false;
		}
		break;

	default:
		Com_Printf("UI_ParseProperties: unknown property type '%d' (0x%X) (%s@%s)\n",
				property->type, property->type, objectName, property->string);
		return false;
	}

	return true;
}
Esempio n. 3
0
static void CL_ParsePtlCmds (const char *name, const char **text)
{
	ptlCmd_t *pc;
	const value_t *pp;
	const char *errhead = "CL_ParsePtlCmds: unexpected end of file";
	const char *token;
	int i, j;

	/* get it's body */
	token = Com_Parse(text);

	if (!*text || *token != '{') {
		Com_Printf("CL_ParsePtlCmds: particle cmds \"%s\" without body ignored\n", name);
		return;
	}

	do {
		token = Com_EParse(text, errhead, name);
		if (!*text)
			break;
		if (*token == '}')
			break;

		for (i = 0; i < PC_NUM_PTLCMDS; i++)
			if (Q_streq(token, pc_strings[i])) {
				/* allocate an new cmd */
				if (numPtlCmds >= MAX_PTLCMDS)
					Com_Error(ERR_DROP, "CL_ParsePtlCmds: MAX_PTLCMDS exceeded");
				pc = &ptlCmd[numPtlCmds++];
				OBJZERO(*pc);

				pc->cmd = i;

				if (!pc_types[i])
					break;

				/* get parameter type */
				token = Com_EParse(text, errhead, name);
				if (!*text)
					return;

				/* operate on the top element on the stack */
				if (token[0] == '#') {
					pc->ref = RSTACK;
					if (token[1] == '.')
						pc->ref -= (token[2] - '0');
					break;
				}

				if (token[0] == '*') {
					int len;
					char baseComponentToken[MAX_VAR];

					/* it's a variable reference */
					token++;

					/* we maybe have to modify it */
					Q_strncpyz(baseComponentToken, token, sizeof(baseComponentToken));

					/* check for component specifier */
					len = strlen(baseComponentToken);
					/* it's possible to change only the second value of e.g. a vector
					 * just defined e.g. 'size.2' to modify the second value of size */
					if (len >= 2 && baseComponentToken[len - 2] == '.') {
						baseComponentToken[len - 2] = 0;
					} else
						len = 0;

					for (pp = pps; pp->string; pp++)
						if (Q_streq(baseComponentToken, pp->string))
							break;

					if (!pp->string) {
						Com_Printf("CL_ParsePtlCmds: bad reference \"%s\" specified (particle %s)\n", token, name);
						numPtlCmds--;
						break;
					}

					if ((pc_types[i] & PTL_ONLY_ONE_TYPE)) {
						if ((pc_types[i] & ~PTL_ONLY_ONE_TYPE) != pp->type) {
							Com_Printf("CL_ParsePtlCmds: bad type in var \"%s\" (PTL_ONLY_ONE_TYPE) specified (particle %s) (ptl type: %i (pc_type: %i), string: %s)\n", token, name, pp->type, pc_types[i], pc_strings[i]);
							numPtlCmds--;
							break;
						}
					} else if (pp->type >= V_NUM_TYPES || !((1 << pp->type) & pc_types[i])) {
						Com_Printf("CL_ParsePtlCmds: bad type in var \"%s\" specified (particle %s) (ptl type: %i (pc_type: %i), string: %s)\n", token, name, pp->type, pc_types[i], pc_strings[i]);
						numPtlCmds--;
						break;
					}

					if (len) {
						/* get single component */
						if ((1 << pp->type) & V_VECS) {
							const int component = (baseComponentToken[len - 1] - '1');
							/* get the component we want to modify */
							if (component > 3) {
								Com_Printf("CL_ParsePtlCmds: bad component value - it's bigger than 3: %i (particle %s)\n", component, name);
								numPtlCmds--;
								break;
							}
							pc->type = V_FLOAT;
							/* go to component offset */
							pc->ref = -((int)pp->ofs) - component * sizeof(float);
							break;
						} else {
							Com_Printf("CL_ParsePtlCmds: can't get components of a non-vector type (particle %s)\n", name);
							numPtlCmds--;
							break;
						}
					}

					/* set the values */
					pc->type = pp->type;
					pc->ref = -((int)pp->ofs);
					break;
				}

				/* get the type */
				if (pc_types[i] & PTL_ONLY_ONE_TYPE)
					/* extract the real type */
					j = pc_types[i] & ~PTL_ONLY_ONE_TYPE;
				else {
					for (j = 0; j < V_NUM_TYPES; j++)
						if (Q_streq(token, vt_names[j]))
							break;

					if (j >= V_NUM_TYPES || !((1 << j) & pc_types[i])) {
						Com_Printf("CL_ParsePtlCmds: bad type \"%s\" specified (particle %s)\n", token, name);
						numPtlCmds--;
						break;
					}

					/* get the value */
					token = Com_EParse(text, errhead, name);
					if (!*text)
						return;
				}

				/* set the values */
				pc->type = j;

				pcmdPos = (byte*) Com_AlignPtr(pcmdPos, (valueTypes_t)pc->type);
				pc->ref = (int) (pcmdPos - pcmdData);
				pcmdPos += Com_EParseValue(pcmdPos, token, (valueTypes_t)pc->type, 0, 0);

/*				Com_Printf("%s %s %i\n", vt_names[pc->type], token, pcmdPos - pc->ref, (char *)pc->ref); */
				break;
			}

		if (i < PC_NUM_PTLCMDS)
			continue;

		for (pp = pps; pp->string; pp++)
			if (Q_streq(token, pp->string)) {
				/* get parameter */
				token = Com_EParse(text, errhead, name);
				if (!*text)
					return;

				/* translate set to a push and pop */
				if (numPtlCmds >= MAX_PTLCMDS - 1)
					Com_Error(ERR_DROP, "CL_ParsePtlCmds: MAX_PTLCMDS exceeded");
				pc = &ptlCmd[numPtlCmds++];
				pc->cmd = PC_PUSH;
				pc->type = pp->type;

				pcmdPos = (byte*) Com_AlignPtr(pcmdPos, (valueTypes_t)pc->type);
				pc->ref = (int) (pcmdPos - pcmdData);
				pcmdPos += Com_EParseValue(pcmdPos, token, (valueTypes_t)pc->type, 0, 0);

				pc = &ptlCmd[numPtlCmds++];
				pc->cmd = PC_POP;
				pc->type = pp->type;
				pc->ref = -((int)pp->ofs);
				break;
			}

		if (!pp->string)
			Com_Printf("CL_ParsePtlCmds: unknown token \"%s\" ignored (particle %s)\n", token, name);

	} while (*text);

	/* terminalize cmd chain */
	if (numPtlCmds >= MAX_PTLCMDS)
		Com_Error(ERR_DROP, "CL_ParsePtlCmds: MAX_PTLCMDS exceeded");
	pc = &ptlCmd[numPtlCmds++];
	OBJZERO(*pc);
}