bool csWrappedDocumentNode::ProcessInstrTemplate (NodeProcessingState* state, iDocumentNode* node, const TempString<>& args, bool weak) { TempString<> templateName (args); Template newTempl; size_t templateEnd = templateName.FindFirst (' '); if (templateEnd != (size_t)-1) { // Parse template parameter names Template::Params paramNames; ParseTemplateArguments (templateName.GetData() + templateEnd + 1, paramNames, true); csSet<TempString<>, TempHeapAlloc> dupeCheck; for (size_t i = 0; i < paramNames.GetSize (); i++) { if (dupeCheck.Contains (paramNames[i])) { Report (syntaxErrorSeverity, node, "Duplicate template parameter %s", CS::Quote::Single (paramNames[i].GetData())); return false; } newTempl.paramMap.Push (paramNames[i]); dupeCheck.Add (paramNames[i]); } templateName.Truncate (templateEnd); } if (templateName.IsEmpty()) { Report (syntaxErrorSeverity, node, "%s without name", CS::Quote::Single ("template")); return false; } if (shared->pitokens.Request (templateName) != csInvalidStringID) { Report (syntaxErrorSeverity, node, "Reserved template name %s", CS::Quote::Single (templateName.GetData())); return false; } state->templateName = templateName; state->templ = newTempl; state->templActive = true; state->templWeak = weak; state->templNestLevel = 1; return true; }
void csWrappedDocumentNode::ProcessSingleWrappedNode ( NodeProcessingState* state, iDocumentNode* node) { CS_ASSERT(globalState); if (ProcessTemplate (node, state)) return; if (ProcessStaticIf (state, node)) { // Template invokation has precedence over dropping nodes... TempString<> tokenStr, args; if (SplitNodeValue (node->GetValue(), tokenStr, args)) { Template::Params params; if (!args.IsEmpty()) { ParseTemplateArguments (args, params, false); } InvokeTemplate (tokenStr, node, state, params); } return; } csRefArray<iDocumentNode>& currentWrapper = state->currentWrapper; bool handled = false; if (node->GetType() == CS_NODE_UNKNOWN) { TempString<> replaceScratch; const char* nodeValue = ReplaceEntities (node->GetValue(), replaceScratch); if ((nodeValue != 0) && (*nodeValue == '?') && (*(nodeValue + strlen (nodeValue) - 1) == '?')) { const char* valStart = nodeValue + 1; if ((*valStart == '!') || (*valStart == '#')) { /* Discard PIs beginning with ! and #. This allows comments, e.g. * <?! some comment ?> * The difference to XML comments is that the PI comments do not * appear in the final document after processing, hence are useful * if some PIs themselves are to be commented, but it is undesireable * to have an XML comment in the result. */ return; } while (*valStart == ' ') valStart++; CS_ASSERT (*valStart != 0); size_t valLen = strlen (valStart) - 1; if (valLen == 0) { Report (syntaxErrorSeverity, node, "Empty processing instruction"); } else { while (*(valStart + valLen - 1) == ' ') valLen--; const char* space = strchr (valStart, ' '); /* The rightmost spaces were skipped and don't interest us any more. */ if (space >= valStart + valLen) space = 0; size_t cmdLen; if (space != 0) { cmdLen = space - valStart; } else { cmdLen = valLen; } TempString<> tokenStr; tokenStr.Replace (valStart, cmdLen); csStringID tokenID = shared->pitokens.Request (tokenStr); switch (tokenID) { case csWrappedDocumentNodeFactory::PITOKEN_INCLUDE: if (shared->plugin->do_verbose) { Report (CS_REPORTER_SEVERITY_WARNING, node, "Deprecated syntax, please use %s", CS::Quote::Single ("Include")); } // Fall through case csWrappedDocumentNodeFactory::PITOKEN_INCLUDE_NEW: { bool okay = true; TempString<> filename; const char* space = strchr (valStart, ' '); /* The rightmost spaces were skipped and don't interest us * any more. */ if (space != 0) { filename.Replace (space + 1, valLen - cmdLen - 1); filename.Trim (); } if ((space == 0) || (filename.IsEmpty ())) { Report (syntaxErrorSeverity, node, "%s without filename", CS::Quote::Single ("Include")); okay = false; } if (okay) { ProcessInclude (filename, state, node); } handled = true; } break; case csWrappedDocumentNodeFactory::PITOKEN_TEMPLATE: if (shared->plugin->do_verbose) { Report (CS_REPORTER_SEVERITY_WARNING, node, "Deprecated syntax, please use %s", CS::Quote::Single ("Template")); } // Fall through case csWrappedDocumentNodeFactory::PITOKEN_TEMPLATE_NEW: case csWrappedDocumentNodeFactory::PITOKEN_TEMPLATEWEAK: { TempString<> args (valStart + cmdLen, valLen - cmdLen); args.LTrim(); ProcessInstrTemplate (state, node, args, tokenID == csWrappedDocumentNodeFactory::PITOKEN_TEMPLATEWEAK); handled = true; } break; case csWrappedDocumentNodeFactory::PITOKEN_ENDTEMPLATE: if (shared->plugin->do_verbose) { Report (CS_REPORTER_SEVERITY_WARNING, node, "Deprecated syntax, please use %s", CS::Quote::Single ("Endtemplate")); handled = true; } // Fall through case csWrappedDocumentNodeFactory::PITOKEN_ENDTEMPLATE_NEW: { Report (syntaxErrorSeverity, node, "%s without %s", CS::Quote::Single ("Endtemplate"), CS::Quote::Single ("Template")); // ProcessTemplate() would've handled it otherwise handled = true; } break; case csWrappedDocumentNodeFactory::PITOKEN_GENERATE: { bool okay = true; Template::Params args; if (space != 0) { TempString<> pStr (space + 1, valLen - cmdLen - 1); ParseTemplateArguments (pStr, args, false); } if ((args.GetSize() < 3) || (args.GetSize() > 4)) { okay = false; Report (syntaxErrorSeverity, node, "%s expects 3 or 4 arguments, got %zu", CS::Quote::Single ("Generate"), args.GetSize()); } if (okay) { state->generateVar = args[0]; int start, end, step; char dummy; if (sscanf (args[1], "%d%c", &start, &dummy) != 1) { Report (syntaxErrorSeverity, node, "Argument %s is not an integer", CS::Quote::Single (args[1].GetData())); okay = false; } if (okay && sscanf (args[2], "%d%c", &end, &dummy) != 1) { Report (syntaxErrorSeverity, node, "Argument %s is not an integer", CS::Quote::Single (args[2].GetData())); okay = false; } if (okay) { if (args.GetSize() == 4) { if (sscanf (args[3], "%d%c", &step, &dummy) != 1) { Report (syntaxErrorSeverity, node, "Argument %s is not an integer", CS::Quote::Single (args[3].GetData())); okay = false; } } else { step = (end < start) ? -1 : 1; } } if (okay) { state->generateActive = true; state->generateNestLevel = 1; if (((start > end) && (step >= 0)) || ((end >= start) && (step <= 0))) { Report (syntaxErrorSeverity, node, "Can't reach end value %d starting from %d with step %d", end, start, step); state->generateValid = false; } else { state->generateValid = true; state->generateStart = start; state->generateEnd = end; state->generateStep = step; state->templ = Template(); } } } handled = true; } break; case csWrappedDocumentNodeFactory::PITOKEN_ENDGENERATE: { Report (syntaxErrorSeverity, node, "%s without %s", CS::Quote::Single ("Endgenerate"), CS::Quote::Single ("Generate")); // ProcessTemplate() would've handled it otherwise } break; case csWrappedDocumentNodeFactory::PITOKEN_DEFINE: { TempString<> args (valStart + cmdLen, valLen - cmdLen); args.LTrim(); ProcessDefine (state, node, args); handled = true; } break; case csWrappedDocumentNodeFactory::PITOKEN_UNDEF: { TempString<> args (valStart + cmdLen, valLen - cmdLen); args.LTrim(); ProcessUndef (state, node, args); handled = true; } break; case csWrappedDocumentNodeFactory::PITOKEN_STATIC_IFDEF: case csWrappedDocumentNodeFactory::PITOKEN_STATIC_IFNDEF: { TempString<> args (valStart + cmdLen, valLen - cmdLen); args.LTrim(); ProcessStaticIfDef (state, node, args, tokenID == csWrappedDocumentNodeFactory::PITOKEN_STATIC_IFNDEF); handled = true; } break; case csWrappedDocumentNodeFactory::PITOKEN_STATIC_ELSIFDEF: case csWrappedDocumentNodeFactory::PITOKEN_STATIC_ELSIFNDEF: case csWrappedDocumentNodeFactory::PITOKEN_STATIC_ELSE: case csWrappedDocumentNodeFactory::PITOKEN_STATIC_ENDIF: { Report (syntaxErrorSeverity, node, "%s without %s", CS::Quote::Single (shared->pitokens.Request (tokenID)), CS::Quote::Single ("SIfDef")); // ProcessStaticIf() would've handled it otherwise handled = true; } break; default: { Template::Params params; if (space != 0) { TempString<> pStr (space + 1, valLen - cmdLen - 1); ParseTemplateArguments (pStr, params, false); } if (InvokeTemplate (tokenStr, node, state, params)) { handled = true; } // If it's neither a template nor a recognized command, pass through } } } } } if (!handled) { csRef<iDocumentNode> newWrapper; newWrapper.AttachNew (new csWrappedDocumentNode (this, node, shared, globalState)); currentWrapper.Push (newWrapper); } }
bool csWrappedDocumentNode::ProcessTemplate (iDocumentNode* templNode, NodeProcessingState* state) { if (!(state->templActive || state->generateActive)) return false; Template::Nodes& templNodes = state->templ.nodes; csRef<iDocumentNode> node = templNode; if (node->GetType() == CS_NODE_UNKNOWN) { TempString<> tokenStr, args; if (SplitNodeValue (node->GetValue(), tokenStr, args)) { csStringID tokenID = shared->pitokens.Request (tokenStr); switch (tokenID) { case csWrappedDocumentNodeFactory::PITOKEN_ENDTEMPLATE: if (shared->plugin->do_verbose) { Report (CS_REPORTER_SEVERITY_WARNING, node, "Deprecated syntax, please use %s", CS::Quote::Single ("Endtemplate")); } // Fall through case csWrappedDocumentNodeFactory::PITOKEN_ENDTEMPLATE_NEW: if (!state->generateActive) { state->templNestLevel--; if (state->templNestLevel != 0) templNodes.Push (node); } else templNodes.Push (node); break; case csWrappedDocumentNodeFactory::PITOKEN_TEMPLATE: if (shared->plugin->do_verbose) { Report (CS_REPORTER_SEVERITY_WARNING, node, "Deprecated syntax, please use %s", CS::Quote::Single ("Template")); } // Fall through case csWrappedDocumentNodeFactory::PITOKEN_TEMPLATE_NEW: case csWrappedDocumentNodeFactory::PITOKEN_TEMPLATEWEAK: if (!state->generateActive) state->templNestLevel++; // Fall through default: { Template* templ; if ((!state->generateActive) && (state->templNestLevel == 1) && (templ = globalState->templates.GetElementPointer (tokenStr))) { Template::Params templArgs; ParseTemplateArguments (args, templArgs, false); shared->DebugProcessing ("Invoking template %s\n", tokenStr.GetData()); InvokeTemplate (templ, templArgs, templNodes); } else // Avoid recursion when the template is later invoked if (tokenStr != state->templateName) templNodes.Push (node); } break; case csWrappedDocumentNodeFactory::PITOKEN_GENERATE: if (state->generateActive) state->generateNestLevel++; templNodes.Push (node); break; case csWrappedDocumentNodeFactory::PITOKEN_ENDGENERATE: { if (state->generateActive) { state->generateNestLevel--; if (state->generateNestLevel != 0) templNodes.Push (node); } else templNodes.Push (node); } break; } } } else templNodes.Push (node); if (state->generateActive) { if (state->generateNestLevel == 0) { state->generateActive = false; int start = state->generateStart; int end = state->generateEnd; int step = state->generateStep; Template generateTempl (state->templ); generateTempl.paramMap.Push (state->generateVar); if (state->generateValid) { int v = start; while (true) { if (state->generateStep >= 0) { if (v > end) break; } else { if (v < end) break; } Template::Nodes templatedNodes; Template::Params params; TempString<> s; s << v; params.Push (s); shared->DebugProcessing ("Starting generation\n"); InvokeTemplate (&generateTempl, params, templatedNodes); size_t i; for (i = 0; i < templatedNodes.GetSize (); i++) { ProcessSingleWrappedNode (state, templatedNodes[i]); } v += step; } } } } else { if (state->templNestLevel == 0) { if (!state->templWeak || !globalState->templates.Contains (state->templateName)) globalState->templates.PutUnique (state->templateName, state->templ); state->templActive = false; } } return true; }
/* ================ idTypeInfoTools::WriteVariable_r ================ */ int idTypeInfoTools::WriteVariable_r( const void *varPtr, const char *varName, const char *varType, const char *scope, const char *prefix, const int pointerDepth ) { int i, isPointer, typeSize; idLexer typeSrc; idToken token; idStr typeString, templateArgs; isPointer = 0; typeSize = -1; // create a type string without 'const', 'mutable', 'class', 'struct', 'union' typeSrc.LoadMemory( varType, idStr::Length( varType ), varName ); while( typeSrc.ReadToken( &token ) ) { if ( token != "const" && token != "mutable" && token != "class" && token != "struct" && token != "union" ) { typeString += token + " "; } } typeString.StripTrailing( ' ' ); typeSrc.FreeSource(); // if this is an array if ( typeString[typeString.Length() - 1] == ']' ) { for ( i = typeString.Length(); i > 0 && typeString[i - 1] != '['; i-- ) { } int num = atoi( &typeString[i] ); idStr listVarType = typeString; listVarType.CapLength( i - 1 ); typeSize = 0; for ( i = 0; i < num; i++ ) { idStr listVarName = va( "%s[%d]", varName, i ); int size = WriteVariable_r( varPtr, listVarName, listVarType, scope, prefix, pointerDepth ); typeSize += size; if ( size == -1 ) { break; } varPtr = (void *)( ( (byte *) varPtr ) + size ); } return typeSize; } // if this is a pointer isPointer = 0; for ( i = typeString.Length(); i > 0 && typeString[i - 1] == '*'; i -= 2 ) { if ( varPtr == (void *)0xcdcdcdcd || ( varPtr != NULL && *((unsigned long *)varPtr) == 0xcdcdcdcd ) ) { common->Warning( "%s%s::%s%s references uninitialized memory", prefix, scope, varName, "" ); return typeSize; } if ( varPtr != NULL ) { varPtr = *((void **)varPtr); } isPointer++; } if ( varPtr == NULL ) { Write( varName, varType, scope, prefix, "", "<NULL>", varPtr, 0 ); return sizeof( void * ); } typeSrc.LoadMemory( typeString, typeString.Length(), varName ); if ( !typeSrc.ReadToken( &token ) ) { Write( varName, varType, scope, prefix, "", va( "<unknown type '%s'>", varType ), varPtr, 0 ); return -1; } // get full type while( typeSrc.CheckTokenString( "::" ) ) { idToken newToken; typeSrc.ExpectTokenType( TT_NAME, 0, &newToken ); token += "::" + newToken; } if ( token == "signed" ) { if ( !typeSrc.ReadToken( &token ) ) { Write( varName, varType, scope, prefix, "", va( "<unknown type '%s'>", varType ), varPtr, 0 ); return -1; } if ( token == "char" ) { typeSize = sizeof( signed char ); Write( varName, varType, scope, prefix, "", va( "%d", *((signed char *)varPtr) ), varPtr, typeSize ); } else if ( token == "short" ) { typeSize = sizeof( signed short ); Write( varName, varType, scope, prefix, "", va( "%d", *((signed short *)varPtr) ), varPtr, typeSize ); } else if ( token == "int" ) { typeSize = sizeof( signed int ); Write( varName, varType, scope, prefix, "", va( "%d", *((signed int *)varPtr) ), varPtr, typeSize ); } else if ( token == "long" ) { typeSize = sizeof( signed long ); Write( varName, varType, scope, prefix, "", va( "%ld", *((signed long *)varPtr) ), varPtr, typeSize ); } else { Write( varName, varType, scope, prefix, "", va( "<unknown type '%s'>", varType ), varPtr, 0 ); return -1; } } else if ( token == "unsigned" ) { if ( !typeSrc.ReadToken( &token ) ) { Write( varName, varType, scope, prefix, "", va( "<unknown type '%s'>", varType ), varPtr, 0 ); return -1; } if ( token == "char" ) { typeSize = sizeof( unsigned char ); Write( varName, varType, scope, prefix, "", va( "%d", *((unsigned char *)varPtr) ), varPtr, typeSize ); } else if ( token == "short" ) { typeSize = sizeof( unsigned short ); Write( varName, varType, scope, prefix, "", va( "%d", *((unsigned short *)varPtr) ), varPtr, typeSize ); } else if ( token == "int" ) { typeSize = sizeof( unsigned int ); Write( varName, varType, scope, prefix, "", va( "%d", *((unsigned int *)varPtr) ), varPtr, typeSize ); } else if ( token == "long" ) { typeSize = sizeof( unsigned long ); Write( varName, varType, scope, prefix, "", va( "%lu", *((unsigned long *)varPtr) ), varPtr, typeSize ); } else { Write( varName, varType, scope, prefix, "", va( "<unknown type '%s'>", varType ), varPtr, 0 ); return -1; } } else if ( token == "byte" ) { typeSize = sizeof( byte ); Write( varName, varType, scope, prefix, "", va( "%d", *((byte *)varPtr) ), varPtr, typeSize ); } else if ( token == "word" ) { typeSize = sizeof( word ); Write( varName, varType, scope, prefix, "", va( "%d", *((word *)varPtr) ), varPtr, typeSize ); } else if ( token == "dword" ) { typeSize = sizeof( dword ); Write( varName, varType, scope, prefix, "", va( "%d", *((dword *)varPtr) ), varPtr, typeSize ); } else if ( token == "bool" ) { typeSize = sizeof( bool ); Write( varName, varType, scope, prefix, "", va( "%d", *((bool *)varPtr) ), varPtr, typeSize ); } else if ( token == "char" ) { typeSize = sizeof( char ); Write( varName, varType, scope, prefix, "", va( "%d", *((char *)varPtr) ), varPtr, typeSize ); } else if ( token == "short" ) { typeSize = sizeof( short ); Write( varName, varType, scope, prefix, "", va( "%d", *((short *)varPtr) ), varPtr, typeSize ); } else if ( token == "int" ) { typeSize = sizeof( int ); Write( varName, varType, scope, prefix, "", va( "%d", *((int *)varPtr) ), varPtr, typeSize ); } else if ( token == "long" ) { typeSize = sizeof( long ); Write( varName, varType, scope, prefix, "", va( "%ld", *((long *)varPtr) ), varPtr, typeSize ); } else if ( token == "float" ) { typeSize = sizeof( float ); Write( varName, varType, scope, prefix, "", idStr( *((float *)varPtr) ).c_str(), varPtr, typeSize ); } else if ( token == "double" ) { typeSize = sizeof( double ); Write( varName, varType, scope, prefix, "", idStr( (float)*((double *)varPtr) ).c_str(), varPtr, typeSize ); } else if ( token == "idVec2" ) { typeSize = sizeof( idVec2 ); Write( varName, varType, scope, prefix, "", ((idVec2 *)varPtr)->ToString( 8 ), varPtr, typeSize ); } else if ( token == "idVec3" ) { typeSize = sizeof( idVec3 ); Write( varName, varType, scope, prefix, "", ((idVec3 *)varPtr)->ToString( 8 ), varPtr, typeSize ); } else if ( token == "idVec4" ) { typeSize = sizeof( idVec4 ); Write( varName, varType, scope, prefix, "", ((idVec4 *)varPtr)->ToString( 8 ), varPtr, typeSize ); } else if ( token == "idVec5" ) { typeSize = sizeof( idVec5 ); Write( varName, varType, scope, prefix, "", ((idVec5 *)varPtr)->ToString( 8 ), varPtr, typeSize ); } else if ( token == "idVec6" ) { typeSize = sizeof( idVec6 ); Write( varName, varType, scope, prefix, "", ((idVec6 *)varPtr)->ToString( 8 ), varPtr, typeSize ); } else if ( token == "idVecX" ) { const idVecX *vec = ((idVecX *)varPtr); if ( vec->ToFloatPtr() != NULL ) { Write( varName, varType, scope, prefix, "", vec->ToString( 8 ), vec->ToFloatPtr(), vec->GetSize() * sizeof( float ) ); } else { Write( varName, varType, scope, prefix, "", "<NULL>", varPtr, 0 ); } typeSize = sizeof( idVecX ); } else if ( token == "idMat2" ) { typeSize = sizeof( idMat2 ); Write( varName, varType, scope, prefix, "", ((idMat2 *)varPtr)->ToString( 8 ), varPtr, typeSize ); } else if ( token == "idMat3" ) { typeSize = sizeof( idMat3 ); Write( varName, varType, scope, prefix, "", ((idMat3 *)varPtr)->ToString( 8 ), varPtr, typeSize ); } else if ( token == "idMat4" ) { typeSize = sizeof( idMat4 ); Write( varName, varType, scope, prefix, "", ((idMat4 *)varPtr)->ToString( 8 ), varPtr, typeSize ); } else if ( token == "idMat5" ) { typeSize = sizeof( idMat5 ); Write( varName, varType, scope, prefix, "", ((idMat5 *)varPtr)->ToString( 8 ), varPtr, typeSize ); } else if ( token == "idMat6" ) { typeSize = sizeof( idMat6 ); Write( varName, varType, scope, prefix, "", ((idMat6 *)varPtr)->ToString( 8 ), varPtr, typeSize ); } else if ( token == "idMatX" ) { typeSize = sizeof( idMatX ); const idMatX *mat = ((idMatX *)varPtr); if ( mat->ToFloatPtr() != NULL ) { Write( varName, varType, scope, prefix, "", mat->ToString( 8 ), mat->ToFloatPtr(), mat->GetNumColumns() * mat->GetNumRows() * sizeof( float ) ); } else { Write( varName, varType, scope, prefix, "", "<NULL>", NULL, 0 ); } } else if ( token == "idAngles" ) { typeSize = sizeof( idAngles ); Write( varName, varType, scope, prefix, "", ((idAngles *)varPtr)->ToString( 8 ), varPtr, typeSize ); } else if ( token == "idQuat" ) { typeSize = sizeof( idQuat ); Write( varName, varType, scope, prefix, "", ((idQuat *)varPtr)->ToString( 8 ), varPtr, typeSize ); } else if ( token == "idBounds" ) { typeSize = sizeof( idBounds ); const idBounds *bounds = ((idBounds *)varPtr); if ( bounds->IsCleared() ) { Write( varName, varType, scope, prefix, "", "<cleared>", varPtr, typeSize ); } else { Write( varName, varType, scope, prefix, "", va( "(%s)-(%s)", (*bounds)[0].ToString( 8 ), (*bounds)[1].ToString( 8 ) ), varPtr, typeSize ); } } else if ( token == "idList" ) { idList<int> *list = ((idList<int> *)varPtr); Write( varName, varType, scope, prefix, ".num", va( "%d", list->Num() ), NULL, 0 ); // NOTE: we don't care about the amount of memory allocated //Write( varName, varType, scope, prefix, ".size", va( "%d", list->Size() ), NULL, 0 ); Write( varName, varType, scope, prefix, ".granularity", va( "%d", list->GetGranularity() ), NULL, 0 ); if ( list->Num() && ParseTemplateArguments( typeSrc, templateArgs ) ) { void *listVarPtr = list->Ptr(); for ( i = 0; i < list->Num(); i++ ) { idStr listVarName = va( "%s[%d]", varName, i ); int size = WriteVariable_r( listVarPtr, listVarName, templateArgs, scope, prefix, pointerDepth ); if ( size == -1 ) { break; } listVarPtr = (void *)( ( (byte *) listVarPtr ) + size ); } } typeSize = sizeof( idList<int> ); } else if ( token == "idStaticList" ) { idStaticList<int, 1> *list = ((idStaticList<int, 1> *)varPtr); Write( varName, varType, scope, prefix, ".num", va( "%d", list->Num() ), NULL, 0 ); int totalSize = 0; if ( list->Num() && ParseTemplateArguments( typeSrc, templateArgs ) ) { void *listVarPtr = list->Ptr(); for ( i = 0; i < list->Num(); i++ ) { idStr listVarName = va( "%s[%d]", varName, i ); int size = WriteVariable_r( listVarPtr, listVarName, templateArgs, scope, prefix, pointerDepth ); if ( size == -1 ) { break; } totalSize += size; listVarPtr = (void *)( ( (byte *) listVarPtr ) + size ); } } typeSize = sizeof( int ) + totalSize; } else if ( token == "idLinkList" ) { // FIXME: implement typeSize = sizeof( idLinkList<idEntity> ); Write( varName, varType, scope, prefix, "", va( "<unknown type '%s'>", varType ), NULL, 0 ); } else if ( token == "idStr" ) { typeSize = sizeof( idStr ); const idStr *str = ((idStr *)varPtr); Write( varName, varType, scope, prefix, "", OutputString( str->c_str() ), str->c_str(), str->Length() ); } else if ( token == "idStrList" ) { typeSize = sizeof( idStrList ); const idStrList *list = ((idStrList *)varPtr); if ( list->Num() ) { for ( i = 0; i < list->Num(); i++ ) { Write( varName, varType, scope, prefix, va("[%d]", i ), OutputString( (*list)[i].c_str() ), (*list)[i].c_str(), (*list)[i].Length() ); } } else { Write( varName, varType, scope, prefix, "", "<empty>", NULL, 0 ); } } else if ( token == "idDict" ) { typeSize = sizeof( idDict ); const idDict *dict = ((idDict *)varPtr); if ( dict->GetNumKeyVals() ) { for ( i = 0; i < dict->GetNumKeyVals(); i++ ) { const idKeyValue *kv = dict->GetKeyVal( i ); Write( varName, varType, scope, prefix, va("[%d]", i ), va( "\'%s\' \'%s\'", OutputString( kv->GetKey().c_str() ), OutputString( kv->GetValue().c_str() ) ), NULL, 0 ); } } else { Write( varName, varType, scope, prefix, "", "<empty>", NULL, 0 ); } } else if ( token == "idExtrapolate" ) { const idExtrapolate<float> *interpolate = ((idExtrapolate<float> *)varPtr); Write( varName, varType, scope, prefix, ".extrapolationType", idStr( interpolate->GetExtrapolationType() ).c_str(), &interpolate->extrapolationType, sizeof( interpolate->extrapolationType ) ); Write( varName, varType, scope, prefix, ".startTime", idStr( interpolate->GetStartTime() ).c_str(), &interpolate->startTime, sizeof( interpolate->startTime ) ); Write( varName, varType, scope, prefix, ".duration", idStr( interpolate->GetDuration() ).c_str(), &interpolate->duration, sizeof( interpolate->duration ) ); if ( ParseTemplateArguments( typeSrc, templateArgs ) ) { if ( templateArgs == "int" ) { const idExtrapolate<int> *interpolate = ((idExtrapolate<int> *)varPtr); Write( varName, varType, scope, prefix, ".startValue", idStr( interpolate->GetStartValue() ).c_str(), &interpolate->startValue, sizeof( interpolate->startValue ) ); Write( varName, varType, scope, prefix, ".baseSpeed", idStr( interpolate->GetBaseSpeed() ).c_str(), &interpolate->baseSpeed, sizeof( interpolate->baseSpeed ) ); Write( varName, varType, scope, prefix, ".speed", idStr( interpolate->GetSpeed() ).c_str(), &interpolate->speed, sizeof( interpolate->speed ) ); typeSize = sizeof( idExtrapolate<int> ); } else if ( templateArgs == "float" ) { const idExtrapolate<float> *interpolate = ((idExtrapolate<float> *)varPtr); Write( varName, varType, scope, prefix, ".startValue", idStr( interpolate->GetStartValue() ).c_str(), &interpolate->startValue, sizeof( interpolate->startValue ) ); Write( varName, varType, scope, prefix, ".baseSpeed", idStr( interpolate->GetBaseSpeed() ).c_str(), &interpolate->baseSpeed, sizeof( interpolate->baseSpeed ) ); Write( varName, varType, scope, prefix, ".speed", idStr( interpolate->GetSpeed() ).c_str(), &interpolate->speed, sizeof( interpolate->speed ) ); typeSize = sizeof( idExtrapolate<float> ); } else if ( templateArgs == "idVec3" ) { const idExtrapolate<idVec3> *interpolate = ((idExtrapolate<idVec3> *)varPtr); Write( varName, varType, scope, prefix, ".startValue", interpolate->GetStartValue().ToString( 8 ), &interpolate->startValue, sizeof( interpolate->startValue ) ); Write( varName, varType, scope, prefix, ".baseSpeed", interpolate->GetBaseSpeed().ToString( 8 ), &interpolate->baseSpeed, sizeof( interpolate->baseSpeed ) ); Write( varName, varType, scope, prefix, ".speed", interpolate->GetSpeed().ToString( 8 ), &interpolate->speed, sizeof( interpolate->speed ) ); typeSize = sizeof( idExtrapolate<idVec3> ); } else if ( templateArgs == "idAngles" ) { const idExtrapolate<idAngles> *interpolate = ((idExtrapolate<idAngles> *)varPtr); Write( varName, varType, scope, prefix, ".startValue", interpolate->GetStartValue().ToString( 8 ), &interpolate->startValue, sizeof( interpolate->startValue ) ); Write( varName, varType, scope, prefix, ".baseSpeed", interpolate->GetBaseSpeed().ToString( 8 ), &interpolate->baseSpeed, sizeof( interpolate->baseSpeed ) ); Write( varName, varType, scope, prefix, ".speed", interpolate->GetSpeed().ToString( 8 ), &interpolate->speed, sizeof( interpolate->speed ) ); typeSize = sizeof( idExtrapolate<idAngles> ); } else { Write( varName, varType, scope, prefix, "", va( "<unknown template argument type '%s' for idExtrapolate>", templateArgs.c_str() ), NULL, 0 ); } } } else if ( token == "idInterpolate" ) { const idInterpolate<float> *interpolate = ((idInterpolate<float> *)varPtr); Write( varName, varType, scope, prefix, ".startTime", idStr( interpolate->GetStartTime() ).c_str(), &interpolate->startTime, sizeof( interpolate->startTime ) ); Write( varName, varType, scope, prefix, ".duration", idStr( interpolate->GetDuration() ).c_str(), &interpolate->duration, sizeof( interpolate->duration ) ); if ( ParseTemplateArguments( typeSrc, templateArgs ) ) { if ( templateArgs == "int" ) { const idInterpolate<int> *interpolate = ((idInterpolate<int> *)varPtr); Write( varName, varType, scope, prefix, ".startValue", idStr( interpolate->GetStartValue() ).c_str(), &interpolate->startValue, sizeof( interpolate->startValue ) ); Write( varName, varType, scope, prefix, ".endValue", idStr( interpolate->GetEndValue() ).c_str(), &interpolate->endValue, sizeof( interpolate->endValue ) ); typeSize = sizeof( idInterpolate<int> ); } else if ( templateArgs == "float" ) { const idInterpolate<float> *interpolate = ((idInterpolate<float> *)varPtr); Write( varName, varType, scope, prefix, ".startValue", idStr( interpolate->GetStartValue() ).c_str(), &interpolate->startValue, sizeof( interpolate->startValue ) ); Write( varName, varType, scope, prefix, ".endValue", idStr( interpolate->GetEndValue() ).c_str(), &interpolate->endValue, sizeof( interpolate->endValue ) ); typeSize = sizeof( idInterpolate<float> ); } else { Write( varName, varType, scope, prefix, "", va( "<unknown template argument type '%s' for idInterpolate>", templateArgs.c_str() ), NULL, 0 ); } } } else if ( token == "idInterpolateAccelDecelLinear" ) { const idInterpolateAccelDecelLinear<float> *interpolate = ((idInterpolateAccelDecelLinear<float> *)varPtr); Write( varName, varType, scope, prefix, ".startTime", idStr( interpolate->GetStartTime() ).c_str(), &interpolate->startTime, sizeof( interpolate->startTime ) ); Write( varName, varType, scope, prefix, ".accelTime", idStr( interpolate->GetAcceleration() ).c_str(), &interpolate->accelTime, sizeof( interpolate->accelTime ) ); Write( varName, varType, scope, prefix, ".linearTime", idStr( interpolate->linearTime ).c_str(), &interpolate->linearTime, sizeof( interpolate->linearTime ) ); Write( varName, varType, scope, prefix, ".decelTime", idStr( interpolate->GetDeceleration() ).c_str(), &interpolate->decelTime, sizeof( interpolate->decelTime ) ); if ( ParseTemplateArguments( typeSrc, templateArgs ) ) { if ( templateArgs == "int" ) { const idInterpolateAccelDecelLinear<int> *interpolate = ((idInterpolateAccelDecelLinear<int> *)varPtr); Write( varName, varType, scope, prefix, ".startValue", idStr( interpolate->GetStartValue() ).c_str(), &interpolate->startValue, sizeof( interpolate->startValue ) ); Write( varName, varType, scope, prefix, ".endValue", idStr( interpolate->GetEndValue() ).c_str(), &interpolate->endValue, sizeof( interpolate->endValue ) ); typeSize = sizeof( idInterpolateAccelDecelLinear<int> ); } else if ( templateArgs == "float" ) { const idInterpolateAccelDecelLinear<float> *interpolate = ((idInterpolateAccelDecelLinear<float> *)varPtr); Write( varName, varType, scope, prefix, ".startValue", idStr( interpolate->GetStartValue() ).c_str(), &interpolate->startValue, sizeof( interpolate->startValue ) ); Write( varName, varType, scope, prefix, ".endValue", idStr( interpolate->GetEndValue() ).c_str(), &interpolate->endValue, sizeof( interpolate->endValue ) ); typeSize = sizeof( idInterpolateAccelDecelLinear<float> ); } else { Write( varName, varType, scope, prefix, "", va( "<unknown template argument type '%s' for idInterpolateAccelDecelLinear>", templateArgs.c_str() ), NULL, 0 ); } } } else if ( token == "idInterpolateAccelDecelSine" ) { const idInterpolateAccelDecelSine<float> *interpolate = ((idInterpolateAccelDecelSine<float> *)varPtr); Write( varName, varType, scope, prefix, ".startTime", idStr( interpolate->GetStartTime() ).c_str(), &interpolate->startTime, sizeof( interpolate->startTime ) ); Write( varName, varType, scope, prefix, ".accelTime", idStr( interpolate->GetAcceleration() ).c_str(), &interpolate->accelTime, sizeof( interpolate->accelTime ) ); Write( varName, varType, scope, prefix, ".linearTime", idStr( interpolate->linearTime ).c_str(), &interpolate->linearTime, sizeof( interpolate->linearTime ) ); Write( varName, varType, scope, prefix, ".decelTime", idStr( interpolate->GetDeceleration() ).c_str(), &interpolate->decelTime, sizeof( interpolate->decelTime ) ); if ( ParseTemplateArguments( typeSrc, templateArgs ) ) { if ( templateArgs == "int" ) { const idInterpolateAccelDecelSine<int> *interpolate = ((idInterpolateAccelDecelSine<int> *)varPtr); Write( varName, varType, scope, prefix, ".startValue", idStr( interpolate->GetStartValue() ).c_str(), &interpolate->startValue, sizeof( interpolate->startValue ) ); Write( varName, varType, scope, prefix, ".endValue", idStr( interpolate->GetEndValue() ).c_str(), &interpolate->endValue, sizeof( interpolate->endValue ) ); typeSize = sizeof( idInterpolateAccelDecelSine<int> ); } else if ( templateArgs == "float" ) { const idInterpolateAccelDecelSine<float> *interpolate = ((idInterpolateAccelDecelSine<float> *)varPtr); Write( varName, varType, scope, prefix, ".startValue", idStr( interpolate->GetStartValue() ).c_str(), &interpolate->startValue, sizeof( interpolate->startValue ) ); Write( varName, varType, scope, prefix, ".endValue", idStr( interpolate->GetEndValue() ).c_str(), &interpolate->endValue, sizeof( interpolate->endValue ) ); typeSize = sizeof( idInterpolateAccelDecelSine<float> ); } else { Write( varName, varType, scope, prefix, "", va( "<unknown template argument type '%s' for idInterpolateAccelDecelSine>", templateArgs.c_str() ), NULL, 0 ); } } } else if ( token == "idUserInterface" ) { typeSize = sizeof( idUserInterface ); const idUserInterface *gui = ((idUserInterface *)varPtr); Write( varName, varType, scope, prefix, "", gui->Name(), varPtr, sizeof( varPtr ) ); } else if ( token == "idRenderModel" ) { typeSize = sizeof( idRenderModel ); const idRenderModel *model = ((idRenderModel *)varPtr); Write( varName, varType, scope, prefix, "", model->Name(), varPtr, sizeof( varPtr ) ); } else if ( token == "qhandle_t" ) { typeSize = sizeof( int ); Write( varName, varType, scope, prefix, "", va( "%d", *((int *)varPtr) ), varPtr, typeSize ); } else if ( token == "cmHandle_t" ) { typeSize = sizeof( int ); Write( varName, varType, scope, prefix, "", va( "%d", *((int *)varPtr) ), varPtr, typeSize ); } else if ( token == "idEntityPtr" ) { typeSize = sizeof( idEntityPtr<idEntity> ); const idEntityPtr<idEntity> *entPtr = ((idEntityPtr<idEntity> *)varPtr); if ( entPtr->GetEntity() ) { idEntity *entity = entPtr->GetEntity(); Write( varName, varType, scope, prefix, ".", va( "entity %d: \'%s\'", entity->entityNumber, entity->name.c_str() ), varPtr, typeSize ); } else { Write( varName, varType, scope, prefix, "", "<NULL>", varPtr, typeSize ); } } else if ( token == "idEntity::entityFlags_s" ) { const idEntity::entityFlags_s *flags = ((idEntity::entityFlags_s *)varPtr); Write( varName, varType, scope, prefix, ".notarget", flags->notarget ? "true" : "false", NULL, 0 ); Write( varName, varType, scope, prefix, ".noknockback", flags->noknockback ? "true" : "false", NULL, 0 ); Write( varName, varType, scope, prefix, ".takedamage", flags->takedamage ? "true" : "false", NULL, 0 ); Write( varName, varType, scope, prefix, ".hidden", flags->hidden ? "true" : "false", NULL, 0 ); Write( varName, varType, scope, prefix, ".bindOrientated", flags->bindOrientated ? "true" : "false", NULL, 0 ); Write( varName, varType, scope, prefix, ".solidForTeam", flags->solidForTeam ? "true" : "false", NULL, 0 ); Write( varName, varType, scope, prefix, ".forcePhysicsUpdate", flags->forcePhysicsUpdate ? "true" : "false", NULL, 0 ); Write( varName, varType, scope, prefix, ".selected", flags->selected ? "true" : "false", NULL, 0 ); Write( varName, varType, scope, prefix, ".neverDormant", flags->neverDormant ? "true" : "false", NULL, 0 ); Write( varName, varType, scope, prefix, ".isDormant", flags->isDormant ? "true" : "false", NULL, 0 ); Write( varName, varType, scope, prefix, ".hasAwakened", flags->hasAwakened ? "true" : "false", NULL, 0 ); Write( varName, varType, scope, prefix, ".networkSync", flags->networkSync ? "true" : "false", NULL, 0 ); typeSize = sizeof( idEntity::entityFlags_s ); } else if ( token == "idScriptBool" ) { typeSize = sizeof( idScriptBool ); const idScriptBool *scriptBool = ((idScriptBool *)varPtr); if ( scriptBool->IsLinked() ) { Write( varName, varType, scope, prefix, "", ( *scriptBool != 0 ) ? "true" : "false", varPtr, typeSize ); } else { Write( varName, varType, scope, prefix, "", "<not linked>", varPtr, typeSize ); } } else { const classTypeInfo_t *classTypeInfo = FindClassInfo( scope + ( "::" + token ) ); if ( classTypeInfo == NULL ) { classTypeInfo = FindClassInfo( token ); } if ( classTypeInfo != NULL ) { typeSize = classTypeInfo->size; if ( !isPointer ) { char newPrefix[1024]; idStr::snPrintf( newPrefix, sizeof( newPrefix ), "%s%s::%s.", prefix, scope, varName ); WriteClass_r( varPtr, "", token, token, newPrefix, pointerDepth ); } else if ( token == "idAnim" ) { const idAnim *anim = ((idAnim*)varPtr); Write( varName, varType, scope, prefix, "", anim->Name(), NULL, 0 ); } else if ( token == "idPhysics" ) { const idPhysics *physics = ((idPhysics*)varPtr); Write( varName, varType, scope, prefix, "", physics->GetType()->classname, NULL, 0 ); } else if ( IsSubclassOf( token, "idEntity" ) ) { const idEntity *entity = ((idEntity*)varPtr); Write( varName, varType, scope, prefix, "", va( "entity %d: \'%s\'", entity->entityNumber, entity->name.c_str() ), NULL, 0 ); } else if ( IsSubclassOf( token, "idDecl" ) ) { const idDecl *decl = ((idDecl *)varPtr); Write( varName, varType, scope, prefix, "", decl->GetName(), NULL, 0 ); } else if ( pointerDepth == 0 && ( token == "idAFBody" || token == "idAFTree" || token == "idClipModel" || IsSubclassOf( token, "idAFConstraint" ) ) ) { char newPrefix[1024]; idStr::snPrintf( newPrefix, sizeof( newPrefix ), "%s%s::%s->", prefix, scope, varName ); WriteClass_r( varPtr, "", token, token, newPrefix, pointerDepth + 1 ); } else { Write( varName, varType, scope, prefix, "", va( "<pointer type '%s' not listed>", varType ), NULL, 0 ); return -1; } } else { const enumTypeInfo_t *enumTypeInfo = FindEnumInfo( scope + ( "::" + token ) ); if ( enumTypeInfo == NULL ) { enumTypeInfo = FindEnumInfo( token ); } if ( enumTypeInfo != NULL ) { typeSize = sizeof( int ); // NOTE: assuming sizeof( enum ) is sizeof( int ) for ( i = 0; enumTypeInfo->values[i].name != NULL; i++ ) { if ( *((int *)varPtr) == enumTypeInfo->values[i].value ) { break; } } if ( enumTypeInfo->values[i].name != NULL ) { Write( varName, varType, scope, prefix, "", enumTypeInfo->values[i].name, NULL, 0 ); } else { Write( varName, varType, scope, prefix, "", va( "%d", *((int *)varPtr) ), NULL, 0 ); } } else { Write( varName, varType, scope, prefix, "", va( "<unknown type '%s'>", varType ), NULL, 0 ); return -1; } } } i = 0; do { if ( *((unsigned long *)varPtr) == 0xcdcdcdcd ) { common->Warning( "%s%s::%s%s uses uninitialized memory", prefix, scope, varName, "" ); break; } } while( ++i < typeSize ); if ( isPointer ) { return sizeof( void * ); } return typeSize; }