Hi,

I'm trying to bring an old C++ mini-game I made to the web. It heavily 
relies on Sleep, so I've been trying to get it to work through Asyncify. 
When I try to compile it with that flag on, it generates the following 
error  in 1.25:

-----------------------
LLVM ERROR: InvokeState == 1 || InvokeState == 2
Stack dump:
0.      Program arguments: C:/Program 
Files/Emscripten/clang/e1.25.0_64bit\llc 
c:\users\jens\appdata\local\temp\tmpncthh0\a.out.bc -march=js -filetype=asm 
-o c:\users\jens\appdata\local\temp\tmpmqkl4z.4.js -emscripten-assertions=1 
-emscripten-no-aliasing-function-pointers -O0 -emscripten-max-setjmps=20
1.      Running pass 'JavaScript backend' on module 
'c:\users\jens\appdata\local\temp\tmpncthh0\a.out.bc'.
Traceback (most recent call last):
  File "C:\Program Files\Emscripten\emscripten\1.25.0\emscripten.py", line 
1578, in <module>
    _main(environ=os.environ)
  File "C:\Program Files\Emscripten\emscripten\1.25.0\emscripten.py", line 
1566, in _main
    temp_files.run_and_clean(lambda: main(
  File "C:\Program Files\Emscripten\emscripten\1.25.0\tools\tempfiles.py", 
line 39, in run_and_clean
    return func()
  File "C:\Program Files\Emscripten\emscripten\1.25.0\emscripten.py", line 
1574, in <lambda>
    DEBUG_CACHE=DEBUG_CACHE,
  File "C:\Program Files\Emscripten\emscripten\1.25.0\emscripten.py", line 
1461, in main
    jcache=jcache, temp_files=temp_files, DEBUG=DEBUG, 
DEBUG_CACHE=DEBUG_CACHE)
  File "C:\Program Files\Emscripten\emscripten\1.25.0\emscripten.py", line 
804, in emscript_fast
    end_funcs = backend_output.rindex(end_funcs_marker)
ValueError: substring not found
Traceback (most recent call last):
  File "C:\Program Files\Emscripten\emscripten\1.25.0\\emcc", line 1259, in 
<module>
    final = shared.Building.emscripten(final, append_ext=False, 
extra_args=extra_args)
  File "C:\Program Files\Emscripten\emscripten\1.25.0\tools\shared.py", 
line 1464, in emscripten
    assert os.path.exists(filename + '.o.js'), 'Emscripten failed to 
generate .js'
AssertionError: Emscripten failed to generate .js
-----------------------

I've attached the source that generates this error. It's a single .cpp 
file, so maybe it'll be helpful tracking this down.

Cheers,

Jens

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
#include <time.h>
#include <math.h>
#include <string>
#include <list>
#include <vector>
#include <sstream>

#include <emscripten.h>
#include <emscripten/html5.h>

using namespace std;
#define max(a,b)    (((a) > (b)) ? (a) : (b))
#define min(a,b)    (((a) < (b)) ? (a) : (b))

int _kbhit() { return 0; }
int _getch() { return 0; }
void _putch(char _ch)
{
	char buf[2];
	buf[0] = _ch;
	buf[1] = 0;
	printf("%s", buf);
}

#define localtime_s(a, b) localtime_r(b, a)

void fopen_s(
	FILE** pFile,
	const char *filename,
	const char *mode
	)
{
	*pFile = fopen(filename, mode);
}

EM_BOOL keypress_callback(int eventType, const EmscriptenKeyboardEvent *e, void *userData)
{
	printf("keypress\r\n");
	return 0;
}

class COsmosis
{
public:
	enum
	{
		RES_CONTINUE = -1,
		RES_CONTINUE_NOLINEFEED = -2,
		RES_CLOSECONNECTION = -3,

		CHAR_LOCALCONTROLKEY = 1,
	};

	int m_iProgram;
	int m_Delay[3];
	vector<string> m_lProgram;
	vector<string> m_lVariableKeys;
	vector<string> m_lVariableValues;
	vector<string> m_lOptions;
	int m_iStandaloneResponse;
	int m_ServerSocket;
	int m_ClientSocket;
	int m_MasterSocket;

	COsmosis()
	{
		m_iProgram = 0;
		m_ServerSocket = -1;
		m_ClientSocket = -1;
		m_MasterSocket = -1;
		m_Delay[0] = m_Delay[1] = m_Delay[2] = 0;
		m_iStandaloneResponse = -1;
	}

	~COsmosis()
	{
	}

	void SendCharLocal(char _Ch)
	{
		_putch(_Ch);
	}

	char GetCharLocal()
	{
		while (true)
		{
			if (_kbhit())
			{
				char ch = _getch();
				_putch(ch);
				return ch;
			}
		}
	}

	void SendLocal(const char *_pSt)
	{
		int i = 0;
		while (_pSt[i] != 0)
			SendCharLocal(_pSt[i++]);
	}

	int GetChar(bool _bBlock = true)
	{
		char ch = 0;
		while (ch == 0)
		{
			if (_kbhit())
			{
				ch = _getch();
				if (ch == '!')
					ch = CHAR_LOCALCONTROLKEY;
			}
			else
			{
				if (!_bBlock)
					return 0;
			}
		}

		SendCharLocal(ch);

		return ch;
	}

	bool SendChar(char _Ch)
	{
		SendCharLocal(_Ch);
		return true;
	}

	int FindLineFromLabel(const string &_Label)
	{
		if (_Label.empty())
			return -1;
		size_t nProg = m_lProgram.size();
		for (size_t i = 0; i < nProg; i++)
		{
			const string &Line = m_lProgram[i];
			if (Line.at(0) == '[' && Line.at(1) == '@')
			{
				string Label = Line.substr(1, Line.length() - 2);
				if (Label == _Label)
					return int(i);
			}
		}

		SendLocal("Label not found: ");
		SendLocal(_Label.c_str());
		SendLocal("\r\n");
		return -1;
	}

	void SetVariable(const string &_Var, const string &_Val)
	{
		const string *pVal = &_Val;
		string Val2 = _Val;
		Val2 = _Val;
		pVal = &Val2;
		char EOL[] = "\r\n";
		while (true)
		{
			size_t iPos = pVal->find('|');
			if (iPos == -1)
				break;

			if (pVal == &_Val)
			{
				Val2 = _Val;
				pVal = &Val2;
			}
			Val2.replace(iPos, 1, EOL);
		}

		size_t nVar = m_lVariableKeys.size();
		for (size_t i = 0; i < nVar; i++)
		{
			if (m_lVariableKeys[i] == _Var)
			{
				m_lVariableValues[i] = *pVal;
				return;
			}
		}
		m_lVariableKeys.push_back(_Var);
		m_lVariableValues.push_back(*pVal);
	}


	void SetVariable_i(const string &_Var, int _Val)
	{
		char Buf[1024];
		sprintf(Buf, "%i", _Val);
		SetVariable(_Var, Buf);
	}

	void SetVariable_f(const string &_Var, float _Val)
	{
		char Buf[1024];
		sprintf(Buf, "%.2f", _Val);
		SetVariable(_Var, Buf);
	}

	string GetVariable(const string &_Var)
	{
		size_t nVar = m_lVariableKeys.size();
		for (size_t i = 0; i < nVar; i++)
		{
			if (m_lVariableKeys[i] == _Var)
				return m_lVariableValues[i];
		}
		return string();
	}

	string GetCurTimeString(const char *_pFormat = NULL)
	{
		time_t ltime;
		time(&ltime);
		char Buf[512];
		tm today;
		localtime_s(&today, &ltime);
		if (_pFormat)
			strftime(Buf, 512, _pFormat, &today);
		else
			strftime(Buf, 512, "%d %B %Y, %H:%M", &today);
		return Buf;
	}

	string GetStrSep(string &_St, char _Separator)
	{
		size_t iFind = _St.find(_Separator);
		if (iFind == -1)
		{
			string Res = _St;
			_St.clear();
			return Res;
		}

		string Res = _St.substr(0, iFind);
		_St = _St.substr(iFind + 1, _St.length());
		return Res;
	}

	char InputLine(const string &_Param)
	{
		SendChar('>');
		SendChar(' ');
		while (true)
		{
			char ch = GetChar();
			if (ch == RES_CLOSECONNECTION)
				return RES_CLOSECONNECTION;

			if (ch == '\n' || ch == '\r')
			{
				SendChar('\r');
				SendChar('\n');
				return RES_CONTINUE;
			}
			if (ch == CHAR_LOCALCONTROLKEY)
			{
				return FindLineFromLabel(_Param);
			}
		}
	}

	void EndResponse(string &_StRes)
	{
		if (m_lOptions.size() < 3)
			return;

		for (int i = 0; i < 3; i++)
		{
			emscripten_sleep(3000);
			SendLocal("\r\n");
			SendLocal(m_lOptions[i].c_str());
			SendLocal("\r\n");
			InputLine("");
			SendLocal("Processing input. Please wait.");
		}

		emscripten_sleep(1500);
	}

	int CalibratePanel(string _Param)
	{
		//[calibratepanel,@panels,$panel_x,$panel_y,$panel3_power,-40,10]

		char ch = GetChar();
		if (ch == '5')
			return RES_CONTINUE;
		if (ch == RES_CLOSECONNECTION)
			return RES_CLOSECONNECTION;

		string Loop = GetStrSep(_Param, ',');
		string VarX = GetStrSep(_Param, ',');
		string VarY = GetStrSep(_Param, ',');
		string VarPow = GetStrSep(_Param, ',');
		int OptX = atoi(GetStrSep(_Param, ',').c_str());
		int OptY = atoi(GetStrSep(_Param, ',').c_str());
		int Step = atoi(GetStrSep(_Param, ',').c_str());

		int CurX = atoi(GetVariable(VarX).c_str());
		int CurY = atoi(GetVariable(VarY).c_str());

		switch (ch)
		{
		case '1': CurX = min(CurX + Step, 180); break;
		case '2': CurX = max(CurX - Step, -180); break;
		case '3': CurY = min(CurY + Step, 180); break;
		case '4': CurY = max(CurY - Step, -180); break;
		}

		float Pow = float(max(200 - abs(OptX - CurX) - abs(OptY - CurY), 0)) * 0.20f / 200 + 0.04f;
		SetVariable_f(VarPow, Pow);
		SetVariable_i(VarX, CurX);
		SetVariable_i(VarY, CurY);

		return FindLineFromLabel(Loop);
	}

	int Takeoff(string _Param)
	{
		string Loop = GetStrSep(_Param, ',');
		string VarAltitude = GetStrSep(_Param, ',');
		string VarSpeed = GetStrSep(_Param, ',');
		string VarFuel = GetStrSep(_Param, ',');
		int OptimalAlt1 = atoi(GetStrSep(_Param, ',').c_str());
		int OptimalAlt2 = atoi(GetStrSep(_Param, ',').c_str());

		int Altitude = atoi(GetVariable(VarAltitude).c_str());
		int Speed = atoi(GetVariable(VarSpeed).c_str());
		int Fuel = atoi(GetVariable(VarFuel).c_str());

		if (OptimalAlt2 > 0)
		{
			clock_t ltime = clock();
			while (true)
			{
				char ch = GetChar(false);
				if (ch == RES_CLOSECONNECTION)
					return RES_CLOSECONNECTION;
				if (ch == ' ')
				{
					if (Altitude > OptimalAlt2 * 0.5)
						return RES_CONTINUE;
				}

				emscripten_sleep(1);
				clock_t ctime = clock();

				if (ctime - ltime > 500)
					break;
			}

			int BaseAccel = 214;
			int AltitudeBonus = 0;
			Speed += BaseAccel;

			if (Altitude > OptimalAlt1 && Altitude < OptimalAlt2)
				Speed += int(20 * Altitude);
			else
				Speed += int(10 * Altitude);

			Altitude += int(float(Speed) / 1000 + 0.5f);
			if (Altitude > OptimalAlt2 * 3.0)
				return RES_CONTINUE;
			Fuel -= 7;
		}
		else
		{
			clock_t ltime = clock();
			while (true)
			{
				char ch = GetChar(false);
				if (ch == RES_CLOSECONNECTION)
					return RES_CLOSECONNECTION;

				emscripten_sleep(1);
				clock_t ctime = clock();

				if (ctime - ltime > 500)
					break;
			}

			int Left = OptimalAlt1 - Altitude;
			Speed -= 8000;
			Speed = (4 * Speed + Left * 100) / 5;
			if (abs(Altitude - OptimalAlt1) < 100)
				return RES_CONTINUE;

			Altitude += int(float(Speed) / 1000 + 0.5f);
			Fuel -= 3;
		}

		SetVariable_i(VarSpeed, Speed);
		SetVariable_i(VarAltitude, Altitude);
		SetVariable_i(VarFuel, Fuel);

		return FindLineFromLabel(Loop);
	}

	int Entry(string _Param)
	{
		string Loop = GetStrSep(_Param, ',');
		string VarAltitude = GetStrSep(_Param, ',');
		string VarSpeed = GetStrSep(_Param, ',');
		string VarShield = GetStrSep(_Param, ',');
		string VarAngle = GetStrSep(_Param, ',');
		int OptimalAngle = atoi(GetStrSep(_Param, ',').c_str());
		int EndAltitude = atoi(GetStrSep(_Param, ',').c_str());

		int Altitude = atoi(GetVariable(VarAltitude).c_str());
		int Speed = atoi(GetVariable(VarSpeed).c_str());
		int Angle = atoi(GetVariable(VarAngle).c_str());
		int Shield = atoi(GetVariable(VarShield).c_str());

		clock_t ltime = clock();
		while (true)
		{
			char ch = GetChar(false);
			if (ch == RES_CLOSECONNECTION)
				return RES_CLOSECONNECTION;
			if (ch == '1')
				Angle += 2;
			else if (ch == '2')
				Angle -= 2;

			emscripten_sleep(1);
			clock_t ctime = clock();

			if (ctime - ltime > 500)
				break;
		}

		bool bReduceShield = false;
		if (GetVariable("$shield_trigger").empty())
		{
			SetVariable("$shield_trigger", "1");
			bReduceShield = true;
		}
		else
			SetVariable("$shield_trigger", "");
		if ((OptimalAngle - Angle) > 4)
		{
			SetVariable("$shield_status", "Failing");
			if (bReduceShield)
				Shield -= 2;
			else
				Shield -= 1;
		}
		else
		{
			SetVariable("$shield_status", "Holding");
			if (bReduceShield)
				Shield -= 1;
		}
		if (Shield <= 0)
		{
			Shield = 0;
			SetVariable("$shield_status", "Failed");
		}

		Speed = int(Speed * 0.97f);
		Speed -= 219;
		Altitude -= int(0.5f + float(Speed) / 2809.0f);
		if (Altitude <= EndAltitude)
			return RES_CONTINUE;

		SetVariable_i(VarSpeed, Speed);
		SetVariable_i(VarAltitude, Altitude);
		SetVariable_i(VarAngle, Angle);
		SetVariable_i(VarShield, Shield);

		return FindLineFromLabel(Loop);
	}

	int WaitForClient(const char *_pDev)
	{
		SetVariable("$clientip", "127.0.0.1");
		return -1;
	}

	void KillInput()
	{
		while (_kbhit())
			_getch();
	}

	bool LoadMenu(const char *_pPath)
	{
		FILE *pFile;
		string Path = "menus/";
		Path += _pPath;
		fopen_s(&pFile, Path.c_str(), "rb");
		if (!pFile)
		{
			printf("Could not open %s", _pPath);
			return false;
		}

		fseek(pFile, 0, SEEK_END);
		int Len = ftell(pFile);
		fseek(pFile, 0, SEEK_SET);

		char *pBuf = new char[Len + 1];
		if (!pBuf)
			return false;

		fread(pBuf, 1, Len, pFile);
		fclose(pFile);
		pBuf[Len] = 0;

		int iStartLine = 0;
		int iPos = 0;

		while (pBuf[iPos] != 0)
		{
			if (pBuf[iPos] == '\n')
			{
				string St;
				St.insert(0, pBuf + iStartLine, iPos - iStartLine - 1);
				if (St.length() == 0)
					St = " ";
				if (St.find("#include") == 0)
				{
					string Path = St.substr(9, 1024);
					if (!LoadMenu(Path.c_str()))
						return false;
				}
				m_lProgram.push_back(St);
				iPos++;
				iStartLine = iPos;
			}
			else
				iPos++;
		}

		delete[] pBuf;
		return true;
	}

	int ResolveString(string &_In)
	{
		int Res = RES_CONTINUE;
		while (true)
		{
			size_t iCmdStart = _In.find('[');
			if (iCmdStart == -1)
				break;

			size_t iCmdEnd = _In.find(']', iCmdStart + 1);
			while (true)
			{
				size_t iCmdStart2 = _In.find('[', iCmdStart + 1);
				if (iCmdStart2 == -1 || iCmdStart2 > iCmdEnd)
					break;
				iCmdStart = iCmdStart2;
			}

			string Param = _In.substr(iCmdStart + 1, iCmdEnd - iCmdStart - 1);
			string Msg = GetStrSep(Param, ':');
			string StRes;
			if (Msg.at(0) == '$')
				StRes = GetVariable(Msg);

			else if (Msg == "set")
			{
				string Key = GetStrSep(Param, ',');
				SetVariable(Key, Param);
			}

			else if (Msg == "\\")
				Res = RES_CONTINUE_NOLINEFEED;

			else if (Msg == "|")
				StRes = "\r";

			else if (Msg == "option")
			{
				string Desc = GetStrSep(Param, ',');
				bool bOk = true;
				if (Param.find(',') != -1)
				{
					string Var = Param;
					Param = GetStrSep(Var, ',');
					if (GetVariable(Var).empty())
						bOk = false;
				}

				if (bOk)
				{
					m_lOptions.push_back(Param);
					size_t nOption = m_lOptions.size();
					ostringstream strm;
					strm << nOption << ". " << Desc;
					StRes = strm.str();
				}
			}

			else if (Msg == "endoptions")
			{
				while (true)
				{
					char ch = GetChar();
					if (ch == RES_CLOSECONNECTION)
					{
						_In = "";
						return RES_CLOSECONNECTION;
					}
					ch -= '1';
					if (size_t(ch) < m_lOptions.size())
					{
						string Label = m_lOptions.at(ch);
						if (Label.empty())
							break;
						Res = FindLineFromLabel(Label);
						if (Res != -1)
							break;
					}
				}
				m_lOptions.clear();
				StRes = "\r\n\r\n";
			}

			else if (Msg == "goto")
				Res = FindLineFromLabel(Param);

			else if (Msg == "appendline")
			{
				string Key = GetStrSep(Param, ',');
				string Val = GetVariable(Key);
				Val += "\r\n" + Param;
				SetVariable(Key, Val);
			}

			else if (Msg == "getlastline")
			{
				string Key = GetStrSep(Param, ',');
				string Val = GetVariable(Key);
				size_t iPos = Val.rfind('\n', Val.length() - 1);
				StRes = Val.substr(iPos + 1, 1024);
			}

			else if (Msg == "curdatetime")
				StRes = GetCurTimeString();

			else if (Msg == "quit")
			{
				_In = "";
				return RES_CLOSECONNECTION;
			}

			else if (Msg == "killinput")
			{
				KillInput();
			}

			else if (Msg == "branch")
			{
				string Var = GetVariable(GetStrSep(Param, ','));
				string Operator = GetStrSep(Param, ',');
				string Condition = GetStrSep(Param, ',');

				bool bBranch = false;
				if (Operator == "==")
					bBranch = (Var == Condition);
				else if (Operator == "!=")
					bBranch = (Var != Condition);
				else if (Operator == "<")
					bBranch = (float(atof(Var.c_str())) < float(atof(Condition.c_str())));
				else if (Operator == ">")
					bBranch = (float(atof(Var.c_str())) > float(atof(Condition.c_str())));

				string Branch1 = GetStrSep(Param, ',');
				string Branch2 = GetStrSep(Param, ',');
				if (bBranch)
					Res = FindLineFromLabel(Branch1);
				else
					Res = FindLineFromLabel(Branch2);
			}

			else if (Msg == "key")
			{
				vector<char> lKeys;
				vector<string> lBranch;

				while (true)
				{
					string St = GetStrSep(Param, ',');
					if (St.empty())
						break;
					char ch = St.at(0);
					if (ch == '!')
						ch = 1;
					lKeys.push_back(ch);
					lBranch.push_back(GetStrSep(Param, ','));
				}

				size_t nSize = lKeys.size();
				if (nSize == 2 && lKeys[0] == 1)
				{
					emscripten_sleep(4000);
					Res = FindLineFromLabel(lBranch[1]);
				}
				SendChar('\r');
				SendChar('\n');
			}
			else if (Msg == "setdelay")
			{
				m_Delay[0] = atoi(GetStrSep(Param, ',').c_str());
				m_Delay[1] = atoi(GetStrSep(Param, ',').c_str());
				m_Delay[2] = atoi(GetStrSep(Param, ',').c_str());
			}
			else if (Msg == "disconnect")
			{
				_In = "";
				return RES_CLOSECONNECTION;
			}
			else if (Msg == "m_add")
			{
				float f = 0;
				while (!Param.empty())
				{
					string Var = GetStrSep(Param, ',');
					if (Var.size() > 0 && Var.at(0) == '$')
						Var = GetVariable(Var);
					f += (float)atof(Var.c_str());
				}

				char Res2[1024];
				sprintf(Res2, "%.2f", f);
				StRes = Res2;
			}
			else if (Msg == "m_inc")
			{
				int Val = atoi(GetVariable(Param).c_str());
				SetVariable_i(Param, Val + 1);
			}
			else if (Msg == "calibratepanel")
				Res = CalibratePanel(Param);
			else if (Msg == "takeoff")
				Res = Takeoff(Param);
			else if (Msg == "entry")
				Res = Entry(Param);
			else if (Msg == "inputline")
				Res = InputLine(Param);
			else if (Msg == "response")
			{
				m_lOptions.push_back(Param);
			}
			else if (Msg == "endresponse")
			{
				EndResponse(StRes);
				if (StRes == "")
					Res = FindLineFromLabel(Param);

				m_lOptions.clear();
			}
			else if (Msg == "waitforclient")
			{
				Res = WaitForClient(Param.c_str());
				SendLocal("\n");
			}

			_In.replace(iCmdStart, iCmdEnd - iCmdStart + 1, StRes);
		}
		return Res;
	}

	int Run()
	{
		if (!LoadMenu("root.txt"))
			return 1;

		SetVariable("$datetime", GetCurTimeString());

		int Res = 0;
		while (Res > RES_CLOSECONNECTION)
		{
			Res = 0;
			m_iProgram = 0;
			m_lOptions.clear();
			while (Res >= RES_CONTINUE_NOLINEFEED)
			{
				if (m_iProgram >= int(m_lProgram.size()))
					m_iProgram = 0;

				string St = m_lProgram.at(m_iProgram);
				Res = ResolveString(St);
				size_t Len = St.length();
				if (Len > 0)
				{
					for (size_t i = 0; i < Len; i++)
					{
						char ch = St[i];
						if (ch == '_')
						{
							emscripten_sleep(m_Delay[1]);
						}
						else
						{
							if (Res != RES_CONTINUE_NOLINEFEED)
								emscripten_sleep(m_Delay[0]);
							SendChar(ch);
						}
					}
					if (Res == RES_CONTINUE)
					{
						SendChar('\r');
						if (!SendChar('\n'))
							break;
					}

					emscripten_sleep(m_Delay[2]);
				}

				if (Res >= 0)
					m_iProgram = Res;
				else
					m_iProgram++;
			}
		}

		return 0;
	}
};

int main(int argc, char* argv[])
{
	emscripten_set_keypress_callback(0, 0, 1, keypress_callback);
	COsmosis Game;
	Game.Run();
	return 0;
}

Reply via email to