<commit_before>#pragma sw require header pub.egorpugin.primitives.tools.embedder-master
#pragma sw require header org.sw.demo.lexxmark.winflexbison.bison-master

void configure(Solution &s)
{
    s.Settings.Native.LibrariesType = LibraryType::Static;
    s.Settings.Native.ConfigurationType = ConfigurationType::ReleaseWithDebugInformation;
}

void build(Solution &s)
{
    auto &p = s.addProject("cppan", "master");
    p += Git("https://github.com/cppan/cppan", "", "v1");

    auto &common = p.addTarget<StaticLibraryTarget>("common");
    common.CPPVersion = CPPLanguageStandard::CPP17;
    common +=
        "src/common/.*"_rr,
        "src/printers/.*"_rr,
        "src/comments/.*"_rr,
        "src/bazel/.*"_rr,
        "src/inserts/.*"_rr,
        "src/support/.*"_rr,
        "src/gen/.*"_rr;

    common -= "src/bazel/test/test.cpp", "src/gen/.*"_rr;
    common.Public += "src"_id, "src/common"_id, "src/support"_id;

    common.Public += "VERSION_MAJOR=0"_d;
    common.Public += "VERSION_MINOR=2"_d;
    common.Public += "VERSION_PATCH=5"_d;
    common.Public += "BUILD_NUMBER=0"_d;
    common.Public += "CPPAN_VERSION_STRING=0.2.5"_d;
    if (s.Settings.TargetOS.Type == OSType::Windows)
        common.Public += "UNICODE"_d;

    common.Public +=
        "org.sw.demo.boost.optional-1"_dep,
        "org.sw.demo.boost.property_tree-1"_dep,
        "org.sw.demo.boost.variant-1"_dep,
        "org.sw.demo.boost.stacktrace-1"_dep,
        //"org.sw.demo.apolukhin.stacktrace-master"_dep,
        "org.sw.demo.sqlite3-3"_dep,
        "org.sw.demo.fmt-*"_dep,
        "org.sw.demo.imageworks.pystring-1"_dep,
        "org.sw.demo.giovannidicanio.winreg-master"_dep,

        "pub.egorpugin.primitives.string-master"_dep,
        "pub.egorpugin.primitives.filesystem-master"_dep,
        "pub.egorpugin.primitives.context-master"_dep,
        "pub.egorpugin.primitives.date_time-master"_dep,
        "pub.egorpugin.primitives.executor-master"_dep,
        "pub.egorpugin.primitives.hash-master"_dep,
        "pub.egorpugin.primitives.http-master"_dep,
        "pub.egorpugin.primitives.lock-master"_dep,
        "pub.egorpugin.primitives.log-master"_dep,
        "pub.egorpugin.primitives.pack-master"_dep,
        "pub.egorpugin.primitives.patch-master"_dep,
        "pub.egorpugin.primitives.command-master"_dep,
        "pub.egorpugin.primitives.win32helpers-master"_dep,
        "pub.egorpugin.primitives.yaml-master"_dep;

    time_t v;
    time(&v);
    common.fileWriteSafe("stamp.h.in", "\"" + std::to_string(v) + "\"", true);
    embed(common, "src/inserts/inserts.cpp.in");

    // at the moment flex&bison generated files are present in the build tree,
    // so build passes without generation stage

    /*auto flex_bison = [&common](const std::string &name)
    {
        fs::create_directories(common.BinaryDir / ("src/" + name));

        // flex/bison
        {
            auto c = std::make_shared<Command>();
            c->program = "bison.exe";
            c->args.push_back("-d");
            c->args.push_back("-o" + (common.BinaryDir / ("src/" + name + "/grammar.cpp")).string());
            c->args.push_back((common.SourceDir / ("src/" + name + "/grammar.yy")).string());
            c->addInput(common.SourceDir / ("src/" + name + "/grammar.yy"));
            c->addOutput(common.BinaryDir / ("src/" + name + "/grammar.cpp"));
            common += path(common.BinaryDir / ("src/" + name + "/grammar.cpp"));
        }
        {
            auto c = std::make_shared<Command>();
            c->program = "flex.exe";
            c->args.push_back("--header-file=" + (common.BinaryDir / ("src/" + name + "/lexer.h")).string());
            c->args.push_back("-o" + (common.BinaryDir / ("src/" + name + "/lexer.cpp")).string());
            c->args.push_back((common.SourceDir / ("src/" + name + "/lexer.ll")).string());
            c->addInput(common.SourceDir / ("src/" + name + "/lexer.ll"));
            c->addOutput(common.BinaryDir / ("src/" + name + "/lexer.h"));
            c->addOutput(common.BinaryDir / ("src/" + name + "/lexer.cpp"));
            common += path(common.BinaryDir / ("src/" + name + "/lexer.cpp"));
        }
    };*/

    //flex_bison("bazel");
    //flex_bison("comments");

    auto &client = p.addTarget<ExecutableTarget>("client");
    client.CPPVersion = CPPLanguageStandard::CPP17;
    client += "src/client/.*"_rr, common,
        "pub.egorpugin.primitives.sw.main-master"_dep,
        "org.sw.demo.boost.program_options-1"_dep,
        "org.sw.demo.yhirose.cpp_linenoise-master"_dep;
}
<commit_msg>Fix sw build.<commit_after>#pragma sw require header pub.egorpugin.primitives.tools.embedder-master
//#pragma sw require header org.sw.demo.lexxmark.winflexbison.bison-master

void configure(Solution &s)
{
    s.Settings.Native.LibrariesType = LibraryType::Static;
    s.Settings.Native.ConfigurationType = ConfigurationType::ReleaseWithDebugInformation;
}

void build(Solution &s)
{
    auto &p = s.addProject("cppan", "master");
    p += Git("https://github.com/cppan/cppan", "", "v1");

    auto &common = p.addTarget<StaticLibraryTarget>("common");
    common.CPPVersion = CPPLanguageStandard::CPP17;
    common +=
        "src/common/.*"_rr,
        "src/printers/.*"_rr,
        "src/comments/.*"_rr,
        "src/bazel/.*"_rr,
        "src/inserts/.*"_rr,
        "src/support/.*"_rr,
        "src/gen/.*"_rr;

    common -= "src/bazel/test/test.cpp", "src/gen/.*"_rr;
    common.Public += "src"_id, "src/common"_id, "src/support"_id;

    common.Public += "VERSION_MAJOR=0"_d;
    common.Public += "VERSION_MINOR=2"_d;
    common.Public += "VERSION_PATCH=5"_d;
    common.Public += "BUILD_NUMBER=0"_d;
    common.Public += "CPPAN_VERSION_STRING=0.2.5"_d;
    if (s.Settings.TargetOS.Type == OSType::Windows)
        common.Public += "UNICODE"_d;

    common.Public +=
        "org.sw.demo.boost.optional-1"_dep,
        "org.sw.demo.boost.property_tree-1"_dep,
        "org.sw.demo.boost.variant-1"_dep,
        "org.sw.demo.boost.stacktrace-1"_dep,
        //"org.sw.demo.apolukhin.stacktrace-master"_dep,
        "org.sw.demo.sqlite3-3"_dep,
        "org.sw.demo.fmt-*"_dep,
        "org.sw.demo.imageworks.pystring-1"_dep,
        "org.sw.demo.giovannidicanio.winreg-master"_dep,

        "pub.egorpugin.primitives.string-master"_dep,
        "pub.egorpugin.primitives.filesystem-master"_dep,
        "pub.egorpugin.primitives.context-master"_dep,
        "pub.egorpugin.primitives.date_time-master"_dep,
        "pub.egorpugin.primitives.executor-master"_dep,
        "pub.egorpugin.primitives.hash-master"_dep,
        "pub.egorpugin.primitives.http-master"_dep,
        "pub.egorpugin.primitives.lock-master"_dep,
        "pub.egorpugin.primitives.log-master"_dep,
        "pub.egorpugin.primitives.pack-master"_dep,
        "pub.egorpugin.primitives.patch-master"_dep,
        "pub.egorpugin.primitives.command-master"_dep,
        "pub.egorpugin.primitives.win32helpers-master"_dep,
        "pub.egorpugin.primitives.yaml-master"_dep;

    time_t v;
    time(&v);
    common.writeFileSafe("stamp.h.in", "\"" + std::to_string(v) + "\"");
    embed("pub.egorpugin.primitives.tools.embedder-master"_dep, common, "src/inserts/inserts.cpp.in");

    // at the moment flex&bison generated files are present in the build tree,
    // so build passes without generation stage

    /*auto flex_bison = [&common](const std::string &name)
    {
        fs::create_directories(common.BinaryDir / ("src/" + name));

        // flex/bison
        {
            auto c = std::make_shared<Command>();
            c->program = "bison.exe";
            c->args.push_back("-d");
            c->args.push_back("-o" + (common.BinaryDir / ("src/" + name + "/grammar.cpp")).string());
            c->args.push_back((common.SourceDir / ("src/" + name + "/grammar.yy")).string());
            c->addInput(common.SourceDir / ("src/" + name + "/grammar.yy"));
            c->addOutput(common.BinaryDir / ("src/" + name + "/grammar.cpp"));
            common += path(common.BinaryDir / ("src/" + name + "/grammar.cpp"));
        }
        {
            auto c = std::make_shared<Command>();
            c->program = "flex.exe";
            c->args.push_back("--header-file=" + (common.BinaryDir / ("src/" + name + "/lexer.h")).string());
            c->args.push_back("-o" + (common.BinaryDir / ("src/" + name + "/lexer.cpp")).string());
            c->args.push_back((common.SourceDir / ("src/" + name + "/lexer.ll")).string());
            c->addInput(common.SourceDir / ("src/" + name + "/lexer.ll"));
            c->addOutput(common.BinaryDir / ("src/" + name + "/lexer.h"));
            c->addOutput(common.BinaryDir / ("src/" + name + "/lexer.cpp"));
            common += path(common.BinaryDir / ("src/" + name + "/lexer.cpp"));
        }
    };*/

    //flex_bison("bazel");
    //flex_bison("comments");

    auto &client = p.addTarget<ExecutableTarget>("client");
    client.CPPVersion = CPPLanguageStandard::CPP17;
    client += "src/client/.*"_rr, common,
        "pub.egorpugin.primitives.sw.main-master"_dep,
        "org.sw.demo.boost.program_options-1"_dep,
        "org.sw.demo.yhirose.cpp_linenoise-master"_dep;
}
<|endoftext|>


<commit_before>/* -*-Mode: c++;-*-
   Copyright (c) 2003-2008 John Plevyak, All Rights Reserved
*/
#include "ifadefs.h"
#include "ast.h"
#include "if1.h"
#include "fa.h"
#include "builtin.h"

cchar *type_kind_string[] = {
  "NONE", "UNKNOWN", "SUM", "RECORD", "VECTOR", "FUN", "REF", "ENUM", "PRIMITIVE", "APPLICATION", "VARIABLE", "ALIAS"};

BasicSym::BasicSym(void) :
  name(NULL),
  in(NULL),
  type(NULL),
  aspect(NULL),
  must_specialize(NULL),
  must_implement(NULL),
  ast(NULL),
  var(NULL),
  asymbol(NULL),
  nesting_depth(0),
  cg_string(NULL),
  llvm_value(NULL),
  is_builtin(0),
  is_read_only(0),
  is_constant(0),
  is_lvalue(0),
  is_local(0),
  is_default_arg(0),
  is_exact_match(0),
  is_module(0),
  is_fun(0),
  is_symbol(0),
  is_pattern(0),
  is_rest(0),
  is_generic(0),
  is_external(0),
  is_this(0),
  is_fake(0),
  intent(0),
  is_meta_type(0),
  is_unique_type(0),
  is_value_type(0),
  is_system_type(0),
  is_union_type(0),
  is_structure(0),
  is_vector(0),
  fun_returns_value(0),
  live(0),
  type_kind(0),
  num_kind(0),
  num_index(0),
  clone_for_constants(0),
  dispatch_types_built(0),
  type_live(0)
{}

Sym::Sym() :
  constant(NULL),
  size(0),
  alignment(0),
  scope(NULL),
  labelmap(NULL),
  fun(NULL),
  code(NULL),
  self(NULL),
  ret(NULL),
  cont(NULL),
  instantiates(NULL),
  match_type(NULL),
  abstract_type(NULL),
  alias(NULL),
  init(NULL),
  meta_type(NULL),
#ifdef CONSTANT_TYPES
  constant_type(NULL),
#endif
  element(NULL),
  temp(NULL),
  llvm_type(NULL)
{}

cchar *
Sym::pathname() {
  cchar *p = 0;
  if (asymbol)
    p = asymbol->pathname();
  if (!p && ast)
    p = ast->pathname();
  if (p)
    return p;
  return "<unknown>";
}

cchar *
Sym::has_name(int i) {
  if (i < has_names.n)
    return has_names[i];
  return 0;
}

cchar *
Sym::filename() {
  cchar *fn = pathname();
  cchar *r = strrchr(fn, '/');
  if (r) return r+1; else return fn;
}

int
Sym::line() {
  int l = 0;
  if (asymbol)
    l = asymbol->line();
  if (!l && ast)
    l = ast->line();
  return l;
}

int
Sym::source_line() {
  int l = 0;
  if (asymbol)
    l = asymbol->source_line();
  if (!l && ast)
    l = ast->source_line();
  return l;
}

void
Sym::copy_values(Sym *s) {
  int temp_id = id;
  *this = *s;
  id = temp_id;
}

Sym *
Sym::clone() {
  if (asymbol)
    return asymbol->clone();
  Sym *new_sym = copy();
  return new_sym;
}

Sym *
Sym::copy() {
  Sym *s = new_Sym();
  s->copy_values(this);
  if (s->element)
    s->element = s->element->copy();
  return s;
}

int
compar_syms(const void *ai, const void *aj) {
  uint32 i = (*(Sym**)ai)->id;
  uint32 j = (*(Sym**)aj)->id;
  return (i > j) ? 1 : ((i < j) ? -1 : 0);
}

int
Sym::imm_int(int *result) {
  int i = 0;
  switch (type->num_kind) {
    default: return -1;
    case IF1_NUM_KIND_UINT: {
      switch (type->num_index) {
        case IF1_INT_TYPE_8:  i = imm.v_uint8; break;
        case IF1_INT_TYPE_16: i = imm.v_uint16; break;
        case IF1_INT_TYPE_32: i = imm.v_uint32; break;
        case IF1_INT_TYPE_64: i = imm.v_uint64; break;
        default: return -1;
      }
      break;
    }
    case IF1_NUM_KIND_INT: {
      switch (type->num_index) {
        case IF1_INT_TYPE_8:  i = imm.v_int8; break;
        case IF1_INT_TYPE_16: i = imm.v_int16; break;
        case IF1_INT_TYPE_32: i = imm.v_int32; break;
        case IF1_INT_TYPE_64: i = imm.v_int64; break;
        default: return -1;
      }
      break;
    }
  }
  *result = i;
  return 0;
}

Sym *
unalias_type(Sym *s) {
  if (!s)
    return s;
  if (s->type_kind == Type_ALIAS) {
    Vec<Sym *> aliases;
    do {
      if (!s->alias)
        return 0;
      Sym *ss = s->alias;
      if (aliases.set_in(ss))
        fail("circular type alias");
      aliases.set_add(ss);
      s = ss;
    } while (s->type_kind == Type_ALIAS);
  }
  return s;
}

void
if1_set_int_type(IF1 *p, Sym *t, int signd, int size) {
  int ss = 0;
  size >>= 3;
  while (size) { ss++; size >>= 1; }
  p->int_types[ss][signd] = t;
  t->num_kind = signd ? IF1_NUM_KIND_INT : IF1_NUM_KIND_UINT;
  t->num_index = ss;
}

void
if1_set_float_type(IF1 *p, Sym *t, int size) {
  int ss = 0;
  size >>= 4;
  ss = size - 1;
  p->float_types[ss] = t;
  t->num_kind = IF1_NUM_KIND_FLOAT;
  t->num_index = ss;
}

void
if1_set_complex_type(IF1 *p, Sym *t, int size) {
  int ss = 0;
  size >>= 4;
  ss = size - 1;
  p->complex_types[ss] = t;
  t->num_kind = IF1_NUM_KIND_COMPLEX;
  t->num_index = ss;
}

int
if1_numeric_size(IF1 *p, Sym *t) {
  switch (t->num_kind) {
    case IF1_NUM_KIND_NONE: assert(!"bad case"); break;
    case IF1_NUM_KIND_INT:
    case IF1_NUM_KIND_UINT:
      if (!t->num_index) return sizeof(bool);
      return 1 << ((t->num_index ? t->num_index : 1) - 1);
    case IF1_NUM_KIND_FLOAT:
      return 2 + (2 * t->num_index);
    case IF1_NUM_KIND_COMPLEX:
      return 2 * (2 + (2 * t->num_index));
  }
  return 0;
}

#define MAKE_ALIGNOF(_t) \
struct AlignOf##_t {      \
  char a;                \
  _t b;                  \
}

#define ALIGNOF(_t) ((int)(intptr_t)&(((struct AlignOf##_t *)0)->b))

MAKE_ALIGNOF(bool);
MAKE_ALIGNOF(uint8);
MAKE_ALIGNOF(uint16);
MAKE_ALIGNOF(uint32);
MAKE_ALIGNOF(uint64);
MAKE_ALIGNOF(float32);
MAKE_ALIGNOF(float64);
MAKE_ALIGNOF(float128);
MAKE_ALIGNOF(complex32);
MAKE_ALIGNOF(complex64);
typedef char *alignstring;
MAKE_ALIGNOF(alignstring);

int
if1_numeric_alignment(IF1 *p, Sym *t) {
  int res = -1;
  switch (t->num_kind) {
    default: assert(!"case"); break;
    case IF1_NUM_KIND_UINT:
    case IF1_NUM_KIND_INT:
      switch (t->num_index) {
        case IF1_INT_TYPE_1: return ALIGNOF(bool); break;
        case IF1_INT_TYPE_8: return ALIGNOF(uint8); break;
        case IF1_INT_TYPE_16: return ALIGNOF(uint16); break;
        case IF1_INT_TYPE_32: return ALIGNOF(uint32); break;
        case IF1_INT_TYPE_64: return ALIGNOF(uint64); break;
        default: assert(!"case");
      }
      break;
    case IF1_NUM_KIND_FLOAT:
      switch (t->num_index) {
        case IF1_FLOAT_TYPE_32:  return ALIGNOF(float32);
        case IF1_FLOAT_TYPE_64:  return ALIGNOF(float64);
        case IF1_FLOAT_TYPE_128: return ALIGNOF(float128);
        default: assert(!"case");
      }
      break;
    case IF1_NUM_KIND_COMPLEX:
      switch (t->num_index) {
        case IF1_FLOAT_TYPE_32: return ALIGNOF(complex32);
        case IF1_FLOAT_TYPE_64: return ALIGNOF(complex64);
        default: assert(!"case");
      }
      break;
    case IF1_CONST_KIND_STRING: return ALIGNOF(alignstring);
  }
  return res;
}

void
Sym::inherits_add(Sym *s) {
  implements.add(s);
  specializes.add(s);
  includes.add(s);
}

void
Sym::must_implement_and_specialize(Sym *s) {
  assert((!must_implement || must_implement == s) &&
         (!must_specialize || must_specialize == s));
  must_implement = s;
  must_specialize = s;
}

Sym *
Sym::scalar_type() {
  if (type && type->num_kind)
    return type;
  return 0;
}

Sym *
Sym::coerce_to(Sym *to) {
  if (this == to)
    return this;
  Sym *s1 = this->scalar_type(), *s2 = to->scalar_type();
  if (s1 && s2) {
    Sym *t = coerce_num(s1, s2);
    if (t == s2)
      return s2;
    return NULL;
  }
  if (element) {
    Sym *s1 = element->scalar_type(), *s2 = to->scalar_type();
    if (s1 && s2) {
      Sym *t = coerce_num(s1, s2);
      if (t == s2)
        return s2;
      return NULL;
    }
  }
  if (s1) {
    if (to == sym_string)
      return to;
  }
  return NULL;
}

void
Sym::convert_constant_string_to_immediate() {
  if (!is_constant)
    return;
  imm.const_kind = type->num_kind;
  imm.num_index = type->num_index;
  convert_string_to_immediate(constant, &imm);
}

static Sym *
int_constant_internal(IF1 *i, int n, Sym *t) {
  Immediate imm;
  imm.v_int32 = n;
  if (n >= 0 && n < 10) {
    char c[2];
    c[0] = n + '0';
    c[1] = 0;
    return if1_const(i, t, c, &imm);
  } else {
    char str[100];
    sprintf(str, "%d", n);
    return if1_const(i, t, str, &imm);
  }
}

Sym *
int32_constant(int n) {
  return int_constant_internal(if1, n, sym_int32);
}

Sym *
size_constant(int n) {
  return int_constant_internal(if1, n, sym_size);
}

Sym *
imm_constant(Immediate &imm, Sym *t) {
  char str[256];
  sprint_imm(str, imm);
  return if1_const(if1, t, str, &imm);
}

void
pp(Sym *s) {
  printf("(SYM %d ", s->id);
  if1_dump_sym(stdout, s);
  printf(")");
}
<commit_msg>interm<commit_after>/* -*-Mode: c++;-*-
   Copyright (c) 2003-2008 John Plevyak, All Rights Reserved
*/
#include "ifadefs.h"
#include "ast.h"
#include "if1.h"
#include "fa.h"
#include "builtin.h"

cchar *type_kind_string[] = {
  "NONE", "UNKNOWN", "SUM", "RECORD", "FUN", "REF", "TAGGED", "PRIMITIVE", "APPLICATION", "VARIABLE", "ALIAS"};

BasicSym::BasicSym(void) :
  name(NULL),
  in(NULL),
  type(NULL),
  aspect(NULL),
  must_specialize(NULL),
  must_implement(NULL),
  ast(NULL),
  var(NULL),
  asymbol(NULL),
  nesting_depth(0),
  cg_string(NULL),
  llvm_value(NULL),
  is_builtin(0),
  is_read_only(0),
  is_constant(0),
  is_lvalue(0),
  is_local(0),
  is_default_arg(0),
  is_exact_match(0),
  is_module(0),
  is_fun(0),
  is_symbol(0),
  is_pattern(0),
  is_rest(0),
  is_generic(0),
  is_external(0),
  is_this(0),
  is_fake(0),
  intent(0),
  is_meta_type(0),
  is_unique_type(0),
  is_value_type(0),
  is_system_type(0),
  is_union_type(0),
  is_structure(0),
  is_vector(0),
  fun_returns_value(0),
  live(0),
  type_kind(0),
  num_kind(0),
  num_index(0),
  clone_for_constants(0),
  dispatch_types_built(0),
  type_live(0)
{}

Sym::Sym() :
  constant(NULL),
  size(0),
  alignment(0),
  scope(NULL),
  labelmap(NULL),
  fun(NULL),
  code(NULL),
  self(NULL),
  ret(NULL),
  cont(NULL),
  instantiates(NULL),
  match_type(NULL),
  abstract_type(NULL),
  alias(NULL),
  init(NULL),
  meta_type(NULL),
#ifdef CONSTANT_TYPES
  constant_type(NULL),
#endif
  element(NULL),
  temp(NULL),
  llvm_type(NULL)
{}

cchar *
Sym::pathname() {
  cchar *p = 0;
  if (asymbol)
    p = asymbol->pathname();
  if (!p && ast)
    p = ast->pathname();
  if (p)
    return p;
  return "<unknown>";
}

cchar *
Sym::has_name(int i) {
  if (i < has_names.n)
    return has_names[i];
  return 0;
}

cchar *
Sym::filename() {
  cchar *fn = pathname();
  cchar *r = strrchr(fn, '/');
  if (r) return r+1; else return fn;
}

int
Sym::line() {
  int l = 0;
  if (asymbol)
    l = asymbol->line();
  if (!l && ast)
    l = ast->line();
  return l;
}

int
Sym::source_line() {
  int l = 0;
  if (asymbol)
    l = asymbol->source_line();
  if (!l && ast)
    l = ast->source_line();
  return l;
}

void
Sym::copy_values(Sym *s) {
  int temp_id = id;
  *this = *s;
  id = temp_id;
}

Sym *
Sym::clone() {
  if (asymbol)
    return asymbol->clone();
  Sym *new_sym = copy();
  return new_sym;
}

Sym *
Sym::copy() {
  Sym *s = new_Sym();
  s->copy_values(this);
  if (s->element)
    s->element = s->element->copy();
  return s;
}

int
compar_syms(const void *ai, const void *aj) {
  uint32 i = (*(Sym**)ai)->id;
  uint32 j = (*(Sym**)aj)->id;
  return (i > j) ? 1 : ((i < j) ? -1 : 0);
}

int
Sym::imm_int(int *result) {
  int i = 0;
  switch (type->num_kind) {
    default: return -1;
    case IF1_NUM_KIND_UINT: {
      switch (type->num_index) {
        case IF1_INT_TYPE_8:  i = imm.v_uint8; break;
        case IF1_INT_TYPE_16: i = imm.v_uint16; break;
        case IF1_INT_TYPE_32: i = imm.v_uint32; break;
        case IF1_INT_TYPE_64: i = imm.v_uint64; break;
        default: return -1;
      }
      break;
    }
    case IF1_NUM_KIND_INT: {
      switch (type->num_index) {
        case IF1_INT_TYPE_8:  i = imm.v_int8; break;
        case IF1_INT_TYPE_16: i = imm.v_int16; break;
        case IF1_INT_TYPE_32: i = imm.v_int32; break;
        case IF1_INT_TYPE_64: i = imm.v_int64; break;
        default: return -1;
      }
      break;
    }
  }
  *result = i;
  return 0;
}

Sym *
unalias_type(Sym *s) {
  if (!s)
    return s;
  if (s->type_kind == Type_ALIAS) {
    Vec<Sym *> aliases;
    do {
      if (!s->alias)
        return 0;
      Sym *ss = s->alias;
      if (aliases.set_in(ss))
        fail("circular type alias");
      aliases.set_add(ss);
      s = ss;
    } while (s->type_kind == Type_ALIAS);
  }
  return s;
}

void
if1_set_int_type(IF1 *p, Sym *t, int signd, int size) {
  int ss = 0;
  size >>= 3;
  while (size) { ss++; size >>= 1; }
  p->int_types[ss][signd] = t;
  t->num_kind = signd ? IF1_NUM_KIND_INT : IF1_NUM_KIND_UINT;
  t->num_index = ss;
}

void
if1_set_float_type(IF1 *p, Sym *t, int size) {
  int ss = 0;
  size >>= 4;
  ss = size - 1;
  p->float_types[ss] = t;
  t->num_kind = IF1_NUM_KIND_FLOAT;
  t->num_index = ss;
}

void
if1_set_complex_type(IF1 *p, Sym *t, int size) {
  int ss = 0;
  size >>= 4;
  ss = size - 1;
  p->complex_types[ss] = t;
  t->num_kind = IF1_NUM_KIND_COMPLEX;
  t->num_index = ss;
}

int
if1_numeric_size(IF1 *p, Sym *t) {
  switch (t->num_kind) {
    case IF1_NUM_KIND_NONE: assert(!"bad case"); break;
    case IF1_NUM_KIND_INT:
    case IF1_NUM_KIND_UINT:
      if (!t->num_index) return sizeof(bool);
      return 1 << ((t->num_index ? t->num_index : 1) - 1);
    case IF1_NUM_KIND_FLOAT:
      return 2 + (2 * t->num_index);
    case IF1_NUM_KIND_COMPLEX:
      return 2 * (2 + (2 * t->num_index));
  }
  return 0;
}

#define MAKE_ALIGNOF(_t) \
struct AlignOf##_t {      \
  char a;                \
  _t b;                  \
}

#define ALIGNOF(_t) ((int)(intptr_t)&(((struct AlignOf##_t *)0)->b))

MAKE_ALIGNOF(bool);
MAKE_ALIGNOF(uint8);
MAKE_ALIGNOF(uint16);
MAKE_ALIGNOF(uint32);
MAKE_ALIGNOF(uint64);
MAKE_ALIGNOF(float32);
MAKE_ALIGNOF(float64);
MAKE_ALIGNOF(float128);
MAKE_ALIGNOF(complex32);
MAKE_ALIGNOF(complex64);
typedef char *alignstring;
MAKE_ALIGNOF(alignstring);

int
if1_numeric_alignment(IF1 *p, Sym *t) {
  int res = -1;
  switch (t->num_kind) {
    default: assert(!"case"); break;
    case IF1_NUM_KIND_UINT:
    case IF1_NUM_KIND_INT:
      switch (t->num_index) {
        case IF1_INT_TYPE_1: return ALIGNOF(bool); break;
        case IF1_INT_TYPE_8: return ALIGNOF(uint8); break;
        case IF1_INT_TYPE_16: return ALIGNOF(uint16); break;
        case IF1_INT_TYPE_32: return ALIGNOF(uint32); break;
        case IF1_INT_TYPE_64: return ALIGNOF(uint64); break;
        default: assert(!"case");
      }
      break;
    case IF1_NUM_KIND_FLOAT:
      switch (t->num_index) {
        case IF1_FLOAT_TYPE_32:  return ALIGNOF(float32);
        case IF1_FLOAT_TYPE_64:  return ALIGNOF(float64);
        case IF1_FLOAT_TYPE_128: return ALIGNOF(float128);
        default: assert(!"case");
      }
      break;
    case IF1_NUM_KIND_COMPLEX:
      switch (t->num_index) {
        case IF1_FLOAT_TYPE_32: return ALIGNOF(complex32);
        case IF1_FLOAT_TYPE_64: return ALIGNOF(complex64);
        default: assert(!"case");
      }
      break;
    case IF1_CONST_KIND_STRING: return ALIGNOF(alignstring);
  }
  return res;
}

void
Sym::inherits_add(Sym *s) {
  implements.add(s);
  specializes.add(s);
  includes.add(s);
}

void
Sym::must_implement_and_specialize(Sym *s) {
  assert((!must_implement || must_implement == s) &&
         (!must_specialize || must_specialize == s));
  must_implement = s;
  must_specialize = s;
}

Sym *
Sym::scalar_type() {
  if (type && type->num_kind)
    return type;
  return 0;
}

Sym *
Sym::coerce_to(Sym *to) {
  if (this == to)
    return this;
  Sym *s1 = this->scalar_type(), *s2 = to->scalar_type();
  if (s1 && s2) {
    Sym *t = coerce_num(s1, s2);
    if (t == s2)
      return s2;
    return NULL;
  }
  if (element) {
    Sym *s1 = element->scalar_type(), *s2 = to->scalar_type();
    if (s1 && s2) {
      Sym *t = coerce_num(s1, s2);
      if (t == s2)
        return s2;
      return NULL;
    }
  }
  if (s1) {
    if (to == sym_string)
      return to;
  }
  return NULL;
}

void
Sym::convert_constant_string_to_immediate() {
  if (!is_constant)
    return;
  imm.const_kind = type->num_kind;
  imm.num_index = type->num_index;
  convert_string_to_immediate(constant, &imm);
}

static Sym *
int_constant_internal(IF1 *i, int n, Sym *t) {
  Immediate imm;
  imm.v_int32 = n;
  if (n >= 0 && n < 10) {
    char c[2];
    c[0] = n + '0';
    c[1] = 0;
    return if1_const(i, t, c, &imm);
  } else {
    char str[100];
    sprintf(str, "%d", n);
    return if1_const(i, t, str, &imm);
  }
}

Sym *
int32_constant(int n) {
  return int_constant_internal(if1, n, sym_int32);
}

Sym *
size_constant(int n) {
  return int_constant_internal(if1, n, sym_size);
}

Sym *
imm_constant(Immediate &imm, Sym *t) {
  char str[256];
  sprint_imm(str, imm);
  return if1_const(if1, t, str, &imm);
}

void
pp(Sym *s) {
  printf("(SYM %d ", s->id);
  if1_dump_sym(stdout, s);
  printf(")");
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/views/touchui/touch_mode_support.h"

#include "ui/base/ui_base_switches.h"
#include "base/command_line.h"

#if defined(OS_WIN)
#include <windows.h>
#endif

// static
bool TouchModeSupport::IsTouchOptimized() {
#if !defined(OS_WIN)
  // TODO(port): there is code in src/ui/base/touch for linux but it is not
  // suitable for consumption here.
  return false;
#else
  // TODO: This may need to be cached and updated only occasionally. There is
  // no direct WM_ message that indicates that a touch panel has been added or
  // removed, however.
  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kTouchOptimizedUI))
    return true;
  // Asking for SM_DIGITIZER always returns 0 in Windows Vista and Windows XP.
  int sm = ::GetSystemMetrics(SM_DIGITIZER);
  return (sm & NID_READY) && (sm & NID_INTEGRATED_TOUCH);
#endif
}
<commit_msg>Only enable touch-friendly tab strip based on command line flag<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/views/touchui/touch_mode_support.h"

#include "ui/base/ui_base_switches.h"
#include "base/command_line.h"

#if defined(OS_WIN)
#include <windows.h>
#endif

// static
bool TouchModeSupport::IsTouchOptimized() {
#if !defined(OS_WIN)
  // TODO(port): there is code in src/ui/base/touch for linux but it is not
  // suitable for consumption here.
  return false;
#else
  // TODO: Enable based on GetSystemMetrics(SM_DIGITIZER) returning NID_READY
  // and NID_INTEGRATED_TOUCH once code is ready.
  return CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kTouchOptimizedUI);
#endif
}
<|endoftext|>


<commit_before>//===- Cloning.cpp - Unit tests for the Cloner ----------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "gtest/gtest.h"

using namespace llvm;

namespace {

class CloneInstruction : public ::testing::Test {
protected:
  virtual void SetUp() {
    V = nullptr;
  }

  template <typename T>
  T *clone(T *V1) {
    Value *V2 = V1->clone();
    Orig.insert(V1);
    Clones.insert(V2);
    return cast<T>(V2);
  }

  void eraseClones() {
    DeleteContainerPointers(Clones);
  }

  virtual void TearDown() {
    eraseClones();
    DeleteContainerPointers(Orig);
    delete V;
  }

  SmallPtrSet<Value *, 4> Orig;   // Erase on exit
  SmallPtrSet<Value *, 4> Clones; // Erase in eraseClones

  LLVMContext context;
  Value *V;
};

TEST_F(CloneInstruction, OverflowBits) {
  V = new Argument(Type::getInt32Ty(context));

  BinaryOperator *Add = BinaryOperator::Create(Instruction::Add, V, V);
  BinaryOperator *Sub = BinaryOperator::Create(Instruction::Sub, V, V);
  BinaryOperator *Mul = BinaryOperator::Create(Instruction::Mul, V, V);

  BinaryOperator *AddClone = this->clone(Add);
  BinaryOperator *SubClone = this->clone(Sub);
  BinaryOperator *MulClone = this->clone(Mul);

  EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
  EXPECT_FALSE(AddClone->hasNoSignedWrap());
  EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
  EXPECT_FALSE(SubClone->hasNoSignedWrap());
  EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
  EXPECT_FALSE(MulClone->hasNoSignedWrap());

  eraseClones();

  Add->setHasNoUnsignedWrap();
  Sub->setHasNoUnsignedWrap();
  Mul->setHasNoUnsignedWrap();

  AddClone = this->clone(Add);
  SubClone = this->clone(Sub);
  MulClone = this->clone(Mul);

  EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
  EXPECT_FALSE(AddClone->hasNoSignedWrap());
  EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
  EXPECT_FALSE(SubClone->hasNoSignedWrap());
  EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
  EXPECT_FALSE(MulClone->hasNoSignedWrap());

  eraseClones();

  Add->setHasNoSignedWrap();
  Sub->setHasNoSignedWrap();
  Mul->setHasNoSignedWrap();

  AddClone = this->clone(Add);
  SubClone = this->clone(Sub);
  MulClone = this->clone(Mul);

  EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
  EXPECT_TRUE(AddClone->hasNoSignedWrap());
  EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
  EXPECT_TRUE(SubClone->hasNoSignedWrap());
  EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
  EXPECT_TRUE(MulClone->hasNoSignedWrap());

  eraseClones();

  Add->setHasNoUnsignedWrap(false);
  Sub->setHasNoUnsignedWrap(false);
  Mul->setHasNoUnsignedWrap(false);

  AddClone = this->clone(Add);
  SubClone = this->clone(Sub);
  MulClone = this->clone(Mul);

  EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
  EXPECT_TRUE(AddClone->hasNoSignedWrap());
  EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
  EXPECT_TRUE(SubClone->hasNoSignedWrap());
  EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
  EXPECT_TRUE(MulClone->hasNoSignedWrap());
}

TEST_F(CloneInstruction, Inbounds) {
  V = new Argument(Type::getInt32PtrTy(context));

  Constant *Z = Constant::getNullValue(Type::getInt32Ty(context));
  std::vector<Value *> ops;
  ops.push_back(Z);
  GetElementPtrInst *GEP =
      GetElementPtrInst::Create(Type::getInt32Ty(context), V, ops);
  EXPECT_FALSE(this->clone(GEP)->isInBounds());

  GEP->setIsInBounds();
  EXPECT_TRUE(this->clone(GEP)->isInBounds());
}

TEST_F(CloneInstruction, Exact) {
  V = new Argument(Type::getInt32Ty(context));

  BinaryOperator *SDiv = BinaryOperator::Create(Instruction::SDiv, V, V);
  EXPECT_FALSE(this->clone(SDiv)->isExact());

  SDiv->setIsExact(true);
  EXPECT_TRUE(this->clone(SDiv)->isExact());
}

TEST_F(CloneInstruction, Attributes) {
  Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
  FunctionType *FT1 =  FunctionType::get(Type::getVoidTy(context), ArgTy1, false);

  Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
  BasicBlock *BB = BasicBlock::Create(context, "", F1);
  IRBuilder<> Builder(BB);
  Builder.CreateRetVoid();

  Function *F2 = Function::Create(FT1, Function::ExternalLinkage);

  Attribute::AttrKind AK[] = { Attribute::NoCapture };
  AttributeSet AS = AttributeSet::get(context, 0, AK);
  Argument *A = F1->arg_begin();
  A->addAttr(AS);

  SmallVector<ReturnInst*, 4> Returns;
  ValueToValueMapTy VMap;
  VMap[A] = UndefValue::get(A->getType());

  CloneFunctionInto(F2, F1, VMap, false, Returns);
  EXPECT_FALSE(F2->arg_begin()->hasNoCaptureAttr());

  delete F1;
  delete F2;
}

TEST_F(CloneInstruction, CallingConvention) {
  Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
  FunctionType *FT1 =  FunctionType::get(Type::getVoidTy(context), ArgTy1, false);

  Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
  F1->setCallingConv(CallingConv::Cold);
  BasicBlock *BB = BasicBlock::Create(context, "", F1);
  IRBuilder<> Builder(BB);
  Builder.CreateRetVoid();

  Function *F2 = Function::Create(FT1, Function::ExternalLinkage);

  SmallVector<ReturnInst*, 4> Returns;
  ValueToValueMapTy VMap;
  VMap[F1->arg_begin()] = F2->arg_begin();

  CloneFunctionInto(F2, F1, VMap, false, Returns);
  EXPECT_EQ(CallingConv::Cold, F2->getCallingConv());

  delete F1;
  delete F2;
}

class CloneFunc : public ::testing::Test {
protected:
  virtual void SetUp() {
    SetupModule();
    CreateOldFunc();
    CreateNewFunc();
    SetupFinder();
  }

  virtual void TearDown() {
    delete Finder;
  }

  void SetupModule() {
    M = new Module("", C);
  }

  void CreateOldFunc() {
    FunctionType* FuncType = FunctionType::get(Type::getVoidTy(C), false);
    OldFunc = Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", M);
    CreateOldFunctionBodyAndDI();
  }

  void CreateOldFunctionBodyAndDI() {
    DIBuilder DBuilder(*M);
    IRBuilder<> IBuilder(C);

    // Function DI
    DIFile File = DBuilder.createFile("filename.c", "/file/dir/");
    DITypeArray ParamTypes = DBuilder.getOrCreateTypeArray(None);
    DICompositeType FuncType = DBuilder.createSubroutineType(File, ParamTypes);
    DICompileUnit CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99,
        "filename.c", "/file/dir", "CloneFunc", false, "", 0);

    DISubprogram Subprogram = DBuilder.createFunction(CU, "f", "f", File, 4,
        FuncType, true, true, 3, 0, false, OldFunc);

    // Function body
    BasicBlock* Entry = BasicBlock::Create(C, "", OldFunc);
    IBuilder.SetInsertPoint(Entry);
    DebugLoc Loc = DebugLoc::get(3, 2, Subprogram);
    IBuilder.SetCurrentDebugLocation(Loc);
    AllocaInst* Alloca = IBuilder.CreateAlloca(IntegerType::getInt32Ty(C));
    IBuilder.SetCurrentDebugLocation(DebugLoc::get(4, 2, Subprogram));
    Value* AllocaContent = IBuilder.getInt32(1);
    Instruction* Store = IBuilder.CreateStore(AllocaContent, Alloca);
    IBuilder.SetCurrentDebugLocation(DebugLoc::get(5, 2, Subprogram));
    Instruction* Terminator = IBuilder.CreateRetVoid();

    // Create a local variable around the alloca
    DIType IntType = DBuilder.createBasicType("int", 32, 0,
        dwarf::DW_ATE_signed);
    DIExpression E = DBuilder.createExpression();
    DIVariable Variable = DBuilder.createLocalVariable(
      dwarf::DW_TAG_auto_variable, Subprogram, "x", File, 5, IntType, true);
    DBuilder.insertDeclare(Alloca, Variable, E, Store);
    DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, E, Terminator);
    // Finalize the debug info
    DBuilder.finalize();

    // Create another, empty, compile unit
    DIBuilder DBuilder2(*M);
    DBuilder2.createCompileUnit(dwarf::DW_LANG_C99,
        "extra.c", "/file/dir", "CloneFunc", false, "", 0);
    DBuilder2.finalize();
  }

  void CreateNewFunc() {
    ValueToValueMapTy VMap;
    NewFunc = CloneFunction(OldFunc, VMap, true, nullptr);
    M->getFunctionList().push_back(NewFunc);
  }

  void SetupFinder() {
    Finder = new DebugInfoFinder();
    Finder->processModule(*M);
  }

  LLVMContext C;
  Function* OldFunc;
  Function* NewFunc;
  Module* M;
  DebugInfoFinder* Finder;
};

// Test that a new, distinct function was created.
TEST_F(CloneFunc, NewFunctionCreated) {
  EXPECT_NE(OldFunc, NewFunc);
}

// Test that a new subprogram entry was added and is pointing to the new
// function, while the original subprogram still points to the old one.
TEST_F(CloneFunc, Subprogram) {
  unsigned SubprogramCount = Finder->subprogram_count();
  EXPECT_EQ(2U, SubprogramCount);

  auto Iter = Finder->subprograms().begin();
  DISubprogram Sub1(*Iter);
  EXPECT_TRUE(Sub1.Verify());
  Iter++;
  DISubprogram Sub2(*Iter);
  EXPECT_TRUE(Sub2.Verify());

  EXPECT_TRUE((Sub1.getFunction() == OldFunc && Sub2.getFunction() == NewFunc)
           || (Sub1.getFunction() == NewFunc && Sub2.getFunction() == OldFunc));
}

// Test that the new subprogram entry was not added to the CU which doesn't
// contain the old subprogram entry.
TEST_F(CloneFunc, SubprogramInRightCU) {
  EXPECT_EQ(2U, Finder->compile_unit_count());

  auto Iter = Finder->compile_units().begin();
  DICompileUnit CU1(*Iter);
  EXPECT_TRUE(CU1.Verify());
  Iter++;
  DICompileUnit CU2(*Iter);
  EXPECT_TRUE(CU2.Verify());
  EXPECT_TRUE(CU1.getSubprograms().getNumElements() == 0
           || CU2.getSubprograms().getNumElements() == 0);
}

// Test that instructions in the old function still belong to it in the
// metadata, while instruction in the new function belong to the new one.
TEST_F(CloneFunc, InstructionOwnership) {
  inst_iterator OldIter = inst_begin(OldFunc);
  inst_iterator OldEnd = inst_end(OldFunc);
  inst_iterator NewIter = inst_begin(NewFunc);
  inst_iterator NewEnd = inst_end(NewFunc);
  while (OldIter != OldEnd && NewIter != NewEnd) {
    Instruction& OldI = *OldIter;
    Instruction& NewI = *NewIter;
    EXPECT_NE(&OldI, &NewI);

    EXPECT_EQ(OldI.hasMetadata(), NewI.hasMetadata());
    if (OldI.hasMetadata()) {
      const DebugLoc& OldDL = OldI.getDebugLoc();
      const DebugLoc& NewDL = NewI.getDebugLoc();

      // Verify that the debug location data is the same
      EXPECT_EQ(OldDL.getLine(), NewDL.getLine());
      EXPECT_EQ(OldDL.getCol(), NewDL.getCol());

      // But that they belong to different functions
      DISubprogram OldSubprogram(OldDL.getScope());
      DISubprogram NewSubprogram(NewDL.getScope());
      EXPECT_TRUE(OldSubprogram.Verify());
      EXPECT_TRUE(NewSubprogram.Verify());
      EXPECT_EQ(OldFunc, OldSubprogram.getFunction());
      EXPECT_EQ(NewFunc, NewSubprogram.getFunction());
    }

    ++OldIter;
    ++NewIter;
  }
  EXPECT_EQ(OldEnd, OldIter);
  EXPECT_EQ(NewEnd, NewIter);
}

// Test that the arguments for debug intrinsics in the new function were
// properly cloned
TEST_F(CloneFunc, DebugIntrinsics) {
  inst_iterator OldIter = inst_begin(OldFunc);
  inst_iterator OldEnd = inst_end(OldFunc);
  inst_iterator NewIter = inst_begin(NewFunc);
  inst_iterator NewEnd = inst_end(NewFunc);
  while (OldIter != OldEnd && NewIter != NewEnd) {
    Instruction& OldI = *OldIter;
    Instruction& NewI = *NewIter;
    if (DbgDeclareInst* OldIntrin = dyn_cast<DbgDeclareInst>(&OldI)) {
      DbgDeclareInst* NewIntrin = dyn_cast<DbgDeclareInst>(&NewI);
      EXPECT_TRUE(NewIntrin);

      // Old address must belong to the old function
      EXPECT_EQ(OldFunc, cast<AllocaInst>(OldIntrin->getAddress())->
                         getParent()->getParent());
      // New address must belong to the new function
      EXPECT_EQ(NewFunc, cast<AllocaInst>(NewIntrin->getAddress())->
                         getParent()->getParent());

      // Old variable must belong to the old function
      EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
                         .getContext()).getFunction());
      // New variable must belong to the New function
      EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
                         .getContext()).getFunction());
    } else if (DbgValueInst* OldIntrin = dyn_cast<DbgValueInst>(&OldI)) {
      DbgValueInst* NewIntrin = dyn_cast<DbgValueInst>(&NewI);
      EXPECT_TRUE(NewIntrin);

      // Old variable must belong to the old function
      EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
                         .getContext()).getFunction());
      // New variable must belong to the New function
      EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
                         .getContext()).getFunction());
    }

    ++OldIter;
    ++NewIter;
  }
}

}
<commit_msg>Transforms: Update unit tests to use verifyModule()<commit_after>//===- Cloning.cpp - Unit tests for the Cloner ----------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "gtest/gtest.h"

using namespace llvm;

namespace {

class CloneInstruction : public ::testing::Test {
protected:
  virtual void SetUp() {
    V = nullptr;
  }

  template <typename T>
  T *clone(T *V1) {
    Value *V2 = V1->clone();
    Orig.insert(V1);
    Clones.insert(V2);
    return cast<T>(V2);
  }

  void eraseClones() {
    DeleteContainerPointers(Clones);
  }

  virtual void TearDown() {
    eraseClones();
    DeleteContainerPointers(Orig);
    delete V;
  }

  SmallPtrSet<Value *, 4> Orig;   // Erase on exit
  SmallPtrSet<Value *, 4> Clones; // Erase in eraseClones

  LLVMContext context;
  Value *V;
};

TEST_F(CloneInstruction, OverflowBits) {
  V = new Argument(Type::getInt32Ty(context));

  BinaryOperator *Add = BinaryOperator::Create(Instruction::Add, V, V);
  BinaryOperator *Sub = BinaryOperator::Create(Instruction::Sub, V, V);
  BinaryOperator *Mul = BinaryOperator::Create(Instruction::Mul, V, V);

  BinaryOperator *AddClone = this->clone(Add);
  BinaryOperator *SubClone = this->clone(Sub);
  BinaryOperator *MulClone = this->clone(Mul);

  EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
  EXPECT_FALSE(AddClone->hasNoSignedWrap());
  EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
  EXPECT_FALSE(SubClone->hasNoSignedWrap());
  EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
  EXPECT_FALSE(MulClone->hasNoSignedWrap());

  eraseClones();

  Add->setHasNoUnsignedWrap();
  Sub->setHasNoUnsignedWrap();
  Mul->setHasNoUnsignedWrap();

  AddClone = this->clone(Add);
  SubClone = this->clone(Sub);
  MulClone = this->clone(Mul);

  EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
  EXPECT_FALSE(AddClone->hasNoSignedWrap());
  EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
  EXPECT_FALSE(SubClone->hasNoSignedWrap());
  EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
  EXPECT_FALSE(MulClone->hasNoSignedWrap());

  eraseClones();

  Add->setHasNoSignedWrap();
  Sub->setHasNoSignedWrap();
  Mul->setHasNoSignedWrap();

  AddClone = this->clone(Add);
  SubClone = this->clone(Sub);
  MulClone = this->clone(Mul);

  EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
  EXPECT_TRUE(AddClone->hasNoSignedWrap());
  EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
  EXPECT_TRUE(SubClone->hasNoSignedWrap());
  EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
  EXPECT_TRUE(MulClone->hasNoSignedWrap());

  eraseClones();

  Add->setHasNoUnsignedWrap(false);
  Sub->setHasNoUnsignedWrap(false);
  Mul->setHasNoUnsignedWrap(false);

  AddClone = this->clone(Add);
  SubClone = this->clone(Sub);
  MulClone = this->clone(Mul);

  EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
  EXPECT_TRUE(AddClone->hasNoSignedWrap());
  EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
  EXPECT_TRUE(SubClone->hasNoSignedWrap());
  EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
  EXPECT_TRUE(MulClone->hasNoSignedWrap());
}

TEST_F(CloneInstruction, Inbounds) {
  V = new Argument(Type::getInt32PtrTy(context));

  Constant *Z = Constant::getNullValue(Type::getInt32Ty(context));
  std::vector<Value *> ops;
  ops.push_back(Z);
  GetElementPtrInst *GEP =
      GetElementPtrInst::Create(Type::getInt32Ty(context), V, ops);
  EXPECT_FALSE(this->clone(GEP)->isInBounds());

  GEP->setIsInBounds();
  EXPECT_TRUE(this->clone(GEP)->isInBounds());
}

TEST_F(CloneInstruction, Exact) {
  V = new Argument(Type::getInt32Ty(context));

  BinaryOperator *SDiv = BinaryOperator::Create(Instruction::SDiv, V, V);
  EXPECT_FALSE(this->clone(SDiv)->isExact());

  SDiv->setIsExact(true);
  EXPECT_TRUE(this->clone(SDiv)->isExact());
}

TEST_F(CloneInstruction, Attributes) {
  Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
  FunctionType *FT1 =  FunctionType::get(Type::getVoidTy(context), ArgTy1, false);

  Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
  BasicBlock *BB = BasicBlock::Create(context, "", F1);
  IRBuilder<> Builder(BB);
  Builder.CreateRetVoid();

  Function *F2 = Function::Create(FT1, Function::ExternalLinkage);

  Attribute::AttrKind AK[] = { Attribute::NoCapture };
  AttributeSet AS = AttributeSet::get(context, 0, AK);
  Argument *A = F1->arg_begin();
  A->addAttr(AS);

  SmallVector<ReturnInst*, 4> Returns;
  ValueToValueMapTy VMap;
  VMap[A] = UndefValue::get(A->getType());

  CloneFunctionInto(F2, F1, VMap, false, Returns);
  EXPECT_FALSE(F2->arg_begin()->hasNoCaptureAttr());

  delete F1;
  delete F2;
}

TEST_F(CloneInstruction, CallingConvention) {
  Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
  FunctionType *FT1 =  FunctionType::get(Type::getVoidTy(context), ArgTy1, false);

  Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
  F1->setCallingConv(CallingConv::Cold);
  BasicBlock *BB = BasicBlock::Create(context, "", F1);
  IRBuilder<> Builder(BB);
  Builder.CreateRetVoid();

  Function *F2 = Function::Create(FT1, Function::ExternalLinkage);

  SmallVector<ReturnInst*, 4> Returns;
  ValueToValueMapTy VMap;
  VMap[F1->arg_begin()] = F2->arg_begin();

  CloneFunctionInto(F2, F1, VMap, false, Returns);
  EXPECT_EQ(CallingConv::Cold, F2->getCallingConv());

  delete F1;
  delete F2;
}

class CloneFunc : public ::testing::Test {
protected:
  virtual void SetUp() {
    SetupModule();
    CreateOldFunc();
    CreateNewFunc();
    SetupFinder();
  }

  virtual void TearDown() {
    delete Finder;
  }

  void SetupModule() {
    M = new Module("", C);
  }

  void CreateOldFunc() {
    FunctionType* FuncType = FunctionType::get(Type::getVoidTy(C), false);
    OldFunc = Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", M);
    CreateOldFunctionBodyAndDI();
  }

  void CreateOldFunctionBodyAndDI() {
    DIBuilder DBuilder(*M);
    IRBuilder<> IBuilder(C);

    // Function DI
    DIFile File = DBuilder.createFile("filename.c", "/file/dir/");
    DITypeArray ParamTypes = DBuilder.getOrCreateTypeArray(None);
    DICompositeType FuncType = DBuilder.createSubroutineType(File, ParamTypes);
    DICompileUnit CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99,
        "filename.c", "/file/dir", "CloneFunc", false, "", 0);

    DISubprogram Subprogram = DBuilder.createFunction(CU, "f", "f", File, 4,
        FuncType, true, true, 3, 0, false, OldFunc);

    // Function body
    BasicBlock* Entry = BasicBlock::Create(C, "", OldFunc);
    IBuilder.SetInsertPoint(Entry);
    DebugLoc Loc = DebugLoc::get(3, 2, Subprogram);
    IBuilder.SetCurrentDebugLocation(Loc);
    AllocaInst* Alloca = IBuilder.CreateAlloca(IntegerType::getInt32Ty(C));
    IBuilder.SetCurrentDebugLocation(DebugLoc::get(4, 2, Subprogram));
    Value* AllocaContent = IBuilder.getInt32(1);
    Instruction* Store = IBuilder.CreateStore(AllocaContent, Alloca);
    IBuilder.SetCurrentDebugLocation(DebugLoc::get(5, 2, Subprogram));
    Instruction* Terminator = IBuilder.CreateRetVoid();

    // Create a local variable around the alloca
    DIType IntType = DBuilder.createBasicType("int", 32, 0,
        dwarf::DW_ATE_signed);
    DIExpression E = DBuilder.createExpression();
    DIVariable Variable = DBuilder.createLocalVariable(
      dwarf::DW_TAG_auto_variable, Subprogram, "x", File, 5, IntType, true);
    DBuilder.insertDeclare(Alloca, Variable, E, Store);
    DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, E, Terminator);
    // Finalize the debug info
    DBuilder.finalize();

    // Create another, empty, compile unit
    DIBuilder DBuilder2(*M);
    DBuilder2.createCompileUnit(dwarf::DW_LANG_C99,
        "extra.c", "/file/dir", "CloneFunc", false, "", 0);
    DBuilder2.finalize();
  }

  void CreateNewFunc() {
    ValueToValueMapTy VMap;
    NewFunc = CloneFunction(OldFunc, VMap, true, nullptr);
    M->getFunctionList().push_back(NewFunc);
  }

  void SetupFinder() {
    Finder = new DebugInfoFinder();
    Finder->processModule(*M);
  }

  LLVMContext C;
  Function* OldFunc;
  Function* NewFunc;
  Module* M;
  DebugInfoFinder* Finder;
};

// Test that a new, distinct function was created.
TEST_F(CloneFunc, NewFunctionCreated) {
  EXPECT_NE(OldFunc, NewFunc);
}

// Test that a new subprogram entry was added and is pointing to the new
// function, while the original subprogram still points to the old one.
TEST_F(CloneFunc, Subprogram) {
  EXPECT_FALSE(verifyModule(*M));

  unsigned SubprogramCount = Finder->subprogram_count();
  EXPECT_EQ(2U, SubprogramCount);

  auto Iter = Finder->subprograms().begin();
  DISubprogram Sub1(*Iter);
  EXPECT_TRUE(Sub1.isSubprogram());
  Iter++;
  DISubprogram Sub2(*Iter);
  EXPECT_TRUE(Sub2.isSubprogram());

  EXPECT_TRUE((Sub1.getFunction() == OldFunc && Sub2.getFunction() == NewFunc)
           || (Sub1.getFunction() == NewFunc && Sub2.getFunction() == OldFunc));
}

// Test that the new subprogram entry was not added to the CU which doesn't
// contain the old subprogram entry.
TEST_F(CloneFunc, SubprogramInRightCU) {
  EXPECT_FALSE(verifyModule(*M));

  EXPECT_EQ(2U, Finder->compile_unit_count());

  auto Iter = Finder->compile_units().begin();
  DICompileUnit CU1(*Iter);
  EXPECT_TRUE(CU1.isCompileUnit());
  Iter++;
  DICompileUnit CU2(*Iter);
  EXPECT_TRUE(CU2.isCompileUnit());
  EXPECT_TRUE(CU1.getSubprograms().getNumElements() == 0
           || CU2.getSubprograms().getNumElements() == 0);
}

// Test that instructions in the old function still belong to it in the
// metadata, while instruction in the new function belong to the new one.
TEST_F(CloneFunc, InstructionOwnership) {
  EXPECT_FALSE(verifyModule(*M));

  inst_iterator OldIter = inst_begin(OldFunc);
  inst_iterator OldEnd = inst_end(OldFunc);
  inst_iterator NewIter = inst_begin(NewFunc);
  inst_iterator NewEnd = inst_end(NewFunc);
  while (OldIter != OldEnd && NewIter != NewEnd) {
    Instruction& OldI = *OldIter;
    Instruction& NewI = *NewIter;
    EXPECT_NE(&OldI, &NewI);

    EXPECT_EQ(OldI.hasMetadata(), NewI.hasMetadata());
    if (OldI.hasMetadata()) {
      const DebugLoc& OldDL = OldI.getDebugLoc();
      const DebugLoc& NewDL = NewI.getDebugLoc();

      // Verify that the debug location data is the same
      EXPECT_EQ(OldDL.getLine(), NewDL.getLine());
      EXPECT_EQ(OldDL.getCol(), NewDL.getCol());

      // But that they belong to different functions
      DISubprogram OldSubprogram(OldDL.getScope());
      DISubprogram NewSubprogram(NewDL.getScope());
      EXPECT_TRUE(OldSubprogram.isSubprogram());
      EXPECT_TRUE(NewSubprogram.isSubprogram());
      EXPECT_EQ(OldFunc, OldSubprogram.getFunction());
      EXPECT_EQ(NewFunc, NewSubprogram.getFunction());
    }

    ++OldIter;
    ++NewIter;
  }
  EXPECT_EQ(OldEnd, OldIter);
  EXPECT_EQ(NewEnd, NewIter);
}

// Test that the arguments for debug intrinsics in the new function were
// properly cloned
TEST_F(CloneFunc, DebugIntrinsics) {
  EXPECT_FALSE(verifyModule(*M));

  inst_iterator OldIter = inst_begin(OldFunc);
  inst_iterator OldEnd = inst_end(OldFunc);
  inst_iterator NewIter = inst_begin(NewFunc);
  inst_iterator NewEnd = inst_end(NewFunc);
  while (OldIter != OldEnd && NewIter != NewEnd) {
    Instruction& OldI = *OldIter;
    Instruction& NewI = *NewIter;
    if (DbgDeclareInst* OldIntrin = dyn_cast<DbgDeclareInst>(&OldI)) {
      DbgDeclareInst* NewIntrin = dyn_cast<DbgDeclareInst>(&NewI);
      EXPECT_TRUE(NewIntrin);

      // Old address must belong to the old function
      EXPECT_EQ(OldFunc, cast<AllocaInst>(OldIntrin->getAddress())->
                         getParent()->getParent());
      // New address must belong to the new function
      EXPECT_EQ(NewFunc, cast<AllocaInst>(NewIntrin->getAddress())->
                         getParent()->getParent());

      // Old variable must belong to the old function
      EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
                         .getContext()).getFunction());
      // New variable must belong to the New function
      EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
                         .getContext()).getFunction());
    } else if (DbgValueInst* OldIntrin = dyn_cast<DbgValueInst>(&OldI)) {
      DbgValueInst* NewIntrin = dyn_cast<DbgValueInst>(&NewI);
      EXPECT_TRUE(NewIntrin);

      // Old variable must belong to the old function
      EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
                         .getContext()).getFunction());
      // New variable must belong to the New function
      EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
                         .getContext()).getFunction());
    }

    ++OldIter;
    ++NewIter;
  }
}

}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <sal/config.h>

#include <com/sun/star/ucb/UniversalContentBroker.hpp>
#include <comphelper/processfactory.hxx>
#include <unotools/tempfile.hxx>
#include <unotools/localfilehelper.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <ucbhelper/fileidentifierconverter.hxx>
#include <rtl/ustring.hxx>
#include <rtl/instance.hxx>
#include <osl/file.hxx>
#include <tools/time.hxx>
#include <tools/debug.hxx>
#include <stdio.h>

#ifdef UNX
#include <sys/stat.h>
#endif

using namespace osl;

namespace
{
    struct TempNameBase_Impl
        : public rtl::Static< OUString, TempNameBase_Impl > {};
}

namespace utl
{

OUString getParentName( const OUString& aFileName )
{
    sal_Int32 lastIndex = aFileName.lastIndexOf( '/' );
    OUString aParent = aFileName.copy( 0, lastIndex );

    if( aParent.endsWith(":") && aParent.getLength() == 6 )
        aParent += "/";

    if( aParent.equalsAscii( "file://" ) )
        aParent = "file:///";

    return aParent;
}

bool ensuredir( const OUString& rUnqPath )
{
    OUString aPath;
    if ( rUnqPath.isEmpty() )
        return false;

    // remove trailing slash
    if ( rUnqPath.endsWith("/") )
        aPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 );
    else
        aPath = rUnqPath;

    // HACK: create directory on a mount point with nobrowse option
    // returns ENOSYS in any case !!
    osl::Directory aDirectory( aPath );
    osl::FileBase::RC nError = aDirectory.open();
    aDirectory.close();
    if( nError == osl::File::E_None )
        return true;

    // try to create the directory
    nError = osl::Directory::create( aPath );
    bool  bSuccess = ( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST );
    if( !bSuccess )
    {
        // perhaps parent(s) don't exist
        OUString aParentDir = getParentName( aPath );
        if ( aParentDir != aPath )
        {
            bSuccess = ensuredir( getParentName( aPath ) );

            // After parent directory structure exists try it one's more
            if ( bSuccess )
            {
                // Parent directory exists, retry creation of directory
                nError = osl::Directory::create( aPath );
                bSuccess =( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST );
            }
        }
    }

    return bSuccess;
}

OUString ConstructTempDir_Impl( const OUString* pParent )
{
    OUString aName;
    if ( pParent && !pParent->isEmpty() )
    {
        com::sun::star::uno::Reference<
            com::sun::star::ucb::XUniversalContentBroker > pBroker(
                com::sun::star::ucb::UniversalContentBroker::create(
                    comphelper::getProcessComponentContext() ) );

        // if parent given try to use it
        OUString aTmp( *pParent );

        // test for valid filename
        OUString aRet;
        ::osl::FileBase::getFileURLFromSystemPath(
            ::ucbhelper::getSystemPathFromFileURL( pBroker, aTmp ),
            aRet );
        if ( !aRet.isEmpty() )
        {
            ::osl::DirectoryItem aItem;
            sal_Int32 i = aRet.getLength();
            if ( aRet[i-1] == '/' )
                i--;

            if ( DirectoryItem::get( aRet.copy(0, i), aItem ) == FileBase::E_None )
                aName = aRet;
        }
    }

    if ( aName.isEmpty() )
    {
        OUString &rTempNameBase_Impl = TempNameBase_Impl::get();
        if (rTempNameBase_Impl.isEmpty())
        {
            OUString ustrTempDirURL;
            ::osl::FileBase::RC rc = ::osl::File::getTempDirURL(
                ustrTempDirURL );
            if (rc == ::osl::FileBase::E_None)
                rTempNameBase_Impl = ustrTempDirURL;
        }
        // if no parent or invalid parent : use default directory
        DBG_ASSERT( !rTempNameBase_Impl.isEmpty(), "No TempDir!" );
        aName = rTempNameBase_Impl;
        ensuredir( aName );
    }

    // Make sure that directory ends with a separator
    if( !aName.isEmpty() && !aName.endsWith("/") )
        aName += "/";

    return aName;
}

OUString lcl_createName(
    const OUString& rLeadingChars, unsigned long nSeed, sal_Int16 nRadix,
    bool bFirst, const OUString* pExtension, const OUString* pParent,
    bool bDirectory, bool bKeep, bool bLock)
{
    // 36 ** 6 == 2176782336
    unsigned long const nMaxRadix = 36;
    unsigned long const nMax = (nMaxRadix*nMaxRadix*nMaxRadix*nMaxRadix*nMaxRadix*nMaxRadix);
    nSeed %= nMax;

    // get correct directory
    OUString aName = ConstructTempDir_Impl( pParent );

    bool bUseNumber = bFirst;
    // now use special naming scheme ( name takes leading chars and an index counting up from zero
    aName += rLeadingChars;
    for ( unsigned long i=nSeed;; )
    {
        OUString aTmp( aName );
        if ( bUseNumber )
            aTmp += OUString::number(i, nRadix);
        bUseNumber = true;
        if ( pExtension )
            aTmp += *pExtension;
        else
            aTmp += ".tmp";
        if ( bDirectory )
        {
            FileBase::RC err = Directory::create( aTmp );
            if ( err == FileBase::E_None )
            {
                // !bKeep: only for creating a name, not a file or directory
                if ( bKeep || Directory::remove( aTmp ) == FileBase::E_None )
                    return aTmp;
                else
                    return OUString();
            }
            else if ( err != FileBase::E_EXIST )
                // if f.e. name contains invalid chars stop trying to create dirs
                return OUString();
        }
        else
        {
            DBG_ASSERT( bKeep, "Too expensive, use directory for creating name!" );
            File aFile( aTmp );
#ifdef UNX
            /* RW permission for the user only! */
            mode_t old_mode = umask(077);
#endif
            FileBase::RC err = aFile.open(osl_File_OpenFlag_Create | (bLock ? 0 : osl_File_OpenFlag_NoLock));
#ifdef UNX
            umask(old_mode);
#endif
            if ( err == FileBase::E_None || (bLock && err == FileBase::E_NOLCK) )
            {
                aFile.close();
                return aTmp;
            }
            else if ( err != FileBase::E_EXIST )
            {
                // if f.e. name contains invalid chars stop trying to create dirs
                // but if there is a folder with such name proceed further

                DirectoryItem aTmpItem;
                FileStatus aTmpStatus( osl_FileStatus_Mask_Type );
                if ( DirectoryItem::get( aTmp, aTmpItem ) != FileBase::E_None
                  || aTmpItem.getFileStatus( aTmpStatus ) != FileBase::E_None
                  || aTmpStatus.getFileType() != FileStatus::Directory )
                    return OUString();
            }
        }
        i = (i + 1) % nMax;
        if (i == nSeed) {
            return OUString();
        }
    }
}

OUString lcl_createName_BROKEN(
    const OUString& rLeadingChars, sal_Int16 nRadix,
    bool bFirst, const OUString* pExtension, const OUString* pParent,
    bool bDirectory, bool bKeep, bool bLock)
{
    // 36 ** 6 == 2176782336
    unsigned long const nMaxRadix = 36;
    unsigned long const nMax = (nMaxRadix*nMaxRadix*nMaxRadix*nMaxRadix*nMaxRadix*nMaxRadix);
    static unsigned long nSeed = Time::GetSystemTicks() % nMax;

    // get correct directory
    OUString aName = ConstructTempDir_Impl( pParent );

    bool bUseNumber = bFirst;
    // now use special naming scheme ( name takes leading chars and an index counting up from zero
    aName += rLeadingChars;
    for ( unsigned long i=nSeed;; )
    {
        OUString aTmp( aName );
        if ( bUseNumber )
            aTmp += OUString::number(nSeed, nRadix);
        bUseNumber = true;
        if ( pExtension )
            aTmp += *pExtension;
        else
            aTmp += ".tmp";
        if ( bDirectory )
        {
            FileBase::RC err = Directory::create( aTmp );
            if ( err == FileBase::E_None )
            {
                // !bKeep: only for creating a name, not a file or directory
                if ( bKeep || Directory::remove( aTmp ) == FileBase::E_None )
                    return aTmp;
                else
                    return OUString();
            }
            else if ( err != FileBase::E_EXIST )
                // if f.e. name contains invalid chars stop trying to create dirs
                return OUString();
        }
        else
        {
            DBG_ASSERT( bKeep, "Too expensive, use directory for creating name!" );
            File aFile( aTmp );
#ifdef UNX
            /* RW permission for the user only! */
            mode_t old_mode = umask(077);
#endif
            FileBase::RC err = aFile.open(osl_File_OpenFlag_Create | (bLock ? 0 : osl_File_OpenFlag_NoLock));
#ifdef UNX
            umask(old_mode);
#endif
            if ( err == FileBase::E_None || (bLock && err == FileBase::E_NOLCK) )
            {
                aFile.close();
                return aTmp;
            }
            else if ( err != FileBase::E_EXIST )
            {
                // if f.e. name contains invalid chars stop trying to create dirs
                // but if there is a folder with such name proceed further

                DirectoryItem aTmpItem;
                FileStatus aTmpStatus( osl_FileStatus_Mask_Type );
                if ( DirectoryItem::get( aTmp, aTmpItem ) != FileBase::E_None
                  || aTmpItem.getFileStatus( aTmpStatus ) != FileBase::E_None
                  || aTmpStatus.getFileType() != FileStatus::Directory )
                    return OUString();
            }
        }
        nSeed = (nSeed + 1) % nMax;
        if (i == nSeed) {
            return OUString();
        }
    }
}

OUString CreateTempName_Impl( const OUString* pParent, bool bKeep, bool bDir = true )
{
    OUString aEyeCatcher = "lu";
#ifdef DBG_UTIL
#ifdef UNX
    const char* eye = getenv("LO_TESTNAME");
    if(eye)
    {
        aEyeCatcher = OUString(eye, strlen(eye), RTL_TEXTENCODING_ASCII_US);
    }
#endif
#endif
    return lcl_createName_BROKEN(
        aEyeCatcher, 36, true, 0, pParent, bDir, bKeep,
        false);
}

OUString TempFile::CreateTempName()
{
    OUString aName(CreateTempName_Impl( 0, false ));

    // convert to file URL
    OUString aTmp;
    if ( !aName.isEmpty() )
        FileBase::getSystemPathFromFileURL( aName, aTmp );
    return aTmp;
}

TempFile::TempFile( const OUString* pParent, bool bDirectory )
    : pStream( 0 )
    , bIsDirectory( bDirectory )
    , bKillingFileEnabled( false )
{
    aName = CreateTempName_Impl( pParent, true, bDirectory );
}

TempFile::TempFile( const OUString& rLeadingChars, bool _bStartWithZero, const OUString* pExtension, const OUString* pParent, bool bDirectory)
    : pStream( 0 )
    , bIsDirectory( bDirectory )
    , bKillingFileEnabled( false )
{
    aName = lcl_createName(rLeadingChars, 0, 10, _bStartWithZero, pExtension, pParent, bDirectory, true, true);
}

TempFile::~TempFile()
{
    delete pStream;
    if ( bKillingFileEnabled )
    {
        if ( bIsDirectory )
        {
            // at the moment no recursiv algorithm present
            Directory::remove( aName );
        }
        else
        {
            File::remove( aName );
        }
    }
}

bool TempFile::IsValid() const
{
    return !aName.isEmpty();
}

OUString TempFile::GetFileName() const
{
    OUString aTmp;
    FileBase::getSystemPathFromFileURL( aName, aTmp );
    return aTmp;
}

OUString TempFile::GetURL()
{
    if ( aURL.isEmpty() )
    {
        OUString aTmp;
        LocalFileHelper::ConvertPhysicalNameToURL( GetFileName(), aTmp );
        aURL = aTmp;
    }

    return aURL;
}

SvStream* TempFile::GetStream( StreamMode eMode )
{
    if ( !pStream )
    {
        if ( !GetURL().isEmpty() )
            pStream = UcbStreamHelper::CreateStream( aURL, eMode, true /* bFileExists */ );
        else
            pStream = new SvMemoryStream( eMode );
    }

    return pStream;
}

void TempFile::CloseStream()
{
    if ( pStream )
    {
        delete pStream;
        pStream = NULL;
    }
}

OUString TempFile::SetTempNameBaseDirectory( const OUString &rBaseName )
{
    if( rBaseName.isEmpty() )
        return OUString();

    OUString aUnqPath( rBaseName );

    // remove trailing slash
    if ( rBaseName.endsWith("/") )
        aUnqPath = rBaseName.copy( 0, rBaseName.getLength() - 1 );

    // try to create the directory
    bool bRet = false;
    osl::FileBase::RC err = osl::Directory::create( aUnqPath );
    if ( err != FileBase::E_None && err != FileBase::E_EXIST )
        // perhaps parent(s) don't exist
        bRet = ensuredir( aUnqPath );
    else
        bRet = true;

    // failure to create base directory means returning an empty string
    OUString aTmp;
    if ( bRet )
    {
        // append own internal directory
        bRet = true;
        OUString &rTempNameBase_Impl = TempNameBase_Impl::get();
        rTempNameBase_Impl = rBaseName;
        rTempNameBase_Impl += OUString('/');

        TempFile aBase( NULL, true );
        if ( aBase.IsValid() )
            // use it in case of success
            rTempNameBase_Impl = aBase.aName;

        // return system path of used directory
        FileBase::getSystemPathFromFileURL( rTempNameBase_Impl, aTmp );
    }

    return aTmp;
}
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Abstract over Tokens algorithm<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <sal/config.h>

#include <cassert>

#include <com/sun/star/ucb/UniversalContentBroker.hpp>
#include <comphelper/processfactory.hxx>
#include <unotools/tempfile.hxx>
#include <unotools/localfilehelper.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <ucbhelper/fileidentifierconverter.hxx>
#include <rtl/ustring.hxx>
#include <rtl/instance.hxx>
#include <osl/file.hxx>
#include <tools/time.hxx>
#include <tools/debug.hxx>
#include <stdio.h>

#ifdef UNX
#include <sys/stat.h>
#endif

using namespace osl;

namespace
{
    struct TempNameBase_Impl
        : public rtl::Static< OUString, TempNameBase_Impl > {};
}

namespace utl
{

OUString getParentName( const OUString& aFileName )
{
    sal_Int32 lastIndex = aFileName.lastIndexOf( '/' );
    OUString aParent = aFileName.copy( 0, lastIndex );

    if( aParent.endsWith(":") && aParent.getLength() == 6 )
        aParent += "/";

    if( aParent.equalsAscii( "file://" ) )
        aParent = "file:///";

    return aParent;
}

bool ensuredir( const OUString& rUnqPath )
{
    OUString aPath;
    if ( rUnqPath.isEmpty() )
        return false;

    // remove trailing slash
    if ( rUnqPath.endsWith("/") )
        aPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 );
    else
        aPath = rUnqPath;

    // HACK: create directory on a mount point with nobrowse option
    // returns ENOSYS in any case !!
    osl::Directory aDirectory( aPath );
    osl::FileBase::RC nError = aDirectory.open();
    aDirectory.close();
    if( nError == osl::File::E_None )
        return true;

    // try to create the directory
    nError = osl::Directory::create( aPath );
    bool  bSuccess = ( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST );
    if( !bSuccess )
    {
        // perhaps parent(s) don't exist
        OUString aParentDir = getParentName( aPath );
        if ( aParentDir != aPath )
        {
            bSuccess = ensuredir( getParentName( aPath ) );

            // After parent directory structure exists try it one's more
            if ( bSuccess )
            {
                // Parent directory exists, retry creation of directory
                nError = osl::Directory::create( aPath );
                bSuccess =( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST );
            }
        }
    }

    return bSuccess;
}

OUString ConstructTempDir_Impl( const OUString* pParent )
{
    OUString aName;
    if ( pParent && !pParent->isEmpty() )
    {
        com::sun::star::uno::Reference<
            com::sun::star::ucb::XUniversalContentBroker > pBroker(
                com::sun::star::ucb::UniversalContentBroker::create(
                    comphelper::getProcessComponentContext() ) );

        // if parent given try to use it
        OUString aTmp( *pParent );

        // test for valid filename
        OUString aRet;
        ::osl::FileBase::getFileURLFromSystemPath(
            ::ucbhelper::getSystemPathFromFileURL( pBroker, aTmp ),
            aRet );
        if ( !aRet.isEmpty() )
        {
            ::osl::DirectoryItem aItem;
            sal_Int32 i = aRet.getLength();
            if ( aRet[i-1] == '/' )
                i--;

            if ( DirectoryItem::get( aRet.copy(0, i), aItem ) == FileBase::E_None )
                aName = aRet;
        }
    }

    if ( aName.isEmpty() )
    {
        OUString &rTempNameBase_Impl = TempNameBase_Impl::get();
        if (rTempNameBase_Impl.isEmpty())
        {
            OUString ustrTempDirURL;
            ::osl::FileBase::RC rc = ::osl::File::getTempDirURL(
                ustrTempDirURL );
            if (rc == ::osl::FileBase::E_None)
                rTempNameBase_Impl = ustrTempDirURL;
        }
        // if no parent or invalid parent : use default directory
        DBG_ASSERT( !rTempNameBase_Impl.isEmpty(), "No TempDir!" );
        aName = rTempNameBase_Impl;
        ensuredir( aName );
    }

    // Make sure that directory ends with a separator
    if( !aName.isEmpty() && !aName.endsWith("/") )
        aName += "/";

    return aName;
}

class Tokens {
public:
    virtual bool next(OUString *) = 0;

protected:
    virtual ~Tokens() {} // avoid warnings
};

class SequentialTokens: public Tokens {
public:
    explicit SequentialTokens(bool showZero): m_value(0), m_show(showZero) {}

    bool next(OUString * token) SAL_OVERRIDE {
        assert(token != 0);
        if (m_value == SAL_MAX_UINT32) {
            return false;
        }
        *token = m_show ? OUString::number(m_value) : OUString();
        ++m_value;
        m_show = true;
        return true;
    }

private:
    sal_uInt32 m_value;
    bool m_show;
};

class UniqueTokens: public Tokens {
public:
    UniqueTokens(): m_count(0) {}

    bool next(OUString * token) SAL_OVERRIDE {
        assert(token != 0);
        // Because of the shared globalValue, no single instance of UniqueTokens
        // is guaranteed to exhaustively test all 36^6 possible values, but stop
        // after that many attempts anyway:
        sal_uInt32 radix = 36;
        sal_uInt32 max = radix * radix * radix * radix * radix * radix;
            // 36^6 == 2'176'782'336 < SAL_MAX_UINT32 == 4'294'967'295
        if (m_count == max) {
            return false;
        }
        sal_uInt32 v;
        {
            osl::MutexGuard g(osl::Mutex::getGlobalMutex());
            globalValue
                = ((globalValue == SAL_MAX_UINT32
                    ? Time::GetSystemTicks() : globalValue + 1)
                   % max);
            v = globalValue;
        }
        *token = OUString::number(v, radix);
        ++m_count;
        return true;
    }

private:
    static sal_uInt32 globalValue;

    sal_uInt32 m_count;
};

sal_uInt32 UniqueTokens::globalValue = SAL_MAX_UINT32;

OUString lcl_createName(
    const OUString& rLeadingChars, Tokens & tokens, const OUString* pExtension,
    const OUString* pParent, bool bDirectory, bool bKeep, bool bLock)
{
    OUString aName = ConstructTempDir_Impl( pParent ) + rLeadingChars;;
    OUString token;
    while (tokens.next(&token))
    {
        OUString aTmp( aName + token );
        if ( pExtension )
            aTmp += *pExtension;
        else
            aTmp += ".tmp";
        if ( bDirectory )
        {
            FileBase::RC err = Directory::create( aTmp );
            if ( err == FileBase::E_None )
            {
                // !bKeep: only for creating a name, not a file or directory
                if ( bKeep || Directory::remove( aTmp ) == FileBase::E_None )
                    return aTmp;
                else
                    return OUString();
            }
            else if ( err != FileBase::E_EXIST )
                // if f.e. name contains invalid chars stop trying to create dirs
                return OUString();
        }
        else
        {
            DBG_ASSERT( bKeep, "Too expensive, use directory for creating name!" );
            File aFile( aTmp );
#ifdef UNX
            /* RW permission for the user only! */
            mode_t old_mode = umask(077);
#endif
            FileBase::RC err = aFile.open(osl_File_OpenFlag_Create | (bLock ? 0 : osl_File_OpenFlag_NoLock));
#ifdef UNX
            umask(old_mode);
#endif
            if ( err == FileBase::E_None || (bLock && err == FileBase::E_NOLCK) )
            {
                aFile.close();
                return aTmp;
            }
            else if ( err != FileBase::E_EXIST )
            {
                // if f.e. name contains invalid chars stop trying to create dirs
                // but if there is a folder with such name proceed further

                DirectoryItem aTmpItem;
                FileStatus aTmpStatus( osl_FileStatus_Mask_Type );
                if ( DirectoryItem::get( aTmp, aTmpItem ) != FileBase::E_None
                  || aTmpItem.getFileStatus( aTmpStatus ) != FileBase::E_None
                  || aTmpStatus.getFileType() != FileStatus::Directory )
                    return OUString();
            }
        }
    }
    return OUString();
}

OUString CreateTempName_Impl( const OUString* pParent, bool bKeep, bool bDir = true )
{
    OUString aEyeCatcher = "lu";
#ifdef DBG_UTIL
#ifdef UNX
    const char* eye = getenv("LO_TESTNAME");
    if(eye)
    {
        aEyeCatcher = OUString(eye, strlen(eye), RTL_TEXTENCODING_ASCII_US);
    }
#endif
#endif
    UniqueTokens t;
    return lcl_createName(aEyeCatcher, t, 0, pParent, bDir, bKeep, false);
}

OUString TempFile::CreateTempName()
{
    OUString aName(CreateTempName_Impl( 0, false ));

    // convert to file URL
    OUString aTmp;
    if ( !aName.isEmpty() )
        FileBase::getSystemPathFromFileURL( aName, aTmp );
    return aTmp;
}

TempFile::TempFile( const OUString* pParent, bool bDirectory )
    : pStream( 0 )
    , bIsDirectory( bDirectory )
    , bKillingFileEnabled( false )
{
    aName = CreateTempName_Impl( pParent, true, bDirectory );
}

TempFile::TempFile( const OUString& rLeadingChars, bool _bStartWithZero, const OUString* pExtension, const OUString* pParent, bool bDirectory)
    : pStream( 0 )
    , bIsDirectory( bDirectory )
    , bKillingFileEnabled( false )
{
    SequentialTokens t(_bStartWithZero);
    aName = lcl_createName(rLeadingChars, t, pExtension, pParent, bDirectory, true, true);
}

TempFile::~TempFile()
{
    delete pStream;
    if ( bKillingFileEnabled )
    {
        if ( bIsDirectory )
        {
            // at the moment no recursiv algorithm present
            Directory::remove( aName );
        }
        else
        {
            File::remove( aName );
        }
    }
}

bool TempFile::IsValid() const
{
    return !aName.isEmpty();
}

OUString TempFile::GetFileName() const
{
    OUString aTmp;
    FileBase::getSystemPathFromFileURL( aName, aTmp );
    return aTmp;
}

OUString TempFile::GetURL()
{
    if ( aURL.isEmpty() )
    {
        OUString aTmp;
        LocalFileHelper::ConvertPhysicalNameToURL( GetFileName(), aTmp );
        aURL = aTmp;
    }

    return aURL;
}

SvStream* TempFile::GetStream( StreamMode eMode )
{
    if ( !pStream )
    {
        if ( !GetURL().isEmpty() )
            pStream = UcbStreamHelper::CreateStream( aURL, eMode, true /* bFileExists */ );
        else
            pStream = new SvMemoryStream( eMode );
    }

    return pStream;
}

void TempFile::CloseStream()
{
    if ( pStream )
    {
        delete pStream;
        pStream = NULL;
    }
}

OUString TempFile::SetTempNameBaseDirectory( const OUString &rBaseName )
{
    if( rBaseName.isEmpty() )
        return OUString();

    OUString aUnqPath( rBaseName );

    // remove trailing slash
    if ( rBaseName.endsWith("/") )
        aUnqPath = rBaseName.copy( 0, rBaseName.getLength() - 1 );

    // try to create the directory
    bool bRet = false;
    osl::FileBase::RC err = osl::Directory::create( aUnqPath );
    if ( err != FileBase::E_None && err != FileBase::E_EXIST )
        // perhaps parent(s) don't exist
        bRet = ensuredir( aUnqPath );
    else
        bRet = true;

    // failure to create base directory means returning an empty string
    OUString aTmp;
    if ( bRet )
    {
        // append own internal directory
        bRet = true;
        OUString &rTempNameBase_Impl = TempNameBase_Impl::get();
        rTempNameBase_Impl = rBaseName;
        rTempNameBase_Impl += OUString('/');

        TempFile aBase( NULL, true );
        if ( aBase.IsValid() )
            // use it in case of success
            rTempNameBase_Impl = aBase.aName;

        // return system path of used directory
        FileBase::getSystemPathFromFileURL( rTempNameBase_Impl, aTmp );
    }

    return aTmp;
}
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#include "TextureFont.hpp"
#include FT_LCD_FILTER_H

using namespace rffalcon;

#define POINT_RES 64
#define DPI 72

TextureFont::TextureFont(std::shared_ptr<TextureAtlas> atlas, const float pointSize, const std::string &filename)
	: _atlas(atlas), _pointSize(pointSize), _filename(filename)
{
	_lcdWeights[0] = 0x10;
	_lcdWeights[0] = 0x40;
	_lcdWeights[0] = 0x70;
	_lcdWeights[0] = 0x40;
	_lcdWeights[0] = 0x10;
	_initialize();
}

TextureFont::~TextureFont()
{
}

float TextureFont::getHeight() const
{
	return _height;
}

void TextureFont::loadGlyphs(const std::string &text)
{
	int width = _atlas->getWidth();
	int height = _atlas->getHeight();
	int depth = _atlas->getDepth();

	FT_Error error;
	FT_Library library;
	FT_Face face;
	_loadFace(&library, &face);

	FT_Int32 flags = _getFlags();
	int length = text.length();
	// Load the glyph for each character in the string
	for (int i = 0; i < length; ++i)
	{
		char charCode = text[i];
		if (_shouldLoadGlyph(charCode))
		{
			_setFiltering(&library);
			FT_UInt glyphIndex = FT_Get_Char_Index(face, charCode);
			error = FT_Load_Glyph(face, glyphIndex, flags);
			if (error) { throw new std::exception(); }
		}
	}

	FT_Done_Face(face);
	FT_Done_FreeType(library);
}

void TextureFont::_setFiltering(FT_Library *library)
{
	if (_atlas->getDepth() == 3)
	{
		FT_Library_SetLcdFilter(*library, FT_LCD_FILTER_LIGHT);
		if (_filtering)
		{
			FT_Library_SetLcdFilterWeights(*library, _lcdWeights);
		}
	}
}

FT_Int32 TextureFont::_getFlags()
{
	FT_Int32 flags = 0;
	if (_outlineType > 0)
	{
		flags |= FT_LOAD_NO_BITMAP;
	}
	else
	{
		flags |= FT_LOAD_RENDER;
	}

	if (!_hinting)
	{
		flags |= FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT;
	}
	else
	{
		flags |= FT_LOAD_FORCE_AUTOHINT;
	}

	if (_atlas->getDepth() == 3)
	{
		flags |= FT_LOAD_TARGET_LCD;
	}

	return flags;
}

bool TextureFont::_shouldLoadGlyph(const char charCode)
{
	// Skip glyphs that have already been loaded
	bool skip = false;
	int sizeGlyphs = static_cast<int>(_glyphs.size());
	for (int j = 0; j < sizeGlyphs; ++j)
	{
		auto glyph = _glyphs[j];
		if (glyph->charCode == charCode &&
			(glyph->outlineType == _outlineType && glyph->outlineThickness == _outlineThickness))
		{
			skip = true;
			break;
		}
	}

	return skip;
}

void TextureFont::_initialize()
{
	FT_Library library;
	FT_Face face;
	FT_Size_Metrics metrics;

	FT_Error error = FT_Init_FreeType(&library);
	if (error != FT_Err_Ok)
	{
		throw new std::exception();
	}

	_loadFace(&library, &face, _pointSize * 100.0f);
	metrics = face->size->metrics;
	_ascender = (metrics.ascender >> 6) / 100.0f;
	_descender = (metrics.descender >> 6) / 100.0f;
	_height = (metrics.height >> 6) / 100.0f;
	_linegap = _height - _ascender + _descender;

	FT_Done_Face(face);
	FT_Done_FreeType(library);
}

void TextureFont::_loadFace(FT_Library *library, FT_Face *face, float pointSize)
{
	FT_Error error = FT_New_Face(*library, _filename.c_str(), 0, face);
	if (error != FT_Err_Ok)
	{
		throw new std::exception();
	}

	error = FT_Select_Charmap(*face, FT_ENCODING_UNICODE);
	if (error)
	{
		throw new std::exception();
	}

	error = FT_Set_Char_Size(*face, (int)(pointSize * POINT_RES), 0, DPI * POINT_RES, DPI);
	if (error)
	{
		throw new std::exception();
	}

	FT_Matrix matrix = {
		(int)((1.0 / POINT_RES) * 0x10000L),
		0,
		0,
		0x10000L
	};

	FT_Set_Transform(*face, &matrix, nullptr);
}

void TextureFont::_loadFace(FT_Library *library, FT_Face *face)
{
	_loadFace(library, face, _pointSize);
}<commit_msg>slot, bitmap, top and left for outline none<commit_after>#include "TextureFont.hpp"
#include FT_LCD_FILTER_H

using namespace rffalcon;

#define POINT_RES 64
#define DPI 72

TextureFont::TextureFont(std::shared_ptr<TextureAtlas> atlas, const float pointSize, const std::string &filename)
	: _atlas(atlas), _pointSize(pointSize), _filename(filename)
{
	_lcdWeights[0] = 0x10;
	_lcdWeights[0] = 0x40;
	_lcdWeights[0] = 0x70;
	_lcdWeights[0] = 0x40;
	_lcdWeights[0] = 0x10;
	_initialize();
}

TextureFont::~TextureFont()
{
}

float TextureFont::getHeight() const
{
	return _height;
}

void TextureFont::loadGlyphs(const std::string &text)
{
	int width = _atlas->getWidth();
	int height = _atlas->getHeight();
	int depth = _atlas->getDepth();

	FT_Error error;
	FT_Library library;
	FT_Face face;
	_loadFace(&library, &face);

	FT_Int32 flags = _getFlags();
	int length = text.length();
	// Load the glyph for each character in the string
	for (int i = 0; i < length; ++i)
	{
		char charCode = text[i];
		if (_shouldLoadGlyph(charCode))
		{
			_setFiltering(&library);
			FT_UInt glyphIndex = FT_Get_Char_Index(face, charCode);
			error = FT_Load_Glyph(face, glyphIndex, flags);
			if (error) { throw new std::exception(); }

			if (_outlineType == 0)
			{
				FT_GlyphSlot slot = face->glyph;
				FT_Bitmap bitmap = slot->bitmap;
				int top = slot->bitmap_top;
				int left = slot->bitmap_left;
			}
		}
	}

	FT_Done_Face(face);
	FT_Done_FreeType(library);
}

void TextureFont::_setFiltering(FT_Library *library)
{
	if (_atlas->getDepth() == 3)
	{
		FT_Library_SetLcdFilter(*library, FT_LCD_FILTER_LIGHT);
		if (_filtering)
		{
			FT_Library_SetLcdFilterWeights(*library, _lcdWeights);
		}
	}
}

FT_Int32 TextureFont::_getFlags()
{
	FT_Int32 flags = 0;
	if (_outlineType > 0)
	{
		flags |= FT_LOAD_NO_BITMAP;
	}
	else
	{
		flags |= FT_LOAD_RENDER;
	}

	if (!_hinting)
	{
		flags |= FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT;
	}
	else
	{
		flags |= FT_LOAD_FORCE_AUTOHINT;
	}

	if (_atlas->getDepth() == 3)
	{
		flags |= FT_LOAD_TARGET_LCD;
	}

	return flags;
}

bool TextureFont::_shouldLoadGlyph(const char charCode)
{
	// Skip glyphs that have already been loaded
	bool skip = false;
	int sizeGlyphs = static_cast<int>(_glyphs.size());
	for (int j = 0; j < sizeGlyphs; ++j)
	{
		auto glyph = _glyphs[j];
		if (glyph->charCode == charCode &&
			(glyph->outlineType == _outlineType && glyph->outlineThickness == _outlineThickness))
		{
			skip = true;
			break;
		}
	}

	return skip;
}

void TextureFont::_initialize()
{
	FT_Library library;
	FT_Face face;
	FT_Size_Metrics metrics;

	FT_Error error = FT_Init_FreeType(&library);
	if (error != FT_Err_Ok)
	{
		throw new std::exception();
	}

	_loadFace(&library, &face, _pointSize * 100.0f);
	metrics = face->size->metrics;
	_ascender = (metrics.ascender >> 6) / 100.0f;
	_descender = (metrics.descender >> 6) / 100.0f;
	_height = (metrics.height >> 6) / 100.0f;
	_linegap = _height - _ascender + _descender;

	FT_Done_Face(face);
	FT_Done_FreeType(library);
}

void TextureFont::_loadFace(FT_Library *library, FT_Face *face, float pointSize)
{
	FT_Error error = FT_New_Face(*library, _filename.c_str(), 0, face);
	if (error != FT_Err_Ok)
	{
		throw new std::exception();
	}

	error = FT_Select_Charmap(*face, FT_ENCODING_UNICODE);
	if (error)
	{
		throw new std::exception();
	}

	error = FT_Set_Char_Size(*face, (int)(pointSize * POINT_RES), 0, DPI * POINT_RES, DPI);
	if (error)
	{
		throw new std::exception();
	}

	FT_Matrix matrix = {
		(int)((1.0 / POINT_RES) * 0x10000L),
		0,
		0,
		0x10000L
	};

	FT_Set_Transform(*face, &matrix, nullptr);
}

void TextureFont::_loadFace(FT_Library *library, FT_Face *face)
{
	_loadFace(library, face, _pointSize);
}<|endoftext|>


<commit_before>#include "AppInfo.h"
#include "Config.h"
#include "DNSMusic.h"

#include <iostream>
#include <mosquittopp.h>
#include <signal.h>
#include <sys/stat.h>

using namespace std;

volatile bool receivedSIGINT{ false };

void handleSIGINT (int) {
    cerr << "revieced signal for signalhandler" << endl;
    receivedSIGINT = true;
}

void handleSIGCHLD (int) {
    /*TODO implement SIGCHLD handler*/
    int status;
    pid_t pid = wait (&status);
    /*lookup pid in map to find function
    remove pid entry from map
    call function
    */
}

int main (int argc, char* argv[]) {
    signal (SIGINT, handleSIGINT);
    signal (SIGCHLD, handleSIGCHLD);

    int major{ 0 };
    int minor{ 0 };
    int revision{ 0 };

    // temp test
    if (argc != 2) {
        std::cout << "usage: " << argv[0] << " file.ogg" << std::endl;
        return 1;
    }

    std::string music_file = argv[1];

    struct stat buffer;
    if (stat (music_file.c_str (), &buffer) != 0) {
        std::perror ("error, file:");
        return 1;
    }
    // end temp

    cout << "-- MQTT application: " << APPNAME_VERSION << "  ";
    mosqpp::lib_init ();
    mosqpp::lib_version (&major, &minor, &revision);
    cout << "uses Mosquitto lib version " << major << '.' << minor << '.'
         << revision << endl;
    try {
        DNSMusic client ("DNSMusic", "tempDNS", MQTT_BROKER, MQTT_BROKER_PORT, music_file);

        // auto clients{ static_cast<mosqpp::mosquittopp*> (&tempDNS) };

        while (!receivedSIGINT) {
            // for (auto client : clients) {
            int rc = client.loop ();
            if (rc) {
                cerr << "-- MQTT reconnect" << std::endl;
                client.reconnect ();
            }
            //}
        }
    } catch (exception& e) {
        cerr << "Exception " << e.what () << std::endl;
    } catch (...) {
        cerr << "UNKNOWN EXCEPTION \n";
    }

    cout << "-- MQTT application: " << APPNAME_VERSION << " stopped" << endl
         << endl;
    mosqpp::lib_cleanup ();

    return 0;
}
<commit_msg>fix compile warning and a faulty string<commit_after>#include "AppInfo.h"
#include "Config.h"
#include "DNSMusic.h"

#include <iostream>
#include <mosquittopp.h>
#include <signal.h>
#include <sys/stat.h>

using namespace std;

volatile bool receivedSIGINT{ false };

void handleSIGINT (int) {
    cerr << "revieced signal for signalhandler" << endl;
    receivedSIGINT = true;
}

void handleSIGCHLD (int) {
    /*TODO implement SIGCHLD handler*/
    int status;
    wait (&status); // pid_t pid =
    /*lookup pid in map to find function
    remove pid entry from map
    call function
    */
}

int main (int argc, char* argv[]) {
    signal (SIGINT, handleSIGINT);
    signal (SIGCHLD, handleSIGCHLD);

    int major{ 0 };
    int minor{ 0 };
    int revision{ 0 };

    // temp test
    if (argc != 2) {
        std::cout << "usage: " << argv[0] << " file.ogg" << std::endl;
        return 1;
    }

    std::string music_file = argv[1];

    struct stat buffer;
    if (stat (music_file.c_str (), &buffer) != 0) {
        std::perror ("error, file");
        return 1;
    }
    // end temp

    cout << "-- MQTT application: " << APPNAME_VERSION << "  ";
    mosqpp::lib_init ();
    mosqpp::lib_version (&major, &minor, &revision);
    cout << "uses Mosquitto lib version " << major << '.' << minor << '.'
         << revision << endl;
    try {
        DNSMusic client ("DNSMusic", "tempDNS", MQTT_BROKER, MQTT_BROKER_PORT, music_file);

        // auto clients{ static_cast<mosqpp::mosquittopp*> (&tempDNS) };

        while (!receivedSIGINT) {
            // for (auto client : clients) {
            int rc = client.loop ();
            if (rc) {
                cerr << "-- MQTT reconnect" << std::endl;
                client.reconnect ();
            }
            //}
        }
    } catch (exception& e) {
        cerr << "Exception " << e.what () << std::endl;
    } catch (...) {
        cerr << "UNKNOWN EXCEPTION \n";
    }

    cout << "-- MQTT application: " << APPNAME_VERSION << " stopped" << endl
         << endl;
    mosqpp::lib_cleanup ();

    return 0;
}
<|endoftext|>