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; }
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; }
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; }
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; }
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; }
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; } }
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; }