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 FieldVisitor::VisitRecordType(clang::RecordType *rt) { if ( debug_level >= 3 ) { std::cout << "FieldVisitor VisitRecordType" << std::endl ; rt->dump() ; } /* String types are typed as records but we treat them differently. The attributes type is set to TRICK_STRING instead of TRICK_STRUCTURE. The type is set to std::string. We can return false here to stop processing of this type. */ std::string type_name = rt->getDecl()->getQualifiedNameAsString() ; if ( ! type_name.compare("std::basic_string") || !type_name.compare("std::__1::basic_string") || ! type_name.compare("std::__cxx11::basic_string") ) { fdes->setEnumString("TRICK_STRING") ; fdes->setTypeName("std::string") ; return false ; } std::string tst_string = rt->desugar().getAsString() ; // remove class keyword if it exists size_t pos ; while ((pos = tst_string.find("class ")) != std::string::npos ) { tst_string.erase(pos , 6) ; } while ((pos = tst_string.find("struct ")) != std::string::npos ) { tst_string.erase(pos , 7) ; } // clang changes bool to _Bool. We need to change it back if ((pos = tst_string.find("<_Bool")) != std::string::npos ) { tst_string.replace(pos , 6, "<bool") ; } while ((pos = tst_string.find(" _Bool")) != std::string::npos ) { tst_string.replace(pos , 6, " bool") ; } // NOTE: clang also changes FILE * to struct _SFILE *. We may need to change that too. // Test if we have some type from std. if (!tst_string.compare( 0 , 5 , "std::")) { // If we have some type from std, figure out if it is one we support. for ( std::map<std::string, bool>::iterator it = stl_classes.begin() ; it != stl_classes.end() ; it++ ) { /* Mark STL types that are not strings and exit */ if (!tst_string.compare( 0 , (*it).first.size() , (*it).first)) { fdes->setEnumString("TRICK_STL") ; fdes->setSTL(true) ; fdes->setTypeName(tst_string) ; fdes->setSTLClear((*it).second) ; // set the type name to the non canonical name, the name the user put in the header file // The typename is not used by STL variables, and it is nice to see the type that was // actually inputted by the user fdes->setMangledTypeName(fdes->getNonCanonicalTypeName()) ; return false ; } } } /* Template specialization types will be processed here because the canonical type will be typed as a record. We test if we have a template specialization type. If so process the template type and return */ clang::RecordDecl * rd = rt->getDecl()->getDefinition() ; if ( rd != NULL and clang::ClassTemplateSpecializationDecl::classof(rd) ) { if ( debug_level >= 3 ) { rd->dump() ; std::cout << " tst_string = " << tst_string << std::endl ; std::cout << " rd is_a_template_specialization = " << clang::ClassTemplateSpecializationDecl::classof(rd) << std::endl ; } return ProcessTemplate(tst_string, clang::cast<clang::CXXRecordDecl>(rd)) ; } /* Test to see if we have an embedded anonymous struct/union. e.g. SB is anonymous below. struct SA { struct { double d ; } SB ; } ; */ //std::cout << "hasNameForLinkage " << rt->getDecl()->hasNameForLinkage() << std::endl ; if ( rt->getDecl()->hasNameForLinkage() ) { if ( rt->getDecl()->getDeclName() ) { //std::cout << "getDeclName " << type_name << std::endl ; fdes->setTypeName(type_name) ; } else { //std::cout << "getTypedefNameForAnonDecl " << rt->getDecl()->getTypedefNameForAnonDecl() << std::endl ; fdes->setTypeName(rt->getDecl()->getTypedefNameForAnonDecl()->getQualifiedNameAsString()) ; } } else { // io_src code not possible for anonymous struct/unions. Set the I/O to 0 to ignore it. if ( debug_level >= 3 ) { std::cout << "FieldVisitor VisitRecordType found anonymous type, setIO = 0" << std::endl ; } fdes->setIO(0) ; } fdes->setEnumString("TRICK_STRUCTURED") ; fdes->setRecord(true) ; // We have our type, return false to stop processing this AST branch return false; }