예제 #1
0
String EvalExpr::ExpStr(CParser& p, int numDigits) {
	String x = MulStr(p, numDigits);
	for(;;) {
		if(p.Char('+'))
			x = x + " + " + MulStr(p, numDigits);
		else if(p.Char('-'))
			x = x + " - " + MulStr(p, numDigits);
		else if(p.Char(':'))
			x = x + ":" + MulStr(p, numDigits);
		else {
			x.Replace("+ -", "- ");
			return x;
		}
	}
}
예제 #2
0
TInt E32Main()
	{
	__UHEAP_MARK;
	CTrapCleanup* cleanup=CTrapCleanup::New();
 
 	// set filename
	TFileName theFileName = _L("c:\\etext\\incp\\dunk.pml");

	// Parse PML
	CParser* myParser;
	CRichText* richTextDoc;
	TRAPD(ret, myParser=CParser::NewL());
	TRAP(ret, richTextDoc = myParser->ParseL(theFileName));

// *********** insert test code here ****************


/*	TInt para=richTextDoc->CountParas();
	TInt length=richTextDoc->DocumentLength();
	CParaFormat* myformat;
	TRAP(ret,myformat=CParaFormat::NewL());
	TCharFormat charFormat; CPicture* picture; TPtrC view;
	TRAP(ret,richTextDoc->SenseParaFormatL(length,myformat));
	TRAP(ret,richTextDoc->SenseChars(0,view,charFormat,picture));
	TRAP(ret,richTextDoc->SenseChars(10,view,charFormat,picture));
	richTextDoc->Delete(4,6);
	//TRAP(ret,richTextDoc->InsertL(richTextDoc->DocumentLength(),EParagraphDelimiter));
*/

	// make rich text reader & read rich text doc & parse back to PML
	CRichTextReader* myRTReader;
	CBufSeg* returnedPmlDoc; 
	TRAP(ret, myRTReader = CRichTextReader::NewL());
	TRAP(ret, returnedPmlDoc = myRTReader->ConvertRichText(richTextDoc));

	// save to disc
	CFileApp* myFileApp;
	TRAP(ret, myFileApp = CFileApp::NewL());
	TInt errorLevel = myFileApp->SaveFile(returnedPmlDoc,theFileName);

	// finish up
	Adt::Destroy(myFileApp);
	Adt::Destroy(myRTReader);
	Adt::Destroy(myParser);
	Adt::Destroy(cleanup);
	__UHEAP_MARKEND;
	return 0;
	}
예제 #3
0
파일: CDatas.cpp 프로젝트: Stroff/Amonsoft
//----------------------------------------------------------------------------
// Export Entreprise to XML file
//----------------------------------------------------------------------------
void Datas::exportEntreprise( QString filename, const CEntreprise &p )
{
    qDebug( "CDatas::exportPersonne" );

    // Fake to keep information about global which is used by gerant and employe save function
    CParser *parserEntses = g_ParserEntses;

    CParser *Parser = new CParser( filename );
    g_ParserEntses = Parser;
    Parser->initWrite( "Exportation" );
    p.saveToXML( Parser->getDocument() );
    Parser->writeFile();
    delete Parser;

    g_ParserEntses = parserEntses;
}
예제 #4
0
Point ReadPoint(CParser& p)
{
	Point pt;
	pt.x = p.ReadInt();
	pt.y = p.ReadInt();
	return pt;
}
예제 #5
0
파일: compiler.cpp 프로젝트: mildrock/dummy
bool CCompiler::_CheckName()
{
	int i;
	CStrMap oMapName;
	for(int nParser = 0; nParser < (int)m_oVecChildParsers.size(); nParser++)
	{
		CParser* poParser = m_oVecChildParsers[nParser];
		for(i = 0; i < poParser->GetDefineInfoCount(); i++)
		{
			SDefineInfo* pstDefineInfo = poParser->GetDefineInfoByPos(i);
			if(oMapName.find(pstDefineInfo->szName) != oMapName.end())
			{
				m_strErrMsg.Format("%s error: <define name=%s> already defined", poParser->GetName(), pstDefineInfo->szName);
				return false;
			}
			oMapName[pstDefineInfo->szName] = 0;
			m_oDefineInfoMap[pstDefineInfo->szName] = pstDefineInfo;
		}

		for(i = 0; i < poParser->GetTypeInfoCount(); i++)
		{
			STypeInfo* pstTypeInfo = poParser->GetTypeInfoByPos(i);
			if(oMapName.find(pstTypeInfo->szName) != oMapName.end())
			{
				m_strErrMsg.Format("%s error: <type name=%s> already defined", poParser->GetName(), pstTypeInfo->szName);
				return false;
			}
			oMapName[pstTypeInfo->szName] = 0;

			pstTypeInfo->nSeq = ++m_nTypeSeq;
			m_oMapTypeInfo[pstTypeInfo->szName] = pstTypeInfo;
		}

		for(i = 0; i < poParser->GetMessageInfoCount(); i++)
		{
			SMessageInfo* pstMessageInfo = poParser->GetMessageInfoByPos(i);
			if(oMapName.find(pstMessageInfo->szName) != oMapName.end())
			{
				m_strErrMsg.Format("%s error: <message name=%s> already defined", poParser->GetName(), pstMessageInfo->szName);
				return false;
			}
			oMapName[pstMessageInfo->szName] = 0;
		}
	}
	return true;
}
예제 #6
0
/* calculate expression from inputtext */
EXP_ValueHandle EXP_ParseInput(const char* inputtext)
{
	CValue* resultval=NULL;
	CParser parser;
	CExpression* expr = parser.ProcessText(inputtext);
	if (expr)
	{
		resultval = expr->Calculate();
		expr->Release();
	}
	else
	{
		resultval = new CErrorValue("couldn't parsetext");
	}

	return (EXP_ValueHandle) resultval;
}
예제 #7
0
int main(int argc, const char** argv)
{
	CParser cParser;
	CConverter cConv;

	if(argc<3) {
		usage();
		return 0;
	}

	cParser.Parse(argc,argv);
	cConv = CConverter(&cParser);
	if (cConv.GenerateTextures() != EXIT_SUCCESS) return EXIT_FAILURE;
	if (cConv.WriteTextures() != EXIT_SUCCESS) return EXIT_FAILURE;

	return 0;
}
예제 #8
0
String EvalExpr::PowStr(CParser& p, int numDigits) {
	String x = TermStr(p, numDigits);
	for(;;)
		if(p.Char('^'))
			x = x + "^" + TermStr(p, numDigits);
		else
			return x;
}
예제 #9
0
String EvalExpr::TermStr(CParser& p, int numDigits) {
	if(p.IsId()) {
		String strId = p.ReadId();
		if(functions.Find(strId) >= 0) {
			p.PassChar('(');
			String x = ExpStr(p, numDigits);
			p.PassChar(')');
			return strId + "(" + x + ")";
		}
		if (noCase)
			strId = ToUpper(strId);
		if (IsNull(numDigits)) {
			if (constants.Find(strId) < 0)
				variables.GetAdd(strId, 0);
			return strId;
		} else {
			if (constants.Find(strId) >= 0)
				return strId;
			else {
				double dat = variables.GetAdd(strId, 0);
				return FormatDoubleFix(dat, numDigits);
			}
		}
	}
	if(p.Char('(')) {
		String x = ExpStr(p, numDigits);
		p.PassChar(')');
		return "(" + x + ")";
	}
	return FormatDoubleFix(p.ReadDouble(), IsNull(numDigits) ? 3 : numDigits);
}
예제 #10
0
double EvalExpr::Pow(CParser& p) {
	double x = Term(p);
	for(;;) {
		if(p.Char('^'))
			x = pow(x, Term(p));
		else
			return x;
	}
}
예제 #11
0
파일: compiler.cpp 프로젝트: mildrock/dummy
bool CCompiler::_Parse(LPCTSTR pszFile, BOOL bCliEnDe)
{
	if(false == m_oMainParser.Parse(pszFile, &m_oMainParser, bCliEnDe))
	{
		m_strErrMsg.Format("Parse %s failed:\r\n %s", pszFile, m_oMainParser.GetErrMsg());
		return false;
	}

	char szDir[MAX_PATH];
	lstrcpyn(szDir, pszFile, sizeof(szDir));
	char* p = szDir;
	while(*p != '\0')
	{
		if(*p == '/')
			*p = '\\';
		p++;
	}
	p = strrchr(szDir, '\\');
	if(p != NULL)
		*(p+1) = '\0';
	else
		szDir[0] = '\0';

	for(int i = 0; i < m_oMainParser.GetIncludeInfoCount(); i++)
	{
		SIncludeInfo* pstInfo = m_oMainParser.GetIncludeInfoByPos(i);
		ASSERT(pstInfo != NULL);

		char szFile[MAX_PATH];
		sprintf(szFile, "%s%s", szDir, pstInfo->szFile);

		CParser* poParser = new CParser;
		if(false == poParser->Parse(szFile, &m_oMainParser, bCliEnDe))
		{
			m_strErrMsg.Format("Parse %s failed:\r\n %s", szFile, poParser->GetErrMsg());
			delete poParser;
			return false;
		}

		m_oVecChildParsers.push_back(poParser);
	}

	return true;
}
예제 #12
0
/**
@SYMTestCaseID 		 		SYSLIB-XML-CT-3748
@SYMTestCaseDesc		    Processing namespaces.
@SYMTestPriority 		    Medium
@SYMTestActions  		    Creating an xml parser and enabling namespace mapping reporting, before parsing a document.
@SYMTestExpectedResults 	The document is parsed with the namespace mapping reporting enabled.
@SYMDEF 		 		 	INC059062
*/
LOCAL_C void INC059062L()
	{
	RDefectTests handler;
	CleanupClosePushL (handler);

	CParser* parser = CParser::NewLC(KXmlParserDataType, handler);

	User::LeaveIfError(parser->EnableFeature(EReportNamespaceMapping));

	RFile handle;
	handle.Open(TheFs, KNsAndBindingFile, EFileShareReadersOnly);
	CleanupClosePushL (handle);

	ParseL(*parser, handle);

	CleanupStack::PopAndDestroy (&handle);
	CleanupStack::PopAndDestroy (parser);
	CleanupStack::PopAndDestroy (&handler);
	}
예제 #13
0
void Ctrl::ReadKeyMods(CParser& p)
{
	const char *s = p.GetPtr();
	if(*s)
		keyShift = *s++ == '1';
	if(*s)
		keyCtrl = *s++ == '1';
	if(*s)
		keyAlt = *s++ == '1';
}
예제 #14
0
LOCAL_C void Defect_DEF096973L()
	{

	test.Next(_L(" @SYMTestCaseID:SYSLIB-XML-CT-3173 "));
	TBuf16<128> ucs4_0041;

	ucs4_0041.Append(0x01);
	ucs4_0041.Append(0x04);
	ucs4_0041.Append(0x6A);
	ucs4_0041.Append(0x00);
	ucs4_0041.Append(0x7F);
	ucs4_0041.Append(0x02);
	ucs4_0041.Append(0x80);
	ucs4_0041.Append(0x41);
	ucs4_0041.Append(0x01);
	ucs4_0041.Append(0x01); //Extra END tag

	_LIT8 (KWbxmlParserDataType, "text/wbxml");

	RDefectTests handler;
	CleanupClosePushL (handler);

	CParser* parser = CParser::NewL(KWbxmlParserDataType, handler);
	CleanupStack::PushL (parser);


	// Now switch to a different parser (wbxml)
	parser->ParseBeginL (KWbxmlParserDataType);

	TBuf8<256> buf8;
	// Copy will ignore the upper byte if the byte-pair < 256, otherwise the value 1 is used.
	buf8.Copy(ucs4_0041);

	TRAPD (err,parser->ParseL(buf8));
	test(err == KErrXmlDocumentCorrupt);

	parser->ParseEndL();


	CleanupStack::PopAndDestroy (parser);
	CleanupStack::PopAndDestroy (&handler);
	}
예제 #15
0
CCommandEventManager::CScriptNode	*parseWhile()
{
	Parser.skipSpace();

	CWhileNode	*node = new CWhileNode();
	node->Root = parsedScript;
	node->Line = Parser.Line;
	node->Condition = Parser.getLine();
	Parser.skipLine();

	node->Statement = parseInstructionList();

	if (Parser.getToken() != TOKEN_ENDLOOP)
	{
		nlwarning("[%s] Unknown token found in structure while, expected endloop at line %d. Skip line", parsedScript->Name.c_str(), Parser.Line);
		Parser.skipLine();
	}

	return (CCommandEventManager::CScriptNode*)node;
}
예제 #16
0
//User has selected FSX addon menu ("VatConnect...")
void CFSXGUI::OnFSXAddonMenuSelected()
{
	if (m_bRunning)
		return;

	m_bRunning = true;
	if (!m_bGraphicsInitialized)
	{
		m_apDialogs.push_back(&m_dlgMain);
		m_apOpenDialogs.push_back(&m_dlgMain);
	}

	//Determine full path to preferences file. 
	PWSTR pPath;
	if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &pPath)))
	{
		WCHAR Temp[MAX_PATH];
		size_t n;
		wcscpy_s(Temp, MAX_PATH, pPath);
		CoTaskMemFree(pPath);

		//Make directory just in case not there. Since this is the first module called,
		//other classes don't have to do this.
		PathAppend(Temp, APPDATA_FOLDER);
		CreateDirectory(Temp, NULL);

		PathAppend(Temp, PREF_FILENAME_L);
		wcstombs_s(&n, m_cPrefPathAndFilename, Temp, MAX_PATH);
	}

	//Load preferences/options 
	CParser File;
	CreateDefaultPreferences(false);

	if (!File.SetFileAsInput(m_cPrefPathAndFilename))
		CreateDefaultPreferences(true);
	else
		LoadPreferences(File); //REVISIT if this fails (mangled file?), values are okay but should alert user

	return;
} 
예제 #17
0
void VerifyVersionFile ()
{
	CFileBuffer Buffer (VERSION_PATH, true);
	CParser Parser (Buffer.GetBuffer<char> (), PSP_COMMENT_LINE);

	String prefix;
	Parser.ParseToken (PSF_ALLOW_NEWLINES, prefix);

	uint8 minor;
	uint16 major;
	uint32 build;
	Parser.ParseDataType<uint16> (PSF_ALLOW_NEWLINES, &major, 1);
	Parser.ParseDataType<uint8> (PSF_ALLOW_NEWLINES, &minor, 1);
	Parser.ParseDataType<uint32> (PSF_ALLOW_NEWLINES, &build, 1);

	if (CompareVersion (prefix.CString(), major, minor, build))
	{
		ServerPrint ("Version file out of date; updating...\n");
		WriteVersion ();
	}
}
예제 #18
0
//
// Load()
// Parses a .vmt file.  Note, the parser is very loose.  .vmt files vary
// so much in the official resources that it is hard to know what is legal.
//
vlBool CVMTFile::Load(IO::Readers::IReader *Reader) {
	delete this->Root;
	this->Root = 0;

	if (!Reader->Open()) {
		return vlFalse;
	}
	CByteTokenizer ByteTokenizer = CByteTokenizer(Reader);
	CTokenizer Tokenizer = CTokenizer(&ByteTokenizer);
	CParser Parser = CParser(&Tokenizer);

	try{
		this->Root = Parser.Parse();
	}catch (char *cErrorMessage) {
		LastError.SetFormatted("Error parsing material on line %u (%s).", Tokenizer.GetLine(), cErrorMessage);
	}

	Reader->Close();

	return this->Root != 0;
}
예제 #19
0
CCommandEventManager::CScriptNode	*parseIf()
{
	Parser.skipSpace();

	CIfNode	*node = new CIfNode();
	node->Root = parsedScript;
	node->Line = Parser.Line;
	node->Condition = Parser.getLine();
	Parser.skipLine();

	node->TrueStatement = parseInstructionList();

	uint	token = Parser.getToken();
	if (token == TOKEN_ELSE)
	{
		node->FalseStatement = parseInstructionList();
		token = Parser.getToken();
	}

	if (token != TOKEN_ENDIF)
	{
		nlwarning("[%s] Unknown token found in structure if, expected endif at line %d. Skip line", parsedScript->Name.c_str(), Parser.Line);
		Parser.skipLine();
	}

	return (CCommandEventManager::CScriptNode*)node;
}
예제 #20
0
/*
@SYMTestCaseID          BASESRVCS-XML-UT-4012
@SYMTestCaseDesc	    INC133484-Watchermainthread crashes when receiving corrupted email notification.
@SYMTestPriority 	    High
@SYMTestActions  	    Tests that the wbxml parser can handle parsing of corrupted emnc file.
@SYMTestExpectedResults WBXML Parser should detect corruption or negative length and  leave with KErrXmlDocumentCorrupt
@SYMDEF                 INC133484	
*/
LOCAL_C void Incident_INC133484L()
	{
	_LIT8( KWbxmlParserDataType, "text/wbxml");
	
	RBuf8 aBuf;
	RFs aRfs;
	RFile aRFile;

	
	RDefectTests handler;
	CleanupClosePushL(handler);
	
	CParser* parser = CParser::NewLC( KWbxmlParserDataType, handler );
	parser->ParseBeginL();


	User::LeaveIfError(aRfs.Connect());
	CleanupClosePushL(aRfs);
	
	
	User::LeaveIfError(aRFile.Open(aRfs,KCorruptWAPEmailPushMsg3,EFileRead));
	CleanupClosePushL(aRFile);
	TInt size;
	User::LeaveIfError(aRFile.Size(size));
	aBuf.CreateL(size);
	CleanupClosePushL(aBuf);
	aRFile.Read(aBuf);

	TRAPD(err,parser->ParseL(aBuf));
	// If inside an OOM test loop and alloc failure then report it back to the caller.
	if (OOM_TestingActive && (err == KErrNoMemory))
        User::Leave(err);
    test(err == KErrXmlDocumentCorrupt);
	
	
	CleanupStack::PopAndDestroy(3, &aRfs); 

	CleanupStack::PopAndDestroy (parser);
	CleanupStack::PopAndDestroy (&handler);
	}
예제 #21
0
ICommand* CInputHandler::getCommand(string command)
{
    CParser parser;
    CCommandMetadata* metacmd = parser.parse(command);
    if(metacmd->command.isPresent)
    {
        if(metacmd->command.value == "h")
        {
            if(metacmd->startAddress.isPresent || metacmd->startAddress.isPresent)
            {
                throw EUnexpectedAddress();
                return 0;
            }
        }
    }
    if(!isValid(metacmd))
    {
        throw EInvalidAddress();
        return 0;
    }
    return commandFactory->getCommand(metacmd);
}
예제 #22
0
int main(int argc, char* argv[])
{
	FILE *inf;
	char fistr[100];
	char endr[3];
	printf("Enter filename:\n");
	gets(fistr);
	inf = fopen(fistr,"r");
	if(inf==NULL){
		printf("Cannot open input file %s\n",fistr);
		return 0;
	}
	CParser obj;
	obj.InitParse(inf,stderr,stdout);
//	obj.pr_tokentable();
	obj.yyparse();

	printf("\nEnde?\n");
	gets(endr);
	if(endr=="ja")
	return 0;
}
예제 #23
0
파일: Sch.cpp 프로젝트: AbdelghaniDr/mirror
String ReadId(CParser& p, String& rr)
{
	String id = SchId(p, rr);
	p.Char(',');
	if(p.IsNumber())
		p.ReadNumber();
	p.Char(',');
	if(p.IsNumber())
		p.ReadNumber();
	p.Char(')');
	return id;
}
예제 #24
0
/**
@SYMTestCaseID          SYSLIB-XML-CT-1598
@SYMTestCaseDesc	    Tests to make sure XML parser does not crash when parsing a message that is not complete.
@SYMTestPriority 	    Medium
@SYMTestActions  	    Parses the message that is not complete.
@SYMTestExpectedResults Test must not fail.
@SYMDEF                 INC073797
*/
LOCAL_C void INC073797()
	{
	RFs fs;
	User::LeaveIfError(fs.Connect());
	CleanupClosePushL(fs);

	RFile result;
	TFileName filename;
	User::LeaveIfError(result.Temp(fs, _L("C:\\"), filename, EFileWrite));
	CleanupClosePushL(result);

	TRebuildingContentHandler contentHandler(result);

	CParser* parser = CParser::NewLC(KParserDataType, contentHandler);

	parser->ParseL(KIncompleteData());
	test(contentHandler.iError==KErrNone);

	CleanupStack::PopAndDestroy(2);

	fs.Delete(filename);
	CleanupStack::PopAndDestroy(&fs);
	}
예제 #25
0
/*

PDEF142385-Tests that the wbxml parser can handle parsing of corrupted emnc file.
	
*/
LOCAL_C void Defect_PDEF142385L()
 	{
 	_LIT8( KWbxmlParserDataType, "text/wbxml");
 	
	RBuf8 aBuf;
 	RFs aRfs;
 	RFile aRFile;
 
 	RDefectTests handler;
 	CleanupClosePushL(handler);
 	
 	CParser* parser = CParser::NewLC( KWbxmlParserDataType, handler );
 	parser->ParseBeginL();
 
 
 	User::LeaveIfError(aRfs.Connect());
 	CleanupClosePushL(aRfs);
 	

 	User::LeaveIfError(aRFile.Open(aRfs,KCorruptWAPEmailPushMsg4,EFileRead));
 	CleanupClosePushL(aRFile);
 	TInt size;
 	User::LeaveIfError(aRFile.Size(size));
 	aBuf.CreateL(size);
 	CleanupClosePushL(aBuf);
 	aRFile.Read(aBuf);
 
 	TRAPD(err,parser->ParseL(aBuf));
 	// If inside an OOM test loop and alloc failure then report it back to the caller.
 	if (OOM_TestingActive && (err == KErrNoMemory))
         User::Leave(err);
     // Since the input file is a well formed WBXML, the code should not crash nor should it raise a "KErrXmlDocumentCorrupt" exception
 	test(err == KErrNone);
 	
 	CleanupStack::PopAndDestroy(5); 
 	}
예제 #26
0
//Save preferences to m_cPrefPathAndFilename
int CFSXGUI::SavePreferences()
{
	CParser File;

	if (!File.OpenFileForOutput(m_cPrefPathAndFilename))  
		return 0;
	
	File.WriteString(STR_PREF_HEADER);
	File.WriteString("\nPTTKey = ");
	File.WriteInt(m_Prefs.PTTVKey);

	File.WriteString("\nPTTJoyButton = ");
	File.WriteInt(m_Prefs.PTTJoyButton);

	File.CloseFile();

	return 1;
}
예제 #27
0
String ReadPropertyParam(CParser& p)
{
	const char *b = p.GetPtr();
	int level = 0;
	while(!p.IsEof()) {
		if(p.IsChar(';'))
			break;
		if(p.IsChar(')') && level == 0)
			break;
		if(p.Char(')')) {
			if(level == 0)
				break;
			level--;
		}
		else
		if(p.Char('('))
			level++;
		else
			p.SkipTerm();
	}
	return TrimLeft(TrimRight(String(b, p.GetPtr())));
}
예제 #28
0
double EvalExpr::Term(CParser& p) {
	if(p.IsId()) {
		String strId = p.ReadId();
		if(double (*function)(double) = functions.Get(strId, 0)) {
			p.PassChar('(');
			double x = Exp(p);
			p.PassChar(')');
			return function(x);
		}	
		if (noCase)
			strId = ToUpper(strId);
		double ret = constants.Get(strId, Null);
		if (IsNull(ret))
			ret = variables.GetAdd(strId, 0);
		return ret;
	} else if(p.Char('(')) {
		double x = Exp(p);
		p.PassChar(')');
		return x;
	} else
		return p.ReadDouble();
}
예제 #29
0
파일: main.cpp 프로젝트: daiwx/UltraDemo
int main()
{
	

	ETMachine machine; 

	CParser parser;

	//IParser& parser = myParser;
	parser.LoadFromFile( "SAMPLE.hpp" );
	parser.Parse( true );

	std::cout << parser.GetImmCode();

	std::ofstream out( "code.txt" );
	out << parser.GetImmCode() << std::endl;

	Imm2asm i2a;
	std::string asmcode = i2a.TranslateToAsm( parser.GetImmCode(), parser.GetTables() );


	std::cout << asmcode << std::endl;


	machine.LoadCode( asmcode );
	machine.Reset();

	while ( machine.Step() ) ;

	std::cout << machine.GetOutputLog();

	//long* a = (long*)(machine.m_stack.m_stack + MaxStackSize - 4);
	//long* b = (long*)(machine.m_stack.m_stack + MaxStackSize - 8);

	//std::cout << *a << " " << *b;

	return 0;
}
예제 #30
0
// Look up each key binding in the config file and set the mappings for
// all key combinations that trigger it.
static void LoadConfigBindings()
{
	std::map<CStr, CConfigValueSet> bindings = g_ConfigDB.GetValuesWithPrefix( CFG_COMMAND, "hotkey." );

	CParser multikeyParser;
	multikeyParser.InputTaskType( "multikey", "<[~$arg(_negate)]$value_+_>_[~$arg(_negate)]$value" );

	for( std::map<CStr, CConfigValueSet>::iterator bindingsIt = bindings.begin(); bindingsIt != bindings.end(); ++bindingsIt )
	{
		std::string hotkeyName = bindingsIt->first.substr(7); // strip the "hotkey." prefix

		for( CConfigValueSet::iterator it = bindingsIt->second.begin(); it != bindingsIt->second.end(); ++it )
		{
			std::string hotkey;
			if( it->GetString( hotkey ) )
			{
				std::vector<SKey> keyCombination;

				CParserLine multikeyIdentifier;
				multikeyIdentifier.ParseString( multikeyParser, hotkey );

				// Iterate through multiple-key bindings (e.g. Ctrl+I)

				bool negateNext = false;

				for( size_t t = 0; t < multikeyIdentifier.GetArgCount(); t++ )
				{

					if( multikeyIdentifier.GetArgString( (int)t, hotkey ) )
					{
						if( hotkey == "_negate" )
						{
							negateNext = true;
							continue;
						}

						// Attempt decode as key name
						int mapping = FindKeyCode( hotkey );

						// Attempt to decode as a negation of a keyname
						// Yes, it's going a bit far, perhaps.
						// Too powerful for most uses, probably.
						// However, it got some hardcoding out of the engine.
						// Thus it makes me happy.

						if( !mapping )
						{
							LOGWARNING(L"Hotkey mapping used invalid key '%hs'", hotkey.c_str() );
							continue;
						}

						SKey key = { (SDLKEY)mapping, negateNext };
						keyCombination.push_back(key);

						negateNext = false;

					}
				}

				std::vector<SKey>::iterator itKey, itKey2;

				for( itKey = keyCombination.begin(); itKey != keyCombination.end(); ++itKey )
				{
					SHotkeyMapping bindCode;

					bindCode.name = hotkeyName;
					bindCode.negated = itKey->negated;

					for( itKey2 = keyCombination.begin(); itKey2 != keyCombination.end(); ++itKey2 )
					{
						// Push any auxiliary keys.
						if( itKey != itKey2 )
							bindCode.requires.push_back( *itKey2 );
					}

					g_HotkeyMap[itKey->code].push_back( bindCode );
				}
			}
		}
	}
}