Game Development Community

dev|Pro Game Development Curriculum

TorqueScript Preprocessor

by Fyodor -bank- Osokin · 01/09/2011 (10:11 pm) · 8 comments

This resource adds Preprocessor into TorqueScript.

Download patch:
T3D11B3 Preprocessor for GIT
T3D11B3 Preprocessor for SVN
Patch should be applied to the clean/stock T3D 1.1 Beta 3 installation.

If you want to implement TS preprocessor into TGE/TGEA/TGB, please follow manual instructions.

Supported:
//OPERATORS (high to low)
// defined
// '(', ')'
// '+', '-' (unary)
// '*', '/'
// '+', '-',
// '!' (unary)
// '!=', '<=', '<', '==', '>', '>='
// &&
// ||
No macros support!

It works really simple - clears the scripts lines which doesn't needed to be parsed, so if you have:

#define SKIP_THIS
#ifdef SKIP_THIS
echo("This should be skipped!");
#endif
echo("This always shown!");
#undef SKIP_THIS
#ifdef SKIP_THIS
echo("This should be visible!");
#endif
Will give output:
This always shown!
This should be visible!

Keep in mind, that defines are kept globally.
E.g. if you have a few scripts like:
1. script1.cs #ifndef SOMETHING .. #endif
2. script2.cs with #define SOMETHING

And you do:
exec("script1.cs");
exec("script2.cs");

The code between #ifndef SOMETHING and #endif will be parsed by compiler.
But if you re-exec first scripts again:
exec("script1.cs");
The part will not be parsed, but anything defined before will be still in memory and active. That's the way of how TS works.

This resource plays nice with Torsion, so you can debug your game without problems.

IMPORTANT NOTICE 1: Don't forget to make a backup of your project before applying changes.

IMPORTANT NOTICE 2: You will need to regenerate projects so the new files are included into solution, or add new files manually.

IMPORTANT NOTICE 3: All changes are wrapped with _dl_script_preprocessor define, so if you go with manual instructions, or not using "Template/Full", be sure you add to preprocessor definitions of you project(s).

Manual instructions:

Download archive: T3D11B3 Preprocessor

Extract (codeBlockPreprocessor.h and codeBlockPreprocessor.cpp) into Engine/sources/console/.

Open: console/codeBlock.cpp
At the top of file where the other includes are, add:
#ifdef _dl_script_preprocessor
#include "console/codeBlockPreprocessor.h"
#endif
At the end of the file add:
#ifdef _dl_script_preprocessor
void CodeBlock::preprocessExec(StringTableEntry fileName, char* script)
{
	CodeBlockPreprocessor::process(script);
}
#endif

Open: console/codeBlock.h
At the end of class declaration before final "};"
Add:
#ifdef _dl_script_preprocessor
   void preprocessExec(StringTableEntry fileName, char* script);
#endif

Open: console/console.cpp
Before function
const char *evaluatef(const char* string, ...)
Paste:
#ifdef _dl_script_preprocessor
const char *evaluate(char* string, bool echo, const char *fileName)
{
   if (echo)
      Con::printf("%s%s", getVariable( "$Con::Prompt" ), string);

   if(fileName)
      fileName = StringTable->insert(fileName);

   CodeBlock *newCodeBlock = new CodeBlock();
   newCodeBlock->preprocessExec(fileName, string);
   return newCodeBlock->compileExec(fileName, string, false, fileName ? -1 : 0);
}
#endif

Few lines down, inside:
const char *evaluatef(const char* string, ...)
Add:
#ifdef _dl_script_preprocessor
   newCodeBlock->preprocessExec(NULL, buffer);
#endif
before the
return newCodeBlock->compileExec(NULL, buffer, false, 0);

Open: console/console.h
After the declaration:
const char *evaluate(const char* string, bool echo = false, const char *fileName = NULL);
Add:
#ifdef _dl_script_preprocessor
   const char *evaluate(char* string, bool echo = false, const char *fileName = NULL);
#endif

Open: console/consoleFunctions.cpp
In definition of console function "compile":
find:
#ifdef TORQUE_DEBUG
   Con::printf("Compiling %s...", scriptFilenameBuffer);
#endif
and few lines up, replace the:
char *script = static_cast<char *>(data);
with:
#ifndef _dl_script_preprocessor
   const char *script = static_cast<const char *>(data);
#else
   char *script = static_cast<char *>(data);
#endif
At the same place, few lines down after:
CodeBlock *code = new CodeBlock();
Add:
#ifdef _dl_script_preprocessor
   code->preprocessExec(scriptFilenameBuffer, script);
#endif
so it comes right before the:
code->compile(nameBuffer, scriptFilenameBuffer, script, overrideNoDSO);

In same file, in definition of console function "exec", before:
newCodeBlock->compileExec(scriptFileName, script, noCalls, 0);
Add:
#ifdef _dl_script_preprocessor
      newCodeBlock->preprocessExec(scriptFileName, script);
#endif
In same function find:
code->compile(nameBuffer, scriptFileName, script);
And add before that line:
#ifdef _dl_script_preprocessor
         code->preprocessExec(scriptFileName, script);
#endif
Again in same function, find:
newCodeBlock->compileExec(name, script, noCalls, 0);
And add before that line:
#ifdef _dl_script_preprocessor
         code->preprocessExec(name, script);
#endif

Open: console/telnetDebugger.cpp
in function:
void TelnetDebugger::evaluateExpression
Find:
const char* result = newCodeBlock->compileExec( NULL, buffer, false, frame );
And before that line add:
#ifdef _dl_script_preprocessor
   newCodeBlock->preprocessExec(NULL, buffer);
#endif

Don't forget to open Templates/Full/buildFiles/config/project.conf
And add
addProjectDefine( '_dl_script_preprocessor' );
so everything you have added actually will be enabled.. Or, remove the defines. It's up to you.

#1
01/09/2011 (10:36 pm)
Ahh, great!!! Finally some decent debugging tools :D
#2
01/10/2011 (3:55 pm)
nice addon, thank!...
#3
01/11/2011 (7:23 am)
thx Bank.
#4
01/12/2011 (11:11 am)
Wow great resrouce - thanks :)
#5
01/13/2011 (4:06 am)
Awesome resource. I was just thinking about something like this yesterday. I had to laugh though when I saw your first example. You got the logic backwards so the output would actually be for:
#define SKIP_THIS
#ifdef SKIP_THIS
echo("This should be skipped!");
#endif
echo("This always shown!");
#undef SKIP_THIS
#ifdef SKIP_THIS
echo("This should be visible!");
#endif
would output:
This should be skipped!
This always shown!

Hopefully everyone will get that, but just in case ;)
#6
02/09/2011 (5:07 am)
Great Job bank .See AfterWorld are working to hard to get the Survival faster .

Cheer Iulian
#7
03/31/2011 (4:35 am)
WARNING:
Looks like there is a bug somewhere in our code. We experience crashes when using pre-processor in scripts.
As soon as we this will get fixed, I'll post an update.
#8
04/11/2011 (2:20 am)
Good news.
Please download an updated codeBlockPreprocessor.h/cpp files and put it over current ones (overwriting).

This update includes:
* FIX preprocessor EndOfLine bug
* FIX/MOD preprocess multi-line comments
* FIX - no more crashes when "#define" is used in scripts (using ArrayObject instead of SimFieldDictionary now)