Introduction Projects and Files Statements Expressions Symbols Types
Attributes Labels Non-Member Functions Constructing Declarations Example Programs Index

Projects and Files

A project is a group of parsed source files (.dep files) making up a program that is to be manipulated by Sage++. Currently, Sage++ can only deal with one project at a time. If multiple files in a project are desired, please see section Attributes.

On disk, a project is represented as a file with name ending in .proj, containing a list of names of the component .dep files, one file name per line. A file is one of the parsed source files in a project. Each .dep file contains a parse tree. The root of the tree for a file is called the global node and its immediate children are the top level definitions and functions in the files. The file also contains a symbol table and type table. Refer to the Overview for more details about .dep files.


SgProject

Represents the files in the current project, for all languages.

class  SgProject {
  public:
  inline SgProject(SgProject &);
  SgProject(char * proj_file_name);
  inline ~SgProject();
  inline int numberOfFiles();
  SgFile &file(int i);   
  inline char *fileName(int i); 
  inline int Fortranlanguage(); 
  inline int Clanguage();                         
  void addFile(char * dep_file_name);
  void deleteFile(SgFile * file);
};

Member Functions

SgProject(char * proj_file_name)

int numberOfFiles()

SgFile &file(int i)

char *fileName(int i)

int Fortranlanguage()

int Clanguage()

void addFile(char * dep_file_name)

void deleteFile(SgFile * file)

SgProject Usage

Typical usage of SgProject is as in the following example:

Here's another one:

Example Programs

SgProject is used in the following example programs:


SgFile

This class provides access to the local symbol and type tables, and the top level definitions, in the .dep file it corresponds to.

class  SgFile {
  public:
  PTR_FILE filept;
  SgFile(char* file_name); // the file must exist.
  SgFile(int Language, char* file_name); // for new empty file objects.
  inline ~SgFile();
  inline SgFile(SgFile &);
  inline int languageType();
  inline void saveDepFile(char *dep_file);
  inline void unparse(FILE *filedisc);
  inline void unparsestdout();   

inline SgStatement *mainProgram(); SgStatement *functions(int i); inline int numberOfFunctions(); SgStatement *getStruct(int i); inline int numberOfStructs();

inline SgStatement *firstStatement(); inline SgSymbol *firstSymbol(); inline SgType *firstType(); inline SgExpression *firstExpression();

inline SgExpression *SgExpressionWithId(int i); inline SgStatement *SgStatementWithId( int id); inline SgStatement *SgStatementAtLine(int lineno); inline SgSymbol *SgSymbolWithId( int id); inline SgType *SgTypeWithId( int id); // for attributes; void saveAttributes(char *file); void saveAttributes(char *file, void (*savefunction)(void *dat,FILE *f)); void readAttributes(char *file); void readAttributes(char *file, void * (*readfunction)(FILE *f)); int numberOfAttributes(); SgAttribute *attribute(int i); int SgFile::expressionGarbageCollection(int deleteExpressionNode, int verbose); };

Member Functions

SgFile(char* file_name)

SgFile(int Language, char* file_name)

int languageType()

void saveDepFile(char *dep_file)

void unparse(FILE *filedisc)

void unparsestdout()

SgStatement *mainProgram()

SgStatement *functions(int i)

int numberOfFunctions()

SgStatement *getStruct(int i)

int numberOfStructs()

SgStatement *firstStatement()

SgSymbol *firstSymbol()

SgType *firstType()

SgExpression *firstExpression()

SgExpression *SgExpressionWithId(int i)

SgStatement *SgStatementWithId( int id)

SgStatement *SgStatementAtLine(int lineno)

SgSymbol *SgSymbolWithId(int id)

SgType *SgTypeWithId( int id)

SgFile Usage

Usually, the .dep file is created by a parser and a Sage program modifies an already existing .dep file. However, in some situations, there is a need for creating an empty .dep file and then adding statements to it. In Sage++ version 1.7, a new constructor:

     SgFile::SgFile(int Language, char * dep_file_name)

has been added. It can be used to create new, empty .dep files. The code fragment below shows an example of usage:

  SgProject project("x.proj");
  SgFile file(CSrc, "y.c");  // create a new file
  SgStatement *s = f->firstStatement();
  SgPointerType *p, *q;
  SgType *v;
  if(s == NULL) printf("no first statement\n");
  SgFuncHedrStmt *mane = new SgFuncHedrStmt("main");
  mane->AddArg("argc",*SgTypeInt());  // add int argc
  v = new SgPointerType(*SgTypeChar());
  q = new SgPointerType(*v);
  // note: new SgPointerType (*p) will not work,
  //  the reason is that the default copy constructor is called
  mane->AddArg("argv", *q); // char ** argv
  s->insertStmtAfter(*mane);

Note that the "empty" file created by the SgFile constructor is not really completely empty: it contains one statement (the global node). Also, in order for the above example to work, you need to have x.proj and x.dep files in the same directory.

Normally, you wouldn't instantiate a SgFile yourself. Rather, you would instantiate a project, and then access the files in the project through the file() member of SgProject.

There are two ways to traverse a file. One way is to access each subroutine and function by means of the numberOfFunctions() and functions(i) methods. For example, to print the names of all the subroutines in the project, you might try:

The other way to traverse a file is to access it in lexical order starting with firstStatement(), as in:

Example Programs

SgFile is used in the following example programs:


Multiple Files Project

Multiple files capabilities exist in Sage, but there exists a set of limitations: only one file can be selected at a time. A file is selected by the methods:

     SgProject::file(int i)
     SgFile::SgFile(char * dep_file_name)

When a file is selected, then all the operation in the data base will use the current file data structure (see Figure 1). For instance, if a statement is created, it is added in the current file structure. When the project is opened, then the first file is automatically selected.

Example Usage

Here is an example of the usage of the multiple file capability:

  project =  new SgProject("test.proj");
  nbfile = project->numberOfFiles();
  for (i=0; i< nbfile; i++)
    {
      file = &(project->file(i));
      printf("|||||||||||||||||||||||||||||||||||||||||||||||||||||||||\n");
      // any operations here will operate on file number i
      // file i has been selected by the method project->file(i)

// do work here.......

file->unparsestdout(); }

Here is an example of code to retrieve a function code in a multiple file project:

  nbfile = project->numberOfFiles();
  printf("Give the name of the function: ");
  scanf("%s",str);
  for (i=0; i< nbfile; i++)
    {
      file = &(project->file(i));
      if (!file)  
        {
          Message("file not found",0);
          exit(1);
        }
      nbfunc = file->numberOfFunctions();
      for (j=0; jfunctions(j);
          if (!strcmp(func->symbol()->identifier(),str))
            {
              printf("Function %s found in file %s\n",
                     func->symbol()->identifier(),
                     project->fileName(i));
              break;
            }
        }
    }

Copy Across Files

Copy across files must be done by the member function,

     inline SgSymbol &SgSymbol::copyAcrossFiles(SgStatement &where)
where the parameter where indicates where the statements will be inserted. This method can only copy a full function, subroutine, class or structure. It duplicates all the expressions, symbols and types referenced in the body of a function, so that after the copy there are no more references to the original file.

To illustrate the problem of copying across files, let's consider this incorrect example. The result is illustrated in Figure 2:

  project =  new SgProject("test.proj");
  nbfile = project->numberOfFiles();  
  file = &(project->file(0));
  func = file->functions(0);  // take the first function of file 0 to
                              // be copied and inserted in the other file
  func->extractStmt();    // extract to allow copy
  for (i=1; i< nbfile; i++)
    {
      file = &(project->file(i));
      if (!file)  
        {
          Message("file not found",0);
          exit(1);
        }
      first =   file->firstStatement();
      copyoffunc = &(func->copy()); // THIS IS REALLY WRONG
      first->insertStmtAfter(*copyoffunc);
      printf("|||||||||||||||||||||||||||||||||||||||||||||||||||||||||\n");
      file->unparsestdout();
      // unparse correctly but database is corrupted.
      sprintf(str,"debug%d.dep",i);
      file->saveDepFile(str); // incorrect database output.
    }

Remark: Even though the multiple file operation is very limited and fragile it is still possible to use it for creating complex data structures easily. In one file an object to be copied can be created by the parser. It can then be copied into another file to be used as a template.

  .....
  project =  new SgProject("test.proj");
  nbfile = project->numberOfFiles();
  // set to the first file
  file = &(project->file(0));
  // get the first function
  func = file->functions(0);
  // get the symbol
  fc = func->symbol();
  // the following loop add the first function
  // of file number 0 to all the other files
  for (i=1; i< nbfile; i++)
    {
      file = &(project->file(i));
      first =   file->firstStatement();
      // call the copy across file function
      fccop =  &(fc->copyAcrossFiles(*first));
      // how to get the corresponding statement
      copyoffunc = fccop->body();
      file->unparsestdout();
    }
   .....
}


Exit Sage++ User's Guide