void
Unparse_Jovial::unparseIfStmt(SgStatement* stmt, SgUnparse_Info& info)
   {
     SgIfStmt* if_stmt = isSgIfStmt(stmt);
     ROSE_ASSERT(if_stmt != NULL);
     ROSE_ASSERT(if_stmt->get_conditional());

  // condition
     curprint("IF (");
     info.set_inConditional();

     SgExprStatement* expressionStatement = isSgExprStatement(if_stmt->get_conditional());
     unparseExpression(expressionStatement->get_expression(), info);

     info.unset_inConditional();
     curprint(") ;");
     unp->cur.insert_newline(1);

  // true body
     ROSE_ASSERT(if_stmt->get_true_body());
     unparseStatement(if_stmt->get_true_body(), info);

  // false body
     if (if_stmt->get_false_body() != NULL) {
        curprint("ELSE");
        unp->cur.insert_newline(1);
        unparseStatement(if_stmt->get_false_body(), info);
     }
   }
示例#2
0
string
Doxygen::getQualifiedPrototype(SgNode *node)
{
    SgClassDeclaration *cd = dynamic_cast<SgClassDeclaration *>(node);
    if (cd) return getProtoName(cd);
    SgUnparse_Info info;
    info.set_SkipSemiColon();
    info.set_SkipFunctionDefinition();
    info.set_forceQualifiedNames();
    info.set_skipCheckAccess();
    info.set_SkipClassSpecifier();
    info.set_SkipInitializer();
    info.set_current_scope(TransformationSupport::getGlobalScope(node));

    string proto = node->unparseToString(&info);
    while (proto[proto.size()-1] == '\n') { /* sometimes the prototype will be unparsed with a newline at the end */
        proto.resize(proto.size()-1);
    }
    return proto;
}
示例#3
0
// DQ (8/14/2007): This function does not make sense for Fortran.
void
UnparseFortran_type::unparseClassType(SgType* type, SgUnparse_Info& info)
{
    // printf ("Inside of UnparserFortran::unparseClassType \n");

    SgClassType* class_type = isSgClassType(type);
    ROSE_ASSERT(class_type != NULL);

    // DQ (10/7/2004): We need to output just the name when isTypeFirstPart == false and isTypeSecondPart == false
    // this allows us to handle: "doubleArray* arrayPtr2 = new doubleArray();"
    if (info.isTypeSecondPart() == false)
    {
        // Fortran is not as complex as C++, so we can, at least for now, skip the name qualification!
        ROSE_ASSERT(class_type != NULL);
        curprint("TYPE ( ");
        curprint(class_type->get_name().str());
        curprint(" ) ");
    }
}
string
FixupTemplateArguments::generate_string_name (SgType* type, SgNode* nodeReferenceToType)
   {
  // DQ (2/11/2017): This function has been added to support debugging.  It is a current problem that
  // the substitution of private types in template arguments with type aliases not containing private 
  // types, is that the typename can be generated to be extremely large (e.g 803+ million characters long).

     SgUnparse_Info* unparseInfoPointer = new SgUnparse_Info();
     ROSE_ASSERT (unparseInfoPointer != NULL);
     unparseInfoPointer->set_outputCompilerGeneratedStatements();

  // Avoid unpasing the class definition when unparseing the type.
     unparseInfoPointer->set_SkipClassDefinition();

  // DQ (5/8/2013): Added specification to skip enum definitions also (see test2012_202.C).
     unparseInfoPointer->set_SkipEnumDefinition();

  // Associate the unparsing of this type with the statement or scope where it occures.
  // This is the key to use in the lookup of the qualified name. But this is the correct key....
  // unparseInfoPointer->set_reference_node_for_qualification(positionStatement);
  // unparseInfoPointer->set_reference_node_for_qualification(currentScope);
     unparseInfoPointer->set_reference_node_for_qualification(nodeReferenceToType);

  // DQ (5/7/2013): A problem with this is that it combines the first and second parts of the 
  // type into a single string (e.g. the array type will include two parts "base_type" <array name> "[index]".
  // When this is combined for types that have two parts (most types don't) the result is an error
  // when the type is unparsed.  It is not clear, but a solution might be for this to be built here
  // as just the 1st part, and let the second part be generated when the array type is unparsed.
  // BTW, the reason why it is computed here is that there may be many nested types that require 
  // name qualifications and so it is required that we save the whole string.  However, name 
  // qualification might only apply to the first part of types.  So we need to investigate this.
  // This is a problem demonstrated in test2013_156.C and test2013_158.C.

  // DQ (5/8/2013): Set the SgUnparse_Info so that only the first part will be unparsed.
     unparseInfoPointer->set_isTypeFirstPart();

  // DQ (8/19/2013): Added specification to skip class specifier (fixes problem with test2013_306.C).
     unparseInfoPointer->set_SkipClassSpecifier();

     string typeNameString = globalUnparseToString(type,unparseInfoPointer);

     return typeNameString;
   }
示例#5
0
string
Doxygen::getProtoName(SgDeclarationStatement *st)
{
    SgScopeStatement *scope;
    if (SgVariableDeclaration* varDeclSt = isSgVariableDeclaration(st))
    {
        // TODO: uncomment SgVariableDeclaration::get_scope removing need for this code
        scope = varDeclSt->get_variables().front()->get_scope();
    }
    else
    {
        scope = st->get_scope();
    }
    if (isSgGlobal(scope))
    {
        return getDeclStmtName(st);
    }
    else
    {
        SgUnparse_Info info;
        info.set_SkipSemiColon();
        info.set_SkipFunctionDefinition();
        info.set_forceQualifiedNames();
        info.set_skipCheckAccess();
        info.set_SkipInitializer();
        info.set_SkipClassSpecifier();
        //AS(091507) In the new version of ROSE global qualifiers are paret of the qualified name of
        //a scope statement. For the documentation work we do not want that and we therefore use string::substr()
        //to trim of  "::" from the front of the qualified name.

        if( scope->get_qualified_name().getString().length() > 2 )
        {
            return scope->get_qualified_name().getString().substr(2)+("::"+getDeclStmtName(st));
        } else {
            return getDeclStmtName(st);

        }

        //return scope->get_qualified_name().str()+("::"+getDeclStmtName(st));
    }
}
示例#6
0
void
UnparseFortran_type::unparseFunctionType(SgType* type, SgUnparse_Info& info)
{
    SgFunctionType* func_type = isSgFunctionType(type);
    ROSE_ASSERT (func_type != NULL);

    SgUnparse_Info ninfo(info);

    // DQ (1/24/2011): The case of a procedure type in Fortran is quite simple.
    // Note that test2011_28.f90 demonstrates an example of this.
    // curprint("procedure()");
    curprint("procedure(), pointer");

#if 0
    int needParen = 0;
    if (ninfo.isReferenceToSomething() || ninfo.isPointerToSomething()) {
        needParen=1;
    }

    // DQ (10/8/2004): Skip output of class definition for return type! C++ standard does not permit
    // a defining declaration within a return type, function parameter, or sizeof expression.
    ninfo.set_SkipClassDefinition();

    if (ninfo.isTypeFirstPart()) {
        if (needParen) {
            ninfo.unset_isReferenceToSomething();
            ninfo.unset_isPointerToSomething();
            unparseType(func_type->get_return_type(), ninfo);
            curprint("(");
        }
        else {
            unparseType(func_type->get_return_type(), ninfo);
        }
    }
    else {
        if (ninfo.isTypeSecondPart()) {
            if (needParen) {
                curprint(")");
                info.unset_isReferenceToSomething();
                info.unset_isPointerToSomething();
            }
            // print the arguments
            SgUnparse_Info ninfo2(info);
            ninfo2.unset_SkipBaseType();
            ninfo2.unset_isTypeSecondPart();
            ninfo2.unset_isTypeFirstPart();

            curprint("(");
            SgTypePtrList::iterator p = func_type->get_arguments().begin();
            while(p != func_type->get_arguments().end())
            {
                // printf ("Output function argument ... \n");
                unparseType(*p, ninfo2);
                p++;
                if (p != func_type->get_arguments().end())
                {
                    curprint(", ");
                }
            }
            curprint(")");
            unparseType(func_type->get_return_type(), info); // catch the 2nd part of the rtype
        }
        else
        {
            ninfo.set_isTypeFirstPart();
            unparseType(func_type, ninfo);
            ninfo.set_isTypeSecondPart();
            unparseType(func_type, ninfo);
        }
    }
#endif

}
示例#7
0
void
UnparseFortran_type::unparsePointerType(SgType* type, SgUnparse_Info& info, bool printAttrs)
{
#if 0
    // printf ("Inside of UnparserFort::unparsePointerType \n");
    // cur << "\n/* Inside of UnparserFort::unparsePointerType */\n";
    curprint ("\n! Inside of UnparserFort::unparsePointerType \n");
#endif

    // DQ (1/16/2011): Note that pointers in fortran are not expressed the same as in C/C++, are are
    // only a part of the type which is managed more directly using attributes in the variable declaration.
    // Not clear that we want to do anything here in the unparser...

    SgPointerType* pointer_type = isSgPointerType(type);
    ROSE_ASSERT(pointer_type != NULL);

#if 0
    /* special cases: ptr to array, int (*p) [10] */
    /*                ptr to function, int (*p)(int) */
    /*                ptr to ptr to .. int (**p) (int) */

    if (isSgReferenceType(pointer_type->get_base_type()) ||
            isSgPointerType(pointer_type->get_base_type()) ||
            isSgArrayType(pointer_type->get_base_type()) ||
            isSgFunctionType(pointer_type->get_base_type()) ||
            isSgMemberFunctionType(pointer_type->get_base_type()) ||
            isSgModifierType(pointer_type->get_base_type()) )
    {
        info.set_isPointerToSomething();
    }

    // If not isTypeFirstPart nor isTypeSecondPart this unparse call
    // is not controlled from the statement level but from the type level

    if (info.isTypeFirstPart() == true)
    {
        unparseType(pointer_type->get_base_type(), info);

        // DQ (9/21/2004): Moved this conditional into this branch (to fix test2004_93.C)
        // DQ (9/21/2004): I think we can assert this, and if so we can simplify the logic below
        ROSE_ASSERT(info.isTypeSecondPart() == false);

        curprint("*");
    }
    else
    {
        if (info.isTypeSecondPart() == true)
        {
            unparseType(pointer_type->get_base_type(), info);
        }
        else
        {
            SgUnparse_Info ninfo(info);
            ninfo.set_isTypeFirstPart();
            unparseType(pointer_type, ninfo);
            ninfo.set_isTypeSecondPart();
            unparseType(pointer_type, ninfo);
        }
    }
#else
    if (info.supressStrippedTypeName() == false)
    {
        // DQ (1/16/2011): We only want to output the name of the stripped type once!
        SgType* stripType = pointer_type->stripType();
        unparseType(stripType, info);
        info.set_supressStrippedTypeName();
    }

    curprint(type->get_isCoArray()? ", COPOINTER": ", POINTER");

    // DQ (1/16/2011): Plus unparse the base type...(unless it will just output the stripped types name).
    if (pointer_type->get_base_type()->containsInternalTypes() == true)
    {
        unparseType(pointer_type->get_base_type(), info, printAttrs);
    }
#endif

#if 0
    // printf ("Leaving of UnparserFort::unparsePointerType \n");
    // cur << "\n/* Leaving of UnparserFort::unparsePointerType */\n";
    curprint ("\n! Leaving UnparserFort::unparsePointerType \n");
#endif
}
示例#8
0
void
UnparseFortran_type::unparseArrayType(SgType* type, SgUnparse_Info& info, bool printDim)
{
    // Examples:
    //   real, dimension(10, 10) :: A1, A2
    //   real, dimension(:) :: B1
    //   character(len=*) :: s1
#if 0
    curprint ("\n! Inside of UnparserFort::unparseArrayType \n");
#endif

    SgArrayType* array_type = isSgArrayType(type);
    ROSE_ASSERT(array_type != NULL);

    // I think that supressStrippedTypeName() and SkipBaseType() are redundant...
    if (info.supressStrippedTypeName() == false)
    {
        // DQ (1/16/2011): We only want to output the name of the stripped type once!
        SgType* stripType = array_type->stripType();
        unparseType(stripType, info);
        info.set_supressStrippedTypeName();
    }

    // DQ (8/5/2010): It is an error to treat an array of char as a string (see test2010_16.f90).
#if 0
    // dimension information
    SgExprListExp* dim = array_type->get_dim_info();

    // if (isCharType(array_type->get_base_type()))
    // if (false && isCharType(array_type->get_base_type()))
    if (isCharType(array_type->get_base_type()))
    {
        // a character type: must be treated specially
        ROSE_ASSERT(array_type->get_rank() == 1);
        curprint("(len=");

        SgExpressionPtrList::iterator it = dim->get_expressions().begin();
        if (it != dim->get_expressions().end())
        {
            SgExpression* expr = *it;
            if (expr->variantT() == V_SgSubscriptExpression)
            {
                // this is a subscript expression but all we want to unparse is the length
                // of the string, which should be the upper bound of the subscript expression
                SgSubscriptExpression* sub_expr = isSgSubscriptExpression(expr);
                ROSE_ASSERT(sub_expr != NULL);

                ROSE_ASSERT(unp != NULL);
                ROSE_ASSERT(unp->u_fortran_locatedNode != NULL);
                unp->u_fortran_locatedNode->unparseExpression(sub_expr->get_upperBound(), info);
            }
            else
            {
                // unparse the entire expression
                ROSE_ASSERT(unp != NULL);
                ROSE_ASSERT(unp->u_fortran_locatedNode != NULL);
                unp->u_fortran_locatedNode->unparseExpression(*it, info);
            }
        }
        else
        {
            curprint("*");
        }
        curprint(")");
    }
    else
    {
        // a non-character type

        // explicit-shape (explicit rank and bounds/extents)
        // assumed-shape (explicit rank; unspecified bounds/extents)
        // deferred-shape (explicit rank; unspecified bounds/extents)
        // assumed-size (explicit ranks, explicit bounds/extents except last dim)
        ROSE_ASSERT(array_type->get_rank() >= 1);
        curprint(", DIMENSION");

        ROSE_ASSERT(unp != NULL);
        ROSE_ASSERT(unp->u_fortran_locatedNode != NULL);
        // unp->u_fortran_locatedNode->unparseExprList(dim, info); // adds parens
        // unp->u_fortran_locatedNode->UnparseLanguageIndependentConstructs::unparseExprList(dim, info); // adds parens

        // curprint("(");
        // curprint( StringUtility::numberToString(array_type->get_rank()) );
        // curprint(")");

        // unp->u_fortran_locatedNode->unparseExpression(array_type->get_dim_info(),info);
        unp->u_fortran_locatedNode->unparseExprList(array_type->get_dim_info(),info,/* output parens */ true);
    }
#else

    if (printDim)
    {
        ROSE_ASSERT(array_type->get_rank() >= 1);
        curprint(array_type->get_isCoArray()? ", CODIMENSION": ", DIMENSION");

        ROSE_ASSERT(unp != NULL);
        ROSE_ASSERT(unp->u_fortran_locatedNode != NULL);

        if (array_type->get_isCoArray())
        {   // print codimension info
            curprint("[");
            unp->u_fortran_locatedNode->unparseExprList(array_type->get_dim_info(),info,/* do not output parens */ false);
            curprint("]");
        }
        else  // print dimension info
            unp->u_fortran_locatedNode->unparseExprList(array_type->get_dim_info(),info,/* output parens */ true);
    }

    // DQ (1/16/2011): Plus unparse the base type...(unless it will just output the stripped types name).
    if (array_type->get_base_type()->containsInternalTypes() == true)
    {
        unparseType(array_type->get_base_type(), info, printDim);
    }
#endif

#if 0
    curprint ("\n! Leaving UnparserFort::unparseArrayType \n");
#endif
}
示例#9
0
void
Unparse_Java::unparseEnumType(SgEnumType* type, SgUnparse_Info& info)
   {
     SgEnumType* enum_type = isSgEnumType(type);
     ROSE_ASSERT(enum_type);

     if (info.isTypeSecondPart() == false)
        {
          SgEnumDeclaration *edecl = isSgEnumDeclaration(enum_type->get_declaration());
          SgClassDefinition *cdefn = NULL;
          SgNamespaceDefinitionStatement* namespaceDefn = NULL;

          ROSE_ASSERT(edecl != NULL);

       // Build reference to any possible enclosing scope represented by a SgClassDefinition or SgNamespaceDefinition
       // to be used check if name qualification is required.
          unp->u_exprStmt->initializeDeclarationsFromParent ( edecl, cdefn, namespaceDefn );

          if (info.isTypeFirstPart() == true && info.SkipEnumDefinition() == false)
             {
               unp->u_exprStmt->unparseAttachedPreprocessingInfo(edecl, info, PreprocessingInfo::before);
             }

          curprint ( "enum ");

          SgNamedType *ptype = NULL;
          if (cdefn != NULL)
             {
               ptype = isSgNamedType(cdefn->get_declaration()->get_type());
             }

          if (SageInterface::is_C_language() == true || SageInterface::is_C99_language() == true)
             {
               curprint ( enum_type->get_name().getString() + " ");
             }
            else
             {
            // DQ (7/20/2011): Test compilation without the generateNameQualifier() functions.
            // The C++ support is more complex and can require qualified names!
            // SgName nameQualifier = unp->u_name->generateNameQualifier( edecl , info );
               SgName nameQualifier;

            // printf ("nameQualifier (from unp->u_name->generateNameQualifier function) = %s \n",nameQualifier.str());
            // curprint ( "\n/* nameQualifier (from unp->u_name->generateNameQualifier function) = " + nameQualifier + " */ \n ";
               curprint ( nameQualifier.str());
               SgName nm = enum_type->get_name();

               if (nm.getString() != "")
                  {
                 // printf ("Output qualifier of current types to the name = %s \n",nm.str());
                    curprint ( nm.getString() + " ");
                  }
             }
        }

     if (info.isTypeFirstPart() == true)
        {
      // info.display("info before constructing ninfo");
         SgUnparse_Info ninfo(info);

      // don't skip the semicolon in the output of the statement in the class definition
         ninfo.unset_SkipSemiColon();

         ninfo.set_isUnsetAccess();

      // printf ("info.SkipEnumDefinition() = %s \n",(info.SkipEnumDefinition() == true) ? "true" : "false");

         if ( info.SkipEnumDefinition() == false)
            {
              SgUnparse_Info ninfo(info);
              ninfo.set_inEnumDecl();
              SgInitializer *tmp_init = NULL;
              SgName tmp_name;

              SgEnumDeclaration *enum_stmt = isSgEnumDeclaration(enum_type->get_declaration());
              ROSE_ASSERT(enum_stmt != NULL);

           // This permits support of the empty enum case! "enum x{};"
              curprint ( "{");

              SgInitializedNamePtrList::iterator p = enum_stmt->get_enumerators().begin();
              if (p != enum_stmt->get_enumerators().end())
                 {
                // curprint ( "{";
                   while (1)
                      {
                        unp->u_exprStmt->unparseAttachedPreprocessingInfo(*p, info, PreprocessingInfo::before);
                        tmp_name=(*p)->get_name();
                        tmp_init=(*p)->get_initializer();
                        curprint ( tmp_name.str());
                        if(tmp_init)
                           {
                             curprint ( "=");
                             unp->u_exprStmt->unparseExpression(tmp_init, ninfo);
                           }
                        p++;
                        if (p != enum_stmt->get_enumerators().end())
                           {
                             curprint ( ",");
                           }
                          else
                             break;
                       }
                 // curprint ( "}";
                  }

            // Putting the "inside" info right here is just a wild guess as to where it might really belong.
               unp->u_exprStmt->unparseAttachedPreprocessingInfo(enum_stmt, info, PreprocessingInfo::inside);

               curprint ( "}");

               unp->u_exprStmt->unparseAttachedPreprocessingInfo(enum_stmt, info, PreprocessingInfo::after);
             }
        }
   }
string
PrefixSuffixGenerationTraversal::DeclarationOrCommentListElement::
generateDeclarationString ( SgDeclarationStatement* declaration ) const
   {
  // This function generates a string for a declaration. The string is required for 
  // the intermediate file to make sure that all transformation code will compile 
  // (since it could depend on declarations defined within the code).

  // Details:
  //   1) Only record declarations found within the source file (exclude all header files 
  //      since they will be seen when the same header files are included).
  //   2) Resort the variable declarations to remove redundent entries.
  //        WRONG: variable declarations could have dependences upon class declarations!
  //   3) Don't sort all declarations since some could have dependences.
  //        a) class declarations
  //        b) typedefs
  //        c) function declarations
  //        d) template declarations
  //        e) variable definition???

      ROSE_ASSERT (this != NULL);
      ROSE_ASSERT ( declaration != NULL );
      string declarationString;

   // Build a SgUnparse_Info object to represent formatting options for
   // this statement (use the default values).
      SgUnparse_Info info;

   // exclude comments
      info.set_SkipComments();

   // exclude all CPP directives (since they have already been evaluated by the front-end)
      info.set_SkipCPPDirectives();

      switch ( declaration->variantT() )
        {
       // Enum declarations should not skip their definition since 
       // this is where the constants are declared.
          case V_SgEnumDeclaration:

          case V_SgVariableDeclaration:
          case V_SgTemplateDeclaration:
          case V_SgTypedefDeclaration:
            // Need to figure out if a forward declaration would work or be 
            // more conservative and always output the complete class definition.

            // turn off output of initializer values
               info.set_SkipInitializer();
            // output the declaration as a string
               declarationString = globalUnparseToString(declaration,&info);
               break;

          case V_SgClassDeclaration:
            // Need to figure out if a forward declaration would work or be 
            // more conservative and always output the complete class definition.

            // turn off the generation of the function definitions only 
            // (we still want the restof the class definition since these 
            // define all member data and member functions).
            // info.set_SkipClassDefinition();
               info.set_SkipFunctionDefinition();
               info.set_AddSemiColonAfterDeclaration();

            // output the declaration as a string
               declarationString = globalUnparseToString(declaration,&info);
               break;

       // For functions just output the declaration and skip the definition
       // (This also avoids the generation of redundent definitions since the 
       // function we are in when we generate all declarations would be included).
          case V_SgMemberFunctionDeclaration:
          case V_SgFunctionDeclaration:
             {
            // turn off the generation of the definition
               info.set_SkipFunctionDefinition();
               info.set_AddSemiColonAfterDeclaration();

            // output the declaration as a string
               declarationString = globalUnparseToString(declaration,&info);
               break;
             }

          case V_SgFunctionParameterList:
             {
            // Handle generation of declaration strings this case differnetly from unparser
            // since want to generate declaration strings and not function parameter lists
            // (function parameter lists would be delimited by "," while declarations would
            // be delimited by ";").
               SgFunctionParameterList* parameterListDeclaration = dynamic_cast<SgFunctionParameterList*>(declaration);
               ROSE_ASSERT (parameterListDeclaration != NULL);
               SgInitializedNamePtrList & argList = parameterListDeclaration->get_args();
               SgInitializedNamePtrList::iterator i;
               for (i = argList.begin(); i != argList.end(); i++)
                  {
                    printf ("START: Calling unparseToString on type! \n");
                    ROSE_ASSERT((*i) != NULL);
                    ROSE_ASSERT((*i)->get_type() != NULL);
                    string typeNameString = (*i)->get_type()->unparseToString();
                    printf ("DONE: Calling unparseToString on type! \n");

                    string variableName;
                    if ( (*i)->get_name().getString() != "")
                       {
                         variableName   = (*i)->get_name().getString();
                         declarationString += typeNameString + " " + variableName + "; ";
                       }
                      else
                       {
                      // Don't need the tailing ";" if there is no variable name (I think)
                         declarationString += typeNameString + " ";
                       }
                  }
               break;
             }

       // ignore this case ... not really a declaration
          case V_SgCtorInitializerList:
            // printf ("Ignore the SgCtorInitializerList (constructor initializer list) \n");
               break;

          case V_SgVariableDefinition:
               printf ("ERROR: SgVariableDefinition nodes not used in AST \n");
               ROSE_ABORT();
               break;

       // default case should always be an error
          default:
               printf ("Default reached in AST_Rewrite::AccumulatedDeclarationsAttribute::generateDeclarationString() \n");
               printf ("     declaration->sage_class_name() = %s \n",declaration->sage_class_name());
               ROSE_ABORT();
               break;
        }

  // Add a space to make it easier to read (not required)
     declarationString += " ";

  // printf ("For this scope: declarationString = %s \n",declarationString.c_str());

     return declarationString;
   }
示例#11
0
void POETAstInterface::unparse(POETCode_ext* n, std::ostream& out, int align)
{ 
 static SgUnparse_Info info;
 static Unparser* roseUnparser = 0;
 static POETCode* linebreak=ASTFactory::inst()->new_string("\n");
 static POETCode* comma=ASTFactory::inst()->new_string(",");
 static bool template_only=false;
 static POETCode* left_over = 0;
  SgNode * input = (SgNode*)n->get_content();
  POETCode* res = POETAstInterface::find_Ast2POET(input);
  if (res == n) {
      if (template_only && input->variantT() == V_SgFunctionDeclaration) 
         { left_over = LIST(n,left_over); }
      else {
        std::string res = input->unparseToCompleteString(); 
        out << res;
      }
  }
  else {
     if (roseUnparser == 0) {
        /* QY/2013: copied from the global unparseFile to use a different ostream and delegate*/
       bool UseAutoKeyword                = false;
       bool generateLineDirectives        = true;
       bool useOverloadedOperators        = false;
       bool num                           = false;
       bool _this                         = true;
       bool caststring                    = false;
       bool _debug                        = false;
       bool _class                        = false;
       bool _forced_transformation_format = false;
       bool _unparse_includes             = false; 
       Unparser_Opt roseOptions( UseAutoKeyword,
                                    generateLineDirectives,
                                    useOverloadedOperators,
                                    num,
                                    _this,
                                    caststring,
                                    _debug,
                                    _class,
                                    _forced_transformation_format,
                                    _unparse_includes );
       roseUnparser = new Unparser(&out, "", roseOptions);
     }
     switch (input->variantT()) {
     case V_SgSourceFile: 
      {
       SgSourceFile* f = isSgSourceFile(input);
       info.set_current_scope(f->get_globalScope());
       template_only = true;
       code_gen(out, n->get_children(), 0, 0, align); 
       template_only = false; 
       if (left_over != 0) {
           code_gen(out, left_over, 0, 0, align); 
           left_over = 0;
       }
       break;
      }
     case V_SgFunctionDeclaration:
      if (template_only) { left_over = LIST(n, left_over); break; }
     case V_SgTemplateInstantiationFunctionDecl:
      {
        SgFunctionDeclaration* d = isSgFunctionDeclaration(input);
        roseUnparser->u_exprStmt->unparseAttachedPreprocessingInfo(d,info,PreprocessingInfo::before);
        POETCode_ext_delegate repl(n, out);
        roseUnparser->repl = &repl;
        roseUnparser->u_exprStmt->unparseFuncDeclStmt(d, info);
        break;
      }
     case V_SgFunctionDefinition:
      {
        SgStatement* d = isSgStatement(input);
        POETCode_ext_delegate repl(n, out);
        roseUnparser->repl = &repl;
        roseUnparser->u_exprStmt->unparseStatement(d, info);
        assert(n->get_children() != n);
        out << "{"; code_gen(out, linebreak, 0, 0, align + 2); 
        code_gen(out, n->get_children(), 0, linebreak, align+2); 
        code_gen(out, linebreak, 0, 0, align); out << "}"; 
        break;
      }
     case V_SgPragmaDeclaration:
      {
         out << "#pragma ";
         POETTuple* c = dynamic_cast<POETTuple*>(n->get_children());
         assert(c != 0);
         code_gen(out, c->get_entry(0)); 
         roseUnparser->cur << " "; roseUnparser->cur.insert_newline(1,align);
         code_gen(out, c->get_entry(1), 0, 0, align); 
         break;
      }
     case V_SgForStatement:
      {
         out << "for (" ;
         POETTuple* c = dynamic_cast<POETTuple*>(n->get_children());
         assert(c != 0);
         code_gen(out, c->get_entry(0)); 
         code_gen(out, c->get_entry(1)); out << ";";
         code_gen(out, c->get_entry(2)); out << ")";
         break;
      }
     case V_SgExprStatement:
        code_gen(out, n->get_children(), 0, 0, align); 
        out << ";";
        break;
     case V_SgTemplateInstantiationMemberFunctionDecl:  break;
     default: 
std::cerr << "Unsupported unparsing for  : " << input->class_name() << input->unparseToString() << "\n";
//assert(0); 
     }
  }
}
SgName
Unparser_Nameq::generateNameQualifierSupport ( SgScopeStatement* scope, const SgUnparse_Info& info, bool qualificationOfType )
   {
  // DQ (5/28/2011): We need this information to be passed in from the outside (qualificationOfType):
  //    qualificationOfName == true implies this is name qualification for a name vs a type.
  //    qualificationOfName == false implies this is name qualification for a type.
  // note that the complete minimally qualified name is stored and retrieved from the map using
  // either SgNode::get_globalQualifiedNameMapForNames() or SgNode::get_globalQualifiedNameMapForTypes().
  // bool qualificationOfType = false;

     SgName qualifiedName;

  // If the name qualification length required is zero then we can return an empty string and avoid the logic below.
     if (info.get_name_qualification_length() > 0)
        {
       // DQ (5/28/2011): Adding support for qualified name lookup.
          SgNode* nameQualificationReferenceNode = info.get_reference_node_for_qualification();
          if (nameQualificationReferenceNode != NULL)
             {
               if (qualificationOfType == false)
                  {
                    std::map<SgNode*,std::string>::iterator i = SgNode::get_globalQualifiedNameMapForNames().find(nameQualificationReferenceNode);
                    if (i != SgNode::get_globalQualifiedNameMapForNames().end())
                       {
                         qualifiedName = i->second;
                       }
                      else
                       {
                         printf ("key not found in node map nameQualificationReferenceNode = %s \n",nameQualificationReferenceNode->class_name().c_str());
                         ROSE_ASSERT(false);
                       }
                  }
                 else
                  {
                    std::map<SgNode*,std::string>::iterator i = SgNode::get_globalQualifiedNameMapForTypes().find(nameQualificationReferenceNode);
                    if (i != SgNode::get_globalQualifiedNameMapForTypes().end())
                       {
                         qualifiedName = i->second;
                       }
                      else
                       {
                      // Debugging support...
                         printf ("key not found in type map nameQualificationReferenceNode = %s \n",nameQualificationReferenceNode->class_name().c_str());

                      // Extra Debugging support...
                         switch(nameQualificationReferenceNode->variantT())
                            {
                              case V_SgInitializedName:
                                 {
                                   SgInitializedName* initializedName = isSgInitializedName(nameQualificationReferenceNode);
                                   printf ("initializedName = %s \n",initializedName->get_name().str());
                                   break;
                                 }

                              default:
                                 {
                                   printf ("Default reached in switch(nameQualificationReferenceNode->variantT()) \n");
                                   ROSE_ASSERT(false);
                                 }
                            }
                         ROSE_ASSERT(false);
                       }
                  }
             }
            else
             {
            // This should be an error.
               printf ("Error: nameQualificationReferenceNode == NULL but info.get_name_qualification_length() = %d \n",info.get_name_qualification_length());
               ROSE_ASSERT(false);
             }
        }
       else
        {
       // printf ("return empty qualified name since info.get_name_qualification_length() == 0 \n");
        }

     return qualifiedName;
   }
SgName
Unparser_Nameq::generateNameQualifier( SgDeclarationStatement* declarationStatement, const SgUnparse_Info & info, bool qualificationOfType )
   {
  // This unparser support for name qualification is C++ specific.

#if 0
     printf ("In Unparser_Nameq::generateNameQualifier(): qualificationOfType                      = %s \n",qualificationOfType ? "true" : "false");
     printf ("In Unparser_Nameq::generateNameQualifier(): info.get_name_qualification_length()     = %d \n",info.get_name_qualification_length());
     printf ("In Unparser_Nameq::generateNameQualifier(): info.get_type_elaboration_required()     = %s \n",info.get_type_elaboration_required() ? "true" : "false");
     printf ("In Unparser_Nameq::generateNameQualifier(): info.get_global_qualification_required() = %s \n",info.get_global_qualification_required() ? "true" : "false");
#endif

     ROSE_ASSERT(declarationStatement != NULL);
     return generateNameQualifierSupport(declarationStatement->get_scope(),info,qualificationOfType);
   }
示例#14
0
void
UnparseFormat::format(SgLocatedNode* node, SgUnparse_Info& info, FormatOpt opt)
   {
  // DQ (added comments): this function addes new line formatting to the unparse statements
  // depending on the type of statement and the options with which it is called.

     if (info.get_outputCodeGenerationFormatDelimiters() == true)
        {
       // printf ("In UnparseFormat::format(%s,opt=%d) \n",node->class_name().c_str(),opt);
       // (*this) << formatOptionToString(opt) << ":" << node->class_name() << "[";
          (*this) << formatOptionToString(opt) << ":" << node->class_name() << "[";
        }

#if 0
     printf ("UnparseFormat::format(): node = %p = %s currentLine = %d chars_on_line = %d \n",node,node->class_name().c_str(),currentLine,chars_on_line);
#endif

  // DQ (3/18/2006): The default is TABINDENT but we get a value from formatHelp if available
     int tabIndentSize = TABINDENT;
     if (formatHelpInfo != NULL)
          tabIndentSize = formatHelpInfo->tabIndent();

  // This provides a default implementation when the user has not specificed any help to control the unparsing
     if ( formatHelp(node, info, opt) == false )
        {
          int v = node->variantT();
          int v1 = (prevnode == 0) ? 0 : prevnode->variantT();
          switch (opt)
             {
               case FORMAT_AFTER_STMT:
                    if (v == V_SgFunctionDefinition || v == V_SgClassDefinition)
                         insert_newline(1); // DXN: changed from 2 to 1
                    break;
               case FORMAT_BEFORE_STMT:
                  {
#if 0
                    printf ("UnparseFormat::format(): case FORMAT_BEFORE_STMT: node = %p = %s \n",node,node->class_name().c_str());
#endif
                    switch(v)
                       {
                         case V_SgBasicBlock:
                      // DQ (3/18/2006): Added SgNullStatement as something that should not generate formatting in this case
                         case V_SgNullStatement:
                              break;
                         default:
                            {
#if 0
                              printf ("UnparseFormat::format(): case FORMAT_BEFORE_STMT: info.inConditional() = %s \n",info.inConditional() ? "true" : "false");
#endif
                              if (!info.inConditional())
                                 {
                                   linewrap = MAXCHARSONLINE;
                                   prevnode = node;
                                   if  (v == V_SgFunctionDefinition || v == V_SgClassDefinition)
                                      {
                                        insert_newline(2,stmtIndent);
                                      }
                                     else
                                      {
                                        insert_newline(1,stmtIndent);
                                      }
                                 }
                            }
                       }
                    break;
                  }
               case FORMAT_BEFORE_DIRECTIVE:
                    linewrap = -1;
                    insert_newline(1,0); 
                    break;
               case FORMAT_AFTER_DIRECTIVE:
                    linewrap = MAXCHARSONLINE;
                    insert_newline();
                    break;
               case FORMAT_BEFORE_BASIC_BLOCK1:
                    if ( v1 != V_SgCatchOptionStmt && v1 != V_SgDoWhileStmt  && 
                         v1 != V_SgForStatement && v1 != V_SgIfStmt && 
                         v1 != V_SgSwitchStatement && v1 != V_SgWhileStmt ) 
                       insert_newline(); 
                    break;
               case FORMAT_AFTER_BASIC_BLOCK1:
                    stmtIndent += tabIndentSize;
                    break;
               case FORMAT_BEFORE_BASIC_BLOCK2:
                    stmtIndent -= tabIndentSize;
                    insert_newline(1,stmtIndent);
                    break;
               case FORMAT_AFTER_BASIC_BLOCK2:
                    break;
               case FORMAT_BEFORE_NESTED_STATEMENT:
                    if (v != V_SgBasicBlock) {
                      stmtIndent += tabIndentSize;
                    }
                    break;
               case FORMAT_AFTER_NESTED_STATEMENT:
                    if (v != V_SgBasicBlock) {
                      stmtIndent -= tabIndentSize;
                    }
                    break;
               default:
                  {
                    printf ("Error: default reached in switch for formatting within unparsing ... \n");
                    ROSE_ASSERT(false);
                  }
             }
        }

     if (info.get_outputCodeGenerationFormatDelimiters() == true)
        {
       // printf ("Leaving UnparseFormat::format(%s,opt=%d) \n",node->class_name().c_str(),opt);
          (*this) << "]" << node->class_name();
        }

#if 0
     printf ("Leaving UnparseFormat::format(): node = %p = %s currentLine = %d chars_on_line = %d \n",node,node->class_name().c_str(),currentLine,chars_on_line);
#endif
   }
示例#15
0
文件: unparser.C 项目: 8l/rose
string globalUnparseToString ( SgNode* astNode, SgUnparse_Info* inputUnparseInfoPointer )
{
  // This global function permits any SgNode (including it's subtree) to be turned into a string

  // DQ (3/2/2006): Let's make sure we have a valid IR node!
     ROSE_ASSERT(astNode != NULL);

     string returnString;

  // all options are now defined to be false. When these options can be passed in
  // from the prompt, these options will be set accordingly.
     bool _auto                         = false;
     bool linefile                      = false;
     bool useOverloadedOperators        = false;
     bool num                           = false;

  // It is an error to have this always turned off (e.g. pointer = this; will not unparse correctly)
     bool _this                         = true;

     bool caststring                    = false;
     bool _debug                        = false;
     bool _class                        = false;
     bool _forced_transformation_format = false;
     bool _unparse_includes             = false;

  // printf ("In globalUnparseToString(): astNode->sage_class_name() = %s \n",astNode->sage_class_name());

     Unparser_Opt roseOptions( _auto,
                               linefile,
                               useOverloadedOperators,
                               num,
                               _this,
                               caststring,
                               _debug,
                               _class,
                               _forced_transformation_format,
                               _unparse_includes );

     int lineNumber = 0;  // Zero indicates that ALL lines should be unparsed

     // Initialize the Unparser using a special string stream inplace of the usual file stream 
     ostringstream outputString;

     SgLocatedNode* locatedNode = isSgLocatedNode(astNode);
     string fileNameOfStatementsToUnparse;
     if (locatedNode == NULL)
        {
       // printf ("WARNING: applying AST -> string for non expression/statement AST objects \n");
          fileNameOfStatementsToUnparse = "defaultFileNameInGlobalUnparseToString";
        }
       else
        {
          ROSE_ASSERT (locatedNode != NULL);

       // DQ (5/31/2005): Get the filename from a traversal back through the parents to the SgFile
       // fileNameOfStatementsToUnparse = locatedNode->getFileName();
       // fileNameOfStatementsToUnparse = rose::getFileNameByTraversalBackToFileNode(locatedNode);
          if (locatedNode->get_parent() == NULL)
             {
            // DQ (7/29/2005):
            // Allow this function to be called with disconnected AST fragments not connected to 
            // a previously generated AST.  This happens in Qing's interface where AST fragements 
            // are built and meant to be unparsed.  Only the parent of the root of the AST 
            // fragement is expected to be NULL.
               fileNameOfStatementsToUnparse = locatedNode->getFileName();
             }
            else
             {
               fileNameOfStatementsToUnparse = rose::getFileNameByTraversalBackToFileNode(locatedNode);
             }
          
        }
     ROSE_ASSERT (fileNameOfStatementsToUnparse.size() > 0);

     Unparser roseUnparser ( &outputString, fileNameOfStatementsToUnparse, roseOptions, lineNumber );

  // Information that is passed down through the tree (inherited attribute)
  // Use the input SgUnparse_Info object if it is available.
     SgUnparse_Info* inheritedAttributeInfoPointer = NULL;
     if (inputUnparseInfoPointer != NULL)
        {
       // printf ("Using the input inputUnparseInfoPointer object \n");

       // Use the user provided SgUnparse_Info object
          inheritedAttributeInfoPointer = inputUnparseInfoPointer;
        }
       else
        {
       // DEFINE DEFAULT BEHAVIOUR FOR THE CASE WHEN NO inputUnparseInfoPointer (== NULL) IS 
       // PASSED AS ARGUMENT TO THE FUNCTION
       // printf ("Building a new Unparse_Info object \n");

       // If no input parameter has been specified then allocate one
       // inheritedAttributeInfoPointer = new SgUnparse_Info (NO_UNPARSE_INFO);
          inheritedAttributeInfoPointer = new SgUnparse_Info();
          ROSE_ASSERT (inheritedAttributeInfoPointer != NULL);

       // MS: 09/30/2003: comments de-activated in unparsing
          ROSE_ASSERT (inheritedAttributeInfoPointer->SkipComments() == false);

       // Skip all comments in unparsing
          inheritedAttributeInfoPointer->set_SkipComments();
          ROSE_ASSERT (inheritedAttributeInfoPointer->SkipComments() == true);
       // Skip all whitespace in unparsing (removed in generated string)
          inheritedAttributeInfoPointer->set_SkipWhitespaces();
          ROSE_ASSERT (inheritedAttributeInfoPointer->SkipWhitespaces() == true);

       // Skip all directives (macros are already substituted by the front-end, so this has no effect on those)
          inheritedAttributeInfoPointer->set_SkipCPPDirectives();
          ROSE_ASSERT (inheritedAttributeInfoPointer->SkipCPPDirectives() == true);
        }

     ROSE_ASSERT (inheritedAttributeInfoPointer != NULL);
     SgUnparse_Info & inheritedAttributeInfo = *inheritedAttributeInfoPointer;

  // Turn ON the error checking which triggers an error if the default SgUnparse_Info constructor is called
  // SgUnparse_Info::forceDefaultConstructorToTriggerError = true;

#if 1
  // DQ (10/19/2004): Cleaned up this code, remove this dead code after we are sure that this worked properly
  // Actually, this code is required to be this way, since after this branch the current function returns and
  // some data must be cleaned up differently!  So put this back and leave it this way, and remove the
  // "Implementation Note".

  // Both SgProject and SgFile are handled via recursive calls
     if ( (isSgProject(astNode) != NULL) || (isSgFile(astNode) != NULL) )
        {
       // printf ("Implementation Note: Put these cases (unparsing the SgProject and SgFile into the cases for nodes derived from SgSupport below! \n");

       // Handle recursive call for SgProject
          if (isSgProject(astNode) != NULL)
             {
               SgProject* project = isSgProject(astNode);
               ROSE_ASSERT(project != NULL);
               for (int i = 0; i < project->numberOfFiles(); i++)
                  {
                    SgFile* file = &(project->get_file(i));
                    ROSE_ASSERT(file != NULL);
                    string unparsedFileString = globalUnparseToString(file,inputUnparseInfoPointer);
                    string prefixString       = string("/* TOP:")      + string(rose::getFileName(file)) + string(" */ \n");
                    string suffixString       = string("\n/* BOTTOM:") + string(rose::getFileName(file)) + string(" */ \n\n");
                    returnString += prefixString + unparsedFileString + suffixString;
                  }
             }

       // Handle recursive call for SgFile
          if (isSgFile(astNode) != NULL)
             {
               SgFile* file = isSgFile(astNode);
               ROSE_ASSERT(file != NULL);
               SgGlobal* globalScope = file->get_root();
               ROSE_ASSERT(globalScope != NULL);
               returnString = globalUnparseToString(globalScope,inputUnparseInfoPointer);
             }
        }
       else
#endif
        {
       // DQ (1/12/2003): Only now try to trap use of SgUnparse_Info default constructor
       // Turn ON the error checking which triggers an error if the default SgUnparse_Info constructor is called
          SgUnparse_Info::set_forceDefaultConstructorToTriggerError(true);

          if (isSgStatement(astNode) != NULL)
             {
               SgStatement* stmt = isSgStatement(astNode);
               roseUnparser.unparseStatement ( stmt, inheritedAttributeInfo );
             }

          if (isSgExpression(astNode) != NULL)
             {
               SgExpression* expr = isSgExpression(astNode);
               roseUnparser.unparseExpression ( expr, inheritedAttributeInfo );
             }

          if (isSgType(astNode) != NULL)
             {
               SgType* type = isSgType(astNode);
               roseUnparser.unparseType ( type, inheritedAttributeInfo );
             }

          if (isSgSymbol(astNode) != NULL)
             {
               SgSymbol* symbol = isSgSymbol(astNode);
               roseUnparser.unparseSymbol ( symbol, inheritedAttributeInfo );
             }

          if (isSgSupport(astNode) != NULL)
             {
            // Handle different specific cases derived from SgSupport 
            // (e.g. template parameters and template arguments).
               switch (astNode->variantT())
                  {
#if 0
                    case V_SgProject:
                       {
                         SgProject* project = isSgProject(astNode);
                         ROSE_ASSERT(project != NULL);
                         for (int i = 0; i < project->numberOfFiles(); i++)
                            {
                              SgFile* file = &(project->get_file(i));
                              ROSE_ASSERT(file != NULL);
                              string unparsedFileString = globalUnparseToString(file,inputUnparseInfoPointer);
                              string prefixString       = string("/* TOP:")      + string(rose::getFileName(file)) + string(" */ \n");
                              string suffixString       = string("\n/* BOTTOM:") + string(rose::getFileName(file)) + string(" */ \n\n");
                              returnString += prefixString + unparsedFileString + suffixString;
                            }
                         break;
                       }
                    case V_SgFile:
                       {
                         SgFile* file = isSgFile(astNode);
                         ROSE_ASSERT(file != NULL);
                         SgGlobal* globalScope = file->get_root();
                         ROSE_ASSERT(globalScope != NULL);
                         returnString = globalUnparseToString(globalScope,inputUnparseInfoPointer);
                         break;
                       }
#endif
                    case V_SgTemplateParameter:
                       {
                         SgTemplateParameter* templateParameter = isSgTemplateParameter(astNode);
                         roseUnparser.unparseTemplateParameter(templateParameter,inheritedAttributeInfo);
                         break;
                       }
                    case V_SgTemplateArgument:
                       {
                         SgTemplateArgument* templateArgument = isSgTemplateArgument(astNode);
                         roseUnparser.unparseTemplateArgument(templateArgument,inheritedAttributeInfo);
                         break;
                       }
                    case V_SgInitializedName:
                       {
                      // QY: not sure how to implement this
                      // DQ (7/23/2004): This should unparse as a declaration 
                      // (type and name with initializer).
                         break;
                       }

                    case V_Sg_File_Info:
                       {
                      // DQ (5/11/2006): Not sure how or if we shoul implement this
                         break;
                       }

                 // Perhaps the support for SgFile and SgProject shoud be moved to this location?
                    default:
                         printf ("Error: default reached in node derived from SgSupport astNode = %s \n",astNode->sage_class_name());
                         ROSE_ABORT();
                }
             }

       // Turn OFF the error checking which triggers an if the default SgUnparse_Info constructor is called
          SgUnparse_Info::set_forceDefaultConstructorToTriggerError(false);

       // MS: following is the rewritten code of the above outcommented 
       //     code to support ostringstream instead of ostrstream.
          returnString = outputString.str();

       // Call function to tighten up the code to make it more dense
          if (inheritedAttributeInfo.SkipWhitespaces() == true)
             {
               returnString = roseUnparser.removeUnwantedWhiteSpace ( returnString );
             }

       // delete the allocated SgUnparse_Info object
          if (inputUnparseInfoPointer == NULL)
               delete inheritedAttributeInfoPointer;
        }

     return returnString;
   }
void
generateModFile(SgFile *sfile)
   {
     ROSE_ASSERT(sfile != NULL);

  // file name, with full path.
     string  originalModuleFilenameWithPath = sfile->get_file_info()->get_filenameString();

#if 0
  // DQ (10/24/2010): This is overly restrictive...we still want to generate the rmod file.
  // It does not matter is we compile or not compile any generated file.  This premature
  // exit will cause F03 code to fail to be processed by ROSE since any mod file required 
  // will not generated.
  // FMZ (10/28/2009): don't generate the .rmod for the readin .rmod file
     if (sfile->get_skipfinalCompileStep() == true)
        {
          if (SgProject::get_verbose() > 0)
               printf ("Skipping generation of rmod file: %s \n",originalModuleFilenameWithPath.c_str());

          return;
        }
#endif

  // Cause the output of a message with verbose level is turned on.
     if (SgProject::get_verbose() > 0)
        {
          printf ("In generateModFile(): Generating a Fortran 90 specific module (*.rmod file) for file = %s \n",originalModuleFilenameWithPath.c_str());
        }

  // Get the list of SgModuleStatement objects for the current AST.
     Rose_STL_Container<SgNode*> moduleDeclarationList = NodeQuery::querySubTree (sfile,V_SgModuleStatement);

#if 0
  // DQ: I think this case is not required since the loop (below) would be empty.
     if (moduleDeclarationList.empty())
        {
       // no module in the file
          return;
        }
#endif

     for (Rose_STL_Container<SgNode*>::iterator i = moduleDeclarationList.begin(); i != moduleDeclarationList.end(); i++)
        {
       // For a module named "xx" generate a file "xx.rose_mod" which contains 
       // all the variable definitions and function declarations 
          SgModuleStatement* module_stmt = isSgModuleStatement(*i);

          ROSE_ASSERT(module_stmt != NULL);
string outputDir = get_rmod_dir(sfile);
string outputFilename;
if (outputDir !="")
          outputFilename =outputDir + module_stmt->get_name() + MOD_FILE_SUFFIX;
else
          outputFilename = module_stmt->get_name() + MOD_FILE_SUFFIX;

          string lowerCaseOutputFilename = StringUtility::convertToLowerCase(outputFilename);

       // Cause the output of a message with verbose level is turned on.
          if (SgProject::get_verbose() > 0)
             {
               printf ("In generateModFile() (loop over module declarations): Generating a Fortran 90 specific module file %s for module = %s \n",lowerCaseOutputFilename.c_str(),outputFilename.c_str());
             }

       // Use a lower case generate filename for the generated ROSE mod (or rmod) file. 
       // fstream Module_OutputFile(outputFilename.c_str(),ios::out);
          fstream Module_OutputFile(lowerCaseOutputFilename.c_str(),ios::out);

          if (!Module_OutputFile) {
             cout << "Error detected in opening file " << lowerCaseOutputFilename.c_str()
                  << "for output" << endl;
             ROSE_ASSERT(false);
             }

       // Output header at the top of the generate *.rmod file.
          Module_OutputFile <<  endl
               << "! =================================================================================== \n"
               << "! <<Automatically generated for Rose Fortran Separate Compilation, DO NOT MODIFY IT>> \n"
               << "! =================================================================================== \n"
               << endl;
          SgUnparse_Info ninfo;

          ninfo.set_current_scope((SgScopeStatement*)module_stmt);

          ninfo.set_SkipFormatting();

       // set the flag bit "outputFortranModFile" 
          ninfo.set_outputFortranModFile();

          ostringstream outputString;
          Unparser_Opt options(false, false,false,false,true,false,false,false,false,false);

       // This is a confusing use of originalModuleFilename vs. outputFilename (Oh, the first one has the full path!).
       // The originalModuleFilename will be used to build a FortranCodeGeneration_locatedNode using
       // the originalModuleFilename as a basis.
       // printf ("originalModuleFilenameWithPath = %s outputFilename = %s \n",originalModuleFilenameWithPath.c_str(),outputFilename.c_str());
          Unparser unp(&Module_OutputFile, originalModuleFilenameWithPath,options,NULL,NULL);
          unp.currentFile = sfile;

       // The outputFilename is the name that will be matched against in the selection of statements to unparse.
       // However, that its suffix is ".rmod" will cause UnparseLanguageIndependentConstructs::statementFromFile() 
       // to always return true.  So use of outputFilename should map to the file from the file constructed.
          FortranCodeGeneration_locatedNode myunp(&unp, outputFilename);

       // This calls the unparser for just the module declaration.
          myunp.unparseClassDeclStmt_module((SgStatement*)module_stmt,(SgUnparse_Info&)ninfo);

          Module_OutputFile.flush();
          Module_OutputFile.close();
        }
   }