<commit_before>#include "compile_type.hpp"

#include "error/compile_type_error.hpp"
#include "core_unique_ids.hpp"
#include "core_utils.hpp"

#include <llvm/IR/DerivedTypes.h>

#include <boost/variant.hpp>

#include <string>
#include <algorithm>

using std::size_t;
using std::string;
using std::stoul;
using std::out_of_range;
using std::invalid_argument;
using std::distance;

using boost::blank;

using llvm::IntegerType;
using llvm::LLVMContext;
using llvm::Type;
using llvm::PointerType;

using namespace symbol_shortcuts;
using namespace compile_type_error;

unsigned long read_bit_width(const symbol& node)
{
    const lit_symbol& bit_width_lit = node.cast_else<lit_symbol>([&]()
    {
        fatal<id("int_invalid_argument_symbol")>(node.source());
    });

    unsigned long width;
    try
    {
        size_t index_after;
        string as_str{bit_width_lit.begin(), bit_width_lit.end()};
        width = stoul(as_str, &index_after);
        if(index_after != as_str.size())
            throw invalid_argument{""};
        if(width == 0 || width > 1024) // TODO: be less conservative
            throw out_of_range{""};
    }
    catch(const invalid_argument&)
    {
        fatal<id("int_invalid_argument_literal")>(bit_width_lit.source());
    }
    catch(const out_of_range&)
    {
        fatal<id("int_out_of_range_bit_width")>(bit_width_lit.source());
    }

    return width;
}

type_info compile_type(const symbol& node, LLVMContext& llvm_context)
{
    const symbol& resolved_node = resolve_refs(node);
    if(resolved_node.is<list_symbol>())
    {
        const list_symbol& type_node = resolved_node.cast<list_symbol>();
        if(type_node.empty())
            fatal<id("empty_list_type")>(type_node.source());
        const id_symbol& type_constructor = type_node[0].cast_else<id_symbol>([&]
        {
            fatal<id("invalid_type_constructor")>(type_node[0].source());
        });

        auto check_arity = [&](const char* type_constructor_name, unsigned int expected_argument_number)
        {
            if(expected_argument_number != type_node.size() - 1)
                fatal<id("invalid_type_constructor_argument_number")>(type_node.source());
        };

        switch(type_constructor.id())
        {
        case unique_ids::INT:
        {
            check_arity("int", 1);
            const symbol& bit_width_node = type_node[1];
            unsigned long bit_width = read_bit_width(bit_width_node);
            Type* llvm_type = IntegerType::get(llvm_context, bit_width);
            return type_info{node, integer_type{bit_width}, llvm_type};
        }
        case unique_ids::PTR:
        {
            check_arity("ptr", 0);
            Type* llvm_type = PointerType::getUnqual(IntegerType::get(llvm_context, 8));
            return type_info{node, pointer_type{}, llvm_type};
        }
        default:
            fatal<id("unknown_type_constructor")>(type_constructor.source());
        }
    }

    const id_symbol& type_node = resolved_node.cast_else<id_symbol>([&]
    {
        fatal<id("invalid_type_node")>(node.source());
    });
    if(type_node.id() != unique_ids::PTR)
        fatal<id("unknown_type_constructor")>(type_node.source());
    Type* llvm_type = PointerType::getUnqual(IntegerType::get(llvm_context, 8));
    return type_info{node, pointer_type{}, llvm_type};
}

<commit_msg>fix bug - missing resolve_refs on constructor<commit_after>#include "compile_type.hpp"

#include "error/compile_type_error.hpp"
#include "core_unique_ids.hpp"
#include "core_utils.hpp"

#include <llvm/IR/DerivedTypes.h>

#include <boost/variant.hpp>

#include <string>
#include <algorithm>

using std::size_t;
using std::string;
using std::stoul;
using std::out_of_range;
using std::invalid_argument;
using std::distance;

using boost::blank;

using llvm::IntegerType;
using llvm::LLVMContext;
using llvm::Type;
using llvm::PointerType;

using namespace symbol_shortcuts;
using namespace compile_type_error;

unsigned long read_bit_width(const symbol& node)
{
    const lit_symbol& bit_width_lit = node.cast_else<lit_symbol>([&]()
    {
        fatal<id("int_invalid_argument_symbol")>(node.source());
    });

    unsigned long width;
    try
    {
        size_t index_after;
        string as_str{bit_width_lit.begin(), bit_width_lit.end()};
        width = stoul(as_str, &index_after);
        if(index_after != as_str.size())
            throw invalid_argument{""};
        if(width == 0 || width > 1024) // TODO: be less conservative
            throw out_of_range{""};
    }
    catch(const invalid_argument&)
    {
        fatal<id("int_invalid_argument_literal")>(bit_width_lit.source());
    }
    catch(const out_of_range&)
    {
        fatal<id("int_out_of_range_bit_width")>(bit_width_lit.source());
    }

    return width;
}

type_info compile_type(const symbol& node, LLVMContext& llvm_context)
{
    const symbol& resolved_node = resolve_refs(node);
    if(resolved_node.is<list_symbol>())
    {
        const list_symbol& type_node = resolved_node.cast<list_symbol>();
        if(type_node.empty())
            fatal<id("empty_list_type")>(type_node.source());
        const symbol& resolved_constructor = resolve_refs(type_node[0]);
        const id_symbol& type_constructor = resolved_constructor.cast_else<id_symbol>([&]
        {
            fatal<id("invalid_type_constructor")>(type_node[0].source());
        });

        auto check_arity = [&](const char* type_constructor_name, unsigned int expected_argument_number)
        {
            if(expected_argument_number != type_node.size() - 1)
                fatal<id("invalid_type_constructor_argument_number")>(type_node.source());
        };

        switch(type_constructor.id())
        {
        case unique_ids::INT:
        {
            check_arity("int", 1);
            const symbol& bit_width_node = type_node[1];
            unsigned long bit_width = read_bit_width(bit_width_node);
            Type* llvm_type = IntegerType::get(llvm_context, bit_width);
            return type_info{node, integer_type{bit_width}, llvm_type};
        }
        case unique_ids::PTR:
        {
            check_arity("ptr", 0);
            Type* llvm_type = PointerType::getUnqual(IntegerType::get(llvm_context, 8));
            return type_info{node, pointer_type{}, llvm_type};
        }
        default:
            fatal<id("unknown_type_constructor")>(type_constructor.source());
        }
    }

    const id_symbol& type_node = resolved_node.cast_else<id_symbol>([&]
    {
        fatal<id("invalid_type_node")>(node.source());
    });
    if(type_node.id() != unique_ids::PTR)
        fatal<id("unknown_type_constructor")>(type_node.source());
    Type* llvm_type = PointerType::getUnqual(IntegerType::get(llvm_context, 8));
    return type_info{node, pointer_type{}, llvm_type};
}

<|endoftext|>


<commit_before>/*****************************************************************************
 *  Copyright (C) 2008-2011 Massachusetts Institute of Technology            *
 *                                                                           *
 *  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           *
 *                                                                           *
 *  This source code is part of the PetaBricks project:                      *
 *    http://projects.csail.mit.edu/petabricks/                              *
 *                                                                           *
 *****************************************************************************/

#include "codegenerator.h"
#include "maximawrapper.h"
#include "transform.h"

#include "common/hash.h"
#include "common/jargs.h"
#include "common/jfilesystem.h"
#include "common/jtunable.h"

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#ifdef HAVE_OPENCL
#include "openclutil.h"
#endif

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#include <fstream>
#include <iostream>
#include <sys/stat.h>
#include <sys/types.h>

const char headertxth[] =
  "// Generated by " PACKAGE " compiler (pbc) v" VERSION " " REVISION_LONG "\n"
  "#include \"petabricks.h\"\n"
  "#ifdef __GNUC__\n"
  "#pragma GCC diagnostic ignored \"-Wunused-variable\"\n"
  "#pragma GCC diagnostic ignored \"-Wunused-parameter\"\n"
  "#pragma GCC diagnostic ignored \"-Wunused-value\"\n"
  "#endif\n"
  "using namespace petabricks;\n\n"
  ;

const char headertxtcpp[] =
  "// Generated by " PACKAGE " compiler (pbc) v" VERSION " " REVISION_LONG "\n"
  "#include \""GENHEADER"\"\n"
  ;

using namespace petabricks;

namespace pbcConfig {
  bool shouldCompile = true;
  bool shouldLink = true;
  std::string theCommonDir;
  std::string theHardcodedConfig;
  std::string theInput;
  std::string theLibDir;
  std::string theMainName;
  std::string theObjDir;
  std::string theObjectFile;
  std::string theOutputBin;
  std::string theOutputInfo;
  std::string theRuntimeDir;
  std::string thePbPreprocessor;
  std::string theBasename;
  int theNJobs = 2;
}
using namespace pbcConfig;

//defined in pbparser.ypp
TransformListPtr parsePbFile(const char* filename);

/* wrapper around popen */
FILE* opensubproc(const std::string& cmd) {
  FILE* p = popen((cmd+" 2>&1").c_str(), "r");
  JTRACE("calling gcc")(cmd);
  JASSERT(p!= 0)(cmd);
  return p;
}

/* wrapper around pclose */
void closesubproc(FILE* p, const std::string& name) {
  std::cerr << name << std::endl;
  while(!feof(p)) {
    char buf[1024];
    memset(buf, 0, sizeof buf);
    if(fread(buf, 1, sizeof buf -1,  p) > 0) {
      std::cerr << buf;
    }
  }
  JASSERT(pclose(p)==0);
}

/**
 * Small helper class used to output cpp files and call gcc
 */
class OutputCode {
  std::string   _cpp;
  std::string   _obj;
  StreamTreePtr _code;
  std::string   _gcccmd;
  FILE*         _gccfd;
public:
  OutputCode(const std::string& basename, CodeGenerator& o)
    : _cpp(basename+".cpp")
    , _obj(basename+".o")
    , _gccfd(0)
  {
    _code = o.startSubfile(basename);

    std::ostringstream os;
    os << CXX " " CXXFLAGS " " CXXDEFS " -c "
       << " -o "  << _obj
       << " "     << _cpp
       << " -I\"" << theLibDir << "\""
       << " -I\"" << theRuntimeDir << "\"";
    _gcccmd = os.str();
  }

  void write() {
    std::ofstream of(_cpp.c_str());
    of << headertxtcpp;
    of << "/* Compile with: \n"
       <<  _gcccmd << "\n"
       << " */\n";
    _code->writeTo(of);
    of.flush();
    of.close();
  }

  void forkCompile() {
    JTRACE(_gcccmd.c_str());
    _gccfd = opensubproc(_gcccmd);
  }

  void waitCompile() {
    closesubproc(_gccfd, "Compile "+_cpp);
  }

  const std::string& objpath() const { return _obj; }

  void writeMakefile(std::ostream& o) {
    o << _obj << ":\n\t"
      << _gcccmd
      << "\n\n";
  }

};

/**
 * Collection of all the output source files of the compiler
 */
class OutputCodeList : public std::vector<OutputCode> {
public:
  void writeHeader(const StreamTreePtr& h) {
    std::ofstream of((theObjDir+"/"GENHEADER).c_str());
    h->writeTo(of);
    of.flush();
    of.close();
  }

  void write() {
    for(iterator i=begin(); i!=end(); ++i)
      i->write();
  }

  void compile() {
    iterator iwrite=begin(), ifork=begin(), iwait=begin();

    JASSERT(theNJobs>=1)(theNJobs);
    for(int i=0; i<theNJobs && iwait!=end(); ++i){
      if(iwrite!=end())
        (iwrite++)->write();
      if(ifork!=end())
        (ifork++)->forkCompile();
    }

    while(iwait!=end()) {
      //invariant: iwrite == ifork > iwait
      if(iwrite!=end())
        (iwrite++)->write();
      if(iwait!=end())
        (iwait++)->waitCompile();
      if(ifork!=end())
        (ifork++)->forkCompile();
    }
    JASSERT(iwrite==end());
    JASSERT(ifork==end());
  }

  std::string mklinkcmd() {
    std::ostringstream os;
    os << CXX " -o " BIN_TMPFILE " " CXXFLAGS;
    for(const_iterator i=begin(); i!=end(); ++i)
      os << " " << i->objpath();
    os << " " CXXLDFLAGS " -L\"" << theLibDir <<"\" -lpbmain -lpbruntime -lpbcommon " CXXLIBS;
    return os.str();
  }

  void link() {
    JTRACE(mklinkcmd().c_str());
    closesubproc(opensubproc(mklinkcmd()), "Link "+theOutputBin);
  }

  void writeMakefile() {
    std::ofstream o("Makefile");
    o << "# Generated by " PACKAGE " compiler (pbc) v" VERSION " " REVISION_LONG "\n";
    o << "# This file is generated only for testing purposes and it not used\n\n";

    o << "all: " BIN_TMPFILE "\n\n";
    for(iterator i=begin(); i!=end(); ++i)
      i->writeMakefile(o);

    o << BIN_TMPFILE << ":";
    for(iterator i=begin(), e=end(); i!=e; ++i)
      o << " " << i->objpath();
    o << "\n\t" << mklinkcmd() << "\n\n";

    o << "clean_bin:\n";
    o << "\trm -f " BIN_TMPFILE "\n\n";

    o << "clean_obj:\n";
    o << "\trm -f *.o\n\n";

    o << "clean_temp:\n";
    o << "\trm -f *~ *.bak *.tmp *.temp\n\n";

    o << "clean: clean_bin clean_obj clean_temp\n";
  }
};

void findMainTransform(const TransformListPtr& t) {
  //find the main transform if it has not been specified
  if(theMainName==""){
    for(TransformList::const_iterator i=t->begin(); i!=t->end(); ++i){
      if((*i)->isMain()){
        JASSERT(theMainName=="")(theMainName)((*i)->name())
          .Text("Two transforms both have the 'main' keyword");
        theMainName = (*i)->name();
      }
    }
    if(theMainName=="") theMainName = t->back()->name();
  }
}

int main( int argc, const char ** argv){

  /*
  #ifdef HAVE_OPENCL
  OpenCLUtil::init();
  OpenCLUtil::printDeviceList();
  OpenCLUtil::deinit();
  exit(-1);
  #endif
  */

  // READ COMMAND LINE:

  OutputCodeList ccfiles;

  jalib::JArgs args(argc, argv);
  std::vector<std::string> inputs;
  if(args.needHelp())
    std::cerr << "OPTIONS:" << std::endl;

  thePbPreprocessor="\""PYTHON"\" \"" +
                    jalib::Filesystem::FindHelperUtility("preprocessor.py")
                    +"\"";

  args.param("input",      inputs).help("input file to compile (*.pbcc)");
  args.param("output",     theOutputBin).help("output binary to be produced");
  args.param("outputinfo", theOutputInfo).help("output *.info file to be produced");
  args.param("outputobj",  theObjectFile).help("output *.o file to be produced");
  args.param("runtimedir", theRuntimeDir).help("directory where petabricks.h may be found");
  args.param("libdir",     theLibDir).help("directory where libpbruntime.a may be found");
  args.param("preproc",    thePbPreprocessor).help("program to use as preprocessor");
  args.param("compile",    shouldCompile).help("disable the compilation step");
  args.param("link",       shouldLink).help("disable the linking step");
  args.param("main",       theMainName).help("transform name to use as program entry point");
  args.param("hardcode",   theHardcodedConfig).help("a config file containing tunables to set to hardcoded values");
  args.param("jobs",       theNJobs).help("number of gcc processes to call at once");

  if(args.param("version").help("print out version number and exit") ){
    std::cerr << PACKAGE " compiler (pbc) v" VERSION " " REVISION_LONG << std::endl;
    return 1;
  }

  args.finishParsing(inputs);

  if(inputs.empty() || args.needHelp()){
    std::cerr << "\n" PACKAGE " compiler (pbc) v" VERSION " " REVISION_SHORT << std::endl;
    std::cerr << "USAGE: " << argv[0] << " [OPTIONS] filename.pbcc" << std::endl;
    std::cerr << "run `" << argv[0] << " --help` for options" << std::endl;
    return 1;
  }

  JASSERT(inputs.size()==1)(inputs.size()).Text("expected exactly one input file");
  theInput = inputs.front();
  if(theRuntimeDir.empty()) theRuntimeDir = jalib::Filesystem::Dirname(jalib::Filesystem::FindHelperUtility("runtime/petabricks.h"));
  if(theLibDir    .empty()) theLibDir     = jalib::Filesystem::Dirname(jalib::Filesystem::FindHelperUtility("libpbruntime.a"));
  if(theOutputBin .empty()) theOutputBin  = jalib::Filesystem::Basename(theInput);
  if(theObjDir.empty())     theObjDir     = theOutputBin + ".obj";
  if(theOutputInfo.empty()) theOutputInfo = theOutputBin + ".info";
  if(theObjectFile.empty()) theObjectFile = theOutputBin + ".o";

  int rv = mkdir(theObjDir.c_str(), 0755);
  if(rv!=0 && errno==EEXIST)
    rv=0, errno=0;
  JASSERT(rv==0)(theObjDir).Text("failed to create objdir");

  if(!theHardcodedConfig.empty())
    CodeGenerator::theHardcodedTunables() = jalib::JTunableManager::loadRaw(theHardcodedConfig);

  JASSERT(jalib::Filesystem::FileExists(theInput))(theInput)
    .Text("input file does not exist");

  // PARSE:

  TransformListPtr t = parsePbFile(theInput.c_str());

  // COMPILE:

  for(TransformList::iterator i=t->begin(); i!=t->end(); ++i){
    (*i)->initialize();
    #ifdef DEBUG
    (*i)->print(std::cout);
    #endif
  }

  for(TransformList::iterator i=t->begin(); i!=t->end(); ++i){
    (*i)->compile();
  }

  findMainTransform(t);

  // CODEGEN:
  StreamTreePtr header = new StreamTree("header");
  StreamTreePtr prefix = header->add(new StreamTree("prefix"));
  CodeGenerator o(header, NULL);

  for(TransformList::iterator i=t->begin(); i!=t->end(); ++i){
    ccfiles.push_back(OutputCode((*i)->name(), o));
    (*i)->generateCode(o);
  }

  // generate misc files:
  o.cg().beginGlobal();
#ifdef SINGLE_SEQ_CUTOFF
  o.createTunable(true, "system.cutoff.sequential", "sequentialcutoff", 64);
#endif
  o.cg().endGlobal();
  ccfiles.push_back(OutputCode(GENMISC, o));
  o.outputTunables(o.os());
  o.comment("A hook called by PetabricksRuntime");
  o.beginFunc("petabricks::PetabricksRuntime::Main*", "petabricksMainTransform");
  o.write("return "+theMainName+"_main::instance();");
  o.endFunc();
  o.comment("A hook called by PetabricksRuntime");
  o.beginFunc( "petabricks::PetabricksRuntime::Main*"
             , "petabricksFindTransform"
             , std::vector<std::string>(1, "const std::string& name"));
  for(TransformList::iterator i=t->begin(); i!=t->end(); ++i){
    (*i)->registerMainInterface(o);
  }
  o.write("return NULL;");
  o.endFunc();

  // generate common header file:
  *prefix << headertxth;
  *prefix << "namespace { \n";
  *prefix << CodeGenerator::theFilePrefix().str();
  *prefix << "} \n";
  o.outputTunableHeaders(*prefix);
  ccfiles.writeHeader(header);

  // dump .info file:
  std::ofstream infofile(theOutputInfo.c_str());
  o.cg().dumpTo(infofile);
  infofile.flush();
  infofile.close();

  char olddir[1024];
  memset(olddir, 0, sizeof olddir);
  JASSERT(olddir==getcwd(olddir, sizeof olddir - 1));
  JASSERT(chdir(theObjDir.c_str())==0)(theObjDir);

  ccfiles.writeMakefile();

  // COMPILE AND LINK:
  if(shouldCompile)
    ccfiles.compile();
  else
    ccfiles.write();

  if(shouldLink) {
    ccfiles.link();
    JASSERT(chdir(olddir)==0)(olddir);
    JASSERT(rename((theObjDir+"/"BIN_TMPFILE).c_str(), theOutputBin.c_str())==0)
      (theObjDir+"/"BIN_TMPFILE)(theOutputBin);
  }else{
    JASSERT(chdir(olddir)==0)(olddir);
  }

#ifdef DEBUG
  MAXIMA.sanityCheck();
#endif

  JTRACE("done")(theInput)(theOutputInfo)(theObjDir)(theOutputBin);
  return 0;
}

<commit_msg>- worker_threads in .info file<commit_after>/*****************************************************************************
 *  Copyright (C) 2008-2011 Massachusetts Institute of Technology            *
 *                                                                           *
 *  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           *
 *                                                                           *
 *  This source code is part of the PetaBricks project:                      *
 *    http://projects.csail.mit.edu/petabricks/                              *
 *                                                                           *
 *****************************************************************************/

#include "codegenerator.h"
#include "maximawrapper.h"
#include "transform.h"

#include "common/hash.h"
#include "common/jargs.h"
#include "common/jfilesystem.h"
#include "common/jtunable.h"

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#ifdef HAVE_OPENCL
#include "openclutil.h"
#endif

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#include <fstream>
#include <iostream>
#include <sys/stat.h>
#include <sys/types.h>

const char headertxth[] =
  "// Generated by " PACKAGE " compiler (pbc) v" VERSION " " REVISION_LONG "\n"
  "#include \"petabricks.h\"\n"
  "#ifdef __GNUC__\n"
  "#pragma GCC diagnostic ignored \"-Wunused-variable\"\n"
  "#pragma GCC diagnostic ignored \"-Wunused-parameter\"\n"
  "#pragma GCC diagnostic ignored \"-Wunused-value\"\n"
  "#endif\n"
  "using namespace petabricks;\n\n"
  ;

const char headertxtcpp[] =
  "// Generated by " PACKAGE " compiler (pbc) v" VERSION " " REVISION_LONG "\n"
  "#include \""GENHEADER"\"\n"
  ;

using namespace petabricks;

namespace pbcConfig {
  bool shouldCompile = true;
  bool shouldLink = true;
  std::string theCommonDir;
  std::string theHardcodedConfig;
  std::string theInput;
  std::string theLibDir;
  std::string theMainName;
  std::string theObjDir;
  std::string theObjectFile;
  std::string theOutputBin;
  std::string theOutputInfo;
  std::string theRuntimeDir;
  std::string thePbPreprocessor;
  std::string theBasename;
  int theNJobs = 2;
}
using namespace pbcConfig;

//defined in pbparser.ypp
TransformListPtr parsePbFile(const char* filename);

/* wrapper around popen */
FILE* opensubproc(const std::string& cmd) {
  FILE* p = popen((cmd+" 2>&1").c_str(), "r");
  JTRACE("calling gcc")(cmd);
  JASSERT(p!= 0)(cmd);
  return p;
}

/* wrapper around pclose */
void closesubproc(FILE* p, const std::string& name) {
  std::cerr << name << std::endl;
  while(!feof(p)) {
    char buf[1024];
    memset(buf, 0, sizeof buf);
    if(fread(buf, 1, sizeof buf -1,  p) > 0) {
      std::cerr << buf;
    }
  }
  JASSERT(pclose(p)==0);
}

/**
 * Small helper class used to output cpp files and call gcc
 */
class OutputCode {
  std::string   _cpp;
  std::string   _obj;
  StreamTreePtr _code;
  std::string   _gcccmd;
  FILE*         _gccfd;
public:
  OutputCode(const std::string& basename, CodeGenerator& o)
    : _cpp(basename+".cpp")
    , _obj(basename+".o")
    , _gccfd(0)
  {
    _code = o.startSubfile(basename);

    std::ostringstream os;
    os << CXX " " CXXFLAGS " " CXXDEFS " -c "
       << " -o "  << _obj
       << " "     << _cpp
       << " -I\"" << theLibDir << "\""
       << " -I\"" << theRuntimeDir << "\"";
    _gcccmd = os.str();
  }

  void write() {
    std::ofstream of(_cpp.c_str());
    of << headertxtcpp;
    of << "/* Compile with: \n"
       <<  _gcccmd << "\n"
       << " */\n";
    _code->writeTo(of);
    of.flush();
    of.close();
  }

  void forkCompile() {
    JTRACE(_gcccmd.c_str());
    _gccfd = opensubproc(_gcccmd);
  }

  void waitCompile() {
    closesubproc(_gccfd, "Compile "+_cpp);
  }

  const std::string& objpath() const { return _obj; }

  void writeMakefile(std::ostream& o) {
    o << _obj << ":\n\t"
      << _gcccmd
      << "\n\n";
  }

};

/**
 * Collection of all the output source files of the compiler
 */
class OutputCodeList : public std::vector<OutputCode> {
public:
  void writeHeader(const StreamTreePtr& h) {
    std::ofstream of((theObjDir+"/"GENHEADER).c_str());
    h->writeTo(of);
    of.flush();
    of.close();
  }

  void write() {
    for(iterator i=begin(); i!=end(); ++i)
      i->write();
  }

  void compile() {
    iterator iwrite=begin(), ifork=begin(), iwait=begin();

    JASSERT(theNJobs>=1)(theNJobs);
    for(int i=0; i<theNJobs && iwait!=end(); ++i){
      if(iwrite!=end())
        (iwrite++)->write();
      if(ifork!=end())
        (ifork++)->forkCompile();
    }

    while(iwait!=end()) {
      //invariant: iwrite == ifork > iwait
      if(iwrite!=end())
        (iwrite++)->write();
      if(iwait!=end())
        (iwait++)->waitCompile();
      if(ifork!=end())
        (ifork++)->forkCompile();
    }
    JASSERT(iwrite==end());
    JASSERT(ifork==end());
  }

  std::string mklinkcmd() {
    std::ostringstream os;
    os << CXX " -o " BIN_TMPFILE " " CXXFLAGS;
    for(const_iterator i=begin(); i!=end(); ++i)
      os << " " << i->objpath();
    os << " " CXXLDFLAGS " -L\"" << theLibDir <<"\" -lpbmain -lpbruntime -lpbcommon " CXXLIBS;
    return os.str();
  }

  void link() {
    JTRACE(mklinkcmd().c_str());
    closesubproc(opensubproc(mklinkcmd()), "Link "+theOutputBin);
  }

  void writeMakefile() {
    std::ofstream o("Makefile");
    o << "# Generated by " PACKAGE " compiler (pbc) v" VERSION " " REVISION_LONG "\n";
    o << "# This file is generated only for testing purposes and it not used\n\n";

    o << "all: " BIN_TMPFILE "\n\n";
    for(iterator i=begin(); i!=end(); ++i)
      i->writeMakefile(o);

    o << BIN_TMPFILE << ":";
    for(iterator i=begin(), e=end(); i!=e; ++i)
      o << " " << i->objpath();
    o << "\n\t" << mklinkcmd() << "\n\n";

    o << "clean_bin:\n";
    o << "\trm -f " BIN_TMPFILE "\n\n";

    o << "clean_obj:\n";
    o << "\trm -f *.o\n\n";

    o << "clean_temp:\n";
    o << "\trm -f *~ *.bak *.tmp *.temp\n\n";

    o << "clean: clean_bin clean_obj clean_temp\n";
  }
};

void findMainTransform(const TransformListPtr& t) {
  //find the main transform if it has not been specified
  if(theMainName==""){
    for(TransformList::const_iterator i=t->begin(); i!=t->end(); ++i){
      if((*i)->isMain()){
        JASSERT(theMainName=="")(theMainName)((*i)->name())
          .Text("Two transforms both have the 'main' keyword");
        theMainName = (*i)->name();
      }
    }
    if(theMainName=="") theMainName = t->back()->name();
  }
}

int main( int argc, const char ** argv){

  /*
  #ifdef HAVE_OPENCL
  OpenCLUtil::init();
  OpenCLUtil::printDeviceList();
  OpenCLUtil::deinit();
  exit(-1);
  #endif
  */

  // READ COMMAND LINE:

  OutputCodeList ccfiles;

  jalib::JArgs args(argc, argv);
  std::vector<std::string> inputs;
  if(args.needHelp())
    std::cerr << "OPTIONS:" << std::endl;

  thePbPreprocessor="\""PYTHON"\" \"" +
                    jalib::Filesystem::FindHelperUtility("preprocessor.py")
                    +"\"";

  args.param("input",      inputs).help("input file to compile (*.pbcc)");
  args.param("output",     theOutputBin).help("output binary to be produced");
  args.param("outputinfo", theOutputInfo).help("output *.info file to be produced");
  args.param("outputobj",  theObjectFile).help("output *.o file to be produced");
  args.param("runtimedir", theRuntimeDir).help("directory where petabricks.h may be found");
  args.param("libdir",     theLibDir).help("directory where libpbruntime.a may be found");
  args.param("preproc",    thePbPreprocessor).help("program to use as preprocessor");
  args.param("compile",    shouldCompile).help("disable the compilation step");
  args.param("link",       shouldLink).help("disable the linking step");
  args.param("main",       theMainName).help("transform name to use as program entry point");
  args.param("hardcode",   theHardcodedConfig).help("a config file containing tunables to set to hardcoded values");
  args.param("jobs",       theNJobs).help("number of gcc processes to call at once");

  if(args.param("version").help("print out version number and exit") ){
    std::cerr << PACKAGE " compiler (pbc) v" VERSION " " REVISION_LONG << std::endl;
    return 1;
  }

  args.finishParsing(inputs);

  if(inputs.empty() || args.needHelp()){
    std::cerr << "\n" PACKAGE " compiler (pbc) v" VERSION " " REVISION_SHORT << std::endl;
    std::cerr << "USAGE: " << argv[0] << " [OPTIONS] filename.pbcc" << std::endl;
    std::cerr << "run `" << argv[0] << " --help` for options" << std::endl;
    return 1;
  }

  JASSERT(inputs.size()==1)(inputs.size()).Text("expected exactly one input file");
  theInput = inputs.front();
  if(theRuntimeDir.empty()) theRuntimeDir = jalib::Filesystem::Dirname(jalib::Filesystem::FindHelperUtility("runtime/petabricks.h"));
  if(theLibDir    .empty()) theLibDir     = jalib::Filesystem::Dirname(jalib::Filesystem::FindHelperUtility("libpbruntime.a"));
  if(theOutputBin .empty()) theOutputBin  = jalib::Filesystem::Basename(theInput);
  if(theObjDir.empty())     theObjDir     = theOutputBin + ".obj";
  if(theOutputInfo.empty()) theOutputInfo = theOutputBin + ".info";
  if(theObjectFile.empty()) theObjectFile = theOutputBin + ".o";

  int rv = mkdir(theObjDir.c_str(), 0755);
  if(rv!=0 && errno==EEXIST)
    rv=0, errno=0;
  JASSERT(rv==0)(theObjDir).Text("failed to create objdir");

  if(!theHardcodedConfig.empty())
    CodeGenerator::theHardcodedTunables() = jalib::JTunableManager::loadRaw(theHardcodedConfig);

  JASSERT(jalib::Filesystem::FileExists(theInput))(theInput)
    .Text("input file does not exist");

  // PARSE:

  TransformListPtr t = parsePbFile(theInput.c_str());

  // COMPILE:

  for(TransformList::iterator i=t->begin(); i!=t->end(); ++i){
    (*i)->initialize();
    #ifdef DEBUG
    (*i)->print(std::cout);
    #endif
  }

  for(TransformList::iterator i=t->begin(); i!=t->end(); ++i){
    (*i)->compile();
  }

  findMainTransform(t);

  // CODEGEN:
  StreamTreePtr header = new StreamTree("header");
  StreamTreePtr prefix = header->add(new StreamTree("prefix"));
  CodeGenerator o(header, NULL);

  for(TransformList::iterator i=t->begin(); i!=t->end(); ++i){
    ccfiles.push_back(OutputCode((*i)->name(), o));
    (*i)->generateCode(o);
  }

  // generate misc files:
  o.cg().beginGlobal();
#ifdef SINGLE_SEQ_CUTOFF
  o.createTunable(true, "system.cutoff.sequential", "sequentialcutoff", 64);
#endif
  o.createTunable(true, "system.runtime.threads", "worker_threads", 8, MIN_NUM_WORKERS, MAX_NUM_WORKERS);
  o.cg().endGlobal();
  ccfiles.push_back(OutputCode(GENMISC, o));
  o.outputTunables(o.os());
  o.comment("A hook called by PetabricksRuntime");
  o.beginFunc("petabricks::PetabricksRuntime::Main*", "petabricksMainTransform");
  o.write("return "+theMainName+"_main::instance();");
  o.endFunc();
  o.comment("A hook called by PetabricksRuntime");
  o.beginFunc( "petabricks::PetabricksRuntime::Main*"
             , "petabricksFindTransform"
             , std::vector<std::string>(1, "const std::string& name"));
  for(TransformList::iterator i=t->begin(); i!=t->end(); ++i){
    (*i)->registerMainInterface(o);
  }
  o.write("return NULL;");
  o.endFunc();

  // generate common header file:
  *prefix << headertxth;
  *prefix << "namespace { \n";
  *prefix << CodeGenerator::theFilePrefix().str();
  *prefix << "} \n";
  o.outputTunableHeaders(*prefix);
  ccfiles.writeHeader(header);

  // dump .info file:
  std::ofstream infofile(theOutputInfo.c_str());
  o.cg().dumpTo(infofile);
  infofile.flush();
  infofile.close();

  char olddir[1024];
  memset(olddir, 0, sizeof olddir);
  JASSERT(olddir==getcwd(olddir, sizeof olddir - 1));
  JASSERT(chdir(theObjDir.c_str())==0)(theObjDir);

  ccfiles.writeMakefile();

  // COMPILE AND LINK:
  if(shouldCompile)
    ccfiles.compile();
  else
    ccfiles.write();

  if(shouldLink) {
    ccfiles.link();
    JASSERT(chdir(olddir)==0)(olddir);
    JASSERT(rename((theObjDir+"/"BIN_TMPFILE).c_str(), theOutputBin.c_str())==0)
      (theObjDir+"/"BIN_TMPFILE)(theOutputBin);
  }else{
    JASSERT(chdir(olddir)==0)(olddir);
  }

#ifdef DEBUG
  MAXIMA.sanityCheck();
#endif

  JTRACE("done")(theInput)(theOutputInfo)(theObjDir)(theOutputBin);
  return 0;
}

<|endoftext|>


<commit_before>/*********************************************************************
* PulseSensor library
* a class to control a pulse sensor connected to one of the pins
* attached to one of the external interrupt.
* version 0.3 BETA 19/09/2015
* Author: Jaime García  @peninquen
* Licence: Apache License Version 2.0.
*
**********************************************************************/
//------------------------------------------------------------------------------
// Poner PULSE_DEBUG a 1 para depuración.

#define PULSE_DEBUG  0

//------------------------------------------------------------------------------
// Debug directives

#if PULSE_DEBUG
#   define PULSE_DEBUG_PRINT(...)    Serial.print(__VA_ARGS__)
#   define PULSE_DEBUG_PRINTLN(...)  Serial.println(__VA_ARGS__)
#else
#   define PULSE_DEBUG_PRINT(...)
#   define PULSE_DEBUG_PRINTLN(...)
#endif

#include "PulseSensor.h"

volatile unsigned int _COUNTER;
volatile unsigned long _startTime;
volatile unsigned long _finishTime;

void detectPulseISR() {
  _COUNTER++;
  _startTime = _finishTime;
  _finishTime = micros();

}

/***************************************************************************/
/*constructor*/

PulseSensor::PulseSensor() {
}

/***************************************************************************/
/*Setup variables and initialize interrupts*/

void PulseSensor::begin(int pulsePin, unsigned int interval, float rateConversion, float acumConversion) {
  _interval = interval;
  _rateConversion = rateConversion;
  _acumConversion = acumConversion;
  _processTime = millis();       // start timer
  _flag = false;
  _acumCounter = 0;
  _counter = 0;                  // reset instance counter
  _COUNTER = 0;                  // reset global counter
  _startTime = 0;
  _finishTime = micros();

  PULSE_DEBUG_PRINT(F("Pulse Pin:")); PULSE_DEBUG_PRINT(pulsePin);
  PULSE_DEBUG_PRINT(F("  INT")); PULSE_DEBUG_PRINTLN(digitalPinToInterrupt(pulsePin));
  pinMode(pulsePin, INPUT_PULLUP); //
  attachInterrupt(digitalPinToInterrupt(pulsePin), detectPulseISR, RISING);
}

/***************************************************************************/
/*check interval and update data, include at least one time inside loop cycle*/
void PulseSensor::refreshData() {
  unsigned long nowTime = millis();
  if (nowTime - _processTime >= _interval) {
    byte oldSREG = SREG;
    noInterrupts();
    _counter = _COUNTER;
    _COUNTER = 0;
    _acumCounter += _counter;  // increase counter
    _processTime = nowTime;     //stamp process time
    _flag = true;
    SREG = oldSREG;            //enable last state interrupts register
  }
}

/***************************************************************************/
/*read sensor value[units per second]*/

float PulseSensor::read() {
  _flag = false;
  return (float)(_counter * 1000.0 / _rateConversion / _interval);
}

/***************************************************************************/
/*read instant value in defined units */
float PulseSensor::readInstant() {
  unsigned long period;
  if ((_counter==0)&&(_COUNTER<2)) return 0.0; //we need 2 consecutive pulses to process
  byte oldSREG = SREG;
  noInterrupts();
  period = micros() - _finishTime;
  if (period < _finishTime - _startTime) period = _finishTime - _startTime;
  }
  SREG = oldSREG;            //enable last state interrupts register
  return (float)1000 / _rateConversion / period;
}

/***************************************************************************/
/*read acumulated value [units]*/

float PulseSensor::readAcum() {
  return (float)_acumCounter / _acumConversion;
}

/***************************************************************************/
/*read instance partial pulse counter*/

unsigned int PulseSensor::readPulses() {
  _flag = false;
  return _counter;
}

/***************************************************************************/
/*read instance acumulated pulse counter*/

unsigned long PulseSensor::readAcumPulses() {
  return _acumCounter;
}

/***************************************************************************/
/*reset acumulated pulse counter */

void PulseSensor::resetAcum() {
  _acumCounter = 0;
}

/***************************************************************************/
/* Is new data available */

boolean PulseSensor::available() {
  refreshData();
  return _flag;
}
<commit_msg>change readInstant()<commit_after>/*********************************************************************
* PulseSensor library
* a class to control a pulse sensor connected to one of the pins
* attached to one of the external interrupt.
* version 0.3 BETA 22/09/2015
* Author: Jaime García  @peninquen
* Licence: Apache License Version 2.0.
*
**********************************************************************/
//------------------------------------------------------------------------------
// Poner DEBUG a 1 para depuración.

#define DEBUG  0

//------------------------------------------------------------------------------
// Debug directives

#if DEBUG
#   define DEBUG_PRINT(...)    Serial.print(__VA_ARGS__)
#   define DEBUG_PRINTLN(...)  Serial.println(__VA_ARGS__)
#else
#   define DEBUG_PRINT(...)
#   define DEBUG_PRINTLN(...)
#endif

#include "PulseSensor.h"

volatile unsigned int _COUNTER;
volatile unsigned long _startTime;
volatile unsigned long _finishTime;

void detectPulseISR() {
  _COUNTER++;
  _startTime = _finishTime;
  _finishTime = micros();

}

/***************************************************************************/
/*constructor*/

PulseSensor::PulseSensor() {
}

/***************************************************************************/
/*Setup variables and initialize interrupts*/

void PulseSensor::begin(int pulsePin, unsigned int interval, float rateConversion, float acumConversion) {
  _interval = interval;
  _rateConversion = rateConversion;
  _acumConversion = acumConversion;
  _processTime = millis();       // start timer
  _flag = false;
  _acumCounter = 0;
  _counter = 0;                  // reset instance counter
  _COUNTER = 0;                  // reset global counter
  _startTime = 0;
  _finishTime = micros();

  DEBUG_PRINT(F("Pulse Pin:")); DEBUG_PRINT(pulsePin);
  DEBUG_PRINT(F("  INT")); DEBUG_PRINTLN(digitalPinToInterrupt(pulsePin));

  pinMode(pulsePin, INPUT_PULLUP); //
  attachInterrupt(digitalPinToInterrupt(pulsePin), detectPulseISR, RISING);
}

/***************************************************************************/
/*check interval and update data, include at least one time inside loop cycle*/
void PulseSensor::refreshData() {
  unsigned long nowTime = millis();
  if (nowTime - _processTime >= _interval) {
    byte oldSREG = SREG;
    noInterrupts();
    _counter = _COUNTER;
    _COUNTER = 0;
    _acumCounter += _counter;  // increase counter
    _processTime = nowTime;     //stamp process time
    _flag = true;
    SREG = oldSREG;            //enable last state interrupts register
  }
}

/***************************************************************************/
/*read sensor value[units per second]*/

float PulseSensor::read() {
  _flag = false;
  return (float)(_counter * 1000.0 / _rateConversion / _interval);
}

/***************************************************************************/
/*read instant value in defined units */
float PulseSensor::readInstant() {
  unsigned long period;
  if ((_counter == 0) && (_COUNTER < 2)) return 0.0; //we need 2 consecutive pulses to process
  byte oldSREG = SREG;
  noInterrupts();
  period = micros() - _finishTime;
  if (period < _finishTime - _startTime) period = _finishTime - _startTime;
  SREG = oldSREG;            //enable last state interrupts register
  return (float)1000 / _rateConversion / period;
}

/***************************************************************************/
/*read acumulated value [units]*/

float PulseSensor::readAcum() {
  return (float)_acumCounter / _acumConversion;
}

/***************************************************************************/
/*read instance partial pulse counter*/

unsigned int PulseSensor::readPulses() {
  _flag = false;
  return _counter;
}

/***************************************************************************/
/*read instance acumulated pulse counter*/

unsigned long PulseSensor::readAcumPulses() {
  return _acumCounter;
}

/***************************************************************************/
/*reset acumulated pulse counter */

void PulseSensor::resetAcum() {
  _acumCounter = 0;
}

/***************************************************************************/
/* Is new data available */

boolean PulseSensor::available() {
  refreshData();
  return _flag;
}
<|endoftext|>


<commit_before>/*
	Flexisip, a flexible SIP proxy server with media capabilities.
    Copyright (C) 2010  Belledonne Communications SARL.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "lpconfig.h"
#include <cstring>
#include "configmanager.hh"
#include "common.hh"

ConfigArea::ConfigArea(ConfigManager *m, const char *area) :  mArea(area), mManager(m){
}

bool ConfigArea::get(const char *key, bool default_value)const{
	std::string result;
	if (mManager->get(mArea.c_str(),key,&result)){
		return atoi(result.c_str());
	}
	return default_value;
}

int ConfigArea::get(const char *key, int default_value)const{
	std::string result;
	if (mManager->get(mArea.c_str(),key,&result)){
		return atoi(result.c_str());
	}
	return default_value;
}

std::list<std::string> ConfigArea::get(const char *key, const std::list<std::string> & default_value)const{
	std::string result;
	if (mManager->get(mArea.c_str(),key,&result)){
		std::list<std::string> retlist;
		char *res=strdup(result.c_str());
		char *saveptr=NULL;
		char *ret=strtok_r(res,",",&saveptr);
		while(ret!=NULL){
			retlist.push_back(std::string(ret));
			ret=strtok_r(NULL,",",&saveptr);
		}
		free(res);
		return retlist;
	}
	return default_value;
}

const char *ConfigManager::sGlobalArea="global";
ConfigManager *ConfigManager::sInstance=0;

ConfigManager *ConfigManager::get(){
	if (sInstance==NULL)
		sInstance=new ConfigManager();
	return sInstance;
}

ConfigManager::ConfigManager(){
	mConf=lp_config_new("/etc/flexisip/flexisip.conf");
}

ConfigArea ConfigManager::getArea(const char *name){
	return ConfigArea(this,name);
}

bool ConfigManager::get(const char *area, const char *key, std::string *result){
	const char *res;
	const char *undefined="undefined";
	res=lp_config_get_string(mConf,area,key,undefined);
	if (res==undefined) return false;
	if (res!=NULL) result->assign(res);
	return true;
}

<commit_msg>improve parsing of config file<commit_after>/*
	Flexisip, a flexible SIP proxy server with media capabilities.
    Copyright (C) 2010  Belledonne Communications SARL.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "lpconfig.h"
#include <cstring>
#include "configmanager.hh"
#include "common.hh"

ConfigArea::ConfigArea(ConfigManager *m, const char *area) :  mArea(area), mManager(m){
}

bool ConfigArea::get(const char *key, bool default_value)const{
	std::string result;
	if (mManager->get(mArea.c_str(),key,&result)){
		return atoi(result.c_str());
	}
	return default_value;
}

int ConfigArea::get(const char *key, int default_value)const{
	std::string result;
	if (mManager->get(mArea.c_str(),key,&result)){
		return atoi(result.c_str());
	}
	return default_value;
}

#define DELIMITERS " \n,"

std::list<std::string> ConfigArea::get(const char *key, const std::list<std::string> & default_value)const{
	std::string result;
	if (mManager->get(mArea.c_str(),key,&result)){
		std::list<std::string> retlist;
		char *res=strdup(result.c_str());
		char *saveptr=NULL;
		char *ret=strtok_r(res,DELIMITERS,&saveptr);
		while(ret!=NULL){
			retlist.push_back(std::string(ret));
			ret=strtok_r(NULL,DELIMITERS,&saveptr);
		}
		free(res);
		return retlist;
	}
	return default_value;
}

const char *ConfigManager::sGlobalArea="global";
ConfigManager *ConfigManager::sInstance=0;

ConfigManager *ConfigManager::get(){
	if (sInstance==NULL)
		sInstance=new ConfigManager();
	return sInstance;
}

ConfigManager::ConfigManager(){
	mConf=lp_config_new("/etc/flexisip/flexisip.conf");
}

ConfigArea ConfigManager::getArea(const char *name){
	return ConfigArea(this,name);
}

bool ConfigManager::get(const char *area, const char *key, std::string *result){
	const char *res;
	const char *undefined="undefined";
	res=lp_config_get_string(mConf,area,key,undefined);
	if (res==undefined) return false;
	if (res!=NULL) result->assign(res);
	return true;
}

<|endoftext|>


<commit_before>//
// Copyright (c) 2012 Kim Walisch, <kim.walisch@gmail.com>.
// All rights reserved.
//
// This file is part of primesieve.
// Homepage: http://primesieve.googlecode.com
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//   * Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above
//     copyright notice, this list of conditions and the following
//     disclaimer in the documentation and/or other materials provided
//     with the distribution.
//   * Neither the name of the author nor the names of its
//     contributors may be used to endorse or promote products derived
//     from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

/**
 * @file  main.cpp
 * @brief Command-line version of primesieve, multi-threaded (OpenMP).
 * @see   http://primesieve.googlecode.com
 *
 * primesieve is a highly optimized implementation of the sieve of
 * Eratosthenes that generates prime numbers and prime k-tuplets (twin
 * primes, prime triplets, ...) up to 2^64 maximum.
 */

#include "../expr/ExpressionParser.h"
#include "../soe/ParallelPrimeSieve.h"

/// declared in test.cpp
void test();

#include <stdint.h>
#include <exception>
#include <iostream>
#include <string>
#include <vector>
#include <iomanip> /* std::setw(int) */

namespace {

std::vector<uint64_t> numbers; /* start and stop number for sieving */

int32_t threads    = -1;
int32_t flags      =  0;
int32_t sieveSize  = -1;
int32_t preSieve   = -1;

bool quietMode   = false;
bool printParser = false;

const std::string primes[7] = {
  "Prime numbers",
  "Twin primes",
  "Prime triplets",
  "Prime quadruplets",
  "Prime quintuplets",
  "Prime sextuplets",
  "Prime septuplets"
};

enum {
  OPTION_ERROR,
  OPTION_HELP,
  OPTION_TEST,
  OPTION_VERSION,
  START_SIEVING
};

void help() {
  std::cout << "Usage: primesieve START STOP [OPTION]..."                                              << std::endl
            << "Use the segmented sieve of Eratosthenes to generate the prime numbers and/or"          << std::endl
            << "prime k-tuplets in the interval [START, STOP] < 2^64"                                  << std::endl
                                                                                << std::endl
            << "Options:"                                                                              << std::endl
                                                                                << std::endl
            << "  -c<N+>        Count prime numbers and/or prime k-tuplets, 1 <= N <= 7"               << std::endl
            << "                e.g. -c1 count prime numbers (DEFAULT)"                                << std::endl
            << "                     -c23 count twin primes and prime triplets"                        << std::endl
            << "  -o<OFFSET>    Sieve the interval [START, START+OFFSET]"                              << std::endl
            << "  -p<N>         Print prime numbers or prime k-tuplets, 1 <= N <= 7"                   << std::endl
            << "                e.g. -p1 print prime numbers"                                          << std::endl
            << "                     -p5 print prime quintuplets"                                      << std::endl
            << "  -q            Quiet mode, print less output"                                         << std::endl
            << "  -r<PRE-SIEVE> Pre-sieve multiples of small primes <= PRE-SIEVE to speed up"          << std::endl
            << "                the sieve of Eratosthenes, 13 <= PRE-SIEVE <= 23"                      << std::endl
            << "  -s<SIZE>      Set the sieve size in kilobytes, 1 <= SIZE <= 4096"                    << std::endl
            << "                Set SIZE to your CPU's L1/L2 cache size for best performance"          << std::endl
            << "  -t<THREADS>   Set the number of threads for sieving, 1 <= THREADS <= " << ParallelPrimeSieve::getMaxThreads() << std::endl
            << "                Primes are not generated in order if THREADS >= 2"                     << std::endl
            << "  -test         Run various sieving tests and exit"                                    << std::endl
            << "  -v            Print version and license information and exit"                        << std::endl
                                                                                << std::endl
            << "Examples:"                                                                             << std::endl
                                                                                << std::endl
            << "Print the prime numbers up to 1000:"                                                   << std::endl
            << "> primesieve 2 1000 -p1"                                                               << std::endl
                                                                                << std::endl
            << "Count the twin primes and prime triplets in the interval [1E10, 1E10+2^32]:"           << std::endl
            << "> primesieve 1E10 -o2**32 -c23"                                                        << std::endl;
}

void version() {
  std::cout << "primesieve 3.5, <http://primesieve.googlecode.com>" << std::endl
            << "Copyright (C) 2012 Kim Walisch" << std::endl
            << "This software is licensed under the New BSD License. See the LICENSE file" << std::endl
            << "for more information." << std::endl;
}

bool isDigits(const std::string &str) {
  const std::string digits("0123456789");
  if (str.size() == 0)
    return false;
  return str.find_first_not_of(digits) == std::string::npos;
}

/**
 * Process the command-line options.
 * @see help(void)
 */
int processOptions(std::size_t argc, char* argv[]) {
  if (argc < 2 || argc > 20)
    return OPTION_HELP;

  std::string testOption("est");
  std::string arg;
  ExpressionParser<uint64_t> parser;
  uint64_t tmp = 0;

  // process the START and STOP numbers
  for (std::size_t i = 1; i < 3 && i < argc; i++) {
    if (parser.eval(argv[i])) {
      numbers.push_back(parser.getResult());
      if (!isDigits(argv[i]))
        printParser = true;
    }
  }
  // process the options
  for (std::size_t i = numbers.size() + 1; i < argc; i++) {
    if (*argv[i] != '-' && *argv[i] != '/')
      return OPTION_HELP;
    argv[i]++;
    switch (*argv[i]++) {
      case 'c': parser.eval(argv[i]);
                if (!parser.isSuccess())
                  return OPTION_HELP;
                tmp = parser.getResult();
                do {
                  if (tmp % 10 < 1 || tmp % 10 > 7)
                    return OPTION_HELP;
                  flags |= ParallelPrimeSieve::COUNT_PRIMES << (tmp % 10 - 1);
                  tmp /= 10;
                } while (tmp > 0);
                break;
      case 'o': parser.eval(argv[i]);
                if (!parser.isSuccess() || numbers.size() == 0)
                  return OPTION_HELP;
                tmp = numbers[0] + parser.getResult();
                numbers.push_back(tmp);
                break;
      case 'p': parser.eval(argv[i]);
                if (!parser.isSuccess() || parser.getResult() < 1 || parser.getResult() > 7)
                  return OPTION_HELP;
                tmp = parser.getResult() - 1;
                flags |= ParallelPrimeSieve::PRINT_PRIMES << tmp;
                quietMode = true;
                break;
      case 'q': quietMode = true;
                break;
      case 'r': parser.eval(argv[i]);
                if (!parser.isSuccess())
                  return OPTION_HELP;
                preSieve = static_cast<int32_t>(parser.getResult());
                break;
      case 's': parser.eval(argv[i]);
                if (!parser.isSuccess())
                  return OPTION_HELP;
                sieveSize = static_cast<int32_t>(parser.getResult());
                break;
      case 't': arg = argv[i];
                if (arg.compare(testOption) == 0)
                  return OPTION_TEST;
                parser.eval(argv[i]);
                if (!parser.isSuccess())
                  return OPTION_HELP;
                threads = static_cast<int32_t>(parser.getResult());
                break;
      case 'v': return OPTION_VERSION;
      default : return OPTION_HELP;
    }
  }
  return (numbers.size() == 2) ? START_SIEVING : OPTION_HELP;
}

} // end anonymous namespace

int main(int argc, char* argv[]) {
  // process the command-line options, see help()
  switch(processOptions(argc, argv)) {
    case OPTION_ERROR:              return 1;
    case OPTION_HELP:    help();    return 0;
    case OPTION_VERSION: version(); return 0;
    case OPTION_TEST:    test();    return 0;
    case START_SIEVING:  break;
  }

  std::cout << std::left;
  if (!quietMode && printParser) {
    std::cout << std::setw(10) << "START" << " = " << numbers[0] << std::endl;
    std::cout << std::setw(10) << "STOP"  << " = " << numbers[1] << std::endl;
  }
  try {
    ParallelPrimeSieve pps;
    pps.setStart(numbers[0]);
    pps.setStop(numbers[1]);
    if (flags     !=  0) pps.setFlags(flags);
    if (sieveSize != -1) pps.setSieveSize(sieveSize);
    if (preSieve  != -1) pps.setPreSieveLimit(preSieve);
    if (threads   != -1) pps.setNumThreads(threads);

    // set default settings
    if (!pps.testFlags(pps.COUNT_FLAGS | pps.PRINT_PRIMES | pps.PRINT_KTUPLETS))
      pps.addFlags(pps.COUNT_PRIMES);
    if (!pps.testFlags(pps.PRINT_PRIMES | pps.PRINT_KTUPLETS) && !quietMode)
      pps.addFlags(pps.PRINT_STATUS);

    if (!quietMode) {
      if (preSieve != -1)
      std::cout << std::setw(10) << "Pre-sieve"  << " = " << pps.getPreSieveLimit() << std::endl;
      std::cout << std::setw(10) << "Sieve size" << " = " << pps.getSieveSize() << " kilobytes" << std::endl;
      std::cout << std::setw(10) << "Threads"    << " = " << pps.getNumThreads() << std::endl;
    }

    // start sieving primes
    pps.sieve();

    if (pps.isFlag(pps.PRINT_STATUS))
      std::cout << std::endl;
    else if (pps.testFlags(pps.COUNT_FLAGS) && pps.testFlags(pps.PRINT_PRIMES | pps.PRINT_KTUPLETS))
      std::cout << std::endl;

    // get max string size
    std::size_t size = (quietMode) ? 0 : 12;
    for (int i = 0; i < 7; i++) {
      if (pps.isFlag(pps.COUNT_PRIMES << i) && size < primes[i].size())
        size = primes[i].size();
    }
    // print prime count results
    int width = static_cast<int>(size);
    for (int32_t i = 0; i < 7; i++) {
      if (pps.isFlag(pps.COUNT_PRIMES << i))
        std::cout << std::setw(width)
                  << primes[i] << " : " << pps.getCounts(i)
                  << std::endl;
    }
    if (!pps.testFlags(pps.PRINT_PRIMES | pps.PRINT_KTUPLETS)) {
      std::cout << std::setw(width)
                << "Time elapsed" << " : " << pps.getTimeElapsed() << " sec"
                << std::endl;
    }
    if (!quietMode && pps.getNumThreads() >= 64) {
      std::cout << "\nHint: the -q (Quiet mode) option significantly reduces the thread" << std::endl
                << "synchronization overhead when using >= 64 threads." << std::endl;
    }
  }
  catch (std::exception& e) {
    std::cerr << "Error: " << e.what() << std::endl
              << "Try `primesieve -help' for more information." << std::endl;
    return 1;
  }
  return 0;
}
<commit_msg>silenced potential warning<commit_after>//
// Copyright (c) 2012 Kim Walisch, <kim.walisch@gmail.com>.
// All rights reserved.
//
// This file is part of primesieve.
// Homepage: http://primesieve.googlecode.com
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//   * Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above
//     copyright notice, this list of conditions and the following
//     disclaimer in the documentation and/or other materials provided
//     with the distribution.
//   * Neither the name of the author nor the names of its
//     contributors may be used to endorse or promote products derived
//     from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

/**
 * @file  main.cpp
 * @brief Command-line version of primesieve, multi-threaded (OpenMP).
 * @see   http://primesieve.googlecode.com
 *
 * primesieve is a highly optimized implementation of the sieve of
 * Eratosthenes that generates prime numbers and prime k-tuplets (twin
 * primes, prime triplets, ...) up to 2^64 maximum.
 */

#include "../expr/ExpressionParser.h"
#include "../soe/ParallelPrimeSieve.h"

/// declared in test.cpp
void test();

#include <stdint.h>
#include <exception>
#include <iostream>
#include <string>
#include <vector>
#include <iomanip> /* std::setw(int) */

namespace {

std::vector<uint64_t> numbers; /* start and stop number for sieving */

int32_t threads    = -1;
int32_t flags      =  0;
int32_t sieveSize  = -1;
int32_t preSieve   = -1;

bool quietMode   = false;
bool printParser = false;

const std::string primes[7] = {
  "Prime numbers",
  "Twin primes",
  "Prime triplets",
  "Prime quadruplets",
  "Prime quintuplets",
  "Prime sextuplets",
  "Prime septuplets"
};

enum {
  OPTION_ERROR,
  OPTION_HELP,
  OPTION_TEST,
  OPTION_VERSION,
  START_SIEVING
};

void help() {
  const int maxThreads = ParallelPrimeSieve::getMaxThreads();
  std::cout << "Usage: primesieve START STOP [OPTION]..."                                              << std::endl
            << "Use the segmented sieve of Eratosthenes to generate the prime numbers and/or"          << std::endl
            << "prime k-tuplets in the interval [START, STOP] < 2^64"                                  << std::endl
                                                                                << std::endl
            << "Options:"                                                                              << std::endl
                                                                                << std::endl
            << "  -c<N+>        Count prime numbers and/or prime k-tuplets, 1 <= N <= 7"               << std::endl
            << "                e.g. -c1 count prime numbers (DEFAULT)"                                << std::endl
            << "                     -c23 count twin primes and prime triplets"                        << std::endl
            << "  -o<OFFSET>    Sieve the interval [START, START+OFFSET]"                              << std::endl
            << "  -p<N>         Print prime numbers or prime k-tuplets, 1 <= N <= 7"                   << std::endl
            << "                e.g. -p1 print prime numbers"                                          << std::endl
            << "                     -p5 print prime quintuplets"                                      << std::endl
            << "  -q            Quiet mode, print less output"                                         << std::endl
            << "  -r<PRE-SIEVE> Pre-sieve multiples of small primes <= PRE-SIEVE to speed up"          << std::endl
            << "                the sieve of Eratosthenes, 13 <= PRE-SIEVE <= 23"                      << std::endl
            << "  -s<SIZE>      Set the sieve size in kilobytes, 1 <= SIZE <= 4096"                    << std::endl
            << "                Set SIZE to your CPU's L1/L2 cache size for best performance"          << std::endl
            << "  -t<THREADS>   Set the number of threads for sieving, 1 <= THREADS <= " << maxThreads << std::endl
            << "                Primes are not generated in order if THREADS >= 2"                     << std::endl
            << "  -test         Run various sieving tests and exit"                                    << std::endl
            << "  -v            Print version and license information and exit"                        << std::endl
                                                                                << std::endl
            << "Examples:"                                                                             << std::endl
                                                                                << std::endl
            << "Print the prime numbers up to 1000:"                                                   << std::endl
            << "> primesieve 2 1000 -p1"                                                               << std::endl
                                                                                << std::endl
            << "Count the twin primes and prime triplets in the interval [1E10, 1E10+2^32]:"           << std::endl
            << "> primesieve 1E10 -o2**32 -c23"                                                        << std::endl;
}

void version() {
  std::cout << "primesieve 3.5, <http://primesieve.googlecode.com>" << std::endl
            << "Copyright (C) 2012 Kim Walisch" << std::endl
            << "This software is licensed under the New BSD License. See the LICENSE file" << std::endl
            << "for more information." << std::endl;
}

bool isDigits(const std::string &str) {
  const std::string digits("0123456789");
  if (str.size() == 0)
    return false;
  return str.find_first_not_of(digits) == std::string::npos;
}

/**
 * Process the command-line options.
 * @see help(void)
 */
int processOptions(std::size_t argc, char* argv[]) {
  if (argc < 2 || argc > 20)
    return OPTION_HELP;

  std::string testOption("est");
  std::string arg;
  ExpressionParser<uint64_t> parser;
  uint64_t tmp = 0;

  // process the START and STOP numbers
  for (std::size_t i = 1; i < 3 && i < argc; i++) {
    if (parser.eval(argv[i])) {
      numbers.push_back(parser.getResult());
      if (!isDigits(argv[i]))
        printParser = true;
    }
  }
  // process the options
  for (std::size_t i = numbers.size() + 1; i < argc; i++) {
    if (*argv[i] != '-' && *argv[i] != '/')
      return OPTION_HELP;
    argv[i]++;
    switch (*argv[i]++) {
      case 'c': parser.eval(argv[i]);
                if (!parser.isSuccess())
                  return OPTION_HELP;
                tmp = parser.getResult();
                do {
                  if (tmp % 10 < 1 || tmp % 10 > 7)
                    return OPTION_HELP;
                  flags |= ParallelPrimeSieve::COUNT_PRIMES << (tmp % 10 - 1);
                  tmp /= 10;
                } while (tmp > 0);
                break;
      case 'o': parser.eval(argv[i]);
                if (!parser.isSuccess() || numbers.size() == 0)
                  return OPTION_HELP;
                tmp = numbers[0] + parser.getResult();
                numbers.push_back(tmp);
                break;
      case 'p': parser.eval(argv[i]);
                if (!parser.isSuccess() || parser.getResult() < 1 || parser.getResult() > 7)
                  return OPTION_HELP;
                tmp = parser.getResult() - 1;
                flags |= ParallelPrimeSieve::PRINT_PRIMES << tmp;
                quietMode = true;
                break;
      case 'q': quietMode = true;
                break;
      case 'r': parser.eval(argv[i]);
                if (!parser.isSuccess())
                  return OPTION_HELP;
                preSieve = static_cast<int32_t>(parser.getResult());
                break;
      case 's': parser.eval(argv[i]);
                if (!parser.isSuccess())
                  return OPTION_HELP;
                sieveSize = static_cast<int32_t>(parser.getResult());
                break;
      case 't': arg = argv[i];
                if (arg.compare(testOption) == 0)
                  return OPTION_TEST;
                parser.eval(argv[i]);
                if (!parser.isSuccess())
                  return OPTION_HELP;
                threads = static_cast<int32_t>(parser.getResult());
                break;
      case 'v': return OPTION_VERSION;
      default : return OPTION_HELP;
    }
  }
  return (numbers.size() == 2) ? START_SIEVING : OPTION_HELP;
}

} // end anonymous namespace

int main(int argc, char* argv[]) {
  // process the command-line options, see help()
  switch(processOptions(argc, argv)) {
    case OPTION_ERROR:              return 1;
    case OPTION_HELP:    help();    return 0;
    case OPTION_VERSION: version(); return 0;
    case OPTION_TEST:    test();    return 0;
    case START_SIEVING:  break;
  }

  std::cout << std::left;
  if (!quietMode && printParser) {
    std::cout << std::setw(10) << "START" << " = " << numbers[0] << std::endl;
    std::cout << std::setw(10) << "STOP"  << " = " << numbers[1] << std::endl;
  }
  try {
    ParallelPrimeSieve pps;
    pps.setStart(numbers[0]);
    pps.setStop(numbers[1]);
    if (flags     !=  0) pps.setFlags(flags);
    if (sieveSize != -1) pps.setSieveSize(sieveSize);
    if (preSieve  != -1) pps.setPreSieveLimit(preSieve);
    if (threads   != -1) pps.setNumThreads(threads);

    // set default settings
    if (!pps.testFlags(pps.COUNT_FLAGS | pps.PRINT_PRIMES | pps.PRINT_KTUPLETS))
      pps.addFlags(pps.COUNT_PRIMES);
    if (!pps.testFlags(pps.PRINT_PRIMES | pps.PRINT_KTUPLETS) && !quietMode)
      pps.addFlags(pps.PRINT_STATUS);

    if (!quietMode) {
      if (preSieve != -1)
      std::cout << std::setw(10) << "Pre-sieve"  << " = " << pps.getPreSieveLimit() << std::endl;
      std::cout << std::setw(10) << "Sieve size" << " = " << pps.getSieveSize() << " kilobytes" << std::endl;
      std::cout << std::setw(10) << "Threads"    << " = " << pps.getNumThreads() << std::endl;
    }

    // start sieving primes
    pps.sieve();

    if (pps.isFlag(pps.PRINT_STATUS))
      std::cout << std::endl;
    else if (pps.testFlags(pps.COUNT_FLAGS) && pps.testFlags(pps.PRINT_PRIMES | pps.PRINT_KTUPLETS))
      std::cout << std::endl;

    // get max string size
    std::size_t size = (quietMode) ? 0 : 12;
    for (int i = 0; i < 7; i++) {
      if (pps.isFlag(pps.COUNT_PRIMES << i) && size < primes[i].size())
        size = primes[i].size();
    }
    // print prime count results
    int width = static_cast<int>(size);
    for (int32_t i = 0; i < 7; i++) {
      if (pps.isFlag(pps.COUNT_PRIMES << i))
        std::cout << std::setw(width)
                  << primes[i] << " : " << pps.getCounts(i)
                  << std::endl;
    }
    if (!pps.testFlags(pps.PRINT_PRIMES | pps.PRINT_KTUPLETS)) {
      std::cout << std::setw(width)
                << "Time elapsed" << " : " << pps.getTimeElapsed() << " sec"
                << std::endl;
    }
    if (!quietMode && pps.getNumThreads() >= 64) {
      std::cout << "\nHint: the -q (Quiet mode) option significantly reduces the thread" << std::endl
                << "synchronization overhead when using >= 64 threads." << std::endl;
    }
  }
  catch (std::exception& e) {
    std::cerr << "Error: " << e.what() << std::endl
              << "Try `primesieve -help' for more information." << std::endl;
    return 1;
  }
  return 0;
}
<|endoftext|>


<commit_before>/*!
    \qmltype Ticker
    \instantiates QniteTicker
    \ingroup scaling
    \inqmlmodule Qnite
    \brief Divide axes scales into tickers

    TODO: add a long description
*/
#include "qniteticker.h"

#define DEFAULT_NUM_STEPS 0
#define DEFAULT_LOWER_B 0
#define DEFAULT_UPPER_B 0

// utility functions
namespace {

    template<typename T>
    QList<T> fromVariantList(const QVariantList& in)
    {
        QList<T> out;
        foreach(QVariant val, in) {
            out.append(val.value<T>());
        }
        return out;
    }

    template<typename T>
    QVariantList toVariantList(const QList<T>& in)
    {
        QVariantList out;
        foreach(T val, in) {
            out.append(QVariant(val));
        }
        return out;
    }

}

QniteTicker::QniteTicker(QObject * parent)
    : QObject(parent), lowerBound_(DEFAULT_LOWER_B),
      upperBound_(DEFAULT_UPPER_B), numSteps_(DEFAULT_NUM_STEPS)
{

}

QVariantList QniteTicker::values() const
{
    return toVariantList<double>(values_);
}

void QniteTicker::setValues(QVariantList& values)
{
    values_ = fromVariantList<double>(values);

    // compute min and max bounds
    std::sort(values_.begin(), values_.end(), std::less<double>());
    lowerBound_ = values_.first();
    upperBound_ = values_.last();

    // build ticks
    buildTicks();

    // notify
    emit valuesChanged();
}

void QniteTicker::setMinorTicks(QVariantList& ticks)
{
    minorTicks_ = fromVariantList<double>(ticks);
}

void QniteTicker::setMidTicks(QVariantList& ticks)
{
    midTicks_ = fromVariantList<double>(ticks);
}

void QniteTicker::setMajorTicks(QVariantList& ticks)
{
    majorTicks_ = fromVariantList<double>(ticks);
}

QVariantList QniteTicker::minorTicks() const
{
    return toVariantList<double>(minorTicks_);
}

QVariantList QniteTicker::midTicks() const
{
    return toVariantList<double>(midTicks_);
}

QVariantList QniteTicker::majorTicks() const
{
    return toVariantList<double>(majorTicks_);
}

void QniteTicker::setNumSteps(int steps)
{
    numSteps_ = steps;
}

void QniteTicker::setBoundaries(double lower, double upper)
{
    lowerBound_ = lower;
    upperBound_ = upper;
}

void QniteTicker::reset()
{
    lowerBound_ = DEFAULT_LOWER_B;
    upperBound_ = DEFAULT_UPPER_B;
    numSteps_ = DEFAULT_NUM_STEPS;
    values_.clear();
    minorTicks_.clear();
    midTicks_.clear();
    majorTicks_.clear();
}
<commit_msg>rebuild ticks if numsteps changes<commit_after>/*!
    \qmltype Ticker
    \instantiates QniteTicker
    \ingroup scaling
    \inqmlmodule Qnite
    \brief Divide axes scales into tickers

    TODO: add a long description
*/
#include "qniteticker.h"

#define DEFAULT_NUM_STEPS 0
#define DEFAULT_LOWER_B 0
#define DEFAULT_UPPER_B 0

// utility functions
namespace {

    template<typename T>
    QList<T> fromVariantList(const QVariantList& in)
    {
        QList<T> out;
        foreach(QVariant val, in) {
            out.append(val.value<T>());
        }
        return out;
    }

    template<typename T>
    QVariantList toVariantList(const QList<T>& in)
    {
        QVariantList out;
        foreach(T val, in) {
            out.append(QVariant(val));
        }
        return out;
    }

}

QniteTicker::QniteTicker(QObject * parent)
    : QObject(parent), lowerBound_(DEFAULT_LOWER_B),
      upperBound_(DEFAULT_UPPER_B), numSteps_(DEFAULT_NUM_STEPS)
{

}

QVariantList QniteTicker::values() const
{
    return toVariantList<double>(values_);
}

void QniteTicker::setValues(QVariantList& values)
{
    values_ = fromVariantList<double>(values);

    // compute min and max bounds
    std::sort(values_.begin(), values_.end(), std::less<double>());
    lowerBound_ = values_.first();
    upperBound_ = values_.last();

    // build ticks
    buildTicks();

    // notify
    emit valuesChanged();
}

void QniteTicker::setMinorTicks(QVariantList& ticks)
{
    minorTicks_ = fromVariantList<double>(ticks);
}

void QniteTicker::setMidTicks(QVariantList& ticks)
{
    midTicks_ = fromVariantList<double>(ticks);
}

void QniteTicker::setMajorTicks(QVariantList& ticks)
{
    majorTicks_ = fromVariantList<double>(ticks);
}

QVariantList QniteTicker::minorTicks() const
{
    return toVariantList<double>(minorTicks_);
}

QVariantList QniteTicker::midTicks() const
{
    return toVariantList<double>(midTicks_);
}

QVariantList QniteTicker::majorTicks() const
{
    return toVariantList<double>(majorTicks_);
}

void QniteTicker::setNumSteps(int steps)
{
    numSteps_ = steps;

    if (majorTicks_.size() != steps) {
        // rebuild ticks if needed
        buildTicks();
        emit valuesChanged();
    }
}

void QniteTicker::setBoundaries(double lower, double upper)
{
    lowerBound_ = lower;
    upperBound_ = upper;
}

void QniteTicker::reset()
{
    lowerBound_ = DEFAULT_LOWER_B;
    upperBound_ = DEFAULT_UPPER_B;
    numSteps_ = DEFAULT_NUM_STEPS;
    values_.clear();
    minorTicks_.clear();
    midTicks_.clear();
    majorTicks_.clear();
}
<|endoftext|>


<commit_before>#ifndef FOREVER_HPP_
#define FOREVER_HPP_

#include <memory>
#include <core/animation.hpp>

template <typename State>
class Forever: public Animation<State>
{
public:
    Forever(AnimationPtr<State> &&animation):
        m_animation(std::move(animation))
    {}

    State nextState(const int32_t deltaTime) override
    {
        if (m_animation->isFinished()) {
            m_animation->reset();
        }

        return m_animation->nextState(deltaTime);
    }

    State getCurrentState() const override
    {
        return m_animation->getCurrentState();
    }

    bool isFinished() const override
    {
        return false;
    }

    void reset() override
    {}

private:
    AnimationPtr<State> m_animation;
};

#endif  // FOREVER_HPP_
<commit_msg>Add virtual function specifier<commit_after>#ifndef FOREVER_HPP_
#define FOREVER_HPP_

#include <memory>
#include <core/animation.hpp>

template <typename State>
class Forever: public Animation<State>
{
public:
    Forever(AnimationPtr<State> &&animation):
        m_animation(std::move(animation))
    {}

    virtual State nextState(const int32_t deltaTime) override
    {
        if (m_animation->isFinished()) {
            m_animation->reset();
        }

        return m_animation->nextState(deltaTime);
    }

    virtual State getCurrentState() const override
    {
        return m_animation->getCurrentState();
    }

    virtual bool isFinished() const override
    {
        return false;
    }

    virtual void reset() override
    {}

private:
    AnimationPtr<State> m_animation;
};

#endif  // FOREVER_HPP_
<|endoftext|>


<commit_before>#include "cvm.h"

static void _twrite(std::vector<byte> &out, const byte *data, size_t size)
{
    for (size_t i = 0; i < size; i++)
    {
        out.push_back(data[i]);
    }
}

template <typename T>
static void _twrite(std::vector<byte> &out, T value)
{
    _twrite(out, (const byte *)&value, sizeof(value));
}

template <typename T>
static void _twrite(std::vector<byte> &out, std::vector<T> value)
{
    for (const auto &item : value)
    {
        _twrite(out, item);
    }
}

enum
{
    TEMP_REGULAR         = 0,
    TEMP_FUNC_SECTION    = 1,
    TEMP_SYMBOLS_SECTION = 2,
    TEMP_SYMDATA_SECTION = 3,
};

void DabVM::dump_vm(FILE *out)
{
    BinDabHeader            dump_header;
    std::vector<BinSection> dump_sections = sections;
    std::vector<byte>       dump_data;

    dump_sections.erase(std::remove_if(dump_sections.begin(), dump_sections.end(),
                                       [](BinSection section) {
                                           std::string name = section.name;
                                           return name == "func" || name == "symb" ||
                                                  name == "symd";
                                       }),
                        dump_sections.end());

    BinSection func_section = {};
    memcpy(func_section.name, "func", 4);
    std::vector<BinFunction> dump_functions;
    for (auto it : functions)
    {
        if (!it.second.regular)
            continue;

        BinFunction bin_func;
        bin_func.symbol  = it.first;
        bin_func.klass   = DAB_CLASS_NIL;
        bin_func.address = it.second.address;
        dump_functions.push_back(bin_func);
    }
    func_section.special_index = TEMP_FUNC_SECTION;
    func_section.length        = dump_functions.size() * sizeof(BinFunction);

    BinSection symb_section;
    memcpy(symb_section.name, "symb", 4);

    BinSection symd_section;
    memcpy(symd_section.name, "symd", 4);

    std::vector<byte>     symd_data;
    std::vector<uint64_t> symb_data;
    for (auto sym : symbols)
    {
        auto pos = symd_data.size();
        symb_data.push_back(pos);
        for (char ch : sym)
        {
            symd_data.push_back(ch);
        }
        symd_data.push_back(0);
    }
    symb_section.special_index = TEMP_SYMBOLS_SECTION;
    symb_section.length        = symb_data.size() * sizeof(uint64_t);

    symd_section.special_index = TEMP_SYMDATA_SECTION;
    symd_section.length        = symd_data.size();

    dump_sections.push_back(symd_section);
    auto symd_section_index = dump_sections.size() - 1;
    dump_sections.push_back(symb_section);
    dump_sections.push_back(func_section);

    memcpy(dump_header.dab, "DAB\0", 4);
    dump_header.version        = 3;
    dump_header.offset         = 0;
    dump_header.section_count  = dump_sections.size();
    dump_header.size_of_header = sizeof(BinHeader) + dump_header.section_count * sizeof(BinSection);

    auto new_pos = dump_header.size_of_header;

    auto code_offset = new_pos - instructions.peek_header()->header.size_of_header;
    for (auto &func : dump_functions)
    {
        func.address += code_offset;
    }

    for (auto &section : dump_sections)
    {
        auto pos    = section.pos;
        auto length = section.length;

        section.pos = new_pos;

        if (section.special_index == TEMP_REGULAR)
        {
            auto ptr = instructions.raw_base_data() + pos;

            _twrite(dump_data, (byte *)ptr, (size_t)length);
        }
        else if (section.special_index == TEMP_FUNC_SECTION)
        {
            _twrite(dump_data, dump_functions);
        }
        else if (section.special_index == TEMP_SYMDATA_SECTION)
        {
            _twrite(dump_data, symd_data);
        }
        else if (section.special_index == TEMP_SYMBOLS_SECTION)
        {
            for (auto &symb : symb_data)
            {
                symb += dump_sections[symd_section_index].pos;
            }
            _twrite(dump_data, symb_data);
        }

        section.special_index = 0;

        new_pos += length;
    }

    dump_header.size_of_data = dump_data.size();

    fwrite(&dump_header, sizeof(BinHeader), 1, out);
    for (auto &section : dump_sections)
    {
        fwrite(&section, sizeof(BinSection), 1, out);
    }
    fwrite(&dump_data[0], 1, dump_data.size(), out);
}
<commit_msg>disasm: rewrite symbols offset<commit_after>#include "cvm.h"

static void _twrite(std::vector<byte> &out, const byte *data, size_t size)
{
    for (size_t i = 0; i < size; i++)
    {
        out.push_back(data[i]);
    }
}

template <typename T>
static void _twrite(std::vector<byte> &out, T value)
{
    _twrite(out, (const byte *)&value, sizeof(value));
}

template <typename T>
static void _twrite(std::vector<byte> &out, std::vector<T> value)
{
    for (const auto &item : value)
    {
        _twrite(out, item);
    }
}

enum
{
    TEMP_REGULAR         = 0,
    TEMP_FUNC_SECTION    = 1,
    TEMP_SYMBOLS_SECTION = 2,
    TEMP_SYMDATA_SECTION = 3,
};

void DabVM::dump_vm(FILE *out)
{
    BinDabHeader            dump_header;
    std::vector<BinSection> dump_sections = sections;
    std::vector<byte>       dump_data;

    dump_sections.erase(std::remove_if(dump_sections.begin(), dump_sections.end(),
                                       [](BinSection section) {
                                           std::string name = section.name;
                                           return name == "func" || name == "symb" ||
                                                  name == "symd";
                                       }),
                        dump_sections.end());

    BinSection func_section = {};
    memcpy(func_section.name, "func", 4);
    std::vector<BinFunction> dump_functions;
    for (auto it : functions)
    {
        if (!it.second.regular)
            continue;

        BinFunction bin_func;
        bin_func.symbol  = it.first;
        bin_func.klass   = DAB_CLASS_NIL;
        bin_func.address = it.second.address;
        dump_functions.push_back(bin_func);
    }
    func_section.special_index = TEMP_FUNC_SECTION;
    func_section.length        = dump_functions.size() * sizeof(BinFunction);

    BinSection symb_section;
    memcpy(symb_section.name, "symb", 4);

    BinSection symd_section;
    memcpy(symd_section.name, "symd", 4);

    std::vector<byte>     symd_data;
    std::vector<uint64_t> symb_data;
    for (auto sym : symbols)
    {
        auto pos = symd_data.size();
        symb_data.push_back(pos);
        for (char ch : sym)
        {
            symd_data.push_back(ch);
        }
        symd_data.push_back(0);
    }
    symb_section.special_index = TEMP_SYMBOLS_SECTION;
    symb_section.length        = symb_data.size() * sizeof(uint64_t);

    symd_section.special_index = TEMP_SYMDATA_SECTION;
    symd_section.length        = symd_data.size();

    dump_sections.push_back(symd_section);
    auto symd_section_index = dump_sections.size() - 1;
    dump_sections.push_back(symb_section);
    dump_sections.push_back(func_section);

    memcpy(dump_header.dab, "DAB\0", 4);
    dump_header.version        = 3;
    dump_header.offset         = 0;
    dump_header.section_count  = dump_sections.size();
    dump_header.size_of_header = sizeof(BinHeader) + dump_header.section_count * sizeof(BinSection);

    auto new_pos = dump_header.size_of_header;

    auto code_offset = new_pos - instructions.peek_header()->header.size_of_header;
    for (auto &func : dump_functions)
    {
        func.address += code_offset;
    }

    for (auto &section : dump_sections)
    {
        auto pos    = section.pos;
        auto length = section.length;

        section.pos = new_pos;

        if (section.special_index == TEMP_REGULAR)
        {
            auto ptr = instructions.raw_base_data() + pos;

            _twrite(dump_data, (byte *)ptr, (size_t)length);
        }
        else if (section.special_index == TEMP_FUNC_SECTION)
        {
            _twrite(dump_data, dump_functions);
        }
        else if (section.special_index == TEMP_SYMDATA_SECTION)
        {
            _twrite(dump_data, symd_data);
        }
        else if (section.special_index == TEMP_SYMBOLS_SECTION)
        {
            auto offset = dump_sections[symd_section_index].pos;
            for (auto &symb : symb_data)
            {
                symb += offset;
            }
            _twrite(dump_data, symb_data);
        }

        section.special_index = 0;

        new_pos += length;
    }

    dump_header.size_of_data = dump_data.size();

    fwrite(&dump_header, sizeof(BinHeader), 1, out);
    for (auto &section : dump_sections)
    {
        fwrite(&section, sizeof(BinSection), 1, out);
    }
    fwrite(&dump_data[0], 1, dump_data.size(), out);
}
<|endoftext|>


<commit_before><commit_msg>hdmap_map_test runs in parallel<commit_after><|endoftext|>