Fri, 10 Jan 2014 21:58:42 +0200
- major refactoring begins
--- a/CMakeLists.txt Fri Jan 10 16:11:49 2014 +0200 +++ b/CMakeLists.txt Fri Jan 10 21:58:42 2014 +0200 @@ -1,6 +1,7 @@ add_executable (botc src/commands.cxx src/events.cxx + src/format.cc src/main.cxx src/objwriter.cxx src/parser.cxx @@ -9,4 +10,6 @@ src/str.cxx src/stringtable.cxx src/variables.cxx -) \ No newline at end of file +) + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -W -Wall") \ No newline at end of file
--- a/src/array.h Fri Jan 10 16:11:49 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,190 +0,0 @@ -/* - * botc source code - * Copyright (C) 2012 Santeri `Dusk` Piippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of the developer nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * 4. Redistributions in any form must be accompanied by information on how to - * obtain complete source code for the software and any accompanying - * software that uses the software. The source code must either be included - * in the distribution or be available for no more than the cost of - * distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include "common.h" - -#define ITERATE_SUBSCRIPTS(link) \ - for (link = data; link; link = link->next) - -#define foreach_counter(NAME) \ - (int)(reinterpret_cast<int> (foreach_counter##NAME) / sizeof (foreach_counter##NAME)) -#define foreach(T,NAME,ARRAY) \ - if (ARRAY.size() > 0) for (T NAME = ARRAY[0], *foreach_counter##NAME = 0; \ - foreach_counter(NAME) < (int)(ARRAY.size()); \ - NAME = ARRAY[reinterpret_cast<int> (++foreach_counter##NAME) / sizeof (foreach_counter##NAME)]) - -// Single element of an array -template <class T> class arrayElement { -public: - T value; - arrayElement<T>* next; - - arrayElement () { - next = NULL; - } -}; - -// Dynamic array -template <class T> class array { -public: - array () { - data = NULL; - } - - array (T* stuff, unsigned int c) { - printf ("%d elements\n", c); - data = NULL; - - for (unsigned int i = 0; i < c; i++) - push (stuff[c]); - } - - ~array () { - if (data) - deleteElement (data); - } - - void push (T stuff) { - arrayElement<T>* e = new arrayElement<T>; - e->value = stuff; - e->next = NULL; - - if (!data) { - data = e; - return; - } - - arrayElement<T>* link; - for (link = data; link && link->next; link = link->next); - link->next = e; - } - - T pop () { - int pos = size() - 1; - if (pos == -1) - error ("array::pop: tried to pop an array with no elements\n"); - T res = subscript (pos); - remove (pos); - return res; - } - - void remove (unsigned int pos) { - if (!data) - error ("tried to use remove on an array with no elements"); - - if (pos == 0) { - // special case for first element - arrayElement<T>* first = data; - data = data->next; - delete first; - return; - } - - arrayElement<T>* link = data; - unsigned int x = 0; - while (link->next) { - if (x == pos - 1) - break; - link = link->next; - x++; - } - if (!link) - error ("no such element in array\n"); - - arrayElement<T>* nextlink = link->next->next; - delete link->next; - link->next = nextlink; - } - - unsigned int size () { - unsigned int x = 0; - arrayElement<T>* link; - ITERATE_SUBSCRIPTS(link) - x++; - return x; - } - - T& subscript (unsigned int i) { - arrayElement<T>* link; - unsigned int x = 0; - ITERATE_SUBSCRIPTS(link) { - if (x == i) - return link->value; - x++; - } - - error ("array: tried to access subscript %u in an array of %u elements\n", i, x); - return data->value; - } - - T* out () { - int s = size(); - T* out = new T[s]; - unsigned int x = 0; - - arrayElement<T>* link; - ITERATE_SUBSCRIPTS(link) { - out[x] = link->value; - x++; - } - - return out; - } - - T& operator [] (const unsigned int i) { - return subscript (i); - } - - void operator << (const T stuff) { - push (stuff); - } - -private: - void deleteElement (arrayElement<T>* e) { - if (e->next) - deleteElement (e->next); - delete e; - } - - arrayElement<T>* data; -};
--- a/src/botcommands.h Fri Jan 10 16:11:49 2014 +0200 +++ b/src/botcommands.h Fri Jan 10 21:58:42 2014 +0200 @@ -49,23 +49,14 @@ // //----------------------------------------------------------------------------- -#ifndef __BOTCOMMANDS_H__ -#define __BOTCOMMANDS_H__ +#ifndef BOTC_BOTCOMMANDS_H +#define BOTC_BOTCOMMANDS_H #include "bots.h" //***************************************************************************** // DEFINES -#define SETENEMY_LASTSEEN 0 -#define SETENEMY_LASTSHOTBY 1 - -// Different results for pathing commands. -#define PATH_UNREACHABLE -1 -#define PATH_INCOMPLETE 0 -#define PATH_COMPLETE 1 -#define PATH_REACHEDGOAL 2 - // This is the size of the return string for the bot command functions. #define BOTCMD_RETURNSTRING_SIZE 256 @@ -170,4 +161,4 @@ } BOTCMD_e; -#endif // __BOTCOMMANDS_H__ \ No newline at end of file +#endif // BOTC_BOTCOMMANDS_H \ No newline at end of file
--- a/src/bots.h Fri Jan 10 16:11:49 2014 +0200 +++ b/src/bots.h Fri Jan 10 21:58:42 2014 +0200 @@ -48,8 +48,8 @@ // //----------------------------------------------------------------------------- -#ifndef __BOTS_H__ -#define __BOTS_H__ +#ifndef BOTC_BOTS_H +#define BOTC_BOTS_H //***************************************************************************** // DEFINES @@ -269,4 +269,4 @@ } BOTEVENT_e; -#endif // __BOTS_H__ +#endif // BOTC_BOTS_H
--- a/src/commands.cxx Fri Jan 10 16:11:49 2014 +0200 +++ b/src/commands.cxx Fri Jan 10 21:58:42 2014 +0200 @@ -38,30 +38,31 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#define __COMMANDS_CXX__ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include "common.h" +#include "main.h" #include "scriptreader.h" #include "str.h" #include "commands.h" +CommandDef* g_CommDef; + // ============================================================================ // Reads command definitions from commands.def and stores them to memory. void ReadCommands () { ScriptReader* r = new ScriptReader ("commands.def"); - g_CommDef = NULL; + g_CommDef = null; CommandDef* curdef = g_CommDef; unsigned int numCommDefs = 0; while (r->PeekNext().len()) { CommandDef* comm = new CommandDef; - comm->next = NULL; + comm->next = null; // Number r->MustNumber (); - comm->number = r->token; + comm->number = r->token.to_long(); r->MustNext (":"); @@ -83,13 +84,13 @@ // Num args r->MustNumber (); - comm->numargs = r->token; + comm->numargs = r->token.to_long(); r->MustNext (":"); // Max args r->MustNumber (); - comm->maxargs = r->token; + comm->maxargs = r->token.to_long(); if (comm->maxargs > MAX_MAXARGS) r->ParserError ("maxargs (%d) greater than %d!", comm->maxargs, MAX_MAXARGS); @@ -134,7 +135,7 @@ break; } - comm->defvals[curarg] = r->token; + comm->defvals[curarg] = r->token.to_long(); } r->MustNext (")"); @@ -163,20 +164,20 @@ // ============================================================================ // Finds a command by name -CommandDef* FindCommand (str fname) { +CommandDef* FindCommand (string fname) { CommandDef* comm; ITERATE_COMMANDS (comm) { - if (!fname.icompare (comm->name)) + if (fname.to_uppercase() == comm->name.to_uppercase()) return comm; } - return NULL; + return null; } // ============================================================================ // Returns the prototype of the command -str GetCommandPrototype (CommandDef* comm) { - str text; +string GetCommandPrototype (CommandDef* comm) { + string text; text += GetTypeName (comm->returnvalue); text += ' '; text += comm->name;
--- a/src/commands.h Fri Jan 10 16:11:49 2014 +0200 +++ b/src/commands.h Fri Jan 10 21:58:42 2014 +0200 @@ -38,21 +38,21 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __COMMANDS_H__ -#define __COMMANDS_H__ +#ifndef BOTC_COMMANDS_H +#define BOTC_COMMANDS_H #define MAX_MAXARGS 8 #define MAX_ARGNAMELEN 16 -#include "common.h" +#include "main.h" #include "str.h" #include "botcommands.h" #define ITERATE_COMMANDS(comm) \ - for (comm = g_CommDef; comm->next != NULL; comm = comm->next) + for (comm = g_CommDef; comm->next != null; comm = comm->next) struct CommandDef { - str name; + string name; int number; int numargs; int maxargs; @@ -64,12 +64,9 @@ }; void ReadCommands (); -CommandDef* FindCommand (str a); -str GetCommandPrototype (CommandDef* comm); +CommandDef* FindCommand (string a); +string GetCommandPrototype (CommandDef* comm); -#ifndef __COMMANDS_CXX__ -extern -#endif -CommandDef* g_CommDef; +extern CommandDef* g_CommDef; -#endif // __COMMANDS_H__ \ No newline at end of file +#endif // BOTC_COMMANDS_H \ No newline at end of file
--- a/src/common.h Fri Jan 10 16:11:49 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,186 +0,0 @@ -/* - * botc source code - * Copyright (C) 2012 Santeri `Dusk` Piippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of the developer nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * 4. Redistributions in any form must be accompanied by information on how to - * obtain complete source code for the software and any accompanying - * software that uses the software. The source code must either be included - * in the distribution or be available for no more than the cost of - * distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef __COMMON_H__ -#define __COMMON_H__ - -#include <stdio.h> -#include <stdarg.h> -#include <stdint.h> -#include "bots.h" -#include "str.h" - -// Application name and version -#define APPNAME "botc" -#define VERSION_MAJOR 0 -#define VERSION_MINOR 999 - -// Use a macro for Write so we can get the function name -// This can be pretty crucial in debugging. -#ifdef __GNUC__ -#define Write(STUFF) DoWrite (__PRETTY_FUNCTION__, STUFF) -#else -#define Write(STUFF) DoWrite (__func__, STUFF) -#endif - -// On Windows, files are case-insensitive -#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__) - #define FILE_CASEINSENSITIVE -#endif - -// Parser mode: where is the parser at? -enum parsermode_e { - MODE_TOPLEVEL, // at top level - MODE_EVENT, // inside event definition - MODE_MAINLOOP, // inside mainloop - MODE_ONENTER, // inside onenter - MODE_ONEXIT, // inside onexit -}; - -enum type_e { - TYPE_UNKNOWN = 0, - TYPE_VOID, - TYPE_INT, - TYPE_STRING, - TYPE_BOOL, -}; - -#define CHECK_FILE(pointer,path,action) \ - if (!pointer) { \ - error ("couldn't open %s for %s!\n", (char*)path, action); \ - exit (1); \ - } - -// Shortcut for formatting -#define PERFORM_FORMAT(in, out) \ - va_list v; \ - va_start (v, in); \ - char* out = vdynformat (in, v, 256); \ - va_end (v); - -// Plural expression -#define PLURAL(n) (n != 1) ? "s" : "" - -// Shortcut for zeroing something -#define ZERO(obj) memset (&obj, 0, sizeof (obj)); - -void error (const char* text, ...); -char* ObjectFileName (str s); -bool fexists (char* path); -type_e GetTypeByName (str token); -str GetTypeName (type_e type); - -// Make the parser's variables globally available -extern int g_NumStates; -extern int g_NumEvents; -extern parsermode_e g_CurMode; -extern str g_CurState; - -#define neurosphere if (g_Neurosphere) -#define twice for (int repeat_token = 0; repeat_token < 2; repeat_token++) - -#ifndef __GNUC__ -#define __attribute__(X) -#endif -#define deprecated __attribute__ ((deprecated)) - -// Power function -template<class T> T pow (T a, unsigned int b) { - if (!b) - return 1; - - T r = a; - while (b > 1) { - b--; - r = r * a; - } - - return r; -} - -// Whitespace check -inline bool IsCharWhitespace (char c) { - return (c <= 32 || c == 127 || c == 255); -} - -// Byte datatype -typedef int32_t word; -typedef unsigned char byte; - -// Keywords -#ifndef __MAIN_CXX__ -extern const char** g_Keywords; -#endif - -bool IsKeyword (str s); -unsigned int NumKeywords (); - -// Script mark and reference -struct ScriptMark { - str name; - size_t pos; -}; - -struct ScriptMarkReference { - unsigned int num; - size_t pos; -}; - -// ==================================================================== -// Generic union -template <class T> union union_t { - T val; - byte b[sizeof (T)]; - char c[sizeof (T)]; - double d; - float f; - int i; - word w; -}; - -// ==================================================================== -// Finds a byte in the given value. -template <class T> inline unsigned char GetByteIndex (T a, unsigned int b) { - union_t<T> uni; - uni.val = a; - return uni.b[b]; -} - -#endif // __COMMON_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/containers.h Fri Jan 10 21:58:42 2014 +0200 @@ -0,0 +1,227 @@ +#ifndef LIBCOBALT_CONTAINERS_H +#define LIBCOBALT_CONTAINERS_H + +#include <cassert> +#include <algorithm> +#include <deque> +#include <initializer_list> + +template<class T> class list +{ + public: + typedef typename ::std::deque<T> list_type; + typedef typename list_type::iterator it; + typedef typename list_type::const_iterator c_it; + typedef typename list_type::reverse_iterator r_it; + typedef typename list_type::const_reverse_iterator cr_it; + typedef T element_type; + typedef list<T> self_type; + + list() {} + list (std::initializer_list<element_type> vals) + { + m_data = vals; + } + + list (const list_type& a) : m_data (a) {} + + it begin() + { + return m_data.begin(); + } + + c_it begin() const + { + return m_data.cbegin(); + } + + it end() + { + return m_data.end(); + } + + c_it end() const + { + return m_data.cend(); + } + + r_it rbegin() + { + return m_data.rbegin(); + } + + cr_it crbegin() const + { + return m_data.crbegin(); + } + + r_it rend() + { + return m_data.rend(); + } + + cr_it crend() const + { + return m_data.crend(); + } + + void erase (int pos) + { + assert (pos < size()); + m_data.erase (m_data.begin() + pos); + } + + element_type& push_front (const element_type& value) + { + m_data.push_front (value); + return m_data[0]; + } + + element_type& push_back (const element_type& value) + { + m_data.push_back (value); + return m_data[m_data.size() - 1]; + } + + void push_back (const self_type& vals) + { + for (const T & val : vals) + push_back (val); + } + + bool pop (T& val) + { + if (size() == 0) + return false; + + val = m_data[size() - 1]; + erase (size() - 1); + return true; + } + + T& operator<< (const T& value) + { + return push_back (value); + } + + void operator<< (const self_type& vals) + { + push_back (vals); + } + + bool operator>> (T& value) + { + return pop (value); + } + + self_type reverse() const + { + self_type rev; + + for (const T & val : *this) + val >> rev; + + return rev; + } + + void clear() + { + m_data.clear(); + } + + void insert (int pos, const element_type& value) + { + m_data.insert (m_data.begin() + pos, value); + } + + void makeUnique() + { + // Remove duplicate entries. For this to be effective, the vector must be + // sorted first. + sort(); + it pos = std::unique (begin(), end()); + resize (std::distance (begin(), pos)); + } + + int size() const + { + return m_data.size(); + } + + element_type& operator[] (int n) + { + assert (n < size()); + return m_data[n]; + } + + const element_type& operator[] (int n) const + { + assert (n < size()); + return m_data[n]; + } + + void resize (std::ptrdiff_t size) + { + m_data.resize (size); + } + + void sort() + { + std::sort (begin(), end()); + } + + int find (const element_type& needle) + { + int i = 0; + + for (const element_type & hay : *this) + { + if (hay == needle) + return i; + + i++; + } + + return -1; + } + + void remove (const element_type& it) + { + int idx; + + if ( (idx = find (it)) != -1) + erase (idx); + } + + inline bool is_empty() const + { + return size() == 0; + } + + self_type mid (int a, int b) const + { + assert (a >= 0 && b >= 0 && a < size() && b < size() && a <= b); + self_type result; + + for (int i = a; i <= b; ++i) + result << operator[] (i); + + return result; + } + + inline const list_type& std_deque() const + { + return m_data; + } + + private: + list_type m_data; +}; + +template<class T> list<T>& operator>> (const T& value, list<T>& haystack) +{ + haystack.push_front (value); + return haystack; +} + +#endif // LIBCOBALT_CONTAINERS_H
--- a/src/databuffer.h Fri Jan 10 16:11:49 2014 +0200 +++ b/src/databuffer.h Fri Jan 10 21:58:42 2014 +0200 @@ -1,48 +1,8 @@ -/* - * botc source code - * Copyright (C) 2012 Santeri `Dusk` Piippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of the developer nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * 4. Redistributions in any form must be accompanied by information on how to - * obtain complete source code for the software and any accompanying - * software that uses the software. The source code must either be included - * in the distribution or be available for no more than the cost of - * distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __DATABUFFER_H__ -#define __DATABUFFER_H__ +#ifndef BOTC_DATABUFFER_H +#define BOTC_DATABUFFER_H #include <stdio.h> #include <string.h> -#include "common.h" +#include "main.h" #include "stringtable.h" #define MAX_MARKS 512 @@ -79,8 +39,8 @@ // Clear the marks table out for (unsigned int u = 0; u < MAX_MARKS; u++) { - marks[u] = NULL; - refs[u] = NULL; + marks[u] = null; + refs[u] = null; } } @@ -100,8 +60,7 @@ // ==================================================================== // Write stuff to the buffer - template<class T> void DoWrite (const char* func, T stuff) { - // printf ("DoWrite: called from %s\n", func); + template<class T> void Write (T stuff) { if (writesize + sizeof (T) >= allocsize) { // We don't have enough space in the buffer to write // the stuff - thus resize. First, store the old @@ -157,11 +116,11 @@ marks[u] = other->marks[u]; marks[u]->pos += oldsize; - // The original mark becomes NULL so that the deconstructor + // The original mark becomes null so that the deconstructor // will not delete it prematurely. (should it delete any // marks in the first place since there is no such thing // as at temporary mark?) - other->marks[u] = NULL; + other->marks[u] = null; } if (other->refs[u]) { @@ -188,7 +147,7 @@ // position in the bytecode. The actual permanent position cannot // be predicted in any way or form, thus these things will be used // to "mark" a position like that for future use. - unsigned int AddMark (str name) { + unsigned int AddMark (string name) { // Find a free slot for the mark unsigned int u = g_NextMark++; @@ -237,27 +196,29 @@ // Delete the mark delete marks[marknum]; - marks[marknum] = NULL; + marks[marknum] = null; // Delete its references for (unsigned int u = 0; u < MAX_MARKS; u++) { if (refs[u]->num == marknum) { delete refs[u]; - refs[u] = NULL; + refs[u] = null; } } } // Adjusts a mark to the current position - void MoveMark (unsigned int mark, int offset = -1) { + void MoveMark (unsigned int mark) { if (!marks[mark]) return; + marks[mark]->pos = writesize; } - void OffsetMark (unsigned int mark, size_t offset) { + void OffsetMark (unsigned int mark, int offset) { if (!marks[mark]) return; + marks[mark]->pos += offset; } @@ -284,7 +245,7 @@ } // Write a float into the buffer - void WriteFloat (str floatstring) { + void WriteFloat (string floatstring) { // TODO: Casting float to word causes the decimal to be lost. // Find a way to store the number without such loss. float val = atof (floatstring); @@ -294,10 +255,10 @@ Write (DH_UNARYMINUS); } - void WriteString (str string) { + void WriteString (string a) { Write (DH_PUSHSTRINGINDEX); - Write (PushToStringTable (string)); + Write (get_string_table_index (a)); } }; -#endif // __DATABUFFER_H__ \ No newline at end of file +#endif // BOTC_DATABUFFER_H \ No newline at end of file
--- a/src/events.cxx Fri Jan 10 16:11:49 2014 +0200 +++ b/src/events.cxx Fri Jan 10 21:58:42 2014 +0200 @@ -38,10 +38,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#define __EVENTS_CXX__ #include <stdlib.h> #include <stdio.h> -#include "common.h" +#include "main.h" #include "scriptreader.h" #include "str.h" #include "events.h" @@ -52,14 +51,14 @@ // Read event definitions from file void ReadEvents () { ScriptReader* r = new ScriptReader ("events.def"); - g_EventDef = NULL; + g_EventDef = null; EventDef* curdef = g_EventDef; unsigned int numEventDefs = 0; while (r->Next()) { EventDef* e = new EventDef; e->name = r->token; e->number = numEventDefs; - e->next = NULL; + e->next = null; // g_EventDef becomes the first eventdef if (!g_EventDef) @@ -92,7 +91,7 @@ EventDef* e = g_EventDef; while (idx > 0) { if (!e->next) - return NULL; + return null; e = e->next; idx--; } @@ -101,12 +100,12 @@ // ============================================================================ // Finds an event definition by name -EventDef* FindEventByName (str a) { +EventDef* FindEventByName (string a) { EventDef* e; - for (e = g_EventDef; e->next != NULL; e = e->next) { - if (!a.icompare (e->name)) + for (e = g_EventDef; e->next != null; e = e->next) { + if (a.to_uppercase() == e->name.to_uppercase()) return e; } - return NULL; + return null; } \ No newline at end of file
--- a/src/events.h Fri Jan 10 16:11:49 2014 +0200 +++ b/src/events.h Fri Jan 10 21:58:42 2014 +0200 @@ -38,13 +38,13 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __EVENT_H__ -#define __EVENT_H__ +#ifndef BOTC_EVENTS_H +#define BOTC_EVENTS_H #include "str.h" struct EventDef { - str name; + string name; int number; EventDef* next; }; @@ -52,6 +52,6 @@ void ReadEvents (); void UnlinkEvents (EventDef* e); EventDef* FindEventByIdx (unsigned int idx); -EventDef* FindEventByName (str a); +EventDef* FindEventByName (string a); -#endif // __EVENT_H__ \ No newline at end of file +#endif // BOTC_EVENTS_H \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/format.cc Fri Jan 10 21:58:42 2014 +0200 @@ -0,0 +1,94 @@ +#include <cstdio> +#include "main.h" +#include "format.h" + +static void draw_pos (const string& fmt, int pos) +{ + string rep (fmt); + rep.replace ("\n", "↵"); + rep.replace ("\t", "⇥"); + + fprintf (stderr, "%s\n", rep.chars()); + + for (int x = 0; x < pos; ++x) + fprintf (stderr, "-"); + + fprintf (stderr, "^\n"); +} + +string format_args (const list<format_arg>& args) +{ + const string& fmtstr = args[0].as_string(); + assert (args.size() >= 1); + + if (args.size() == 1) + return args[0].as_string(); + + string fmt = fmtstr; + string out; + int pos = 0; + + while ((pos = fmt.first ("%", pos)) != -1) + { + if (fmt[pos + 1] == '%') + { + fmt.replace (pos, 2, "%"); + pos++; + continue; + } + + int ofs = 1; + char mod = '\0'; + + // handle modifiers + if (fmt[ pos + ofs ] == 's' || fmt[ pos + ofs ] == 'x') + { + mod = fmt[ pos + ofs ]; + ofs++; + } + + if (!isdigit (fmt[ pos + ofs ])) + { + fprintf (stderr, "bad format string, expected digit with optional " + "modifier after '%%':\n"); + draw_pos (fmt, pos); + return fmt; + } + + int i = fmt[ pos + ofs ] - '0'; + + if (i >= args.size()) + { + fprintf (stderr, "format arg #%d used but not defined: %s\n", i, fmtstr.chars()); + return fmt; + } + + string repl = args[i].as_string(); + + if (mod == 's') + { + repl = (repl == "1") ? "" : "s"; + } + + elif (mod == 'd') + { + repl.sprintf ("%d", repl[0]); + } + elif (mod == 'x') + { + // modifier x: reinterpret the argument as hex + repl.sprintf ("0x%X", strtol (repl.chars(), null, 10)); + } + + fmt.replace (pos, 1 + ofs, repl); + pos += repl.length(); + } + + return fmt; +} + +void print_args (FILE* fp, const list<format_arg>& args) +{ + string out = format_args (args); + fprintf (fp, "%s", out.chars()); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/format.h Fri Jan 10 21:58:42 2014 +0200 @@ -0,0 +1,150 @@ +#ifndef BOTC_FORMAT_H +#define BOTC_FORMAT_H + +#include "str.h" +#include "containers.h" + +class format_arg +{ + public: + format_arg (const string& a) + { + m_string = a; + } + + format_arg (int a) + { + m_string.sprintf ("%d", a); + } + + format_arg (long a) + { + m_string.sprintf ("%ld", a); + } + + format_arg (uint a) + { + m_string.sprintf ("%u", a); + } + + format_arg (ulong a) + { + m_string.sprintf ("%lu", a); + } + + format_arg (const char* a) + { + m_string = a; + } + + format_arg (void* a) + { + m_string.sprintf ("%p", a); + } + + format_arg (const void* a) + { + m_string.sprintf ("%p", a); + } + + template<class T> format_arg (const list<T>& list) + { + if (list.is_empty()) + { + m_string = "{}"; + return; + } + + m_string = "{ "; + + for (const T & a : list) + { + if (&a != &list[0]) + m_string += ", "; + + m_string += format_arg (a).as_string(); + } + + m_string += " }"; + } + +/* + template<class T, class R> format_arg (const std::map<T, R>& a) + { + if (a.size() == 0) + { + m_string = "{}"; + return; + } + + m_string = "{ "; + + for (std::pair<T, R> it : a) + { + if (m_string != "{ ") + m_string += ", "; + + m_string += format_arg (it.first).as_string() + "=" + + format_arg (it.second).as_string(); + } + + m_string += " }"; + } +*/ + + inline const string& as_string() const + { + return m_string; + } + + private: + string m_string; +}; + +template<class T> string custom_format (T a, const char* fmtstr) +{ + string out; + out.sprintf (fmtstr, a); + return out; +} + +inline string hex (ulong a) +{ + return custom_format (a, "0x%X"); +} + +inline string charnum (char a) +{ + return custom_format (a, "%d"); +} + +string format_args (const list<format_arg>& args); +void print_args (FILE* fp, const list<format_arg>& args); +void do_fatal (const list<format_arg>& args); + +#ifndef IN_IDE_PARSER +#define format(...) format_args({ __VA_ARGS__ }) +#define fprint(A, ...) print_args( A, { __VA_ARGS__ }) +#define print(...) print_args( stdout, { __VA_ARGS__ }) +#define fatal(...) do_fatal({ __VA_ARGS__ }) +#else +string format (void, ...); +void fprint (FILE* fp, ...); +void print (void, ...); +void fatal (void, ...); +#endif + +#ifndef IN_IDE_PARSER +# ifdef DEBUG +# define devf(...) fprint( stderr, __VA_ARGS__ ) +# define dvalof( A ) fprint( stderr, "value of '%1' = %2\n", #A, A ) +# else +# define devf(...) +# define dvalof( A ) +# endif // DEBUG +#else +void devf (void, ...); +void dvalof (void a); +#endif // IN_IDE_PARSER + +#endif // BOTC_FORMAT_H
--- a/src/main.cxx Fri Jan 10 16:11:49 2014 +0200 +++ b/src/main.cxx Fri Jan 10 21:58:42 2014 +0200 @@ -38,12 +38,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#define __MAIN_CXX__ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "common.h" +#include "main.h" #include "str.h" #include "scriptreader.h" @@ -52,14 +51,14 @@ #include "commands.h" #include "stringtable.h" #include "variables.h" -#include "array.h" +#include "containers.h" #include "databuffer.h" #include "bots.h" #include "botcommands.h" // List of keywords -const char* g_Keywords[] = { +const string_list g_Keywords = { "bool", "break", "case", @@ -103,7 +102,7 @@ CommandDef* comm; ITERATE_COMMANDS (comm) - printf ("%s\n", GetCommandPrototype (comm).chars()); + print ("%1\n", GetCommandPrototype (comm)); printf ("------------------------------------------------------\n"); printf ("End of command list\n"); @@ -111,13 +110,15 @@ } // Print header - str header; - str headerline = "-="; - header.appendformat ("%s version %d.%d", APPNAME, VERSION_MAJOR, VERSION_MINOR); - - headerline *= (header.len() / 2) - 1; + string header; + string headerline; + header = format ("%1 version %2.%3", APPNAME, VERSION_MAJOR, VERSION_MINOR); + + for (int i = 0; i < (header.len() / 2) - 1; ++i) + headerline += "-="; + headerline += '-'; - printf ("%s\n%s\n", header.chars(), headerline.chars()); + print ("%1\n%2\n", header, headerline); if (argc < 2) { fprintf (stderr, "usage: %s <infile> [outfile] # compiles botscript\n", argv[0]); @@ -131,7 +132,7 @@ error ("%s expects a word (uint32_t) to be 4 bytes in size, is %d\n", APPNAME, sizeof (word)); - str outfile; + string outfile; if (argc < 3) outfile = ObjectFileName (argv[1]); else @@ -141,7 +142,7 @@ // ask the user if we want to overwrite it if (fexists (outfile)) { // Additional warning if the paths are the same - str warning; + string warning; #ifdef FILE_CASEINSENSITIVE if (!outfile.icompare (argv[1])) #else @@ -167,9 +168,6 @@ ReadEvents (); ReadCommands (); - // Init stuff - InitStringTable (); - // Prepare reader and writer ScriptReader* r = new ScriptReader (argv[1]); ObjWriter* w = new ObjWriter (outfile); @@ -181,7 +179,7 @@ // Parse done, print statistics and write to file unsigned int globalcount = g_GlobalVariables.size(); - unsigned int stringcount = CountStringTable (); + unsigned int stringcount = num_strings_in_table (); int NumMarks = w->MainBuffer->CountMarks (); int NumRefs = w->MainBuffer->CountReferences (); printf ("%u / %u strings written\n", stringcount, MAX_LIST_STRINGS); @@ -206,39 +204,44 @@ // ============================================================================ // Does the given file exist? -bool fexists (char* path) { +bool fexists (string path) { if (FILE* test = fopen (path, "r")) { fclose (test); return true; } + return false; } // ============================================================================ // Generic error void error (const char* text, ...) { - PERFORM_FORMAT (text, c); - fprintf (stderr, "error: %s", c); + va_list va; + va_start (va, text); + fprintf (stderr, "error: "); + vfprintf (stderr, text, va); + va_end (va); exit (1); } // ============================================================================ // Mutates given filename to an object filename -char* ObjectFileName (str s) { +string ObjectFileName (string s) { // Locate the extension and chop it out - unsigned int extdot = s.last ("."); - if (extdot >= s.len()-4) + int extdot = s.last ("."); + + if (extdot >= s.len() - 4) s -= (s.len() - extdot); s += ".o"; - return s.chars(); + return s; } // ============================================================================ // Is the given argument a reserved keyword? -bool IsKeyword (str s) { +bool IsKeyword (string s) { for (unsigned int u = 0; u < NumKeywords (); u++) - if (!s.icompare (g_Keywords[u])) + if (s.to_uppercase() == g_Keywords[u].to_uppercase()) return true; return false; } @@ -248,8 +251,8 @@ } // ============================================================================ -type_e GetTypeByName (str t) { - t = t.tolower(); +type_e GetTypeByName (string t) { + t = t.to_lowercase(); return (t == "int") ? TYPE_INT : (t == "str") ? TYPE_STRING : (t == "void") ? TYPE_VOID : @@ -260,7 +263,7 @@ // ============================================================================ // Inverse operation - type name by value -str GetTypeName (type_e type) { +string GetTypeName (type_e type) { switch (type) { case TYPE_INT: return "int"; break; case TYPE_STRING: return "str"; break;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main.h Fri Jan 10 21:58:42 2014 +0200 @@ -0,0 +1,133 @@ +#ifndef BOTC_COMMON_H +#define BOTC_COMMON_H + +#if !defined (__cplusplus) || __cplusplus < 201103L +# error botc requires a C++11-compliant compiler to be built +#endif + +#include <cstdio> +#include <cstdarg> +#include <cstdint> +#include "types.h" +#include "bots.h" +#include "str.h" +#include "containers.h" +#include "format.h" + +// Application name and version +#define APPNAME "botc" +#define VERSION_MAJOR 0 +#define VERSION_MINOR 999 + +// On Windows, files are case-insensitive +#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__) + #define FILE_CASEINSENSITIVE +#endif + +// Parser mode: where is the parser at? +enum parsermode_e { + MODE_TOPLEVEL, // at top level + MODE_EVENT, // inside event definition + MODE_MAINLOOP, // inside mainloop + MODE_ONENTER, // inside onenter + MODE_ONEXIT, // inside onexit +}; + +enum type_e { + TYPE_UNKNOWN = 0, + TYPE_VOID, + TYPE_INT, + TYPE_STRING, + TYPE_BOOL, +}; + +#define elif else if + +#define CHECK_FILE(pointer,path,action) \ + if (!pointer) { \ + error ("couldn't open %s for %s!\n", path.chars(), action); \ + exit (1); \ + } + +// Plural expression +#define PLURAL(n) (n != 1) ? "s" : "" + +// Shortcut for zeroing something +#define ZERO(obj) memset (&obj, 0, sizeof (obj)); + +void error (const char* text, ...); +string ObjectFileName (string s); +bool fexists (string path); +type_e GetTypeByName (string token); +string GetTypeName (type_e type); + +// Make the parser's variables globally available +extern int g_NumStates; +extern int g_NumEvents; +extern parsermode_e g_CurMode; +extern string g_CurState; + +#define neurosphere if (g_Neurosphere) +#define twice for (int repeat_token = 0; repeat_token < 2; repeat_token++) + +#ifndef __GNUC__ +#define __attribute__(X) +#endif +#define deprecated __attribute__ ((deprecated)) + +// Power function +template<class T> T pow (T a, unsigned int b) { + if (!b) + return 1; + + T r = a; + while (b > 1) { + b--; + r = r * a; + } + + return r; +} + +// Byte datatype +typedef int32_t word; +typedef unsigned char byte; + +// Keywords +extern const char** g_Keywords; + +bool IsKeyword (string s); +unsigned int NumKeywords (); + +// Script mark and reference +struct ScriptMark { + string name; + size_t pos; +}; + +struct ScriptMarkReference { + unsigned int num; + size_t pos; +}; + +// ==================================================================== +// Generic union +template <class T> union union_t { + T val; + byte b[sizeof (T)]; + char c[sizeof (T)]; + double d; + float f; + int i; + word w; +}; + +// ==================================================================== +// Finds a byte in the given value. +template <class T> inline unsigned char GetByteIndex (T a, unsigned int b) { + union_t<T> uni; + uni.val = a; + return uni.b[b]; +} + +#endif // BOTC_COMMON_H
--- a/src/objwriter.cxx Fri Jan 10 16:11:49 2014 +0200 +++ b/src/objwriter.cxx Fri Jan 10 21:58:42 2014 +0200 @@ -1,48 +1,7 @@ -/* - * botc source code - * Copyright (C) 2012 Santeri `Dusk` Piippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of the developer nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * 4. Redistributions in any form must be accompanied by information on how to - * obtain complete source code for the software and any accompanying - * software that uses the software. The source code must either be included - * in the distribution or be available for no more than the cost of - * distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#define __OBJWRITER_CXX__ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "common.h" +#include "main.h" #include "str.h" #include "objwriter.h" #include "databuffer.h" @@ -52,11 +11,11 @@ extern bool g_GotMainLoop; -ObjWriter::ObjWriter (str path) { +ObjWriter::ObjWriter (string path) { MainBuffer = new DataBuffer; MainLoopBuffer = new DataBuffer; OnEnterBuffer = new DataBuffer; - SwitchBuffer = NULL; // created on demand + SwitchBuffer = null; // created on demand numWrittenBytes = 0; numWrittenReferences = 0; filepath = path; @@ -72,7 +31,7 @@ WriteString (const_cast<char*> (s)); } -void ObjWriter::WriteString (str s) { +void ObjWriter::WriteString (string s) { WriteString (s.chars()); } @@ -102,7 +61,7 @@ // Write string table void ObjWriter::WriteStringTable () { - unsigned int stringcount = CountStringTable (); + unsigned int stringcount = num_strings_in_table (); if (!stringcount) return; @@ -112,7 +71,7 @@ // Write all strings for (unsigned int a = 0; a < stringcount; a++) - WriteString (g_StringTable[a]); + WriteString (get_string_table()[a]); } // Write main buffer to file @@ -155,10 +114,10 @@ MainBuffer; } -ScriptMark* g_ScriptMark = NULL; +ScriptMark* g_ScriptMark = null; // Adds a mark -unsigned int ObjWriter::AddMark (str name) { +unsigned int ObjWriter::AddMark (string name) { return GetCurrentBuffer()->AddMark (name); } @@ -169,10 +128,10 @@ } // Finds a mark -unsigned int ObjWriter::FindMark (str name) { +unsigned int ObjWriter::FindMark (string name) { DataBuffer* b = GetCurrentBuffer(); for (unsigned int u = 0; u < MAX_MARKS; u++) { - if (b->marks[u] && !b->marks[u]->name.icompare (name)) + if (b->marks[u] && b->marks[u]->name.to_uppercase() == name.to_uppercase()) return u; } return MAX_MARKS;
--- a/src/objwriter.h Fri Jan 10 16:11:49 2014 +0200 +++ b/src/objwriter.h Fri Jan 10 21:58:42 2014 +0200 @@ -1,50 +1,10 @@ -/* - * botc source code - * Copyright (C) 2012 Santeri `Dusk` Piippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of the developer nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * 4. Redistributions in any form must be accompanied by information on how to - * obtain complete source code for the software and any accompanying - * software that uses the software. The source code must either be included - * in the distribution or be available for no more than the cost of - * distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __OBJWRITER_H__ -#define __OBJWRITER_H__ +#ifndef BOTC_OBJWRITER_H +#define BOTC_OBJWRITER_H #include <stdio.h> #include <typeinfo> #include <string.h> -#include "common.h" +#include "main.h" #include "str.h" #include "databuffer.h" @@ -57,7 +17,7 @@ FILE* fp; // Path to the file we're writing to - str filepath; + string filepath; // The main buffer - the contents of this is what we // write to file after parsing is complete @@ -83,33 +43,34 @@ // ==================================================================== // METHODS - ObjWriter (str path); + ObjWriter (string path); void WriteString (char* s); void WriteString (const char* s); - void WriteString (str s); + void WriteString (string s); void WriteBuffer (DataBuffer* buf); void WriteBuffers (); void WriteStringTable (); void WriteToFile (); DataBuffer* GetCurrentBuffer (); - unsigned int AddMark (str name); - unsigned int FindMark (str name); + unsigned int AddMark (string name); + unsigned int FindMark (string name); unsigned int AddReference (unsigned int mark); void MoveMark (unsigned int mark); void OffsetMark (unsigned int mark, int offset); void DeleteMark (unsigned int mark); - template <class T> void DoWrite (const char* func, T stuff) { - GetCurrentBuffer ()->DoWrite (func, stuff); + + template <class T> void Write (T stuff) { + GetCurrentBuffer ()->Write (stuff); } // Default to word - void DoWrite (const char* func, word stuff) { - DoWrite<word> (func, stuff); + void Write (word stuff) { + Write<word> (stuff); } - void DoWrite (const char* func, byte stuff) { - DoWrite<byte> (func, stuff); + void DoWrite (byte stuff) { + Write<byte> (stuff); } private: @@ -125,4 +86,4 @@ } }; -#endif // __OBJWRITER_H__ \ No newline at end of file +#endif // BOTC_OBJWRITER_H \ No newline at end of file
--- a/src/parser.cxx Fri Jan 10 16:11:49 2014 +0200 +++ b/src/parser.cxx Fri Jan 10 21:58:42 2014 +0200 @@ -1,56 +1,10 @@ -/* - * botc source code - * Copyright (C) 2012 Santeri `Dusk` Piippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of the developer nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * 4. Redistributions in any form must be accompanied by information on how to - * obtain complete source code for the software and any accompanying - * software that uses the software. The source code must either be included - * in the distribution or be available for no more than the cost of - * distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#define __PARSER_CXX__ - -#include <stdio.h> -#include <stdlib.h> -#include "common.h" -#include "str.h" #include "objwriter.h" #include "scriptreader.h" #include "events.h" #include "commands.h" #include "stringtable.h" #include "variables.h" -#include "array.h" +#include "containers.h" #define MUST_TOPLEVEL if (g_CurMode != MODE_TOPLEVEL) \ ParserError ("%s-statements may only be defined at top level!", token.chars()); @@ -63,15 +17,15 @@ int g_NumStates = 0; int g_NumEvents = 0; parsermode_e g_CurMode = MODE_TOPLEVEL; -str g_CurState = ""; +string g_CurState = ""; bool g_stateSpawnDefined = false; bool g_GotMainLoop = false; unsigned int g_ScopeCursor = 0; -DataBuffer* g_IfExpression = NULL; +DataBuffer* g_IfExpression = null; bool g_CanElse = false; -str* g_UndefinedLabels[MAX_MARKS]; +string* g_UndefinedLabels[MAX_MARKS]; bool g_Neurosphere = false; // neurosphere-compat -array<constinfo_t> g_ConstInfo; +list<constinfo_t> g_ConstInfo; // ============================================================================ // Main parser code. Begins read of the script file, checks the syntax of it @@ -83,7 +37,7 @@ ZERO(scopestack[i]); for (int i = 0; i < MAX_MARKS; i++) - g_UndefinedLabels[i] = NULL; + g_UndefinedLabels[i] = null; while (Next()) { // Check if else is potentically valid @@ -101,7 +55,7 @@ // State name must be a word. if (token.first (" ") != token.len()) ParserError ("state name must be a single word, got `%s`", token.chars()); - str statename = token; + string statename = token; // stateSpawn is special - it *must* be defined. If we // encountered it, then mark down that we have it. @@ -185,10 +139,10 @@ MustNext (); // Var name must not be a number - if (token.isnumber()) + if (token.is_numeric()) ParserError ("variable name must not be a number"); - str varname = token; + string varname = token; ScriptVar* var = DeclareGlobalVariable (this, type, varname); if (!var) @@ -213,7 +167,7 @@ // If not set, define it if (m == MAX_MARKS) { m = w->AddMark (token); - g_UndefinedLabels[m] = new str (token); + g_UndefinedLabels[m] = new string (token); } // Add a reference to the mark. @@ -403,7 +357,7 @@ MustNext ("{"); SCOPE(0).type = SCOPETYPE_SWITCH; SCOPE(0).mark1 = w->AddMark (""); // end mark - SCOPE(0).buffer1 = NULL; // default header + SCOPE(0).buffer1 = null; // default header continue; } @@ -428,12 +382,12 @@ // AddSwitchCase will add the reference to the mark // for the case block that this heralds, and takes care // of buffering setup and stuff like that. - // NULL the switch buffer for the case-go-to statement, + // null the switch buffer for the case-go-to statement, // we want it all under the switch, not into the case-buffers. - w->SwitchBuffer = NULL; + w->SwitchBuffer = null; w->Write (DH_CASEGOTO); w->Write (num); - AddSwitchCase (w, NULL); + AddSwitchCase (w, null); SCOPE(0).casenumbers[SCOPE(0).casecursor] = num; continue; } @@ -542,7 +496,7 @@ // No longer undefinde delete g_UndefinedLabels[i]; - g_UndefinedLabels[i] = NULL; + g_UndefinedLabels[i] = null; } } @@ -563,7 +517,7 @@ info.type = GetTypeByName (token); if (info.type == TYPE_UNKNOWN || info.type == TYPE_VOID) - ParserError ("unknown type `%s` for constant", (char*)token); + ParserError ("unknown type `%s` for constant", token.c_str()); MustNext (); info.name = token; @@ -642,7 +596,7 @@ if (SCOPE(1).casecursor != -1) w->SwitchBuffer = SCOPE(1).casebuffers[SCOPE(1).casecursor]; else - w->SwitchBuffer = NULL; + w->SwitchBuffer = null; // If there was a default in the switch, write its header down now. // If not, write instruction to jump to the end of switch after @@ -901,7 +855,7 @@ } else { // Write to buffer retbuf->Merge (rb); - retbuf->Write (DataHeaderByOperator (NULL, oper)); + retbuf->Write (DataHeaderByOperator (null, oper)); } } @@ -910,9 +864,9 @@ // ============================================================================ // Parses an operator string. Returns the operator number code. -#define ISNEXT(char) (!PeekNext (peek ? 1 : 0) == char) +#define ISNEXT(C) (PeekNext (peek ? 1 : 0) == C) int ScriptReader::ParseOperator (bool peek) { - str oper; + string oper; if (peek) oper += PeekNext (); else @@ -981,9 +935,9 @@ } // ============================================================================ -str ScriptReader::ParseFloat () { +string ScriptReader::ParseFloat () { MustNumber (true); - str floatstring = token; + string floatstring = token; // Go after the decimal point if (PeekNext () == ".") { @@ -1021,7 +975,7 @@ ParserError ("strlen only works with const str"); if (reqtype != TYPE_INT) - ParserError ("strlen returns int but %s is expected\n", (char*)GetTypeName (reqtype)); + ParserError ("strlen returns int but %s is expected\n", GetTypeName (reqtype).c_str()); b->Write (DH_PUSHNUMBER); b->Write (constant->val.len ()); @@ -1044,8 +998,8 @@ // Type check if (reqtype != constant->type) ParserError ("constant `%s` is %s, expression requires %s\n", - (char*)constant->name, (char*)GetTypeName (constant->type), - (char*)GetTypeName (reqtype)); + constant->name.c_str(), GetTypeName (constant->type).c_str(), + GetTypeName (reqtype).c_str()); switch (constant->type) { case TYPE_BOOL: @@ -1152,11 +1106,11 @@ info->type = SCOPETYPE_UNKNOWN; info->mark1 = 0; info->mark2 = 0; - info->buffer1 = NULL; + info->buffer1 = null; info->casecursor = -1; for (int i = 0; i < MAX_CASE; i++) { info->casemarks[i] = MAX_MARKS; - info->casebuffers[i] = NULL; + info->casebuffers[i] = null; info->casenumbers[i] = -1; } } @@ -1169,7 +1123,7 @@ if (ScriptVar* var = FindGlobalVariable (token)) return ParseAssignment (var); - return NULL; + return null; } void ScriptReader::AddSwitchCase (ObjWriter* w, DataBuffer* b) { @@ -1195,9 +1149,9 @@ info->casebuffers[info->casecursor] = w->SwitchBuffer = new DataBuffer; } -constinfo_t* FindConstant (str token) { +constinfo_t* FindConstant (string token) { for (uint i = 0; i < g_ConstInfo.size(); i++) if (g_ConstInfo[i].name == token) return &g_ConstInfo[i]; - return NULL; + return null; } \ No newline at end of file
--- a/src/preprocessor.cxx Fri Jan 10 16:11:49 2014 +0200 +++ b/src/preprocessor.cxx Fri Jan 10 21:58:42 2014 +0200 @@ -1,48 +1,6 @@ -/* - * botc source code - * Copyright (C) 2012 Santeri `Dusk` Piippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of the developer nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * 4. Redistributions in any form must be accompanied by information on how to - * obtain complete source code for the software and any accompanying - * software that uses the software. The source code must either be included - * in the distribution or be available for no more than the cost of - * distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#define __PARSER_CXX__ - #include <stdio.h> #include <stdlib.h> -#include "common.h" +#include "main.h" #include "str.h" #include "scriptreader.h" @@ -66,11 +24,11 @@ // ============================================================================ // Reads a word until whitespace -str ScriptReader::PPReadWord (char &term) { - str word; +string ScriptReader::PPReadWord (char &term) { + string word; while (1) { char c = PPReadChar(); - if (feof (fp[fc]) || (IsCharWhitespace (c) && word.len ())) { + if (feof (fp[fc]) || (isspace (c) && word.len ())) { term = c; break; } @@ -101,13 +59,13 @@ // Read characters until next whitespace to // build the name of the directive - str directive = PPReadWord (trash); + string directive = PPReadWord (trash); // Now check the directive name against known names if (directive == "include") { // #include-directive char terminator; - str file = PPReadWord (terminator); + string file = PPReadWord (terminator); if (!file.len()) ParserError ("expected file name for #include, got nothing instead");
--- a/src/scriptreader.cxx Fri Jan 10 16:11:49 2014 +0200 +++ b/src/scriptreader.cxx Fri Jan 10 21:58:42 2014 +0200 @@ -1,69 +1,25 @@ -/* - * botc source code - * Copyright (C) 2012 Santeri `Dusk` Piippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of the developer nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * 4. Redistributions in any form must be accompanied by information on how to - * obtain complete source code for the software and any accompanying - * software that uses the software. The source code must either be included - * in the distribution or be available for no more than the cost of - * distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stdio.h> -#include <stdlib.h> -#include "string.h" -#include "str.h" -#include "common.h" +#include "main.h" #include "scriptreader.h" #define STORE_POSITION \ - bool _atnewline = atnewline; \ - unsigned int _curline = curline[fc]; \ - unsigned int _curchar = curchar[fc]; + bool stored_atnewline = atnewline; \ + unsigned int stored_curline = curline[fc]; \ + unsigned int stored_curchar = curchar[fc]; #define RESTORE_POSITION \ - atnewline = _atnewline; \ - curline[fc] = _curline; \ - curchar[fc] = _curchar; + atnewline = stored_atnewline; \ + curline[fc] = stored_curline; \ + curchar[fc] = stored_curchar; // ============================================================================ -ScriptReader::ScriptReader (str path) { +ScriptReader::ScriptReader (string path) { token = ""; prevtoken = ""; prevpos = 0; fc = -1; for (unsigned int u = 0; u < MAX_FILESTACK; u++) - fp[u] = NULL; + fp[u] = null; OpenFile (path); commentmode = 0; @@ -87,7 +43,7 @@ // ============================================================================ // Opens a file and pushes its pointer to stack -void ScriptReader::OpenFile (str path) { +void ScriptReader::OpenFile (string path) { if (fc+1 >= MAX_FILESTACK) ParserError ("supposed to open file `%s` but file stack is full! do you have recursive `#include` directives?", path.chars()); @@ -123,7 +79,7 @@ return; fclose (fp[u]); - fp[u] = NULL; + fp[u] = null; fc--; if (fc != -1) @@ -186,7 +142,7 @@ // Read a token from the file buffer. Returns true if token was found, false if not. bool ScriptReader::Next (bool peek) { prevpos = ftell (fp[fc]); - str tmp = ""; + string tmp = ""; while (1) { // Check end-of-file @@ -251,7 +207,7 @@ break; } - if (IsCharWhitespace (c)) { + if (isspace (c)) { // Don't break if we haven't gathered anything yet. if (tmp.len()) break; @@ -275,9 +231,9 @@ // ============================================================================ // Returns the next token without advancing the cursor. -str ScriptReader::PeekNext (int offset) { +string ScriptReader::PeekNext (int offset) { // Store current information - str storedtoken = token; + string storedtoken = token; int cpos = ftell (fp[fc]); STORE_POSITION @@ -288,7 +244,7 @@ offset--; } - str tmp = token; + string tmp = token; // Restore position fseek (fp[fc], cpos, SEEK_SET); @@ -337,24 +293,32 @@ // ============================================================================ void ScriptReader::ParserError (const char* message, ...) { - PERFORM_FORMAT (message, outmessage); - ParserMessage ("\nError: ", outmessage); + char buf[512]; + va_list va; + va_start (va, message); + sprintf (buf, message, va); + va_end (va); + ParserMessage ("\nError: ", buf); exit (1); } // ============================================================================ void ScriptReader::ParserWarning (const char* message, ...) { - PERFORM_FORMAT (message, outmessage); - ParserMessage ("Warning: ", outmessage); + char buf[512]; + va_list va; + va_start (va, message); + sprintf (buf, message, va); + va_end (va); + ParserMessage ("Warning: ", buf); } // ============================================================================ -void ScriptReader::ParserMessage (const char* header, char* message) { +void ScriptReader::ParserMessage (const char* header, string message) { if (fc >= 0 && fc < MAX_FILESTACK) fprintf (stderr, "%s%s:%u:%u: %s\n", - header, filepath[fc], curline[fc], curchar[fc], message); + header, filepath[fc].c_str(), curline[fc], curchar[fc], message.c_str()); else - fprintf (stderr, "%s%s\n", header, message); + fprintf (stderr, "%s%s\n", header, message.c_str()); } // ============================================================================ @@ -365,7 +329,7 @@ else MustNext ("\""); - str string; + string string; // Keep reading characters until we find a terminating quote. while (1) { // can't end here! @@ -387,26 +351,24 @@ if (!fromthis) MustNext (); - str num = token; + string num = token; if (num == "-") { MustNext (); num += token; } // "true" and "false" are valid numbers - if (!token.icompare ("true")) + if (-token == "true") token = "1"; - else if (!token.icompare ("false")) + else if (-token == "false") token = "0"; else { - if (!token.isnumber()) - ParserError ("expected a number, got `%s`", num.chars()); - - str check; - check.appendformat ("%d", atoi (num)); - if (token != check) - ParserWarning ("integer too large: %s -> %s", num.chars(), check.chars()); - + bool ok; + int num = token.to_long (&ok); + + if (!ok) + ParserError ("expected a number, got `%s`", token.chars()); + token = num; } } \ No newline at end of file
--- a/src/scriptreader.h Fri Jan 10 16:11:49 2014 +0200 +++ b/src/scriptreader.h Fri Jan 10 21:58:42 2014 +0200 @@ -1,48 +1,8 @@ -/* - * botc source code - * Copyright (C) 2012 Santeri `Dusk` Piippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of the developer nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * 4. Redistributions in any form must be accompanied by information on how to - * obtain complete source code for the software and any accompanying - * software that uses the software. The source code must either be included - * in the distribution or be available for no more than the cost of - * distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __SCRIPTREADER_H__ -#define __SCRIPTREADER_H__ +#ifndef BOTC_SCRIPTREADER_H +#define BOTC_SCRIPTREADER_H #include <stdio.h> -#include "str.h" +#include "main.h" #include "commands.h" #include "objwriter.h" @@ -129,9 +89,9 @@ // ============================================================================ typedef struct { - str name; + string name; type_e type; - str val; + string val; } constinfo_t; // ============================================================================ @@ -142,7 +102,7 @@ // ==================================================================== // MEMBERS FILE* fp[MAX_FILESTACK]; - char* filepath[MAX_FILESTACK]; + string filepath[MAX_FILESTACK]; int fc; unsigned int pos[MAX_FILESTACK]; @@ -150,23 +110,23 @@ unsigned int curchar[MAX_FILESTACK]; ScopeInfo scopestack[MAX_SCOPE]; long savedpos[MAX_FILESTACK]; // filepointer cursor position - str token; + string token; int commentmode; long prevpos; - str prevtoken; + string prevtoken; // ==================================================================== // METHODS // scriptreader.cxx: - ScriptReader (str path); + ScriptReader (string path); ~ScriptReader (); - void OpenFile (str path); + void OpenFile (string path); void CloseFile (unsigned int u = MAX_FILESTACK); char ReadChar (); char PeekChar (int offset = 0); bool Next (bool peek = false); void Prev (); - str PeekNext (int offset = 0); + string PeekNext (int offset = 0); void Seek (unsigned int n, int origin); void MustNext (const char* c = ""); void MustThis (const char* c); @@ -185,7 +145,7 @@ DataBuffer* ParseAssignment (ScriptVar* var); int ParseOperator (bool peek = false); DataBuffer* ParseExprValue (type_e reqtype); - str ParseFloat (); + string ParseFloat (); void PushScope (); // preprocessor.cxx: @@ -197,15 +157,15 @@ private: bool atnewline; char c; - void ParserMessage (const char* header, char* message); + void ParserMessage (const char* header, string message); bool DoDirectivePreprocessing (); char PPReadChar (); void PPMustChar (char c); - str PPReadWord (char &term); + string PPReadWord (char &term); }; -constinfo_t* FindConstant (str token); +constinfo_t* FindConstant (string token); extern bool g_Neurosphere; -#endif // __SCRIPTREADER_H__ \ No newline at end of file +#endif // BOTC_SCRIPTREADER_H \ No newline at end of file
--- a/src/str.cxx Fri Jan 10 16:11:49 2014 +0200 +++ b/src/str.cxx Fri Jan 10 21:58:42 2014 +0200 @@ -1,426 +1,434 @@ -/* - * botc source code - * Copyright (C) 2012 Santeri `Dusk` Piippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of the developer nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * 4. Redistributions in any form must be accompanied by information on how to - * obtain complete source code for the software and any accompanying - * software that uses the software. The source code must either be included - * in the distribution or be available for no more than the cost of - * distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ +#include <cstring> +#include "main.h" +#include "str.h" + +// ============================================================================= +// +int string::compare (const string& other) const +{ + return m_string.compare (other.std_string()); +} -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include "array.h" -#include "str.h" -#include "common.h" - -#define ITERATE_STRING(u) \ - for (unsigned int u = 0; u < strlen (text); u++) +// ============================================================================= +// +void string::trim (string::length_type n) +{ + if (n > 0) + m_string = substring (0, length() - n).std_string(); + else + m_string = substring (n, -1).std_string(); +} -// ============================================================================ -// vdynformat: Try to write to a formatted string with size bytes first, if -// that fails, double the size and keep recursing until it works. -char* vdynformat (const char* c, va_list v, unsigned int size) { - char* buffer = new char[size]; - int r = vsnprintf (buffer, size-1, c, v); - if (r > (int)size-1 || r < 0) { - delete buffer; - buffer = vdynformat (c, v, size*2); - } - return buffer; +// ============================================================================= +// +string string::strip (list<char> unwanted) +{ + string copy (m_string); + + for (char c : unwanted) + for (int i = 0; i < copy.length(); ++i) + if (copy[i] == c) + copy.erase (i); + + /* + while(( pos = copy.first( c )) != -1 ) + copy.erase( pos ); + */ + + return copy; } -// ============================================================================ -str::str () { - text = new char[1]; - clear(); - alloclen = strlen (text); +// ============================================================================= +// +string string::to_uppercase() const +{ + string newstr = m_string; + + for (char& c : newstr) + if (c >= 'a' && c <= 'z') + c -= 'a' - 'A'; + + return newstr; } -str::str (const char* c) { - text = new char[1]; - clear (); - alloclen = strlen (text); - append (c); +// ============================================================================= +// +string string::to_lowercase() const +{ + string newstr = m_string; + + for (char & c : newstr) + if (c >= 'A' && c <= 'Z') + c += 'a' - 'A'; + + return newstr; } -str::str (char c) { - text = new char[1]; - clear (); - alloclen = strlen (text); - append (c); +// ============================================================================= +// +string_list string::split (char del) const +{ + string delimstr; + delimstr += del; + return split (delimstr); } -// ============================================================================ -void str::clear () { - delete text; - text = new char[1]; - text[0] = '\0'; - curs = 0; +// ============================================================================= +// +string_list string::split (string del) const +{ + string_list res; + long a = 0; + + // Find all separators and store the text left to them. + for (;;) + { + long b = first (del, a); + + if (b == -1) + break; + + string sub = substring (a, b); + + if (sub.length() > 0) + res.push_back (substring (a, b)); + + a = b + strlen (del); + } + + // Add the string at the right of the last separator + if (a < (int) length()) + res.push_back (substring (a, length())); + + return res; } -unsigned int str::len () {return strlen(text);} +// ============================================================================= +// +void string::replace (const char* a, const char* b) +{ + long pos; + + while ( (pos = first (a)) != -1) + m_string = m_string.replace (pos, strlen (a), b); +} -// ============================================================================ -void str::resize (unsigned int len) { - unsigned int oldlen = strlen (text); - char* oldtext = new char[oldlen]; - strncpy (oldtext, text, oldlen); - - delete text; - text = new char[len+1]; - for (unsigned int u = 0; u < len+1; u++) - text[u] = 0; - strncpy (text, oldtext, len); - - alloclen = len; +// ============================================================================= +// +int string::count (const char needle) const +{ + int numNeedles = 0; + + for (const char & c : m_string) + if (c == needle) + numNeedles++; + + return numNeedles; } -// ============================================================================ -void str::dump () { - for (unsigned int u = 0; u <= alloclen; u++) - printf ("\t%u. %u (%c)\n", u, text[u], text[u]); -} +// ============================================================================= +// +string string::substring (long a, long b) const +{ + if (b == -1) + b = length(); + + if (b == a) + return ""; -// ============================================================================ -// Adds a new character at the end of the string. -void str::append (char c) { - // Out of space, thus resize - if (curs == alloclen) - resize (alloclen+1); - text[curs] = c; - curs++; -} + if (b < a) + { + // Swap the variables + int c = a; + a = b; + b = c; + } -void str::append (const char* c) { - resize (alloclen + strlen (c)); - - for (unsigned int u = 0; u < strlen (c); u++) { - if (c[u] != 0) - append (c[u]); - } -} + char* newString = new char[b - a + 1]; + strncpy (newString, m_string.c_str() + a, b - a); + newString[b - a] = '\0'; -void str::append (str c) { - append (c.chars()); + string other (newString); + delete[] newString; + return other; } -// ============================================================================ -void str::appendformat (const char* c, ...) { - va_list v; - - va_start (v, c); - char* buf = vdynformat (c, v, 256); - va_end (v); - - append (buf); -} +// ============================================================================= +// +string::length_type string::posof (int n) const +{ + int count = 0; -void str::appendformat (str c, ...) { - va_list v; - - va_start (v, c); - char* buf = vdynformat (c.chars(), v, 256); - va_end (v); - - append (buf); -} + for (int i = 0; i < length(); ++i) + { + if (m_string[i] != ' ') + continue; -// ============================================================================ -char* str::chars () { - return text; + if (++count < n) + continue; + + return i; + } + + return -1; } -// ============================================================================ -unsigned int str::first (const char* c, unsigned int a) { - unsigned int r = 0; - unsigned int index = 0; - for (; a < alloclen; a++) { - if (text[a] == c[r]) { - if (r == 0) - index = a; - - r++; - if (r == strlen (c)) - return index; - } else { - if (r != 0) { - // If the string sequence broke at this point, we need to - // check this character again, for a new sequence just - // might start right here. - a--; - } - - r = 0; - } - } - - return len (); +// ============================================================================= +// +int string::first (const char* c, string::length_type a) const +{ + for (; a < length(); a++) + if (m_string[a] == c[0] && strncmp (m_string.c_str() + a, c, strlen (c)) == 0) + return a; + + return -1; +} + +// ============================================================================= +// +int string::last (const char* c, string::length_type a) const +{ + if (a == -1 || a >= length()) + a = length() - 1; + + for (; a > 0; a--) + if (m_string[a] == c[0] && strncmp (m_string.c_str() + a, c, strlen (c)) == 0) + return a; + + return -1; +} + +// ============================================================================= +// +void string::dump() const +{ + print ("`%1`:\n", chars()); + int i = 0; + + for (char u : m_string) + print ("\t%1. [%d2] `%3`\n", i++, u, string (u)); } -// ============================================================================ -unsigned int str::last (const char* c, int a) { - if (a == -1) - a = len(); - - int max = strlen (c)-1; - - int r = max; - for (; a >= 0; a--) { - if (text[a] == c[r]) { - r--; - if (r == -1) - return a; - } else { - if (r != max) - a++; - - r = max; - } - } - - return len (); +// ============================================================================= +// +long string::to_long (bool* ok, int base) const +{ + errno = 0; + char* endptr; + long i = strtol (m_string.c_str(), &endptr, base); + *ok = (errno == 0 && *endptr == '\0'); + return i; +} + +// ============================================================================= +// +float string::to_float (bool* ok) const +{ + errno = 0; + char* endptr; + float i = strtof (m_string.c_str(), &endptr); + *ok = (errno == 0 && *endptr == '\0'); + return i; } -// ============================================================================ -str str::substr (unsigned int a, unsigned int b) { - if (a > len()) a = len(); - if (b > len()) b = len(); - - if (b == a) - return ""; - - if (b < a) { - printf ("str::substr: indices %u and %u given, should be the other way around, swapping..\n", a, b); - - // Swap the variables - unsigned int c = a; - a = b; - b = c; - } - - char* s = new char[b-a]; - strncpy (s, text+a, b-a); - return str(s); +// ============================================================================= +// +double string::to_double (bool* ok) const +{ + errno = 0; + char* endptr; + double i = strtod (m_string.c_str(), &endptr); + *ok = (errno == 0 && *endptr == '\0'); + return i; +} + +// ============================================================================= +// +bool operator== (const char* a, const string& b) +{ + return b == a; +} + +// ============================================================================= +// +string operator+ (const char* a, const string& b) +{ + return string (a) + b; } -// ============================================================================ -void str::remove (unsigned int idx, unsigned int dellen) { - str s1 = substr (0, idx); - str s2 = substr (idx + dellen, len()); - - clear(); - - append (s1); - append (s2); +// ============================================================================= +// +string string::operator+ (const string data) const +{ + string newString = *this; + newString += data; + return newString; } -// ============================================================================ -void str::trim (int dellen) { - if (!dellen) - return; - - unsigned int delpos; - if (dellen > 0) { - delpos = len()-dellen; - text[delpos] = 0; - curs -= dellen; - } else { - str s = substr (-dellen, len()); - clear(); - append (s); - } +// ============================================================================= +// +string string::operator+ (const char* data) const +{ + string newString = *this; + newString += data; + return newString; +} + +// ============================================================================= +// +string& string::operator+= (const string data) +{ + append (data); + return *this; } -// ============================================================================ -void str::replace (const char* o, const char* n, unsigned int a) { - unsigned int idx; - - while ((idx = first (o, a)) != len()) { - str s1 = substr (0, idx); - str s2 = substr (idx + strlen (o), len()); - - clear(); - - append (s1); - append (n); - append (s2); - } +// ============================================================================= +// +string& string::operator+= (const char* data) +{ + append (data); + return *this; } -void str::insert (char* c, unsigned int pos) { - str s1 = substr (0, pos); - str s2 = substr (pos, len()); - - clear(); - append (s1); - append (c); - append (s2); -} +// ============================================================================= +// +bool string::is_numeric() const +{ + bool gotDot = false; + + for (const char & c : m_string) + { + // Allow leading hyphen for negatives + if (&c == &m_string[0] && c == '-') + continue; -void str::reverse () { - char* tmp = new char[alloclen]; - strcpy (tmp, text); - - clear(); - curs = 0; - resize (alloclen); - for (int i = alloclen-1; i >= 0; i--) - append (tmp[i]); + // Check for decimal point + if (!gotDot && c == '.') + { + gotDot = true; + continue; + } + + if (c >= '0' && c <= '9') + continue; // Digit + + // If the above cases didn't catch this character, it was + // illegal and this is therefore not a number. + return false; + } + + return true; } -void str::repeat (unsigned int n) { - char* tmp = new char[alloclen]; - strcpy (tmp, text); - - for (; n > 0; n--) - append (tmp); +// ============================================================================= +// +bool string::ends_with (const string& other) +{ + if (length() < other.length()) + return false; + + const int ofs = length() - other.length(); + return strncmp (chars() + ofs, other.chars(), other.length()) == 0; } -// ============================================================================ -bool str::isnumber () { - ITERATE_STRING (u) { - // Minus sign as the first character is allowed for negatives - if (!u && text[u] == '-') - continue; - - if (text[u] < '0' || text[u] > '9') - return false; - } - return true; +// ============================================================================= +// +bool string::starts_with (const string& other) +{ + if (length() < other.length()) + return false; + + return strncmp (chars(), other.chars(), other.length()) == 0; } -// ============================================================================ -bool str::isword () { - ITERATE_STRING (u) { - // lowercase letters - if (text[u] >= 'a' || text[u] <= 'z') - continue; - - // uppercase letters - if (text[u] >= 'A' || text[u] <= 'Z') - continue; - - return false; - } - return true; +// ============================================================================= +// +void string::sprintf (const char* fmtstr, ...) +{ + char* buf; + int bufsize = 256; + va_list va; + va_start (va, fmtstr); + + do + buf = new char[bufsize]; + + while (vsnprintf (buf, bufsize, fmtstr, va) >= bufsize); + + va_end (va); + m_string = buf; + delete[] buf; } -// ============================================================================ -int str::compare (const char* c) { - return strcmp (text, c); -} - -int str::compare (str c) { - return compare (c.chars()); -} - -int str::icompare (const char* c) { - return icompare (str ((char*)c)); -} - -int str::icompare (str b) { - return strcmp (tolower().chars(), b.tolower().chars()); +// ============================================================================= +// +void string::prepend (string a) +{ + m_string = (a + m_string).std_string(); } -// ============================================================================ -str str::tolower () { - str n = text; - - for (uint u = 0; u < len(); u++) { - if (n[u] > 'A' && n[u] < 'Z') - n.text[u] += ('a' - 'A'); - } - - return n; -} +// ============================================================================= +// +string string_list::join (const string& delim) +{ + string result; -// ============================================================================ -str str::toupper () { - str n = text; - - for (uint u = 0; u < len(); u++) { - if (n[u] > 'a' && n[u] < 'z') - n.text[u] -= ('A' - 'a'); - } - - return n; + for (const string & it : std_deque()) + { + if (!result.is_empty()) + result += delim; + + result += it; + } + + return result; } -// ============================================================================ -unsigned int str::count (char* c) { - unsigned int r = 0; - unsigned int tmp = 0; - ITERATE_STRING (u) { - if (text[u] == c[r]) { - r++; - if (r == strlen (c)) { - r = 0; - tmp++; - } - } else { - if (r != 0) - u--; - r = 0; - } - } - - return tmp; -} +// ============================================================================= +// +bool string::mask (const string& pattern) const +{ + // Elevate to uppercase for case-insensitive matching + string pattern_upper = pattern.to_uppercase(); + string this_upper = to_uppercase(); + const char* maskstring = pattern_upper.chars(); + const char* mptr = &maskstring[0]; + + for (const char* sptr = this_upper.chars(); *sptr != '\0'; sptr++) + { + if (*mptr == '?') + { + if (* (sptr + 1) == '\0') + { + // ? demands that there's a character here and there wasn't. + // Therefore, mask matching fails + return false; + } + } -// ============================================================================ -array<str> str::split (str del) { - array<str> res; - unsigned int a = 0; - - // Find all separators and store the text left to them. - while (1) { - unsigned int b = first (del, a); - - if (b == len()) - break; - - res.push (substr (a, b)); - a = b + strlen (del); - } - - // Add the string at the right of the last separator - res.push (substr (a, len())); - return res; + elif (*mptr == '*') + { + char end = * (++mptr); + + // If '*' is the final character of the message, all of the remaining + // string matches against the '*'. We don't need to bother checking + // the string any further. + if (end == '\0') + return true; + + // Skip to the end character + while (*sptr != end && *sptr != '\0') + sptr++; + + // String ended while the mask still had stuff + if (*sptr == '\0') + return false; + } + elif (*sptr != *mptr) + return false; + + mptr++; + } + + return true; } - -array<str> str::operator/ (str splitstring) {return split(splitstring);} -array<str> str::operator/ (char* splitstring) {return split(splitstring);} -array<str> str::operator/ (const char* splitstring) {return split(splitstring);} \ No newline at end of file
--- a/src/str.h Fri Jan 10 16:11:49 2014 +0200 +++ b/src/str.h Fri Jan 10 21:58:42 2014 +0200 @@ -1,233 +1,301 @@ -/* - * botc source code - * Copyright (C) 2012 Santeri `Dusk` Piippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of the developer nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * 4. Redistributions in any form must be accompanied by information on how to - * obtain complete source code for the software and any accompanying - * software that uses the software. The source code must either be included - * in the distribution or be available for no more than the cost of - * distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ +#ifndef STRING_H +#define STRING_H + +#include <deque> +#include <string> +#include <stdarg.h> +#include "types.h" +#include "containers.h" + +class string; +class string_list; + +// ============================================================================= +// +class string +{ + public: + typedef typename ::std::string::iterator iterator; + typedef typename ::std::string::const_iterator const_iterator; + using length_type = int; + + string() {} + + string (char a) + { + m_string = &a; + } + + string (const char* data) + { + m_string = data; + } + + string (std::string data) + { + m_string = data; + } + + void dump() const; + int compare (const string& other) const; + bool ends_with (const string& other); + int count (const char needle) const; + int first (const char* c, length_type a = 0) const; + int last (const char* c, length_type a = -1) const; + string to_lowercase() const; + bool is_numeric() const; + bool mask (const string& pattern) const; + length_type posof (int n) const; + void prepend (string a); + void replace (const char* a, const char* b); + string_list split (string del) const; + string_list split (char del) const; + void sprintf (const char* fmtstr, ...); + bool starts_with (const string& other); + string strip (list< char > unwanted); + string substring (long a, long b = -1) const; + double to_double (bool* ok = null) const; + float to_float (bool* ok = null) const; + long to_long (bool* ok = null, int base = 10) const; + void trim (length_type n); + string to_uppercase() const; + + string operator+ (const string data) const; + string operator+ (const char* data) const; + string& operator+= (const string data); + string& operator+= (const char* data); -#ifndef __STR_H__ -#define __STR_H__ + inline bool is_empty() const + { + return m_string[0] == '\0'; + } + + inline void append (const char* data) + { + m_string.append (data); + } + + inline void append (const char data) + { + m_string.push_back (data); + } -template<class T> class array; + inline void append (const string& data) + { + m_string.append (data.chars()); + } + + inline iterator begin() + { + return m_string.begin(); + } + + inline const_iterator begin() const + { + return m_string.cbegin(); + } + + inline int capacity() const + { + return m_string.capacity(); + } -char* vdynformat (const char* c, va_list v, unsigned int size); + inline const char* chars() const + { + return m_string.c_str(); + } + + inline const char* c_str() const + { + return m_string.c_str(); + } + + inline iterator end() + { + return m_string.end(); + } -#define SCCF_NUMBER 1<<0 -#define SCCF_WORD 1<<1 + inline const_iterator end() const + { + return m_string.end(); + } + + inline void clear() + { + m_string.clear(); + } + + inline bool empty() const + { + return m_string.empty(); + } + + inline void erase (length_type pos) + { + m_string.erase (m_string.begin() + pos); + } -// Dynamic string object, allocates memory when needed and -// features a good bunch of manipulation methods -class str { -private: - // The actual message - char* text; - - // Where will append() place new characters? - unsigned int curs; - - // Allocated length - unsigned int alloclen; - - // Resize the text buffer to len characters - void resize (unsigned int len); -public: - // ====================================================================== - // CONSTRUCTORS - str (); - str (const char* c); - str (char c); - - // ====================================================================== - // METHODS - - // Empty the string - void clear (); - - // Length of the string - unsigned int len (); - - // The char* form of the string - char* chars (); - - // Dumps the character table of the string - void dump (); - - // Appends text to the string - void append (char c); - void append (const char* c); - void append (str c); - - // Appends formatted text to the string. - void appendformat (const char* c, ...); - void appendformat (str c, ...); - - // Returns the first occurrence of c in the string, optionally starting - // from a certain position rather than the start. - unsigned int first (const char* c, unsigned int a = 0); - - // Returns the last occurrence of c in the string, optionally starting - // from a certain position rather than the end. - unsigned int last (const char* c, int a = -1); - - // Returns a substring of the string, from a to b. - str substr (unsigned int a, unsigned int b); - - // Replace a substring with another substring. - void replace (const char* o, const char* n, unsigned int a = 0); - - // Removes a given index from the string, optionally more characters than just 1. - void remove (unsigned int idx, unsigned int dellen=1); - - void trim (int dellen); - - // Inserts a substring into a certain position. - void insert (char* c, unsigned int pos); - - // Reverses the string. - void reverse (); - - // Repeats the string a given amount of times. - void repeat (unsigned int n); - - // Is the string a number? - bool isnumber (); - - // Is the string a word, i.e consists only of alphabetic letters? - bool isword (); - - // Convert string to lower case - str tolower (); - - // Convert string to upper case - str toupper (); - - // Compare this string with another - int compare (const char* c); - int compare (str c); - int icompare (str c); - int icompare (const char* c); - - // Counts the amount of substrings in the string - unsigned int count (char* s); - - array<str> split (str del); - - // ====================================================================== - // OPERATORS - str operator+ (str& c) { - append (c); - return *this; - } - - str& operator+= (char c) { - append (c); - return *this; - } - - str& operator+= (const char* c) { - append (c); - return *this; - } - - str& operator+= (const str c) { - append (c); - return *this; - } - - str operator* (const int repcount) { - repeat (repcount); - return *this; - } - - str& operator*= (const int repcount) { - repeat (repcount); - return *this; - } - - str operator- (const int trimcount) { - trim (trimcount); - return *this; - } - - str& operator-= (const int trimcount) { - trim (trimcount); - return *this; - } - - array<str> operator/ (str splitstring); - array<str> operator/ (char* splitstring); - array<str> operator/ (const char* splitstring); - - str operator+ () { - return toupper (); - } - - str operator- () { - return tolower (); - } - - str operator! () { - reverse (); - return *this; - } - -#define DEFINE_OPERATOR_TYPE(OPER, TYPE) \ - bool operator OPER (TYPE other) {return compare(other) OPER 0;} -#define DEFINE_OPERATOR(OPER) \ - DEFINE_OPERATOR_TYPE (OPER, str) \ - DEFINE_OPERATOR_TYPE (OPER, char*) \ - DEFINE_OPERATOR_TYPE (OPER, const char*) - - DEFINE_OPERATOR (==) - DEFINE_OPERATOR (!=) - DEFINE_OPERATOR (>) - DEFINE_OPERATOR (<) - DEFINE_OPERATOR (>=) - DEFINE_OPERATOR (<=) - - char operator [] (unsigned int pos) { - return text[pos]; - } - - operator char* () const { - return text; - } - - operator int () const {return atoi(text);} - operator unsigned int () const {return atoi(text);} + inline void insert (length_type pos, char c) + { + m_string.insert (m_string.begin() + pos, c); + } + + inline length_type len() const + { + return length(); + } + + inline length_type length() const + { + return m_string.length(); + } + + inline int max_size() const + { + return m_string.max_size(); + } + + inline string mid (int a, int len) const + { + return m_string.substr (a, len); + } + + inline void remove (int pos, int len) + { + m_string.replace (pos, len, ""); + } + + inline void remove_from_start (int len) + { + remove (0, len); + } + + inline void remove_from_end (int len) + { + remove (length() - len, len); + } + + inline void resize (int n) + { + m_string.resize (n); + } + + inline void replace (int pos, int n, const string& a) + { + m_string.replace (pos, n, a.chars()); + } + + inline void shrink_to_fit() + { + m_string.shrink_to_fit(); + } + + inline const std::string& std_string() const + { + return m_string; + } + + inline string strip (char unwanted) + { + return strip ( {unwanted}); + } + + string& operator+= (const char data) + { + append (data); + return *this; + } + + string operator- (int n) const + { + string new_string = m_string; + new_string -= n; + return new_string; + } + + inline string& operator-= (int n) + { + trim (n); + return *this; + } + + inline string operator+() const + { + return to_uppercase(); + } + + inline string operator-() const + { + return to_lowercase(); + } + + inline bool operator== (const string& other) const + { + return std_string() == other.std_string(); + } + + inline bool operator== (const char* other) const + { + return operator== (string (other)); + } + + inline bool operator!= (const string& other) const + { + return std_string() != other.std_string(); + } + + inline bool operator!= (const char* other) const + { + return operator!= (string (other)); + } + + inline bool operator> (const string& other) const + { + return std_string() > other.std_string(); + } + + inline bool operator< (const string& other) const + { + return std_string() < other.std_string(); + } + + inline operator const char*() const + { + return chars(); + } + + inline operator const std::string&() const + { + return std_string(); + } + + // Difference between indices @a and @b. @b can be -1, in which + // case it will be length() - 1. + inline int index_difference (int a, int b) + { + assert (b == -1 || b >= a); + return (b != -1 ? b - a : length() - 1 - a); + } + + private: + std::string m_string; }; -#endif // __STR_H__ \ No newline at end of file +// ============================================================================= +// +class string_list : public list<string> +{ + public: + string_list() {} + string_list (std::initializer_list<string> vals) : + list<string> (vals) {} + string_list (const list<string>& a) : list<string> (a.std_deque()) {} + string_list (const list_type& a) : list<string> (a) {} + + string join (const string& delim); +}; + +bool operator== (const char* a, const string& b); +string operator+ (const char* a, const string& b); + +#endif // STRING_H
--- a/src/stringtable.cxx Fri Jan 10 16:11:49 2014 +0200 +++ b/src/stringtable.cxx Fri Jan 10 21:58:42 2014 +0200 @@ -1,104 +1,53 @@ -/* - * botc source code - * Copyright (C) 2012 Santeri `Dusk` Piippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of the developer nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * 4. Redistributions in any form must be accompanied by information on how to - * obtain complete source code for the software and any accompanying - * software that uses the software. The source code must either be included - * in the distribution or be available for no more than the cost of - * distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#define __STRINGTABLE_CXX__ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "common.h" +#include "main.h" #include "bots.h" #include "stringtable.h" +static string_list g_string_table; + // ============================================================================ -// Initializes the string table -void InitStringTable() { - // Zero out everything first. - for (unsigned int a = 0; a < MAX_LIST_STRINGS; a++) - for (unsigned int b = 0; b < MAX_STRING_LENGTH; b++) - g_StringTable[a][b] = 0; +// +const string_list& get_string_table() +{ + return g_string_table; } // ============================================================================ // Potentially adds a string to the table and returns the index of it. -unsigned int PushToStringTable (char* s) { +// +int get_string_table_index (const string& a) +{ // Must not be too long. - if (strlen (s) >= MAX_STRING_LENGTH) - error ("string `%s` too long (%d characters max)\n", s, strlen (s)); - - // Find a free slot in the table. - unsigned int a; - for (a = 0; a < MAX_LIST_STRINGS; a++) { + if (strlen (a) >= MAX_STRING_LENGTH) + error ("string `%s` too long (%d characters, max is %d)\n", + a.c_str(), a.length(), MAX_STRING_LENGTH); + + // Find a free slot in the table. + int idx; + + for (idx = 0; idx < g_string_table.size(); idx++) + { // String is already in the table, thus return it. - if (!strcmp (s, g_StringTable[a])) - return a; - - // String is empty, thus it's free. - if (!strlen (g_StringTable[a])) - break; + if (g_string_table[idx] == a) + return idx; } - - // no free slots! - if (a == MAX_LIST_STRINGS) - error ("too many strings defined!\n"); - - // Determine the length - size_t l1 = strlen (s); - size_t l2 = MAX_LIST_STRINGS - 1; - size_t len = (l1 < l2) ? l1 : l2; - + + // Check if the table is already full + if (g_string_table.size() == MAX_LIST_STRINGS - 1) + error ("too many strings!\n"); + // Now, dump the string into the slot - strncpy (g_StringTable[a], s, len); - g_StringTable[a][len] = 0; - - return a; + g_string_table[idx] = a; + + return idx; } // ============================================================================ // Counts the amount of strings in the table. -unsigned int CountStringTable () { - unsigned int count = 0; - for (unsigned int a = 0; a < MAX_LIST_STRINGS; a++) { - if (!strlen (g_StringTable[a])) - break; - else - count++; - } - return count; -} \ No newline at end of file +// +int num_strings_in_table() +{ + return g_string_table.size(); +}
--- a/src/stringtable.h Fri Jan 10 16:11:49 2014 +0200 +++ b/src/stringtable.h Fri Jan 10 21:58:42 2014 +0200 @@ -1,50 +1,11 @@ -/* - * botc source code - * Copyright (C) 2012 Santeri `Dusk` Piippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of the developer nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * 4. Redistributions in any form must be accompanied by information on how to - * obtain complete source code for the software and any accompanying - * software that uses the software. The source code must either be included - * in the distribution or be available for no more than the cost of - * distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ +#ifndef BOTC_STRINGTABLE_H +#define BOTC_STRINGTABLE_H +#include "main.h" #include "bots.h" -void InitStringTable(); -unsigned int PushToStringTable (char* s); -unsigned int CountStringTable (); +int get_string_table_index(const string& a); +const string_list& get_string_table(); +int num_strings_in_table(); -#ifndef __STRINGTABLE_CXX__ -extern -#endif -char g_StringTable[MAX_LIST_STRINGS][MAX_STRING_LENGTH]; \ No newline at end of file +#endif // BOTC_STRINGTABLE_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/types.h Fri Jan 10 21:58:42 2014 +0200 @@ -0,0 +1,8 @@ +#ifndef BOTC_TYPES_H +#define BOTC_TYPES_H + +#include <cstdlib> + +static const std::nullptr_t null = nullptr; + +#endif // BOTC_TYPES_H \ No newline at end of file
--- a/src/variables.cxx Fri Jan 10 16:11:49 2014 +0200 +++ b/src/variables.cxx Fri Jan 10 21:58:42 2014 +0200 @@ -38,12 +38,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#define __VARIABLES_CXX__ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "common.h" -#include "array.h" +#include "main.h" +#include "containers.h" #include "bots.h" #include "botcommands.h" #include "objwriter.h" @@ -51,13 +50,13 @@ #include "variables.h" #include "scriptreader.h" -array<ScriptVar> g_GlobalVariables; -array<ScriptVar> g_LocalVariables; +list<ScriptVar> g_GlobalVariables; +list<ScriptVar> g_LocalVariables; // ============================================================================ // Tries to declare a new global-scope variable. Returns pointer -// to new global variable, NULL if declaration failed. -ScriptVar* DeclareGlobalVariable (ScriptReader* r, type_e type, str name) { +// to new global variable, null if declaration failed. +ScriptVar* DeclareGlobalVariable (ScriptReader* r, type_e type, string name) { // Unfortunately the VM does not support string variables so yeah. if (type == TYPE_STRING) r->ParserError ("variables cannot be string\n"); @@ -89,14 +88,14 @@ // ============================================================================ // Find a global variable by name -ScriptVar* FindGlobalVariable (str name) { +ScriptVar* FindGlobalVariable (string name) { for (uint i = 0; i < g_GlobalVariables.size(); i++) { ScriptVar* g = &g_GlobalVariables[i]; if (g->name == name) return g; } - return NULL; + return null; } // ============================================================================
--- a/src/variables.h Fri Jan 10 16:11:49 2014 +0200 +++ b/src/variables.h Fri Jan 10 21:58:42 2014 +0200 @@ -1,66 +1,27 @@ -/* - * botc source code - * Copyright (C) 2012 Santeri `Dusk` Piippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of the developer nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * 4. Redistributions in any form must be accompanied by information on how to - * obtain complete source code for the software and any accompanying - * software that uses the software. The source code must either be included - * in the distribution or be available for no more than the cost of - * distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ +#ifndef BOTC_VARIABLES_H +#define BOTC_VARIABLES_H -#ifndef __VARIABLES_H__ -#define __VARIABLES_H__ #include "str.h" #include "scriptreader.h" struct ScriptVar { - str name; - str statename; + string name; + string statename; type_e type; int value; unsigned int index; }; -extern array<ScriptVar> g_GlobalVariables; -extern array<ScriptVar> g_LocalVariables; +extern list<ScriptVar> g_GlobalVariables; +extern list<ScriptVar> g_LocalVariables; #define ITERATE_GLOBAL_VARS(u) \ for (u = 0; u < MAX_SCRIPT_VARIABLES; u++) #define ITERATE_SCRIPT_VARS(g) \ - for (g = g_ScriptVariable; g != NULL; g = g->next) + for (g = g_ScriptVariable; g != null; g = g->next) -ScriptVar* DeclareGlobalVariable (ScriptReader* r, type_e type, str name); +ScriptVar* DeclareGlobalVariable (ScriptReader* r, type_e type, string name); deprecated unsigned int CountGlobalVars (); -ScriptVar* FindGlobalVariable (str name); +ScriptVar* FindGlobalVariable (string name); -#endif // __VARIABLES_H__ \ No newline at end of file +#endif // BOTC_VARIABLES_H \ No newline at end of file