diff --git a/stepmania/PBProject/Installer/BuildInstaller.cpp b/stepmania/PBProject/Installer/BuildInstaller.cpp new file mode 100644 index 0000000000..3971fa9fff --- /dev/null +++ b/stepmania/PBProject/Installer/BuildInstaller.cpp @@ -0,0 +1,111 @@ +/* + * BuildInstaller.cpp + * stepmania + * + * Created by Steve Checkoway on Sun Sep 07 2003. + * Copyright (c) 2003 Steve Checkoway. All rights reserved. + * + */ + +using namespace std; + +#include "StdString.h" +#include "InstallerFile.h" +#include "Processor.h" +#include +#include +#include +#include + +void HandleFile(const char *file, const char *archivePath, bool overwrite) +{ + static bool archiveMade = false; + CString command; + + if (archiveMade) + command = "tar rfP '"; + else + { + archiveMade = true; + command = "tar cfP '"; + } + command += archivePath; + command += "' '"; + command += file; + command += "'"; + + system(command); + + printf("%s\n", file); +} + +void PrintUsage(int err) +{ + printf("usage: BuildInstaller config [dir]\n\n" + "config: The configuration file for the installer.\n" + "dir: The output directory. It is created if it doesn't exist\n"); + exit(err); +} + +int main(int argc, char *argv[]) +{ + CString inFile, outDir; + + switch (argc) + { + case 1: + printf("BuildInstaller needs to be run with at least one argument.\n"); + PrintUsage(1); + + case 2: + inFile = argv[1]; + outDir = "."; + break; + + case 3: + inFile = argv[1]; + outDir = argv[2]; + break; + + default: + printf("BuildInstaller takes at most 2 arguments.\n"); + PrintUsage(2); + } + + if (inFile == "help" || inFile == "-h" || inFile == "--help") + PrintUsage(0); + + + InstallerFile config(inFile); + unsigned nextLine = 0; + + if (!config.ReadFile()) + { + printf("Couldn't read config file, \"%s\".\n", inFile.c_str()); + return 3; + } + + /* Create the directory--the lazy man's way */ + CString command = "mkdir -p '" + outDir + "'"; + + if (system(command)) + { + printf("The system(\"%s\") call failed.\n", command.c_str()); + return 4; + } + + CString archivePath = outDir + "/archive.tar"; + + Processor p(archivePath, HandleFile, NULL, false); + + while (nextLine < config.GetNumLines()) + p.ProcessLine(config.GetLine(nextLine), nextLine); + + if (!config.WriteFile(outDir + "/config")) + { + printf("%s\n", strerror(errno)); + return 6; + } + + return 0; +} diff --git a/stepmania/PBProject/Installer/InstallerFile.cpp b/stepmania/PBProject/Installer/InstallerFile.cpp new file mode 100644 index 0000000000..444bab5b29 --- /dev/null +++ b/stepmania/PBProject/Installer/InstallerFile.cpp @@ -0,0 +1,140 @@ +/* + * InstallerFile.cpp + * stepmania + * + * Created by Steve Checkoway on Sun Sep 07 2003. + * Copyright (c) 2003 Steve Checkoway. All rights reserved. + * + */ + +using namespace std; + +#include +#include +#include +#include +#include +#include +#include +#include "StdString.h" +#include "InstallerFile.h" + +const unsigned maxLineLen = 1024; +const unsigned short magicNumber = 0xBAD1; + +bool InstallerFile::ReadFile(const CString& path) +{ + const CString& file = (path == "" ? mPath : path); + int fd = open(file, O_RDONLY, S_IROTH); + if (fd == -1) + return false; + struct stat sb; + + if (fstat(fd, &sb) == -1) + return false; + + + unsigned fileLength = sb.st_size; + + if (fileLength <= 2) + return false; + fileLength += 1000; /* Just in case */ + + char buf[fileLength]; + + unsigned len = read(fd, buf, fileLength); + + close(fd); + unsigned short temp = (buf[0] << 8) | (buf[1] & 0x00FF) ; + + if (temp == magicNumber) + ReadBinary(buf + 2, len - 2); + else + ReadText(buf, len); + + return mLines.size(); +} + +void InstallerFile::ReadBinary(const char *buf, unsigned len) +{ + unsigned pos = 0; + while (pos < len) + { + if (len < pos + 2) + break; + unsigned length = *(unsigned short *)buf; + + buf += 2; + pos += 2; + if (len < pos + length) + break; + mLines.push_back(CString(buf, length)); + buf += length; + pos += length; + } +} + +void InstallerFile::ReadText(const char *buf, unsigned len) +{ + unsigned pos = 0; + + while (pos < len) + { + unsigned lineLen = 0; + bool ignoreLine = false; + char line[maxLineLen]; + + while (lineLen < maxLineLen && pos < len) + { + ++pos; + if (strspn(buf, "\r\n")) + { + ++buf; + break; + } + if (!lineLen && strspn(buf, " \t")){ + ++buf; + continue; + } + if (!lineLen && *buf == '#') + { + ignoreLine = true; + ++buf; + } + else + line[lineLen++] = *(buf++); + } + + if (!lineLen || ignoreLine) + continue; + mLines.push_back(CString(line, lineLen)); + } +} + +bool InstallerFile::WriteFile(const CString& path) +{ + /* Use buffered I/O */ + FILE *fp = fopen(path, "w"); + + if (fp == NULL) + return false; + + fwrite(&magicNumber, sizeof(magicNumber), 1, fp); + + for (unsigned i=0; i= mLines.size()) + return ""; + return mLines[line]; +} diff --git a/stepmania/PBProject/Installer/InstallerFile.h b/stepmania/PBProject/Installer/InstallerFile.h new file mode 100644 index 0000000000..89aeced4b4 --- /dev/null +++ b/stepmania/PBProject/Installer/InstallerFile.h @@ -0,0 +1,32 @@ +/* + * InstallerFile.h + * stepmania + * + * Created by Steve Checkoway on Sun Sep 07 2003. + * Copyright (c) 2003 Steve Checkoway. All rights reserved. + * + */ + +#ifndef INSTALLER_FILE_H +#define INSTALLER_FILE_H + +#include +#include + +class InstallerFile { +private: + CString mPath; + vector mLines; + + void ReadBinary(const char *buf, unsigned len); + void ReadText(const char *buf, unsigned len); + +public: + InstallerFile(CString path) : mPath(path) { } + bool ReadFile(const CString& path = ""); + bool WriteFile(const CString& path); + CString GetLine(unsigned line); + unsigned GetNumLines() { return mLines.size(); } +}; + +#endif diff --git a/stepmania/PBProject/Installer/Processor.cpp b/stepmania/PBProject/Installer/Processor.cpp new file mode 100644 index 0000000000..e2aeefcf01 --- /dev/null +++ b/stepmania/PBProject/Installer/Processor.cpp @@ -0,0 +1,238 @@ +/* + * Processor.cpp + * stepmania + * + * Created by Steve Checkoway on Sun Sep 07 2003. + * Copyright (c) 2003 Steve Checkoway. All rights reserved. + * + */ + +using namespace std; + +#include +#include +#include +#include "StdString.h" +#include "Processor.h" + +void split(const CString& Source, const CString& Deliminator, vector& AddIt) +{ + unsigned startpos = 0; + + do { + unsigned pos = Source.find(Deliminator, startpos); + if (pos == Source.npos) pos=Source.size(); + + CString AddCString = Source.substr(startpos, pos-startpos); + AddIt.push_back(AddCString); + + startpos=pos+Deliminator.size(); + } while (startpos <= Source.size()); +} + +bool IsAVar(const CString& var) +{ + return var[0] == '$'; +} + +CString StripVar(const CString& var) +{ + if (!IsAVar(var)) + return var; + return var.substr(1, var.npos); +} + +void Processor::ProcessLine(const CString& line, unsigned& nextLine) +{ + CStringArray parts; + + split(line, ":", parts); + + if (!mInstalling) + { + if (parts[0] == "FILE") + { + if (parts.size() != 3) + goto error; + (*mHandleFile)(parts[1], mPath, true); + } + ++nextLine; + return; + } + + if (parts[0] == "LABEL") + { + if (parts.size() != 2) + goto error; + if (mDoGoto && parts[1] == mLabel) + { + mDoGoto = false; + mLabel = ""; + } + mLabels[parts[1]] = ++nextLine; // set mLabel to be the next line + return; + } + + if (mDoGoto) + { + ++nextLine; + return; + } + + if (parts[0] == "GOTO") + { + if (parts.size() != 2) + goto error; + if (parts[1] == "") + goto error; + mLabel = parts[1]; + if (mLabels.find(mLabel) != mLabels.end()) + { + mReturnStack.push(nextLine + 1); + nextLine = mLabels[mLabel]; + mLabel = ""; + return; + } + mDoGoto = true; + mReturnStack.push(++nextLine); + return; + } + + if (parts[0] == "IF") + { + if (parts.size() != 4) + goto error; + if (ResolveConditional(parts[1])) + mLabel = parts[2]; + else + mLabel = parts[3]; + if (mLabel == "") + { + ++nextLine; + return; + } + mReturnStack.push(nextLine + 1); + if (mLabels.find(mLabel) != mLabels.end()) + { + nextLine = mLabels[mLabel]; + mLabel = ""; + return; + } + mDoGoto = true; + ++nextLine; + return; + } + + if (parts[0] == "FILE") + { + if (parts.size() != 3) + goto error; + bool overwrite = ResolveConditional(parts[2]); + (*mHandleFile)(parts[1], mPath, overwrite); + + ++nextLine; + return; + } + + if (parts[0] == "RETURN") + { + if (mReturnStack.empty()) + nextLine = unsigned(-1); // quite large + else + { + nextLine = mReturnStack.top(); + mReturnStack.pop(); + } + return; + } + + if (parts[0] == "GETPATH") + { + if (parts.size() != 3) + goto error; + mVars[parts[2]] = (*mGetPath)(parts[1]); + ++nextLine; + return; + } + + if (parts[0] == "SETVAR") + { + if (parts.size() < 3) + goto error; + CString temp = ""; + for (unsigned i=2; i +#include +#include "StdString.h" + +class Processor +{ +private: + typedef void (*handleFileFunc)(const char *file, const char *archivePath, bool overwrite); + typedef const char *(*getPathFunc)(const char *id); + typedef void (*errorFunc)(const char *fmt, ...); + + stack mReturnStack; + bool mDoGoto; + CString mLabel; + map mConditionals; + map mVars; + map mLabels; + CString mPath; + CString mCWD; + handleFileFunc mHandleFile; + getPathFunc mGetPath; + errorFunc mError; + bool mInstalling; + + const CString& ResolveVar(const CString& var); + bool ResolveConditional(const CString& cond); + static void DefaultError(const char *fmt, ...); +public: + Processor(CString& path, handleFileFunc f, getPathFunc p, bool i) + : mDoGoto(false), mPath(path), mCWD("."), mHandleFile(f), mGetPath(p), + mError(Processor::DefaultError), mInstalling(i) { } + void ProcessLine(const CString& line, unsigned& nextLine); + void SetErrorFunc(errorFunc f) { mError = f; } +}; + +#endif