Program Listing for File rose_attributes_list.h

Program Listing for File rose_attributes_list.h#

↰ Return to documentation for file (src/frontend/SageIII/rose_attributes_list.h)

#ifndef __ROSEAttributesList_H__
#define __ROSEAttributesList_H__

//#include "setup.h"

//#include <list>
//#include <vector>
#include <map>
#include <boost/wave.hpp>
#include <boost/wave/cpplexer/cpp_lex_token.hpp>
// Include the ROSE lex specific definitions of tokens
#include "general_token_defs.h"
//#define ROSE_SKIP_COMPILATION_OF_WAVE 1

// #ifdef CAN_NOT_COMPILE_WITH_ROSE
//    #warning "CAN_NOT_COMPILE_WITH_ROSE IS defined"
// #else
//   #warning "CAN_NOT_COMPILE_WITH_ROSE is NOT defined"
// #endif

// DQ (2/28/2010): Skip this if we are compiling ROSE using ROSE.
// This is being used in place of the CAN_NOT_COMPILE_WITH_ROSE macro.
// Note that CAN_NOT_COMPILE_WITH_ROSE is set by the following projects:
//     1) projects/DocumentationGenerator
//     2) projects/haskellport
// in their Makefile.am files.  I think that using CXX_IS_ROSE_ANALYSIS
// will be equivalent (used to indicate the a ROSE translator is being
// used to compile the ROSE source code).
// However, it might be that this is equivalent to the USE_ROSE macro,
// which is set for all ROSE translators when they compile any code.
// DQ (12/22/2008): I would appreciate it if this were a better name...
// #if !CAN_NOT_COMPILE_WITH_ROSE
// #ifndef USE_ROSE

class ROSE_DLL_API PreprocessingInfo;
class ROSEAttributesList;
//AS(01/04/07) Global map of filenames to PreprocessingInfo*'s as it is inefficient
//to get this by a traversal of the AST
extern std::map<std::string,ROSEAttributesList* > mapFilenameToAttributes;


// DQ (4/19/2006): Forward declaration so that PreprocessingInfo can
// contain a pointer to a Sg_File_Info object.
class Sg_File_Info;

// DQ (1/21/2008): Need forward declaration
class SgFile;

// #if !CAN_NOT_COMPILE_WITH_ROSE
// #ifndef USE_ROSE
#ifndef ROSE_SKIP_COMPILATION_OF_WAVE

typedef boost::wave::cpplexer::lex_token<>  token_type;
typedef std::vector<token_type>             token_container;
typedef std::list<token_type>               token_list_container;
typedef std::vector<std::list<token_type> > token_container_container;

#endif

class PreprocessingInfo
   {
     public:
      //  DQ (10/15/2002) moved this to nested scope to avoid global name pollution :-).
          enum RelativePositionType
             {
               defaultValue = 0, // let the zero value be an error value
               undef        = 1, // Position of the directive is only going to be defined
                                 // when the preprocessing object is copied into the AST,
                                 // it remains undefined before that
               before       = 2, // Directive goes before the corresponding code segment
               after        = 3, // Directive goes after the corresponding code segment
               inside       = 4, // Directive goes inside the corresponding code segment (as in between "{" and "}" of an empty basic block)

            // DQ (7/19/2008): Added additional fields so that we could use this enum type in the AstUnparseAttribute
            // replace       = 5, // Support for replacing the IR node in the unparsing of any associated subtree
               before_syntax = 6, // We still have to specify the syntax
               after_syntax  = 7  // We still have to specify the syntax
             };

       // Enum type to help classify the type for string that has been saved.
       // This helps in the unparsing to make sure that line feeds are introduced properly.
       //
       // Rama (08/17/07): Adding a CpreprocessorDeadIfDeclaration and its support
       // in various files.
          enum DirectiveType
             {
            // This is treated as an error
               CpreprocessorUnknownDeclaration,

            // These are a classification for comments
               C_StyleComment,
               CplusplusStyleComment,
               FortranStyleComment,

            // FMZ(5/14/2010): Added freeform comments (started with "!")
               F90StyleComment,

            // DQ (11/20/2008): Added classification for blank line (a language independent form of comment).
               CpreprocessorBlankLine,

            // These used to be translated into IR nodes (and will be in the future).
               CpreprocessorIncludeDeclaration,
               CpreprocessorIncludeNextDeclaration,
               CpreprocessorDefineDeclaration,
               CpreprocessorUndefDeclaration,
               CpreprocessorIfdefDeclaration,
               CpreprocessorIfndefDeclaration,
               CpreprocessorIfDeclaration,
               CpreprocessorDeadIfDeclaration,
               CpreprocessorElseDeclaration,
               CpreprocessorElifDeclaration,
               CpreprocessorEndifDeclaration,
               CpreprocessorLineDeclaration,
               CpreprocessorErrorDeclaration,

            // DQ (10/19/2005): Added CPP warning directive
               CpreprocessorWarningDeclaration,
               CpreprocessorEmptyDeclaration,

            // AS (11/18/05): Added macro support (these are generated by the Wave
            // support, but need to be better documented as to what they mean).
               CSkippedToken,
               CMacroCall,

            // AS & LIAO (8/12/2008): A PreprocessingInfo that is a
            // hand made MacroCall that will expand into a valid statement.
               CMacroCallStatement,

            // DQ (11/28/2008): What does this mean!
            // A line replacement will replace a sub-tree in the AST
            // after a node with position (filename,line)
               LineReplacement,

            // The is the 'extern "C" {' construct.  Note that this is not captured in
            // the EDG AST and it is required to be captured as part of the CPP and
            // comment preprocessing.
               ClinkageSpecificationStart,
               ClinkageSpecificationEnd,

            // DQ (11/17/2008): Added support for #ident
               CpreprocessorIdentDeclaration,

            // DQ (11/17/2008): This handles the case CPP declarations (called "linemarkers")
            // (see Google for more details) such as: "# 1 "test2008_05.F90"", "# 1 "<built-in>"",
            // "# 1 "<command line>"" "# 1 "test2008_05.F90""
            // The first token is the line number,
            // the second token is the filename (or string),
            // the optional tokens (zero or more) are flags:
            //   '1' indicates the start of a new file.
            //   '2' indicates returning to a file (having included another file).
            //   '3' indicates that the following text comes from a system header file, so certain warnings should be supressed.
            //   '4' indicates that the following text should be treated as being wrapped in an implicit 'extern "C"' block
               CpreprocessorCompilerGeneratedLinemarker,

            // DQ (2/2/2014): permit raw text to be specified as a extremely simple way to add text to the unparsing of the AST.
            // Note that it is the user's responcability to have the text be legal code.  Additionall any language constructs
            // added using this mechanism will ot show up in the AST.  So it is not possible to reference functions (for example)
            // added using this mechanism to build function calls as transformation elsewhere in the code.  But one could add
            // the function via AST transformations and the function body using a mechanism provided here and that would define
            // a simple appoach to adding large complex functions for which it is impractical to build up an AST.
               RawText,

               CpreprocessorEnd_ifDeclaration, // PP (10/1/21): Ada "end if"

               LastDirectiveType
             };

       // DQ (7/10/2004): Make the data private
     private:

       // DQ (4/19/2006): Use the SgFileInfo object to hold the more complete
       // information about the filename, line number, and column number.
          Sg_File_Info* file_info;
       // int   lineNumber;
       // int   columnNumber;

       // Use string class to improve implementation
       // char* stringPointer;
          std::string internalString;

          int   numberOfLines;

       // enum value representing a classification of the different types of directives
          DirectiveType whatSortOfDirective;

       // Corresponding enum value
          RelativePositionType relativePosition;

       // DQ (11/28/2008): Support for CPP generated linemarkers
          int lineNumberForCompilerGeneratedLinemarker;
          std::string filenameForCompilerGeneratedLinemarker;
          std::string optionalflagsForCompilerGeneratedLinemarker;

       // DQ (1/15/2015): Adding support for token-based unparsing. When new comments and CPP directives are added we need
       // to record these as a kind of transformation that will trigger the token stream representation to NOT be used and
       // the comments and CPP directives unparsed from the AST seperately from the associated IR node being unparsed from
       // the AST.  The problem is that we wnat to record where there might be comments or CPP directives removed and having
       // a flag here is not going to work for that.  so we have to also record that the ROSEAttributesList has changed.
          bool p_isTransformation;

// This is part of Wave support in ROSE.
// #ifndef USE_ROSE
     public:
/*
       // AS using the lexer_token from boost_wave in order to store structures
          typedef boost::wave::cpplexer::lex_token<> token_type;
          typedef std::vector<token_type>            token_container;
          typedef std::list<token_type>              token_list_container;
          typedef std::vector<std::list<token_type> >       token_container_container;
*/
     private:
       // FIXME: To support Jochens AST binary save work the tokenSteam must
       // have a pointer type.

#ifndef ROSE_SKIP_COMPILATION_OF_WAVE
       // A stream of tokens representing the current prerpocessing info
       // object. This is equivalent to the internal string, but of cause
       // contains more information since it is a tokenized stream.
          token_container* tokenStream;

     public:
          typedef struct r_include_directive
             {
            // The parameter 'directive' contains the (expanded) file name found after
            // the #include directive. This has the format '<file>', '"file"' or 'file'.
               token_type directive;
            // The paths plus name to the include directive filename
               std::string absname;
               std::string relname;
             } rose_include_directive;

       // Internal representation of a macro #define directive
          typedef struct r_macro_def
             {
               bool is_functionlike;
               bool is_predefined;
               token_type macro_name;
               token_container paramaters;
               token_list_container definition;
               r_macro_def() : macro_name(), paramaters(),definition() {}
             } rose_macro_definition;

       // Internal representation of a macro call
       // e.g #define MACRO_CALL int x;
       // MACRO_CALL
#if 0
          typedef struct r_macro_call
             {
               bool is_functionlike;
               PreprocessingInfo* macro_def;
               token_type macro_call;
               token_container_container arguments;
               token_container expanded_macro;

            // Get string representation of the expanded macro
               std::string get_expanded_string()
                  {
                    std::ostringstream os;
                    token_container::const_iterator iter;
                    for (iter=expanded_macro.begin(); iter!=expanded_macro.end(); iter++)
                         os << (*iter).get_value();
                    return os.str();
                  }

               r_macro_call() : macro_call(), arguments(),expanded_macro() {}
             } rose_macro_call;
#else
       // DQ (3/9/2013): Modified to address SWIG error.
          struct rose_macro_call
             {
               bool is_functionlike;
               PreprocessingInfo* macro_def;
               token_type macro_call;
               token_container_container arguments;
               token_container expanded_macro;

            // DQ (3/9/2013): The function definition is moved to the source file to get around SWIG error.
            // Get string representation of the expanded macro
               std::string get_expanded_string();

            // DQ (3/9/2013): The function definition is moved to the source file to get around SWIG error.
               rose_macro_call();
             };
#endif

     private:
       // AS add macro definition
          rose_macro_definition*  macroDef;
       // AS add macro call
          rose_macro_call*        macroCall;
       // AS include directive
          rose_include_directive* includeDirective;

#endif

  // member functions
     public:
         ~PreprocessingInfo();
          PreprocessingInfo();

// #ifndef USE_ROSE
#ifndef ROSE_SKIP_COMPILATION_OF_WAVE
       // AS (112105) Added constructors to support macros
          PreprocessingInfo(token_container, DirectiveType, RelativePositionType);
          PreprocessingInfo(rose_macro_call*, RelativePositionType);
          PreprocessingInfo(rose_macro_definition*, RelativePositionType);
          PreprocessingInfo(token_type, token_list_container, bool, DirectiveType,RelativePositionType);
          PreprocessingInfo(rose_include_directive*, RelativePositionType);
#endif

       // This constructor is called from the C++ code generated from the lex file (preproc.lex)
       // PreprocessingInfo(DirectiveType, const char *inputStringPointer, int line_no , int col_no,
       //                   int nol, RelativePositionType relPos, bool copiedFlag, bool unparsedFlag) ROSE_DEPRECATED_FUNCTION;

       // DQ (7/19/2008): I have removed the bool copiedFlag and bool unparsedFlag parameters because they are not used
       // and are present only because in an older implementation of the unparser it would make the PreprocessingInfo
       // as unparsed (and maybe copied) but this sort of side-effect of the unparser was later removed to make the
       // unparsing side-effect free.
       // DQ (4/19/2006): Use the SgFileInfo object to hold the more complete
       // information about the filename, line number, and column number.
       // DQ (3/15/2006): Build constructor that uses C++ string as input (to replace the char* based constructor)
       // PreprocessingInfo(DirectiveType, const std::string inputString, int line_no , int col_no,
       //                   int nol, RelativePositionType relPos, bool copiedFlag, bool unparsedFlag);
       // PreprocessingInfo(DirectiveType, const std::string & inputString,
       //      const std::string & filenameString, int line_no , int col_no,
       //      int nol, RelativePositionType relPos, bool copiedFlag, bool unparsedFlag );
          PreprocessingInfo(DirectiveType, const std::string & inputString,
               const std::string & filenameString, int line_no , int col_no,
               int nol, RelativePositionType relPos );

       // Copy constructor
          PreprocessingInfo(const PreprocessingInfo &prepInfo);

          void display(const std::string & label) const;

       // Access functions
          int getLineNumber() const;
          int getColumnNumber() const;
          std::string getString() const;
          void setString ( const std::string & s );
          int getStringLength() const;
          DirectiveType getTypeOfDirective() const;
          void setTypeOfDirective(DirectiveType);
          RelativePositionType getRelativePosition(void) const;
          void setRelativePosition(RelativePositionType relPos);

       // DQ (2/27/2019): Adding support for CPP directives and comments to have filename information (already present, but we need to access it).
          std::string getFilename() const;
          int getFileId() const;

       // Number of lines occupied by this comment (count the number of line feeds)
          int getNumberOfLines() const;
          int getColumnNumberOfEndOfString() const; // only correct for single line directives

       // Used in unparse to string mechanism
       // char* removeLeadingWhiteSpace (const char* inputStringPointer);

       // DQ (8/6/2006): Modified to make these static functions
       // useful for debugging
          static std::string directiveTypeName (const DirectiveType & directive);
          static std::string relativePositionName (const RelativePositionType & position);

       // JH (01/03/2006) methods for packing the PreprocessingInfo data, in order to store it into
       // a file and rebuild it!
          unsigned int packed_size () const;

       // JH (01/032006) This pack methods might cause memory leaks. Think of deleting them after stored to file ...
          char* packed()  const;
          void unpacked( char* storePointer );

       // DQ (4/19/2006): Added Sg_File_Info objects to each PreprocessingInfo object
          Sg_File_Info* get_file_info() const;
          void set_file_info( Sg_File_Info* info );

       // DQ (8/26/2020): include directive have a filename imbedded inside, and we need to
       // extract that for from tools (e.g. the fixup for initializers from include files).
          std::string get_filename_from_include_directive();

       // DQ (11/28/2008): Support for CPP generated linemarkers
          int get_lineNumberForCompilerGeneratedLinemarker();
          std::string get_filenameForCompilerGeneratedLinemarker();
          std::string get_optionalflagsForCompilerGeneratedLinemarker();

       // DQ (11/28/2008): Support for CPP generated linemarkers
          void set_lineNumberForCompilerGeneratedLinemarker( int x );
          void set_filenameForCompilerGeneratedLinemarker( std::string x );
          void set_optionalflagsForCompilerGeneratedLinemarker( std::string x );

// #ifndef USE_ROSE
#ifndef ROSE_SKIP_COMPILATION_OF_WAVE
  // Wave specific member functions.
     public:
       // Access functions to get the macro call or macro definition.
       // These are NULL if the type is not CMacroCall or
       // CpreprocessorDefineDeclaration
          rose_macro_call* get_macro_call();
          rose_macro_definition* get_macro_def();
          rose_include_directive* get_include_directive();

          const token_container* get_token_stream();
          void push_front_token_stream(token_type tok);
          void push_back_token_stream(token_type tok);

#endif

      // DQ (12/30/2013): Adding support to supress output of macros that are self-referential.
      // e.g. "#define foo X->foo", which would be expanded a second time in the backend processing.
      // Note that if we don't output the #define, then we still might have a problem if there was
      // code that depended upon a "#ifdef foo".  So this handling is not without some risk, but it
      // always better to use the token stream unparsing for these cases.
         bool isSelfReferential();
         std::string getMacroName();

       // DQ (1/15/2015): Adding support for token-based unparsing. Access function for new data member.
          bool isTransformation() const;
          void setAsTransformation();
          void unsetAsTransformation();
   };

// DQ (10/15/2002) Changed list element from "PreprocessingInfo" to
// "PreprocessingInfo*" to avoid redundant copying of internal data.
// Define a new data type for the container that stores the
// PreprocessingInfo objects attached to an AST node
typedef Rose_STL_Container<PreprocessingInfo*> AttachedPreprocessingInfoType;

class ROSEAttributesList
   {
     private:
       // DQ replaced use of old list class with STL
          std::vector<PreprocessingInfo*> attributeList;

       // DQ (1/9/2021): Added comment.
       // Note that the token stream is contained in the ROSEAttributesList list which before this just held
       // the comments and CPP directives.  This is OK, but the makes of the types and data members are less
       // than ideal.
          LexTokenStreamTypePointer rawTokenStream;

       // [DT] 3/15/2000 -- Name of file from which the directives come.
       // char fileName[256];
          std::string fileName;

       //      3/16/2000 -- Index into the list.  Not sure if this is really
       //      necessary.  See implementation in unparser.C.
       //
       // This is where the current line number is stored while we
       // go off and unparse a different include file.  This really should have
       // been stored in a static structure (I think) rather than in this list.
          int index;

       // DQ (12/15/2012): Save file ids that are from filenames referenced in #line
       // directives, these will be considered equivalent to the input source filename.
          std::set<int> filenameIdSet;

       // DQ (1/15/2015): Adding support for token-based unparsing. When new comments and CPP directives are added we need
       // to record these as a kind of transformatiPreprocessingInfoon that will trigger the token stream representation to NOT be used and
       // the comments and CPP directives unparsed from the AST seperately from the associated IR node being unparsed from
       // the AST.  The problem is that we want to record where there might be comments or CPP directives removed and having
       // a flag here is not going to work for that, so we have to also record that the ROSEAttributesList has changed.
       // bool p_isTransformation;

     public:
       // DQ (11/19/2008): Added language selection support for handling comments
          enum languageTypeEnum
             {
               e_unknown_language   = 0,
               e_C_language         = 1,
               e_Cxx_language       = 2,
               e_Fortran77_language = 3,
               e_Fortran9x_language = 4,
               e_lastLanguage
             };

          ROSEAttributesList();
         ~ROSEAttributesList();
       // DQ (4/19/2006): Adding SgFileInfo objects so we need to pass in a filename string
       // void addElement(PreprocessingInfo::DirectiveType, const char *pLine, int lineNumber, int columnNumber, int numberOfLines);
          void addElement(PreprocessingInfo::DirectiveType, const std::string & pLine, const std::string & filename, int lineNumber, int columnNumber, int numberOfLines);
#if 1
       // DQ (5/9/2007): This is required for WAVE support.
       // DQ (4/13/2007): I would like to remove this function, but it is used by WAVE support within ROSE.
          void addElement( PreprocessingInfo &pRef );
#endif
       // void addElements( ROSEAttributesList &);
          void moveElements( ROSEAttributesList &);

#if 1
       // DQ (5/9/2007): This is required for WAVE support.
       // DQ (4/13/2007): I would like to remove this function
          void insertElement( PreprocessingInfo & pRef );
#endif

       // [DT] 3/15/2000 -- Interface to fileName member.
          void setFileName(const std::string & fName);
          std::string getFileName();

       // 3/16/2000 -- Interface to index member.
          void setIndex(int i);
          int getIndex();

          PreprocessingInfo* operator[](int i);
          int size(void);
          int getLength(void);
          void deepClean(void);
          void clean(void);

      // DQ (9/19/2013): generate the number associated with each position relative to the attached IR node.
      // size_t numberByRelativePosition(PreprocessingInfo::RelativePositionType pos);

       // Access function for list
          std::vector<PreprocessingInfo*> & getList() { return attributeList; };

          void display ( const std::string & label );          // DQ 02/18/2001 -- For debugging.

       // DQ (1/21/2008): Added access function to save the raw token stream from the lex pass.
          void set_rawTokenStream( LexTokenStreamTypePointer s );
          LexTokenStreamTypePointer get_rawTokenStream();

       // This function processes the token stream to generate the input for what weaves the
       // CPP directives and comments into the AST.  All other tokens are ignore in this pass.
          void generatePreprocessorDirectivesAndCommentsForAST( const std::string & filename );

       // DQ (11/26/2008): This is old code!
       // Collection comments and CPP directives for fixed format (easier case)
       // void collectFixedFormatPreprocessorDirectivesAndCommentsForAST( const std::string & filename );

       // DQ (11/16/2008): Adding support for recognition of CPP directives outside of the lex tokenization.
          void collectPreprocessorDirectivesAndCommentsForAST( const std::string & filename, languageTypeEnum languageType );

       // DQ (11/17/2008): Refactored the code.
          bool isFortran77Comment( const std::string & line );
          bool isFortran90Comment( const std::string & line );
          bool isCppDirective( const std::string & line, PreprocessingInfo::DirectiveType & cppDeclarationKind, std::string & restOfTheLine );

       // DQ (12/15/2012): traverse the attributeList and process all of the #line directives to generate a
       // list of file ids that should be considered equivalent to that of the input source file's filename.
       // std::set<int> generateFileIdListFromLineDirectives();
          void generateFileIdListFromLineDirectives();

       // DQ (12/15/2012): Added access function.
          std::set<int> & get_filenameIdSet();

       // DQ (9/29/2013): Added to support adding processed CPP directives and comments as tokens to token list.
          PreprocessingInfo* lastElement();

       // DQ (1/15/2015): Adding support for token-based unparsing. Access function for new data member.
       // bool isTransformation() const;
       // void setAsTransformation();
       // void unsetAsTransformation();
   };

//
// [DT] 3/16/2000 -- Want to have preprocessing info for
//      each file included from the main source file.
//
class ROSEAttributesListContainer
   {
     private:
       // DQ replaced use of old list class with STL
       // std::vector<ROSEAttributesList*> attributeListList;
       // std::map<std::string,ROSEAttributesList*>* attrMap;
          std::map<std::string, ROSEAttributesList*> attributeListMap;

     public:
          ROSEAttributesListContainer();
         ~ROSEAttributesListContainer();
       // void addList ( ROSEAttributesList* listPointer );
          void addList ( std::string fileName, ROSEAttributesList* listPointer );
       // void addList(ROSEAttributesList &aRef);
       // void insertList(ROSEAttributesList &aRef);
       // ROSEAttributesList* operator[](int i);
       // ROSEAttributesList* findList ( const std::string & fName );

       // Check to see if the ROSEAttributesList for the fName (filename) is in the container
          bool isInList ( const std::string & fName );

       // int size(void);
       // int getLength(void);
          void dumpContents(void); // [DT] 3/16/2000 -- For debugging.
          void deepClean(void);
          void clean(void);
          ROSEAttributesList & operator[]( const std::string & fName);

       // Access function for list
       // std::vector<ROSEAttributesList*> & getList() { return attributeListList; };
          std::map<std::string, ROSEAttributesList*> & getList() { return attributeListMap; };
          void display ( const std::string & label );          // DQ 02/18/2001 -- For debugging.
   };


// #ifndef USE_ROSE
#ifndef ROSE_SKIP_COMPILATION_OF_WAVE

extern token_container wave_tokenStream;

#endif

#endif