Exemplo n.º 1
0
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);
  }
}
Exemplo n.º 2
0
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;
}