Exemple #1
0
//////////
//
// Function: VARTYPE()
// Returns the variable type, parsing NULL values.
//
//////
// Version 0.57
// Last update:
//     Apr.06.2015
//////
// Change log:
//     Apr.06.2015 - Initial creation
//////
// Parameters:
//     P1			-- The variable to examine
//     P2			-- (Optional) If provided, .t. or .f. indicating if NULL values should return the type (default to .f.)
//
//////
// Returns:
//    Character		-- A one-digit value indicating the type
//////
	void function_vartype(SThisCode* thisCode, SFunctionParams* rpar)
	{
		SVariable* var		= rpar->ip[0];
		SVariable* varNull	= rpar->ip[1];

		bool	llNullIsType;
		bool	error;
		u32		errorNum;


		//////////
		// varLookup must exist
		//////
			rpar->rp[0] = NULL;
			if (!iVariable_isValidType(var))
			{
				iError_reportByNumber(thisCode, _ERROR_P1_IS_INCORRECT, iVariable_getRelatedComp(thisCode, var), false);
				return;
			}


		//////////
		// If varNull is specified, must be logical
		//////
			if (varNull)
			{

				//////////
				// Must be logical
				//////
					if (!iVariable_isValid(varNull) || !iVariable_isTypeLogical(varNull))
					{
						iError_reportByNumber(thisCode, _ERROR_P2_IS_INCORRECT, iVariable_getRelatedComp(thisCode, varNull), false);
						return;
					}


				//////////
				// Grab the value
				//////
					llNullIsType = iiVariable_getAs_bool(thisCode, varNull, false, &error, &errorNum);
					if (error)
					{
						iError_reportByNumber(thisCode, errorNum, iVariable_getRelatedComp(thisCode, varNull), false);
						return;
					}


			} else {
				// Do not report on NULL types
				llNullIsType = false;
			}


		//////////
		// Compute our result
		//////
			ifunction_type_common(thisCode, rpar, var, false, true, llNullIsType);

	}
Exemple #2
0
//////////
//
// Function: EMPTY()
// Determines whether an expression evaluates to empty.
//
//////
// Version 0.57
// Last update:
//     Mar.20.2015
//////
// Change log:
//     Mar.20.2015 - Refactoring by Stefano D'Amico
//     Mar.19.2015 - Refactoring by Rick C. Hodgin
//     Mar.19.2015 - Initial creation by Stefano D'Amico
//////
// Parameters:
//     p1	-- Specifies the expression that EMPTY( ) evaluates.
//
//////
// Returns:
//    EMPTY( ) returns True (.T.) if the expression eExpression evaluates to empty;
//    otherwise, EMPTY( ) returns False (.F.)
//////
// Example:
//    ? EMPTY("AA")	&& Display .F.
//    ? EMPTY("  ")	&& Display .T.
//    ? EMPTY(0.0)	&& Display .T.
//////
	void function_empty(SThisCode* thisCode, SFunctionParms* rpar)
	{
		SVariable*	varExpr = rpar->params[0];
		bool		llEmpty;
		SVariable*	result;


		//////////
		// Verify the expression is correct
		//////
			rpar->returns[0] = NULL;
			if (!iVariable_isValid(varExpr))
			{
				iError_reportByNumber(thisCode, _ERROR_PARAMETER_IS_INCORRECT, iVariable_getRelatedComp(thisCode, varExpr), false);
				return;
			}


		//////////
		// Create and populate the return variable
		//////
			llEmpty	= function_isempty_common(thisCode, rpar, varExpr);
			result	= iVariable_createAndPopulate_byText(thisCode, _VAR_TYPE_LOGICAL, (cs8*)((llEmpty) ? &_LOGICAL_TRUE : &_LOGICAL_FALSE), 1, false);
			if (!result)
				iError_reportByNumber(thisCode, _ERROR_INTERNAL_ERROR, iVariable_getRelatedComp(thisCode, varExpr), false);


		//////////
		// Signify our result
		//////
			rpar->returns[0] = result;

	}
Exemple #3
0
//////////
//
// Function: VECCOUNT()
// The vector element count.
//
//////
// Version 0.57
// Last update:
//     Mar.21.2015
//////
// Change log:
//     Mar.21.2015 - Initial creation
//////
// Parameters:
//     varVec		- Vector
//
//////
// Returns:
//     Numeric, the number of elements in the vector.
//////
	void function_veccount(SThisCode* thisCode, SFunctionParams* rpar)
	{
		SVariable* varVec = rpar->ip[0];


		// Not yet completed
		iError_reportByNumber(thisCode, _ERROR_FEATURE_NOT_AVAILABLE, iVariable_getRelatedComp(thisCode, varVec), false);
		rpar->rp[0] = NULL;
	}
Exemple #4
0
//////////
//
// Function: EVL()
// Returns a non-empty value from two expressions.
//
//////
// Version 0.57
// Last update:
//     Mar.20.2015
//////
// Change log:
//     Mar.20.2015 - Some refactoring by Rick C. Hodgin
//     Mar.20.2015 - Initial creation by Stefano D'Amico
//////
// Parameters:
//     p1	-- Specifies the expression that EMPTY( ) evaluates.
//     p2	-- Specifies the expression to return if p1 is empty.
//
//////
// Returns:
//    EVL( ) returns p1 if it does not evaluate to an empty value; otherwise, it returns p2.
//////
// Example:
//    ? EVL("  ", "None")	&& Display "None"
//////
	void function_evl(SThisCode* thisCode, SFunctionParms* rpar)
	{
		SVariable*	varExpr1 = rpar->params[0];
		SVariable*	varExpr2 = rpar->params[1];
		bool		llEmpty;
		SVariable*	result;


		//////////
		// Verify p1 is correct
		//////
			rpar->returns[0] = NULL;
			if (!iVariable_isValid(varExpr1))
			{
				iError_reportByNumber(thisCode, _ERROR_P1_IS_INCORRECT, iVariable_getRelatedComp(thisCode, varExpr1), false);
				return;
			}


		//////////
		// Verify p2 is correct
		//////
			if (!iVariable_isValid(varExpr2))
			{
				iError_reportByNumber(thisCode, _ERROR_P2_IS_INCORRECT, iVariable_getRelatedComp(thisCode, varExpr2), false);
				return;
			}


		//////////
		// Create our result
		//////
			llEmpty	= function_isempty_common(thisCode, rpar, varExpr1);
			result	= iVariable_copy(thisCode, ((llEmpty) ? varExpr2 : varExpr1), false);
			if (!result)
				iError_reportByNumber(thisCode, _ERROR_INTERNAL_ERROR, iVariable_getRelatedComp(thisCode, ((llEmpty) ? varExpr2 : varExpr1)), false);


		//////////
		// Signify our result
		//////
			rpar->returns[0] = result;

	}
Exemple #5
0
//////////
//
// Function: VECSTR()
// Generates a character string containing the vectors.
//
//////
// Version 0.57
// Last update:
//     Mar.21.2015
//////
// Change log:
//     Mar.21.2015 - Initial creation
//////
// Parameters:
//     varVec				- Vector
//     varSymbolOverride	- A symbol to use between vectors
//
//////
// Returns:
//     A character string containing the vector values interspersed with symbol space, or the varSymbolOverride
//////
	void function_vecstr(SThisCode* thisCode, SFunctionParams* rpar)
	{
//		SVariable* varVec				= rpar->params[0];
//		SVariable* varSymbolOverride	= rpar->params[1];


		// Not yet completed
		iError_reportByNumber(thisCode, _ERROR_FEATURE_NOT_AVAILABLE, NULL, false);
		rpar->rp[0] = NULL;
	}
Exemple #6
0
//////////
//
// Function: ENDSWITHC()
// Case-insensitive version of ENDSWITH()
//
//////
	void function_endswithc(SThisCode* thisCode, SFunctionParms* rpar)
	{
		SVariable* varString	= rpar->params[0];
//		SVariable* varSearch	= rpar->params[1];
//		SVariable* varStart		= rpar->params[2];
//		SVariable* varEnd		= rpar->params[3];


		// Not yet completed
		iError_reportByNumber(thisCode, _ERROR_FEATURE_NOT_AVAILABLE, iVariable_getRelatedComp(thisCode, varString), false);
	}
Exemple #7
0
//////////
//
// Function: VECSTUFF()
// Updates or resizes a vector element. Works like STUFF().
//
//////
// Version 0.57
// Last update:
//     Mar.21.2015
//////
// Change log:
//     Mar.21.2015 - Initial creation
//////
// Parameters:
//     varVec			- Vector
//     varStartEl		- Element to start the operation at.
//     varRemoveCount	- The number of elements to remove
//     varVecStuff		- (Optional) The new vector to stuff in there after varStartEl
//
//////
// Returns:
//    if varNewValue was specified, returns the new vector
//    else                          returns the value of that element
//////
	void function_vecstuff(SThisCode* thisCode, SFunctionParams* rpar)
	{
		SVariable* varVec			= rpar->ip[0];
//		SVariable* varStartEl		= rpar->params[1];
//		SVariable* varRemoveCount	= rpar->params[2];
//		SVariable* varVecStuff		= rpar->params[3];


		// Not yet completed
		iError_reportByNumber(thisCode, _ERROR_FEATURE_NOT_AVAILABLE, iVariable_getRelatedComp(thisCode, varVec), false);
		rpar->rp[0] = NULL;
	}
Exemple #8
0
//////////
//
// Function: LOWER()
// Converts every character in the string to lowercase.
//
//////
// Version 0.57
// Last update:
//     Jul.12.2014
//////
// Change log:
//     Jul.12.2014 - Initial creation
//////
// Parameters:
//     pString		-- Character, the string to lower
//
//////
// Returns:
//    Character		-- The string with all lowercase characters converted to lowercase
//////
	void function_lower(SThisCode* thisCode, SFunctionParms* rpar)
	{
		SVariable*	varString = rpar->params[0];
		s32			lnI;
        SVariable*	result;


		//////////
		// Parameter 1 must be character
		//////
			rpar->returns[0] = NULL;
			if (!iVariable_isValid(varString) || iVariable_getType(varString) != _VAR_TYPE_CHARACTER)
			{
				iError_reportByNumber(thisCode, _ERROR_P1_IS_INCORRECT, iVariable_getRelatedComp(thisCode, varString), false);
				return;
			}


		//////////
        // Create our return result
		//////
	        result = iVariable_create(thisCode, _VAR_TYPE_CHARACTER, NULL, true);
			if (!result)
			{
				iError_report(thisCode, cgcInternalError, false);
				return;
			}


		//////////
        // Copy the source string
		//////
	        iDatum_duplicate(&result->value, &varString->value);


		//////////
		// Lower every character
		//////
			for (lnI = 0; lnI < result->value.length; lnI++)
			{
				if (result->value.data[lnI] >= 'A' && result->value.data[lnI] <= 'Z')
					result->value.data[lnI] += 0x20;
			}


		//////////
        // Return our converted result
		//////
			rpar->returns[0] = result;

	}
Exemple #9
0
//////////
//
// Function: LEN()
// Returns the length of the string.
//
//////
// Version 0.57
// Last update:
//     Jul.12.2014
//////
// Change log:
//     Jul.12.2014 - Initial creation
//////
// Parameters:
//     pString		-- Character, the string to return the length from
//
//////
// Returns:
//    Numeric		-- The length of the string
//////
	void function_len(SThisCode* thisCode, SFunctionParms* rpar)
	{
		SVariable* varString = rpar->params[0];
        SVariable* result;


		//////////
		// Parameter 1 must be character
		//////
			rpar->returns[0] = NULL;
			if (!iVariable_isValid(varString) || iVariable_getType(varString) != _VAR_TYPE_CHARACTER)
			{
				iError_reportByNumber(thisCode, _ERROR_P1_IS_INCORRECT, iVariable_getRelatedComp(thisCode, varString), false);
				return;
			}


		//////////
        // Create our return result
		//////
	        result = iVariable_create(thisCode, _VAR_TYPE_S32, NULL, true);
			if (!result)
			{
				iError_report(thisCode, cgcInternalError, false);
				return;
			}


		//////////
		// Populate based on the length
		//////
			*(s32*)result->value.data = varString->value.length;


		//////////
        // Return our converted result
		//////
			rpar->returns[0] = result;

	}
Exemple #10
0
//////////
//
// Function: VERSION()
// Based on input, retrieves various version information.
//
//////
// Version 0.57
// Last update:
//     Jul.13.2014
//////
// Change log:
//     Jul.13.2014 - Initial creation
//////
// Parameters:
//     pIndex		-- (Optional) If present, Numeric, in the range 1..5
//
//////
// Returns:
//    Numeric or Character	-- Depending on index, various values are returned
//////
    void function_version(SThisCode* thisCode, SFunctionParams* rpar)
    {
		SVariable*	varIndex = rpar->ip[0];
        s32			index;
		u32			errorNum;
        bool		error;
		u8*			lptr;
        SVariable*	result;


		//////////
		// Parameter 1 must be numeric
		//////
			rpar->rp[0]	= NULL;
			lptr				= NULL;
			if (!iVariable_isValid(varIndex))
			{
				// They are requesting the default information
				lptr = (u8*)cgcVersionText;

			} else if (!iVariable_isTypeNumeric(varIndex)) {
				// The parameter is not numeric
				iError_reportByNumber(thisCode, _ERROR_P1_IS_INCORRECT, iVariable_getRelatedComp(thisCode, varIndex), false);
				return;

			} else {
				// It must be in the range 1..5
				index = iiVariable_getAs_s32(thisCode, varIndex, false, &error, &errorNum);
				if (error)
				{
					iError_reportByNumber(thisCode, errorNum, iVariable_getRelatedComp(thisCode, varIndex), false);
					return;

				} else if (index < 1 || index > 5) {
					// We report our own error
					iError_report(thisCode, (cu8*)"Parameter must be in the range 1..5", false);
					return;
				}
			}


		//////////
        // Create our return result
		//////
			if (lptr || index == 1 || index == 4)
			{
				// Character return
				result = iVariable_create(thisCode, _VAR_TYPE_CHARACTER, NULL, true);
				if (lptr)
				{
					// Copy the version info
					iDatum_duplicate(&result->value, lptr, -1);

				} else if (index == 1) {
					// Copy the version1 info
					iDatum_duplicate(&result->value, cgcVersion1Text, -1);

				} else {
					// Copy the version4 info
					iDatum_duplicate(&result->value, cgcVersion4Text, -1);
				}

			} else {
				result = iVariable_create(thisCode, _VAR_TYPE_S32, NULL, true);
				if (index == 2)
				{
					// 0=runtime, 1=standard, 2=professional
					*(s32*)result->value.data = gnVersion2;	// Oh yeah!

				} else if (index == 3) {
					// Localized version
					*(s32*)result->value.data = gnVersion3;	// English

				} else {
					// Version in a form like Major.Minor as M.mm, or 123 for version 1.23
					*(s32*)result->value.data = gnVersion5;
				}
			}
			if (!result)
			{
				iError_report(thisCode, cgcInternalError, false);
				return;
			}


		//////////
        // Return our converted result
		//////
			rpar->rp[0] = result;

    }
Exemple #11
0
//////////
//
// Function: VAL()
// Returns a numeric or currency value from a expression.
//
//////
// Version 0.57
// Last update:
//     Mar.22.2015
//////
// Change log:
//     Mar.21.2015 - Initial creation by Stefano D'Amico
//////
// Parameters:
//     varExpr			-- Any, to convert
//	   varIgnoreList	-- Characters to ignore
//
//////
// Returns:
//    Numeric		--	VAL( ) returns the numbers in the character expression from left to right until a non-numeric character is encountered.
//						Leading blanks are ignored.
//						VAL( ) returns 0 if the first character of the character expression is not a number, a dollar sign ($), a plus sign (+), or minus sign (-).
//////
	void function_val(SThisCode* thisCode, SFunctionParams* rpar)
	{
		SVariable*	varExpr			= rpar->ip[0];
		SVariable*	varIgnoreChars	= rpar->ip[1];
		s8			c, cCurrency, cPoint, cSeparator;
		s32			lnI, lnJ, lnBuffOffset;
		s64			lnValue;
		f64			lfValue;
		bool		llAsInteger, llStillGoing, llCurrency;
		SVariable*	varCurrency;
		SVariable*	varPoint;
		SVariable*	varSeparator;
		SVariable*	result;
		u32			errorNum;
        bool		error;
		s8			buffer[64];


		//////////
		// Parameter 1 must be valid
		//////
			rpar->rp[0] = NULL;
			if (!iVariable_isValid(varExpr))
			{
				iError_reportByNumber(thisCode, _ERROR_P1_IS_INCORRECT, iVariable_getRelatedComp(thisCode, varExpr), false);
				return;
			}

		//////////
		// If numeric, copy whatever's already there
		//////
			if (varExpr->varType >= _VAR_TYPE_NUMERIC_START && varExpr->varType <= _VAR_TYPE_NUMERIC_END)
			{
				// Copy The existing variable
				result = iVariable_copy(thisCode, varExpr, false);
				if (!result)
					iError_reportByNumber(thisCode, _ERROR_INTERNAL_ERROR, iVariable_getRelatedComp(thisCode, varExpr), false);

				// Success or failure, return our result
				rpar->rp[0] = result;
				return;
			}



		//////////
		// Determine what we're evaluating
		//////
			switch (varExpr->varType)
			{
				case _VAR_TYPE_NULL:
					iError_reportByNumber(thisCode, _ERROR_P1_IS_INCORRECT, iVariable_getRelatedComp(thisCode, varExpr), false);
					return;
					break;

				case _VAR_TYPE_LOGICAL:		// 0=.F., 1=.T.
				case _VAR_TYPE_DATE:		// YYYYMMDD
					result = iVariable_create(thisCode, _VAR_TYPE_S32, NULL, true);
					if (result)
					{
						// Populate the s32
						*result->value.data_s32 = iiVariable_getAs_s32(thisCode, varExpr, true, &error, &errorNum);
						if (error)
							iError_reportByNumber(thisCode, errorNum, iVariable_getRelatedComp(thisCode, varExpr), false);
					}
					break;

				case _VAR_TYPE_DATETIME:
					// YYYYMMDDHhMmSsMss as s64
				case _VAR_TYPE_DATETIMEX:
					// YYYYMMDDHhMmSsNssssssss
					result = iVariable_create(thisCode, _VAR_TYPE_S64, NULL, true);
					if (result)
					{
						// Populate the s64
						*result->value.data_s64 = iiVariable_getAs_s64(thisCode, varExpr, true, &error, &errorNum);
						if (error)
							iError_reportByNumber(thisCode, errorNum, iVariable_getRelatedComp(thisCode, varExpr), false);
					}
					break;

				case _VAR_TYPE_CHARACTER:

					//////////
					// If present, parameter 2 must be valid
					//////
						if (varIgnoreChars)
						{
							if (!iVariable_isValid(varIgnoreChars) || !iVariable_isTypeCharacter(varIgnoreChars))
							{
								iError_reportByNumber(thisCode, _ERROR_P2_IS_INCORRECT, iVariable_getRelatedComp(thisCode, varIgnoreChars), false);
								return;
							}
						}


					//////////
					// Prepare our characters
					//////
						varCurrency		= propGet_settings_Currency(_settings);
						varPoint		= propGet_settings_Point(_settings);
						varSeparator	= propGet_settings_Separator(_settings);
						if (!varCurrency || !varPoint || !varSeparator)
						{
							// Should never happen
							iError_reportByNumber(thisCode, _ERROR_INTERNAL_ERROR, NULL, false);
							return;
						}


					//////////
					// Create single characters
					//////
						cCurrency	= varCurrency->value.data_s8[0];
						cPoint		= varPoint->value.data_s8[0];
						cSeparator	= varSeparator->value.data_s8[0];


					//////////
					// Iterate through each character
					//////
						for (lnI = 0, lnBuffOffset = 0, llStillGoing = true, llCurrency = false; llStillGoing && lnI < (s32)varExpr->value.length && lnBuffOffset < (s32)sizeof(buffer) - 1; lnI++)
						{

							//////////
							// Grab this character
							//////
								c = varExpr->value.data[lnI];


							//////////
							// Is it a character we're including in our buffer (a number, or natural number-related symbol)?
							//////
								if ((c >= '0' && c <= '9' ) || c == '+' || c == '-' || c == cPoint)
								{
									// Yes, Copy this character
									buffer[lnBuffOffset++] = c;

								} else {
									// Are we still in a valid sequence of characters to skip?
									if (c == ' ' || c == cSeparator)
									{
										// It's a character we're skipping naturally (space, separator symbol)
										// We don't do anything here ... it's just more clear to keep this logic visible rather than inverting it. :-)

									} else if (c == cCurrency) {
										// We encountered the currency symbol, so the output will be currency
										llCurrency = true;

									} else if (varIgnoreChars) {
										// We won't continue unless we're sitting on a character in the varIgnoreChars
										for (lnJ = 0, llStillGoing = false; lnJ < varIgnoreChars->value.length; lnJ++)
										{
											// Is this one of our skip characters?
											if (c == varIgnoreChars->value.data_s8[lnJ])
											{
												llStillGoing = true;
												break;
											}
										}

									} else {
										// We're done
										break;
									}
								}

						}

						// NULL terminate
						buffer[lnBuffOffset] = 0;


					//////////
					// Convert to f64, and s64
					//////
						lfValue = atof(buffer);
#if defined(__GNUC__) || defined(__solaris__)
						lnValue = strtoll(buffer, NULL, 10);
#else
						lnValue = _strtoi64(buffer, NULL, 10);
#endif


					//////////
					// Is currency or not? If it's an integer value, store it as the same, otherwise use floating point
					//////
						if ((f64)lnValue == lfValue)
						{
							// We can return as an integer
							llAsInteger = true;
							if (llCurrency)
							{
								// Multiply by 10000 to obtain the 4 implied decimal places
								lnValue = lnValue * 10000;
								result	= iVariable_create(thisCode, _VAR_TYPE_CURRENCY, NULL, true);

							} else {
								if (lnValue < (s64)_s32_max)
								{
									// We can create as an s32
									result = iVariable_create(thisCode, _VAR_TYPE_S32, NULL, true);

								} else {
									// Create as an s64
									result = iVariable_create(thisCode, _VAR_TYPE_S64, NULL, true);
								}
							}

						} else {
							// Must return as f64
							llAsInteger	= false;
							if (llCurrency)
							{
								// As currency
								lfValue	*= 10000.0;
								result	= iVariable_create(thisCode, _VAR_TYPE_CURRENCY, NULL, true);

							} else {
								// As is
								result	= iVariable_create(thisCode, _VAR_TYPE_F64, NULL, true);
							}
						}


					//////////
					// Store the result
					//////
						if (result)
						{
							if (llAsInteger)	iVariable_setNumeric_toNumericType(thisCode, result, NULL, NULL, NULL, NULL, &lnValue, NULL);
							else				iVariable_setNumeric_toNumericType(thisCode, result, NULL, &lfValue, NULL, NULL, NULL, NULL);
						}
						break;

				default:
					// Unrecognized type
					iError_reportByNumber(thisCode, _ERROR_FEATURE_NOT_AVAILABLE, iVariable_getRelatedComp(thisCode, varExpr), false);
					return;
			}


		//////////
		// Are we good?
		//////
			if (!result)
				iError_reportByNumber(thisCode, _ERROR_INTERNAL_ERROR, iVariable_getRelatedComp(thisCode, varExpr), false);


		//////////
        // Return our converted result
		//////
			rpar->rp[0] = result;

	}
Exemple #12
0
//////////
//
// Function: LEFT()
// Returns the left N characters of a string.
//
//////
// Version 0.57
// Last update:
//     Jul.12.2014
//////
// Change log:
//     Jul.12.2014 - Initial creation
//////
// Parameters:
//     pString		-- Character, the string to trim
//     pCount		-- Numeric, the number of characters to copy
//
//////
// Returns:
//    Character		-- The string of the left N characters
//////
	void function_left(SThisCode* thisCode, SFunctionParms* rpar)
	{
		SVariable*	varString	= rpar->params[0];
		SVariable*	varCount	= rpar->params[1];
		s32			lnLength;
		u32			errorNum;
		bool		error;
        SVariable*	result;


		//////////
		// Parameter 1 must be character
		//////
			rpar->returns[0] = NULL;
			if (!iVariable_isValid(varString) || iVariable_getType(varString) != _VAR_TYPE_CHARACTER)
			{
				iError_reportByNumber(thisCode, _ERROR_P1_IS_INCORRECT, iVariable_getRelatedComp(thisCode, varString), false);
				return;
			}


		//////////
		// Parameter 2 must be numeric
		//////
			if (!iVariable_isValid(varCount) || !iVariable_isTypeNumeric(varCount))
			{
				iError_reportByNumber(thisCode, _ERROR_P2_IS_INCORRECT, iVariable_getRelatedComp(thisCode, varCount), false);
				return;
			}


		//////////
        // Find out how long they want our string to be
		//////
			lnLength = iiVariable_getAs_s32(thisCode, varCount, false, &error, &errorNum);
			if (error)
			{
				iError_reportByNumber(thisCode, errorNum, iVariable_getRelatedComp(thisCode, varCount), false);
				return;
			}


		//////////
        // Create our return result
		//////
	        result = iVariable_create(thisCode, _VAR_TYPE_CHARACTER, NULL, true);
			if (!result)
			{
				iError_report(thisCode, cgcInternalError, false);
				return;
			}


		//////////
        // Copy as much of the source string as will fit
		//////
			if (lnLength > 0)
				iDatum_duplicate(&result->value, varString->value.data_u8, min(varString->value.length, lnLength));


		//////////
        // Return our converted result
		//////
			rpar->returns[0] = result;

	}
Exemple #13
0
	// Common numeric functions used for EXP(), LOG(), LOG10(), PI(), SQRT(), CEILING(), FLOOR(), DTOR(), RTOD(), ...
    void ifunction_numbers_common(SThisCode* thisCode, SFunctionParms* rpar, SVariable* varNumber1, SVariable* varNumber2, SVariable* varNumber3, u32 tnFunctionType, const u32 tnResultType, bool tlSameInputType, bool tlNoEmptyParam)
    {
		f64			lfResult, lfValue1, lfValue2, lfValue3;
		u32			errorNum;
        bool		error;
        SVariable*	result;


		//////////
		// If varNumber1 is provided, must also be numeric
		//////
			rpar->returns[0] = NULL;
			if (varNumber1)
			{
				//////////
				// Must be numeric
				//////
					if (!iVariable_isValid(varNumber1) || !iVariable_isTypeNumeric(varNumber1))
					{
						iError_reportByNumber(thisCode, _ERROR_PARAMETER_IS_INCORRECT, iVariable_getRelatedComp(thisCode, varNumber1), false);
						return;
					}


				//////////
				// Convert to f64
				//////
					lfValue1 = iiVariable_getAs_f64(thisCode, varNumber1, false, &error, &errorNum);
					if (error)
					{
						iError_reportByNumber(thisCode, errorNum, iVariable_getRelatedComp(thisCode, varNumber1), false);
						return;
					}

				//////////
				// Check empty param
				//////
					if (tlNoEmptyParam && lfValue1 == 0.0)
					{
						iError_reportByNumber(thisCode, _ERROR_CANNOT_BE_ZERO, iVariable_getRelatedComp(thisCode, varNumber1), false);
						return;
					}

			} else {
				lfValue1 = 0.0;
			}


		//////////
		// If varNumber2 is provided, must also be numeric
		//////
			if (varNumber2)
			{
				//////////
				// Must be numeric
				//////
					if (!iVariable_isValid(varNumber2) || !iVariable_isTypeNumeric(varNumber2))
					{
						iError_reportByNumber(thisCode, _ERROR_PARAMETER_IS_INCORRECT, iVariable_getRelatedComp(thisCode, varNumber2), false);
						return;
					}


				//////////
				// Convert to f64
				//////
					lfValue2 = iiVariable_getAs_f64(thisCode, varNumber2, false, &error, &errorNum);
					if (error)
					{
						iError_reportByNumber(thisCode, errorNum, iVariable_getRelatedComp(thisCode, varNumber2), false);
						return;
					}

				//////////
				// Check empty param
				//////
					if (tlNoEmptyParam && lfValue2 == 0.0)
					{
						iError_reportByNumber(thisCode, _ERROR_CANNOT_BE_ZERO, iVariable_getRelatedComp(thisCode, varNumber2), false);
						return;
					}

			} else {
				lfValue2 = 0.0;
			}


		//////////
		// If varNumber3 is provided, must also be numeric
		//////
			if (varNumber3)
			{
				//////////
				// Must be numeric
				//////
					if (!iVariable_isValid(varNumber3) || !iVariable_isTypeNumeric(varNumber3))
					{
						iError_reportByNumber(thisCode, _ERROR_PARAMETER_IS_INCORRECT, iVariable_getRelatedComp(thisCode, varNumber3), false);
						return;
					}


				//////////
				// Convert to f64
				//////
					lfValue3 = iiVariable_getAs_f64(thisCode, varNumber3, false, &error, &errorNum);
					if (error)
					{
						iError_reportByNumber(thisCode, errorNum, iVariable_getRelatedComp(thisCode, varNumber3), false);
						return;
					}

				//////////
				// Check empty param
				//////
					if (tlNoEmptyParam && lfValue3 == 0.0)
					{
						iError_reportByNumber(thisCode, _ERROR_CANNOT_BE_ZERO, iVariable_getRelatedComp(thisCode, varNumber3), false);
						return;
					}

			} else {
				lfValue3 = 0.0;
			}


		//////////
		// Compute numeric function
		//////
			switch (tnFunctionType)
			{

// SQRT()
				case _FP_COMMON_SQRT:

					//////////
					// Verify p1 >= 0
					//////
						if (lfValue1 < 0.0)
						{
							// Oops!
							iError_reportByNumber(thisCode, _ERROR_CANNOT_BE_NEGATIVE, iVariable_getRelatedComp(thisCode, varNumber1), false);
							return;
						}


					//////////
					// Compute sqrt
					//////
						lfResult = sqrt(lfValue1);
						break;

// EXP()
				case _FP_COMMON_EXP:
					lfResult = exp(lfValue1);
					break;

// PI()
				case _FP_COMMON_PI:
					lfResult = _MATH_PI;
					break;

// LOG()
// LOG10()
				case _FP_COMMON_LOG:
				case _FP_COMMON_LOG10:

					//////////
					// Verify p1 > 0
					//////
						if (lfValue1 <= 0.0)
						{
							// Oops!
							iError_reportByNumber(thisCode, _ERROR_CANNOT_BE_ZERO_OR_NEGATIVE, iVariable_getRelatedComp(thisCode, varNumber1), false);
							return;
						}


					//////////
					// Compute
					//////
						if (tnFunctionType == _FP_COMMON_LOG)		lfResult = log(lfValue1);
						else										lfResult = log10(lfValue1);
						break;

// CEILING()
				case _FP_COMMON_CEILING:
					lfResult = ceil(lfValue1);
					break;

// FLOOR()
				case _FP_COMMON_FLOOR:
					lfResult = floor(lfValue1);
					break;

// DTOR()
				case _FP_COMMON_DTOR:
					lfResult = lfValue1 * _MATH_PI180;
					break;

// RTOD()
				case _FP_COMMON_RTOD:
					lfResult = lfValue1 * _MATH_180PI;
					break;

// COS()
				case _FP_COMMON_COS:
					lfResult = cos(lfValue1);
					break;

// SIN()
				case _FP_COMMON_SIN:
					lfResult = sin(lfValue1);
					break;

// ABS()
				case _FP_COMMON_ABS:
					lfResult = abs(lfValue1);
					break;

// ACOS()
// ASIN()
				case _FP_COMMON_ACOS:
				case _FP_COMMON_ASIN:

					//////////
					// Verify p1 > 0
					//////
						if (lfValue1 < -1 || lfValue1 > 1)
						{
							// Oops!
							iError_reportByNumber(thisCode, _ERROR_OUT_OF_RANGE, iVariable_getRelatedComp(thisCode, varNumber1), false);
							return;
						}

					//////////
					// Compute
					//////
						if (tnFunctionType == _FP_COMMON_ACOS)		lfResult = acos(lfValue1);
						else										lfResult = asin(lfValue1);
						break;

// ATAN()
				case _FP_COMMON_ATAN:

					//////////
					// Verify p1 > 0
					//////
						if (lfValue1 < -_MATH_PI2 || lfValue1 > _MATH_PI2)
						{
							// Oops!
							iError_reportByNumber(thisCode, _ERROR_OUT_OF_RANGE, iVariable_getRelatedComp(thisCode, varNumber1), false);
							return;
						}

					//////////
					// Compute
					//////
						lfResult = atan(lfValue1);
						break;

// ATN2()
				case _FP_COMMON_ATN2:
					lfResult = atan2(lfValue1, lfValue2);
					break;
// TAN()
				case _FP_COMMON_TAN:
					lfResult = tan(lfValue1);
					break;
// MOD()
				case _FP_COMMON_MOD:

					//////////
					// Verify divisor not 0
					//////
						if (lfValue2 == 0.0)
						{
							// Oops!
							iError_reportByNumber(thisCode, _ERROR_DIVISION_BY_ZERO, iVariable_getRelatedComp(thisCode, varNumber2), false);
							return;
						}


					//////////
					// Compute
					//////
						lfResult = fmod(lfValue1, abs(lfValue2));
						if (lfValue2 < 0 && lfResult != 0.0)			// Mar.14.2015
							lfResult += lfValue2;

					break;

// FV()
				case _FP_COMMON_FV:

					//////////
					// Future value
					//////
						lfResult = (pow((1 + lfValue2), lfValue3) - 1) / lfValue2 * lfValue1;
						break;

// PV()
				case _FP_COMMON_PV:

					//////////
					// Present value
					//////
						lfResult = lfValue1 * ((1 - pow((1 + lfValue2), -lfValue3)) / lfValue2);
						break;

// PAYMENT()
				case _FP_COMMON_PAYMENT:

					//////////
					// Payment
					//////
						lfValue1 = (lfValue1 * pow(lfValue2 + 1, lfValue3) * lfValue2) / (pow(lfValue2 + 1, lfValue3) - 1);
						break;

				default:
					// Programmer error... this is an internal function and we should never get here
					iError_reportByNumber(thisCode, _ERROR_INTERNAL_ERROR, iVariable_getRelatedComp(thisCode, varNumber1), false);
					return;
			}


		//////////
		// Create output variable
		//////
			if (tlSameInputType)	result = iVariable_create(thisCode, varNumber1->varType, NULL, true);
			else					result = iVariable_create(thisCode, tnResultType, NULL, true);

			if (!result)
			{
				iError_reportByNumber(thisCode, errorNum, iVariable_getRelatedComp(thisCode, varNumber1), false);
				return;
			}


		//////////
		// Set the value
		//////
			if (!iVariable_setNumeric_toNumericType(thisCode, result, NULL, &lfResult, NULL, NULL, NULL, NULL))
				iError_reportByNumber(thisCode, errorNum, iVariable_getRelatedComp(thisCode, varNumber1), false);


		//////////
        // return(result)
		//////
			rpar->returns[0] = result;
	}
Exemple #14
0
	bool function_isempty_common(SThisCode* thisCode, SFunctionParms* rpar, SVariable* varExpr)
	{
		s8			c, cPointChar;
		u32			lnI;
		bool		llEmpty;
		SVariable*	varPoint;


		//////////
		// Determine what we're evaluating
		//////
			llEmpty = true;
			switch (varExpr->varType)
			{
				case _VAR_TYPE_NULL:
					// NULL values are considered "not empty" even though they really are.
					llEmpty = false;
					break;

				case _VAR_TYPE_DATE:	// Note:  Dates are stored internally as YYYYMMDD, so they can be directly compared
				case _VAR_TYPE_CHARACTER:
					// Character expressions must have no length, or be completely blank to be considered empty

					//////////
					// Iterate through each character
					//////
						for (lnI = 0; lnI < (u32)varExpr->value.length; lnI++)
						{
							// If we encounter anything other than spaces, not empty
							if (varExpr->value.data[lnI] != 32)
							{
								llEmpty = false;
								break;
							}
						}
						break;


				case _VAR_TYPE_NUMERIC:
					// Numerics are stored as numbers, possibly with a minus sign and the point separator

					//////////
					// Grab the point character
					//////
						if ((varPoint = propGet_settings_Point(_settings)))
						{
							// Extract it
							cPointChar	= varPoint->value.data_s8[0];
							iVariable_delete(thisCode, varPoint, true);

						} else {
							// Default to the standard period
							cPointChar	= cgcPointChar[0];
						}


					//////////
					// Iterate through
					//////
						for (lnI = 0; lnI < (u32)varExpr->value.length; lnI++)
						{
							// If we encounter a non-space, non-zero, or a non-point character, it's then not empty
							c = varExpr->value.data[lnI];
							if (c != 32 && c != '0' && c != cPointChar)
							{
								llEmpty = false;
								break;
							}
						}
						break;


				case _VAR_TYPE_DATETIMEX:
					llEmpty = (varExpr->value.data_dtx->jseconds < 0);
					break;

				case _VAR_TYPE_DATETIME:
					llEmpty = ((varExpr->value.data_dt->julian == _DATETIME_BLANK_DATETIME_JULIAN) && (varExpr->value.data_dt->seconds == _DATETIME_BLANK_DATETIME_SECONDS));
					break;

				case _VAR_TYPE_LOGICAL:
					llEmpty = !(varExpr->value.data_s8[0] == _LOGICAL_TRUE);
					break;

				case _VAR_TYPE_S8:
				case _VAR_TYPE_U8:
					llEmpty = (*varExpr->value.data_u8 == 0);
					break;

				case _VAR_TYPE_S16:
				case _VAR_TYPE_U16:
					llEmpty = (*varExpr->value.data_u16 == 0);
					break;

				case _VAR_TYPE_S32:
				case _VAR_TYPE_U32:
					llEmpty = (*varExpr->value.data_u32 == 0);
					break;

				case _VAR_TYPE_S64:
				case _VAR_TYPE_U64:
				case _VAR_TYPE_CURRENCY:
					llEmpty = (*varExpr->value.data_u64 == 0);
					break;

				case _VAR_TYPE_F32:
					llEmpty = (*varExpr->value.data_f32 == 0.0f);
					break;

				case _VAR_TYPE_F64:
					llEmpty = (*varExpr->value.data_f64 == 0.0);
					break;

//				case _VAR_TYPE_BI:
//					// Big integer
//					break;

//				case _VAR_TYPE_BFP:
//					// Big floating point
//					break;

				default:
					iError_reportByNumber(thisCode, _ERROR_FEATURE_NOT_AVAILABLE, NULL, false);
					return(NULL);
			}


		//////////
		// Signify our result
		//////
			return(llEmpty);

	}