dhewm3/neo/TypeInfo/TypeInfoGen.cpp
dhewg 736ec20d4d Untangle the epic precompiled.h mess
Don't include the lazy precompiled.h everywhere, only what's
required for the compilation unit.
platform.h needs to be included instead to provide all essential
defines and types.
All includes use the relative path to the neo or the game
specific root.
Move all idlib related includes from idlib/Lib.h to precompiled.h.
precompiled.h still exists for the MFC stuff in tools/.
Add some missing header guards.
2011-12-19 23:21:47 +01:00

1050 lines
24 KiB
C++

/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "sys/platform.h"
#include "TypeInfo/TypeInfoGen.h"
#define TYPE_INFO_GEN_VERSION "1.0"
/*
================
idTypeInfoGen::idTypeInfoGen
================
*/
idTypeInfoGen::idTypeInfoGen( void ) {
}
/*
================
idTypeInfoGen::~idTypeInfoGen
================
*/
idTypeInfoGen::~idTypeInfoGen( void ) {
constants.DeleteContents( true );
enums.DeleteContents( true );
classes.DeleteContents( true );
}
/*
================
idTypeInfoGen::GetInheritance
================
*/
int idTypeInfoGen::GetInheritance( const char *typeName ) const {
int i;
for ( i = 0; i < classes.Num(); i++ ) {
if ( classes[i]->typeName.Cmp( typeName ) == 0 ) {
if ( classes[i]->superType[0] != '\0' ) {
return 1 + GetInheritance( classes[i]->superType );
}
break;
}
}
return 0;
}
/*
================
idTypeInfoGen::EvaluateIntegerString
================
*/
int idTypeInfoGen::EvaluateIntegerString( const idStr &string ) {
idParser src;
idStr evalString;
if ( string.Find( "::" ) != -1 ) {
return 0;
}
evalString = "$evalint(" + string + ")";
src.LoadMemory( evalString, evalString.Length(), "eval integer" );
return src.ParseInt();
}
/*
================
idTypeInfoGen::EvaluateFloatString
================
*/
float idTypeInfoGen::EvaluateFloatString( const idStr &string ) {
idParser src;
idStr evalString;
if ( string.Find( "::" ) != -1 ) {
return 0.0f;
}
evalString = "$evalfloat(" + string + ")";
src.LoadMemory( evalString, evalString.Length(), "eval float" );
return src.ParseFloat();
}
/*
================
idTypeInfoGen::FindConstant
================
*/
idConstantInfo *idTypeInfoGen::FindConstant( const char *name ) {
int i;
for ( i = 0; i < constants.Num(); i++ ) {
if ( constants[i]->name.Cmp( name ) == 0 ) {
return constants[i];
}
}
return NULL;
}
/*
================
idTypeInfoGen::GetIntegerConstant
================
*/
int idTypeInfoGen::GetIntegerConstant( const char *scope, const char *name, idParser &src ) {
idConstantInfo *constant = FindConstant( idStr( scope ) + name );
if ( constant == NULL ) {
constant = FindConstant( name );
}
if ( constant ) {
return EvaluateIntegerString( constant->value );
}
src.Warning( "unknown value '%s' in constant expression", name );
return 0;
}
/*
================
idTypeInfoGen::GetFloatConstant
================
*/
float idTypeInfoGen::GetFloatConstant( const char *scope, const char *name, idParser &src ) {
idConstantInfo *constant = FindConstant( idStr( scope ) + name );
if ( constant == NULL ) {
constant = FindConstant( name );
}
if ( constant ) {
return EvaluateFloatString( constant->value );
}
src.Warning( "unknown value '%s' in constant expression", name );
return 0;
}
/*
================
idTypeInfoGen::ParseArraySize
================
*/
int idTypeInfoGen::ParseArraySize( const char *scope, idParser &src ) {
idToken token;
idStr sizeString, constantString;
int size, totalSize;
if ( !src.CheckTokenString( "[" ) ) {
return 0;
}
totalSize = 1;
sizeString = "";
while( src.ReadToken( &token ) ) {
if ( token == "]" ) {
if ( sizeString.Length() ) {
size = EvaluateIntegerString( sizeString );
if ( size ) {
totalSize *= size;
}
sizeString = "";
}
if ( !src.CheckTokenString( "[" ) ) {
break;
}
} else if ( token.type == TT_NAME ) {
constantString = token;
while( src.CheckTokenString( "::" ) ) {
src.ExpectTokenType( TT_NAME, 0, &token );
constantString += "::" + token;
}
sizeString += va( "%d", GetIntegerConstant( scope, constantString, src ) );
} else {
sizeString += token;
}
}
return totalSize;
}
/*
================
idTypeInfoGen::ParseConstantValue
================
*/
void idTypeInfoGen::ParseConstantValue( const char *scope, idParser &src, idStr &value ) {
idToken token;
idStr constantString;
int indent = 0;
while( src.ReadToken( &token ) ) {
if ( token == "(" ) {
indent++;
} else if ( token == ")" ) {
indent--;
} else if ( indent == 0 && ( token == ";" || token == "," || token == "}" ) ) {
src.UnreadToken( &token );
break;
} else if ( token.type == TT_NAME ) {
constantString = token;
while( src.CheckTokenString( "::" ) ) {
src.ExpectTokenType( TT_NAME, 0, &token );
constantString += "::" + token;
}
value += va( "%d", GetIntegerConstant( scope, constantString, src ) );
continue;
}
value += token;
}
}
/*
================
idTypeInfoGen::ParseEnumType
================
*/
idEnumTypeInfo *idTypeInfoGen::ParseEnumType( const char *scope, bool isTemplate, bool typeDef, idParser &src ) {
int value;
idToken token;
idEnumTypeInfo *typeInfo;
idEnumValueInfo enumValue;
idStr valueString;
typeInfo = new idEnumTypeInfo;
typeInfo->scope = scope;
typeInfo->isTemplate = isTemplate;
if ( src.CheckTokenType( TT_NAME, 0, &token ) ) {
typeInfo->typeName = token;
typeInfo->unnamed = false;
} else {
sprintf( typeInfo->typeName, "enum_%d", enums.Num() );
typeInfo->unnamed = true;
}
if ( !src.CheckTokenString( "{" ) ) {
src.UnreadToken( &token );
delete typeInfo;
return NULL;
}
value = -1;
while( src.ExpectTokenType( TT_NAME, 0, &token ) ) {
enumValue.name = token;
if ( src.CheckTokenString( "=" ) ) {
idStr valueString;
ParseConstantValue( scope, src, valueString );
if ( valueString.Length() ) {
value = EvaluateIntegerString( valueString );
}
} else {
value++;
}
enumValue.value = value;
typeInfo->values.Append( enumValue );
// add a constant for the enum value
idConstantInfo *constantInfo = new idConstantInfo;
constantInfo->name = scope + enumValue.name;
constantInfo->type = "int";
constantInfo->value = va( "%d", value );
constants.Append( constantInfo );
src.CheckTokenString( "," );
if ( src.CheckTokenString( "}" ) ) {
break;
}
}
if ( typeDef ) {
if ( src.CheckTokenType( TT_NAME, 0, &token ) ) {
typeInfo->typeName = token;
typeInfo->unnamed = false;
}
src.ExpectTokenString( ";" );
}
//common->Printf( "enum %s%s\n", typeInfo->scope.c_str(), typeInfo->typeName.c_str() );
return typeInfo;
}
/*
================
idTypeInfoGen::ParseClassType
================
*/
idClassTypeInfo *idTypeInfoGen::ParseClassType( const char *scope, const char *templateArgs, bool isTemplate, bool typeDef, idParser &src ) {
idToken token;
idClassTypeInfo *typeInfo;
typeInfo = new idClassTypeInfo;
typeInfo->scope = scope;
typeInfo->isTemplate = isTemplate;
if ( src.CheckTokenType( TT_NAME, 0, &token ) ) {
typeInfo->typeName = token + templateArgs;
typeInfo->unnamed = false;
} else {
sprintf( typeInfo->typeName, "class_%d%s", classes.Num(), templateArgs );
typeInfo->unnamed = true;
}
if ( src.CheckTokenString( ":" ) ) {
if ( !src.ExpectTokenType( TT_NAME, 0, &token ) ) {
delete typeInfo;
return NULL;
}
while( token == "public" ||
token == "protected" ||
token == "private" ) {
if ( !src.ExpectTokenType( TT_NAME, 0, &token ) ) {
delete typeInfo;
return NULL;
}
typeInfo->superType = token;
// read template arguments
if ( src.CheckTokenString( "<" ) ) {
int indent = 1;
typeInfo->superType += "< ";
while( src.ReadToken( &token ) ) {
if ( token == "<" ) {
indent++;
} else if ( token == ">" ) {
indent--;
if ( indent == 0 ) {
break;
}
}
typeInfo->superType += token + " ";
}
typeInfo->superType += ">";
}
// check for multiple inheritance
if ( !src.CheckTokenString( "," ) ) {
break;
}
if ( !src.ExpectTokenType( TT_NAME, 0, &token ) ) {
delete typeInfo;
return NULL;
}
src.Warning( "multiple inheritance not supported for '%s%s'", typeInfo->scope.c_str(), typeInfo->typeName.c_str() );
}
}
if ( !src.CheckTokenString( "{" ) ) {
src.UnreadToken( &token );
delete typeInfo;
return NULL;
}
ParseScope( typeInfo->scope + typeInfo->typeName + "::", typeInfo->isTemplate, src, typeInfo );
if ( typeDef ) {
if ( src.CheckTokenType( TT_NAME, 0, &token ) ) {
typeInfo->typeName = token + templateArgs;
typeInfo->unnamed = false;
}
src.ExpectTokenString( ";" );
}
//common->Printf( "class %s%s : %s\n", typeInfo->scope.c_str(), typeInfo->typeName.c_str(), typeInfo->superType.c_str() );
return typeInfo;
}
/*
================
idTypeInfoGen::ParseScope
================
*/
void idTypeInfoGen::ParseScope( const char *scope, bool isTemplate, idParser &src, idClassTypeInfo *typeInfo ) {
int indent;
idToken token;
idClassTypeInfo *classInfo;
idEnumTypeInfo *enumInfo;
idStr varType;
bool isConst = false;
bool isStatic = false;
indent = 1;
while( indent ) {
if ( !src.ReadToken( &token ) ) {
break;
}
if ( token == "{" ) {
do {
if ( token == "{" ) {
indent++;
} else if ( token == "}" ) {
indent--;
}
varType += token + " ";
} while( indent > 1 && src.ReadToken( &token ) );
} else if ( token == "}" ) {
assert( indent == 1 );
indent--;
} else if ( token == "<" ) {
do {
if ( token == "<" ) {
indent++;
} else if ( token == ">" ) {
indent--;
}
varType += token + " ";
} while( indent > 1 && src.ReadToken( &token ) );
} else if ( token == ";" ) {
varType = "";
isConst = false;
isStatic = false;
} else if ( token == "public" || token == "protected" || token == "private" ) {
if ( !src.ExpectTokenString( ":" ) ) {
break;
}
varType = "";
isConst = false;
isStatic = false;
} else if ( token == "friend" ) {
// skip friend classes/methods
while( src.ReadToken( &token ) ) {
if ( token == "{" ) {
indent++;
} else if ( token == "}" ) {
indent--;
if ( indent == 1 ) {
break;
}
} else if ( token == ";" && indent == 1 ) {
break;
}
}
varType = "";
isConst = false;
isStatic = false;
} else if ( token == "template" ) {
varType = "";
if ( src.CheckTokenString( "<" ) ) {
int indent = 1;
varType += "< ";
while( src.ReadToken( &token ) ) {
if ( token == "<" ) {
indent++;
} else if ( token == ">" ) {
indent--;
if ( indent == 0 ) {
break;
}
}
varType += token + " ";
}
varType += ">";
}
if ( src.CheckTokenString( "class" ) ) {
// parse template class
classInfo = ParseClassType( scope, varType, true, false, src );
if ( classInfo ) {
classes.Append( classInfo );
}
} else {
// skip template methods
while( src.ReadToken( &token ) ) {
if ( token == "{" ) {
indent++;
} else if ( token == "}" ) {
indent--;
if ( indent == 1 ) {
break;
}
} else if ( token == ";" && indent == 1 ) {
break;
}
}
}
varType = "";
isConst = false;
isStatic = false;
} else if ( token == "namespace" ) {
// parse namespace
classInfo = ParseClassType( scope, "", isTemplate, false, src );
delete classInfo;
} else if ( token == "class" ) {
// parse class
classInfo = ParseClassType( scope, "", isTemplate, false, src );
if ( classInfo ) {
classes.Append( classInfo );
}
} else if ( token == "struct" ) {
// parse struct
classInfo = ParseClassType( scope, "", isTemplate, false, src );
if ( classInfo ) {
classes.Append( classInfo );
varType = classInfo->scope + classInfo->typeName;
}
} else if ( token == "union" ) {
// parse union
classInfo = ParseClassType( scope, "", isTemplate, false, src );
if ( classInfo ) {
classes.Append( classInfo );
}
} else if ( token == "enum" ) {
// parse enum
enumInfo = ParseEnumType( scope, isTemplate, false, src );
if ( enumInfo ) {
enums.Append( enumInfo );
varType = enumInfo->scope + enumInfo->typeName;
}
} else if ( token == "typedef" ) {
if ( token == "class" ) {
// parse typedef class
classInfo = ParseClassType( scope, "", isTemplate, true, src );
if ( classInfo ) {
classes.Append( classInfo );
}
} else if ( src.CheckTokenString( "struct" ) ) {
// parse typedef struct
classInfo = ParseClassType( scope, "", isTemplate, true, src );
if ( classInfo ) {
classes.Append( classInfo );
}
} else if ( src.CheckTokenString( "union" ) ) {
// parse typedef union
classInfo = ParseClassType( scope, "", isTemplate, true, src );
if ( classInfo ) {
classes.Append( classInfo );
}
} else if ( src.CheckTokenString( "enum" ) ) {
// parse typedef enum
enumInfo = ParseEnumType( scope, isTemplate, true, src );
if ( enumInfo ) {
enums.Append( enumInfo );
}
} else {
// skip other typedefs
while( src.ReadToken( &token ) ) {
if ( token == "{" ) {
indent++;
} else if ( token == "}" ) {
indent--;
} else if ( token == ";" && indent == 1 ) {
break;
}
}
}
varType = "";
isConst = false;
isStatic = false;
} else if ( token == "const" ) {
varType += token + " ";
isConst = true;
} else if ( token == "static" ) {
varType += token + " ";
isStatic = true;
} else if ( token.type == TT_NAME ) {
assert( indent == 1 );
// if this is a class operator
if ( token == "operator" ) {
while( src.ReadToken( &token ) ) {
if ( token == "(" ) {
src.UnreadToken( &token );
break;
}
}
}
// if this is a class method
if ( src.CheckTokenString( "(" ) ) {
indent++;
while( indent > 1 && src.ReadToken( &token ) ) {
if ( token == "(" ) {
indent++;
} else if ( token == ")" ) {
indent--;
}
}
if ( src.CheckTokenString( "(" ) ) {
indent++;
while( indent > 1 && src.ReadToken( &token ) ) {
if ( token == "(" ) {
indent++;
} else if ( token == ")" ) {
indent--;
}
}
}
if ( src.CheckTokenString( "const" ) ) {
}
if ( src.CheckTokenString( "=" ) ) {
src.ExpectTokenString( "0" );
} else if ( src.CheckTokenString( "{" ) ) {
indent++;
while( indent > 1 && src.ReadToken( &token ) ) {
if ( token == "{" ) {
indent++;
} else if ( token == "}" ) {
indent--;
}
}
}
varType = "";
isConst = false;
isStatic = false;
} else if ( ( isStatic || isConst ) && src.CheckTokenString( "=" ) ) {
// constant
idConstantInfo *constantInfo = new idConstantInfo;
constantInfo->name = scope + token;
constantInfo->type = varType;
constantInfo->type.StripTrailing( ' ' );
ParseConstantValue( scope, src, constantInfo->value );
constants.Append( constantInfo );
} else if ( isStatic ) {
// static class variable
varType += token + " ";
} else {
// check for class variables
while( 1 ) {
int arraySize = ParseArraySize( scope, src );
if ( arraySize ) {
idClassVariableInfo var;
var.name = token;
var.type = varType;
var.type.StripTrailing( ' ' );
var.type += va( "[%d]", arraySize );
var.bits = 0;
typeInfo->variables.Append( var );
if ( !src.CheckTokenString( "," ) ) {
varType = "";
isConst = false;
isStatic = false;
break;
}
varType.StripTrailing( "* " );
} else {
int bits = 0;
if ( src.CheckTokenString( ":" ) ) {
idToken bitSize;
src.ExpectTokenType( TT_NUMBER, TT_INTEGER, &bitSize );
bits = bitSize.GetIntValue();
}
if ( src.CheckTokenString( "," ) ) {
idClassVariableInfo var;
var.name = token;
var.type = varType;
var.type.StripTrailing( ' ' );
var.bits = bits;
typeInfo->variables.Append( var );
varType.StripTrailing( "* " );
} else if ( src.CheckTokenString( ";" ) ) {
idClassVariableInfo var;
var.name = token;
var.type = varType;
var.type.StripTrailing( ' ' );
var.bits = bits;
typeInfo->variables.Append( var );
varType = "";
isConst = false;
isStatic = false;
break;
} else {
varType += token + " ";
break;
}
}
while( src.CheckTokenString( "*" ) ) {
varType += "* ";
}
if ( !src.ExpectTokenType( TT_NAME, 0, &token ) ) {
break;
}
}
}
} else {
varType += token + " ";
}
}
}
/*
================
idTypeInfoGen::AddDefine
================
*/
void idTypeInfoGen::AddDefine( const char *define ) {
defines.Append( define );
}
/*
================
idTypeInfoGen::CreateTypeInfo
================
*/
void idTypeInfoGen::CreateTypeInfo( const char *path ) {
int i, j, inheritance;
idStr fileName;
idFileList *files;
idParser src;
common->Printf( "Type Info Generator v"TYPE_INFO_GEN_VERSION" (c) 2004 id Software\n" );
common->Printf( "%s\n", path );
files = fileSystem->ListFilesTree( path, ".cpp" );
for ( i = 0; i < files->GetNumFiles(); i++ ) {
fileName = fileSystem->RelativePathToOSPath( files->GetFile( i ) );
common->Printf( "processing '%s' for type info...\n", fileName.c_str() );
if ( !src.LoadFile( fileName, true ) ) {
common->Warning( "couldn't load %s", fileName.c_str() );
continue;
}
src.SetFlags( LEXFL_NOBASEINCLUDES );
for ( j = 0; j < defines.Num(); j++ ) {
src.AddDefine( defines[j] );
}
idClassTypeInfo *typeInfo = new idClassTypeInfo;
ParseScope( "", false, src, typeInfo );
delete typeInfo;
src.FreeSource();
break;
}
fileSystem->FreeFileList( files );
numTemplates = 0;
for ( i = 0; i < classes.Num(); i++ ) {
if ( classes[i]->isTemplate ) {
numTemplates++;
}
}
maxInheritance = 0;
maxInheritanceClass = "";
for ( i = 0; i < classes.Num(); i++ ) {
inheritance = GetInheritance( classes[i]->typeName );
if ( inheritance > maxInheritance ) {
maxInheritance = inheritance;
maxInheritanceClass = classes[i]->typeName;
}
}
common->Printf( "%d constants\n", constants.Num() );
common->Printf( "%d enums\n", enums.Num() );
common->Printf( "%d classes/structs/unions\n", classes.Num() );
common->Printf( "%d templates\n", numTemplates );
common->Printf( "%d max inheritance level for '%s'\n", maxInheritance, maxInheritanceClass.c_str() );
}
/*
================
CleanName
================
*/
void CleanName( idStr &name ) {
name.Replace( "::", "_" );
name.Replace( " , ", "_" );
name.Replace( "< ", "_" );
name.Replace( " >", "_" );
name.Replace( " ", "_" );
}
/*
================
idTypeInfoGen::WriteTypeInfo
================
*/
void idTypeInfoGen::WriteTypeInfo( const char *fileName ) const {
int i, j;
idStr path, define;
idFile *file;
path = fileSystem->RelativePathToOSPath( fileName );
file = fileSystem->OpenExplicitFileWrite( path );
if ( !file ) {
common->Warning( "couldn't open %s", path.c_str() );
return;
}
common->Printf( "writing %s...\n", path.c_str() );
path.ExtractFileName( define );
define.Replace( ".", "_" );
define.ToUpper();
file->WriteFloatString(
"\n"
"#ifndef __%s__\n"
"#define __%s__\n"
"\n"
"/*\n"
"===================================================================================\n"
"\n"
"\tThis file has been generated with the Type Info Generator v"TYPE_INFO_GEN_VERSION" (c) 2004 id Software\n"
"\n"
"\t%d constants\n"
"\t%d enums\n"
"\t%d classes/structs/unions\n"
"\t%d templates\n"
"\t%d max inheritance level for '%s'\n"
"\n"
"===================================================================================\n"
"*/\n"
"\n", define.c_str(), define.c_str(), constants.Num(), enums.Num(), classes.Num(),
numTemplates, maxInheritance, maxInheritanceClass.c_str() );
file->WriteFloatString(
"typedef struct {\n"
"\t" "const char * name;\n"
"\t" "const char * type;\n"
"\t" "const char * value;\n"
"} constantInfo_t;\n"
"\n"
"typedef struct {\n"
"\t" "const char * name;\n"
"\t" "int value;\n"
"} enumValueInfo_t;\n"
"\n"
"typedef struct {\n"
"\t" "const char * typeName;\n"
"\t" "const enumValueInfo_t * values;\n"
"} enumTypeInfo_t;\n"
"\n"
"typedef struct {\n"
"\t" "const char * type;\n"
"\t" "const char * name;\n"
"\t" "int offset;\n"
"\t" "int size;\n"
"} classVariableInfo_t;\n"
"\n"
"typedef struct {\n"
"\t" "const char * typeName;\n"
"\t" "const char * superType;\n"
"\t" "int size;\n"
"\t" "const classVariableInfo_t * variables;\n"
"} classTypeInfo_t;\n"
"\n" );
// constants
file->WriteFloatString( "static constantInfo_t constantInfo[] = {\n" );
for ( i = 0; i < constants.Num(); i++ ) {
idConstantInfo *info = constants[i];
file->WriteFloatString( "\t{ \"%s\", \"%s\", \"%s\" },\n", info->type.c_str(), info->name.c_str(), info->value.c_str() );
}
file->WriteFloatString( "\t{ NULL, NULL, NULL }\n" );
file->WriteFloatString( "};\n\n" );
// enum values
for ( i = 0; i < enums.Num(); i++ ) {
idEnumTypeInfo *info = enums[i];
idStr typeInfoName = info->scope + info->typeName;
CleanName( typeInfoName );
file->WriteFloatString( "static enumValueInfo_t %s_typeInfo[] = {\n", typeInfoName.c_str() );
for ( j = 0; j < info->values.Num(); j++ ) {
if ( info->isTemplate ) {
file->WriteFloatString( "//" );
}
file->WriteFloatString( "\t{ \"%s\", %d },\n", info->values[j].name.c_str(), info->values[j].value );
}
file->WriteFloatString( "\t{ NULL, 0 }\n" );
file->WriteFloatString( "};\n\n" );
}
// enums
file->WriteFloatString( "static enumTypeInfo_t enumTypeInfo[] = {\n" );
for ( i = 0; i < enums.Num(); i++ ) {
idEnumTypeInfo *info = enums[i];
idStr typeName = info->scope + info->typeName;
idStr typeInfoName = typeName;
CleanName( typeInfoName );
if ( info->isTemplate ) {
file->WriteFloatString( "//" );
}
file->WriteFloatString( "\t{ \"%s\", %s_typeInfo },\n", typeName.c_str(), typeInfoName.c_str() );
}
file->WriteFloatString( "\t{ NULL, NULL }\n" );
file->WriteFloatString( "};\n\n" );
// class variables
for ( i = 0; i < classes.Num(); i++ ) {
idClassTypeInfo *info = classes[i];
idStr typeName = info->scope + info->typeName;
idStr typeInfoName = typeName;
CleanName( typeInfoName );
file->WriteFloatString( "static classVariableInfo_t %s_typeInfo[] = {\n", typeInfoName.c_str() );
for ( j = 0; j < info->variables.Num(); j++ ) {
const char *varName = info->variables[j].name.c_str();
const char *varType = info->variables[j].type.c_str();
if ( info->unnamed || info->isTemplate || info->variables[j].bits != 0 ) {
file->WriteFloatString( "//" );
}
file->WriteFloatString( "\t{ \"%s\", \"%s\", (int)(&((%s *)0)->%s), sizeof( ((%s *)0)->%s ) },\n",
varType, varName, typeName.c_str(), varName, typeName.c_str(), varName );
}
file->WriteFloatString( "\t{ NULL, 0 }\n" );
file->WriteFloatString( "};\n\n" );
}
// classes
file->WriteFloatString( "static classTypeInfo_t classTypeInfo[] = {\n" );
for ( i = 0; i < classes.Num(); i++ ) {
idClassTypeInfo *info = classes[i];
idStr typeName = info->scope + info->typeName;
idStr typeInfoName = typeName;
CleanName( typeInfoName );
if ( info->unnamed || info->isTemplate ) {
file->WriteFloatString( "//" );
}
file->WriteFloatString( "\t{ \"%s\", \"%s\", sizeof(%s), %s_typeInfo },\n",
typeName.c_str(), info->superType.c_str(), typeName.c_str(), typeInfoName.c_str() );
}
file->WriteFloatString( "\t{ NULL, NULL, 0, NULL }\n" );
file->WriteFloatString( "};\n\n" );
file->WriteFloatString( "#endif /* !__%s__ */\n", define.c_str() );
fileSystem->CloseFile( file );
}