Exemplo n.º 1
0
UCS2 *Parser::Parse_Str(bool pathname)
{
	char *p;
	char temp3[128];
	char temp4[256];
	DBL val;
	int l, d;

	GET(LEFT_PAREN_TOKEN);
	val = Parse_Float();
	Parse_Comma();
	l = (int)Parse_Float();
	Parse_Comma();
	d = (int)Parse_Float();
	GET(RIGHT_PAREN_TOKEN);

	p = temp3;
	*p++ = '%';
	if (l > 0)
	{
		p += sprintf(p, "%d", l);
	}
	else
	{
		if (l)
			p += sprintf(p, "0%d", abs(l));
	}

	if (d >= 0)
		p += sprintf(p, ".%d", d);
	strcpy(p, "f");

	// a very large floating point value (e.g. 1e251) will overflow the buffer.
	// TODO: consider changing to %g rather than %f for large numbers (e.g.
	// anything over 1e+64 for example). for now, we will only use %g if the
	// snprintf filled the buffer.
	// NB test for < 0 is because stupid windows _snprintf can return negative values.
	if (((l = snprintf(temp4, sizeof(temp4) - 1, temp3, val)) >= sizeof(temp4) - 1) || (l < 0))
	{
		*p = 'g';

		// it should not be possible to overflow with %g. but just in case ...
		if (((l = snprintf(temp4, sizeof(temp4) - 1, temp3, val)) >= sizeof(temp4) - 1) || (l < 0))
			strcpy(temp4, "<invalid>");
	}

	return String_To_UCS2(temp4, pathname);
}
Exemplo n.º 2
0
UCS2 *Parser::Parse_Str(bool pathname)
{
    char *p;
    char temp3[128];
    char temp4[256];
    DBL val;
    int l, d;

    Parse_Paren_Begin();
    val = Parse_Float();
    Parse_Comma();
    l = (int)Parse_Float();
    Parse_Comma();
    d = (int)Parse_Float();
    Parse_Paren_End();

    p = temp3;
    *p++ = '%';
    if (l > 0)
    {
        p += sprintf(p, "%d", l);
    }
    else
    {
        if (l)
            p += sprintf(p, "0%d", abs(l));
    }

    if (d >= 0)
        p += sprintf(p, ".%d", d);
    strcpy(p, "f");

    // a very large floating point value (e.g. 1e251) will overflow the buffer.
    // TODO: consider changing to %g rather than %f for large numbers (e.g.
    // anything over 1e+64 for example). for now, we will only use %g if the
    // snprintf filled the buffer.
    // NB `snprintf` may report errors via a negative return value.
    if (((l = std::snprintf(temp4, sizeof(temp4), temp3, val)) >= sizeof(temp4)) || (l < 0))
    {
        *p = 'g';

        // it should not be possible to overflow with %g. but just in case ...
        if (((l = std::snprintf(temp4, sizeof(temp4), temp3, val)) >= sizeof(temp4)) || (l < 0))
            strcpy(temp4, "<invalid>");
    }

    return String_To_UCS2(temp4);
}
Exemplo n.º 3
0
UCS2 *Parser::Parse_Datetime(bool pathname)
{
	char *FormatStr = NULL;
	bool CallFree;
	int vlen = 0;
	char val[PARSE_NOW_VAL_LENGTH + 1]; // Arbitrary size, usually a date format string is far less

	GET(LEFT_PAREN_TOKEN);
	std::time_t timestamp = floor((Parse_Float() + (365*30+7)) * 24*60*60 + 0.5);
	Parse_Comma();
	EXPECT
		CASE(RIGHT_PAREN_TOKEN)
			CallFree = false;
			// we use GMT as some platforms (e.g. windows) have different ideas of what to print when handling '%z'.
			FormatStr = (char *)"%Y-%m-%d %H:%M:%SZ";
			EXIT
		END_CASE

		OTHERWISE
			UNGET
			CallFree = true;
			FormatStr = Parse_C_String(pathname);
			if (FormatStr[0] == '\0')
			{
				POV_FREE(FormatStr);
				Error("Empty format string.");
			}
			if (strlen(FormatStr) > PARSE_NOW_VAL_LENGTH)
			{
				POV_FREE(FormatStr);
				Error("Format string too long.");
			}
			GET(RIGHT_PAREN_TOKEN);
			EXIT
		END_CASE
	END_EXPECT

	// NB don't wrap only the call to strftime() in the try, because visual C++ will, in release mode,
	// optimize the try/catch away since it doesn't believe that the RTL can throw exceptions. since
	// the windows version of POV hooks the invalid parameter handler RTL callback and throws an exception
	// if it's called, they can.
	try
	{
		std::tm t = boost::posix_time::to_tm(boost::posix_time::from_time_t(timestamp));
		// TODO FIXME - we should either have this locale setting globally, or avoid it completely; in either case it shouldn't be *here*.
		setlocale(LC_TIME,""); // Get the local prefered format
		vlen = strftime(val, PARSE_NOW_VAL_LENGTH, FormatStr, &t);
	}
	catch (pov_base::Exception& e)
	{
		// the windows version of strftime calls the invalid parameter handler if
		// it gets a bad format string. this will in turn raise an exception of type
		// kParamErr. if the exception isn't that, allow normal exception processing
		// to continue, otherwise we issue a more useful error message.
		if ((e.codevalid() == false) || (e.code() != kParamErr))
			throw;
		vlen = 0;
	}
	if (vlen == PARSE_NOW_VAL_LENGTH) // on error: max for libc 4.4.1 & before
		vlen = 0; // return an empty string on error (content of val[] is undefined)
	val[vlen]='\0'; // whatever, that operation is now safe (and superflous except for error)

	if (CallFree)
	{
		POV_FREE(FormatStr);
	}

	if (vlen == 0)
		Error("Invalid formatting code in format string, or resulting string too long.");

	return String_To_UCS2(val, pathname);
}
Exemplo n.º 4
0
UCS2 *Parser::Parse_VStr(bool pathname)
{
	char *p;
	char temp3[128];
	char temp4[768];
	int l, d, vl;
	EXPRESS Express;
	int Terms;
	int Dim = 5;
	UCS2 *str;
	UCS2 *str2;
	UCS2 *New;

	GET(LEFT_PAREN_TOKEN);

	vl = (int)Parse_Float();
	Parse_Comma();

	if(vl < 2)
		vl = 2;
	else if(vl > 5)
		vl = 5;
	Dim = vl;

	Terms = Parse_Unknown_Vector(Express);

	Parse_Comma();
	str = Parse_String(pathname);
	Parse_Comma();
	l = (int)Parse_Float();
	Parse_Comma();
	d = (int)Parse_Float();

	GET(RIGHT_PAREN_TOKEN);

	p = temp3;
	*(p++) = '%';
	if (l > 0)
	{
		sprintf(p, "%d", l);
		while (*p != '\0')
			p++;
	}
	else
	{
		if (l)
		{
			sprintf(p, "0%d", abs(l));
			while (*p != '\0')
				p++;
		}
	}

	if (d >= 0)
	{
		*(p++) = '.';
		sprintf(p, "%d", d);
		while (*(++p))
			;
	}
	*(p++) = 'f';
	*p = '\0';

	sprintf(temp4, temp3, Express[X]);
	New = String_To_UCS2(temp4, pathname);       // add first component

	for(Terms = 1; Terms < Dim; Terms++)
	{
		New = UCS2_strcat(New, str);   // add separator
		sprintf(temp4, temp3, Express[Terms]);
		str2 = String_To_UCS2(temp4, pathname);
		New = UCS2_strcat(New, str2);  // add component
		POV_FREE(str2);
	}

	POV_FREE(str);

	return New;
}
Exemplo n.º 5
0
UCS2 *Parser::Parse_String(bool pathname, bool require)
{
	UCS2 *New = NULL;
	int len = 0;

	EXPECT
		CASE(STRING_LITERAL_TOKEN)
			New = String_To_UCS2(Token.Token_String, pathname);
			EXIT
		END_CASE

		CASE(STR_TOKEN)
			New = Parse_Str(pathname);
			EXIT
		END_CASE

		CASE(VSTR_TOKEN)
			New = Parse_VStr(pathname);
			EXIT
		END_CASE

		CASE(CONCAT_TOKEN)
			New = Parse_Concat(pathname);
			EXIT
		END_CASE

		CASE(CHR_TOKEN)
			New = Parse_Chr(pathname);
			EXIT
		END_CASE

		CASE(DATETIME_TOKEN)
			New = Parse_Datetime(pathname);
			EXIT
		END_CASE

		CASE(SUBSTR_TOKEN)
			New = Parse_Substr(pathname);
			EXIT
		END_CASE

		CASE(STRUPR_TOKEN)
			New = Parse_Strupr(pathname);
			EXIT
		END_CASE

		CASE(STRLWR_TOKEN)
			New = Parse_Strlwr(pathname);
			EXIT
		END_CASE

		CASE(STRING_ID_TOKEN)
			len = UCS2_strlen(reinterpret_cast<UCS2 *>(Token.Data)) + 1;
			New = reinterpret_cast<UCS2 *>(POV_MALLOC(len * sizeof(UCS2), "UCS2 String"));
			POV_MEMMOVE(reinterpret_cast<void *>(New), reinterpret_cast<void *>(Token.Data), len * sizeof(UCS2));
			EXIT
		END_CASE

		OTHERWISE
			if(require)
				Expectation_Error("string expression");
			else
			{
				UNGET
				EXIT
			}
		END_CASE
	END_EXPECT

	return New;
}