Example #1
0
Str Join(double** str, int len1, int len2) {
  VStr tmp;
  for (int i = 0; i < len1; i++) {
    tmp.push_back(Join(str[i], len2));
  }
  return Join(tmp, "\n");
}
Example #2
0
Str Join(const VVVReal &data, StrC &del1, StrC &del2, StrC &del3) {
  VStr tmp;
  for (VVVReal::size_type i = 0; i < data.size(); i++) {
    tmp.push_back(Join(data.at(i), del1, del2));
  }
  return Join(tmp, "\n");
}
Example #3
0
Str Join(const VVReal &data, const Str &del1, const Str &del2) {
  VStr tmp;
  for (VVReal::size_type i = 0; i < data.size(); i++) {
    tmp.push_back(Join(data.at(i), del1));
  }
  return Join(tmp, del2);
}
Example #4
0
Str Join(double* str, int len) {
  VStr tmp;
  for (int i = 0; i < len; i++) {
    tmp.push_back(ToStr(str[i]));
  }
  return Join(tmp, " ");
}
Example #5
0
Str Join(VVIntC &data, StrC &del1, StrC &del2) {
  VStr tmp;
  for (VVInt::size_type i = 0; i < data.size(); i++) {
    tmp.push_back(Join(data.at(i), del1));
  }
  return Join(tmp, del2);
}
Example #6
0
Str Join(It beg, It end, StrC &del) {
  VStr tmp;
  for (It it = beg; it != end; ++it) {
    tmp.push_back(ToStr(*it, 7));
  }
  return Join(tmp, del);
}
Example #7
0
Str Join(const VVStr &vec, const Str &del1, const Str &del2) {
  VStr tmp;
  for (VVStr::size_type i = 0; i < vec.size(); i++) {
    tmp.push_back(Join(vec.at(i), del1));
  }
  return Join(tmp, del2);
}
Example #8
0
VStr StrSplit(string theString, char dlim){
	istringstream iss(theString);
	VStr result;
	string tmp;
	while(!iss.eof() ){
		getline(iss , tmp, dlim );
		result.push_back(tmp);
	}
	return result;
}
Example #9
0
VStr * newVStrFromFile(fstream &infile){
	VStr *allLine = new VStr;

	while(! infile.eof() ){
		string tmp;
		getline(infile,tmp,'\n');
		allLine->push_back(tmp);
	}
//	infile.close();
	return allLine;
}
Example #10
0
VStr StrSplit(string theString){
	istringstream iss(theString);
	VStr result;
	string tmp;
	while(!iss.eof() ){
		//getline(iss , tmp);
		iss >> tmp;
		result.push_back(tmp);
	}
	return result;
}
Example #11
0
void Info_RemoveKey(VStr& s, const VStr& key)
{
    guard(Info_RemoveKey);
    if (s.IsEmpty())
    {
        return;
    }
    if (s.Length() >= MAX_INFO_STRING)
    {
        Host_Error("Info_RemoveKey: oversize infostring");
    }

    if (strchr(*key, '\\'))
    {
        GCon->Log("Can't use a key with a \\");
        return;
    }

    int i = 0;
    while (1)
    {
        int start = i;
        if (s[i] == '\\')
            i++;
        int KeyStart = i;
        while (s[i] != '\\')
        {
            if (!s[i])
                return;
            i++;
        }
        VStr pkey(s, KeyStart, i - KeyStart);
        i++;

        int ValStart = i;
        while (s[i] != '\\' && s[i])
        {
            i++;
        }
        VStr value(s, ValStart, i - ValStart);

        if (!key.Cmp(pkey))
        {
            s = VStr(s, 0, start) + VStr(s, i, s.Length() - i);	// remove this part
            return;
        }

        if (!s[i])
            return;
    }
    unguard;
}
Example #12
0
void VValueBag::DumpXMLIndentation(VString& ioDump, sLONG inIndentLevel)
{
	sLONG level = Min<sLONG>(100L, inIndentLevel);

	VStr<100>	indent;
	UniChar* ptr = indent.GetCPointerForWrite();
//	ptr[0] = 13;
	for (sLONG i = 0 ; i < level ; ++i)
		ptr[i] = CHAR_CONTROL_0009;	// tab
	indent.Validate(level);

	ioDump += indent;
}
Example #13
0
void Info_SetValueForKey(VStr& s, const VStr& key, const VStr& value)
{
    guard(Info_SetValueForKey);
    if (s.Length() >= MAX_INFO_STRING)
    {
        Host_Error("Info_SetValueForKey: oversize infostring");
    }

    if (strchr(*key, '\\') || strchr(*value, '\\'))
    {
        GCon->Log("Can't use keys or values with a \\");
        return;
    }

    if (strchr(*key, '\"') || strchr(*value, '\"'))
    {
        GCon->Log("Can't use keys or values with a \"");
        return;
    }

    // this next line is kinda trippy
    VStr v = Info_ValueForKey(s, key);
    if (v.IsNotEmpty())
    {
        //	Key exists, make sure we have enough room for new value, if we
        // don't, don't change it!
        if (value.Length() - v.Length() + s.Length() > MAX_INFO_STRING)
        {
            GCon->Log("Info string length exceeded");
            return;
        }
    }

    Info_RemoveKey(s, key);
    if (value.IsEmpty())
        return;

    VStr newi = VStr("\\") + key + "\\" +  value;

    if (newi.Length() + s.Length() > MAX_INFO_STRING)
    {
        GCon->Log("Info string length exceeded");
        return;
    }

    s = s + newi;
    unguard;
}
Example #14
0
static VStr FindMainWad(VStr MainWad)
{
	//	First check in IWAD directories.
	for (int i = 0; i < IWadDirs.Num(); i++)
	{
		if (Sys_FileExists(IWadDirs[i] + "/" + MainWad))
		{
			return IWadDirs[i] + "/" + MainWad;
		}
	}

	//	Then look in the save directory.
	if (fl_savedir.IsNotEmpty() && Sys_FileExists(fl_savedir + "/" + MainWad))
	{
		return fl_savedir + "/" + MainWad;
	}

	//	Finally in base directory.
	if (Sys_FileExists(fl_basedir + "/" + MainWad))
	{
		return fl_basedir + "/" + MainWad;
	}

	return VStr();
}
Example #15
0
VCvar::VCvar(const char* AName, const VStr& ADefault, int AFlags)
: Name(AName)
, Flags(AFlags | CVAR_Delete)
{
	guard(VCvar::VCvar);
	char* Tmp = new char[ADefault.Length() + 1];
	VStr::Cpy(Tmp, *ADefault);
	DefaultString = Tmp;

	VCvar *prev = NULL;
	for (VCvar *var = Variables; var; var = var->Next)
	{
		if (VStr::ICmp(var->Name, Name) < 0)
		{
			prev = var;
		}
	}

	if (prev)
	{
		Next = prev->Next;
		prev->Next = this;
	}
	else
	{
		Next = Variables;
		Variables = this;
	}

	check(Initialised);
	Register();
	unguard;
}
Example #16
0
void FL_CreatePath(const VStr& Path)
{
	guard(FL_CreatePath);
	VStr Temp = Path;
	for (size_t i = 3; i <= Temp.Length(); i++)
	{
		if (Temp[i] == '/' || Temp[i] == '\\' || Temp[i] == 0)
		{
			char Save = Temp[i];
			Temp[i] = 0;
			if (!Sys_DirExists(Temp))
				Sys_CreateDirectory(Temp);
			Temp[i] = Save;
		}
	}
	unguard;
}
Example #17
0
void FL_Shutdown()
{
	guard(FL_Shutdown);
	for (int i = 0; i < SearchPaths.Num(); i++)
	{
		delete SearchPaths[i];
		SearchPaths[i] = NULL;
	}
	SearchPaths.Clear();
	fl_basedir.Clean();
	fl_savedir.Clean();
	fl_gamedir.Clean();
	fl_mainwad.Clean();
	wadfiles.Clear();
	IWadDirs.Clear();
	unguard;
}
Example #18
0
// split string by dlim == '  ' (two space)
VStr StrSplitBy2Space(string str){
	string ttmp= str;
	VStr res;
	string ts("\n\n");
	for(int i = 0 ;i < ttmp.size()-1;i++ ){
		if (ttmp.c_str()[i] == ' ' && ttmp.c_str()[i+1] == ' ')
			ttmp.replace(i,2,ts);
	}
	istringstream iss(ttmp);
	while(!iss.eof() ){
		string tmp;
		getline(iss,tmp );
		if(tmp.size() == 0) continue;
		res.push_back(tmp);
	}
	return res;
}
Example #19
0
VStream* FL_OpenFileWrite(const VStr& Name)
{
	guard(FL_OpenFileWrite);
	VStr TmpName;

	if (fl_savedir.IsNotEmpty())
		TmpName = fl_savedir + "/" + fl_gamedir + "/" + Name;
	else
		TmpName = fl_basedir + "/" + fl_gamedir + "/" + Name;
	FL_CreatePath(TmpName.ExtractFilePath());
	FILE *File = fopen(*TmpName, "wb");
	if (!File)
	{
		return NULL;
	}
	return new VStreamFileWriter(File, GCon);
	unguard;
}
Example #20
0
VStr Info_ValueForKey(const VStr& s, const VStr& key)
{
    guard(Info_ValueForKey);
    if (s.IsEmpty() || key.IsEmpty())
    {
        return VStr();
    }

    if (s.Length() >= MAX_INFO_STRING)
    {
        Host_Error("Info_ValueForKey: oversize infostring");
    }

    int i = 0;
    if (s[i] == '\\')
        i++;
    while (1)
    {
        int Start = i;
        while (s[i] != '\\')
        {
            if (!s[i])
                return VStr();
            i++;
        }
        VStr pkey(s, Start, i - Start);
        i++;

        Start = i;
        while (s[i] != '\\' && s[i])
        {
            i++;
        }

        if (!key.ICmp(pkey))
            return VStr(s, Start, i - Start);

        if (!s[i])
            return VStr();
        i++;
    }
    unguard;
}
Example #21
0
static void AddGameDir(const VStr& dir)
{
	guard(AddGameDir);
	AddGameDir(fl_basedir, dir);
	if (fl_savedir.IsNotEmpty())
	{
		AddGameDir(fl_savedir, dir);
	}
	fl_gamedir = dir;
	unguard;
}
Example #22
0
static void AddGameDir(const VStr& basedir, const VStr& dir)
{
	guard(AddGameDir);
	//	First add all .pk3 files in that directory.
	if (Sys_OpenDir(basedir + "/" + dir))
	{
		TArray<VStr> ZipFiles;
		for (VStr test = Sys_ReadDir(); test.IsNotEmpty(); test = Sys_ReadDir())
		{
			VStr ext = test.ExtractFileExtension().ToLower();
			if (ext == "pk3")
				ZipFiles.Append(test);
		}
		Sys_CloseDir();
		qsort(ZipFiles.Ptr(), ZipFiles.Num(), sizeof(VStr), cmpfunc);
		for (int i = 0; i < ZipFiles.Num(); i++)
		{
			AddZipFile(basedir + "/" + dir + "/" + ZipFiles[i]);
		}
	}

	//	Then add wad##.wad files.
	VStr gwadir;
	if (fl_savedir.IsNotEmpty() && basedir != fl_savedir)
	{
		gwadir = fl_savedir + "/" + dir;
	}

	for (int i = 0; i < 1024; i++)
	{
		VStr buf = basedir + "/" + dir + "/wad" + i + ".wad";
		if (!Sys_FileExists(buf))
			break;
		W_AddFile(buf, gwadir, false);
	}

	//	Finally add directory itself.
	VFilesDir* info = new VFilesDir(basedir + "/" + dir);
	SearchPaths.Append(info);
	unguard;
}
Example #23
0
bool VZipFile::FileExists(const VStr& FName)
{
	guard(VZipFile::FileExists);
	VStr CheckName = FName.ToLower();
	for (int i = 0; i < NumFiles; i++)
	{
		if (Files[i].Name == CheckName)
		{
			return true;
		}
	}
	return false;
	unguard;
}
Example #24
0
void VValueBag::DumpXMLCData( VString& ioDump, VIndex inCDataAttributeIndex) const
{
	VStr<1000> cdata;

	GetNthAttribute( inCDataAttributeIndex, NULL)->GetString( cdata);

	if (NeedsEscapeSequence( cdata, sXMLEscapeChars_Contents, sXMLEscapeChars_Contents + sizeof(sXMLEscapeChars_Contents)/sizeof(UniChar)))
	{
		ioDump += CVSTR( "<![CDATA[");

		// see if there's a "]]>" for which we need to split
		// someting like: hello ]]> world
		// becomes: <![CDATA[hello ]]>]]<![CDATA[> world]]>
		
		VIndex pos = 1;
		while( pos <= cdata.GetLength())
		{
			VIndex endTag = cdata.Find( CVSTR( "]]>"), pos, true);
			if (endTag > 0)
			{
				// add everything including ]]>
				ioDump.AppendBlock( cdata.GetCPointer() + pos - 1, (endTag - pos + 3) * sizeof( UniChar), VTC_UTF_16);
				// add ]] outside CDATA section
				ioDump.AppendString( CVSTR( "]]"));
				// open a new CDATA section and add remaining >
				ioDump += CVSTR( "<![CDATA[>");
				pos = endTag + 3;
			}
			else
			{
				// add everything left
				ioDump.AppendBlock( cdata.GetCPointer() + pos - 1, (cdata.GetLength() - pos + 1) * sizeof( UniChar), VTC_UTF_16);
				break;
			}
		}
		ioDump += CVSTR( "]]>");
	}
	else
	{
		VString toInsert;
		for (sLONG i = 0, n = cdata.GetLength(); i < n; i++)
		{
			UniChar c = cdata[ i ];
			if (c != 13 && c != 10 && c != 9)
			{
				toInsert += c;
			}
		}
		if ( ! toInsert.IsEmpty() )
			ioDump += toInsert;
	}
}
Example #25
0
int saveVStrToFilename(VStr _strs, string _savefile){
	ofstream outfile;
	outfile.open(_savefile.c_str());
	if(outfile.is_open() != true  ){
		printf("open file %s error",_savefile.c_str());
		return -1;
	}

	for(int i = 0 ;i < _strs.size() ;i++ ){
		outfile << _strs[i] << "\n";
	}

	outfile.close();
	return 1;
}
Example #26
0
int VZipFile::CheckNumForFileName(VStr Name)
{
	guard(VZipFile::CheckNumForFileName);
	VStr CheckName = Name.ToLower();
	for (int i = NumFiles - 1; i >= 0; i--)
	{
		if (Files[i].Name == CheckName)
		{
			return i;
		}
	}

	// Not found.
	return -1;
	unguard;
}
Example #27
0
void VMemberBase::StaticSplitStateLabel(const VStr& LabelName,
                                        TArray<VName>& Parts)
{
    guard(VMemberBase::StaticSplitStateLabel);
    TArray<VStr> StrParts;
    LabelName.Split(".", StrParts);
    Parts.Clear();
    //	Remap old death state labels to proper names.
    if (StrParts[0] == "XDeath")
    {
        Parts.Append("Death");
        Parts.Append("Extreme");
    }
    else if (StrParts[0] == "Burn")
    {
        Parts.Append("Death");
        Parts.Append("Fire");
    }
    else if (StrParts[0] == "Ice")
    {
        Parts.Append("Death");
        Parts.Append("Ice");
    }
    else if (StrParts[0] == "Disintegrate")
    {
        Parts.Append("Death");
        Parts.Append("Disintegrate");
    }
    else
    {
        Parts.Append(*StrParts[0]);
    }
    for (int i = 1; i < StrParts.Num(); i++)
    {
        Parts.Append(*StrParts[i]);
    }
    unguard;
}
Example #28
0
static void ParseBase(const VStr& name)
{
	guard(ParseBase);
	TArray<version_t>	games;
	bool				select_game;
	VStr				UseName;

	if (fl_savedir.IsNotEmpty() && Sys_FileExists(fl_savedir + "/" + name))
	{
		UseName = fl_savedir + "/" + name;
	}
	else if (Sys_FileExists(fl_basedir + "/" + name))
	{
		UseName = fl_basedir + "/" + name;
	}
	else
	{
		return;
	}

	select_game = false;
	VScriptParser* sc = new VScriptParser(UseName, FL_OpenSysFileRead(UseName));
	while (!sc->AtEnd())
	{
		version_t &dst = games.Alloc();
		dst.ParmFound = 0;
		dst.FixVoices = false;
		sc->Expect("game");
		sc->ExpectString();
		dst.GameDir = sc->String;
		if (sc->Check("iwad"))
		{
			sc->ExpectString();
			dst.MainWad = sc->String;
		}
		while (sc->Check("addfile"))
		{
			sc->ExpectString();
			dst.AddFiles.Append(sc->String);
		}
		if (sc->Check("param"))
		{
			sc->ExpectString();
			dst.ParmFound = GArgs.CheckParm(*sc->String);
			if (dst.ParmFound)
			{
				select_game = true;
			}
		}
		if (sc->Check("fixvoices"))
		{
			dst.FixVoices = true;
		}
		sc->Expect("end");
	}
	delete sc;
	sc = NULL;

	for (int gi = games.Num() - 1; gi >= 0; gi--)
	{
		version_t& G = games[gi];
		if (select_game && !G.ParmFound)
		{
			continue;
		}
		if (fl_mainwad.IsNotEmpty())
		{
			if (G.MainWad.IsEmpty() || G.MainWad == fl_mainwad || select_game)
			{
				if (!bIwadAdded)
				{
					IWadIndex = SearchPaths.Num();
					VStr MainWadPath = FindMainWad(fl_mainwad);
					W_AddFile(MainWadPath, fl_savedir, G.FixVoices);
					bIwadAdded = true;
				}
				for (int j = 0; j < G.AddFiles.Num(); j++)
				{
					W_AddFile(fl_basedir + "/" + G.AddFiles[j], fl_savedir,
						false);
				}
				SetupGameDir(G.GameDir);
				return;
			}
			continue;
		}
		if (G.MainWad.IsEmpty())
		{
			continue;
		}

		//	Look for the main wad file.
		VStr MainWadPath = FindMainWad(G.MainWad);
		if (MainWadPath.IsNotEmpty())
		{
			fl_mainwad = G.MainWad;
			if (!bIwadAdded)
			{
				IWadIndex = SearchPaths.Num();
				W_AddFile(MainWadPath, fl_savedir, G.FixVoices);
				bIwadAdded = true;
			}
			for (int j = 0; j < G.AddFiles.Num(); j++)
			{
				VStr FName = FindMainWad(G.AddFiles[j]);
				if (FName.IsEmpty())
				{
					Sys_Error("Required file %s not found", *G.AddFiles[j]);
				}
				W_AddFile(FName, fl_savedir, false);
			}
			SetupGameDir(G.GameDir);
			return;
		}
	}

	if (select_game)
		Sys_Error("Main wad file not found.");
	else
		Sys_Error("Game mode indeterminate.");
	unguard;
}
Example #29
0
bool C_Responder(event_t* ev)
{
	const char*	cp;
	VStr		str;
	int			i;
	bool		eat;

	//  Respond to events only when console is active
	if (!C_Active())
		return false;

	//	We are iterested only in key down events
	if (ev->type != ev_keydown)
		return false;

	switch (ev->data1)
	{
	// Close console
	case K_ESCAPE:
		if (consolestate != cons_open)
			return false;

	case '`':
		if (consolestate == cons_closing)
			C_Start();
		else
			C_Stop();
		return true;

	// Execute entered command
	case K_ENTER:
	case K_PADENTER:
		//	Print it
		GCon->Logf(">%s", c_iline.Data);

		//	Add to history
		c_history_last = (MAXHISTORY + c_history_last - 1) % MAXHISTORY;
		if (c_history_size < MAXHISTORY)
			c_history_size++;
		VStr::Cpy(c_history[c_history_last], c_iline.Data);
		c_history_current = -1;

		//	Add to command buffer
		GCmdBuf << c_iline.Data << "\n";

		//	Clear line
		c_iline.Init();
		c_autocompleteIndex = -1;
		return true;

	// Scroll lines up
	case K_PAGEUP:
		for (i = 0; i < (GInput->ShiftDown ? 1 : 5); i++)
		{
			if (last_line > 1)
			{
				last_line--;
			}
		}
		return true;

	// Scroll lines down
	case K_PAGEDOWN:
		for (i = 0; i < (GInput->ShiftDown ? 1 : 5); i++)
		{
			if (last_line < num_lines)
			{
				last_line++;
			}
		}
		return true;

	// Go to first line
	case K_HOME:
		last_line = 1;
		return true;

	// Go to last line
	case K_END:
		last_line = num_lines;
		return true;

	// Command history up
	case K_UPARROW:
		c_history_current++;
		c_iline.Init();
		if (c_history_current >= c_history_size)
		{
			c_history_current = c_history_size;
		}
		else
		{
			cp = c_history[(c_history_last +
				c_history_current) % MAXHISTORY];
			while (*cp) c_iline.AddChar(*cp++);
		}
		c_autocompleteIndex = -1;
		return true;

	// Command history down
	case K_DOWNARROW:
		c_history_current--;
		c_iline.Init();
		if (c_history_current < 0)
		{
			c_history_current = -1;
		}
		else
		{
			cp = c_history[(c_history_last +
				c_history_current) % MAXHISTORY];
			while (*cp) c_iline.AddChar(*cp++);
		}
		c_autocompleteIndex = -1;
		return true;

	// Auto complete
	case K_TAB:
		if (!c_iline.Data[0])
			return true;

		if (c_autocompleteIndex == -1)
		{
			c_autocompleteString = c_iline.Data;
		}
		str = VCommand::GetAutoComplete(c_autocompleteString,
			c_autocompleteIndex, GInput->ShiftDown ? true : false);
		if (str.IsNotEmpty())
		{
			c_iline.Init();
			for (i = 0; i < (int)str.Length(); i++)
				c_iline.AddChar(str[i]);
			c_iline.AddChar(' ');
		}
		return true;

	// Add character to input line
	default:
		eat = c_iline.Key((byte)ev->data1);
		if (eat)
			c_autocompleteIndex = -1;
		return eat;
	}
}
void VInvocation::CheckDecorateParams(VEmitContext& ec)
{
	guard(VInvocation::CheckDecorateParams);
	int max_params;
	int num_needed_params = Func->NumParams;
	if (Func->Flags & FUNC_VarArgs)
	{
		max_params = VMethod::MAX_PARAMS - 1;
	}
	else
	{
		max_params = Func->NumParams;
	}
	if (NumArgs > max_params)
	{
		ParseError(Loc, "Incorrect number of arguments, need %d, got %d.", max_params, NumArgs);
	}

	for (int i = 0; i < NumArgs; i++)
	{
		if (i >= num_needed_params)
		{
			continue;
		}
		if (!Args[i])
		{
			continue;
		}
		switch (Func->ParamTypes[i].Type)
		{
		case TYPE_Name:
			if (Args[i]->IsDecorateSingleName())
			{
				VDecorateSingleName* E = (VDecorateSingleName*)Args[i];
				Args[i] = new VNameLiteral(*E->Name, E->Loc);
				delete E;
				E = NULL;
			}
			else if (Args[i]->IsStrConst())
			{
				VStr Val = Args[i]->GetStrConst(ec.Package);
				TLocation ALoc = Args[i]->Loc;
				delete Args[i];
				Args[i] = NULL;
				Args[i] = new VNameLiteral(*Val, ALoc);
			}
			break;

		case TYPE_String:
			if (Args[i]->IsDecorateSingleName())
			{
				VDecorateSingleName* E = (VDecorateSingleName*)Args[i];
				Args[i] = new VStringLiteral(ec.Package->FindString(*E->Name), E->Loc);
				delete E;
				E = NULL;
			}
			break;

		case TYPE_Class:
			if (Args[i]->IsDecorateSingleName())
			{
				VDecorateSingleName* E = (VDecorateSingleName*)Args[i];
				Args[i] = new VStringLiteral(ec.Package->FindString(*E->Name), E->Loc);
				delete E;
				E = NULL;
			}
			if (Args[i]->IsStrConst())
			{
				VStr CName = Args[i]->GetStrConst(ec.Package);
				TLocation ALoc = Args[i]->Loc;
				VClass* Cls = VClass::FindClassNoCase(*CName);
				if (!Cls)
				{
					ParseWarning(ALoc, "No such class %s", *CName);
					delete Args[i];
					Args[i] = NULL;
					Args[i] = new VNoneLiteral(ALoc);
				}
				else if (Func->ParamTypes[i].Class &&
					!Cls->IsChildOf(Func->ParamTypes[i].Class))
				{
					ParseWarning(ALoc, "Class %s is not a descendant of %s",
						*CName, Func->ParamTypes[i].Class->GetName());
					delete Args[i];
					Args[i] = NULL;
					Args[i] = new VNoneLiteral(ALoc);
				}
				else
				{
					delete Args[i];
					Args[i] = NULL;
					Args[i] = new VClassConstant(Cls, ALoc);
				}
			}
			break;

		case TYPE_State:
			if (Args[i]->IsIntConst())
			{
				int Offs = Args[i]->GetIntConst();
				TLocation ALoc = Args[i]->Loc;
				if (Offs < 0)
				{
					ParseError(ALoc, "Negative state jumps are not allowed");
				}
				else if (Offs == 0)
				{
					//	0 means no state
					delete Args[i];
					Args[i] = NULL;
					Args[i] = new VNoneLiteral(ALoc);
				}
				else
				{
					check(CallerState);
					VState* S = CallerState->GetPlus(Offs, true);
					if (!S)
					{
						ParseError(ALoc, "Bad state jump offset");
					}
					else
					{
						delete Args[i];
						Args[i] = NULL;
						Args[i] = new VStateConstant(S, ALoc);
					}
				}
			}
			else if (Args[i]->IsStrConst())
			{
				VStr Lbl = Args[i]->GetStrConst(ec.Package);
				TLocation ALoc = Args[i]->Loc;
				int DCol = Lbl.IndexOf("::");
				if (DCol >= 0)
				{
					//	Jump to a specific parent class state, resolve it and
					// pass value directly.
					VStr ClassName(Lbl, 0, DCol);
					VClass* CheckClass;
					if (ClassName.ICmp("Super"))
					{
						CheckClass = ec.SelfClass->ParentClass;
					}
					else
					{
						CheckClass = VClass::FindClassNoCase(*ClassName);
						if (!CheckClass)
						{
							ParseError(ALoc, "No such class %s", *ClassName);
						}
						else if (!ec.SelfClass->IsChildOf(CheckClass))
						{
							ParseError(ALoc, "%s is not a subclass of %s",
								ec.SelfClass->GetName(), CheckClass->GetName());
							CheckClass = NULL;
						}
					}
					if (CheckClass)
					{
						VStr LblName(Lbl, DCol + 2, Lbl.Length() - DCol - 2);
						TArray<VName> Names;
						VMemberBase::StaticSplitStateLabel(LblName, Names);
						VStateLabel* StLbl = CheckClass->FindStateLabel(Names, true);
						if (!StLbl)
						{
							ParseError(ALoc, "No such state %s", *Lbl);
						}
						else
						{
							delete Args[i];
							Args[i] = NULL;
							Args[i] = new VStateConstant(StLbl->State, ALoc);
						}
					}
				}
				else
				{
					//	It's a virtual state jump
					VExpression* TmpArgs[1];
					TmpArgs[0] = Args[i];
					Args[i] = new VInvocation(NULL,
						ec.SelfClass->FindMethodChecked("FindJumpState"),
						NULL, false, false, Args[i]->Loc, 1, TmpArgs);
				}
			}
			break;
		}
	}
	unguard;
}