Initial commit
This commit is contained in:
140
tools/langc/Getopt.cc
Executable file
140
tools/langc/Getopt.cc
Executable file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
** Slab NG - The Next Generation of Slab
|
||||
** (c) Copyright 2002-2004 Tom Bampton
|
||||
** All Rights Reserved.
|
||||
**
|
||||
** $Id: Getopt.cpp,v 1.1 2003/10/30 23:55:29 tom Exp $
|
||||
**
|
||||
** Filename: Getopt.cpp
|
||||
** Author: Tom Bampton
|
||||
** Created: 30/10/2003
|
||||
** Purpose:
|
||||
** Command Line Parser
|
||||
**
|
||||
*/
|
||||
|
||||
/*
|
||||
* Based on getopt.c from FreeBSD, bearing the following copyright message:
|
||||
*
|
||||
* Copyright (c) 1987, 1993, 1994
|
||||
* The Regents of the University of California. 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 "platform/platform.h"
|
||||
#include "Getopt.h"
|
||||
|
||||
|
||||
#define EMSG ""
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
Getopt::Getopt(char *sOptions)
|
||||
{
|
||||
m_sOptions = sOptions;
|
||||
m_sPlace = EMSG;
|
||||
m_nOptInd = 1;
|
||||
}
|
||||
|
||||
Getopt::~Getopt()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int Getopt::getopt(int nargc, char **nargv)
|
||||
{
|
||||
char *oli; /* option letter list index */
|
||||
|
||||
m_nargc = nargc;
|
||||
m_nargv = nargv;
|
||||
|
||||
if (!*m_sPlace) { /* update scanning pointer */
|
||||
if (m_nOptInd >= nargc || *(m_sPlace = nargv[m_nOptInd]) != '-') {
|
||||
m_sPlace = EMSG;
|
||||
return -1;
|
||||
}
|
||||
if (m_sPlace[1] && *++m_sPlace == '-') { /* found "--" */
|
||||
++m_nOptInd;
|
||||
m_sPlace = EMSG;
|
||||
return -1;
|
||||
}
|
||||
} /* option letter okay? */
|
||||
if ((m_nOptOpt = (int)*m_sPlace++) == (int)':' ||
|
||||
!(oli = dStrchr(m_sOptions, m_nOptOpt))) {
|
||||
/*
|
||||
* if the user didn't specify '-' as an option,
|
||||
* assume it means -1.
|
||||
*/
|
||||
if (m_nOptOpt == (int)'-')
|
||||
return (-1);
|
||||
if (!*m_sPlace)
|
||||
++m_nOptInd;
|
||||
if (*m_sOptions != ':' && m_nOptOpt != GO_BAD_CHAR)
|
||||
return GO_INVALID_CHAR;
|
||||
return (GO_BAD_CHAR);
|
||||
}
|
||||
if (*++oli != ':') { /* don't need argument */
|
||||
m_sOptArg = NULL;
|
||||
if (!*m_sPlace)
|
||||
++m_nOptInd;
|
||||
}
|
||||
else { /* need an argument */
|
||||
if (*m_sPlace) /* no white space */
|
||||
m_sOptArg = m_sPlace;
|
||||
else if (nargc <= ++m_nOptInd) { /* no arg */
|
||||
m_sPlace = EMSG;
|
||||
//if (*m_sOptions == ':')
|
||||
return (GO_BAD_ARG);
|
||||
//return (GO_BAD_CHAR);
|
||||
}
|
||||
else /* white space */
|
||||
m_sOptArg = nargv[m_nOptInd];
|
||||
m_sPlace = EMSG;
|
||||
++m_nOptInd;
|
||||
}
|
||||
return (m_nOptOpt); /* dump back option letter */
|
||||
}
|
||||
|
||||
void Getopt::Reset(void)
|
||||
{
|
||||
if (!*m_sPlace) { /* update scanning pointer */
|
||||
if (m_nOptInd >= m_nargc || *(m_sPlace = m_nargv[m_nOptInd]) != '-') {
|
||||
m_sPlace = EMSG;
|
||||
return;
|
||||
}
|
||||
if (m_sPlace[1] && *++m_sPlace == '-') { /* found "--" */
|
||||
++m_nOptInd;
|
||||
m_sPlace = EMSG;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
115
tools/langc/Getopt.h
Executable file
115
tools/langc/Getopt.h
Executable file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
** Slab NG - The Next Generation of Slab
|
||||
** (c) Copyright 2002-2004 Tom Bampton
|
||||
** All Rights Reserved.
|
||||
**
|
||||
** $Id: Getopt.h,v 1.1 2003/10/30 23:55:29 tom Exp $
|
||||
**
|
||||
** Filename: Getopt.h
|
||||
** Author: Tom Bampton
|
||||
** Created: 30/10/2003
|
||||
** Purpose:
|
||||
** Command Line Parser
|
||||
**
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
/// \file Getopt.h
|
||||
/// \brief Header for Getopt
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SLAB_GETOPT_H
|
||||
#define SLAB_GETOPT_H
|
||||
|
||||
#define GO_BAD_CHAR '?'
|
||||
#define GO_BAD_ARG ':'
|
||||
#define GO_INVALID_CHAR '!'
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
/// \brief Command Line Parser
|
||||
///
|
||||
/// Getopt provides a command line parser similar to Unix's getopt()
|
||||
///
|
||||
/// Note that this version of getopt() will not print any messages to
|
||||
/// the terminal, you will need to manage this yourself.
|
||||
///
|
||||
/// Parts of this section have been lifted from the getopt() manual page.
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
class Getopt
|
||||
{
|
||||
private:
|
||||
char *m_sOptions;
|
||||
char *m_sPlace;
|
||||
int m_nargc;
|
||||
char **m_nargv;
|
||||
|
||||
public:
|
||||
/*! \brief Current argv Index
|
||||
*/
|
||||
int m_nOptInd;
|
||||
/*! \brief Current Option
|
||||
*/
|
||||
int m_nOptOpt;
|
||||
/*! \brief Argument to current option if applicable
|
||||
*/
|
||||
char *m_sOptArg;
|
||||
|
||||
/*! \brief Construct a Getopt
|
||||
|
||||
The string tells Getopt what arguments this program takes. It may
|
||||
contain the following elements: individual characters, and characters
|
||||
followed by a colon to indicate an option argument is to follow. For
|
||||
example, an option string "x" recognizes an option ``-x'', and an
|
||||
option string "x:" recognizes an option and argu- ment ``-x argument''.
|
||||
It does not matter to Getopt if a following argument has leading
|
||||
white space.
|
||||
|
||||
\param sOptions Option string
|
||||
\sa getopt(), Reset()
|
||||
*/
|
||||
Getopt(char *sOptions);
|
||||
virtual ~Getopt();
|
||||
|
||||
/*! \brief Parse arguments
|
||||
|
||||
On return from getopt(), m_sOptArg points to an option argument, if it
|
||||
is anticipated, and the variable m_nOptInd contains the index to the
|
||||
next argv argument for a subsequent call to getopt(). The variable
|
||||
m_nOptOpt saves the last known option character returned by getopt().
|
||||
|
||||
The m_nOptInd variable is set to 1, but may be set to another value
|
||||
before a set of calls to getopt() in order to skip over more or less
|
||||
argv entries.
|
||||
|
||||
In order to use getopt() to evaluate multiple sets of arguments, or to
|
||||
evaluate a single set of arguments multiple times, call Reset() before
|
||||
the second and each additional set of calls to getopt()
|
||||
|
||||
The getopt() function returns -1 when the argument list is exhausted,
|
||||
or GO_INVALID_CHAR if a non-recognized option is encountered. You may
|
||||
use m_nOptOpt to find the invalid character, and display a warning. If
|
||||
an option takes an argument, but the user did not supply one on the
|
||||
command line, getopt() returns GO_BAD_ARG. m_nOptOpt will then contain
|
||||
the option, for printing of warning messages. The interpretation of
|
||||
options in the argument list may be cancelled by the option `--'
|
||||
(double dash) which causes getopt() to signal the end of argument
|
||||
processing and return -1. When all options have been processed (i.e.,
|
||||
up to the first non-option argument), getopt() returns -1.
|
||||
|
||||
\param nargc The argc from your main() function
|
||||
\param nargv The argv from your main() function
|
||||
\return -1 on end of processing, the character of the current option
|
||||
or one of the error values as described above.
|
||||
\sa Reset(), Getopt(char *sOptions)
|
||||
*/
|
||||
int getopt(int nargc, char **nargv);
|
||||
/*! \brief Reset getopt() for subsequent calls
|
||||
|
||||
See the description of getopt() for information on Reset()
|
||||
|
||||
\sa getopt()
|
||||
*/
|
||||
void Reset(void);
|
||||
};
|
||||
|
||||
#endif // SLAB_GETOPT_H
|
194
tools/langc/langc.cc
Executable file
194
tools/langc/langc.cc
Executable file
@ -0,0 +1,194 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "platform/event.h"
|
||||
#include "platform/platformAssert.h"
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "math/mathTypes.h"
|
||||
#include "langc/langc.h"
|
||||
|
||||
#include "core/fileStream.h"
|
||||
|
||||
#include "i18n/lang.h"
|
||||
#include "langcomp.h"
|
||||
#include "Getopt.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LangCGame GameObject;
|
||||
|
||||
// FOR SILLY LINK DEPENDANCY. REMOVE THIS AT YOUR PERIL.
|
||||
bool gEditingMission = false;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool initLibraries()
|
||||
{
|
||||
// asserts should be created FIRST
|
||||
PlatformAssert::create();
|
||||
|
||||
_StringTable::create();
|
||||
// ResManager::create();
|
||||
|
||||
Con::init();
|
||||
|
||||
Math::init();
|
||||
Platform::init(); // platform specific initialization
|
||||
return(true);
|
||||
}
|
||||
|
||||
static void shutdownLibraries()
|
||||
{
|
||||
// Purge any resources on the timeout list...
|
||||
// if (ResourceManager)
|
||||
// ResourceManager->purge();
|
||||
|
||||
// shut down
|
||||
Platform::shutdown();
|
||||
Con::shutdown();
|
||||
|
||||
// ResManager::destroy();
|
||||
_StringTable::destroy();
|
||||
|
||||
// asserts should be destroyed LAST
|
||||
PlatformAssert::destroy();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
dPrintf("Usage: langc [options] <filename> <outbasename>\n\n");
|
||||
dPrintf("Where options is one or more of:\n\n");
|
||||
dPrintf(" -l Write Language File -h Write C++ Header\n");
|
||||
dPrintf(" -s Write Script -d Write C++ Defaults\n");
|
||||
dPrintf(" -t Compile a translation -r Write translation file\n");
|
||||
dPrintf(" -e <filename> Specify english file when compiling translations\n");
|
||||
dPrintf("\n");
|
||||
dPrintf(" -S Don't strip leading spaces -T Strip trailing spaces\n");
|
||||
dPrintf(" -I Don't warn for invalid chars -W Don't warn for empty identifiers\n");
|
||||
dPrintf(" -q Quiet mode, no warnings at all\n");
|
||||
dPrintf("\nMore information can be found in the documentation at:\n %s\n", I18N_DOC_URL);
|
||||
}
|
||||
|
||||
S32 LangCGame::main(S32 argc, const char **argv)
|
||||
{
|
||||
S32 i, ch;
|
||||
U32 flags = LCO_WARNNOSTRING;
|
||||
Getopt opts("STIWqhsdlrte:");
|
||||
char *englishFile = NULL;
|
||||
|
||||
if(! initLibraries())
|
||||
return 0;
|
||||
|
||||
while((ch = opts.getopt(argc, (char **)argv)) != -1)
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case 't':
|
||||
// Compile a translation
|
||||
flags |= LCO_COMPILETRANSLATION;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
// Specify english file
|
||||
englishFile = opts.m_sOptArg;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
// Don't strip spaces
|
||||
flags |= LCO_DONTSTRIPSPACES;
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
// Strip trailing space
|
||||
flags |= LCO_STRIPTRAILINGSPACE;
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
// Don't warn for invalid chars
|
||||
flags |= LCO_DONTWARNINVALIDCHAR;
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
// Don't warn for empty identifiers
|
||||
flags &= ~LCO_WARNNOSTRING;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
// Quiet mode, no warnings at all
|
||||
flags |= LCO_NOWARNINGS;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
// Write Header
|
||||
flags |= LCO_WRITEHEADER;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
// Write Script
|
||||
flags |= LCO_WRITESCRIPT;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
// Write C++ Defaults
|
||||
flags |= LCO_WRITECDEFAULTS;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
// Write Lang Table
|
||||
flags |= LCO_WRITELANGTABLE;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
// Write translation
|
||||
flags |= LCO_WRITETRANSLATION;
|
||||
break;
|
||||
|
||||
case GO_BAD_ARG:
|
||||
dPrintf("option %c requires an argument\n", opts.m_nOptOpt);
|
||||
break;
|
||||
|
||||
case GO_INVALID_CHAR:
|
||||
dPrintf("%c is an invalid option\n", opts.m_nOptOpt);
|
||||
break;
|
||||
|
||||
case GO_BAD_CHAR:
|
||||
usage();
|
||||
shutdownLibraries();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
argc -= opts.m_nOptInd;
|
||||
argv += opts.m_nOptInd;
|
||||
|
||||
if(argc < 2)
|
||||
{
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
LangComp c(flags);
|
||||
|
||||
dPrintf("Compiling ... \n");
|
||||
c.Compile(argv[0], argv[1], englishFile);
|
||||
|
||||
shutdownLibraries();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GameReactivate()
|
||||
{
|
||||
}
|
||||
|
||||
void GameDeactivate( bool )
|
||||
{
|
||||
}
|
19
tools/langc/langc.h
Executable file
19
tools/langc/langc.h
Executable file
@ -0,0 +1,19 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _LANGC_H_
|
||||
#define _LANGC_H_
|
||||
|
||||
#include "platform/gameInterface.h"
|
||||
|
||||
#define I18N_DOC_URL "http://tdn.garagegames.com/wiki/TorqueLocalization"
|
||||
|
||||
class LangCGame : public GameInterface
|
||||
{
|
||||
public:
|
||||
S32 main(S32 argc, const char **argv);
|
||||
};
|
||||
|
||||
#endif // _LANGC_H_
|
702
tools/langc/langcomp.cc
Executable file
702
tools/langc/langcomp.cc
Executable file
@ -0,0 +1,702 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "platform/event.h"
|
||||
#include "platform/platformAssert.h"
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "math/mathTypes.h"
|
||||
#include "langc/langc.h"
|
||||
|
||||
#include "core/fileStream.h"
|
||||
|
||||
#include "i18n/lang.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "langcomp.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Simple hash function for ID lookups in translations
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static U32 hashString(const UTF8 *str)
|
||||
{
|
||||
S32 i;
|
||||
U32 h = 0;
|
||||
|
||||
for(i = 0;str[i];i++)
|
||||
{
|
||||
h += (str[i] * i);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// LFileWriter Class
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LFileWriter::LFileWriter(LangFile *langFile) : mLangFile(langFile)
|
||||
{
|
||||
}
|
||||
|
||||
bool LFileWriter::Open(const UTF8 *basename)
|
||||
{
|
||||
UTF8 filename[256];
|
||||
|
||||
GetFilename(basename, filename, sizeof(filename));
|
||||
return mStream.open((const char*)filename, FileStream::Write);
|
||||
}
|
||||
|
||||
void LFileWriter::Close()
|
||||
{
|
||||
mStream.close();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Writer Classes
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class LHeaderWriter : public LFileWriter
|
||||
{
|
||||
public:
|
||||
LHeaderWriter(LangFile *l) : LFileWriter(l)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void GetFilename(const UTF8 *basename, UTF8 *buf, U32 bufsize)
|
||||
{
|
||||
dSprintf(buf, bufsize, "%s.h", basename);
|
||||
}
|
||||
|
||||
virtual void WriteHeader()
|
||||
{
|
||||
mStream.writeLine((U8 *)"// Automatically generated. DO NOT EDIT\n");
|
||||
mStream.writeLine((U8 *)"#ifndef _TGE_I18N_AUTOGEN_H_");
|
||||
mStream.writeLine((U8 *)"#define _TGE_I18N_AUTOGEN_H_\n");
|
||||
}
|
||||
|
||||
virtual void WriteFooter()
|
||||
{
|
||||
UTF8 buf[LCL_MAXSTRINGLENGTH + 4];
|
||||
|
||||
dSprintf(buf, sizeof(buf), "\n#define I18N_NUM_STRINGS\t%d", mLangFile->getNumStrings());
|
||||
mStream.writeLine((U8 *)&buf);
|
||||
|
||||
mStream.writeLine((U8 *)"\n#endif // _TGE_I18N_AUTOGEN_H_");
|
||||
}
|
||||
|
||||
virtual void WriteString(UTF8 *idstr, U32 idnum, UTF8 *str)
|
||||
{
|
||||
UTF8 buf[LCL_MAXSTRINGLENGTH + 4];
|
||||
|
||||
dSprintf(buf, sizeof(buf), "// %s", str);
|
||||
mStream.writeLine((U8 *)&buf);
|
||||
dSprintf(buf, sizeof(buf), "#define %s\t%d", idstr, idnum);
|
||||
mStream.writeLine((U8 *)&buf);
|
||||
}
|
||||
};
|
||||
|
||||
class LScriptWriter : public LFileWriter
|
||||
{
|
||||
public:
|
||||
LScriptWriter(LangFile *l) : LFileWriter(l)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void GetFilename(const UTF8 *basename, UTF8 *buf, U32 bufsize)
|
||||
{
|
||||
dSprintf(buf, bufsize, "%s.cs", basename);
|
||||
}
|
||||
|
||||
virtual void WriteHeader()
|
||||
{
|
||||
mStream.writeLine((U8 *)"// Automatically generated. DO NOT EDIT\n");
|
||||
}
|
||||
|
||||
virtual void WriteFooter()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void WriteString(UTF8 *idstr, U32 idnum, UTF8 *str)
|
||||
{
|
||||
UTF8 buf[LCL_MAXSTRINGLENGTH + 4];
|
||||
|
||||
dSprintf(buf, sizeof(buf), "// %s", str);
|
||||
mStream.writeLine((U8 *)&buf);
|
||||
dSprintf(buf, sizeof(buf), "$%s = %d;", idstr, idnum);
|
||||
mStream.writeLine((U8 *)&buf);
|
||||
}
|
||||
};
|
||||
|
||||
class LDefaultsWriter : public LFileWriter
|
||||
{
|
||||
public:
|
||||
LDefaultsWriter(LangFile *l) : LFileWriter(l)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void GetFilename(const UTF8 *basename, UTF8 *buf, U32 bufsize)
|
||||
{
|
||||
dSprintf(buf, bufsize, "%sDefaults.cc", basename);
|
||||
}
|
||||
|
||||
virtual void WriteHeader()
|
||||
{
|
||||
mStream.writeLine((U8 *)"// Automatically generated. DO NOT EDIT\n");
|
||||
mStream.writeLine((U8 *)"const UTF8 *gI18NDefaultStrings[] =\n{");
|
||||
}
|
||||
|
||||
virtual void WriteFooter()
|
||||
{
|
||||
mStream.writeLine((U8 *)"};");
|
||||
}
|
||||
|
||||
virtual void WriteString(UTF8 *idstr, U32 idnum, UTF8 *str)
|
||||
{
|
||||
UTF8 buf[LCL_MAXSTRINGLENGTH + 4];
|
||||
|
||||
dSprintf(buf, sizeof(buf), "\t// %s = %d", idstr, idnum);
|
||||
mStream.writeLine((U8 *)&buf);
|
||||
dSprintf(buf, sizeof(buf), "\t(const UTF8*)\"%s\",", str);
|
||||
mStream.writeLine((U8 *)&buf);
|
||||
}
|
||||
};
|
||||
|
||||
class LTransWriter : public LFileWriter
|
||||
{
|
||||
public:
|
||||
LTransWriter(LangFile *l) : LFileWriter(l)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void GetFilename(const UTF8 *basename, UTF8 *buf, U32 bufsize)
|
||||
{
|
||||
dSprintf(buf, bufsize, "%s.tran", basename);
|
||||
}
|
||||
|
||||
virtual void WriteHeader()
|
||||
{
|
||||
mStream.writeLine((U8 *)"# Automatically generated.\n");
|
||||
}
|
||||
|
||||
virtual void WriteFooter()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void WriteString(UTF8 *idstr, U32 idnum, UTF8 *str)
|
||||
{
|
||||
UTF8 buf[LCL_MAXSTRINGLENGTH + 4];
|
||||
|
||||
dSprintf(buf, sizeof(buf), "# [%s:%d] %s", idstr, idnum, str);
|
||||
mStream.writeLine((U8 *)&buf);
|
||||
dSprintf(buf, sizeof(buf), "%s=\n", idstr);
|
||||
mStream.writeLine((U8 *)&buf);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// LString Class
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LString::LString(UTF8 *i /* = NULL */, UTF8 *s /* = NULL */, UTF8 *sclean /* = NULL */) : str(NULL), strclean(NULL), id(NULL)
|
||||
{
|
||||
if(s)
|
||||
{
|
||||
str = new UTF8 [dStrlen(s) + 1];
|
||||
dStrcpy(str, s);
|
||||
}
|
||||
|
||||
if(sclean)
|
||||
{
|
||||
strclean = new UTF8 [dStrlen(sclean) + 1];
|
||||
dStrcpy(strclean, sclean);
|
||||
}
|
||||
|
||||
if(i)
|
||||
{
|
||||
id = new UTF8 [dStrlen(i) + 1];
|
||||
dStrcpy(id, i);
|
||||
}
|
||||
}
|
||||
|
||||
LString::~LString()
|
||||
{
|
||||
if(str)
|
||||
delete [] str;
|
||||
if(id)
|
||||
delete [] id;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// LangComp Class
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LangComp::LangComp(U32 options /* = 0L */) : mOptions(options), mLangFile(NULL),
|
||||
mCurrentFilename(NULL), mCurrentLine(0), mNumErrors(0), mNumWarn(0),
|
||||
mTransLookup(LC_ID_LOOKUP_SIZE)
|
||||
{
|
||||
}
|
||||
|
||||
LangComp::~LangComp()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Protected Methods
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void LangComp::Free()
|
||||
{
|
||||
if(mLangFile)
|
||||
{
|
||||
delete mLangFile;
|
||||
mLangFile = NULL;
|
||||
}
|
||||
|
||||
if(mCurrentFilename)
|
||||
{
|
||||
delete [] mCurrentFilename;
|
||||
mCurrentFilename = NULL;
|
||||
}
|
||||
mCurrentLine = 0;
|
||||
|
||||
S32 i;
|
||||
for(i = 0;i < mFileWriters.size();i++)
|
||||
{
|
||||
delete mFileWriters[i];
|
||||
}
|
||||
mFileWriters.empty();
|
||||
}
|
||||
|
||||
void LangComp::Error(const UTF8 *msg, ...)
|
||||
{
|
||||
UTF8 buf[512];
|
||||
va_list va;
|
||||
|
||||
va_start(va, msg);
|
||||
dVsprintf(buf, sizeof(buf), msg, va);
|
||||
va_end(va);
|
||||
|
||||
if(mCurrentFilename)
|
||||
dPrintf("error at %s:%d: %s\n", mCurrentFilename, mCurrentLine, buf);
|
||||
else
|
||||
dPrintf("error: %s\n", buf);
|
||||
|
||||
mNumErrors++;
|
||||
}
|
||||
|
||||
void LangComp::Warn(const UTF8 *msg, ...)
|
||||
{
|
||||
UTF8 buf[512];
|
||||
va_list va;
|
||||
|
||||
if(mOptions & LCO_NOWARNINGS)
|
||||
return;
|
||||
|
||||
va_start(va, msg);
|
||||
dVsprintf(buf, sizeof(buf), msg, va);
|
||||
va_end(va);
|
||||
|
||||
if(mCurrentFilename)
|
||||
dPrintf("warning at %s:%d: %s\n", mCurrentFilename, mCurrentLine, buf);
|
||||
else
|
||||
dPrintf("warning: %s\n", buf);
|
||||
|
||||
mNumWarn++;
|
||||
}
|
||||
|
||||
LString * LangComp::ParseLine(UTF8 *line)
|
||||
{
|
||||
UTF8 *p, id[LCL_MAXIDLENGTH], str[LCL_MAXSTRINGLENGTH];
|
||||
S32 i, warnCount;
|
||||
|
||||
i = dStrlen(line)-1;
|
||||
if(line[i] == '\n') line[i] = 0;
|
||||
i = dStrlen(line)-1;
|
||||
if(line[i] == '\r') line[i] = 0;
|
||||
|
||||
p = line;
|
||||
|
||||
// Allowable comment delimiters: # ; //
|
||||
if(*p == '#' || *p == ';' || (*p == '/' && *(p+1) == '/') || *p == 0)
|
||||
return new LString();
|
||||
|
||||
i = 0;
|
||||
while(*p)
|
||||
{
|
||||
if(*p == '=')
|
||||
break;
|
||||
|
||||
if(i < (sizeof(id)-1))
|
||||
{
|
||||
if(dIsalnum(*p) || *p == '_')
|
||||
{
|
||||
id[i] = *p;
|
||||
i++;
|
||||
}
|
||||
else if(! dIsspace(*p) && ! (mOptions & LCO_DONTWARNINVALIDCHAR))
|
||||
Warn("invalid character ('%c') in identifier ignored", *p);
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
id[i] = 0;
|
||||
p++;
|
||||
|
||||
// Identifiers cannot start with a number
|
||||
if(dIsdigit(id[0]))
|
||||
{
|
||||
Error("identifiers cannot start with a number");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Identifiers must be there
|
||||
if(id[0] == 0)
|
||||
{
|
||||
Error("no identifier");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
bool foundStart = (mOptions & LCO_DONTSTRIPSPACES);
|
||||
while(*p)
|
||||
{
|
||||
if(i < (sizeof(str)-1))
|
||||
{
|
||||
if(!foundStart && ! dIsspace(*p))
|
||||
foundStart = true;
|
||||
|
||||
if(foundStart && i < (sizeof(str)-1))
|
||||
{
|
||||
str[i] = *p;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
str[i] = 0;
|
||||
|
||||
if(mOptions & LCO_STRIPTRAILINGSPACE)
|
||||
{
|
||||
p = dStrchr(str, 0);
|
||||
while(dIsspace(*(--p)))
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
if(mOptions & LCO_WARNNOSTRING && str[0] == 0)
|
||||
{
|
||||
Warn("identifier '%s' is empty", id);
|
||||
}
|
||||
|
||||
UTF8 strbuf[LCL_MAXSTRINGLENGTH];
|
||||
processSlashes(str, strbuf);
|
||||
|
||||
return new LString(id, strbuf, str);
|
||||
}
|
||||
|
||||
void LangComp::WriteString(UTF8 *idstr, U32 idnum, UTF8 *str)
|
||||
{
|
||||
S32 i;
|
||||
|
||||
for(i = 0;i < mFileWriters.size();i++)
|
||||
{
|
||||
mFileWriters[i]->WriteString(idstr, idnum, str);
|
||||
}
|
||||
}
|
||||
|
||||
void LangComp::WriteFileHeader()
|
||||
{
|
||||
S32 i;
|
||||
|
||||
for(i = 0;i < mFileWriters.size();i++)
|
||||
{
|
||||
mFileWriters[i]->WriteHeader();
|
||||
}
|
||||
}
|
||||
|
||||
void LangComp::WriteFileFooter()
|
||||
{
|
||||
S32 i;
|
||||
|
||||
for(i = 0;i < mFileWriters.size();i++)
|
||||
{
|
||||
mFileWriters[i]->WriteFooter();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// [tom, 3/7/2005] There is no buffer size limit here as the size of the buffer
|
||||
// in ParseLine() is the same size as the buffer the string is in. If this function
|
||||
// is ripped for use elsewhere, I suggest adding a buffer size check.
|
||||
UTF8 *LangComp::processSlashes(const UTF8 *string, UTF8 *buffer)
|
||||
{
|
||||
const UTF8 *s = string;
|
||||
UTF8 *d = buffer;
|
||||
|
||||
while(*s)
|
||||
{
|
||||
if(*s == '\\')
|
||||
{
|
||||
s++;
|
||||
switch(*s)
|
||||
{
|
||||
case 'n':
|
||||
*d++ = '\n';
|
||||
s++;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
*d++ = '\r';
|
||||
s++;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
*d++ = '\t';
|
||||
s++;
|
||||
break;
|
||||
|
||||
default:
|
||||
*d++ = *s++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*d++ = *s++;
|
||||
}
|
||||
}
|
||||
*d = 0;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// [tom, 3/17/2005] No buffer check here either, this time out of lazyness.
|
||||
// [tom, 3/17/2005] This function isnt actually used anymore. I'm keeping it
|
||||
// here in case its useful in the future.
|
||||
UTF8 *LangComp::quoteString(const UTF8 *string, UTF8 *buffer)
|
||||
{
|
||||
static struct {
|
||||
unsigned char c;
|
||||
unsigned char q;
|
||||
} quoteTab[]=
|
||||
{
|
||||
{ '\n', 'n' },
|
||||
{ '\r', 'r' },
|
||||
{ '\t', 't' },
|
||||
{ '"', '"' },
|
||||
{ '\'', '\'' },
|
||||
{ '\\', '\\' },
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
const UTF8 *s = string;
|
||||
UTF8 *d = buffer;
|
||||
|
||||
while(*s)
|
||||
{
|
||||
int i;
|
||||
bool rep = false;
|
||||
|
||||
for(i = 0;quoteTab[i].c;i++)
|
||||
{
|
||||
if(*s == quoteTab[i].c)
|
||||
{
|
||||
*d++ = '\\';
|
||||
*d++ = quoteTab[i].q;
|
||||
rep = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!rep)
|
||||
*d++ = *s;
|
||||
|
||||
s++;
|
||||
}
|
||||
*d = 0;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
bool LangComp::AddFileWriter(LFileWriter *lfw, const UTF8 *basename)
|
||||
{
|
||||
if(lfw->Open(basename))
|
||||
{
|
||||
mFileWriters.push_back(lfw);
|
||||
return true;
|
||||
}
|
||||
|
||||
UTF8 buf[256];
|
||||
lfw->GetFilename(basename, buf, sizeof(buf));
|
||||
Warn("Could not open file \"%s\"", buf);
|
||||
|
||||
delete lfw;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Public Methods
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool LangComp::Compile(const UTF8 *filename, const UTF8 *outbasename, const UTF8 *englishTable /* = NULL */)
|
||||
{
|
||||
bool ret = true;
|
||||
UTF8 lsoname[256];
|
||||
|
||||
Free();
|
||||
|
||||
if((mOptions & LCO_COMPILETRANSLATION) && englishTable == NULL)
|
||||
{
|
||||
Error("you must specify the english language file when compiling translations.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(mOptions & LCO_COMPILETRANSLATION)
|
||||
{
|
||||
if(! LoadLangForTranslation(englishTable))
|
||||
{
|
||||
Error("could not load %s", englishTable);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
dSprintf(lsoname, sizeof(lsoname), "%s.lso", outbasename);
|
||||
|
||||
mCurrentFilename = new UTF8 [dStrlen(filename) + 1];
|
||||
dStrcpy(mCurrentFilename, filename);
|
||||
|
||||
mLangFile = new LangFile;
|
||||
|
||||
FileStream fs;
|
||||
if(fs.open(filename, FileStream::Read))
|
||||
{
|
||||
if(mOptions & LCO_WRITEHEADER)
|
||||
AddFileWriter(new LHeaderWriter(mLangFile), outbasename);
|
||||
|
||||
if(mOptions & LCO_WRITESCRIPT)
|
||||
AddFileWriter(new LScriptWriter(mLangFile), outbasename);
|
||||
|
||||
if(mOptions & LCO_WRITECDEFAULTS)
|
||||
AddFileWriter(new LDefaultsWriter(mLangFile), outbasename);
|
||||
|
||||
if(mOptions & LCO_WRITETRANSLATION)
|
||||
AddFileWriter(new LTransWriter(mLangFile), outbasename);
|
||||
|
||||
WriteFileHeader();
|
||||
|
||||
// This buffer must be able to hold the max lengths, the equals, end of line chars and a bit of leeway for spaces
|
||||
UTF8 buf[LCL_MAXIDLENGTH + LCL_MAXSTRINGLENGTH + 28];
|
||||
|
||||
while(fs.getStatus() != Stream::EOS)
|
||||
{
|
||||
mCurrentLine++;
|
||||
fs.readLine((U8 *)&buf[0], sizeof(buf));
|
||||
|
||||
LString *ls;
|
||||
if((ls = ParseLine(buf)) == NULL)
|
||||
break;
|
||||
|
||||
if(ls->id)
|
||||
{
|
||||
U32 idnum;
|
||||
if(mOptions & LCO_COMPILETRANSLATION)
|
||||
{
|
||||
idnum = (U32)mTransLookup.retreive(hashString(ls->id));
|
||||
if(idnum == 0)
|
||||
Warn("id %s does not exist in the english table", ls->id);
|
||||
else
|
||||
idnum--;
|
||||
mLangFile->setString(idnum, ls->str);
|
||||
}
|
||||
else
|
||||
idnum = mLangFile->addString(ls->str);
|
||||
|
||||
WriteString(ls->id, idnum, ls->strclean);
|
||||
}
|
||||
|
||||
delete ls;
|
||||
}
|
||||
|
||||
WriteFileFooter();
|
||||
|
||||
S32 i;
|
||||
for(i = 0;i < mFileWriters.size();i++)
|
||||
{
|
||||
mFileWriters[i]->Close();
|
||||
}
|
||||
|
||||
fs.close();
|
||||
}
|
||||
|
||||
if(mOptions & LCO_WRITELANGTABLE)
|
||||
{
|
||||
if(ret && fs.open(lsoname, FileStream::Write))
|
||||
{
|
||||
mLangFile->save(&fs);
|
||||
fs.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dPrintf("%s - ", lsoname);
|
||||
if(ret)
|
||||
dPrintf("%d string(s), ", mLangFile->getNumStrings());
|
||||
dPrintf("%d error(s), %d warning(s)\n", mNumErrors, mNumWarn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool LangComp::LoadLangForTranslation(const UTF8 *filename)
|
||||
{
|
||||
bool ret = true;
|
||||
FileStream fs;
|
||||
|
||||
UTF8 *fnBak = mCurrentFilename;
|
||||
U32 lineBak = mCurrentLine;
|
||||
|
||||
mCurrentFilename = new UTF8 [dStrlen(filename) + 1];
|
||||
dStrcpy(mCurrentFilename, filename);
|
||||
mCurrentLine = 0;
|
||||
|
||||
if(fs.open(filename, FileStream::Read))
|
||||
{
|
||||
// This buffer must be able to hold the max lengths, the equals, end of line chars and a bit of leeway for spaces
|
||||
UTF8 buf[LCL_MAXIDLENGTH + LCL_MAXSTRINGLENGTH + 28];
|
||||
U32 lastID = 1; // [tom, 4/25/2005] 0 is used as an error indicator
|
||||
|
||||
while(fs.getStatus() != Stream::EOS)
|
||||
{
|
||||
mCurrentLine++;
|
||||
fs.readLine((U8 *)&buf[0], sizeof(buf));
|
||||
|
||||
LString *ls;
|
||||
if((ls = ParseLine(buf)) == NULL)
|
||||
break;
|
||||
|
||||
if(ls->id)
|
||||
{
|
||||
U32 h = hashString(ls->id);
|
||||
mTransLookup.insert((U32 *)lastID, h);
|
||||
lastID++;
|
||||
}
|
||||
|
||||
delete ls;
|
||||
}
|
||||
|
||||
fs.close();
|
||||
}
|
||||
|
||||
delete [] mCurrentFilename;
|
||||
mCurrentFilename = fnBak;
|
||||
mCurrentLine = lineBak;
|
||||
|
||||
return ret;
|
||||
}
|
115
tools/langc/langcomp.h
Executable file
115
tools/langc/langcomp.h
Executable file
@ -0,0 +1,115 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "core/tVector.h"
|
||||
#include "tSimpleHash.h"
|
||||
|
||||
#ifndef _LANGCOMP_H_
|
||||
#define _LANGCOMP_H_
|
||||
|
||||
// Limits
|
||||
#define LCL_MAXIDLENGTH 128 // Maximum ID length
|
||||
#define LCL_MAXSTRINGLENGTH 512 // Maximum string length
|
||||
|
||||
class LFileWriter
|
||||
{
|
||||
protected:
|
||||
FileStream mStream;
|
||||
LangFile *mLangFile;
|
||||
|
||||
public:
|
||||
LFileWriter(LangFile *langFile);
|
||||
|
||||
virtual bool Open(const UTF8 *basename);
|
||||
virtual void Close();
|
||||
|
||||
virtual void GetFilename(const UTF8 *basename, UTF8 *buf, U32 bufsize) = 0;
|
||||
|
||||
virtual void WriteHeader() = 0;
|
||||
virtual void WriteFooter() = 0;
|
||||
|
||||
virtual void WriteString(UTF8 *idstr, U32 idnum, UTF8 *str) = 0;
|
||||
};
|
||||
|
||||
struct LString
|
||||
{
|
||||
UTF8 *str;
|
||||
UTF8 *strclean;
|
||||
UTF8 *id;
|
||||
|
||||
LString(UTF8 *i = NULL, UTF8 *s = NULL, UTF8 *sclean = NULL);
|
||||
virtual ~LString();
|
||||
};
|
||||
|
||||
// [tom, 4/25/2005] This is the size of the SimpleHash table. Its created in
|
||||
// the SimpleHash ctor so there is a trade off here between performance and
|
||||
// memory usage, as the array will always be created. In practice, the memory
|
||||
// usage probably isnt really going to be that horrendous for an empty table.
|
||||
// It works out to 12 bytes multiplied by whatever you set LC_ID_LOOKUP_SIZE to.
|
||||
//
|
||||
// Since SimpleHash doesnt rehash, the optimal size depends entirely on the
|
||||
// amount of strings in the table. starter.fps typically has a few hundred,
|
||||
// whilst the C++ code typically has a few thousand. Compiling translations is
|
||||
// still going to be pretty fast regardless of how bad the performance of
|
||||
// the SparseArry is, so on the whole this comment probably doesnt really matter.
|
||||
#define LC_ID_LOOKUP_SIZE 128
|
||||
|
||||
class LangComp
|
||||
{
|
||||
protected:
|
||||
|
||||
U32 mOptions;
|
||||
|
||||
LangFile *mLangFile;
|
||||
UTF8 *mCurrentFilename;
|
||||
U32 mCurrentLine;
|
||||
|
||||
U32 mNumErrors;
|
||||
U32 mNumWarn;
|
||||
|
||||
Vector<LFileWriter *> mFileWriters;
|
||||
SimpleHash<U32> mTransLookup;
|
||||
|
||||
void Free(void);
|
||||
void Error(const UTF8 *msg, ...);
|
||||
void Warn(const UTF8 *msg, ...);
|
||||
|
||||
LString * ParseLine(UTF8 *line);
|
||||
|
||||
void WriteString(UTF8 *idstr, U32 idnum, UTF8 *str);
|
||||
|
||||
void WriteFileHeader();
|
||||
void WriteFileFooter();
|
||||
|
||||
UTF8 *processSlashes(const UTF8 *string, UTF8 *buffer);
|
||||
UTF8 *quoteString(const UTF8 *string, UTF8 *buffer);
|
||||
|
||||
bool AddFileWriter(LFileWriter *lfw, const UTF8 *basename);
|
||||
|
||||
public:
|
||||
LangComp(U32 options = 0L);
|
||||
virtual ~LangComp();
|
||||
|
||||
bool Compile(const UTF8 *filename, const UTF8 *outbasename, const UTF8 *englishTable = NULL);
|
||||
bool LoadLangForTranslation(const UTF8 *filename);
|
||||
};
|
||||
|
||||
// Option Flags
|
||||
#define LCO_DONTSTRIPSPACES (1L) // Don't strip leading spaces in strings
|
||||
#define LCO_STRIPTRAILINGSPACE (1L << 1) // Strip trailing spaces in strings
|
||||
#define LCO_DONTWARNINVALIDCHAR (1L << 2) // Don't warn for invalid characters
|
||||
#define LCO_WARNNOSTRING (1L << 3) // Warn for empty identifiers
|
||||
#define LCO_NOWARNINGS (1L << 4) // Don't warn at all
|
||||
|
||||
#define LCO_WRITEHEADER (1L << 5) // Write C++ Header file
|
||||
#define LCO_WRITESCRIPT (1L << 6) // Write Script IDs file
|
||||
#define LCO_WRITECDEFAULTS (1L << 7) // Write C++ defaults file
|
||||
#define LCO_WRITECSDEFAULTS (1L << 8) // Write Script defaults file
|
||||
#define LCO_WRITELANGTABLE (1L << 9) // Write Lang Table
|
||||
#define LCO_WRITETRANSLATION (1L << 10) // Write an empty language file for translation
|
||||
|
||||
#define LCO_COMPILETRANSLATION (1L << 11) // Compile a translation file
|
||||
|
||||
#endif // _LANGCOMP_H_
|
140
tools/langc/tSimpleHash.h
Executable file
140
tools/langc/tSimpleHash.h
Executable file
@ -0,0 +1,140 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// [tom, 4/26/2005] This was based on SparseArray ...
|
||||
//
|
||||
// SparseArray deletes the objects contained within it, and so doesnt really
|
||||
// work for our purposes. Although SparseArray is not used anywhere in the
|
||||
// engine, I figured it would be best to copy it and hack the copy rather
|
||||
// then risk anyone's code breaking for no real reason.
|
||||
|
||||
#ifndef _TSIMPLEHASH_H_
|
||||
#define _TSIMPLEHASH_H_
|
||||
|
||||
//Includes
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "platform/platform.h"
|
||||
#endif
|
||||
#ifndef _PLATFORMASSERT_H_
|
||||
#include "platform/platformAssert.h"
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
class SimpleHash
|
||||
{
|
||||
protected:
|
||||
struct Node {
|
||||
T* pObject;
|
||||
U32 key;
|
||||
|
||||
Node* next;
|
||||
};
|
||||
|
||||
protected:
|
||||
U32 mModulus;
|
||||
Node* mSentryTables;
|
||||
|
||||
void clearTables(); // Note: _deletes_ the objects!
|
||||
|
||||
public:
|
||||
SimpleHash(const U32 modulusSize = 64);
|
||||
~SimpleHash();
|
||||
|
||||
void insert(T* pObject, U32 key);
|
||||
T* remove(U32 key);
|
||||
T* retreive(U32 key);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline SimpleHash<T>::SimpleHash(const U32 modulusSize)
|
||||
{
|
||||
AssertFatal(modulusSize > 0, "Error, modulus must be > 0");
|
||||
|
||||
mModulus = modulusSize;
|
||||
mSentryTables = new Node[mModulus];
|
||||
for (U32 i = 0; i < mModulus; i++)
|
||||
mSentryTables[i].next = NULL;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline SimpleHash<T>::~SimpleHash()
|
||||
{
|
||||
clearTables();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void SimpleHash<T>::clearTables()
|
||||
{
|
||||
for (U32 i = 0; i < mModulus; i++) {
|
||||
Node* pProbe = mSentryTables[i].next;
|
||||
while (pProbe != NULL) {
|
||||
Node* pNext = pProbe->next;
|
||||
//delete pProbe->pObject;
|
||||
delete pProbe;
|
||||
pProbe = pNext;
|
||||
}
|
||||
}
|
||||
delete [] mSentryTables;
|
||||
mSentryTables = NULL;
|
||||
mModulus = 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void SimpleHash<T>::insert(T* pObject, U32 key)
|
||||
{
|
||||
U32 insert = key % mModulus;
|
||||
Node* pNew = new Node;
|
||||
pNew->pObject = pObject;
|
||||
pNew->key = key;
|
||||
pNew->next = mSentryTables[insert].next;
|
||||
mSentryTables[insert].next = pNew;
|
||||
|
||||
#ifdef TORQUE_DEBUG
|
||||
Node* probe = pNew->next;
|
||||
while (probe != NULL) {
|
||||
AssertFatal(probe->key != key, "error, duplicate keys in sparse array!");
|
||||
probe = probe->next;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T* SimpleHash<T>::remove(U32 key)
|
||||
{
|
||||
U32 remove = key % mModulus;
|
||||
Node* probe = mSentryTables[remove];
|
||||
while (probe->next != NULL) {
|
||||
if (probe->next->key == key) {
|
||||
Node* remove = probe->next;
|
||||
T* pReturn = remove->pObject;
|
||||
probe->next = remove->next;
|
||||
delete remove;
|
||||
return pReturn;
|
||||
}
|
||||
probe = probe->next;
|
||||
}
|
||||
|
||||
AssertFatal(false, "Key didn't exist in the array!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T* SimpleHash<T>::retreive(U32 key)
|
||||
{
|
||||
U32 retrieve = key % mModulus;
|
||||
Node* probe = &mSentryTables[retrieve];
|
||||
while (probe->next != NULL) {
|
||||
if (probe->next->key == key) {
|
||||
return probe->next->pObject;
|
||||
}
|
||||
probe = probe->next;
|
||||
}
|
||||
|
||||
AssertFatal(false, "Key didn't exist in the array!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif //_TSIMPLEHASH_H_
|
||||
|
Reference in New Issue
Block a user