void WarnAboutUnknownSymbol(CString symbol) {
  // Empty symbol 
  // Can happen by DLL or by incorrect parse-tree.
  if (symbol == "") {
    CString error_message = CString("Empty symbol in CGrammar::EvaluateSymbol()\n")
      + CString("This is most probably an incorrect lookup from a DLL.\n");
    OH_MessageBox_Formula_Error(error_message, title_unknown_symbol);
    return;
  }
  // Unknown symbol -- general warning
  CString error_message = CString("Unknown symbol in CGrammar::EvaluateSymbol(): \"")
    + symbol + CString("\"\nThis is most probably a typo in the symbols name.\n")
  + CString("Please check your formula and your DLL.");
  OH_MessageBox_Formula_Error(error_message, title_unknown_symbol);
}
void CSymbolEngineMemorySymbols::ErrorUnnamedMemorySymbol(CString command) {
  // Handles wrong me_re_ and me_inc_ commands
  // but not me_st_.
  CString message;
  message.Format("Invalid memory-symbol: %s\n"
    "Missing variable name.\n"
    "Memory-recall and memory-increment commands must contain\n"
    "  * the prefix me_re_ or me_inc_\n"
    "  * the name of the variable\n"
    " Example: me_inc_ContiBetsRaised\n",
    command);
  OH_MessageBox_Formula_Error(message, "Error");
}
void CSymbolEngineMemorySymbols::ErrorInvalidMemoryStoreCommand(CString command) {
  // Handles wrong me_st_ commands.
  CString message;
  message.Format("Invalid memory-symbol: %s\n"
    "Memory-store-commands must contain\n"
    "  * the prefix me_st_\n"
    "  * the name of the variable\n"
    "  * another underscore\n"
    "  * a value\n"
    " Example: me_st_Pi_3_141592653\n",
    command);
  OH_MessageBox_Formula_Error(message, "Error");
}
bool IsOutdatedSymbol(CString symbol) {
  // This function gets called for every symbol lookup.
  // So we optimize it a bit.
  // Fast switch, depending on first character
  // No check for length > 0 needed, as checking \0 won't harm.
  char first_character = symbol[0];
  switch (first_character) {
    case 'a':
      if (symbol == "ac_aggressor ") {
	      OH_MessageBox_Formula_Error(outdated_symbol_ac_aggressor, title_outdated_symbol);
	    return true;
      }
      if ((symbol == "allidelay") || (symbol == "activemethod")) {
	      OH_MessageBox_Formula_Error(outdated_symbols_tablemap, title_outdated_symbol);
	    return true;
      }
    case 'b':
      if (symbol == "br") {
	    OH_MessageBox_Formula_Error(outdated_symbols_br_ncps_nflopc_chair, title_outdated_symbol);
	    return true;
      }
      if (symbol == "bankroll") {
	      OH_MessageBox_Formula_Error(outdated_symbols_bankroll_rake_defcon, title_outdated_symbol);
	      return true;
      } 
    case 'c': 
      if (symbol == "chair") {
	      OH_MessageBox_Formula_Error(outdated_symbols_br_ncps_nflopc_chair, title_outdated_symbol);
	      return true;
      }
      if (symbol == "callshort") {
	      OH_MessageBox_Formula_Error(outdated_symbols_callshort_raisshort, title_outdated_symbol);
	      return true;
      }
      if (symbol == "clocks") {
	      OH_MessageBox_Formula_Error(outdated_symbol_clocks, title_outdated_symbol);
	      return true;
      }
    case 'd':
      if (symbol == "defcon") {
	      OH_MessageBox_Formula_Error(outdated_symbols_bankroll_rake_defcon, title_outdated_symbol);
	      return true;
      } 
    case 'e':
      if (symbol == "elapsed1970") {
	      OH_MessageBox_Formula_Error(outdated_various_symbols, title_outdated_symbol);
	      return true;
      }
    case 'f':
      if (symbol.Left(7) == "friends") {
	      OH_MessageBox_Formula_Error(outdated_symbol_friends, title_outdated_symbol);
	      return true;
      }
    case 'h':
      if (symbol == "handrank") {
	      OH_MessageBox_Formula_Error(outdated_symbol_handrank, title_outdated_symbol);
	      return true;
      }
    case 'i': 
      if ((symbol == "islistcall") || (symbol == "islistrais") 
	        || (symbol == "islistalli") || (symbol == "isemptylistcall") 
	        || (symbol == "isemptylistrais") || (symbol == "isemptylistalli")) {
	      OH_MessageBox_Formula_Error(outdated_symbols_lists, title_outdated_symbol);
	      return true;
      }
      if (symbol.Left(6) == "islist") {
        OH_MessageBox_Formula_Error(outdated_symbols_islist_symbols, title_outdated_symbol);
        return true;
      }
      if ((symbol == "isbring") || (symbol == "ismanual")) {
	      OH_MessageBox_Formula_Error(outdated_symbols_isbring_ismanual, title_outdated_symbol);
	      return true;
      }
      if ((symbol == "isfiveofakind") || (symbol == "isaggmode") 
	       || (symbol == "isdefmode")) {
	      OH_MessageBox_Formula_Error(outdated_various_symbols, title_outdated_symbol);
	      return true;
      }
    case 'm':
      if (symbol.Left(3) == "mh_") {
	      OH_MessageBox_Formula_Error(outdated_symbols_handstrength, title_outdated_symbol);
	      return true;
      }
    case 'n':
      if ((symbol == "nlistmax") || (symbol == "nlistmin")) {
	      OH_MessageBox_Formula_Error(outdated_symbols_lists, title_outdated_symbol);
	      return true;
      }
      if (symbol == "nopponents") {
        OH_MessageBox_Formula_Error(outdated_symbol_nopponents, title_outdated_symbol);
        return true;
      }
      if (symbol == "nopponentsmax") {
	      OH_MessageBox_Formula_Error(outdated_various_symbols, title_outdated_symbol);
	      return true;
      }
      if (symbol == "nopponentsraising") {
        OH_MessageBox_Formula_Error(outdated_symbol_nopponentsraising, title_outdated_symbol);
        return true;
      }
      if (symbol == "ncommoncardspresent") {
	      OH_MessageBox_Formula_Error(outdated_symbol_ncommoncardspresent, title_outdated_symbol);
	      return true;
      }
      if (symbol == "nclockspersecond") {
	      OH_MessageBox_Formula_Error(outdated_symbol_clocks, title_outdated_symbol);
	      return true;
      }
      if ((symbol == "ncps") || (symbol == "nflopc")) {
	      OH_MessageBox_Formula_Error(outdated_symbols_br_ncps_nflopc_chair, title_outdated_symbol);
	      return true;
      }
      if (symbol.Left(8) == "nfriends") {
	      OH_MessageBox_Formula_Error(outdated_symbol_friends, title_outdated_symbol);
	      return true;
      }
    case 'o':
      if (symbol == "originaldealposition") {
	      OH_MessageBox_Formula_Error(outdated_symbol_originaldealposition, title_outdated_symbol);
	      return true;
      }
      if (symbol == "oppdealt") {
	      OH_MessageBox_Formula_Error(outdated_symbols_br_ncps_nflopc_chair, title_outdated_symbol);
	      return true;
      }
    case 'p':
      if (symbol.Left(3) == "ptt") {
	      OH_MessageBox_Formula_Error(outdated_symbols_ptt, title_outdated_symbol);
	      return true;
      }
      if (symbol == "potdelay") {
	      OH_MessageBox_Formula_Error(outdated_symbols_tablemap, title_outdated_symbol);
	      return true;
      }
    case 'r':
      if (symbol == "raisshort") {
	      OH_MessageBox_Formula_Error(outdated_symbols_callshort_raisshort, title_outdated_symbol);
	      return true;
      }
      if (// Attention: "randomround" is valid
	      // Only randomround1..rnadomround4 are outdated
	      (symbol.GetLength() == 12) && (symbol.Left(11) == "randomround")) {
	      OH_MessageBox_Formula_Error(outdated_symbols_randomround, title_outdated_symbol);
	      return true;
      }
      if ((symbol.Left(4) == "run$") || (symbol.Left(4) == "ron$")) {
	      OH_MessageBox_Formula_Error(outdated_symbols_runron, title_outdated_symbol);
	      return true;
      }
      if (symbol == "rake") {
	      OH_MessageBox_Formula_Error(outdated_symbols_bankroll_rake_defcon, title_outdated_symbol);
	      return true;
      } 
    case 's': 
      if ((symbol == "swagdelay") || (symbol == "swagtextmethod")) {
	      OH_MessageBox_Formula_Error(outdated_symbols_tablemap, title_outdated_symbol);
	      return true;
      }
    case 'N':
      if (symbol == "NIT") {
	      OH_MessageBox_Formula_Error(outdated_symbol_NIT, title_outdated_symbol);
	      return true;
      }
    default: 
	  // Good symbol for sure
	  return false;
  }
}
void CSymbolEnginePokerTracker::WarnAboutInvalidPTSymbol(CString s) {
	CString error_message;
  error_message.Format("Invalid PokerTracker-symbol: %s\n", s);
	OH_MessageBox_Formula_Error(error_message, "Error");
}
bool CSymbolEnginePokerTracker::EvaluateSymbol(const char *name, double *result, bool log /* = false */)
{
  FAST_EXIT_ON_OPENPPL_SYMBOLS(name);
	if (memcmp(name,"pt_",3)!=0)
	{
		// Symbol of a different symbol-engine
		return false;
	}
	CString s = name;
	CheckForChangedPlayersOncePerHeartbeatAndSymbolLookup();
	if (IsOldStylePTSymbol(s))
	{
		CString error_message;
		error_message.Format(
			"Old style PokerTracker symbol detected: %s.\n"
			"\n"
			"PokerTracker symbol start with \"pt_\".\n"
      "Possible postfixes:\n"
      "  * chair number (0..9)\n"
      "  * _raischair\n"
      "  * _headsup\n"
      "  * _smallblind\n"
      "  * _bigblind\n"
      "  * _dealer\n"
      "  * _cutoff\n"
      "  * _user\n"
      "  * _firstraiser\n"
      "  * _firstcaller\n"
      "  * _lastcaller\n", s);
		OH_MessageBox_Formula_Error(
			error_message,			 
			"ERROR: Invalid PokerTracker Symbol");
		*result = kUndefined;
		return true;
	}
	if (!PT_DLL_IsValidSymbol(CString(s)))
	{
		// Invalid PokerTracker symbol
		WarnAboutInvalidPTSymbol(s);
		*result = kUndefined;
		return true;
	}
	int chair = 0;

	if (!p_pokertracker_thread->IsConnected()) 	{
		if (!p_symbol_engine_userchair->userchair_confirmed() || p_formula_parser->IsParsing()) {
			// We are not yet seated or formula is getting parsed.
			// Symbol-lookup happens, because of Formula-validation.
			// Not a problem, if we do not yet have a DB-connection.
			// Don't throw a warning here.
       write_log(preferences.debug_pokertracker(), "[PokerTracker] Not yet seated or formula parsing.\n");
		} else {
			// We are seated and playing.
			// Serious problem, if we do not have a DB-connection.
			OH_MessageBox_Error_Warning("Not connected to PokerTracker database.\n"
				"Can't use PokerTracker symbols.");
		}
		*result = kUndefined;
		return true;
	}

	CString standard_symbol_name;
	assert(StringAIsPrefixOfStringB("pt_", s));
	// PokerTracker symbols for the raise-chair
	if (s.Right(10) == "_raischair") {
		chair = p_symbol_engine_raisers->raischair();
	}
	// PokerTracker symbols for the opponent headsup chair
	else if (s.Right(8) == "_headsup") {
    chair = p_symbol_engine_chairs->opponent_headsup_chair();
	}
  // PokerTracker symbols for the smallblind chair
	else if (s.Right(11) == "_smallblind") {
    chair = p_symbol_engine_chairs->smallblind_chair();
	}
  // PokerTracker symbols for the bigblind chair
	else if (s.Right(9) == "_bigblind") {
    chair = p_symbol_engine_chairs->bigblind_chair();
	}
  // PokerTracker symbols for the cutoff chair
	else if (s.Right(7) == "_cutoff") {
    chair = p_symbol_engine_chairs->cutoff_chair();
	}
  // PokerTracker symbols for the firstcaller chair
	else if (s.Right(12) == "_firstcaller") {
    chair = p_symbol_engine_callers->firstcaller_chair();
	}
  // PokerTracker symbols for the lastcaller chair
	else if (s.Right(11) == "_lastcaller") {
    chair = p_symbol_engine_callers->lastcaller_chair();
	}
  // PokerTracker symbols for the firstraiser chair
	else if (s.Right(12) == "_firstraiser") {
		chair = p_symbol_engine_raisers->firstraiser_chair();
	}
  // PokerTracker symbols for the dealerchair chair
	else if (s.Right(7) == "_dealer") {
    chair = p_symbol_engine_dealerchair->dealerchair();
	}
  // PokerTracker symbols for the  chair
	else if (s.Right(5) == "_user") {
    chair = p_symbol_engine_userchair->userchair();
	}
  // PokerTracker symbols for chair X
	else {
		CString symbol = s;
		CString last_character = symbol.Right(1);
    if (!isdigit(last_character[0])) {
      CString error_message;
      error_message.Format("Invalid PokerTracker Symbol: &s",
        symbol);
      OH_MessageBox_Formula_Error(error_message, "ERROR");
		  *result = kUndefined;
      return false;
    }
		chair = atoi(last_character);
	}
  // Catch undefined chair (e.g. pt_r_-symbol without raisee)
  if (chair < 0) {
    *result = kUndefined;
    return true;
  }
	AssertRange(chair, kFirstChair, kLastChair);
	*result = PT_DLL_GetStat(s, chair); 
	return true;
}