<commit_before>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
The MIT License

Copyright (c) 2008, 2009 Flusspferd contributors (see "CONTRIBUTORS" or
                                       http://flusspferd.org/contributors.txt)

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 "flusspferd/modules.hpp"
#include "flusspferd/create.hpp"
#include "flusspferd/security.hpp"
#include "flusspferd/evaluate.hpp"
#include "flusspferd/value_io.hpp"
#include "flusspferd/io/file.hpp"
#include "flusspferd/io/filesystem-base.hpp"
#include "flusspferd/binary.hpp"
#include "flusspferd/encodings.hpp"
#include <boost/filesystem/fstream.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <sstream>

#ifdef WIN32
#include <windows.h>
#else
#define SHLIBPREFIX "lib"
#include <dlfcn.h>
#endif

using namespace flusspferd;

namespace algo = boost::algorithm;
namespace fs = boost::filesystem;

static fs::path make_dsoname(std::string const &id);

// Create |require| function on container.
void flusspferd::load_require_function(object container) {
  container.set_property("require", require::create_require());
}

require::require()
  : native_function_base(1, "require"),
    module_cache(create_object()),
    paths(create_array()),
    alias(create_object()),
    preload(create_object())
{ }

// Copy constructor. Keep the same JS objects for the state variables
require::require(require const &rhs)
  : native_function_base(1, "require"),
    module_cache(rhs.module_cache),
    paths(rhs.paths),
    alias(rhs.alias),
    preload(rhs.preload)
{ }

require::~require() {}

// Static helper method to actually create |require| function objects
object require::create_require() {
  object fn = create_native_functor_function<require>(object());
  require* r = static_cast<require*>(native_function_base::get_native(fn));

  const property_flag perm_ro = permanent_property | read_only_property;

  fn.define_property("module_cache", r->module_cache, perm_ro);
  fn.define_property("paths", r->paths, perm_ro);
  fn.define_property("alias", r->alias, perm_ro);
  fn.define_property("preload", r->preload, perm_ro);
  return fn;
}

// Each module wants a different |require| object, so that it can have a
// different require.id property
object require::new_require_function(string const &id) {
  // Use the copy ctor form to share the JS state variables.
  object new_req = create_native_functor_function<require>(object(), *this);
  new_req.set_prototype(*this);

  new_req.define_property("id", id, permanent_property|read_only_property);

  return new_req;
}

// The implementation of the |require()| function that is available to JS
void require::call(call_context &x) {
  std::string id = x.arg[0].to_std_string();

  // If what ever they require is already loaded, give it to them
  if (module_cache.has_own_property(id)) {
    x.result = module_cache.get_property(id);
    return;
  }

  id_classification type = classify_id(id);

  if (type == top_level) {
    x.result = load_top_level_module(id);
    return;
  }

  fs::path module_path;
  if (type == relative) {
    module_path = resolve_relative_id( id );
    id = module_path.string();
  }
  else if (type == fully_qualified) {
    id = id.substr(strlen("file://"));
    module_path = io::fs_base::canonicalize( id );
  }
  id = "file://" + id;

  // If what ever the file resolves to is already loaded, give it to them
  if (module_cache.has_own_property(id)) {
    x.result = module_cache.get_property(id);
    return;
  }

  x.result = load_absolute_js_file(module_path, id);
}

#include <iostream>

string transcode_js_file(fs::path filename) {
  io::file &f = create_native_object<io::file>(
    object(),
    filename.string().c_str(),
    value("r")
  );

  // buffer blob
  byte_array &blob = create_native_object<byte_array>(
    object(),
    static_cast<binary::element_type*>(0),
    0
  );
  binary::vector_type &buf = blob.get_data();

  // Look for a shebang line
  f.read_binary(2, blob);

  if (buf[0] == '#' && buf[1] == '!') {
    // Shebang line - skip the line, but insert an empty one in there to keep
    // source line numbers right
    buf.clear();
    buf.push_back('\n');
    f.read_line(value("\n"));
  }
  f.read_whole_binary(blob);

  // TODO: Some way of supporting other encodings is probably useful
  return encodings::convert_to_string("UTF-8", blob);

}

/// Load the given @c filename as a module
void require::require_js(fs::path filename, std::string const &id, object exports) {
  class StrictModeScopeGuard {
      bool old_strict;
    public:
      StrictModeScopeGuard(bool v) : old_strict(v) {}

      ~StrictModeScopeGuard() {
        flusspferd::current_context().set_strict(old_strict);
      }
  };
  // Reset the strict mode when we leave (the REPL might have it off)
  StrictModeScopeGuard guard(flusspferd::current_context().set_strict(true));

  local_root_scope root_scope;

  string module_text = transcode_js_file(filename);

  std::vector<std::string> argnames;
  argnames.push_back("exports");
  argnames.push_back("require");
  argnames.push_back("module");

  std::string fname = filename.string();
  function fn = ::flusspferd::create_function(
      fname, argnames.size(), argnames,
      module_text, fname.c_str(), 1ul);

  object module = create_object();
  module.set_property("uri", id);
  module.set_property("id", id);

  object require = new_require_function(id);

  fn.call(fn, exports, require, module);
}

/// What type of require id is @c id
require::id_classification require::classify_id(std::string const &id) {
  if (algo::starts_with(id, "./") || algo::starts_with(id, "../"))
    return relative;
  if (algo::starts_with(id, "file://"))
    return fully_qualified;
  return top_level;
}

/**
 * Resolve a realtive ID (as passed to require) using the current module id
 * returning a canonical filename
 *
 * @param id The require id to resolve into an absolute path
 * @return boost::filesystem::path object
 */
fs::path require::resolve_relative_id(std::string const &id) {

  fs::path module(current_id().substr(strlen("file://")));
  module.remove_filename();

  return io::fs_base::canonicalize( module / id ).replace_extension(".js");
}

// Utility class to remove |module_cache[id]| in case of an exception
class ExportsScopeGuard {
    object module_cache;
    std::string id;
  public:
    ExportsScopeGuard(object _cache, std::string _id)
      : module_cache(_cache),
        id(_id)
    {}

    ~ExportsScopeGuard() {
      if (!module_cache.is_null())
        module_cache.delete_property(id);
    }

    void exit_cleanly() {
      // Replace object with null
      module_cache = object();
    }
};

object load_native_module(fs::path const &dso_name, object exports) {
  std::string const &fullpath = dso_name.string();
#ifdef WIN32
  HMODULE module = LoadLibrary(fullpath.c_str());

  // TODO: Imrpove error message
  if (!module)
    throw exception(("Unable to load library '" +fullpath+"'"));

  FARPROC symbol = GetProcAddress(module, "flusspferd_load");

  if (!symbol)
    throw exception(("Unable to load library '" + fullpath + "': symbol "
                    "not found"));
#else
  // Load the .so
  void *module = dlopen(fullpath.c_str(), RTLD_LAZY);
  if (!module) {
    std::stringstream ss;
    ss << "Unable to load library '" << fullpath
       << "': " << dlerror();
    throw exception(ss.str());
  }

  dlerror(); // clear error state

  void *symbol = dlsym(module, "flusspferd_load");

  char const *const error_string = dlerror();

    if (error_string) {
      std::stringstream ss;
      ss << "Unable to load library '" << fullpath
         << "': " << error_string;
      throw exception(ss.str());
    }
#endif

  flusspferd_load_t func = *(flusspferd_load_t*) &symbol;

  object context = global();
  func(exports, context);

  return exports;
}

std::string require::current_id() {
  return get_property("id").to_std_string();
}

// Loading of top-level IDs is more complex then relative or abs uris
// We need to check alias and prelaod, and also search the require paths for
// .js files and DSOs
object require::load_top_level_module(std::string &id) {
  security &sec = security::get();

  object classes_object = flusspferd::global();
  object ctx = flusspferd::create_object(classes_object);
  ctx.set_parent(classes_object);

  root_object exports(create_object());

  ctx.define_property(
    "exports",
    exports,
    read_only_property | permanent_property);

  ExportsScopeGuard scope_guard(module_cache, id);
  module_cache.set_property(id, exports);

  if (!preload.is_null()) {
    // Check for 'preloaded' module
    value loader = preload.get_property(id);
    if (loader.is_object() && !loader.is_null()) {
      object o = loader.get_object();
      o.call(ctx);
      scope_guard.exit_cleanly();

      return exports;
    }
  }

  size_t len = paths.length();
  bool found = false;

  fs::path dso_name = make_dsoname(id);

  for (size_t i = 0; i < len; i++) {
    fs::path path = io::fs_base::canonicalize(paths.get_element(i).to_std_string());
    fs::path native_path = path / dso_name;
    if (sec.check_path(native_path.string(), security::READ) &&
        fs::exists(native_path) )
    {
      found = true;
      load_native_module(native_path, exports);
      break;
    }
  }

  fs::path js_name = fs::path(id).replace_extension(".js");

  for (size_t i = 0; i < len; i++) {
    fs::path path = io::fs_base::canonicalize(paths.get_element(i).to_std_string());

    fs::path js_path = path / js_name;

    // Check if we loaded something by this name previously, even if the file
    // doesn't exist anymore
    std::string new_id = "file://" + js_path.string();
    if (module_cache.has_own_property(new_id)) {
      exports = module_cache.get_property_object(new_id);
      found = true;
      break;
    }

    if ( !fs::exists(js_path) )
      continue;

    found = true;

    // Cache it under the top-level and fully-qualified ids
    ExportsScopeGuard scope_guard2(module_cache, new_id);
    module_cache.set_property(new_id, exports);

    require_js(js_path, new_id, exports);
    scope_guard2.exit_cleanly();
    break;
  }

  if (found)
    scope_guard.exit_cleanly();
  else {
    std::stringstream ss;
    ss << "Unable to find library '" << id << "' in [" << paths << "]";
    throw exception(ss.str());
  }

  return exports;
}

object require::load_absolute_js_file(fs::path path, std::string &id) {
  security &sec = security::get();

  ExportsScopeGuard scope_guard(module_cache, id);
  if (sec.check_path(path.string(), security::READ) &&
      fs::exists(path))
  {
    root_object exports(create_object());

    module_cache.set_property(id, exports);
    require_js(path, id, exports);
    scope_guard.exit_cleanly();
    return exports;
  }

  std::stringstream ss;
  ss << "Unable to load library '" << id;
  throw exception(ss.str());
}

static fs::path make_dsoname(std::string const &id) {
  fs::path p(id);

  p.replace_extension(FLUSSPFERD_MODULE_SUFFIX);
#ifdef SHLIBPREFIX
  std::string file = SHLIBPREFIX + p.filename();
  p = p.remove_filename() / file;
#endif

  return p;
}

<commit_msg>core/require: Don't replace extension, add to it.<commit_after>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
The MIT License

Copyright (c) 2008, 2009 Flusspferd contributors (see "CONTRIBUTORS" or
                                       http://flusspferd.org/contributors.txt)

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 "flusspferd/modules.hpp"
#include "flusspferd/create.hpp"
#include "flusspferd/security.hpp"
#include "flusspferd/evaluate.hpp"
#include "flusspferd/value_io.hpp"
#include "flusspferd/io/file.hpp"
#include "flusspferd/io/filesystem-base.hpp"
#include "flusspferd/binary.hpp"
#include "flusspferd/encodings.hpp"
#include <boost/filesystem/fstream.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <sstream>

#ifdef WIN32
#include <windows.h>
#else
#define SHLIBPREFIX "lib"
#include <dlfcn.h>
#endif

using namespace flusspferd;

namespace algo = boost::algorithm;
namespace fs = boost::filesystem;

static fs::path make_dsoname(std::string const &id);

// Create |require| function on container.
void flusspferd::load_require_function(object container) {
  container.set_property("require", require::create_require());
}

require::require()
  : native_function_base(1, "require"),
    module_cache(create_object()),
    paths(create_array()),
    alias(create_object()),
    preload(create_object())
{ }

// Copy constructor. Keep the same JS objects for the state variables
require::require(require const &rhs)
  : native_function_base(1, "require"),
    module_cache(rhs.module_cache),
    paths(rhs.paths),
    alias(rhs.alias),
    preload(rhs.preload)
{ }

require::~require() {}

// Static helper method to actually create |require| function objects
object require::create_require() {
  object fn = create_native_functor_function<require>(object());
  require* r = static_cast<require*>(native_function_base::get_native(fn));

  const property_flag perm_ro = permanent_property | read_only_property;

  fn.define_property("module_cache", r->module_cache, perm_ro);
  fn.define_property("paths", r->paths, perm_ro);
  fn.define_property("alias", r->alias, perm_ro);
  fn.define_property("preload", r->preload, perm_ro);
  return fn;
}

// Each module wants a different |require| object, so that it can have a
// different require.id property
object require::new_require_function(string const &id) {
  // Use the copy ctor form to share the JS state variables.
  object new_req = create_native_functor_function<require>(object(), *this);
  new_req.set_prototype(*this);

  new_req.define_property("id", id, permanent_property|read_only_property);

  return new_req;
}

// The implementation of the |require()| function that is available to JS
void require::call(call_context &x) {
  std::string id = x.arg[0].to_std_string();

  // If what ever they require is already loaded, give it to them
  if (module_cache.has_own_property(id)) {
    x.result = module_cache.get_property(id);
    return;
  }

  id_classification type = classify_id(id);

  if (type == top_level) {
    x.result = load_top_level_module(id);
    return;
  }

  fs::path module_path;
  if (type == relative) {
    module_path = resolve_relative_id( id );
    id = module_path.string();
  }
  else if (type == fully_qualified) {
    id = id.substr(strlen("file://"));
    module_path = io::fs_base::canonicalize( id );
  }
  id = "file://" + id;

  // If what ever the file resolves to is already loaded, give it to them
  if (module_cache.has_own_property(id)) {
    x.result = module_cache.get_property(id);
    return;
  }

  x.result = load_absolute_js_file(module_path, id);
}

#include <iostream>

string transcode_js_file(fs::path filename) {
  io::file &f = create_native_object<io::file>(
    object(),
    filename.string().c_str(),
    value("r")
  );

  // buffer blob
  byte_array &blob = create_native_object<byte_array>(
    object(),
    static_cast<binary::element_type*>(0),
    0
  );
  binary::vector_type &buf = blob.get_data();

  // Look for a shebang line
  f.read_binary(2, blob);

  if (buf[0] == '#' && buf[1] == '!') {
    // Shebang line - skip the line, but insert an empty one in there to keep
    // source line numbers right
    buf.clear();
    buf.push_back('\n');
    f.read_line(value("\n"));
  }
  f.read_whole_binary(blob);

  // TODO: Some way of supporting other encodings is probably useful
  return encodings::convert_to_string("UTF-8", blob);

}

/// Load the given @c filename as a module
void require::require_js(fs::path filename, std::string const &id, object exports) {
  class StrictModeScopeGuard {
      bool old_strict;
    public:
      StrictModeScopeGuard(bool v) : old_strict(v) {}

      ~StrictModeScopeGuard() {
        flusspferd::current_context().set_strict(old_strict);
      }
  };
  // Reset the strict mode when we leave (the REPL might have it off)
  StrictModeScopeGuard guard(flusspferd::current_context().set_strict(true));

  local_root_scope root_scope;

  string module_text = transcode_js_file(filename);

  std::vector<std::string> argnames;
  argnames.push_back("exports");
  argnames.push_back("require");
  argnames.push_back("module");

  std::string fname = filename.string();
  function fn = ::flusspferd::create_function(
      fname, argnames.size(), argnames,
      module_text, fname.c_str(), 1ul);

  object module = create_object();
  module.set_property("uri", id);
  module.set_property("id", id);

  object require = new_require_function(id);

  fn.call(fn, exports, require, module);
}

/// What type of require id is @c id
require::id_classification require::classify_id(std::string const &id) {
  if (algo::starts_with(id, "./") || algo::starts_with(id, "../"))
    return relative;
  if (algo::starts_with(id, "file://"))
    return fully_qualified;
  return top_level;
}

/**
 * Resolve a realtive ID (as passed to require) using the current module id
 * returning a canonical filename
 *
 * @param id The require id to resolve into an absolute path
 * @return boost::filesystem::path object
 */
fs::path require::resolve_relative_id(std::string const &id) {

  fs::path module(current_id().substr(strlen("file://")));
  module.remove_filename();

  return io::fs_base::canonicalize( module / id ).replace_extension(".js");
}

// Utility class to remove |module_cache[id]| in case of an exception
class ExportsScopeGuard {
    object module_cache;
    std::string id;
  public:
    ExportsScopeGuard(object _cache, std::string _id)
      : module_cache(_cache),
        id(_id)
    {}

    ~ExportsScopeGuard() {
      if (!module_cache.is_null())
        module_cache.delete_property(id);
    }

    void exit_cleanly() {
      // Replace object with null
      module_cache = object();
    }
};

object load_native_module(fs::path const &dso_name, object exports) {
  std::string const &fullpath = dso_name.string();
#ifdef WIN32
  HMODULE module = LoadLibrary(fullpath.c_str());

  // TODO: Imrpove error message
  if (!module)
    throw exception(("Unable to load library '" +fullpath+"'"));

  FARPROC symbol = GetProcAddress(module, "flusspferd_load");

  if (!symbol)
    throw exception(("Unable to load library '" + fullpath + "': symbol "
                    "not found"));
#else
  // Load the .so
  void *module = dlopen(fullpath.c_str(), RTLD_LAZY);
  if (!module) {
    std::stringstream ss;
    ss << "Unable to load library '" << fullpath
       << "': " << dlerror();
    throw exception(ss.str());
  }

  dlerror(); // clear error state

  void *symbol = dlsym(module, "flusspferd_load");

  char const *const error_string = dlerror();

    if (error_string) {
      std::stringstream ss;
      ss << "Unable to load library '" << fullpath
         << "': " << error_string;
      throw exception(ss.str());
    }
#endif

  flusspferd_load_t func = *(flusspferd_load_t*) &symbol;

  object context = global();
  func(exports, context);

  return exports;
}

std::string require::current_id() {
  return get_property("id").to_std_string();
}

// Loading of top-level IDs is more complex then relative or abs uris
// We need to check alias and prelaod, and also search the require paths for
// .js files and DSOs
object require::load_top_level_module(std::string &id) {
  security &sec = security::get();

  object classes_object = flusspferd::global();
  object ctx = flusspferd::create_object(classes_object);
  ctx.set_parent(classes_object);

  root_object exports(create_object());

  ctx.define_property(
    "exports",
    exports,
    read_only_property | permanent_property);

  ExportsScopeGuard scope_guard(module_cache, id);
  module_cache.set_property(id, exports);

  if (!preload.is_null()) {
    // Check for 'preloaded' module
    value loader = preload.get_property(id);
    if (loader.is_object() && !loader.is_null()) {
      object o = loader.get_object();
      o.call(ctx);
      scope_guard.exit_cleanly();

      return exports;
    }
  }

  size_t len = paths.length();
  bool found = false;

  fs::path dso_name = make_dsoname(id);

  for (size_t i = 0; i < len; i++) {
    fs::path path = io::fs_base::canonicalize(paths.get_element(i).to_std_string());
    fs::path native_path = path / dso_name;
    if (sec.check_path(native_path.string(), security::READ) &&
        fs::exists(native_path) )
    {
      found = true;
      load_native_module(native_path, exports);
      break;
    }
  }

  fs::path js_name = fs::path(id + ".js");

  for (size_t i = 0; i < len; i++) {
    fs::path path = io::fs_base::canonicalize(paths.get_element(i).to_std_string());

    fs::path js_path = path / js_name;

    // Check if we loaded something by this name previously, even if the file
    // doesn't exist anymore
    std::string new_id = "file://" + js_path.string();
    if (module_cache.has_own_property(new_id)) {
      exports = module_cache.get_property_object(new_id);
      found = true;
      break;
    }

    if ( !fs::exists(js_path) )
      continue;

    found = true;

    // Cache it under the top-level and fully-qualified ids
    ExportsScopeGuard scope_guard2(module_cache, new_id);
    module_cache.set_property(new_id, exports);

    require_js(js_path, new_id, exports);
    scope_guard2.exit_cleanly();
    break;
  }

  if (found)
    scope_guard.exit_cleanly();
  else {
    std::stringstream ss;
    ss << "Unable to find library '" << id << "' in [" << paths << "]";
    throw exception(ss.str());
  }

  return exports;
}

object require::load_absolute_js_file(fs::path path, std::string &id) {
  security &sec = security::get();

  ExportsScopeGuard scope_guard(module_cache, id);
  if (sec.check_path(path.string(), security::READ) &&
      fs::exists(path))
  {
    root_object exports(create_object());

    module_cache.set_property(id, exports);
    require_js(path, id, exports);
    scope_guard.exit_cleanly();
    return exports;
  }

  std::stringstream ss;
  ss << "Unable to load library '" << id;
  throw exception(ss.str());
}

static fs::path make_dsoname(std::string const &id) {
  fs::path p(id);

  p.replace_extension(FLUSSPFERD_MODULE_SUFFIX);
#ifdef SHLIBPREFIX
  std::string file = SHLIBPREFIX + p.filename();
  p = p.remove_filename() / file;
#endif

  return p;
}

<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011-2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <algorithm>

#include "assert.hpp"
#include "Variable.hpp"
#include "FunctionContext.hpp"
#include "Type.hpp"
#include "iterators.hpp"
#include "GlobalContext.hpp"

#include "mtac/global_cse.hpp"
#include "mtac/Utils.hpp"
#include "mtac/Quadruple.hpp"

using namespace eddic;

typedef mtac::global_cse::ProblemDomain ProblemDomain;

void mtac::global_cse::meet(ProblemDomain& in, const ProblemDomain& out){
    eddic_assert(!in.top() || !out.top(), "At least one lattice should not be a top element");

    if(in.top()){
        in = out;
    } else if(out.top()){
        //in does not change
    } else {
        auto& first = in.values();
        auto& second = out.values();

        std::set<expression> intersection;

        std::set_intersection(first.begin(), first.end(), second.begin(), second.end(), std::inserter(intersection, intersection.begin()));

        in.values() = std::move(intersection);
    }
}

ProblemDomain mtac::global_cse::Boundary(mtac::Function&){
    return ProblemDomain(ProblemDomain::Values());
}

ProblemDomain mtac::global_cse::Init(mtac::Function& function){
    if(init){
        ProblemDomain result(*init);
        return result;
    }

    this->function = &function;

    pointer_escaped = mtac::escape_analysis(function);

    typename ProblemDomain::Values values;

    //Compute Eval(i)

    for(auto& block : function){
        for(auto& q : block->statements){
            if(mtac::is_expression(q.op) && mtac::is_valid(q, pointer_escaped) && mtac::is_interesting(q)){
                Eval[block].insert({0, *q.arg1, *q.arg2, q.op, nullptr, q.result->type()});
            }

            mtac::kill_expressions(q, Eval[block]);
        }
    }

    //Compute Kill(i)

    for(auto& block : function){
        for(auto& q : block->statements){
            auto op = q.op;
            if(mtac::erase_result(op) || op == mtac::Operator::DOT_ASSIGN || op == mtac::Operator::DOT_FASSIGN || op == mtac::Operator::DOT_PASSIGN){
                for(auto& b : function){
                    if(b != block){
                        for(auto& expression : Eval[b]){
                            if(mtac::is_killing(q, expression)){
                                Kill[block].insert(expression);
                            }
                        }
                    }
                }
            }
        }
    }

    Expressions expressions;

    //Compute Uexp

    for(auto& block : function){
        for(auto& expression : Eval[block]){
            expressions.insert(expression);
        }
    }

    init = expressions;

    ProblemDomain result(expressions);
    return result;
}

void mtac::global_cse::transfer(mtac::basic_block_p basic_block, ProblemDomain& out){
    auto& out_values = out.values();
    auto it = out_values.begin();

    //Compute AEin - Kill(i)

    while(it != out_values.end()){
        if(Kill[basic_block].find(*it) != Kill[basic_block].end()){
            it = out_values.erase(it);
            continue;
        }

        ++it;
    }

    //Compute Eval(i) U (AEin - Kill(i))

    for(auto& expression : Eval[basic_block]){
        out_values.insert(expression);
    }
}

namespace {

void search_path(const mtac::expression& exp, std::shared_ptr<Variable>& tj, mtac::Operator op, mtac::basic_block_p& block){
   auto it = block->end();
   auto end = block->begin();

   do {
        --it;

        auto& quadruple = *it;
        if(mtac::are_equivalent(quadruple, exp)){
            quadruple.op = op;
            quadruple.arg1 = tj;
            quadruple.arg2.reset();

            block->statements.insert(it, mtac::Quadruple(tj, exp.arg1, exp.op, exp.arg2));

            return;
        }
   } while(it != end);

   eddic_assert(!block->predecessors.empty(), "There must be an equivalent expression on each backward path");

   for(auto& P : block->predecessors){
       if(P != block){
           search_path(exp, tj, op, P);
       }
   }
}

} //end of anonymous namespace

bool mtac::global_cse::optimize(mtac::Function& function, std::shared_ptr<mtac::DataFlowResults<ProblemDomain>> global_results){
    bool changes = false;

    for(auto& i : function){
        if(global_results->IN[i].top()){
            continue;
        }

        auto& AEin = global_results->IN[i].values();

        for(auto& exp : Eval[i]){
            if(AEin.find(exp) != AEin.end()){
                function.context->global()->stats().inc_counter("common_subexpr_eliminated");

                auto it = i->begin();

                while(!mtac::are_equivalent(*it, exp)){
                    ++it;
                }

                auto& quadruple = *it;

                bool global_cs = true;

                do {
                    --it;

                    if(mtac::erase_result(it->op) || it->op == mtac::Operator::DOT_ASSIGN || it->op == mtac::Operator::DOT_FASSIGN || it->op == mtac::Operator::DOT_PASSIGN){
                        if(mtac::is_killing(*it, exp)){
                            global_cs = false;
                            break;
                        }
                    }
                } while(it != i->begin());

                if(!global_cs){
                    continue;
                }

                auto tj = function.context->new_temporary(exp.type);
                mtac::Operator op = mtac::assign_op(exp.op);

                quadruple.op = op;
                quadruple.arg1 = tj;
                quadruple.arg2.reset();

                for(auto& P : i->predecessors){
                    if(P != i){
                        search_path(exp, tj, op, P);
                    }
                }
            }
        }
    }

    //TODO Avoid doing that first, but integrate it the process

    /*for(auto& block : function){
        auto& in = global_results->IN[block];

        for(auto& statement : block){
            transfer(block, statement, in);
            global_results->IN_S[statement.uid()] = in;
        }
    }

    for(auto& block : function){
        auto qit = block->statements.begin();
        auto qend = block->statements.end();

        while(qit != qend){
            bool local = false;

            auto& quadruple = *qit;
            auto& results = global_results->IN_S[quadruple.uid()];

            if(results.top()){
                ++qit;
                continue;
            }

            if(optimized.find(quadruple.uid()) == optimized.end()){
                if(mtac::is_expression(quadruple.op)){
                    for(auto& expression : results.values()){
                        auto& source_statement = function.find(expression.expression);
                        auto result = source_statement.result;
                        auto quid = quadruple.uid();

                        if(::are_equivalent(source_statement, quadruple)){
                            mtac::Operator assign_op;
                            if((quadruple.op >= mtac::Operator::ADD && quadruple.op <= mtac::Operator::MOD) || quadruple.op == mtac::Operator::DOT){
                                assign_op = mtac::Operator::ASSIGN;
                            } else {
                                assign_op = mtac::Operator::FASSIGN;
                            }

                            std::shared_ptr<Variable> new_result = result;

                            if(optimized.find(source_statement.uid()) == optimized.end()){
                                function.context->global()->stats().inc_counter("common_subexpr_eliminated");

                                std::shared_ptr<Variable> temp;
                                temp = expression.source->context->new_temporary(result->type());

                                new_result = temp;

                                auto it = expression.source->statements.begin();
                                auto end = expression.source->statements.end();

                                source_statement.result = temp;

                                optimized.insert(source_statement.uid());

                                while(it != end){
                                    auto& target = *it;
                                    if(target == source_statement){
                                        ++it;
                                        expression.source->statements.insert(it, mtac::Quadruple(result, temp, assign_op));

                                        break;
                                    }

                                    ++it;
                                }
                            }

                            if(optimized.find(quid) == optimized.end()){
                                function.context->global()->stats().inc_counter("common_subexpr_eliminated");

                                auto& quadruple = function.find(quid);

                                eddic_assert(new_result, "Should have been filled");

                                quadruple.op = assign_op;
                                quadruple.arg1 = new_result;
                                quadruple.arg2.reset();

                                optimized.insert(quid);

                                local = true;
                                changes = true;

                                break;
                            }
                        }
                    }
                }
            }

            if(local){
                qit = block->statements.begin();
                qend = block->statements.end();
            } else {
                ++qit;
            }
        }
    }*/

    return changes;
}

bool mtac::operator==(const mtac::Domain<Expressions>& lhs, const mtac::Domain<Expressions>& rhs){
    if(lhs.top() || rhs.top()){
        return lhs.top() == rhs.top();
    }

    auto& lhs_values = lhs.values();
    auto& rhs_values = rhs.values();

    if(lhs_values.size() != rhs_values.size()){
        return false;
    }

    for(auto& lhs_expression : lhs_values){
        if(rhs_values.find(lhs_expression) == rhs_values.end()){
            return false;
        }
    }

    return true;
}

bool mtac::operator!=(const mtac::Domain<Expressions>& lhs, const mtac::Domain<Expressions>& rhs){
    return !(lhs == rhs);
}
<commit_msg>Make sure to avoid loops<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <algorithm>

#include "assert.hpp"
#include "Variable.hpp"
#include "FunctionContext.hpp"
#include "Type.hpp"
#include "iterators.hpp"
#include "GlobalContext.hpp"

#include "mtac/global_cse.hpp"
#include "mtac/Utils.hpp"
#include "mtac/Quadruple.hpp"

using namespace eddic;

typedef mtac::global_cse::ProblemDomain ProblemDomain;

void mtac::global_cse::meet(ProblemDomain& in, const ProblemDomain& out){
    eddic_assert(!in.top() || !out.top(), "At least one lattice should not be a top element");

    if(in.top()){
        in = out;
    } else if(out.top()){
        //in does not change
    } else {
        auto& first = in.values();
        auto& second = out.values();

        std::set<expression> intersection;

        std::set_intersection(first.begin(), first.end(), second.begin(), second.end(), std::inserter(intersection, intersection.begin()));

        in.values() = std::move(intersection);
    }
}

ProblemDomain mtac::global_cse::Boundary(mtac::Function&){
    return ProblemDomain(ProblemDomain::Values());
}

ProblemDomain mtac::global_cse::Init(mtac::Function& function){
    if(init){
        ProblemDomain result(*init);
        return result;
    }

    this->function = &function;

    pointer_escaped = mtac::escape_analysis(function);

    typename ProblemDomain::Values values;

    //Compute Eval(i)

    for(auto& block : function){
        for(auto& q : block->statements){
            if(mtac::is_expression(q.op) && mtac::is_valid(q, pointer_escaped) && mtac::is_interesting(q)){
                Eval[block].insert({0, *q.arg1, *q.arg2, q.op, nullptr, q.result->type()});
            }

            mtac::kill_expressions(q, Eval[block]);
        }
    }

    //Compute Kill(i)

    for(auto& block : function){
        for(auto& q : block->statements){
            auto op = q.op;
            if(mtac::erase_result(op) || op == mtac::Operator::DOT_ASSIGN || op == mtac::Operator::DOT_FASSIGN || op == mtac::Operator::DOT_PASSIGN){
                for(auto& b : function){
                    if(b != block){
                        for(auto& expression : Eval[b]){
                            if(mtac::is_killing(q, expression)){
                                Kill[block].insert(expression);
                            }
                        }
                    }
                }
            }
        }
    }

    Expressions expressions;

    //Compute Uexp

    for(auto& block : function){
        for(auto& expression : Eval[block]){
            expressions.insert(expression);
        }
    }

    init = expressions;

    ProblemDomain result(expressions);
    return result;
}

void mtac::global_cse::transfer(mtac::basic_block_p basic_block, ProblemDomain& out){
    auto& out_values = out.values();
    auto it = out_values.begin();

    //Compute AEin - Kill(i)

    while(it != out_values.end()){
        if(Kill[basic_block].find(*it) != Kill[basic_block].end()){
            it = out_values.erase(it);
            continue;
        }

        ++it;
    }

    //Compute Eval(i) U (AEin - Kill(i))

    for(auto& expression : Eval[basic_block]){
        out_values.insert(expression);
    }
}

namespace {

void search_path(const mtac::expression& exp, std::shared_ptr<Variable>& tj, mtac::Operator op, mtac::basic_block_p& block, std::unordered_set<mtac::basic_block_p>& visited){
    if(visited.find(block) != visited.end()){
        return;
    }

    visited.insert(block);

    auto it = block->end();
    auto end = block->begin();

    do {
        --it;

        auto& quadruple = *it;
        if(mtac::are_equivalent(quadruple, exp)){
            quadruple.op = op;
            quadruple.arg1 = tj;
            quadruple.arg2.reset();

            block->statements.insert(it, mtac::Quadruple(tj, exp.arg1, exp.op, exp.arg2));

            return;
        }
    } while(it != end);

    eddic_assert(!block->predecessors.empty(), "There must be an equivalent expression on each backward path");

    for(auto& P : block->predecessors){
        search_path(exp, tj, op, P, visited);
    }
}

} //end of anonymous namespace

bool mtac::global_cse::optimize(mtac::Function& function, std::shared_ptr<mtac::DataFlowResults<ProblemDomain>> global_results){
    bool changes = false;

    for(auto& i : function){
        if(global_results->IN[i].top()){
            continue;
        }

        auto& AEin = global_results->IN[i].values();

        for(auto& exp : Eval[i]){
            if(AEin.find(exp) != AEin.end()){
                function.context->global()->stats().inc_counter("common_subexpr_eliminated");

                auto it = i->begin();

                while(!mtac::are_equivalent(*it, exp)){
                    ++it;
                }

                auto& quadruple = *it;

                bool global_cs = true;

                do {
                    --it;

                    if(mtac::erase_result(it->op) || it->op == mtac::Operator::DOT_ASSIGN || it->op == mtac::Operator::DOT_FASSIGN || it->op == mtac::Operator::DOT_PASSIGN){
                        if(mtac::is_killing(*it, exp)){
                            global_cs = false;
                            break;
                        }
                    }
                } while(it != i->begin());

                if(!global_cs){
                    continue;
                }

                auto tj = function.context->new_temporary(exp.type);
                mtac::Operator op = mtac::assign_op(exp.op);

                quadruple.op = op;
                quadruple.arg1 = tj;
                quadruple.arg2.reset();

                std::unordered_set<mtac::basic_block_p> visited;
                visited.insert(i);

                for(auto& P : i->predecessors){
                    search_path(exp, tj, op, P, visited);
                }
            }
        }
    }

    //TODO Avoid doing that first, but integrate it the process

    /*for(auto& block : function){
        auto& in = global_results->IN[block];

        for(auto& statement : block){
            transfer(block, statement, in);
            global_results->IN_S[statement.uid()] = in;
        }
    }

    for(auto& block : function){
        auto qit = block->statements.begin();
        auto qend = block->statements.end();

        while(qit != qend){
            bool local = false;

            auto& quadruple = *qit;
            auto& results = global_results->IN_S[quadruple.uid()];

            if(results.top()){
                ++qit;
                continue;
            }

            if(optimized.find(quadruple.uid()) == optimized.end()){
                if(mtac::is_expression(quadruple.op)){
                    for(auto& expression : results.values()){
                        auto& source_statement = function.find(expression.expression);
                        auto result = source_statement.result;
                        auto quid = quadruple.uid();

                        if(::are_equivalent(source_statement, quadruple)){
                            mtac::Operator assign_op;
                            if((quadruple.op >= mtac::Operator::ADD && quadruple.op <= mtac::Operator::MOD) || quadruple.op == mtac::Operator::DOT){
                                assign_op = mtac::Operator::ASSIGN;
                            } else {
                                assign_op = mtac::Operator::FASSIGN;
                            }

                            std::shared_ptr<Variable> new_result = result;

                            if(optimized.find(source_statement.uid()) == optimized.end()){
                                function.context->global()->stats().inc_counter("common_subexpr_eliminated");

                                std::shared_ptr<Variable> temp;
                                temp = expression.source->context->new_temporary(result->type());

                                new_result = temp;

                                auto it = expression.source->statements.begin();
                                auto end = expression.source->statements.end();

                                source_statement.result = temp;

                                optimized.insert(source_statement.uid());

                                while(it != end){
                                    auto& target = *it;
                                    if(target == source_statement){
                                        ++it;
                                        expression.source->statements.insert(it, mtac::Quadruple(result, temp, assign_op));

                                        break;
                                    }

                                    ++it;
                                }
                            }

                            if(optimized.find(quid) == optimized.end()){
                                function.context->global()->stats().inc_counter("common_subexpr_eliminated");

                                auto& quadruple = function.find(quid);

                                eddic_assert(new_result, "Should have been filled");

                                quadruple.op = assign_op;
                                quadruple.arg1 = new_result;
                                quadruple.arg2.reset();

                                optimized.insert(quid);

                                local = true;
                                changes = true;

                                break;
                            }
                        }
                    }
                }
            }

            if(local){
                qit = block->statements.begin();
                qend = block->statements.end();
            } else {
                ++qit;
            }
        }
    }*/

    return changes;
}

bool mtac::operator==(const mtac::Domain<Expressions>& lhs, const mtac::Domain<Expressions>& rhs){
    if(lhs.top() || rhs.top()){
        return lhs.top() == rhs.top();
    }

    auto& lhs_values = lhs.values();
    auto& rhs_values = rhs.values();

    if(lhs_values.size() != rhs_values.size()){
        return false;
    }

    for(auto& lhs_expression : lhs_values){
        if(rhs_values.find(lhs_expression) == rhs_values.end()){
            return false;
        }
    }

    return true;
}

bool mtac::operator!=(const mtac::Domain<Expressions>& lhs, const mtac::Domain<Expressions>& rhs){
    return !(lhs == rhs);
}
<|endoftext|>


<commit_before>#include "common.hpp"
#include <errno.h>
#include <sys/socket.h>

#include <posix/fd_map.hpp>
#include <posix/tcp_fd.hpp>
#include <posix/udp_fd.hpp>

static long sock_socket(int domain, int type, int protocol)
{
  // disallow strange domains, like ALG
  if (UNLIKELY(domain < 0 || domain > AF_INET6))
    return -EAFNOSUPPORT;
  // disallow RAW etc
  if (UNLIKELY(type < 0 || type > SOCK_DGRAM))
    return -EINVAL;
  // we are purposefully ignoring the protocol argument
  if (UNLIKELY(protocol < 0))
    return -EPROTONOSUPPORT;

  return [](const int type)->int{
    switch(type)
    {
      case SOCK_STREAM:
        return FD_map::_open<TCP_FD>().get_id();
      case SOCK_DGRAM:
        return FD_map::_open<UDP_FD>().get_id();
      default:
        return -EINVAL;
    }
  }(type);
}

static long sock_connect(int sockfd, const struct sockaddr *addr,
                         socklen_t addrlen)
{
  if(auto* fildes = FD_map::_get(sockfd); fildes)
    return fildes->connect(addr, addrlen);

  return -EBADF;
}

static long sock_bind(int sockfd, const struct sockaddr *addr,
                      socklen_t addrlen)
{
  if(auto* fildes = FD_map::_get(sockfd); fildes)
    return fildes->bind(addr, addrlen);

  return -EBADF;
}

static long sock_sendmsg(int sockfd, const struct msghdr *msg, int flags)
{
  if(auto* fildes = FD_map::_get(sockfd); fildes)
    return fildes->sendmsg(msg, flags);

  return -EBADF;
}

static ssize_t sock_sendto(int sockfd, const void *buf, size_t len, int flags,
                           const struct sockaddr *dest_addr, socklen_t addrlen)
{
  if(auto* fildes = FD_map::_get(sockfd); fildes)
    return fildes->sendto(buf, len, flags, dest_addr, addrlen);

  return -EBADF;
}

static ssize_t sock_recvfrom(int sockfd, void *buf, size_t len, int flags,
                             struct sockaddr *src_addr, socklen_t *addrlen)
{
  if(auto* fildes = FD_map::_get(sockfd); fildes)
    return fildes->recvfrom(buf, len, flags, src_addr, addrlen);

  return -EBADF;
}

static long sock_listen(int sockfd, int backlog)
{
  if(auto* fildes = FD_map::_get(sockfd); fildes)
    return fildes->listen(backlog);

  return -EBADF;
}

static long sock_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
  if(auto* fildes = FD_map::_get(sockfd); fildes)
    return fildes->accept(addr, addrlen);

  return -EBADF;
}

static long sock_shutdown(int sockfd, int how)
{
  if(auto* fildes = FD_map::_get(sockfd); fildes)
    return fildes->shutdown(how);

  return -EBADF;
}

extern "C" {
long socketcall_socket(int domain, int type, int protocol)
{
  return strace(sock_socket, "socket", domain, type, protocol);
}

long socketcall_connect(int sockfd, const struct sockaddr *addr,
                        socklen_t addrlen)
{
  return strace(sock_connect, "connect", sockfd, addr, addrlen);
}

long socketcall_bind(int sockfd, const struct sockaddr *addr,
                     socklen_t addrlen)
{
  return strace(sock_bind, "bind", sockfd, addr, addrlen);
}

long socketcall_sendmsg(int sockfd, const struct msghdr *msg, int flags)
{
  return strace(sock_sendmsg, "sendmsg", sockfd, msg, flags);
}

ssize_t socketcall_sendto(int sockfd, const void *buf, size_t len, int flags,
                          const struct sockaddr *dest_addr, socklen_t addrlen)
{
  return strace(sock_sendto, "sendto", sockfd, buf, len, flags, dest_addr, addrlen);
}

ssize_t socketcall_recvfrom(int sockfd, void *buf, size_t len, int flags,
                            struct sockaddr *src_addr, socklen_t *addrlen)
{
  return strace(sock_recvfrom, "recvfrom", sockfd, buf, len, flags, src_addr, addrlen);
}

long socketcall_listen(int sockfd, int backlog)
{
  return strace(sock_listen, "listen", sockfd, backlog);
}

long socketcall_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
  return strace(sock_accept, "accept", sockfd, addr, addrlen);
}

long socketcall_shutdown(int sockfd, int how)
{
  return strace(sock_shutdown, "shutdown", sockfd, how);
}
} // < extern "C"
<commit_msg>musl: Only support AF_INET (ip4) sockets<commit_after>#include "common.hpp"
#include <errno.h>
#include <sys/socket.h>

#include <posix/fd_map.hpp>
#include <posix/tcp_fd.hpp>
#include <posix/udp_fd.hpp>

static long sock_socket(int domain, int type, int protocol)
{
  // currently only support for AF_INET (IPv4, no local/unix or IP6)
  if (UNLIKELY(domain != AF_INET))
    return -EAFNOSUPPORT;
  // disallow RAW etc
  if (UNLIKELY(type < 0 || type > SOCK_DGRAM))
    return -EINVAL;
  // we are purposefully ignoring the protocol argument
  if (UNLIKELY(protocol < 0))
    return -EPROTONOSUPPORT;

  return [](const int type)->int{
    switch(type)
    {
      case SOCK_STREAM:
        return FD_map::_open<TCP_FD>().get_id();
      case SOCK_DGRAM:
        return FD_map::_open<UDP_FD>().get_id();
      default:
        return -EINVAL;
    }
  }(type);
}

static long sock_connect(int sockfd, const struct sockaddr *addr,
                         socklen_t addrlen)
{
  if(auto* fildes = FD_map::_get(sockfd); fildes)
    return fildes->connect(addr, addrlen);

  return -EBADF;
}

static long sock_bind(int sockfd, const struct sockaddr *addr,
                      socklen_t addrlen)
{
  if(auto* fildes = FD_map::_get(sockfd); fildes)
    return fildes->bind(addr, addrlen);

  return -EBADF;
}

static long sock_sendmsg(int sockfd, const struct msghdr *msg, int flags)
{
  if(auto* fildes = FD_map::_get(sockfd); fildes)
    return fildes->sendmsg(msg, flags);

  return -EBADF;
}

static ssize_t sock_sendto(int sockfd, const void *buf, size_t len, int flags,
                           const struct sockaddr *dest_addr, socklen_t addrlen)
{
  if(auto* fildes = FD_map::_get(sockfd); fildes)
    return fildes->sendto(buf, len, flags, dest_addr, addrlen);

  return -EBADF;
}

static ssize_t sock_recvfrom(int sockfd, void *buf, size_t len, int flags,
                             struct sockaddr *src_addr, socklen_t *addrlen)
{
  if(auto* fildes = FD_map::_get(sockfd); fildes)
    return fildes->recvfrom(buf, len, flags, src_addr, addrlen);

  return -EBADF;
}

static long sock_listen(int sockfd, int backlog)
{
  if(auto* fildes = FD_map::_get(sockfd); fildes)
    return fildes->listen(backlog);

  return -EBADF;
}

static long sock_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
  if(auto* fildes = FD_map::_get(sockfd); fildes)
    return fildes->accept(addr, addrlen);

  return -EBADF;
}

static long sock_shutdown(int sockfd, int how)
{
  if(auto* fildes = FD_map::_get(sockfd); fildes)
    return fildes->shutdown(how);

  return -EBADF;
}

extern "C" {
long socketcall_socket(int domain, int type, int protocol)
{
  return strace(sock_socket, "socket", domain, type, protocol);
}

long socketcall_connect(int sockfd, const struct sockaddr *addr,
                        socklen_t addrlen)
{
  return strace(sock_connect, "connect", sockfd, addr, addrlen);
}

long socketcall_bind(int sockfd, const struct sockaddr *addr,
                     socklen_t addrlen)
{
  return strace(sock_bind, "bind", sockfd, addr, addrlen);
}

long socketcall_sendmsg(int sockfd, const struct msghdr *msg, int flags)
{
  return strace(sock_sendmsg, "sendmsg", sockfd, msg, flags);
}

ssize_t socketcall_sendto(int sockfd, const void *buf, size_t len, int flags,
                          const struct sockaddr *dest_addr, socklen_t addrlen)
{
  return strace(sock_sendto, "sendto", sockfd, buf, len, flags, dest_addr, addrlen);
}

ssize_t socketcall_recvfrom(int sockfd, void *buf, size_t len, int flags,
                            struct sockaddr *src_addr, socklen_t *addrlen)
{
  return strace(sock_recvfrom, "recvfrom", sockfd, buf, len, flags, src_addr, addrlen);
}

long socketcall_listen(int sockfd, int backlog)
{
  return strace(sock_listen, "listen", sockfd, backlog);
}

long socketcall_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
  return strace(sock_accept, "accept", sockfd, addr, addrlen);
}

long socketcall_shutdown(int sockfd, int how)
{
  return strace(sock_shutdown, "shutdown", sockfd, how);
}
} // < extern "C"
<|endoftext|>


<commit_before>#include "hecl/HMDLMeta.hpp"

#include "hecl/Runtime.hpp"

#include <athena/MemoryReader.hpp>
#include <logvisor/logvisor.hpp>

namespace hecl::Runtime {
static logvisor::Module HMDL_Log("HMDL");

HMDLData::HMDLData(boo::IGraphicsDataFactory::Context& ctx, const void* metaData, const void* vbo, const void* ibo) {
  HMDLMeta meta;
  {
    athena::io::MemoryReader r(metaData, HECL_HMDL_META_SZ);
    meta.read(r);
  }
  if (meta.magic != 'TACO')
    HMDL_Log.report(logvisor::Fatal, fmt("invalid HMDL magic"));

  m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, vbo, meta.vertStride, meta.vertCount);
  m_ibo = ctx.newStaticBuffer(boo::BufferUse::Index, ibo, 4, meta.indexCount);

  size_t elemCount = 2 + meta.colorCount + meta.uvCount + meta.weightCount;
  m_vtxFmtData.reset(new boo::VertexElementDescriptor[elemCount]);

  m_vtxFmtData[0].semantic = boo::VertexSemantic::Position3;
  m_vtxFmtData[1].semantic = boo::VertexSemantic::Normal3;
  size_t e = 2;

  for (size_t i = 0; i < meta.colorCount; ++i, ++e) {
    m_vtxFmtData[e].semantic = boo::VertexSemantic::ColorUNorm;
    m_vtxFmtData[e].semanticIdx = i;
  }

  for (size_t i = 0; i < meta.uvCount; ++i, ++e) {
    m_vtxFmtData[e].semantic = boo::VertexSemantic::UV2;
    m_vtxFmtData[e].semanticIdx = i;
  }

  for (size_t i = 0; i < meta.weightCount; ++i, ++e) {
    m_vtxFmtData[e].semantic = boo::VertexSemantic::Weight;
    m_vtxFmtData[e].semanticIdx = i;
  }

  m_vtxFmt = boo::VertexFormatInfo(elemCount, m_vtxFmtData.get());
}

} // namespace hecl::Runtime
<commit_msg>HMDL_RT: Make use of std::make_unique<commit_after>#include "hecl/HMDLMeta.hpp"

#include "hecl/Runtime.hpp"

#include <athena/MemoryReader.hpp>
#include <logvisor/logvisor.hpp>

namespace hecl::Runtime {
static logvisor::Module HMDL_Log("HMDL");

HMDLData::HMDLData(boo::IGraphicsDataFactory::Context& ctx, const void* metaData, const void* vbo, const void* ibo) {
  HMDLMeta meta;
  {
    athena::io::MemoryReader r(metaData, HECL_HMDL_META_SZ);
    meta.read(r);
  }
  if (meta.magic != 'TACO')
    HMDL_Log.report(logvisor::Fatal, fmt("invalid HMDL magic"));

  m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, vbo, meta.vertStride, meta.vertCount);
  m_ibo = ctx.newStaticBuffer(boo::BufferUse::Index, ibo, 4, meta.indexCount);

  const size_t elemCount = 2 + meta.colorCount + meta.uvCount + meta.weightCount;
  m_vtxFmtData = std::make_unique<boo::VertexElementDescriptor[]>(elemCount);

  m_vtxFmtData[0].semantic = boo::VertexSemantic::Position3;
  m_vtxFmtData[1].semantic = boo::VertexSemantic::Normal3;
  size_t e = 2;

  for (size_t i = 0; i < meta.colorCount; ++i, ++e) {
    m_vtxFmtData[e].semantic = boo::VertexSemantic::ColorUNorm;
    m_vtxFmtData[e].semanticIdx = i;
  }

  for (size_t i = 0; i < meta.uvCount; ++i, ++e) {
    m_vtxFmtData[e].semantic = boo::VertexSemantic::UV2;
    m_vtxFmtData[e].semanticIdx = i;
  }

  for (size_t i = 0; i < meta.weightCount; ++i, ++e) {
    m_vtxFmtData[e].semantic = boo::VertexSemantic::Weight;
    m_vtxFmtData[e].semanticIdx = i;
  }

  m_vtxFmt = boo::VertexFormatInfo(elemCount, m_vtxFmtData.get());
}

} // namespace hecl::Runtime
<|endoftext|>


<commit_before>#include <flusspferd.hpp>
#include <iostream>
#include <ostream>
#include <set>
#include <string>

using namespace flusspferd::param;

// Inherit from flusspferd::native_object_base or a class that derives from it.
class StringSet : public flusspferd::native_object_base {
public:
    // StringSet::class_info is used by load_class.
    struct class_info : flusspferd::class_info {
        static char const *constructor_name() {
            return "StringSet";
        }

        static char const *full_name() {
            return "StringSet";
        }

        // Function for creating the class prototype.
        static object create_prototype() {
            // Create a prototype object (with default prototype).
            flusspferd::object proto = flusspferd::create<flusspferd::object>();

            // Add the methods.
            flusspferd::create<flusspferd::method>(
                "dump", &StringSet::dump, _container = proto);
            flusspferd::create<flusspferd::method>(
                "add", &StringSet::add, _container = proto);
            flusspferd::create<flusspferd::method>(
                "delete", &StringSet::delete_, _container = proto);
            flusspferd::create<flusspferd::method>(
                "toArray", &StringSet::to_array, _container = proto);

            return proto;
        }
    };

    // The only difference here is that you must initialise
    // flusspferd::native_object_base directly.
    StringSet(flusspferd::object const &self, flusspferd::call_context &x)
        : flusspferd::native_object_base(self)
    {
        std::cout << "Creating StringSet" << std::endl;

        for (flusspferd::arguments::iterator it = x.arg.begin();
                it != x.arg.end();
                ++it) {
            data.insert((*it).to_std_string());
        }
    }

    ~StringSet() {
        std::cout << "Destroying StringSet" << std::endl;
    }

private:
    typedef std::set<std::string> container;
    typedef container::iterator iterator;

    void dump() {
        std::cout << "Dumping StringSet: ";
        for (iterator it = data.begin(); it != data.end(); ++it) {
            if (it != data.begin())
                std::cout << ',';
            std::cout << *it;
        }
        std::cout << std::endl;
    }

    void add(std::string const &x) {
        data.insert(x);
    }

    void delete_(std::string const &x) {
        if (!data.erase(x))
            throw flusspferd::exception("No such element");
    }

    flusspferd::array to_array() {
        flusspferd::root_array result(flusspferd::create<flusspferd::array>());

        for (iterator it = data.begin(); it != data.end(); ++it) {
            result.push(*it);
        }

        return result;
    }

private:
    container data;
};

void print(flusspferd::string const &x) {
    std::cout << x << std::endl;
}

int main() {
    flusspferd::current_context_scope context_scope(
        flusspferd::context::create());

    flusspferd::create<flusspferd::function>("print", &print, _container = flusspferd::global());

    flusspferd::load_class<StringSet>();

    flusspferd::evaluate(
        "var set = new StringSet('b', 'a', 'd');\n"
        "set.add('c');\n"
        "set.dump();\n"
        "set.delete('a'); set.delete('b');\n"
        "print('As Array: ' +  set.toArray().toSource());\n"
    );
}
<commit_msg>help/examples: make example benefit from create_on<commit_after>#include <flusspferd.hpp>
#include <iostream>
#include <ostream>
#include <set>
#include <string>

using namespace flusspferd::param;

// Inherit from flusspferd::native_object_base or a class that derives from it.
class StringSet : public flusspferd::native_object_base {
public:
    // StringSet::class_info is used by load_class.
    struct class_info : flusspferd::class_info {
        static char const *constructor_name() {
            return "StringSet";
        }

        static char const *full_name() {
            return "StringSet";
        }

        // Function for creating the class prototype.
        static object create_prototype() {
            // Create a prototype object (with default prototype).
            flusspferd::object proto = flusspferd::create<flusspferd::object>();

            // Add the methods.
            flusspferd::create_on(proto)
                .create<flusspferd::method>("dump", &StringSet::dump)
                .create<flusspferd::method>("add", &StringSet::add)
                .create<flusspferd::method>("delete", &StringSet::delete_)
                .create<flusspferd::method>("toArray", &StringSet::to_array);

            return proto;
        }
    };

    // The only difference here is that you must initialise
    // flusspferd::native_object_base directly.
    StringSet(flusspferd::object const &self, flusspferd::call_context &x)
        : flusspferd::native_object_base(self)
    {
        std::cout << "Creating StringSet" << std::endl;

        for (flusspferd::arguments::iterator it = x.arg.begin();
                it != x.arg.end();
                ++it) {
            data.insert((*it).to_std_string());
        }
    }

    ~StringSet() {
        std::cout << "Destroying StringSet" << std::endl;
    }

private:
    typedef std::set<std::string> container;
    typedef container::iterator iterator;

    void dump() {
        std::cout << "Dumping StringSet: ";
        for (iterator it = data.begin(); it != data.end(); ++it) {
            if (it != data.begin())
                std::cout << ',';
            std::cout << *it;
        }
        std::cout << std::endl;
    }

    void add(std::string const &x) {
        data.insert(x);
    }

    void delete_(std::string const &x) {
        if (!data.erase(x))
            throw flusspferd::exception("No such element");
    }

    flusspferd::array to_array() {
        flusspferd::root_array result(flusspferd::create<flusspferd::array>());

        for (iterator it = data.begin(); it != data.end(); ++it) {
            result.push(*it);
        }

        return result;
    }

private:
    container data;
};

void print(flusspferd::string const &x) {
    std::cout << x << std::endl;
}

int main() {
    flusspferd::current_context_scope context_scope(
        flusspferd::context::create());

    flusspferd::create<flusspferd::function>("print", &print, _container = flusspferd::global());

    flusspferd::load_class<StringSet>();

    flusspferd::evaluate(
        "var set = new StringSet('b', 'a', 'd');\n"
        "set.add('c');\n"
        "set.dump();\n"
        "set.delete('a'); set.delete('b');\n"
        "print('As Array: ' +  set.toArray().toSource());\n"
    );
}
<|endoftext|>


<commit_before>//===--- TargetInfo.cpp - Information about Target machine ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements the TargetInfo and TargetInfoImpl interfaces.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/AST/Builtins.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
using namespace clang;

// TargetInfo Constructor.
TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
  // Set defaults.  These should be overridden by concrete targets as needed.
  CharIsSigned = true;
  WCharWidth = WCharAlign = 32;
  FloatFormat = &llvm::APFloat::IEEEsingle;
  DoubleFormat = &llvm::APFloat::IEEEdouble;
  LongDoubleFormat = &llvm::APFloat::IEEEdouble;
}

// Out of line virtual dtor for TargetInfo.
TargetInfo::~TargetInfo() {}

//===----------------------------------------------------------------------===//

static void removeGCCRegisterPrefix(const char *&Name) {
  if (Name[0] == '%' || Name[0] == '#')
    Name++;
}

/// isValidGCCRegisterName - Returns whether the passed in string
/// is a valid register name according to GCC. This is used by Sema for
/// inline asm statements.
bool TargetInfo::isValidGCCRegisterName(const char *Name) const {
  const char * const *Names;
  unsigned NumNames;

  // Get rid of any register prefix.
  removeGCCRegisterPrefix(Name);

  if (strcmp(Name, "memory") == 0 ||
      strcmp(Name, "cc") == 0)
    return true;

  getGCCRegNames(Names, NumNames);

  // If we have a number it maps to an entry in the register name array.
  if (isdigit(Name[0])) {
    char *End;
    int n = (int)strtol(Name, &End, 0);
    if (*End == 0)
      return n >= 0 && (unsigned)n < NumNames;
  }

  // Check register names.
  for (unsigned i = 0; i < NumNames; i++) {
    if (strcmp(Name, Names[i]) == 0)
      return true;
  }

  // Now check aliases.
  const GCCRegAlias *Aliases;
  unsigned NumAliases;

  getGCCRegAliases(Aliases, NumAliases);
  for (unsigned i = 0; i < NumAliases; i++) {
    for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
      if (!Aliases[i].Aliases[j])
        break;
      if (strcmp(Aliases[i].Aliases[j], Name) == 0)
        return true;
    }
  }

  return false;
}

const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const {
  assert(isValidGCCRegisterName(Name) && "Invalid register passed in");

  removeGCCRegisterPrefix(Name);

  const char * const *Names;
  unsigned NumNames;

  getGCCRegNames(Names, NumNames);

  // First, check if we have a number.
  if (isdigit(Name[0])) {
    char *End;
    int n = (int)strtol(Name, &End, 0);
    if (*End == 0) {
      assert(n >= 0 && (unsigned)n < NumNames &&
             "Out of bounds register number!");
      return Names[n];
    }
  }

  // Now check aliases.
  const GCCRegAlias *Aliases;
  unsigned NumAliases;

  getGCCRegAliases(Aliases, NumAliases);
  for (unsigned i = 0; i < NumAliases; i++) {
    for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
      if (!Aliases[i].Aliases[j])
        break;
      if (strcmp(Aliases[i].Aliases[j], Name) == 0)
        return Aliases[i].Register;
    }
  }

  return Name;
}

bool TargetInfo::validateOutputConstraint(const char *Name,
                                          ConstraintInfo &info) const
{
  // An output constraint must start with '=' or '+'
  if (*Name != '=' && *Name != '+')
    return false;

  if (*Name == '+')
    info = CI_ReadWrite;
  else
    info = CI_None;

  Name++;
  while (*Name) {
    switch (*Name) {
    default:
      if (!validateAsmConstraint(*Name, info)) {
        // FIXME: This assert is in place temporarily
        // so we can add more constraints as we hit it.
        // Eventually, an unknown constraint should just be treated as 'g'.
        assert(0 && "Unknown output constraint type!");
      }
    case '&': // early clobber.
      break;
    case 'r': // general register.
      info = (ConstraintInfo)(info|CI_AllowsRegister);
      break;
    case 'm': // memory operand.
      info = (ConstraintInfo)(info|CI_AllowsMemory);
      break;
    case 'g': // general register, memory operand or immediate integer.
      info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
      break;
    }

    Name++;
  }

  return true;
}

bool TargetInfo::validateInputConstraint(const char *Name,
                                         unsigned NumOutputs,
                                         ConstraintInfo &info) const {
  while (*Name) {
    switch (*Name) {
    default:
      // Check if we have a matching constraint
      if (*Name >= '0' && *Name <= '9') {
        unsigned i = *Name - '0';

        // Check if matching constraint is out of bounds.
        if (i >= NumOutputs)
          return false;
      } else if (!validateAsmConstraint(*Name, info)) {
        // FIXME: This assert is in place temporarily
        // so we can add more constraints as we hit it.
        // Eventually, an unknown constraint should just be treated as 'g'.
        assert(0 && "Unknown input constraint type!");
      }
    case '%': // commutative
      // FIXME: Fail if % is used with the last operand.
      break;
    case 'i': // immediate integer.
    case 'I':
      break;
    case 'r': // general register.
      info = (ConstraintInfo)(info|CI_AllowsRegister);
      break;
    case 'm': // memory operand.
      info = (ConstraintInfo)(info|CI_AllowsMemory);
      break;
    case 'g': // general register, memory operand or immediate integer.
      info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
      break;
    }

    Name++;
  }

  return true;
}
<commit_msg>Handle the 'n' constraint<commit_after>//===--- TargetInfo.cpp - Information about Target machine ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements the TargetInfo and TargetInfoImpl interfaces.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/AST/Builtins.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
using namespace clang;

// TargetInfo Constructor.
TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
  // Set defaults.  These should be overridden by concrete targets as needed.
  CharIsSigned = true;
  WCharWidth = WCharAlign = 32;
  FloatFormat = &llvm::APFloat::IEEEsingle;
  DoubleFormat = &llvm::APFloat::IEEEdouble;
  LongDoubleFormat = &llvm::APFloat::IEEEdouble;
}

// Out of line virtual dtor for TargetInfo.
TargetInfo::~TargetInfo() {}

//===----------------------------------------------------------------------===//

static void removeGCCRegisterPrefix(const char *&Name) {
  if (Name[0] == '%' || Name[0] == '#')
    Name++;
}

/// isValidGCCRegisterName - Returns whether the passed in string
/// is a valid register name according to GCC. This is used by Sema for
/// inline asm statements.
bool TargetInfo::isValidGCCRegisterName(const char *Name) const {
  const char * const *Names;
  unsigned NumNames;

  // Get rid of any register prefix.
  removeGCCRegisterPrefix(Name);

  if (strcmp(Name, "memory") == 0 ||
      strcmp(Name, "cc") == 0)
    return true;

  getGCCRegNames(Names, NumNames);

  // If we have a number it maps to an entry in the register name array.
  if (isdigit(Name[0])) {
    char *End;
    int n = (int)strtol(Name, &End, 0);
    if (*End == 0)
      return n >= 0 && (unsigned)n < NumNames;
  }

  // Check register names.
  for (unsigned i = 0; i < NumNames; i++) {
    if (strcmp(Name, Names[i]) == 0)
      return true;
  }

  // Now check aliases.
  const GCCRegAlias *Aliases;
  unsigned NumAliases;

  getGCCRegAliases(Aliases, NumAliases);
  for (unsigned i = 0; i < NumAliases; i++) {
    for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
      if (!Aliases[i].Aliases[j])
        break;
      if (strcmp(Aliases[i].Aliases[j], Name) == 0)
        return true;
    }
  }

  return false;
}

const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const {
  assert(isValidGCCRegisterName(Name) && "Invalid register passed in");

  removeGCCRegisterPrefix(Name);

  const char * const *Names;
  unsigned NumNames;

  getGCCRegNames(Names, NumNames);

  // First, check if we have a number.
  if (isdigit(Name[0])) {
    char *End;
    int n = (int)strtol(Name, &End, 0);
    if (*End == 0) {
      assert(n >= 0 && (unsigned)n < NumNames &&
             "Out of bounds register number!");
      return Names[n];
    }
  }

  // Now check aliases.
  const GCCRegAlias *Aliases;
  unsigned NumAliases;

  getGCCRegAliases(Aliases, NumAliases);
  for (unsigned i = 0; i < NumAliases; i++) {
    for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
      if (!Aliases[i].Aliases[j])
        break;
      if (strcmp(Aliases[i].Aliases[j], Name) == 0)
        return Aliases[i].Register;
    }
  }

  return Name;
}

bool TargetInfo::validateOutputConstraint(const char *Name,
                                          ConstraintInfo &info) const
{
  // An output constraint must start with '=' or '+'
  if (*Name != '=' && *Name != '+')
    return false;

  if (*Name == '+')
    info = CI_ReadWrite;
  else
    info = CI_None;

  Name++;
  while (*Name) {
    switch (*Name) {
    default:
      if (!validateAsmConstraint(*Name, info)) {
        // FIXME: This assert is in place temporarily
        // so we can add more constraints as we hit it.
        // Eventually, an unknown constraint should just be treated as 'g'.
        assert(0 && "Unknown output constraint type!");
      }
    case '&': // early clobber.
      break;
    case 'r': // general register.
      info = (ConstraintInfo)(info|CI_AllowsRegister);
      break;
    case 'm': // memory operand.
      info = (ConstraintInfo)(info|CI_AllowsMemory);
      break;
    case 'g': // general register, memory operand or immediate integer.
      info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
      break;
    }

    Name++;
  }

  return true;
}

bool TargetInfo::validateInputConstraint(const char *Name,
                                         unsigned NumOutputs,
                                         ConstraintInfo &info) const {
  while (*Name) {
    switch (*Name) {
    default:
      // Check if we have a matching constraint
      if (*Name >= '0' && *Name <= '9') {
        unsigned i = *Name - '0';

        // Check if matching constraint is out of bounds.
        if (i >= NumOutputs)
          return false;
      } else if (!validateAsmConstraint(*Name, info)) {
        // FIXME: This assert is in place temporarily
        // so we can add more constraints as we hit it.
        // Eventually, an unknown constraint should just be treated as 'g'.
        assert(0 && "Unknown input constraint type!");
      }
    case '%': // commutative
      // FIXME: Fail if % is used with the last operand.
      break;
    case 'i': // immediate integer.
    case 'I':
    case 'n': // immediate integer with a known value.
      break;
    case 'r': // general register.
      info = (ConstraintInfo)(info|CI_AllowsRegister);
      break;
    case 'm': // memory operand.
      info = (ConstraintInfo)(info|CI_AllowsMemory);
      break;
    case 'g': // general register, memory operand or immediate integer.
      info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
      break;
    }

    Name++;
  }

  return true;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fmtcol.hxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: vg $ $Date: 2007-02-05 10:51:35 $
 *
 *  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
 *
 ************************************************************************/
#ifndef _FMTCOL_HXX
#define _FMTCOL_HXX

#ifndef _SVARRAY_HXX //autogen
#include <svtools/svarray.hxx>
#endif

#ifndef INCLUDED_SWDLLAPI_H
#include "swdllapi.h"
#endif
#ifndef _FORMAT_HXX
#include <format.hxx>
#endif
#ifndef _SWTYPES_HXX
#include <swtypes.hxx>      // fuer MAXLEVEL
#endif

class SwDoc;        // fuer friend

class SwFmtColl : public SwFmt
{
protected:
    SwFmtColl( SwAttrPool& rPool, const sal_Char* pFmtName,
                const USHORT* pWhichRanges, SwFmtColl* pDerFrom,
                USHORT nFmtWhich )
          : SwFmt( rPool, pFmtName, pWhichRanges, pDerFrom, nFmtWhich )
    { SetAuto( FALSE ); }

    SwFmtColl( SwAttrPool& rPool, const String &rFmtName,
                const USHORT* pWhichRanges, SwFmtColl* pDerFrom,
                USHORT nFmtWhich )
          : SwFmt( rPool, rFmtName, pWhichRanges, pDerFrom, nFmtWhich )
    { SetAuto( FALSE ); }

private:
    // erstmal wird nicht kopiert und nicht zugewiesen
    SwFmtColl(const SwFmtColl & );
    const SwFmtColl &operator=(const SwFmtColl &);
};

class SW_DLLPUBLIC SwTxtFmtColl: public SwFmtColl
{
    friend class SwDoc;

    SwTxtFmtColl(const SwTxtFmtColl & rRef);

    // --> OD 2007-01-24 #i73790#
    bool mbStayAssignedToListLevelOfOutlineStyle;
    // <--
protected:
    BYTE nOutlineLevel;
    SwTxtFmtColl *pNextTxtFmtColl;

    SwTxtFmtColl( SwAttrPool& rPool, const sal_Char* pFmtCollName,
                    SwTxtFmtColl* pDerFrom = 0,
                    USHORT nFmtWh = RES_TXTFMTCOLL )
        : SwFmtColl( rPool, pFmtCollName, aTxtFmtCollSetRange,
                        pDerFrom, nFmtWh ),
          // --> OD 2007-01-24 #i73790#
          mbStayAssignedToListLevelOfOutlineStyle( false ),
          // <--
          nOutlineLevel( NO_NUMBERING )
    { pNextTxtFmtColl = this; }

    SwTxtFmtColl( SwAttrPool& rPool, const String &rFmtCollName,
                    SwTxtFmtColl* pDerFrom = 0,
                    USHORT nFmtWh = RES_TXTFMTCOLL )
        : SwFmtColl( rPool, rFmtCollName, aTxtFmtCollSetRange,
                        pDerFrom, nFmtWh ),
          // --> OD 2007-01-24 #i73790#
          mbStayAssignedToListLevelOfOutlineStyle( false ),
          // <--
          nOutlineLevel( NO_NUMBERING )
    { pNextTxtFmtColl = this; }

public:

    // zum "abfischen" von UL-/LR-/FontHeight Aenderungen
    virtual void Modify( SfxPoolItem*, SfxPoolItem* );

    TYPEINFO();     //Bereits in Basisklasse Client drin.

    void SetOutlineLevel( BYTE );
    inline BYTE GetOutlineLevel() const { return nOutlineLevel; }

    inline void SetNextTxtFmtColl(SwTxtFmtColl& rNext);
    SwTxtFmtColl& GetNextTxtFmtColl() const { return *pNextTxtFmtColl; }

    BOOL IsAtDocNodeSet() const;

    // --> OD 2006-11-22 #i71574#
    inline const bool AssignedToListLevelOfOutlineStyle() const
    {
        return ( 0 <= GetOutlineLevel() && GetOutlineLevel() < MAXLEVEL );
    }

    inline void DeleteAssignmentToListLevelOfOutlineStyle()
    {
        SetOutlineLevel( NO_NUMBERING );
    }
    // <--

    // --> OD 2007-01-24 #i73790#
    // override <ResetAllFmtAttr()> to stay assigned to list level of outline style
    virtual USHORT ResetAllFmtAttr();

    inline bool StayAssignedToListLevelOfOutlineStyle() const
    {
        return mbStayAssignedToListLevelOfOutlineStyle;
    }
    // <--
/*----------------- JP 09.08.94 17:36 -------------------
 wird die Funktionalitaet von Zeichenvorlagen an Absatzvorlagen
 ueberhaupt benoetigt ??

 Wenn, ja dann muessen im TextNode und hier in der TxtCollection ein 2.
 Attset fuer die Char-Attribute angelegt werden; damit die Vererbung
 und der Zugriff auf die gesetzen Attribute richtig funktioniert!!

    virtual BOOL SetDerivedFrom( SwFmtColl* pDerFrom = 0 );

    inline SwCharFmt* GetCharFmt() const;
    inline BOOL IsCharFmtSet() const;
    void SetCharFmt(SwCharFmt *);
    void ResetCharFmt();
inline BOOL SwTxtFmtColl::IsCharFmtSet() const
{
    return aCharDepend.GetRegisteredIn() ? TRUE : FALSE;
}
inline SwCharFmt* SwTxtFmtColl::GetCharFmt() const
{
    return (SwCharFmt*)aCharDepend.GetRegisteredIn();
}
--------------------------------------------------*/
};

typedef SwTxtFmtColl* SwTxtFmtCollPtr;
SV_DECL_PTRARR(SwTxtFmtColls,SwTxtFmtCollPtr,2,4)

class SwGrfFmtColl: public SwFmtColl
{
    friend class SwDoc;
protected:
    SwGrfFmtColl( SwAttrPool& rPool, const sal_Char* pFmtCollName,
                    SwGrfFmtColl* pDerFrom = 0 )
        : SwFmtColl( rPool, pFmtCollName, aGrfFmtCollSetRange,
                    pDerFrom, RES_GRFFMTCOLL )
    {}

    SwGrfFmtColl( SwAttrPool& rPool, const String &rFmtCollName,
                    SwGrfFmtColl* pDerFrom = 0 )
        : SwFmtColl( rPool, rFmtCollName, aGrfFmtCollSetRange,
                    pDerFrom, RES_GRFFMTCOLL )
    {}

public:
    TYPEINFO();     //Bereits in Basisklasse Client drin.
};

typedef SwGrfFmtColl* SwGrfFmtCollPtr;
SV_DECL_PTRARR(SwGrfFmtColls,SwGrfFmtCollPtr,2,4)

//FEATURE::CONDCOLL
// --------- Bedingte Vorlagen -------------------------------

enum Master_CollConditions
{
    PARA_IN_LIST        = 0x0001,
    PARA_IN_OUTLINE     = 0x0002,
    PARA_IN_FRAME       = 0x0004,
    PARA_IN_TABLEHEAD   = 0x0008,
    PARA_IN_TABLEBODY   = 0x0010,
    PARA_IN_SECTION     = 0x0020,
    PARA_IN_FOOTENOTE   = 0x0040,
    PARA_IN_FOOTER      = 0x0080,
    PARA_IN_HEADER      = 0x0100,
    PARA_IN_ENDNOTE     = 0x0200,
    // ...
    USRFLD_EXPRESSION   = (int)0x8000
};

class SW_DLLPUBLIC SwCollCondition : public SwClient
{
    ULONG nCondition;
    union
    {
        ULONG nSubCondition;
        String* pFldExpression;
    } aSubCondition;

public:
    TYPEINFO();     //Bereits in Basisklasse Client drin.

    SwCollCondition( SwTxtFmtColl* pColl, ULONG nMasterCond,
                    ULONG nSubCond = 0 );
    SwCollCondition( SwTxtFmtColl* pColl, ULONG nMasterCond,
                    const String& rSubExp );
    virtual ~SwCollCondition();

    // @@@ public copy ctor, but no copy assignment?
    SwCollCondition( const SwCollCondition& rCpy );
private:
    // @@@ public copy ctor, but no copy assignment?
    SwCollCondition & operator= (const SwCollCondition &);
public:

    int operator==( const SwCollCondition& rCmp ) const;
    int operator!=( const SwCollCondition& rCmp ) const
                            { return ! (*this == rCmp); }

    ULONG GetCondition() const      { return nCondition; }
    ULONG GetSubCondition() const   { return aSubCondition.nSubCondition; }
    const String* GetFldExpression() const
                                    { return aSubCondition.pFldExpression; }

    void SetCondition( ULONG nCond, ULONG nSubCond );
    SwTxtFmtColl* GetTxtFmtColl() const     { return (SwTxtFmtColl*)GetRegisteredIn(); }
};

typedef SwCollCondition* SwCollConditionPtr;
SV_DECL_PTRARR_DEL( SwFmtCollConditions, SwCollConditionPtr, 0, 5 )

class SW_DLLPUBLIC SwConditionTxtFmtColl : public SwTxtFmtColl
{
    friend class SwDoc;
protected:
    SwFmtCollConditions aCondColls;

    SwConditionTxtFmtColl( SwAttrPool& rPool, const sal_Char* pFmtCollName,
                            SwTxtFmtColl* pDerFrom = 0 )
        : SwTxtFmtColl( rPool, pFmtCollName, pDerFrom, RES_CONDTXTFMTCOLL )
    {}
    SwConditionTxtFmtColl( SwAttrPool& rPool, const String &rFmtCollName,
                            SwTxtFmtColl* pDerFrom = 0 )
        : SwTxtFmtColl( rPool, rFmtCollName, pDerFrom, RES_CONDTXTFMTCOLL )
    {}

public:
    TYPEINFO();     //Bereits in Basisklasse Client drin.

    virtual ~SwConditionTxtFmtColl();

    // zum "abfischen" von Aenderungen
//  virtual void Modify( SfxPoolItem*, SfxPoolItem* );

    const SwCollCondition* HasCondition( const SwCollCondition& rCond ) const;
    const SwFmtCollConditions& GetCondColls() const     { return aCondColls; }
    void InsertCondition( const SwCollCondition& rCond );
    BOOL RemoveCondition( const SwCollCondition& rCond );

    void SetConditions( const SwFmtCollConditions& );
};

//FEATURE::CONDCOLL

// ------------- Inline Implementierungen --------------------

inline void SwTxtFmtColl::SetNextTxtFmtColl( SwTxtFmtColl& rNext )
{
    pNextTxtFmtColl = &rNext;
}
#endif

<commit_msg>INTEGRATION: CWS swwarnings (1.9.16); FILE MERGED 2007/02/27 13:06:33 tl 1.9.16.1: #i69287# warning-free code<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fmtcol.hxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: hr $ $Date: 2007-09-27 08:02:45 $
 *
 *  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
 *
 ************************************************************************/
#ifndef _FMTCOL_HXX
#define _FMTCOL_HXX

#ifndef _SVARRAY_HXX //autogen
#include <svtools/svarray.hxx>
#endif

#ifndef INCLUDED_SWDLLAPI_H
#include "swdllapi.h"
#endif
#ifndef _FORMAT_HXX
#include <format.hxx>
#endif
#ifndef _SWTYPES_HXX
#include <swtypes.hxx>      // fuer MAXLEVEL
#endif

class SwDoc;        // fuer friend

class SwFmtColl : public SwFmt
{
protected:
    SwFmtColl( SwAttrPool& rPool, const sal_Char* pFmtName,
                const USHORT* pWhichRanges, SwFmtColl* pDerFrom,
                USHORT nFmtWhich )
          : SwFmt( rPool, pFmtName, pWhichRanges, pDerFrom, nFmtWhich )
    { SetAuto( FALSE ); }

    SwFmtColl( SwAttrPool& rPool, const String &rFmtName,
                const USHORT* pWhichRanges, SwFmtColl* pDerFrom,
                USHORT nFmtWhich )
          : SwFmt( rPool, rFmtName, pWhichRanges, pDerFrom, nFmtWhich )
    { SetAuto( FALSE ); }

private:
    // erstmal wird nicht kopiert und nicht zugewiesen
    SwFmtColl(const SwFmtColl & );
    const SwFmtColl &operator=(const SwFmtColl &);
};

class SW_DLLPUBLIC SwTxtFmtColl: public SwFmtColl
{
    friend class SwDoc;

    SwTxtFmtColl(const SwTxtFmtColl & rRef);

    // --> OD 2007-01-24 #i73790#
    bool mbStayAssignedToListLevelOfOutlineStyle;
    // <--
protected:
    BYTE nOutlineLevel;
    SwTxtFmtColl *pNextTxtFmtColl;

    SwTxtFmtColl( SwAttrPool& rPool, const sal_Char* pFmtCollName,
                    SwTxtFmtColl* pDerFrom = 0,
                    USHORT nFmtWh = RES_TXTFMTCOLL )
        : SwFmtColl( rPool, pFmtCollName, aTxtFmtCollSetRange,
                        pDerFrom, nFmtWh ),
          // --> OD 2007-01-24 #i73790#
          mbStayAssignedToListLevelOfOutlineStyle( false ),
          // <--
          nOutlineLevel( NO_NUMBERING )
    { pNextTxtFmtColl = this; }

    SwTxtFmtColl( SwAttrPool& rPool, const String &rFmtCollName,
                    SwTxtFmtColl* pDerFrom = 0,
                    USHORT nFmtWh = RES_TXTFMTCOLL )
        : SwFmtColl( rPool, rFmtCollName, aTxtFmtCollSetRange,
                        pDerFrom, nFmtWh ),
          // --> OD 2007-01-24 #i73790#
          mbStayAssignedToListLevelOfOutlineStyle( false ),
          // <--
          nOutlineLevel( NO_NUMBERING )
    { pNextTxtFmtColl = this; }

public:

    // zum "abfischen" von UL-/LR-/FontHeight Aenderungen
    virtual void Modify( SfxPoolItem*, SfxPoolItem* );

    TYPEINFO();     //Bereits in Basisklasse Client drin.

    void SetOutlineLevel( BYTE );
    inline BYTE GetOutlineLevel() const { return nOutlineLevel; }

    inline void SetNextTxtFmtColl(SwTxtFmtColl& rNext);
    SwTxtFmtColl& GetNextTxtFmtColl() const { return *pNextTxtFmtColl; }

    BOOL IsAtDocNodeSet() const;

    // --> OD 2006-11-22 #i71574#
    inline const bool AssignedToListLevelOfOutlineStyle() const
    {
        return ( /*0 <= GetOutlineLevel() &&*/ GetOutlineLevel() < MAXLEVEL );
    }

    inline void DeleteAssignmentToListLevelOfOutlineStyle()
    {
        SetOutlineLevel( NO_NUMBERING );
    }
    // <--

    // --> OD 2007-01-24 #i73790#
    // override <ResetAllFmtAttr()> to stay assigned to list level of outline style
    virtual USHORT ResetAllFmtAttr();

    inline bool StayAssignedToListLevelOfOutlineStyle() const
    {
        return mbStayAssignedToListLevelOfOutlineStyle;
    }
    // <--
/*----------------- JP 09.08.94 17:36 -------------------
 wird die Funktionalitaet von Zeichenvorlagen an Absatzvorlagen
 ueberhaupt benoetigt ??

 Wenn, ja dann muessen im TextNode und hier in der TxtCollection ein 2.
 Attset fuer die Char-Attribute angelegt werden; damit die Vererbung
 und der Zugriff auf die gesetzen Attribute richtig funktioniert!!

    virtual BOOL SetDerivedFrom( SwFmtColl* pDerFrom = 0 );

    inline SwCharFmt* GetCharFmt() const;
    inline BOOL IsCharFmtSet() const;
    void SetCharFmt(SwCharFmt *);
    void ResetCharFmt();
inline BOOL SwTxtFmtColl::IsCharFmtSet() const
{
    return aCharDepend.GetRegisteredIn() ? TRUE : FALSE;
}
inline SwCharFmt* SwTxtFmtColl::GetCharFmt() const
{
    return (SwCharFmt*)aCharDepend.GetRegisteredIn();
}
--------------------------------------------------*/
};

typedef SwTxtFmtColl* SwTxtFmtCollPtr;
SV_DECL_PTRARR(SwTxtFmtColls,SwTxtFmtCollPtr,2,4)

class SwGrfFmtColl: public SwFmtColl
{
    friend class SwDoc;
protected:
    SwGrfFmtColl( SwAttrPool& rPool, const sal_Char* pFmtCollName,
                    SwGrfFmtColl* pDerFrom = 0 )
        : SwFmtColl( rPool, pFmtCollName, aGrfFmtCollSetRange,
                    pDerFrom, RES_GRFFMTCOLL )
    {}

    SwGrfFmtColl( SwAttrPool& rPool, const String &rFmtCollName,
                    SwGrfFmtColl* pDerFrom = 0 )
        : SwFmtColl( rPool, rFmtCollName, aGrfFmtCollSetRange,
                    pDerFrom, RES_GRFFMTCOLL )
    {}

public:
    TYPEINFO();     //Bereits in Basisklasse Client drin.
};

typedef SwGrfFmtColl* SwGrfFmtCollPtr;
SV_DECL_PTRARR(SwGrfFmtColls,SwGrfFmtCollPtr,2,4)

//FEATURE::CONDCOLL
// --------- Bedingte Vorlagen -------------------------------

enum Master_CollConditions
{
    PARA_IN_LIST        = 0x0001,
    PARA_IN_OUTLINE     = 0x0002,
    PARA_IN_FRAME       = 0x0004,
    PARA_IN_TABLEHEAD   = 0x0008,
    PARA_IN_TABLEBODY   = 0x0010,
    PARA_IN_SECTION     = 0x0020,
    PARA_IN_FOOTENOTE   = 0x0040,
    PARA_IN_FOOTER      = 0x0080,
    PARA_IN_HEADER      = 0x0100,
    PARA_IN_ENDNOTE     = 0x0200,
    // ...
    USRFLD_EXPRESSION   = (int)0x8000
};

class SW_DLLPUBLIC SwCollCondition : public SwClient
{
    ULONG nCondition;
    union
    {
        ULONG nSubCondition;
        String* pFldExpression;
    } aSubCondition;

public:
    TYPEINFO();     //Bereits in Basisklasse Client drin.

    SwCollCondition( SwTxtFmtColl* pColl, ULONG nMasterCond,
                    ULONG nSubCond = 0 );
    SwCollCondition( SwTxtFmtColl* pColl, ULONG nMasterCond,
                    const String& rSubExp );
    virtual ~SwCollCondition();

    // @@@ public copy ctor, but no copy assignment?
    SwCollCondition( const SwCollCondition& rCpy );
private:
    // @@@ public copy ctor, but no copy assignment?
    SwCollCondition & operator= (const SwCollCondition &);
public:

    int operator==( const SwCollCondition& rCmp ) const;
    int operator!=( const SwCollCondition& rCmp ) const
                            { return ! (*this == rCmp); }

    ULONG GetCondition() const      { return nCondition; }
    ULONG GetSubCondition() const   { return aSubCondition.nSubCondition; }
    const String* GetFldExpression() const
                                    { return aSubCondition.pFldExpression; }

    void SetCondition( ULONG nCond, ULONG nSubCond );
    SwTxtFmtColl* GetTxtFmtColl() const     { return (SwTxtFmtColl*)GetRegisteredIn(); }
};

typedef SwCollCondition* SwCollConditionPtr;
SV_DECL_PTRARR_DEL( SwFmtCollConditions, SwCollConditionPtr, 0, 5 )

class SW_DLLPUBLIC SwConditionTxtFmtColl : public SwTxtFmtColl
{
    friend class SwDoc;
protected:
    SwFmtCollConditions aCondColls;

    SwConditionTxtFmtColl( SwAttrPool& rPool, const sal_Char* pFmtCollName,
                            SwTxtFmtColl* pDerFrom = 0 )
        : SwTxtFmtColl( rPool, pFmtCollName, pDerFrom, RES_CONDTXTFMTCOLL )
    {}
    SwConditionTxtFmtColl( SwAttrPool& rPool, const String &rFmtCollName,
                            SwTxtFmtColl* pDerFrom = 0 )
        : SwTxtFmtColl( rPool, rFmtCollName, pDerFrom, RES_CONDTXTFMTCOLL )
    {}

public:
    TYPEINFO();     //Bereits in Basisklasse Client drin.

    virtual ~SwConditionTxtFmtColl();

    // zum "abfischen" von Aenderungen
//  virtual void Modify( SfxPoolItem*, SfxPoolItem* );

    const SwCollCondition* HasCondition( const SwCollCondition& rCond ) const;
    const SwFmtCollConditions& GetCondColls() const     { return aCondColls; }
    void InsertCondition( const SwCollCondition& rCond );
    BOOL RemoveCondition( const SwCollCondition& rCond );

    void SetConditions( const SwFmtCollConditions& );
};

//FEATURE::CONDCOLL

// ------------- Inline Implementierungen --------------------

inline void SwTxtFmtColl::SetNextTxtFmtColl( SwTxtFmtColl& rNext )
{
    pNextTxtFmtColl = &rNext;
}
#endif

<|endoftext|>


<commit_before><commit_msg>Ajout de la préparation du kernel (buffer des infos).<commit_after><|endoftext|>