(svn r13193) [NoAI] -Add: allow AIs to be packed in a .tar. one AI per tar, always in a subdir. It looks for main.nut in the first dir it finds in the archive
[NoAI] -Add: search for AIs in all searchpaths of OpenTTD
[NoAI] -Fix: only do the initial search once at start-up, not at some random times over time
[NoAI] -Fix: don't compile the sqstdlib files that are never used; this to speed up compilation time
[NoAI] -Fix: *grrmmmm* (very silent talking) forgot svn-props and stuff on ai_info.[ch]pp
--- a/bin/ai/regression/regression.nut Mon May 19 22:28:27 2008 +0000
+++ b/bin/ai/regression/regression.nut Tue May 20 13:09:34 2008 +0000
@@ -15,6 +15,7 @@
this.Sleep(1);
print(" TickTest: " + this.GetTick());
print(" SetCommandDelay: " + AISettings.SetCommandDelay(1));
+ require("require.nut");
}
function Regression::Std()
--- a/bin/ai/regression/regression.txt Mon May 19 22:28:27 2008 +0000
+++ b/bin/ai/regression/regression.txt Tue May 20 13:09:34 2008 +0000
@@ -3,6 +3,7 @@
TickTest: 0
TickTest: 1
SetCommandDelay: (null : 0x00000000)
+ Required this file
--Std--
abs(-21): 21
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/ai/regression/require.nut Tue May 20 13:09:34 2008 +0000
@@ -0,0 +1,3 @@
+
+print(" Required this file");
+
--- a/projects/openttd_vs80.vcproj Mon May 19 22:28:27 2008 +0000
+++ b/projects/openttd_vs80.vcproj Tue May 20 13:09:34 2008 +0000
@@ -2079,34 +2079,6 @@
RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdaux.cpp"
>
</File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdblob.cpp"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdio.cpp"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdmath.cpp"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdrex.cpp"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdstream.cpp"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdstring.cpp"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdsystem.cpp"
- >
- </File>
</Filter>
<Filter
Name="Squirrel headers"
@@ -2132,34 +2104,6 @@
>
</File>
<File
- RelativePath=".\..\src\3rdparty\squirrel\include\sqstdblob.h"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdblobimpl.h"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\include\sqstdio.h"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\include\sqstdmath.h"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdstream.h"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\include\sqstdstring.h"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\include\sqstdsystem.h"
- >
- </File>
- <File
RelativePath=".\..\src\3rdparty\squirrel\squirrel\sqfuncproto.h"
>
</File>
--- a/projects/openttd_vs90.vcproj Mon May 19 22:28:27 2008 +0000
+++ b/projects/openttd_vs90.vcproj Tue May 20 13:09:34 2008 +0000
@@ -2076,34 +2076,6 @@
RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdaux.cpp"
>
</File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdblob.cpp"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdio.cpp"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdmath.cpp"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdrex.cpp"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdstream.cpp"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdstring.cpp"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdsystem.cpp"
- >
- </File>
</Filter>
<Filter
Name="Squirrel headers"
@@ -2129,34 +2101,6 @@
>
</File>
<File
- RelativePath=".\..\src\3rdparty\squirrel\include\sqstdblob.h"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdblobimpl.h"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\include\sqstdio.h"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\include\sqstdmath.h"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\sqstdlib\sqstdstream.h"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\include\sqstdstring.h"
- >
- </File>
- <File
- RelativePath=".\..\src\3rdparty\squirrel\include\sqstdsystem.h"
- >
- </File>
- <File
RelativePath=".\..\src\3rdparty\squirrel\squirrel\sqfuncproto.h"
>
</File>
--- a/source.list Mon May 19 22:28:27 2008 +0000
+++ b/source.list Tue May 20 13:09:34 2008 +0000
@@ -463,13 +463,6 @@
3rdparty/squirrel/squirrel/sqtable.cpp
3rdparty/squirrel/squirrel/sqvm.cpp
3rdparty/squirrel/sqstdlib/sqstdaux.cpp
-3rdparty/squirrel/sqstdlib/sqstdblob.cpp
-3rdparty/squirrel/sqstdlib/sqstdio.cpp
-3rdparty/squirrel/sqstdlib/sqstdmath.cpp
-3rdparty/squirrel/sqstdlib/sqstdrex.cpp
-3rdparty/squirrel/sqstdlib/sqstdstream.cpp
-3rdparty/squirrel/sqstdlib/sqstdstring.cpp
-3rdparty/squirrel/sqstdlib/sqstdsystem.cpp
# Squirrel headers
3rdparty/squirrel/squirrel/sqarray.h
@@ -477,13 +470,6 @@
3rdparty/squirrel/squirrel/sqclosure.h
3rdparty/squirrel/squirrel/sqcompiler.h
3rdparty/squirrel/include/sqstdaux.h
-3rdparty/squirrel/include/sqstdblob.h
-3rdparty/squirrel/sqstdlib/sqstdblobimpl.h
-3rdparty/squirrel/include/sqstdio.h
-3rdparty/squirrel/include/sqstdmath.h
-3rdparty/squirrel/sqstdlib/sqstdstream.h
-3rdparty/squirrel/include/sqstdstring.h
-3rdparty/squirrel/include/sqstdsystem.h
3rdparty/squirrel/squirrel/sqfuncproto.h
3rdparty/squirrel/squirrel/sqfuncstate.h
3rdparty/squirrel/squirrel/sqlexer.h
--- a/src/ai/ai.cpp Mon May 19 22:28:27 2008 +0000
+++ b/src/ai/ai.cpp Tue May 20 13:09:34 2008 +0000
@@ -29,7 +29,7 @@
static AIController *_ai_player[MAX_PLAYERS];
static AIInfo *_ai_info[MAX_PLAYERS];
-static AISquirrel *_ai_squirrel;
+static AISquirrel *_ai_squirrel = NULL;
static uint _ai_frame_counter;
static bool _ai_enabled;
static char *_forced_ai_name = NULL;
@@ -143,6 +143,7 @@
_ai_enabled = true;
/* Create the Squirrel collector, which scans for all AIs available */
+ assert(_ai_squirrel == NULL);
_ai_squirrel = new AISquirrel();
}
@@ -179,6 +180,7 @@
}
delete _ai_squirrel;
+ _ai_squirrel = NULL;
}
/**
--- a/src/ai/ai_info.cpp Mon May 19 22:28:27 2008 +0000
+++ b/src/ai/ai_info.cpp Tue May 20 13:09:34 2008 +0000
@@ -1,3 +1,7 @@
+/* $Id$ */
+
+/** @file ai_info.cpp Implementation of AIInfo */
+
#include "../stdafx.h"
#include "../core/alloc_func.hpp"
@@ -59,6 +63,11 @@
return this->dir_name;
}
+const char *AIInfo::GetScriptName()
+{
+ return this->script_name;
+}
+
void AIInfo::CheckMethods(SQInteger *res, const char *name)
{
if (!this->engine->MethodExists(*this->SQ_instance, name)) {
--- a/src/ai/ai_info.hpp Mon May 19 22:28:27 2008 +0000
+++ b/src/ai/ai_info.hpp Tue May 20 13:09:34 2008 +0000
@@ -1,3 +1,7 @@
+/* $Id$ */
+
+/** @file ai_info.hpp AIInfo keeps track of all information of an AI, like Author, Description, ... */
+
#ifndef AI_INFO
#define AI_INFO
@@ -46,6 +50,11 @@
const char *GetDirName();
/**
+ * Get the complete script name of this AI.
+ */
+ const char *GetScriptName();
+
+ /**
* Check if a given method exists.
*/
void CheckMethods(SQInteger *res, const char *name);
--- a/src/ai/ai_squirrel.cpp Mon May 19 22:28:27 2008 +0000
+++ b/src/ai/ai_squirrel.cpp Tue May 20 13:09:34 2008 +0000
@@ -36,23 +36,41 @@
while ((dirent = readdir(dir)) != NULL) {
ttd_strlcpy(d_name, FS2OTTD(dirent->d_name), sizeof(d_name));
- /* Found file must be directory, but not '.' or '..' */
- if (FiosIsValidFile("ai/", dirent, &sb) && (sb.st_mode & S_IFDIR) &&
- (!FiosIsHiddenFile(dirent) || strncasecmp(d_name, PERSONAL_DIR, strlen(d_name)) == 0) &&
- strcmp(d_name, ".") != 0 && strcmp(d_name, "..") != 0) {
+ /* Valid file, not '.' or '..', not hidden */
+ if (!FiosIsValidFile(dirname, dirent, &sb)) continue;
+ if (strcmp(d_name, ".") == 0 || strcmp(d_name, "..") == 0) continue;
+ if (FiosIsHiddenFile(dirent) && strncasecmp(d_name, PERSONAL_DIR, strlen(d_name)) != 0) continue;
+
+ if (sb.st_mode & S_IFDIR) {
/* Create the full-length script-name */
ttd_strlcpy(script_name, dirname, sizeof(script_name));
- ttd_strlcat(script_name, PATHSEP, sizeof(script_name));
ttd_strlcat(script_name, d_name, sizeof(script_name));
ttd_strlcat(script_name, PATHSEP, sizeof(script_name));
- ttd_strlcat(script_name, "main.nut", sizeof(script_name));
- /* If it exists, load it up */
- if (FileExists(script_name)) {
- DEBUG(ai, 6, "[squirrel] Loading script '%s' for AI handling", script_name);
- this->current_script = script_name;
- this->current_dir = d_name;
- this->engine->LoadScript(this->current_script);
- }
+ }
+ if (sb.st_mode & S_IFREG) {
+ char *ext = strrchr(d_name, '.');
+ if (ext != NULL && strcasecmp(ext, ".tar") != 0) continue;
+
+ /* Create the full path to the tarfile */
+ char tarname[MAX_PATH];
+ ttd_strlcpy(tarname, dirname, sizeof(tarname));
+ ttd_strlcat(tarname, d_name, sizeof(tarname));
+
+ /* Now the script-name starts with the first dir in the tar */
+ assert(FioTarFirstDir(tarname) != NULL);
+ ttd_strlcpy(script_name, FioTarFirstDir(tarname), sizeof(script_name));
+
+ /* The name of the AI is the name of the tar minus the .tar */
+ *ext = '\0';
+ }
+
+ /* We look for the file 'main.nut' inside the AI dir.. if it doesn't exists, it isn't an AI */
+ ttd_strlcat(script_name, "main.nut", sizeof(script_name));
+ if (FioCheckFileExists(script_name, AI_DIR)) {
+ DEBUG(ai, 6, "[squirrel] Loading script '%s' for AI handling", script_name);
+ this->current_script = script_name;
+ this->current_dir = d_name;
+ this->engine->LoadScript(this->current_script);
}
}
closedir(dir);
@@ -75,7 +93,13 @@
this->engine->SetGlobalPointer(this);
/* Scan the AI dir for scripts */
- this->ScanDir("ai");
+ char buf[MAX_PATH];
+ Searchpath sp;
+
+ FOR_ALL_SEARCHPATHS(sp) {
+ FioAppendDirectory(buf, MAX_PATH, sp, AI_DIR);
+ if (FileExists(buf)) this->ScanDir(buf);
+ }
}
AISquirrel::~AISquirrel()
@@ -85,7 +109,21 @@
void AISquirrel::RegisterAI(AIInfo *info)
{
- this->info_list.insert(AIInfoList::value_type(info->GetDirName(), info));
+ const char *ai_name = info->GetDirName();
+
+ /* Check if we register twice; than the latest always wins */
+ if (this->info_list.find(ai_name) != this->info_list.end()) {
+ /* In case they are not the same dir, give a warning */
+ if (strcasecmp(info->GetScriptName(), this->info_list[ai_name]->GetScriptName()) != 0) {
+ DEBUG(ai, 0, "Registering two AIs with the same name");
+ DEBUG(ai, 0, " 1: %s", this->info_list[ai_name]->GetScriptName());
+ DEBUG(ai, 0, " 2: %s", info->GetScriptName());
+ DEBUG(ai, 0, "The latter is taking precedence");
+ }
+ this->info_list[ai_name] = info;
+ return;
+ }
+ this->info_list[ai_name] = info;
}
void AISquirrel::UnregisterAI(AIInfo *info)
--- a/src/ai/ai_squirrel.hpp Mon May 19 22:28:27 2008 +0000
+++ b/src/ai/ai_squirrel.hpp Tue May 20 13:09:34 2008 +0000
@@ -6,6 +6,7 @@
#define AI_SQUIRREL_HPP
#include <map>
+struct ltstr { bool operator()(const char *s1, const char *s2) const { return strcmp(s1, s2) < 0; } };
class AISquirrel {
public:
@@ -53,7 +54,7 @@
const char *GetCurrentDirName() { return this->current_dir; }
private:
- typedef std::map<const char *, class AIInfo *> AIInfoList;
+ typedef std::map<const char *, class AIInfo *, ltstr> AIInfoList;
/**
* Scan a dir for AIs. If found, AIInfo is created, and the AI is registered to the central system.
--- a/src/fileio.cpp Mon May 19 22:28:27 2008 +0000
+++ b/src/fileio.cpp Tue May 20 13:09:34 2008 +0000
@@ -215,7 +215,8 @@
"scenario" PATHSEP "heightmap" PATHSEP,
"gm" PATHSEP,
"data" PATHSEP,
- "lang" PATHSEP
+ "lang" PATHSEP,
+ "ai" PATHSEP,
};
const char *_searchpaths[NUM_SEARCHPATHS];
@@ -355,7 +356,7 @@
}
/* We can only use .tar in case of data-dir, and read-mode */
- if (f == NULL && subdir == DATA_DIR && mode[0] == 'r') {
+ if (f == NULL && (subdir == DATA_DIR || subdir == AI_DIR) && mode[0] == 'r') {
/* Filenames in tars are always forced to be lowercase */
char *lcfilename = strdup(filename);
strtolower(lcfilename);
@@ -442,6 +443,13 @@
return dest;
}
+const char *FioTarFirstDir(const char *tarname)
+{
+ TarList::iterator it = _tar_list.find(tarname);
+ if (it == _tar_list.end()) return NULL;
+ return (*it).second->dirname;
+}
+
static bool TarListAddFile(const char *filename)
{
/* The TAR-header, repeated for every file */
@@ -475,6 +483,7 @@
TarListEntry *tar_entry = MallocT<TarListEntry>(1);
tar_entry->filename = strdup(filename);
+ tar_entry->dirname = NULL;
_tar_list.insert(TarList::value_type(filename, tar_entry));
TarHeader th;
@@ -513,12 +522,21 @@
/* Copy the name of the file in a safe way at the end of 'name' */
memcpy(&name[len], th.name, sizeof(th.name));
name[len + sizeof(th.name)] = '\0';
+ /* Tar-files always have '/' path-seperator, but we want our PATHSEPCHAR */
+#if (PATHSEPCHAR != '/')
+ for (char *n = name; *n != '\0'; n++) if (*n == '/') *n = PATHSEPCHAR;
+#endif
+ /* Force lowercase */
+ strtolower(name);
/* Calculate the size of the file.. for some strange reason this is stored as a string */
memcpy(buf, th.size, sizeof(th.size));
buf[sizeof(th.size)] = '\0';
int skip = strtol(buf, &end, 8);
+ /* Store the first directory name we detect */
+ if (skip == 0 && tar_entry->dirname == NULL) tar_entry->dirname = strdup(name);
+
/* 0 byte sized files can be skipped (dirs, symlinks, ..) */
if (skip == 0) continue;
@@ -527,13 +545,6 @@
entry.tar = tar_entry;
entry.size = skip;
entry.position = pos;
- /* Force lowercase */
- strtolower(name);
-
- /* Tar-files always have '/' path-seperator, but we want our PATHSEPCHAR */
-#if (PATHSEPCHAR != '/')
- for (char *n = name; *n != '\0'; n++) if (*n == '/') *n = PATHSEPCHAR;
-#endif
DEBUG(misc, 6, "Found file in tar: %s (%d bytes, %d offset)", name, skip, pos);
if (_tar_filelist.insert(TarFileList::value_type(name, entry)).second) num++;
@@ -600,6 +611,8 @@
FOR_ALL_SEARCHPATHS(sp) {
FioAppendDirectory(path, MAX_PATH, sp, DATA_DIR);
num += ScanPathForTarFiles(path, strlen(path));
+ FioAppendDirectory(path, MAX_PATH, sp, AI_DIR);
+ num += ScanPathForTarFiles(path, strlen(path));
}
DEBUG(misc, 1, "Scan complete, found %d files", num);
}
--- a/src/fileio.h Mon May 19 22:28:27 2008 +0000
+++ b/src/fileio.h Tue May 20 13:09:34 2008 +0000
@@ -34,6 +34,7 @@
GM_DIR, ///< Subdirectory for all music
DATA_DIR, ///< Subdirectory for all data (GRFs, sample.cat, intro game)
LANG_DIR, ///< Subdirectory for all translation files
+ AI_DIR, ///< Subdirectory for all AI files
NUM_SUBDIRS, ///< Number of subdirectories
NO_DIRECTORY, ///< A path without any base directory
};
@@ -67,6 +68,7 @@
*/
struct TarListEntry {
const char *filename;
+ const char *dirname;
};
struct TarFileListEntry {
TarListEntry *tar;
@@ -115,6 +117,7 @@
void DeterminePaths(const char *exe);
void *ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize);
bool FileExists(const char *filename);
+const char *FioTarFirstDir(const char *tarname);
extern char *_personal_dir; ///< custom directory for personal settings, saves, newgrf, etc.
--- a/src/misc.cpp Mon May 19 22:28:27 2008 +0000
+++ b/src/misc.cpp Tue May 20 13:09:34 2008 +0000
@@ -99,7 +99,6 @@
InitializeTrains();
InitializeNPF();
- AI_Initialize();
InitializePlayers();
InitializeCheats();
--- a/src/openttd.cpp Mon May 19 22:28:27 2008 +0000
+++ b/src/openttd.cpp Tue May 20 13:09:34 2008 +0000
@@ -465,6 +465,7 @@
case 'x': save_config = false; break;
case -2:
case 'h':
+ DeterminePaths(argv[0]);
ShowHelp();
return 0;
}
--- a/src/squirrel.cpp Mon May 19 22:28:27 2008 +0000
+++ b/src/squirrel.cpp Tue May 20 13:09:34 2008 +0000
@@ -3,12 +3,12 @@
/** @file squirrel.cpp the implementation of the Squirrel class. It handles all Squirrel-stuff and gives a nice API back to work with. */
#include <squirrel.h>
-#include <sqstdio.h>
#include <stdarg.h>
#include "stdafx.h"
#include "debug.h"
#include "squirrel.hpp"
#include "squirrel_std.hpp"
+#include "fileio.h"
#include <sqstdaux.h>
void Squirrel::CompileError(HSQUIRRELVM vm, const SQChar *desc, const SQChar *source, SQInteger line, SQInteger column)
@@ -246,18 +246,140 @@
squirrel_register_global_std(this);
}
-bool Squirrel::LoadScript(const char *script)
+static SQInteger _io_file_lexfeed_ASCII(SQUserPointer file)
+{
+ SQInteger ret;
+ char c;
+ if ((ret = fread(&c, sizeof(c), 1, (FILE *)file) > 0)) return c;
+ return 0;
+}
+
+static SQInteger _io_file_lexfeed_UTF8(SQUserPointer file)
+{
+ static const SQInteger utf8_lengths[16] =
+ {
+ 1, 1, 1, 1, 1, 1, 1, 1, /* 0000 to 0111 : 1 byte (plain ASCII) */
+ 0, 0, 0, 0, /* 1000 to 1011 : not valid */
+ 2, 2, /* 1100, 1101 : 2 bytes */
+ 3, /* 1110 : 3 bytes */
+ 4 /* 1111 : 4 bytes */
+ };
+ static unsigned char byte_masks[5] = {0, 0, 0x1F, 0x0F, 0x07};
+ unsigned char inchar;
+ SQInteger c = 0;
+ if (fread(&inchar, sizeof(inchar), 1, (FILE *)file) != 1) return 0;
+ c = inchar;
+
+ if (c >= 0x80) {
+ SQInteger tmp;
+ SQInteger codelen = utf8_lengths[c >> 4];
+ if (codelen == 0) return 0;
+
+ tmp = c & byte_masks[codelen];
+ for (SQInteger n = 0; n < codelen - 1; n++) {
+ tmp <<= 6;
+ if (fread(&inchar, sizeof(inchar), 1, (FILE *)file) != 1) return 0;
+ tmp |= inchar & 0x3F;
+ }
+ c = tmp;
+ }
+ return c;
+}
+
+static SQInteger _io_file_lexfeed_UCS2_LE(SQUserPointer file)
+{
+ SQInteger ret;
+ wchar_t c;
+ if ((ret = fread(&c, sizeof(c), 1, (FILE *)file) > 0)) return (SQChar)c;
+ return 0;
+}
+
+static SQInteger _io_file_lexfeed_UCS2_BE(SQUserPointer file)
+{
+ SQInteger ret;
+ unsigned short c;
+ if ((ret = fread(&c, sizeof(c), 1, (FILE *)file) > 0)) {
+ c = ((c >> 8) & 0x00FF)| ((c << 8) & 0xFF00);
+ return (SQChar)c;
+ }
+ return 0;
+}
+
+static SQInteger _io_file_read(SQUserPointer file, SQUserPointer buf, SQInteger size)
+{
+ SQInteger ret = fread(buf, 1, size, (FILE *)file);
+ if (ret == 0) return -1;
+ return ret;
+}
+
+/* static */ SQRESULT Squirrel::LoadFile(HSQUIRRELVM vm, const char *filename, SQBool printerror)
+{
+ FILE *file = FioFOpenFile(filename, "rb", AI_DIR);
+ SQInteger ret;
+ unsigned short us;
+ unsigned char uc;
+ SQLEXREADFUNC func;
+
+ if (file != NULL) {
+ ret = fread(&us, 1, sizeof(us), file);
+ /* Most likely an empty file */
+ if (ret != 2) us = 0;
+
+ switch (us) {
+ case SQ_BYTECODE_STREAM_TAG: // BYTECODE
+ fseek(file, -2, SEEK_CUR);
+ if (SQ_SUCCEEDED(sq_readclosure(vm, _io_file_read, file))) {
+ FioFCloseFile(file);
+ return SQ_OK;
+ }
+ return sq_throwerror(vm, _SC("Couldn't read bytecode"));
+ case 0xFFFE: func = _io_file_lexfeed_UCS2_BE; break; // UTF-16 little endian
+ case 0xFEFF: func = _io_file_lexfeed_UCS2_LE; break; // UTF-16 big endian
+ case 0xBBEF: // UTF-8
+ if (fread(&uc, 1, sizeof(uc), file) == 0) {
+ FioFCloseFile(file);
+ return sq_throwerror(vm, _SC("I/O error"));
+ }
+ if (uc != 0xBF) {
+ FioFCloseFile(file);
+ return sq_throwerror(vm, _SC("Unrecognized encoding"));
+ }
+ func = _io_file_lexfeed_UTF8;
+ break;
+ default: func = _io_file_lexfeed_ASCII; fseek(file, -2, SEEK_CUR); break; // ASCII
+ }
+
+ if (SQ_SUCCEEDED(sq_compile(vm, func, file, OTTD2FS(filename), printerror))) {
+ FioFCloseFile(file);
+ return SQ_OK;
+ }
+ FioFCloseFile(file);
+ return SQ_ERROR;
+ }
+ return sq_throwerror(vm, _SC("cannot open the file"));
+}
+
+/* static */ bool Squirrel::LoadScript(HSQUIRRELVM vm, const char *script)
{
/* Make sure we are always in the root-table */
- sq_pushroottable(this->vm);
+ sq_pushroottable(vm);
/* Load and run the script */
- if (SQ_FAILED(sqstd_dofile(this->vm, OTTD2FS(script), SQFalse, SQTrue))) {
- DEBUG(misc, 0, "[squirrel] Failed to compile '%s'", script);
- return false;
+ if (SQ_SUCCEEDED(LoadFile(vm, script, SQTrue))) {
+ sq_push(vm, -2);
+ if (SQ_SUCCEEDED(sq_call(vm, 1, SQFalse, SQTrue))) {
+ sq_remove(vm, -1);
+ return true;
+ }
}
- return true;
+ DEBUG(misc, 0, "[squirrel] Failed to compile '%s'", script);
+ return false;
+}
+
+bool Squirrel::LoadScript(const char *script)
+{
+ return LoadScript(this->vm, script);
}
Squirrel::~Squirrel()
--- a/src/squirrel.hpp Mon May 19 22:28:27 2008 +0000
+++ b/src/squirrel.hpp Tue May 20 13:09:34 2008 +0000
@@ -49,6 +49,12 @@
* @return False if loading failed.
*/
bool LoadScript(const char *script);
+ static bool LoadScript(HSQUIRRELVM vm, const char *script);
+
+ /**
+ * Load a file to a given VM.
+ */
+ static SQRESULT LoadFile(HSQUIRRELVM vm, const char *filename, SQBool printerror);
/**
* Adds a function to the stack. Depending on the current state this means
--- a/src/squirrel_std.cpp Mon May 19 22:28:27 2008 +0000
+++ b/src/squirrel_std.cpp Tue May 20 13:09:34 2008 +0000
@@ -1,6 +1,5 @@
#include <squirrel.h>
-#include <sqstdio.h>
#include "stdafx.h"
#include "debug.h"
#include "squirrel.hpp"
@@ -47,21 +46,13 @@
real_filename = ReallocT(real_filename, scstrlen(real_filename) + scstrlen(filename) + 1);
scstrcat(real_filename, filename);
- /* Make sure we are in the root-table, so everything is included in the root-level */
- sq_pushroottable(vm);
-
- SQInteger ret = 0;
+ bool ret = Squirrel::LoadScript(vm, FS2OTTD(real_filename));
- /* Compile and load the file */
- if (!SQ_SUCCEEDED(sqstd_dofile(vm, real_filename, SQFalse, SQTrue))) {
- DEBUG(misc, 0, "[squirrel] Failed to compile '%s'", filename);
- ret = SQ_ERROR;
- }
/* Reset the top, so the stack stays correct */
sq_settop(vm, top);
free(real_filename);
- return ret;
+ return ret ? 0: SQ_ERROR;
}
void squirrel_register_global_std(Squirrel *engine)