////////// // // 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); }
////////// // // 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; }
////////// // // 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; }
////////// // // 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; }
////////// // // 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; }
////////// // // 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); }
////////// // // 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; }
////////// // // 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; }
////////// // // 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; }
////////// // // 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; }
////////// // // 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; }
////////// // // 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; }
// 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; }
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); }