summaryrefslogtreecommitdiff
path: root/src/script/script_scanner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/script_scanner.cpp')
-rw-r--r--src/script/script_scanner.cpp105
1 files changed, 105 insertions, 0 deletions
diff --git a/src/script/script_scanner.cpp b/src/script/script_scanner.cpp
new file mode 100644
index 000000000..7b993889e
--- /dev/null
+++ b/src/script/script_scanner.cpp
@@ -0,0 +1,105 @@
+/* $Id$ */
+
+/** @file script_scanner.cpp Allows scanning for scripts. */
+
+#include "../stdafx.h"
+#include "../string_func.h"
+#include "../fileio_func.h"
+#include <sys/stat.h>
+
+#include <squirrel.h>
+#include "../script/squirrel.hpp"
+#include "script_info.hpp"
+#include "script_scanner.hpp"
+
+void ScriptScanner::ScanDir(const char *dirname, const char *info_file_name)
+{
+ extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb);
+ extern bool FiosIsHiddenFile(const struct dirent *ent);
+
+ char d_name[MAX_PATH];
+ char temp_script[1024];
+ struct stat sb;
+ struct dirent *dirent;
+ DIR *dir;
+
+ dir = ttd_opendir(dirname);
+ /* Dir not found, so do nothing */
+ if (dir == NULL) return;
+
+ /* Walk all dirs trying to find a dir in which 'main.nut' exists */
+ while ((dirent = readdir(dir)) != NULL) {
+ ttd_strlcpy(d_name, FS2OTTD(dirent->d_name), sizeof(d_name));
+
+ /* 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;
+
+ /* Create the full length dirname */
+ ttd_strlcpy(temp_script, dirname, sizeof(temp_script));
+ ttd_strlcat(temp_script, d_name, sizeof(temp_script));
+
+ if (S_ISREG(sb.st_mode)) {
+ /* Only .tar files are allowed */
+ char *ext = strrchr(d_name, '.');
+ if (ext == NULL || strcasecmp(ext, ".tar") != 0) continue;
+
+ /* We always expect a directory in the TAR */
+ const char *first_dir = FioTarFirstDir(temp_script);
+ if (first_dir == NULL) continue;
+
+ ttd_strlcat(temp_script, PATHSEP, sizeof(temp_script));
+ ttd_strlcat(temp_script, first_dir, sizeof(temp_script));
+ FioTarAddLink(temp_script, first_dir);
+ } else if (!S_ISDIR(sb.st_mode)) {
+ /* Skip any other type of file */
+ continue;
+ }
+
+ /* Add an additional / where needed */
+ if (temp_script[strlen(temp_script) - 1] != PATHSEPCHAR) ttd_strlcat(temp_script, PATHSEP, sizeof(temp_script));
+
+ char info_script[MAX_PATH];
+ ttd_strlcpy(info_script, temp_script, sizeof(info_script));
+ ttd_strlcpy(main_script, temp_script, sizeof(main_script));
+
+ /* Every script should contain an 'info.nut' and 'main.nut' file; else it is not a valid script */
+ ttd_strlcat(info_script, info_file_name, sizeof(info_script));
+ ttd_strlcat(main_script, "main.nut", sizeof(main_script));
+ if (!FioCheckFileExists(info_script, NO_DIRECTORY) || !FioCheckFileExists(main_script, NO_DIRECTORY)) continue;
+
+ /* We don't care if one of the other scripts failed to load. */
+ this->engine->ResetCrashed();
+ this->engine->LoadScript(info_script);
+ }
+ closedir(dir);
+}
+
+void ScriptScanner::ScanScriptDir(const char *info_file_name, Subdirectory search_dir)
+{
+ char buf[MAX_PATH];
+ Searchpath sp;
+
+ extern void ScanForTarFiles();
+ ScanForTarFiles();
+
+ FOR_ALL_SEARCHPATHS(sp) {
+ FioAppendDirectory(buf, MAX_PATH, sp, search_dir);
+ if (FileExists(buf)) this->ScanDir(buf, info_file_name);
+ }
+}
+
+ScriptScanner::ScriptScanner()
+{
+ this->engine = new Squirrel();
+ this->main_script[0] = '\0';
+
+ /* Mark this class as global pointer */
+ this->engine->SetGlobalPointer(this);
+}
+
+ScriptScanner::~ScriptScanner()
+{
+ delete this->engine;
+}