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; }
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; }