/** * Tibia GIMUD Server - a free and open-source MMORPG server emulator * Copyright (C) 2019 Sabrehaven and Mark Samman * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef FS_SCRIPT_H_2905B3D5EAB34B4BA8830167262D2DC1 #define FS_SCRIPT_H_2905B3D5EAB34B4BA8830167262D2DC1 #include "tools.h" enum TOKEN { ENDOFFILE = 0, IDENTIFIER, NUMBER, STRING, BYTES, COORDINATE, SPECIAL }; class ScriptReader { public: ScriptReader() { Token = ENDOFFILE; RecursionDepth = -1; } ~ScriptReader() { if (RecursionDepth != -1) { std::cout << "ScriptReader::~ScriptReader: File is still open.\n"; for (int i = RecursionDepth; i != -1; i = RecursionDepth) { if (fclose(File[i])) { std::cout << "ScriptReader::close: Error when closing the file.\n"; } --RecursionDepth; } } } TOKEN Token; FILE* File[3]; int RecursionDepth; char Filename[3][4096]; std::string CurrentDirectory; std::string String; unsigned char Bytes[1000]; int Line[3]; int Number; uint16_t CoordX; uint16_t CoordY; uint8_t CoordZ; char Special; bool open(const std::string& FileName) { RecursionDepth++; if (RecursionDepth == 3) { error("ScriptReader::open: too big recursion.\n"); error("Recursion depth too high.\n"); return false; } if (RecursionDepth > -1) { CurrentDirectory = FileName; if (FileName.find('/') != std::string::npos) { int32_t end = FileName.find_last_of('/'); CurrentDirectory = FileName.substr(0, end); strcpy(Filename[RecursionDepth], FileName.substr(end + 1, FileName.length() - end).c_str()); } else { strcpy(Filename[RecursionDepth], FileName.c_str()); } File[RecursionDepth] = fopen(FileName.c_str(), "rb"); if (!File[RecursionDepth]) { printf("ScriptReader::open: Can not open file %s.\n", FileName.c_str()); RecursionDepth--; printf("Cannot open script-file\n"); return false; } } Line[RecursionDepth] = 1; return true; } void close() { int depth; // eax@1 depth = RecursionDepth; if (depth == -1) { std::cout << "ScriptReader::close: Invalid recursion depth.\n"; } else { if (fclose(this->File[depth])) { std::cout << "ScriptReader::close: Error when closing file.\n"; } --RecursionDepth; } } void error(const std::string& text) { int depth = this->RecursionDepth; if (depth != -1) { printf("error in script-file \"%s\", line %d: %s\n", Filename[this->RecursionDepth], this->Line[this->RecursionDepth], text.c_str()); do { if (fclose(this->File[depth])) { std::cout << "ScriptReader::close: Error when closing file.\n"; } --this->RecursionDepth; depth = this->RecursionDepth; } while (this->RecursionDepth != -1); } } void nextToken(); std::string readIdentifier() { nextToken(); if (this->Token != IDENTIFIER) error("identifier expected"); if (this->Token != IDENTIFIER) error("identifier expected"); String = asLowerCaseString(String); return std::string(this->String); } int readNumber() { TOKEN v1; // edx@1 int v2; // esi@1 nextToken(); v1 = this->Token; v2 = 1; if (this->Token == SPECIAL && this->Special == 45) { v2 = -1; nextToken(); v1 = this->Token; } if (v1 != NUMBER) error("number expected"); if (this->Token != NUMBER) error("number expected"); return this->Number * v2; } std::string readString() { nextToken(); if (this->Token != STRING) error("string expected"); if (this->Token != STRING) error("string expected"); return this->String; } uint8_t* readBytesequence() { nextToken(); if (this->Token != 4) error("byte-sequence expected"); if (this->Token != 4) error("byte-sequence expected"); return this->Bytes; } void readCoordinate(uint16_t& x, uint16_t& y, uint8_t& z) { nextToken(); if (this->Token != COORDINATE) error("coordinates expected"); if (this->Token != COORDINATE) error("coordinates expected"); x = this->CoordX; y = this->CoordY; z = this->CoordZ; } int readSpecial() { nextToken(); if (this->Token != SPECIAL) error("special-char expected"); if (this->Token != SPECIAL) error("special-char expected"); return this->Special; } void readSymbol(char Symbol) { nextToken(); if (this->Token != SPECIAL) error("special-char expected"); if (Symbol != this->Special) error("special-char expected"); } std::string getIdentifier() { if (this->Token != IDENTIFIER) error("identifier expected"); String = asLowerCaseString(String); return this->String; } int getNumber() { if (this->Token != NUMBER) error("number expected"); return this->Number; } std::string getString() { if (this->Token != STRING) error("string expected"); return this->String; } uint8_t* getBytesequence() { if (this->Token != BYTES) error("byte-sequence expected"); return this->Bytes; } void getcoordinate(int32_t& x, int32_t& y, int32_t& z) { if (this->Token != COORDINATE) error("coordinates expected"); x = this->CoordX; y = this->CoordY; z = this->CoordZ; } int getSpecial() { if (this->Token != SPECIAL) error("special-char expected"); return this->Special; } }; #endif