Beispiel #1
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;
}
Beispiel #2
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;
}
Beispiel #3
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;
}
Beispiel #4
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;
}
Beispiel #5
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;
}
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;
}
Beispiel #7
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;
	}
}
Beispiel #8
0
VZipFile::VZipFile(const VStr& zipfile)
: ZipFileName(zipfile)
, Files(NULL)
, NumFiles(0)
{
	guard(VZipFile::VZipFile);
	GCon->Logf(NAME_Init, "Adding %s", *ZipFileName);

	FileStream = FL_OpenSysFileRead(ZipFileName);
	check(FileStream);

	vuint32 central_pos = SearchCentralDir();
	check(central_pos);

	FileStream->Seek(central_pos);

	vuint32 Signature;
	vuint16 number_disk;		//	Number of the current dist, used for
								// spaning ZIP, unsupported, always 0
	vuint16 number_disk_with_CD;//	Number the the disk with central dir, used
								// for spaning ZIP, unsupported, always 0
	vuint16 number_entry_CD;	//	Total number of entries in
								// the central dir
								// (same than number_entry on nospan)
	vuint16 size_comment;		//	Size of the global comment of the zipfile

	*FileStream
		//	The signature, already checked
		<< Signature
		//	Number of this disk
		<< number_disk
		//	Number of the disk with the start of the central directory
		<< number_disk_with_CD
		//	Total number of entries in the central dir on this disk
		<< NumFiles
		//	Total number of entries in the central dir
		<< number_entry_CD;

	check(number_entry_CD == NumFiles);
	check(number_disk_with_CD == 0);
	check(number_disk == 0);

	vuint32		size_central_dir;	//	Size of the central directory
	vuint32		offset_central_dir;	//	Offset of start of central directory with
									// respect to the starting disk number

	*FileStream
		<< size_central_dir
		<< offset_central_dir
		<< size_comment;

	check(central_pos >= offset_central_dir + size_central_dir);

	BytesBeforeZipFile = central_pos - (offset_central_dir + size_central_dir);

	Files = new VZipFileInfo[NumFiles];

	//	Set the current file of the zipfile to the first file.
	vuint32 pos_in_central_dir = offset_central_dir;
	for (int i = 0; i < NumFiles; i++)
	{
		VZipFileInfo& file_info = Files[i];

		FileStream->Seek(pos_in_central_dir + BytesBeforeZipFile);

		vuint32 Magic;
		vuint16 version;		//	Version made by
		vuint16 version_needed;	//	Version needed to extract
		vuint32 dosDate;		//	Last mod file date in Dos fmt
		vuint16 size_file_extra;//	Extra field length
		vuint16 size_file_comment;	//	File comment length
		vuint16 disk_num_start;	//	Disk number start
		vuint16 internal_fa;	//	Internal file attributes
		vuint32 external_fa;	//	External file attributes

		/* we check the magic */
		*FileStream
			<< Magic
			<< version
			<< version_needed
			<< file_info.flag
			<< file_info.compression_method
			<< dosDate
			<< file_info.crc
			<< file_info.compressed_size
			<< file_info.uncompressed_size
			<< file_info.size_filename
			<< size_file_extra
			<< size_file_comment
			<< disk_num_start
			<< internal_fa
			<< external_fa
			<< file_info.offset_curfile;

		check(Magic == 0x02014b50);

		char* filename_inzip = new char[file_info.size_filename + 1];
		filename_inzip[file_info.size_filename] = '\0';
		FileStream->Serialise(filename_inzip, file_info.size_filename);
		Files[i].Name = VStr(filename_inzip).ToLower().FixFileSlashes();
		delete[] filename_inzip;
		filename_inzip = NULL;

		//	Set up lump name for WAD-like access.
		VStr LumpName = Files[i].Name.ExtractFileName().StripExtension();

		//	Map some directories to WAD namespaces.
		Files[i].LumpNamespace =
			Files[i].Name.StartsWith("sprites/") ? WADNS_Sprites :
			Files[i].Name.StartsWith("flats/") ? WADNS_Flats :
			Files[i].Name.StartsWith("colormaps/") ? WADNS_ColourMaps :
			Files[i].Name.StartsWith("acs/") ? WADNS_ACSLibrary :
			Files[i].Name.StartsWith("textures/") ? WADNS_NewTextures :
			Files[i].Name.StartsWith("voices/") ? WADNS_Voices :
			Files[i].Name.StartsWith("hires/") ? WADNS_HiResTextures :
			Files[i].Name.StartsWith("patches/") ? WADNS_Patches :
			Files[i].Name.StartsWith("graphics/") ? WADNS_Graphics :
			Files[i].Name.StartsWith("sounds/") ? WADNS_Sounds :
			Files[i].Name.StartsWith("music/") ? WADNS_Music :
			Files[i].Name.IndexOf('/') == -1 ? WADNS_Global : -1;

		//	Anything from other directories won't be accessed as lump.
		if (Files[i].LumpNamespace == -1)
			LumpName = VStr();

		//	For sprites \ is a valid frame character but is not allowed to
		// be in a file name, so we do a little mapping here.
		if (Files[i].LumpNamespace == WADNS_Sprites)
		{
			for (size_t ni = 0; ni < LumpName.Length(); ni++)
			{
				if (LumpName[ni] == '^')
				{
					LumpName[ni] = '\\';
				}
			}
		}

		//	Final lump name;
		Files[i].LumpName = VName(*LumpName, VName::AddLower8);

		//	Set the current file of the zipfile to the next file.
		pos_in_central_dir += SIZECENTRALDIRITEM + file_info.size_filename +
			size_file_extra + size_file_comment;
	}

	//	Sort files alphabetically.
	qsort(Files, NumFiles, sizeof(VZipFileInfo), FileCmpFunc);
	unguard;
}