LPTSTR FuncTokenToString(ExprTokenType &aToken, LPTSTR aBuf) // Supports Type() VAR_NORMAL and VAR-CLIPBOARD. // Returns "" on failure to simplify logic in callers. Otherwise, it returns either aBuf (if aBuf was needed // for the conversion) or the token's own string. aBuf may be NULL, in which case the caller presumably knows // that this token is SYM_STRING or SYM_OPERAND (or caller wants "" back for anything other than those). // If aBuf is not NULL, caller has ensured that aBuf is at least MAX_NUMBER_SIZE in size. { switch (aToken.symbol) { case SYM_VAR: // Caller has ensured that any SYM_VAR's Type() is VAR_NORMAL. return aToken.var->Contents(); // Contents() vs. mContents to support VAR_CLIPBOARD, and in case mContents needs to be updated by Contents(). case SYM_STRING: case SYM_OPERAND: return aToken.marker; case SYM_INTEGER: if (aBuf) return ITOA64(aToken.value_int64, aBuf); //else continue on to return the default at the bottom. break; case SYM_FLOAT: if (aBuf) { sntprintf(aBuf, MAX_NUMBER_SIZE, g->FormatFloat, aToken.value_double); return aBuf; } //else continue on to return the default at the bottom. break; //case SYM_OBJECT: // L31: Treat objects as empty strings (or TRUE where appropriate). //default: // Not an operand: continue on to return the default at the bottom. } return _T(""); }
/* print a brief resume of the input ("filename:line:car: " or ""str":car: ") */ tchar * escm_input_prefix(escm_input *f) { tchar *buf, *p; size_t len, all, rest, n; assert(f != NULL); if (f->type == INPUT_FILE) { len = strlen(f->d.file.name); all = len + 50; /* enough for "name:LONG_MAX:LONG_MAX: " */ buf = xmalloc(all * sizeof *buf); n = sntprintf(buf, len + 1, T("%s"), f->d.file.name); /* XXX: n == -1? */ p = buf + n; *p++ = T(':'); rest = all - n - 1; if (f->d.file.line != -1) { n = sntprintf(p, rest, T("%ld"), f->d.file.line); while (n >= rest) { all += 50; rest += 50; buf = xrealloc(buf, all * sizeof *buf); p = buf + all - rest; n = sntprintf(p, rest, T("%ld"), f->d.file.line); } p += n; rest -= n; } if (f->d.file.car != -1) { n = sntprintf(p, rest, T(":%ld: "), f->d.file.car); while (n >= rest) { all += 50; rest += 50; buf = xrealloc(buf, all * sizeof *buf); p = buf + all - rest; n = sntprintf(p, rest, T(":%ld: "), f->d.file.car); } p += n; rest -= n; } else { if (rest <= 4) { all += 5; rest += 5; buf = xrealloc(buf, all * sizeof *buf); p = buf + all - rest; sntprintf(p, rest, T(":: ")); } p += n; rest -= n; } } else { len = tcslen(f->d.str.str) * sizeof(tchar); all = len + 50; /* well enough for "name":LONG_MAX: " */ buf = xmalloc(all * sizeof *buf); n = sntprintf(buf, all, T("\"%") TFMT T("s\":%td: "), f->d.str.str, f->d.str.cur - f->d.str.str); while (n >= all) { all += 50; buf = xrealloc(buf, all * sizeof *buf); n = sntprintf(buf, all, T("\"%") TFMT T("s\":%td: "), f->d.str.str, f->d.str.cur - f->d.str.str); } } return buf; }
//H30 changed to not return anything since it is not used void callFuncDll(FuncAndToken *aFuncAndToken) { Func &func = *(aFuncAndToken->mFunc); ExprTokenType & aResultToken = aFuncAndToken->mToken ; // Func &func = *(Func *)g_script.mTempFunc ; if (!INTERRUPTIBLE_IN_EMERGENCY) return; if (g_nThreads >= g_MaxThreadsTotal) // Below: Only a subset of ACT_IS_ALWAYS_ALLOWED is done here because: // 1) The omitted action types seem too obscure to grant always-run permission for msg-monitor events. // 2) Reduction in code size. if (g_nThreads >= MAX_THREADS_EMERGENCY // To avoid array overflow, this limit must by obeyed except where otherwise documented. || func.mJumpToLine->mActionType != ACT_EXITAPP && func.mJumpToLine->mActionType != ACT_RELOAD) return; // Need to check if backup is needed in case script explicitly called the function rather than using // it solely as a callback. UPDATE: And now that max_instances is supported, also need it for that. // See ExpandExpression() for detailed comments about the following section. VarBkp *var_backup = NULL; // If needed, it will hold an array of VarBkp objects. int var_backup_count; // The number of items in the above array. if (func.mInstances > 0) // Backup is needed. if (!Var::BackupFunctionVars(func, var_backup, var_backup_count)) // Out of memory. return; // Since we're in the middle of processing messages, and since out-of-memory is so rare, // it seems justifiable not to have any error reporting and instead just avoid launching // the new thread. // Since above didn't return, the launch of the new thread is now considered unavoidable. // See MsgSleep() for comments about the following section. TCHAR ErrorLevel_saved[ERRORLEVEL_SAVED_SIZE]; tcslcpy(ErrorLevel_saved, g_ErrorLevel->Contents(), _countof(ErrorLevel_saved)); InitNewThread(0, false, true, func.mJumpToLine->mActionType); // v1.0.38.04: Below was added to maximize responsiveness to incoming messages. The reasoning // is similar to why the same thing is done in MsgSleep() prior to its launch of a thread, so see // MsgSleep for more comments: g_script.mLastScriptRest = g_script.mLastPeekTime = GetTickCount(); DEBUGGER_STACK_PUSH(func.mJumpToLine, func.mName) // ExprTokenType aResultToken; // ExprTokenType &aResultToken = aResultToken_to_return ; func.Call(&aResultToken); // Call the UDF. DEBUGGER_STACK_POP() switch (aFuncAndToken->mToken.symbol) { case SYM_VAR: // Caller has ensured that any SYM_VAR's Type() is VAR_NORMAL. if (_tcslen(aFuncAndToken->mToken.var->Contents())) { aFuncAndToken->result_to_return_dll = (LPTSTR )realloc((LPTSTR )aFuncAndToken->result_to_return_dll,_tcslen(aFuncAndToken->mToken.var->Contents())*sizeof(TCHAR)); _tcscpy(aFuncAndToken->result_to_return_dll,aFuncAndToken->mToken.var->Contents()); // Contents() vs. mContents to support VAR_CLIPBOARD, and in case mContents needs to be updated by Contents(). } else if (aFuncAndToken->result_to_return_dll) *aFuncAndToken->result_to_return_dll = '\0'; break; case SYM_STRING: case SYM_OPERAND: if (_tcslen(aFuncAndToken->mToken.marker)) { aFuncAndToken->result_to_return_dll = (LPTSTR )realloc((LPTSTR )aFuncAndToken->result_to_return_dll,_tcslen(aFuncAndToken->mToken.marker)*sizeof(TCHAR)); _tcscpy(aFuncAndToken->result_to_return_dll,aFuncAndToken->mToken.marker); } else if (aFuncAndToken->result_to_return_dll) *aFuncAndToken->result_to_return_dll = '\0'; break; case SYM_INTEGER: aFuncAndToken->result_to_return_dll = (LPTSTR )realloc((LPTSTR )aFuncAndToken->result_to_return_dll,MAX_INTEGER_LENGTH); ITOA64(aFuncAndToken->mToken.value_int64, aFuncAndToken->result_to_return_dll); break; case SYM_FLOAT: result_to_return_dll = (LPTSTR )realloc((LPTSTR )aFuncAndToken->result_to_return_dll,MAX_INTEGER_LENGTH); sntprintf(aFuncAndToken->result_to_return_dll, MAX_NUMBER_SIZE, g->FormatFloat, aFuncAndToken->mToken.value_double); break; //case SYM_OBJECT: // L31: Treat objects as empty strings (or TRUE where appropriate). default: // Not an operand: continue on to return the default at the bottom. if (aFuncAndToken->result_to_return_dll) *aFuncAndToken->result_to_return_dll = '\0'; } //Var::FreeAndRestoreFunctionVars(func, var_backup, var_backup_count); ResumeUnderlyingThread(ErrorLevel_saved); return; }