<commit_before>//===----------------------------------------------------------------------===//
// The LLVM analyze utility
//
// This utility is designed to print out the results of running various analysis
// passes on a program.  This is useful for understanding a program, or for
// debugging an analysis pass.
//
//  analyze --help           - Output information about command line switches
//  analyze --quiet          - Do not print analysis name before output
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/iPHINode.h"
#include "llvm/Type.h"
#include "llvm/PassManager.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Analysis/Writer.h"
#include "llvm/Analysis/InstForest.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/IntervalPartition.h"
#include "llvm/Analysis/Expressions.h"
#include "llvm/Analysis/InductionVariable.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/DataStructure.h"
#include "llvm/Analysis/FindUnsafePointerTypes.h"
#include "llvm/Analysis/FindUsedTypes.h"
#include "llvm/Support/InstIterator.h"
#include "Support/CommandLine.h"
#include <algorithm>

using std::ostream;
using std::string;

//===----------------------------------------------------------------------===//
// printPass - Specify how to print out a pass.  For most passes, the standard
// way of using operator<< works great, so we use it directly...
//
template<class PassType>
static void printPass(PassType &P, ostream &O, Module &M) {
  O << P;
}

template<class PassType>
static void printPass(PassType &P, ostream &O, Function &F) {
  O << P;
}

// Other classes require more information to print out information, so we
// specialize the template here for them...
//
template<>
static void printPass(LocalDataStructures &P, ostream &O, Module &M) {
  P.print(O, &M);
}

template<>
static void printPass(FindUsedTypes &FUT, ostream &O, Module &M) {
  FUT.printTypes(O, &M);
}

template<>
static void printPass(FindUnsafePointerTypes &FUPT, ostream &O, Module &M) {
  FUPT.printResults(&M, O);
}

template <class PassType, class PassName>
class PassPrinter;  // Do not implement

template <class PassName>
class PassPrinter<Pass, PassName> : public Pass {
  const string Message;
  const AnalysisID ID;
public:
  PassPrinter(const string &M, AnalysisID id) : Message(M), ID(id) {}

  const char *getPassName() const { return "IP Pass Printer"; }

  virtual bool run(Module &M) {
    std::cout << Message << "\n";
    printPass(getAnalysis<PassName>(ID), std::cout, M);
    return false;
  }

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequired(ID);
  }
};

template <class PassName>
class PassPrinter<FunctionPass, PassName> : public FunctionPass {
  const string Message;
  const AnalysisID ID;
public:
  PassPrinter(const string &M, AnalysisID id) : Message(M), ID(id) {}

    const char *getPassName() const { return "Function Pass Printer"; }

  virtual bool runOnFunction(Function &F) {
    std::cout << Message << " on function '" << F.getName() << "'\n";
    printPass(getAnalysis<PassName>(ID), std::cout, F);
    return false;
  }

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequired(ID);
    AU.setPreservesAll();
  }
};

template <class PassType, class PassName, AnalysisID &ID>
Pass *New(const string &Message) {
  return new PassPrinter<PassType, PassName>(Message, ID);
}
template <class PassType, class PassName>
Pass *New(const string &Message) {
  return new PassPrinter<PassType, PassName>(Message, PassName::ID);
}

Pass *createPrintFunctionPass(const string &Message) {
  return new PrintFunctionPass(Message, &std::cout);
}
Pass *createPrintModulePass(const string &Message) {
  return new PrintModulePass(&std::cout);
}

struct InstForestHelper : public FunctionPass {
  const char *getPassName() const { return "InstForest Printer"; }

  void doit(Function &F) {
    std::cout << InstForest<char>(&F);
  }

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.setPreservesAll();
  }
};

struct IndVars : public FunctionPass {
  const char *getPassName() const { return "IndVars Printer"; }

  void doit(Function &F) {
    LoopInfo &LI = getAnalysis<LoopInfo>();
    for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
      if (PHINode *PN = dyn_cast<PHINode>(*I)) {
        InductionVariable IV(PN, &LI);
        if (IV.InductionType != InductionVariable::Unknown)
          std::cout << IV;
      }
  }

  void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequired(LoopInfo::ID);
    AU.setPreservesAll();
  }
};

struct Exprs : public FunctionPass {
  const char *getPassName() const { return "Expression Printer"; }

  static void doit(Function &F) {
    std::cout << "Classified expressions for: " << F.getName() << "\n";
    for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
      std::cout << *I;

      if ((*I)->getType() == Type::VoidTy) continue;
      analysis::ExprType R = analysis::ClassifyExpression(*I);
      if (R.Var == *I) continue;  // Doesn't tell us anything

      std::cout << "\t\tExpr =";
      switch (R.ExprTy) {
      case analysis::ExprType::ScaledLinear:
        WriteAsOperand(std::cout << "(", (Value*)R.Scale) << " ) *";
        // fall through
      case analysis::ExprType::Linear:
        WriteAsOperand(std::cout << "(", R.Var) << " )";
        if (R.Offset == 0) break;
        else std::cout << " +";
        // fall through
      case analysis::ExprType::Constant:
        if (R.Offset) WriteAsOperand(std::cout, (Value*)R.Offset);
        else std::cout << " 0";
        break;
      }
      std::cout << "\n\n";
    }
  }
  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.setPreservesAll();
  }
};

template<class TraitClass>
class PrinterPass : public TraitClass {
  const string Message;
public:
  PrinterPass(const string &M) : Message(M) {}

  virtual bool runOnFunction(Function &F) {
    std::cout << Message << " on function '" << F.getName() << "'\n";

    TraitClass::doit(F);
    return false;
  }
};

template<class PassClass>
Pass *Create(const string &Message) {
  return new PassClass(Message);
}

enum Ans {
  // global analyses
  print, intervals, exprs, instforest, loops, indvars,

  // ip analyses
  printmodule, callgraph, datastructure, printusedtypes, unsafepointertypes,

  domset, idom, domtree, domfrontier,
  postdomset, postidom, postdomtree, postdomfrontier,
};

cl::String InputFilename ("", "Load <arg> file to analyze", cl::NoFlags, "-");
cl::Flag   Quiet         ("q", "Don't print analysis pass names");
cl::Alias  QuietA        ("quiet", "Alias for -q", cl::NoFlags, Quiet);
cl::EnumList<enum Ans> AnalysesList(cl::NoFlags,
  clEnumVal(print          , "Print each function"),
  clEnumVal(intervals      , "Print Interval Partitions"),
  clEnumVal(exprs          , "Classify Expressions"),
  clEnumVal(instforest     , "Print Instruction Forest"),
  clEnumVal(loops          , "Print natural loops"),
  clEnumVal(indvars        , "Print Induction Variables"),

  clEnumVal(printmodule    , "Print entire module"),
  clEnumVal(callgraph      , "Print Call Graph"),
  clEnumVal(datastructure  , "Print data structure information"),
  clEnumVal(printusedtypes , "Print types used by module"),
  clEnumVal(unsafepointertypes, "Print unsafe pointer types"),

  clEnumVal(domset         , "Print Dominator Sets"),
  clEnumVal(idom           , "Print Immediate Dominators"),
  clEnumVal(domtree        , "Print Dominator Tree"),
  clEnumVal(domfrontier    , "Print Dominance Frontier"),

  clEnumVal(postdomset     , "Print Postdominator Sets"),
  clEnumVal(postidom       , "Print Immediate Postdominators"),
  clEnumVal(postdomtree    , "Print Post Dominator Tree"),
  clEnumVal(postdomfrontier, "Print Postdominance Frontier"),
0);

struct {
  enum Ans AnID;
  Pass *(*PassConstructor)(const string &Message);
} AnTable[] = {
  // Global analyses
  { print             , createPrintFunctionPass                 },
  { intervals         , New<FunctionPass, IntervalPartition>    },
  { loops             , New<FunctionPass, LoopInfo>             },
  { instforest        , Create<PrinterPass<InstForestHelper> >  },
  { indvars           , Create<PrinterPass<IndVars> >           },
  { exprs             , Create<PrinterPass<Exprs> >             },

  // IP Analyses...
  { printmodule       , createPrintModulePass             },
  { printusedtypes    , New<Pass, FindUsedTypes>          },
  { callgraph         , New<Pass, CallGraph>              },
  { datastructure     , New<Pass, LocalDataStructures>    },
  { unsafepointertypes, New<Pass, FindUnsafePointerTypes> },

  // Dominator analyses
  { domset            , New<FunctionPass, DominatorSet>        },
  { idom              , New<FunctionPass, ImmediateDominators> },
  { domtree           , New<FunctionPass, DominatorTree>       },
  { domfrontier       , New<FunctionPass, DominanceFrontier>   },

  { postdomset        , New<FunctionPass, DominatorSet, DominatorSet::PostDomID> },
  { postidom          , New<FunctionPass, ImmediateDominators, ImmediateDominators::PostDomID> },
  { postdomtree       , New<FunctionPass, DominatorTree, DominatorTree::PostDomID> },
  { postdomfrontier   , New<FunctionPass, DominanceFrontier, DominanceFrontier::PostDomID> },
};

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm analysis printer tool\n");

  Module *CurMod = 0;
  try {
    CurMod = ParseBytecodeFile(InputFilename);
    if (!CurMod && !(CurMod = ParseAssemblyFile(InputFilename))){
      std::cerr << "Input file didn't read correctly.\n";
      return 1;
    }
  } catch (const ParseException &E) {
    std::cerr << E.getMessage() << "\n";
    return 1;
  }

  // Create a PassManager to hold and optimize the collection of passes we are
  // about to build...
  //
  PassManager Analyses;

  // Loop over all of the analyses looking for analyses to run...
  for (unsigned i = 0; i < AnalysesList.size(); ++i) {
    enum Ans AnalysisPass = AnalysesList[i];

    for (unsigned j = 0; j < sizeof(AnTable)/sizeof(AnTable[0]); ++j) {
      if (AnTable[j].AnID == AnalysisPass) {
        string Message;
        if (!Quiet)
          Message = "\nRunning: '" +
            string(AnalysesList.getArgDescription(AnalysisPass)) + "' analysis";
        Analyses.add(AnTable[j].PassConstructor(Message));
        break;                       // get an error later
      }
    }
  }

  Analyses.run(*CurMod);

  delete CurMod;
  return 0;
}
<commit_msg>Add support for bottom up closure of ds analysis<commit_after>//===----------------------------------------------------------------------===//
// The LLVM analyze utility
//
// This utility is designed to print out the results of running various analysis
// passes on a program.  This is useful for understanding a program, or for
// debugging an analysis pass.
//
//  analyze --help           - Output information about command line switches
//  analyze --quiet          - Do not print analysis name before output
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/iPHINode.h"
#include "llvm/Type.h"
#include "llvm/PassManager.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Analysis/Writer.h"
#include "llvm/Analysis/InstForest.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/IntervalPartition.h"
#include "llvm/Analysis/Expressions.h"
#include "llvm/Analysis/InductionVariable.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/DataStructure.h"
#include "llvm/Analysis/FindUnsafePointerTypes.h"
#include "llvm/Analysis/FindUsedTypes.h"
#include "llvm/Support/InstIterator.h"
#include "Support/CommandLine.h"
#include <algorithm>

using std::ostream;
using std::string;

//===----------------------------------------------------------------------===//
// printPass - Specify how to print out a pass.  For most passes, the standard
// way of using operator<< works great, so we use it directly...
//
template<class PassType>
static void printPass(PassType &P, ostream &O, Module &M) {
  O << P;
}

template<class PassType>
static void printPass(PassType &P, ostream &O, Function &F) {
  O << P;
}

// Other classes require more information to print out information, so we
// specialize the template here for them...
//
template<>
static void printPass(LocalDataStructures &P, ostream &O, Module &M) {
  P.print(O, &M);
}
template<>
static void printPass(BUDataStructures &P, ostream &O, Module &M) {
  P.print(O, &M);
}

template<>
static void printPass(FindUsedTypes &FUT, ostream &O, Module &M) {
  FUT.printTypes(O, &M);
}

template<>
static void printPass(FindUnsafePointerTypes &FUPT, ostream &O, Module &M) {
  FUPT.printResults(&M, O);
}

template <class PassType, class PassName>
class PassPrinter;  // Do not implement

template <class PassName>
class PassPrinter<Pass, PassName> : public Pass {
  const string Message;
  const AnalysisID ID;
public:
  PassPrinter(const string &M, AnalysisID id) : Message(M), ID(id) {}

  const char *getPassName() const { return "IP Pass Printer"; }

  virtual bool run(Module &M) {
    std::cout << Message << "\n";
    printPass(getAnalysis<PassName>(ID), std::cout, M);
    return false;
  }

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequired(ID);
  }
};

template <class PassName>
class PassPrinter<FunctionPass, PassName> : public FunctionPass {
  const string Message;
  const AnalysisID ID;
public:
  PassPrinter(const string &M, AnalysisID id) : Message(M), ID(id) {}

    const char *getPassName() const { return "Function Pass Printer"; }

  virtual bool runOnFunction(Function &F) {
    std::cout << Message << " on function '" << F.getName() << "'\n";
    printPass(getAnalysis<PassName>(ID), std::cout, F);
    return false;
  }

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequired(ID);
    AU.setPreservesAll();
  }
};

template <class PassType, class PassName, AnalysisID &ID>
Pass *New(const string &Message) {
  return new PassPrinter<PassType, PassName>(Message, ID);
}
template <class PassType, class PassName>
Pass *New(const string &Message) {
  return new PassPrinter<PassType, PassName>(Message, PassName::ID);
}

Pass *createPrintFunctionPass(const string &Message) {
  return new PrintFunctionPass(Message, &std::cout);
}
Pass *createPrintModulePass(const string &Message) {
  return new PrintModulePass(&std::cout);
}

struct InstForestHelper : public FunctionPass {
  const char *getPassName() const { return "InstForest Printer"; }

  void doit(Function &F) {
    std::cout << InstForest<char>(&F);
  }

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.setPreservesAll();
  }
};

struct IndVars : public FunctionPass {
  const char *getPassName() const { return "IndVars Printer"; }

  void doit(Function &F) {
    LoopInfo &LI = getAnalysis<LoopInfo>();
    for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
      if (PHINode *PN = dyn_cast<PHINode>(*I)) {
        InductionVariable IV(PN, &LI);
        if (IV.InductionType != InductionVariable::Unknown)
          std::cout << IV;
      }
  }

  void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequired(LoopInfo::ID);
    AU.setPreservesAll();
  }
};

struct Exprs : public FunctionPass {
  const char *getPassName() const { return "Expression Printer"; }

  static void doit(Function &F) {
    std::cout << "Classified expressions for: " << F.getName() << "\n";
    for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
      std::cout << *I;

      if ((*I)->getType() == Type::VoidTy) continue;
      analysis::ExprType R = analysis::ClassifyExpression(*I);
      if (R.Var == *I) continue;  // Doesn't tell us anything

      std::cout << "\t\tExpr =";
      switch (R.ExprTy) {
      case analysis::ExprType::ScaledLinear:
        WriteAsOperand(std::cout << "(", (Value*)R.Scale) << " ) *";
        // fall through
      case analysis::ExprType::Linear:
        WriteAsOperand(std::cout << "(", R.Var) << " )";
        if (R.Offset == 0) break;
        else std::cout << " +";
        // fall through
      case analysis::ExprType::Constant:
        if (R.Offset) WriteAsOperand(std::cout, (Value*)R.Offset);
        else std::cout << " 0";
        break;
      }
      std::cout << "\n\n";
    }
  }
  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.setPreservesAll();
  }
};

template<class TraitClass>
class PrinterPass : public TraitClass {
  const string Message;
public:
  PrinterPass(const string &M) : Message(M) {}

  virtual bool runOnFunction(Function &F) {
    std::cout << Message << " on function '" << F.getName() << "'\n";

    TraitClass::doit(F);
    return false;
  }
};

template<class PassClass>
Pass *Create(const string &Message) {
  return new PassClass(Message);
}

enum Ans {
  // global analyses
  print, intervals, exprs, instforest, loops, indvars,

  // ip analyses
  printmodule, callgraph, datastructure, budatastructure,
  printusedtypes, unsafepointertypes,

  domset, idom, domtree, domfrontier,
  postdomset, postidom, postdomtree, postdomfrontier,
};

cl::String InputFilename ("", "Load <arg> file to analyze", cl::NoFlags, "-");
cl::Flag   Quiet         ("q", "Don't print analysis pass names");
cl::Alias  QuietA        ("quiet", "Alias for -q", cl::NoFlags, Quiet);
cl::EnumList<enum Ans> AnalysesList(cl::NoFlags,
  clEnumVal(print          , "Print each function"),
  clEnumVal(intervals      , "Print Interval Partitions"),
  clEnumVal(exprs          , "Classify Expressions"),
  clEnumVal(instforest     , "Print Instruction Forest"),
  clEnumVal(loops          , "Print natural loops"),
  clEnumVal(indvars        , "Print Induction Variables"),

  clEnumVal(printmodule    , "Print entire module"),
  clEnumVal(callgraph      , "Print Call Graph"),
  clEnumVal(datastructure  , "Print data structure information"),
  clEnumVal(budatastructure, "Print bottom-up data structure information"),
  clEnumVal(printusedtypes , "Print types used by module"),
  clEnumVal(unsafepointertypes, "Print unsafe pointer types"),

  clEnumVal(domset         , "Print Dominator Sets"),
  clEnumVal(idom           , "Print Immediate Dominators"),
  clEnumVal(domtree        , "Print Dominator Tree"),
  clEnumVal(domfrontier    , "Print Dominance Frontier"),

  clEnumVal(postdomset     , "Print Postdominator Sets"),
  clEnumVal(postidom       , "Print Immediate Postdominators"),
  clEnumVal(postdomtree    , "Print Post Dominator Tree"),
  clEnumVal(postdomfrontier, "Print Postdominance Frontier"),
0);

struct {
  enum Ans AnID;
  Pass *(*PassConstructor)(const string &Message);
} AnTable[] = {
  // Global analyses
  { print             , createPrintFunctionPass                 },
  { intervals         , New<FunctionPass, IntervalPartition>    },
  { loops             , New<FunctionPass, LoopInfo>             },
  { instforest        , Create<PrinterPass<InstForestHelper> >  },
  { indvars           , Create<PrinterPass<IndVars> >           },
  { exprs             , Create<PrinterPass<Exprs> >             },

  // IP Analyses...
  { printmodule       , createPrintModulePass             },
  { printusedtypes    , New<Pass, FindUsedTypes>          },
  { callgraph         , New<Pass, CallGraph>              },
  { datastructure     , New<Pass, LocalDataStructures>    },
  { budatastructure   , New<Pass, BUDataStructures>       },
  { unsafepointertypes, New<Pass, FindUnsafePointerTypes> },

  // Dominator analyses
  { domset            , New<FunctionPass, DominatorSet>        },
  { idom              , New<FunctionPass, ImmediateDominators> },
  { domtree           , New<FunctionPass, DominatorTree>       },
  { domfrontier       , New<FunctionPass, DominanceFrontier>   },

  { postdomset        , New<FunctionPass, DominatorSet, DominatorSet::PostDomID> },
  { postidom          , New<FunctionPass, ImmediateDominators, ImmediateDominators::PostDomID> },
  { postdomtree       , New<FunctionPass, DominatorTree, DominatorTree::PostDomID> },
  { postdomfrontier   , New<FunctionPass, DominanceFrontier, DominanceFrontier::PostDomID> },
};

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm analysis printer tool\n");

  Module *CurMod = 0;
  try {
    CurMod = ParseBytecodeFile(InputFilename);
    if (!CurMod && !(CurMod = ParseAssemblyFile(InputFilename))){
      std::cerr << "Input file didn't read correctly.\n";
      return 1;
    }
  } catch (const ParseException &E) {
    std::cerr << E.getMessage() << "\n";
    return 1;
  }

  // Create a PassManager to hold and optimize the collection of passes we are
  // about to build...
  //
  PassManager Analyses;

  // Loop over all of the analyses looking for analyses to run...
  for (unsigned i = 0; i < AnalysesList.size(); ++i) {
    enum Ans AnalysisPass = AnalysesList[i];

    for (unsigned j = 0; j < sizeof(AnTable)/sizeof(AnTable[0]); ++j) {
      if (AnTable[j].AnID == AnalysisPass) {
        string Message;
        if (!Quiet)
          Message = "\nRunning: '" +
            string(AnalysesList.getArgDescription(AnalysisPass)) + "' analysis";
        Analyses.add(AnTable[j].PassConstructor(Message));
        break;                       // get an error later
      }
    }
  }

  Analyses.run(*CurMod);

  delete CurMod;
  return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cppdep.cxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 00:48:05 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_tools.hxx"

#include <stdio.h>
#include <string.h>

#include <unistd.h>

#include <sys/stat.h>
#include <stream.hxx>
#include "cppdep.hxx"

//#define TEST

CppDep::CppDep( ByteString aFileName )
{
    aSourceFile = aFileName;

    pSearchPath = new ByteStringList;
    pFileList = new ByteStringList;
}

CppDep::CppDep()
{
    pSources = new ByteStringList;
    pSearchPath = new ByteStringList;
    pFileList = new ByteStringList;
}

CppDep::~CppDep()
{
    delete pSearchPath;
    delete pFileList;
}

void CppDep::Execute()
{
    ULONG nCount = pSources->Count();
    for ( ULONG n=0; n<nCount;n++)
    {
        ByteString *pStr = pSources->GetObject(n);
        Search( *pStr );
    }
}

BOOL CppDep::AddSearchPath( const char* aPath )
{
    ByteString *pStr = new ByteString( aPath );
    pSearchPath->Insert( pStr, LIST_APPEND );
    return FALSE;
}

BOOL CppDep::AddSource( const char* aSource )
{
    ByteString *pStr = new ByteString( aSource );
    pSources->Insert( pStr, LIST_APPEND );
    return FALSE;
}

BOOL CppDep::Search( ByteString aFileName )
{
#ifdef DEBUG_VERBOSE
    fprintf( stderr, "SEARCH : %s\n", aFileName.GetBuffer());
#endif
    BOOL bRet = FALSE;

    SvFileStream aFile;
    ByteString aReadLine;

    UniString suFileName( aFileName, gsl_getSystemTextEncoding());

    aFile.Open( suFileName, STREAM_READ );
    while ( aFile.ReadLine( aReadLine ))
    {
        USHORT nPos = aReadLine.Search( "include" );
        if ( nPos != STRING_NOTFOUND  )
        {
#ifdef DEBUG_VERBOSE
            fprintf( stderr, "found : %d %s\n", nPos, aReadLine.GetBuffer() );
#endif
            ByteString aResult = IsIncludeStatement( aReadLine );
#ifdef DEBUG_VERBOSE
            fprintf( stderr, "Result : %s\n", aResult.GetBuffer() );
#endif

            ByteString aNewFile;
            if ( aResult !="")
            if ( (aNewFile = Exists( aResult )) != "" )
            {
                BOOL bFound = FALSE;
                ULONG nCount = pFileList->Count();
                for ( ULONG i=0; i<nCount; i++ )
                {
                    ByteString *pStr = pFileList->GetObject(i);
                    if ( *pStr == aNewFile )
                        bFound = TRUE;
                }
#ifdef DEBUG_VERBOSE
                fprintf( stderr, "not in list : %d %s\n", nPos, aReadLine.GetBuffer() );
#endif
                if ( !bFound )
                {
                    pFileList->Insert( new ByteString( aNewFile ), LIST_APPEND );
#ifdef DEBUG_VERBOSE
                    fprintf( stderr, " CppDep %s\\\n", aNewFile.GetBuffer() );
#endif
                    Search(aNewFile);
                }
            }
        }
    }
    aFile.Close();

    return bRet;
}

ByteString CppDep::Exists( ByteString aFileName )
{
    char pFullName[1023];
    ByteString aString;

#ifdef DEBUG_VERBOSE
    fprintf( stderr, "Searching %s \n", aFileName.GetBuffer() );
#endif

    ULONG nCount = pSearchPath->Count();
    for ( ULONG n=0; n<nCount; n++)
    {
        struct stat aBuf;
        ByteString *pPathName = pSearchPath->GetObject(n);

        strcpy( pFullName, pPathName->GetBuffer());
        strcat( pFullName, DIR_SEP );
        strcat( pFullName, aFileName.GetBuffer());

#ifdef DEBUG_VERBOSE
        fprintf( stderr, "looking for %s\t ", pFullName );
#endif
        if ( stat( pFullName, &aBuf ) == 0 )
        {
#ifdef DEBUG_VERBOSE
            fprintf( stderr, "Got Dependency ", pFullName );
#endif
#ifdef DEBUG_VERBOSE
            fprintf( stderr, "%s \\\n", pFullName );
#endif

            return ByteString(pFullName);
        }
    }
    return aString;
}

ByteString CppDep::IsIncludeStatement( ByteString aLine )
{
    ByteString aRetStr;
    // WhiteSpacesfressen
    aLine.EraseAllChars(' ');
    aLine.EraseAllChars('\t');
#ifdef DEBUG_VERBOSE
    fprintf( stderr, "now : %s\n", aLine.GetBuffer() );
#endif
    // ist der erste Teil ein #include ?
    ByteString aTmpStr;
    aTmpStr = aLine.Copy( 0, 8 );
#ifdef DEBUG_VERBOSE
    fprintf( stderr, "is include : %s\n", aTmpStr.GetBuffer() );
#endif
    if ( aTmpStr.Equals("#include") )
    {
        aTmpStr = aLine.Erase( 0, 8 );
        USHORT nLen = aLine.Len();
        aLine.Erase( nLen-1, 1 );
        aLine.Erase( 0, 1 );
#ifdef DEBUG_VERBOSE
        fprintf( stderr, "Gotcha : %s\n", aLine.GetBuffer() );
#endif
        aRetStr = aLine;
    }
    return aRetStr;
}

#ifdef TEST

int main( int argc, char **argv )
{
    CppDep *pDep = new CppDep( "cppdep.cxx" );
    pDep->AddSearchPath(".");
    pDep->AddSearchPath("/usr/include");
    pDep->AddSearchPath("/usr/local/include");
    pDep->AddSearchPath("/usr/include/sys");
    pDep->AddSearchPath("/usr/include/X11");
    pDep->Execute();
    delete pDep;
    return 0;
}

#endif
<commit_msg>INTEGRATION: CWS vgbugs07 (1.13.90); FILE MERGED 2007/06/04 13:32:23 vg 1.13.90.1: #i76605# Remove -I .../inc/module hack introduced by hedaburemove01<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cppdep.cxx,v $
 *
 *  $Revision: 1.14 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 22:06:03 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_tools.hxx"

#include <stdio.h>
#include <string.h>

#include <unistd.h>

#include <sys/stat.h>
#include <tools/stream.hxx>
#include "cppdep.hxx"

//#define TEST

CppDep::CppDep( ByteString aFileName )
{
    aSourceFile = aFileName;

    pSearchPath = new ByteStringList;
    pFileList = new ByteStringList;
}

CppDep::CppDep()
{
    pSources = new ByteStringList;
    pSearchPath = new ByteStringList;
    pFileList = new ByteStringList;
}

CppDep::~CppDep()
{
    delete pSearchPath;
    delete pFileList;
}

void CppDep::Execute()
{
    ULONG nCount = pSources->Count();
    for ( ULONG n=0; n<nCount;n++)
    {
        ByteString *pStr = pSources->GetObject(n);
        Search( *pStr );
    }
}

BOOL CppDep::AddSearchPath( const char* aPath )
{
    ByteString *pStr = new ByteString( aPath );
    pSearchPath->Insert( pStr, LIST_APPEND );
    return FALSE;
}

BOOL CppDep::AddSource( const char* aSource )
{
    ByteString *pStr = new ByteString( aSource );
    pSources->Insert( pStr, LIST_APPEND );
    return FALSE;
}

BOOL CppDep::Search( ByteString aFileName )
{
#ifdef DEBUG_VERBOSE
    fprintf( stderr, "SEARCH : %s\n", aFileName.GetBuffer());
#endif
    BOOL bRet = FALSE;

    SvFileStream aFile;
    ByteString aReadLine;

    UniString suFileName( aFileName, gsl_getSystemTextEncoding());

    aFile.Open( suFileName, STREAM_READ );
    while ( aFile.ReadLine( aReadLine ))
    {
        USHORT nPos = aReadLine.Search( "include" );
        if ( nPos != STRING_NOTFOUND  )
        {
#ifdef DEBUG_VERBOSE
            fprintf( stderr, "found : %d %s\n", nPos, aReadLine.GetBuffer() );
#endif
            ByteString aResult = IsIncludeStatement( aReadLine );
#ifdef DEBUG_VERBOSE
            fprintf( stderr, "Result : %s\n", aResult.GetBuffer() );
#endif

            ByteString aNewFile;
            if ( aResult !="")
            if ( (aNewFile = Exists( aResult )) != "" )
            {
                BOOL bFound = FALSE;
                ULONG nCount = pFileList->Count();
                for ( ULONG i=0; i<nCount; i++ )
                {
                    ByteString *pStr = pFileList->GetObject(i);
                    if ( *pStr == aNewFile )
                        bFound = TRUE;
                }
#ifdef DEBUG_VERBOSE
                fprintf( stderr, "not in list : %d %s\n", nPos, aReadLine.GetBuffer() );
#endif
                if ( !bFound )
                {
                    pFileList->Insert( new ByteString( aNewFile ), LIST_APPEND );
#ifdef DEBUG_VERBOSE
                    fprintf( stderr, " CppDep %s\\\n", aNewFile.GetBuffer() );
#endif
                    Search(aNewFile);
                }
            }
        }
    }
    aFile.Close();

    return bRet;
}

ByteString CppDep::Exists( ByteString aFileName )
{
    char pFullName[1023];
    ByteString aString;

#ifdef DEBUG_VERBOSE
    fprintf( stderr, "Searching %s \n", aFileName.GetBuffer() );
#endif

    ULONG nCount = pSearchPath->Count();
    for ( ULONG n=0; n<nCount; n++)
    {
        struct stat aBuf;
        ByteString *pPathName = pSearchPath->GetObject(n);

        strcpy( pFullName, pPathName->GetBuffer());
        strcat( pFullName, DIR_SEP );
        strcat( pFullName, aFileName.GetBuffer());

#ifdef DEBUG_VERBOSE
        fprintf( stderr, "looking for %s\t ", pFullName );
#endif
        if ( stat( pFullName, &aBuf ) == 0 )
        {
#ifdef DEBUG_VERBOSE
            fprintf( stderr, "Got Dependency ", pFullName );
#endif
#ifdef DEBUG_VERBOSE
            fprintf( stderr, "%s \\\n", pFullName );
#endif

            return ByteString(pFullName);
        }
    }
    return aString;
}

ByteString CppDep::IsIncludeStatement( ByteString aLine )
{
    ByteString aRetStr;
    // WhiteSpacesfressen
    aLine.EraseAllChars(' ');
    aLine.EraseAllChars('\t');
#ifdef DEBUG_VERBOSE
    fprintf( stderr, "now : %s\n", aLine.GetBuffer() );
#endif
    // ist der erste Teil ein #include ?
    ByteString aTmpStr;
    aTmpStr = aLine.Copy( 0, 8 );
#ifdef DEBUG_VERBOSE
    fprintf( stderr, "is include : %s\n", aTmpStr.GetBuffer() );
#endif
    if ( aTmpStr.Equals("#include") )
    {
        aTmpStr = aLine.Erase( 0, 8 );
        USHORT nLen = aLine.Len();
        aLine.Erase( nLen-1, 1 );
        aLine.Erase( 0, 1 );
#ifdef DEBUG_VERBOSE
        fprintf( stderr, "Gotcha : %s\n", aLine.GetBuffer() );
#endif
        aRetStr = aLine;
    }
    return aRetStr;
}

#ifdef TEST

int main( int argc, char **argv )
{
    CppDep *pDep = new CppDep( "cppdep.cxx" );
    pDep->AddSearchPath(".");
    pDep->AddSearchPath("/usr/include");
    pDep->AddSearchPath("/usr/local/include");
    pDep->AddSearchPath("/usr/include/sys");
    pDep->AddSearchPath("/usr/include/X11");
    pDep->Execute();
    delete pDep;
    return 0;
}

#endif
<|endoftext|>


<commit_before>/*
 *  This file is part of WinSparkle (http://winsparkle.org)
 *
 *  Copyright (C) 2012-2013 Vaclav Slavik
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 *
 */

#include "updatedownloader.h"
#include "download.h"
#include "settings.h"
#include "ui.h"
#include "error.h"

#include <wx/string.h>

#include <sstream>
#include <rpc.h>
#include <time.h>

namespace winsparkle
{

/*--------------------------------------------------------------------------*
                                  helpers
 *--------------------------------------------------------------------------*/

namespace
{

std::wstring CreateUniqueTempDirectory()
{
    // We need to put downloaded updates into a directory of their own, because
    // if we put it in $TMP, some DLLs could be there and interfere with the
    // installer.
    //
    // This code creates a new randomized directory name and tries to create it;
    // this process is repeated if the directory already exists.
    wchar_t tmpdir[MAX_PATH+1];
    if ( GetTempPath(MAX_PATH+1, tmpdir) == 0 )
        throw Win32Exception("Cannot create temporary directory");

    for ( ;; )
    {
        std::wstring dir(tmpdir);
        dir += L"Update-";

        UUID uuid;
        UuidCreate(&uuid);
        RPC_WSTR uuidStr;
        RPC_STATUS status = UuidToString(&uuid, &uuidStr);
        dir += reinterpret_cast<wchar_t*>(uuidStr);
        RpcStringFree(&uuidStr);

        if ( CreateDirectory(dir.c_str(), NULL) )
            return dir;
        else if ( GetLastError() != ERROR_ALREADY_EXISTS )
            throw Win32Exception("Cannot create temporary directory");
    }
}

struct UpdateDownloadSink : public IDownloadSink
{
    UpdateDownloadSink(Thread& thread, const std::wstring& dir)
        : m_thread(thread),
          m_dir(dir), m_file(NULL),
          m_downloaded(0), m_total(0), m_lastUpdate(-1)
    {}

    ~UpdateDownloadSink() { Close(); }

    void Close()
    {
        if ( m_file )
        {
            fclose(m_file);
            m_file = NULL;
        }
    }

    std::wstring GetFilePath(void) { return m_path; }

    virtual void SetLength(size_t l) { m_total = l; }

    virtual void SetFilename(const std::wstring& filename)
    {
        if ( m_file )
            throw std::runtime_error("Update file already set");

        m_path = m_dir + L"\\" + filename;
        m_file = _wfopen(m_path.c_str(), L"wb");
        if ( !m_file )
            throw std::runtime_error("Cannot save update file");
    }

    virtual void Add(const void *data, size_t len)
    {
        if ( !m_file )
            throw std::runtime_error("Filename is not net");

        m_thread.CheckShouldTerminate();

        if ( fwrite(data, len, 1, m_file) != 1 )
            throw std::runtime_error("Cannot save update file");
        m_downloaded += len;

        // only update at most 10 times/sec so that we don't flood the UI:
        clock_t now = clock();
        if ( now == -1 || m_downloaded == m_total ||
             ((double(now - m_lastUpdate) / CLOCKS_PER_SEC) >= 0.1) )
        {
          UI::NotifyDownloadProgress(m_downloaded, m_total);
          m_lastUpdate = now;
        }
    }

    Thread& m_thread;
    size_t m_downloaded, m_total;
    FILE *m_file;
    std::wstring m_dir;
    std::wstring m_path;
    clock_t m_lastUpdate;
};

} // anonymous namespace

/*--------------------------------------------------------------------------*
                            updater initialization
 *--------------------------------------------------------------------------*/

UpdateDownloader::UpdateDownloader(const Appcast& appcast)
    : Thread("WinSparkle updater"),
      m_appcast(appcast)
{
}

/*--------------------------------------------------------------------------*
                              downloading
 *--------------------------------------------------------------------------*/

void UpdateDownloader::Run()
{
    // no initialization to do, so signal readiness immediately
    SignalReady();

    try
    {
      const std::wstring tmpdir = CreateUniqueTempDirectory();
      Settings::WriteConfigValue("UpdateTempDir", tmpdir);

      UpdateDownloadSink sink(*this, tmpdir);
      DownloadFile(m_appcast.DownloadURL, &sink);
      sink.Close();
      UI::NotifyUpdateDownloaded(sink.GetFilePath());
    }
    catch ( ... )
    {
        UI::NotifyUpdateError();
        throw;
    }
}

/*--------------------------------------------------------------------------*
                               cleanup
 *--------------------------------------------------------------------------*/

void UpdateDownloader::CleanLeftovers()
{
    // Note: this is called at startup. Do not use wxWidgets from this code!

    std::string tmpdir;
    if ( !Settings::ReadConfigValue("UpdateTempDir", tmpdir) )
        return;

    tmpdir.append(1, '\0'); // double NULL-terminate for SHFileOperation

    SHFILEOPSTRUCTA fos = {0};
    fos.wFunc = FO_DELETE;
    fos.pFrom = tmpdir.c_str();
    fos.fFlags = FOF_NO_UI | // Vista+-only
                 FOF_SILENT |
                 FOF_NOCONFIRMATION |
                 FOF_NOERRORUI;

    if ( SHFileOperationA(&fos) == 0 )
    {
        Settings::DeleteConfigValue("UpdateTempDir");
    }
    // else: try another time, this is just a "soft" error
}

} // namespace winsparkle
<commit_msg>Fix CleanLeftovers can't handle unicode path<commit_after>/*
 *  This file is part of WinSparkle (http://winsparkle.org)
 *
 *  Copyright (C) 2012-2013 Vaclav Slavik
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 *
 */

#include "updatedownloader.h"
#include "download.h"
#include "settings.h"
#include "ui.h"
#include "error.h"

#include <wx/string.h>

#include <sstream>
#include <rpc.h>
#include <time.h>

namespace winsparkle
{

/*--------------------------------------------------------------------------*
                                  helpers
 *--------------------------------------------------------------------------*/

namespace
{

std::wstring CreateUniqueTempDirectory()
{
    // We need to put downloaded updates into a directory of their own, because
    // if we put it in $TMP, some DLLs could be there and interfere with the
    // installer.
    //
    // This code creates a new randomized directory name and tries to create it;
    // this process is repeated if the directory already exists.
    wchar_t tmpdir[MAX_PATH+1];
    if ( GetTempPath(MAX_PATH+1, tmpdir) == 0 )
        throw Win32Exception("Cannot create temporary directory");

    for ( ;; )
    {
        std::wstring dir(tmpdir);
        dir += L"Update-";

        UUID uuid;
        UuidCreate(&uuid);
        RPC_WSTR uuidStr;
        RPC_STATUS status = UuidToString(&uuid, &uuidStr);
        dir += reinterpret_cast<wchar_t*>(uuidStr);
        RpcStringFree(&uuidStr);

        if ( CreateDirectory(dir.c_str(), NULL) )
            return dir;
        else if ( GetLastError() != ERROR_ALREADY_EXISTS )
            throw Win32Exception("Cannot create temporary directory");
    }
}

struct UpdateDownloadSink : public IDownloadSink
{
    UpdateDownloadSink(Thread& thread, const std::wstring& dir)
        : m_thread(thread),
          m_dir(dir), m_file(NULL),
          m_downloaded(0), m_total(0), m_lastUpdate(-1)
    {}

    ~UpdateDownloadSink() { Close(); }

    void Close()
    {
        if ( m_file )
        {
            fclose(m_file);
            m_file = NULL;
        }
    }

    std::wstring GetFilePath(void) { return m_path; }

    virtual void SetLength(size_t l) { m_total = l; }

    virtual void SetFilename(const std::wstring& filename)
    {
        if ( m_file )
            throw std::runtime_error("Update file already set");

        m_path = m_dir + L"\\" + filename;
        m_file = _wfopen(m_path.c_str(), L"wb");
        if ( !m_file )
            throw std::runtime_error("Cannot save update file");
    }

    virtual void Add(const void *data, size_t len)
    {
        if ( !m_file )
            throw std::runtime_error("Filename is not net");

        m_thread.CheckShouldTerminate();

        if ( fwrite(data, len, 1, m_file) != 1 )
            throw std::runtime_error("Cannot save update file");
        m_downloaded += len;

        // only update at most 10 times/sec so that we don't flood the UI:
        clock_t now = clock();
        if ( now == -1 || m_downloaded == m_total ||
             ((double(now - m_lastUpdate) / CLOCKS_PER_SEC) >= 0.1) )
        {
          UI::NotifyDownloadProgress(m_downloaded, m_total);
          m_lastUpdate = now;
        }
    }

    Thread& m_thread;
    size_t m_downloaded, m_total;
    FILE *m_file;
    std::wstring m_dir;
    std::wstring m_path;
    clock_t m_lastUpdate;
};

} // anonymous namespace

/*--------------------------------------------------------------------------*
                            updater initialization
 *--------------------------------------------------------------------------*/

UpdateDownloader::UpdateDownloader(const Appcast& appcast)
    : Thread("WinSparkle updater"),
      m_appcast(appcast)
{
}

/*--------------------------------------------------------------------------*
                              downloading
 *--------------------------------------------------------------------------*/

void UpdateDownloader::Run()
{
    // no initialization to do, so signal readiness immediately
    SignalReady();

    try
    {
      const std::wstring tmpdir = CreateUniqueTempDirectory();
      Settings::WriteConfigValue("UpdateTempDir", tmpdir);

      UpdateDownloadSink sink(*this, tmpdir);
      DownloadFile(m_appcast.DownloadURL, &sink);
      sink.Close();
      UI::NotifyUpdateDownloaded(sink.GetFilePath());
    }
    catch ( ... )
    {
        UI::NotifyUpdateError();
        throw;
    }
}

/*--------------------------------------------------------------------------*
                               cleanup
 *--------------------------------------------------------------------------*/

void UpdateDownloader::CleanLeftovers()
{
    // Note: this is called at startup. Do not use wxWidgets from this code!

    std::wstring tmpdir;
    if ( !Settings::ReadConfigValue("UpdateTempDir", tmpdir) )
        return;

    tmpdir.append(1, '\0'); // double NULL-terminate for SHFileOperation

    SHFILEOPSTRUCT fos = {0};
    fos.wFunc = FO_DELETE;
    fos.pFrom = tmpdir.c_str();
    fos.fFlags = FOF_NO_UI | // Vista+-only
                 FOF_SILENT |
                 FOF_NOCONFIRMATION |
                 FOF_NOERRORUI;

    if ( SHFileOperation(&fos) == 0 )
    {
        Settings::DeleteConfigValue("UpdateTempDir");
    }
    // else: try another time, this is just a "soft" error
}

} // namespace winsparkle
<|endoftext|>


<commit_before>/*
 * PhraseTableMemory.cpp
 *
 *  Created on: 28 Oct 2015
 *      Author: hieu
 */

#include <cassert>
#include <boost/foreach.hpp>
#include "PhraseTableMemory.h"
#include "../../PhraseBased/PhraseImpl.h"
#include "../../Phrase.h"
#include "../../System.h"
#include "../../Scores.h"
#include "../../InputPathsBase.h"
#include "../../legacy/InputFileStream.h"
#include "util/exception.hh"

#include "../../PhraseBased/InputPath.h"
#include "../../PhraseBased/TargetPhraseImpl.h"
#include "../../PhraseBased/TargetPhrases.h"

#include "../../SCFG/PhraseImpl.h"
#include "../../SCFG/TargetPhraseImpl.h"
#include "../../SCFG/InputPath.h"
#include "../../SCFG/Stack.h"
#include "../../SCFG/Stacks.h"
#include "../../SCFG/Manager.h"

using namespace std;

namespace Moses2
{

////////////////////////////////////////////////////////////////////////

PhraseTableMemory::PhraseTableMemory(size_t startInd, const std::string &line)
:PhraseTable(startInd, line)
,m_rootPb(NULL)
,m_rootSCFG(NULL)
{
  ReadParameters();
}

PhraseTableMemory::~PhraseTableMemory()
{
  delete m_rootPb;
  delete m_rootSCFG;
}

void PhraseTableMemory::Load(System &system)
{
  FactorCollection &vocab = system.GetVocab();
  MemPool &systemPool = system.GetSystemPool();
  MemPool tmpSourcePool;

  if (system.isPb) {
    m_rootPb = new PBNODE();
  }
  else {
    m_rootSCFG = new SCFGNODE();
  }

  vector<string> toks;
  size_t lineNum = 0;
  InputFileStream strme(m_path);
  string line;
  while (getline(strme, line)) {
    if (++lineNum % 1000000 == 0) {
      cerr << lineNum << " ";
    }
    toks.clear();
    TokenizeMultiCharSeparator(toks, line, "|||");
    UTIL_THROW_IF2(toks.size() < 3, "Wrong format");
    //cerr << "line=" << line << endl;
    //cerr << "system.isPb=" << system.isPb << endl;

    if (system.isPb) {
      PhraseImpl *source = PhraseImpl::CreateFromString(tmpSourcePool, vocab, system,
          toks[0]);
      //cerr << "created soure" << endl;
      TargetPhraseImpl *target = TargetPhraseImpl::CreateFromString(systemPool, *this, system,
          toks[1]);
      //cerr << "created target" << endl;
      target->GetScores().CreateFromString(toks[2], *this, system, true);
      //cerr << "created scores:" << *target << endl;

      // properties
      if (toks.size() == 7) {
        //target->properties = (char*) system.systemPool.Allocate(toks[6].size() + 1);
        //strcpy(target->properties, toks[6].c_str());
      }

      system.featureFunctions.EvaluateInIsolation(systemPool, system, *source,
          *target);
      //cerr << "EvaluateInIsolation:" << *target << endl;
      m_rootPb->AddRule(*source, target);

    }
    else {
      SCFG::PhraseImpl *source = SCFG::PhraseImpl::CreateFromString(tmpSourcePool, vocab, system,
          toks[0]);
      //cerr << "created source:" << *source << endl;
      SCFG::TargetPhraseImpl *target = SCFG::TargetPhraseImpl::CreateFromString(systemPool, *this,
          system, toks[1]);
      target->SetAlignmentInfo(toks[3]);
      //cerr << "created target " << *target << " source=" << *source << endl;

      target->GetScores().CreateFromString(toks[2], *this, system, true);
      //cerr << "created scores:" << *target << endl;

      // properties
      if (toks.size() == 7) {
        //target->properties = (char*) system.systemPool.Allocate(toks[6].size() + 1);
        //strcpy(target->properties, toks[6].c_str());
      }

      system.featureFunctions.EvaluateInIsolation(systemPool, system, *source,
          *target);
      //cerr << "EvaluateInIsolation:" << *target << endl;
      m_rootSCFG->AddRule(*source, target);
    }
  }

  if (system.isPb) {
    m_rootPb->SortAndPrune(m_tableLimit, systemPool, system);
    cerr << "root=" << &m_rootPb << endl;
  }
  else {
    m_rootSCFG->SortAndPrune(m_tableLimit, systemPool, system);
    cerr << "root=" << &m_rootPb << endl;
  }
  /*
  BOOST_FOREACH(const PtMem::Node<Word>::Children::value_type &valPair, m_rootPb.GetChildren()) {
    const Word &word = valPair.first;
    cerr << word << " ";
  }
  cerr << endl;
  */
}

TargetPhrases* PhraseTableMemory::Lookup(const Manager &mgr, MemPool &pool,
    InputPath &inputPath) const
{
  const SubPhrase<Moses2::Word> &phrase = inputPath.subPhrase;
  TargetPhrases *tps = m_rootPb->Find(phrase);
  return tps;
}

void PhraseTableMemory::InitActiveChart(MemPool &pool, SCFG::InputPath &path) const
{
  size_t ptInd = GetPtInd();
  ActiveChartEntryMem *chartEntry = new (pool.Allocate<ActiveChartEntryMem>()) ActiveChartEntryMem(pool, *m_rootSCFG);
  path.AddActiveChartEntry(ptInd, chartEntry);
}

void PhraseTableMemory::Lookup(MemPool &pool,
    const SCFG::Manager &mgr,
    size_t maxChartSpan,
    const SCFG::Stacks &stacks,
    SCFG::InputPath &path) const
{
  if (path.range.GetNumWordsCovered() > maxChartSpan) {
    return;
  }
  /*
  cerr << GetName() << " " << GetPtInd()
      << " maxChartSpan=" << maxChartSpan
      << " path=" << path << endl;
  */
  size_t endPos = path.range.GetEndPos();
  const SCFG::InputPath *prevPath;
  prevPath = static_cast<const SCFG::InputPath*>(path.prefixPath);
  UTIL_THROW_IF2(prevPath == NULL, "prefixPath == NULL");

  // TERMINAL
  const SCFG::Word &lastWord = path.subPhrase.Back();

  //cerr << "PhraseTableMemory lastWord=" << lastWord << endl;
  //cerr << "path=" << path << endl;
  const SCFG::InputPath &subPhrasePath = *mgr.GetInputPaths().GetMatrix().GetValue(endPos, 1);

  LookupGivenWord(pool, *prevPath, lastWord, NULL, subPhrasePath.range, path);

  // NON-TERMINAL
  //const SCFG::InputPath *prefixPath = static_cast<const SCFG::InputPath*>(path.prefixPath);
  while (prevPath) {
    const Range &prevRange = prevPath->range;
    //cerr << "prevRange=" << prevRange << endl;

    size_t startPos = prevRange.GetEndPos() + 1;
    size_t ntSize = endPos - startPos + 1;
    const SCFG::InputPath &subPhrasePath = *mgr.GetInputPaths().GetMatrix().GetValue(startPos, ntSize);

    LookupNT(pool, subPhrasePath.range, *prevPath, stacks, path);

    prevPath = static_cast<const SCFG::InputPath*>(prevPath->prefixPath);
  }
}

void PhraseTableMemory::LookupUnary(
    MemPool &pool,
    const SCFG::Manager &mgr,
    const SCFG::Stacks &stacks,
    SCFG::InputPath &path) const
{
  //cerr << "LookupUnary" << endl;
  //size_t activeEntriesBefore = path.GetActiveChart(GetPtInd()).entries.size();

  size_t startPos = path.range.GetStartPos();
  const SCFG::InputPath *prevPath = mgr.GetInputPaths().GetMatrix().GetValue(startPos, 0);
  LookupNT(pool, path.range, *prevPath, stacks, path);

  //size_t activeEntriesAfter = path.GetActiveChart(GetPtInd()).entries.size();
  //cerr << "  activeEntries " << (activeEntriesAfter - activeEntriesBefore)  << endl;
}

void PhraseTableMemory::LookupNT(
    MemPool &pool,
    const Moses2::Range &subPhraseRange,
    const SCFG::InputPath &prevPath,
    const SCFG::Stacks &stacks,
    SCFG::InputPath &outPath) const
{
  size_t endPos = outPath.range.GetEndPos();

  const Range &prevRange = prevPath.range;
  //cerr << "prevRange=" << prevRange << endl;

  size_t startPos = prevRange.GetEndPos() + 1;
  size_t ntSize = endPos - startPos + 1;

  const SCFG::Stack &ntStack = stacks.GetStack(startPos, ntSize);
  const SCFG::Stack::Coll &coll = ntStack.GetColl();

  /*
  cerr << "    LookupNT subPhrasePath=" << subPhrasePath
      << " prevPath=" << &prevPath << " " << prevPath
      << " stack=" << coll.size() << endl;
  */

  BOOST_FOREACH (const SCFG::Stack::Coll::value_type &valPair, coll) {
    const SCFG::Word &ntSought = valPair.first;
    const Moses2::HypothesisColl *hypos = valPair.second;
    //cerr << "ntSought=" << ntSought << ntSought.isNonTerminal << endl;
    LookupGivenWord(pool, prevPath, ntSought, hypos, subPhraseRange, outPath);
  }
}

void PhraseTableMemory::LookupGivenWord(
    MemPool &pool,
    const SCFG::InputPath &prevPath,
    const SCFG::Word &wordSought,
    const Moses2::HypothesisColl *hypos,
    const Moses2::Range &subPhraseRange,
    SCFG::InputPath &outPath) const
{
  size_t ptInd = GetPtInd();

  /*
  cerr << "  wordSought=" << wordSought
      << " prevPath=" << &prevPath << " " << prevPath
      << " subPhrasePath=" << &subPhrasePath << " " << subPhrasePath
      << endl;
  */

  BOOST_FOREACH(const SCFG::ActiveChartEntry *entry, *prevPath.GetActiveChart(ptInd).entries) {
    const ActiveChartEntryMem *entryCast = static_cast<const ActiveChartEntryMem*>(entry);
    //cerr << "    entry=" << entry;

    LookupGivenNode(pool, *entryCast, wordSought, hypos, subPhraseRange, outPath);
  }
}

void PhraseTableMemory::LookupGivenNode(
    MemPool &pool,
    const ActiveChartEntryMem &prevEntry,
    const SCFG::Word &wordSought,
    const Moses2::HypothesisColl *hypos,
    const Moses2::Range &subPhraseRange,
    SCFG::InputPath &outPath) const
{
  const SCFGNODE &prevNode = prevEntry.node;
  UTIL_THROW_IF2(&prevNode == NULL, "node == NULL");

  size_t ptInd = GetPtInd();
  const SCFGNODE *nextNode = prevNode.Find(wordSought);

  /*
  cerr << "    finding " << wordSought
      << " from " << &node
      << " found " << nextNode << endl;

  if (nextNode == NULL) {
    cerr << "      " << wordSought << "(" << wordSought.hash() << ")"
        << " node contains:";
    node.Debug();
    cerr << endl;
  }
  */

  if (nextNode) {
    // new entries
    ActiveChartEntryMem *chartEntry = new (pool.Allocate<ActiveChartEntryMem>()) ActiveChartEntryMem(pool, *nextNode, prevEntry);

    SCFG::SymbolBind &symbolBind = *chartEntry->symbolBinds;
    symbolBind.Add(subPhraseRange, wordSought, hypos);
    //cerr << "new symbolBind=" << symbolBind << endl;

    outPath.AddActiveChartEntry(ptInd, chartEntry);

    // there are some rules
    AddTargetPhrasesToPath(pool, *nextNode, symbolBind, outPath);
  }
}

void PhraseTableMemory::AddTargetPhrasesToPath(
    MemPool &pool,
    const SCFGNODE &node,
    const SCFG::SymbolBind &symbolBind,
    SCFG::InputPath &outPath) const
{
  const SCFG::TargetPhrases *tps = node.GetTargetPhrases();
  if (tps) {
    SCFG::TargetPhrases::const_iterator iter;
    for (iter = tps->begin(); iter != tps->end(); ++iter) {
      const SCFG::TargetPhraseImpl *tp = *iter;
      //cerr << "tpCast=" << *tp << endl;
      outPath.AddTargetPhrase(pool, *this, symbolBind, tp);
    }
  }
}

}

<commit_msg>debug<commit_after>/*
 * PhraseTableMemory.cpp
 *
 *  Created on: 28 Oct 2015
 *      Author: hieu
 */

#include <cassert>
#include <boost/foreach.hpp>
#include "PhraseTableMemory.h"
#include "../../PhraseBased/PhraseImpl.h"
#include "../../Phrase.h"
#include "../../System.h"
#include "../../Scores.h"
#include "../../InputPathsBase.h"
#include "../../legacy/InputFileStream.h"
#include "util/exception.hh"

#include "../../PhraseBased/InputPath.h"
#include "../../PhraseBased/TargetPhraseImpl.h"
#include "../../PhraseBased/TargetPhrases.h"

#include "../../SCFG/PhraseImpl.h"
#include "../../SCFG/TargetPhraseImpl.h"
#include "../../SCFG/InputPath.h"
#include "../../SCFG/Stack.h"
#include "../../SCFG/Stacks.h"
#include "../../SCFG/Manager.h"

using namespace std;

namespace Moses2
{

////////////////////////////////////////////////////////////////////////

PhraseTableMemory::PhraseTableMemory(size_t startInd, const std::string &line)
:PhraseTable(startInd, line)
,m_rootPb(NULL)
,m_rootSCFG(NULL)
{
  ReadParameters();
}

PhraseTableMemory::~PhraseTableMemory()
{
  delete m_rootPb;
  delete m_rootSCFG;
}

void PhraseTableMemory::Load(System &system)
{
  FactorCollection &vocab = system.GetVocab();
  MemPool &systemPool = system.GetSystemPool();
  MemPool tmpSourcePool;

  if (system.isPb) {
    m_rootPb = new PBNODE();
  }
  else {
    m_rootSCFG = new SCFGNODE();
  }

  vector<string> toks;
  size_t lineNum = 0;
  InputFileStream strme(m_path);
  string line;
  while (getline(strme, line)) {
    if (++lineNum % 1000000 == 0) {
      cerr << lineNum << " ";
    }
    toks.clear();
    TokenizeMultiCharSeparator(toks, line, "|||");
    UTIL_THROW_IF2(toks.size() < 3, "Wrong format");
    //cerr << "line=" << line << endl;
    //cerr << "system.isPb=" << system.isPb << endl;

    if (system.isPb) {
      PhraseImpl *source = PhraseImpl::CreateFromString(tmpSourcePool, vocab, system,
          toks[0]);
      //cerr << "created soure" << endl;
      TargetPhraseImpl *target = TargetPhraseImpl::CreateFromString(systemPool, *this, system,
          toks[1]);
      //cerr << "created target" << endl;
      target->GetScores().CreateFromString(toks[2], *this, system, true);
      //cerr << "created scores:" << *target << endl;

      // properties
      if (toks.size() == 7) {
        //target->properties = (char*) system.systemPool.Allocate(toks[6].size() + 1);
        //strcpy(target->properties, toks[6].c_str());
      }

      system.featureFunctions.EvaluateInIsolation(systemPool, system, *source,
          *target);
      //cerr << "EvaluateInIsolation:" << *target << endl;
      m_rootPb->AddRule(*source, target);

    }
    else {
      SCFG::PhraseImpl *source = SCFG::PhraseImpl::CreateFromString(tmpSourcePool, vocab, system,
          toks[0]);
      //cerr << "created source:" << *source << endl;
      SCFG::TargetPhraseImpl *target = SCFG::TargetPhraseImpl::CreateFromString(systemPool, *this,
          system, toks[1]);
      target->SetAlignmentInfo(toks[3]);
      //cerr << "created target " << *target << " source=" << *source << endl;

      target->GetScores().CreateFromString(toks[2], *this, system, true);
      //cerr << "created scores:" << *target << endl;

      // properties
      if (toks.size() == 7) {
        //target->properties = (char*) system.systemPool.Allocate(toks[6].size() + 1);
        //strcpy(target->properties, toks[6].c_str());
      }

      system.featureFunctions.EvaluateInIsolation(systemPool, system, *source,
          *target);
      //cerr << "EvaluateInIsolation:" << *target << endl;
      m_rootSCFG->AddRule(*source, target);
    }
  }

  if (system.isPb) {
    m_rootPb->SortAndPrune(m_tableLimit, systemPool, system);
    cerr << "root=" << &m_rootPb << endl;
  }
  else {
    m_rootSCFG->SortAndPrune(m_tableLimit, systemPool, system);
    cerr << "root=" << &m_rootPb << endl;
  }
  /*
  BOOST_FOREACH(const PtMem::Node<Word>::Children::value_type &valPair, m_rootPb.GetChildren()) {
    const Word &word = valPair.first;
    cerr << word << " ";
  }
  cerr << endl;
  */
}

TargetPhrases* PhraseTableMemory::Lookup(const Manager &mgr, MemPool &pool,
    InputPath &inputPath) const
{
  const SubPhrase<Moses2::Word> &phrase = inputPath.subPhrase;
  TargetPhrases *tps = m_rootPb->Find(phrase);
  return tps;
}

void PhraseTableMemory::InitActiveChart(MemPool &pool, SCFG::InputPath &path) const
{
  size_t ptInd = GetPtInd();
  ActiveChartEntryMem *chartEntry = new (pool.Allocate<ActiveChartEntryMem>()) ActiveChartEntryMem(pool, *m_rootSCFG);
  path.AddActiveChartEntry(ptInd, chartEntry);
}

void PhraseTableMemory::Lookup(MemPool &pool,
    const SCFG::Manager &mgr,
    size_t maxChartSpan,
    const SCFG::Stacks &stacks,
    SCFG::InputPath &path) const
{
  if (path.range.GetNumWordsCovered() > maxChartSpan) {
    return;
  }
  /*
  cerr << GetName() << " " << GetPtInd()
      << " maxChartSpan=" << maxChartSpan
      << " path=" << path << endl;
  */
  size_t endPos = path.range.GetEndPos();
  const SCFG::InputPath *prevPath;
  prevPath = static_cast<const SCFG::InputPath*>(path.prefixPath);
  UTIL_THROW_IF2(prevPath == NULL, "prefixPath == NULL");

  // TERMINAL
  const SCFG::Word &lastWord = path.subPhrase.Back();

  //cerr << "PhraseTableMemory lastWord=" << lastWord << endl;
  //cerr << "path=" << path << endl;
  const SCFG::InputPath &subPhrasePath = *mgr.GetInputPaths().GetMatrix().GetValue(endPos, 1);

  LookupGivenWord(pool, *prevPath, lastWord, NULL, subPhrasePath.range, path);

  // NON-TERMINAL
  //const SCFG::InputPath *prefixPath = static_cast<const SCFG::InputPath*>(path.prefixPath);
  while (prevPath) {
    const Range &prevRange = prevPath->range;
    //cerr << "prevRange=" << prevRange << endl;

    size_t startPos = prevRange.GetEndPos() + 1;
    size_t ntSize = endPos - startPos + 1;
    const SCFG::InputPath &subPhrasePath = *mgr.GetInputPaths().GetMatrix().GetValue(startPos, ntSize);

    LookupNT(pool, subPhrasePath.range, *prevPath, stacks, path);

    prevPath = static_cast<const SCFG::InputPath*>(prevPath->prefixPath);
  }
}

void PhraseTableMemory::LookupUnary(
    MemPool &pool,
    const SCFG::Manager &mgr,
    const SCFG::Stacks &stacks,
    SCFG::InputPath &path) const
{
  //cerr << "LookupUnary" << endl;
  //size_t activeEntriesBefore = path.GetActiveChart(GetPtInd()).entries.size();

  size_t startPos = path.range.GetStartPos();
  const SCFG::InputPath *prevPath = mgr.GetInputPaths().GetMatrix().GetValue(startPos, 0);
  LookupNT(pool, path.range, *prevPath, stacks, path);

  //size_t activeEntriesAfter = path.GetActiveChart(GetPtInd()).entries.size();
  //cerr << "  activeEntries " << (activeEntriesAfter - activeEntriesBefore)  << endl;
}

void PhraseTableMemory::LookupNT(
    MemPool &pool,
    const Moses2::Range &subPhraseRange,
    const SCFG::InputPath &prevPath,
    const SCFG::Stacks &stacks,
    SCFG::InputPath &outPath) const
{
  size_t endPos = outPath.range.GetEndPos();

  const Range &prevRange = prevPath.range;
  //cerr << "prevRange=" << prevRange << endl;

  size_t startPos = prevRange.GetEndPos() + 1;
  size_t ntSize = endPos - startPos + 1;

  const SCFG::Stack &ntStack = stacks.GetStack(startPos, ntSize);
  const SCFG::Stack::Coll &stackColl = ntStack.GetColl();

  /*
  cerr << "    LookupNT subPhrasePath=" << subPhrasePath
      << " prevPath=" << &prevPath << " " << prevPath
      << " stack=" << coll.size() << endl;
  */

  BOOST_FOREACH (const SCFG::Stack::Coll::value_type &valPair, stackColl) {
    const SCFG::Word &ntSought = valPair.first;
    const Moses2::HypothesisColl *hypos = valPair.second;
    //cerr << "ntSought=" << ntSought << ntSought.isNonTerminal << endl;
    LookupGivenWord(pool, prevPath, ntSought, hypos, subPhraseRange, outPath);
  }
}

void PhraseTableMemory::LookupGivenWord(
    MemPool &pool,
    const SCFG::InputPath &prevPath,
    const SCFG::Word &wordSought,
    const Moses2::HypothesisColl *hypos,
    const Moses2::Range &subPhraseRange,
    SCFG::InputPath &outPath) const
{
  size_t ptInd = GetPtInd();

  /*
  cerr << "  wordSought=" << wordSought
      << " prevPath=" << &prevPath << " " << prevPath
      << " subPhrasePath=" << &subPhrasePath << " " << subPhrasePath
      << endl;
  */

  BOOST_FOREACH(const SCFG::ActiveChartEntry *entry, *prevPath.GetActiveChart(ptInd).entries) {
    const ActiveChartEntryMem *entryCast = static_cast<const ActiveChartEntryMem*>(entry);
    //cerr << "    entry=" << entry;

    LookupGivenNode(pool, *entryCast, wordSought, hypos, subPhraseRange, outPath);
  }
}

void PhraseTableMemory::LookupGivenNode(
    MemPool &pool,
    const ActiveChartEntryMem &prevEntry,
    const SCFG::Word &wordSought,
    const Moses2::HypothesisColl *hypos,
    const Moses2::Range &subPhraseRange,
    SCFG::InputPath &outPath) const
{
  const SCFGNODE &prevNode = prevEntry.node;
  UTIL_THROW_IF2(&prevNode == NULL, "node == NULL");

  size_t ptInd = GetPtInd();
  const SCFGNODE *nextNode = prevNode.Find(wordSought);

  /*
  cerr << "    finding " << wordSought
      << " from " << &node
      << " found " << nextNode << endl;

  if (nextNode == NULL) {
    cerr << "      " << wordSought << "(" << wordSought.hash() << ")"
        << " node contains:";
    node.Debug();
    cerr << endl;
  }
  */

  if (nextNode) {
    // new entries
    ActiveChartEntryMem *chartEntry = new (pool.Allocate<ActiveChartEntryMem>()) ActiveChartEntryMem(pool, *nextNode, prevEntry);

    SCFG::SymbolBind &symbolBind = *chartEntry->symbolBinds;
    cerr << "BEFORE new symbolBind=" << symbolBind << endl;
    symbolBind.Add(subPhraseRange, wordSought, hypos);
    cerr << "AFTER new symbolBind=" << symbolBind << endl;

    outPath.AddActiveChartEntry(ptInd, chartEntry);

    // there are some rules
    AddTargetPhrasesToPath(pool, *nextNode, symbolBind, outPath);
  }
}

void PhraseTableMemory::AddTargetPhrasesToPath(
    MemPool &pool,
    const SCFGNODE &node,
    const SCFG::SymbolBind &symbolBind,
    SCFG::InputPath &outPath) const
{
  const SCFG::TargetPhrases *tps = node.GetTargetPhrases();
  if (tps) {
    SCFG::TargetPhrases::const_iterator iter;
    for (iter = tps->begin(); iter != tps->end(); ++iter) {
      const SCFG::TargetPhraseImpl *tp = *iter;
      //cerr << "tpCast=" << *tp << endl;
      outPath.AddTargetPhrase(pool, *this, symbolBind, tp);
    }
  }
}

}

<|endoftext|>