<commit_before>namespace factor {

typedef intptr_t fixnum;
typedef uintptr_t cell;

inline static cell align(cell a, cell b) { return (a + (b - 1)) & ~(b - 1); }

inline static cell alignment_for(cell a, cell b) { return align(a, b) - a; }

static const cell data_alignment = 16;

// Must match leaf-stack-frame-size in core/layouts/layouts.factor
#define LEAF_FRAME_SIZE 16

#define WORD_SIZE (signed)(sizeof(cell) * 8)

#define TAG_MASK 15
#define TAG_BITS 4
#define TAG(x) ((cell)(x) & TAG_MASK)
#define UNTAG(x) ((cell)(x) & ~TAG_MASK)
#define RETAG(x, tag) (UNTAG(x) | (tag))

// Type tags, should be kept in sync with:
//   core/bootstrap/layouts/layouts.factor
#define FIXNUM_TYPE 0
#define F_TYPE 1
#define ARRAY_TYPE 2
#define FLOAT_TYPE 3
#define QUOTATION_TYPE 4
#define BIGNUM_TYPE 5
#define ALIEN_TYPE 6
#define TUPLE_TYPE 7
#define WRAPPER_TYPE 8
#define BYTE_ARRAY_TYPE 9
#define CALLSTACK_TYPE 10
#define STRING_TYPE 11
#define WORD_TYPE 12
#define DLL_TYPE 13

#define TYPE_COUNT 14

static inline const char* type_name(cell type) {
  switch (type) {
    case FIXNUM_TYPE:
      return "fixnum";
    case F_TYPE:
      return "f";
    case ARRAY_TYPE:
      return "array";
    case FLOAT_TYPE:
      return "float";
    case QUOTATION_TYPE:
      return "quotation";
    case BIGNUM_TYPE:
      return "bignum";
    case ALIEN_TYPE:
      return "alien";
    case TUPLE_TYPE:
      return "tuple";
    case WRAPPER_TYPE:
      return "wrapper";
    case BYTE_ARRAY_TYPE:
      return "byte-array";
    case CALLSTACK_TYPE:
      return "callstack";
    case STRING_TYPE:
      return "string";
    case WORD_TYPE:
      return "word";
    case DLL_TYPE:
      return "dll";
    default:
      FACTOR_ASSERT(false);
      return "";
  }
}

enum code_block_type {
  CODE_BLOCK_UNOPTIMIZED,
  CODE_BLOCK_OPTIMIZED,
  CODE_BLOCK_PIC
};

// Constants used when floating-point trap exceptions are thrown
enum {
  FP_TRAP_INVALID_OPERATION = 1 << 0,
  FP_TRAP_OVERFLOW = 1 << 1,
  FP_TRAP_UNDERFLOW = 1 << 2,
  FP_TRAP_ZERO_DIVIDE = 1 << 3,
  FP_TRAP_INEXACT = 1 << 4,
};

// What Factor calls 'f'
static const cell false_object = F_TYPE;

inline static bool immediate_p(cell obj) {
  // We assume that fixnums have tag 0 and false_object has tag 1
  return TAG(obj) <= F_TYPE;
}

inline static fixnum untag_fixnum(cell tagged) {
  FACTOR_ASSERT(TAG(tagged) == FIXNUM_TYPE);
  return ((fixnum)tagged) >> TAG_BITS;
}

inline static cell tag_fixnum(fixnum untagged) {
  return (untagged << TAG_BITS) | FIXNUM_TYPE;
}

#define NO_TYPE_CHECK static const cell type_number = TYPE_COUNT

struct object {
  NO_TYPE_CHECK;
  // header format (bits indexed with least significant as zero):
  // bit 0      : free?
  // bit 1      : forwarding pointer?
  // if not forwarding:
  //   bit 2-5    : tag
  //   bit 7-end  : hashcode
  // if forwarding:
  //   bit 2-end  : forwarding pointer
  cell header;

  template <typename Fixup> cell base_size(Fixup fixup) const;
  template <typename Fixup> cell size(Fixup fixup) const;
  cell size() const;

  cell slot_count() const;
  template <typename Fixup> cell slot_count(Fixup fixup) const;

  cell* slots() const { return (cell*)this; }

  template <typename Iterator> void each_slot(Iterator& iter);

  // Only valid for objects in tenured space; must cast to free_heap_block
  // to do anything with it if its free
  bool free_p() const { return (header & 1) == 1; }

  cell type() const { return (header >> 2) & TAG_MASK; }

  void initialize(cell type) { header = type << 2; }

  cell hashcode() const { return (header >> 6); }

  void set_hashcode(cell hashcode) {
    header = (header & 0x3f) | (hashcode << 6);
  }

  bool forwarding_pointer_p() const { return (header & 2) == 2; }

  object* forwarding_pointer() const { return (object*)UNTAG(header); }

  void forward_to(object* pointer) { header = ((cell)pointer | 2); }
};

// Assembly code makes assumptions about the layout of this struct
struct array : public object {
  static const cell type_number = ARRAY_TYPE;
  static const cell element_size = sizeof(cell);
  // tagged
  cell capacity;

  cell* data() const { return (cell*)(this + 1); }
};

// These are really just arrays, but certain elements have special
// significance
struct tuple_layout : public array {
  NO_TYPE_CHECK;
  // tagged
  cell klass;
  // tagged fixnum
  cell size;
  // tagged fixnum
  cell echelon;
};

struct bignum : public object {
  static const cell type_number = BIGNUM_TYPE;
  static const cell element_size = sizeof(cell);
  // tagged
  cell capacity;

  cell* data() const { return (cell*)(this + 1); }
};

struct byte_array : public object {
  static const cell type_number = BYTE_ARRAY_TYPE;
  static const cell element_size = 1;
  // tagged
  cell capacity;

#ifndef FACTOR_64
  cell padding0;
  cell padding1;
#endif

  template <typename Scalar> Scalar* data() const {
    return (Scalar*)(this + 1);
  }
};

// Assembly code makes assumptions about the layout of this struct
struct string : public object {
  static const cell type_number = STRING_TYPE;
  // tagged num of chars
  cell length;
  // tagged
  cell aux;
  // tagged
  cell hashcode;

  uint8_t* data() const { return (uint8_t*)(this + 1); }
};

struct code_block;

// Assembly code makes assumptions about the layout of this struct:
//   basis/bootstrap/images/images.factor
//   basis/compiler/constants/constants.factor
//   core/bootstrap/primitives.factor

struct word : public object {
  static const cell type_number = WORD_TYPE;
  // TAGGED hashcode
  cell hashcode;
  // TAGGED word name
  cell name;
  // TAGGED word vocabulary
  cell vocabulary;
  // TAGGED definition
  cell def;
  // TAGGED property assoc for library code
  cell props;
  // TAGGED alternative entry point for direct non-tail calls. Used for inline
  // caching
  cell pic_def;
  // TAGGED alternative entry point for direct tail calls. Used for inline
  // caching
  cell pic_tail_def;
  // TAGGED machine code for sub-primitive
  cell subprimitive;
  // UNTAGGED entry point: jump here to execute word
  cell entry_point;
  // UNTAGGED compiled code block

  // defined in code_blocks.hpp
  code_block* code() const;
};

// Assembly code makes assumptions about the layout of this struct
struct wrapper : public object {
  static const cell type_number = WRAPPER_TYPE;
  cell object;
};

// Assembly code makes assumptions about the layout of this struct
struct boxed_float : object {
  static const cell type_number = FLOAT_TYPE;

#ifndef FACTOR_64
  cell padding;
#endif

  double n;
};

// Assembly code makes assumptions about the layout of this struct:
//   basis/bootstrap/images/images.factor
//   basis/compiler/constants/constants.factor
//   core/bootstrap/primitives.factor

struct quotation : public object {
  static const cell type_number = QUOTATION_TYPE;
  // tagged
  cell array;
  // tagged
  cell cached_effect;
  // tagged
  cell cache_counter;
  // UNTAGGED entry point; jump here to call quotation
  cell entry_point;

  // defined in code_blocks.hpp
  code_block* code() const;
};

// Assembly code makes assumptions about the layout of this struct
struct alien : public object {
  static const cell type_number = ALIEN_TYPE;
  // tagged
  cell base;
  // tagged
  cell expired;
  // untagged
  cell displacement;
  // untagged
  cell address;

  void update_address() {
    if (base == false_object)
      address = displacement;
    else
      address = UNTAG(base) + sizeof(byte_array) + displacement;
  }
};

struct dll : public object {
  static const cell type_number = DLL_TYPE;
  // tagged byte array holding a C string
  cell path;
  // OS-specific handle
  void* handle;
};

struct callstack : public object {
  static const cell type_number = CALLSTACK_TYPE;
  // tagged
  cell length;

  cell frame_top_at(cell offset) const {
    return (cell)(this + 1) + offset;
  }

  void* top() const { return (void*)(this + 1); }
  void* bottom() const {
    return (void*)((cell)(this + 1) + untag_fixnum(length));
  }
};

struct tuple : public object {
  static const cell type_number = TUPLE_TYPE;
  // tagged layout
  cell layout;

  cell* data() const { return (cell*)(this + 1); }
};

inline static cell tuple_capacity(const tuple_layout *layout) {
  return untag_fixnum(layout->size);
}

inline static cell tuple_size(const tuple_layout* layout) {
  return sizeof(tuple) + tuple_capacity(layout) * sizeof(cell);
}

inline static cell string_capacity(const string* str) {
  return untag_fixnum(str->length);
}

inline static cell string_size(cell size) { return sizeof(string) + size; }

}
<commit_msg>cast fixes undefined behaviour; closes #1919 in upstream<commit_after>namespace factor {

typedef intptr_t fixnum;
typedef uintptr_t cell;

inline static cell align(cell a, cell b) { return (a + (b - 1)) & ~(b - 1); }

inline static cell alignment_for(cell a, cell b) { return align(a, b) - a; }

static const cell data_alignment = 16;

// Must match leaf-stack-frame-size in core/layouts/layouts.factor
#define LEAF_FRAME_SIZE 16

#define WORD_SIZE (signed)(sizeof(cell) * 8)

#define TAG_MASK 15
#define TAG_BITS 4
#define TAG(x) ((cell)(x) & TAG_MASK)
#define UNTAG(x) ((cell)(x) & ~TAG_MASK)
#define RETAG(x, tag) (UNTAG(x) | (tag))

// Type tags, should be kept in sync with:
//   core/bootstrap/layouts/layouts.factor
#define FIXNUM_TYPE 0
#define F_TYPE 1
#define ARRAY_TYPE 2
#define FLOAT_TYPE 3
#define QUOTATION_TYPE 4
#define BIGNUM_TYPE 5
#define ALIEN_TYPE 6
#define TUPLE_TYPE 7
#define WRAPPER_TYPE 8
#define BYTE_ARRAY_TYPE 9
#define CALLSTACK_TYPE 10
#define STRING_TYPE 11
#define WORD_TYPE 12
#define DLL_TYPE 13

#define TYPE_COUNT 14

static inline const char* type_name(cell type) {
  switch (type) {
    case FIXNUM_TYPE:
      return "fixnum";
    case F_TYPE:
      return "f";
    case ARRAY_TYPE:
      return "array";
    case FLOAT_TYPE:
      return "float";
    case QUOTATION_TYPE:
      return "quotation";
    case BIGNUM_TYPE:
      return "bignum";
    case ALIEN_TYPE:
      return "alien";
    case TUPLE_TYPE:
      return "tuple";
    case WRAPPER_TYPE:
      return "wrapper";
    case BYTE_ARRAY_TYPE:
      return "byte-array";
    case CALLSTACK_TYPE:
      return "callstack";
    case STRING_TYPE:
      return "string";
    case WORD_TYPE:
      return "word";
    case DLL_TYPE:
      return "dll";
    default:
      FACTOR_ASSERT(false);
      return "";
  }
}

enum code_block_type {
  CODE_BLOCK_UNOPTIMIZED,
  CODE_BLOCK_OPTIMIZED,
  CODE_BLOCK_PIC
};

// Constants used when floating-point trap exceptions are thrown
enum {
  FP_TRAP_INVALID_OPERATION = 1 << 0,
  FP_TRAP_OVERFLOW = 1 << 1,
  FP_TRAP_UNDERFLOW = 1 << 2,
  FP_TRAP_ZERO_DIVIDE = 1 << 3,
  FP_TRAP_INEXACT = 1 << 4,
};

// What Factor calls 'f'
static const cell false_object = F_TYPE;

inline static bool immediate_p(cell obj) {
  // We assume that fixnums have tag 0 and false_object has tag 1
  return TAG(obj) <= F_TYPE;
}

inline static fixnum untag_fixnum(cell tagged) {
  FACTOR_ASSERT(TAG(tagged) == FIXNUM_TYPE);
  return ((fixnum)tagged) >> TAG_BITS;
}

inline static cell tag_fixnum(fixnum untagged) {
  return ( (cell)untagged << TAG_BITS) | FIXNUM_TYPE;
}

#define NO_TYPE_CHECK static const cell type_number = TYPE_COUNT

struct object {
  NO_TYPE_CHECK;
  // header format (bits indexed with least significant as zero):
  // bit 0      : free?
  // bit 1      : forwarding pointer?
  // if not forwarding:
  //   bit 2-5    : tag
  //   bit 7-end  : hashcode
  // if forwarding:
  //   bit 2-end  : forwarding pointer
  cell header;

  template <typename Fixup> cell base_size(Fixup fixup) const;
  template <typename Fixup> cell size(Fixup fixup) const;
  cell size() const;

  cell slot_count() const;
  template <typename Fixup> cell slot_count(Fixup fixup) const;

  cell* slots() const { return (cell*)this; }

  template <typename Iterator> void each_slot(Iterator& iter);

  // Only valid for objects in tenured space; must cast to free_heap_block
  // to do anything with it if its free
  bool free_p() const { return (header & 1) == 1; }

  cell type() const { return (header >> 2) & TAG_MASK; }

  void initialize(cell type) { header = type << 2; }

  cell hashcode() const { return (header >> 6); }

  void set_hashcode(cell hashcode) {
    header = (header & 0x3f) | (hashcode << 6);
  }

  bool forwarding_pointer_p() const { return (header & 2) == 2; }

  object* forwarding_pointer() const { return (object*)UNTAG(header); }

  void forward_to(object* pointer) { header = ((cell)pointer | 2); }
};

// Assembly code makes assumptions about the layout of this struct
struct array : public object {
  static const cell type_number = ARRAY_TYPE;
  static const cell element_size = sizeof(cell);
  // tagged
  cell capacity;

  cell* data() const { return (cell*)(this + 1); }
};

// These are really just arrays, but certain elements have special
// significance
struct tuple_layout : public array {
  NO_TYPE_CHECK;
  // tagged
  cell klass;
  // tagged fixnum
  cell size;
  // tagged fixnum
  cell echelon;
};

struct bignum : public object {
  static const cell type_number = BIGNUM_TYPE;
  static const cell element_size = sizeof(cell);
  // tagged
  cell capacity;

  cell* data() const { return (cell*)(this + 1); }
};

struct byte_array : public object {
  static const cell type_number = BYTE_ARRAY_TYPE;
  static const cell element_size = 1;
  // tagged
  cell capacity;

#ifndef FACTOR_64
  cell padding0;
  cell padding1;
#endif

  template <typename Scalar> Scalar* data() const {
    return (Scalar*)(this + 1);
  }
};

// Assembly code makes assumptions about the layout of this struct
struct string : public object {
  static const cell type_number = STRING_TYPE;
  // tagged num of chars
  cell length;
  // tagged
  cell aux;
  // tagged
  cell hashcode;

  uint8_t* data() const { return (uint8_t*)(this + 1); }
};

struct code_block;

// Assembly code makes assumptions about the layout of this struct:
//   basis/bootstrap/images/images.factor
//   basis/compiler/constants/constants.factor
//   core/bootstrap/primitives.factor

struct word : public object {
  static const cell type_number = WORD_TYPE;
  // TAGGED hashcode
  cell hashcode;
  // TAGGED word name
  cell name;
  // TAGGED word vocabulary
  cell vocabulary;
  // TAGGED definition
  cell def;
  // TAGGED property assoc for library code
  cell props;
  // TAGGED alternative entry point for direct non-tail calls. Used for inline
  // caching
  cell pic_def;
  // TAGGED alternative entry point for direct tail calls. Used for inline
  // caching
  cell pic_tail_def;
  // TAGGED machine code for sub-primitive
  cell subprimitive;
  // UNTAGGED entry point: jump here to execute word
  cell entry_point;
  // UNTAGGED compiled code block

  // defined in code_blocks.hpp
  code_block* code() const;
};

// Assembly code makes assumptions about the layout of this struct
struct wrapper : public object {
  static const cell type_number = WRAPPER_TYPE;
  cell object;
};

// Assembly code makes assumptions about the layout of this struct
struct boxed_float : object {
  static const cell type_number = FLOAT_TYPE;

#ifndef FACTOR_64
  cell padding;
#endif

  double n;
};

// Assembly code makes assumptions about the layout of this struct:
//   basis/bootstrap/images/images.factor
//   basis/compiler/constants/constants.factor
//   core/bootstrap/primitives.factor

struct quotation : public object {
  static const cell type_number = QUOTATION_TYPE;
  // tagged
  cell array;
  // tagged
  cell cached_effect;
  // tagged
  cell cache_counter;
  // UNTAGGED entry point; jump here to call quotation
  cell entry_point;

  // defined in code_blocks.hpp
  code_block* code() const;
};

// Assembly code makes assumptions about the layout of this struct
struct alien : public object {
  static const cell type_number = ALIEN_TYPE;
  // tagged
  cell base;
  // tagged
  cell expired;
  // untagged
  cell displacement;
  // untagged
  cell address;

  void update_address() {
    if (base == false_object)
      address = displacement;
    else
      address = UNTAG(base) + sizeof(byte_array) + displacement;
  }
};

struct dll : public object {
  static const cell type_number = DLL_TYPE;
  // tagged byte array holding a C string
  cell path;
  // OS-specific handle
  void* handle;
};

struct callstack : public object {
  static const cell type_number = CALLSTACK_TYPE;
  // tagged
  cell length;

  cell frame_top_at(cell offset) const {
    return (cell)(this + 1) + offset;
  }

  void* top() const { return (void*)(this + 1); }
  void* bottom() const {
    return (void*)((cell)(this + 1) + untag_fixnum(length));
  }
};

struct tuple : public object {
  static const cell type_number = TUPLE_TYPE;
  // tagged layout
  cell layout;

  cell* data() const { return (cell*)(this + 1); }
};

inline static cell tuple_capacity(const tuple_layout *layout) {
  return untag_fixnum(layout->size);
}

inline static cell tuple_size(const tuple_layout* layout) {
  return sizeof(tuple) + tuple_capacity(layout) * sizeof(cell);
}

inline static cell string_capacity(const string* str) {
  return untag_fixnum(str->length);
}

inline static cell string_size(cell size) { return sizeof(string) + size; }

}
<|endoftext|>


<commit_before>#include <ctype.h>
#include <string.h>
#include <math.h>
#include <iomanip>

#include "objectmemory.hpp"
#include "marshal.hpp"

#include "object_utils.hpp"

#include <tommath.h>
#include <gdtoa.h>

#include "builtin/array.hpp"
#include "builtin/compiledmethod.hpp"
#include "builtin/encoding.hpp"
#include "builtin/fixnum.hpp"
#include "builtin/float.hpp"
#include "builtin/iseq.hpp"
#include "builtin/string.hpp"
#include "builtin/symbol.hpp"
#include "builtin/tuple.hpp"

#include "detection.hpp"

#define STACK_BUF_SZ 1024

namespace rubinius {

  using std::endl;

  Object* UnMarshaller::get_constant() {
    char stack_data[STACK_BUF_SZ];
    char *malloc_data = NULL;
    char *data = stack_data;

    size_t count;

    stream >> count;
    stream.get();

    if(count >= STACK_BUF_SZ) {
      malloc_data = (char*)malloc(count + 1);
      data = malloc_data;
    }

    stream.read(data, count + 1);
    data[count] = 0; // clamp

    Object* cls = state->vm()->path2class(data);

    if(malloc_data) {
      free(malloc_data);
    }
    return cls;
  }

  Object* UnMarshaller::get_encoding() {
    char stack_data[STACK_BUF_SZ];
    char *malloc_data = NULL;
    char *data = stack_data;
    size_t count;

    stream >> count;
    stream.get();

    if(count >= STACK_BUF_SZ) {
      malloc_data = (char*)malloc(count + 1);
      data = malloc_data;
    }

    stream.read(data, count + 1);
    data[count] = 0; // clamp

    if(count > 0) {
      Encoding* enc = Encoding::find(state, data);
      if(malloc_data) {
        free(malloc_data);
      }
      return enc;
    } else {
      return cNil;
    }
  }

  Object* UnMarshaller::get_int() {
    std::string data;
    stream >> data;

    return Bignum::from_string(state, data.c_str(), 16);
  }

  String* UnMarshaller::get_string() {
    size_t count;

    Encoding* enc = try_as<Encoding>(unmarshal());

    stream >> count;
    // String::create adds room for a trailing null on its own
    // using pinned here allows later stages to optimize these literal
    // strings better.
    String* str = String::create(state, NULL, count);

    stream.get(); // read off newline
    stream.read(reinterpret_cast<char*>(str->byte_address()), count);
    stream.get(); // read off newline

    if(enc) str->encoding(state, enc);

    return str;
  }

  Symbol* UnMarshaller::get_symbol() {
    char stack_data[STACK_BUF_SZ];
    char *malloc_data = NULL;
    char *data = stack_data;
    size_t count;

    stream >> count;
    stream.get();

    if(count >= STACK_BUF_SZ) {
      malloc_data = (char*)malloc(count + 1);
      data = malloc_data;
    }

    stream.read(data, count + 1);
    data[count] = 0; // clamp

    Symbol* sym = state->symbol(data);

    if(malloc_data) {
      free(malloc_data);
    }

    return sym;
  }

  Tuple* UnMarshaller::get_tuple() {
    size_t count;
    stream >> count;

    Tuple* tup = Tuple::create(state, count);

    for(size_t i = 0; i < count; i++) {
      tup->put(state, i, unmarshal());
    }

    return tup;
  }

#define FLOAT_EXP_OFFSET    58

  Float* UnMarshaller::get_float() {
    std::string line;
    const char* data;

    // discard the delimiter
    stream.get();

    std::getline(stream, line);
    if(stream.fail()) {
      Exception::type_error(state, "Unable to unmarshal Float: failed to read value");
    }

    data = line.c_str();
    if(data[0] == ' ') {
      double x;
      long   e;

      x = ::ruby_strtod(data, NULL);
      e = strtol(data+FLOAT_EXP_OFFSET, NULL, 10);

      // This is necessary because exp2(1024) yields inf
      if(e == 1024) {
        double root_exp = ::exp2(512);
        return Float::create(state, x * root_exp * root_exp);
      } else {
        return Float::create(state, x * ::exp2(e));
      }
    } else {
      // avoid compiler warning
      double zero = 0.0;
      double val = 0.0;

      if(!strncasecmp(data, "Infinity", 8U)) {
        val = 1.0;
      } else if(!strncasecmp(data, "-Infinity", 9U)) {
        val = -1.0;
      } else if(!strncasecmp(data, "NaN", 3U)) {
        val = zero;
      } else {
        Exception::type_error(state, "Unable to unmarshal Float: invalid format");
      }

      return Float::create(state, val / zero);
    }
  }

  InstructionSequence* UnMarshaller::get_iseq() {
    size_t count;
    long op;
    char data[32];
    stream >> count;

    // Read off newline
    stream.get();

    InstructionSequence* iseq = InstructionSequence::create(state, count);
    Tuple* ops = iseq->opcodes();

    for(size_t i = 0; i < count; i++) {
      stream.getline(data, 32);
      op = strtol(data, NULL, 10);
      ops->put(state, i, Fixnum::from(op));
    }

    iseq->post_marshal(state);

    return iseq;
  }

  CompiledMethod* UnMarshaller::get_cmethod() {
    size_t ver;
    stream >> ver;

    CompiledMethod* cm = CompiledMethod::create(state);

    cm->metadata(state, unmarshal());
    cm->primitive(state, (Symbol*)unmarshal());
    cm->name(state, (Symbol*)unmarshal());
    cm->iseq(state, (InstructionSequence*)unmarshal());
    cm->stack_size(state, (Fixnum*)unmarshal());
    cm->local_count(state, (Fixnum*)unmarshal());
    cm->required_args(state, (Fixnum*)unmarshal());
    cm->post_args(state, (Fixnum*)unmarshal());
    cm->total_args(state, (Fixnum*)unmarshal());
    cm->splat(state, unmarshal());
    cm->literals(state, (Tuple*)unmarshal());
    cm->lines(state, (Tuple*)unmarshal());
    cm->file(state, (Symbol*)unmarshal());
    cm->local_names(state, (Tuple*)unmarshal());

    cm->post_marshal(state);

    return cm;
  }

  Object* UnMarshaller::unmarshal() {
    char code;

    stream >> code;

    switch(code) {
    case 'n':
      return cNil;
    case 't':
      return cTrue;
    case 'f':
      return cFalse;
    case 'I':
      return get_int();
    case 's':
      return get_string();
    case 'x':
      return get_symbol();
    case 'p':
      return get_tuple();
    case 'd':
      return get_float();
    case 'i':
      return get_iseq();
    case 'M':
      return get_cmethod();
    case 'c':
      return get_constant();
    case 'E':
      return get_encoding();
    default:
      std::string str = "unknown marshal code: ";
      str.append( 1, code );
      Exception::type_error(state, str.c_str());
      return cNil;    // make compiler happy
    }
  }
}
<commit_msg>Marshal doesn't use std::endl.<commit_after>#include <ctype.h>
#include <string.h>
#include <math.h>
#include <iomanip>

#include "objectmemory.hpp"
#include "marshal.hpp"

#include "object_utils.hpp"

#include <tommath.h>
#include <gdtoa.h>

#include "builtin/array.hpp"
#include "builtin/compiledmethod.hpp"
#include "builtin/encoding.hpp"
#include "builtin/fixnum.hpp"
#include "builtin/float.hpp"
#include "builtin/iseq.hpp"
#include "builtin/string.hpp"
#include "builtin/symbol.hpp"
#include "builtin/tuple.hpp"

#include "detection.hpp"

#define STACK_BUF_SZ 1024

namespace rubinius {

  Object* UnMarshaller::get_constant() {
    char stack_data[STACK_BUF_SZ];
    char *malloc_data = NULL;
    char *data = stack_data;

    size_t count;

    stream >> count;
    stream.get();

    if(count >= STACK_BUF_SZ) {
      malloc_data = (char*)malloc(count + 1);
      data = malloc_data;
    }

    stream.read(data, count + 1);
    data[count] = 0; // clamp

    Object* cls = state->vm()->path2class(data);

    if(malloc_data) {
      free(malloc_data);
    }
    return cls;
  }

  Object* UnMarshaller::get_encoding() {
    char stack_data[STACK_BUF_SZ];
    char *malloc_data = NULL;
    char *data = stack_data;
    size_t count;

    stream >> count;
    stream.get();

    if(count >= STACK_BUF_SZ) {
      malloc_data = (char*)malloc(count + 1);
      data = malloc_data;
    }

    stream.read(data, count + 1);
    data[count] = 0; // clamp

    if(count > 0) {
      Encoding* enc = Encoding::find(state, data);
      if(malloc_data) {
        free(malloc_data);
      }
      return enc;
    } else {
      return cNil;
    }
  }

  Object* UnMarshaller::get_int() {
    std::string data;
    stream >> data;

    return Bignum::from_string(state, data.c_str(), 16);
  }

  String* UnMarshaller::get_string() {
    size_t count;

    Encoding* enc = try_as<Encoding>(unmarshal());

    stream >> count;
    // String::create adds room for a trailing null on its own
    // using pinned here allows later stages to optimize these literal
    // strings better.
    String* str = String::create(state, NULL, count);

    stream.get(); // read off newline
    stream.read(reinterpret_cast<char*>(str->byte_address()), count);
    stream.get(); // read off newline

    if(enc) str->encoding(state, enc);

    return str;
  }

  Symbol* UnMarshaller::get_symbol() {
    char stack_data[STACK_BUF_SZ];
    char *malloc_data = NULL;
    char *data = stack_data;
    size_t count;

    stream >> count;
    stream.get();

    if(count >= STACK_BUF_SZ) {
      malloc_data = (char*)malloc(count + 1);
      data = malloc_data;
    }

    stream.read(data, count + 1);
    data[count] = 0; // clamp

    Symbol* sym = state->symbol(data);

    if(malloc_data) {
      free(malloc_data);
    }

    return sym;
  }

  Tuple* UnMarshaller::get_tuple() {
    size_t count;
    stream >> count;

    Tuple* tup = Tuple::create(state, count);

    for(size_t i = 0; i < count; i++) {
      tup->put(state, i, unmarshal());
    }

    return tup;
  }

#define FLOAT_EXP_OFFSET    58

  Float* UnMarshaller::get_float() {
    std::string line;
    const char* data;

    // discard the delimiter
    stream.get();

    std::getline(stream, line);
    if(stream.fail()) {
      Exception::type_error(state, "Unable to unmarshal Float: failed to read value");
    }

    data = line.c_str();
    if(data[0] == ' ') {
      double x;
      long   e;

      x = ::ruby_strtod(data, NULL);
      e = strtol(data+FLOAT_EXP_OFFSET, NULL, 10);

      // This is necessary because exp2(1024) yields inf
      if(e == 1024) {
        double root_exp = ::exp2(512);
        return Float::create(state, x * root_exp * root_exp);
      } else {
        return Float::create(state, x * ::exp2(e));
      }
    } else {
      // avoid compiler warning
      double zero = 0.0;
      double val = 0.0;

      if(!strncasecmp(data, "Infinity", 8U)) {
        val = 1.0;
      } else if(!strncasecmp(data, "-Infinity", 9U)) {
        val = -1.0;
      } else if(!strncasecmp(data, "NaN", 3U)) {
        val = zero;
      } else {
        Exception::type_error(state, "Unable to unmarshal Float: invalid format");
      }

      return Float::create(state, val / zero);
    }
  }

  InstructionSequence* UnMarshaller::get_iseq() {
    size_t count;
    long op;
    char data[32];
    stream >> count;

    // Read off newline
    stream.get();

    InstructionSequence* iseq = InstructionSequence::create(state, count);
    Tuple* ops = iseq->opcodes();

    for(size_t i = 0; i < count; i++) {
      stream.getline(data, 32);
      op = strtol(data, NULL, 10);
      ops->put(state, i, Fixnum::from(op));
    }

    iseq->post_marshal(state);

    return iseq;
  }

  CompiledMethod* UnMarshaller::get_cmethod() {
    size_t ver;
    stream >> ver;

    CompiledMethod* cm = CompiledMethod::create(state);

    cm->metadata(state, unmarshal());
    cm->primitive(state, (Symbol*)unmarshal());
    cm->name(state, (Symbol*)unmarshal());
    cm->iseq(state, (InstructionSequence*)unmarshal());
    cm->stack_size(state, (Fixnum*)unmarshal());
    cm->local_count(state, (Fixnum*)unmarshal());
    cm->required_args(state, (Fixnum*)unmarshal());
    cm->post_args(state, (Fixnum*)unmarshal());
    cm->total_args(state, (Fixnum*)unmarshal());
    cm->splat(state, unmarshal());
    cm->literals(state, (Tuple*)unmarshal());
    cm->lines(state, (Tuple*)unmarshal());
    cm->file(state, (Symbol*)unmarshal());
    cm->local_names(state, (Tuple*)unmarshal());

    cm->post_marshal(state);

    return cm;
  }

  Object* UnMarshaller::unmarshal() {
    char code;

    stream >> code;

    switch(code) {
    case 'n':
      return cNil;
    case 't':
      return cTrue;
    case 'f':
      return cFalse;
    case 'I':
      return get_int();
    case 's':
      return get_string();
    case 'x':
      return get_symbol();
    case 'p':
      return get_tuple();
    case 'd':
      return get_float();
    case 'i':
      return get_iseq();
    case 'M':
      return get_cmethod();
    case 'c':
      return get_constant();
    case 'E':
      return get_encoding();
    default:
      std::string str = "unknown marshal code: ";
      str.append( 1, code );
      Exception::type_error(state, str.c_str());
      return cNil;    // make compiler happy
    }
  }
}
<|endoftext|>


<commit_before>#include "master.hpp"

namespace factor
{

THREADHANDLE start_thread(void *(*start_routine)(void *),void *args)
{
	pthread_attr_t attr;
	pthread_t thread;
	if (pthread_attr_init (&attr) != 0)
		fatal_error("pthread_attr_init() failed",0);
	if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE) != 0)
		fatal_error("pthread_attr_setdetachstate() failed",0);
	if (pthread_create (&thread, &attr, start_routine, args) != 0)
		fatal_error("pthread_create() failed",0);
	pthread_attr_destroy(&attr);
	return thread;
}

pthread_key_t current_vm_tls_key = 0;

void init_platform_globals()
{
	if(pthread_key_create(&current_vm_tls_key, NULL) != 0)
		fatal_error("pthread_key_create() failed",0);
}

void register_vm_with_thread(factor_vm *vm)
{
	pthread_setspecific(current_vm_tls_key,vm);
}

factor_vm *current_vm()
{
	factor_vm *vm = (factor_vm*)pthread_getspecific(current_vm_tls_key);
	assert(vm != NULL);
	return vm;
}

static void *null_dll;

u64 system_micros()
{
	struct timeval t;
	gettimeofday(&t,NULL);
	return (u64)t.tv_sec * 1000000 + t.tv_usec;
}

void sleep_nanos(u64 nsec)
{
	timespec ts;
	timespec ts_rem;
	int ret;
	ts.tv_sec = nsec / 1000000000;
	ts.tv_nsec = nsec % 1000000000;
	ret = nanosleep(&ts,&ts_rem);
	while(ret == -1 && errno == EINTR)
	{
		memcpy(&ts, &ts_rem, sizeof(ts));
		ret = nanosleep(&ts, &ts_rem);
	}

	if(ret == -1)
		fatal_error("nanosleep failed", 0);
}

void factor_vm::init_ffi()
{
	/* NULL_DLL is "libfactor.dylib" for OS X and NULL for generic Unix */
	null_dll = dlopen(NULL_DLL,RTLD_LAZY);
}

void factor_vm::ffi_dlopen(dll *dll)
{
	dll->handle = dlopen(alien_offset(dll->path), RTLD_LAZY);
}

void *factor_vm::ffi_dlsym(dll *dll, symbol_char *symbol)
{
	void *handle = (dll == NULL ? null_dll : dll->handle);
	return dlsym(handle,symbol);
}

void factor_vm::ffi_dlclose(dll *dll)
{
	if(dlclose(dll->handle))
		general_error(ERROR_FFI,false_object,false_object);
	dll->handle = NULL;
}

void factor_vm::primitive_existsp()
{
	struct stat sb;
	char *path = (char *)(untag_check<byte_array>(ctx->pop()) + 1);
	ctx->push(tag_boolean(stat(path,&sb) >= 0));
}

void factor_vm::move_file(const vm_char *path1, const vm_char *path2)
{
	int ret = 0;
	do {
		ret = rename((path1),(path2));
	} while(ret < 0 && errno == EINTR);
	if(ret < 0)
		general_error(ERROR_IO,tag_fixnum(errno),false_object);
}

segment::segment(cell size_, bool executable_p)
{
	size = size_;

	int pagesize = getpagesize();

	int prot;
	if(executable_p)
		prot = (PROT_READ | PROT_WRITE | PROT_EXEC);
	else
		prot = (PROT_READ | PROT_WRITE);

	char *array = (char *)mmap(NULL,pagesize + size + pagesize,prot,MAP_ANON | MAP_PRIVATE,-1,0);
	if(array == (char*)-1) out_of_memory();

	if(mprotect(array,pagesize,PROT_NONE) == -1)
		fatal_error("Cannot protect low guard page",(cell)array);

	if(mprotect(array + pagesize + size,pagesize,PROT_NONE) == -1)
		fatal_error("Cannot protect high guard page",(cell)array);

	start = (cell)(array + pagesize);
	end = start + size;
}

segment::~segment()
{
	int pagesize = getpagesize();
	int retval = munmap((void*)(start - pagesize),pagesize + size + pagesize);
	if(retval)
		fatal_error("Segment deallocation failed",0);
}

void factor_vm::dispatch_signal(void *uap, void (handler)())
{
	UAP_STACK_POINTER(uap) = (UAP_STACK_POINTER_TYPE)fix_callstack_top((stack_frame *)UAP_STACK_POINTER(uap));
	UAP_PROGRAM_COUNTER(uap) = (cell)handler;

	signal_callstack_top = (stack_frame *)UAP_STACK_POINTER(uap);
}

void memory_signal_handler(int signal, siginfo_t *siginfo, void *uap)
{
	factor_vm *vm = current_vm();
	vm->signal_fault_addr = (cell)siginfo->si_addr;
	vm->dispatch_signal(uap,factor::memory_signal_handler_impl);
}

void misc_signal_handler(int signal, siginfo_t *siginfo, void *uap)
{
	factor_vm *vm = current_vm();
	vm->signal_number = signal;
	vm->dispatch_signal(uap,factor::misc_signal_handler_impl);
}

void fpe_signal_handler(int signal, siginfo_t *siginfo, void *uap)
{
	factor_vm *vm = current_vm();
	vm->signal_number = signal;
	vm->signal_fpu_status = fpu_status(uap_fpu_status(uap));
	uap_clear_fpu_status(uap);

	vm->dispatch_signal(uap,
		(siginfo->si_code == FPE_INTDIV || siginfo->si_code == FPE_INTOVF)
		? factor::misc_signal_handler_impl
		: factor::fp_signal_handler_impl);
}

static void sigaction_safe(int signum, const struct sigaction *act, struct sigaction *oldact)
{
	int ret;
	do
	{
		ret = sigaction(signum, act, oldact);
	}
	while(ret == -1 && errno == EINTR);

	if(ret == -1)
		fatal_error("sigaction failed", 0);
}

void factor_vm::unix_init_signals()
{
	signal_callstack_seg = new segment(callstack_size,false);

	stack_t signal_callstack;
	signal_callstack.ss_sp = (void *)signal_callstack_seg->start;
	signal_callstack.ss_size = signal_callstack_seg->size;
	signal_callstack.ss_flags = 0;

	if(sigaltstack(&signal_callstack,(stack_t *)NULL) < 0)
		fatal_error("sigaltstack() failed",0);

	struct sigaction memory_sigaction;
	struct sigaction misc_sigaction;
	struct sigaction fpe_sigaction;
	struct sigaction ignore_sigaction;

	memset(&memory_sigaction,0,sizeof(struct sigaction));
	sigemptyset(&memory_sigaction.sa_mask);
	memory_sigaction.sa_sigaction = memory_signal_handler;
	memory_sigaction.sa_flags = SA_SIGINFO | SA_ONSTACK;

	sigaction_safe(SIGBUS,&memory_sigaction,NULL);
	sigaction_safe(SIGSEGV,&memory_sigaction,NULL);

	memset(&fpe_sigaction,0,sizeof(struct sigaction));
	sigemptyset(&fpe_sigaction.sa_mask);
	fpe_sigaction.sa_sigaction = fpe_signal_handler;
	fpe_sigaction.sa_flags = SA_SIGINFO | SA_ONSTACK;

	sigaction_safe(SIGFPE,&fpe_sigaction,NULL);

	memset(&misc_sigaction,0,sizeof(struct sigaction));
	sigemptyset(&misc_sigaction.sa_mask);
	misc_sigaction.sa_sigaction = misc_signal_handler;
	misc_sigaction.sa_flags = SA_SIGINFO | SA_ONSTACK;

	sigaction_safe(SIGQUIT,&misc_sigaction,NULL);
	sigaction_safe(SIGILL,&misc_sigaction,NULL);

	memset(&ignore_sigaction,0,sizeof(struct sigaction));
	sigemptyset(&ignore_sigaction.sa_mask);
	ignore_sigaction.sa_handler = SIG_IGN;
	sigaction_safe(SIGPIPE,&ignore_sigaction,NULL);
}

/* On Unix, shared fds such as stdin cannot be set to non-blocking mode
(http://homepages.tesco.net/J.deBoynePollard/FGA/dont-set-shared-file-descriptors-to-non-blocking-mode.html)
so we kludge around this by spawning a thread, which waits on a control pipe
for a signal, upon receiving this signal it reads one block of data from stdin
and writes it to a data pipe. Upon completion, it writes a 4-byte integer to
the size pipe, indicating how much data was written to the data pipe.

The read end of the size pipe can be set to non-blocking. */
extern "C" {
	int stdin_read;
	int stdin_write;

	int control_read;
	int control_write;

	int size_read;
	int size_write;
}

void safe_close(int fd)
{
	if(close(fd) < 0)
		fatal_error("error closing fd",errno);
}

bool check_write(int fd, void *data, ssize_t size)
{
	if(write(fd,data,size) == size)
		return true;
	else
	{
		if(errno == EINTR)
			return check_write(fd,data,size);
		else
			return false;
	}
}

void safe_write(int fd, void *data, ssize_t size)
{
	if(!check_write(fd,data,size))
		fatal_error("error writing fd",errno);
}

bool safe_read(int fd, void *data, ssize_t size)
{
	ssize_t bytes = read(fd,data,size);
	if(bytes < 0)
	{
		if(errno == EINTR)
			return safe_read(fd,data,size);
		else
		{
			fatal_error("error reading fd",errno);
			return false;
		}
	}
	else
		return (bytes == size);
}

void *stdin_loop(void *arg)
{
	unsigned char buf[4096];
	bool loop_running = true;

	while(loop_running)
	{
		if(!safe_read(control_read,buf,1))
			break;

		if(buf[0] != 'X')
			fatal_error("stdin_loop: bad data on control fd",buf[0]);

		for(;;)
		{
			ssize_t bytes = read(0,buf,sizeof(buf));
			if(bytes < 0)
			{
				if(errno == EINTR)
					continue;
				else
				{
					loop_running = false;
					break;
				}
			}
			else if(bytes >= 0)
			{
				safe_write(size_write,&bytes,sizeof(bytes));

				if(!check_write(stdin_write,buf,bytes))
					loop_running = false;
				break;
			}
		}
	}

	safe_close(stdin_write);
	safe_close(control_read);

	return NULL;
}

void open_console()
{
	int filedes[2];

	if(pipe(filedes) < 0)
		fatal_error("Error opening control pipe",errno);

	control_read = filedes[0];
	control_write = filedes[1];

	if(pipe(filedes) < 0)
		fatal_error("Error opening size pipe",errno);

	size_read = filedes[0];
	size_write = filedes[1];

	if(pipe(filedes) < 0)
		fatal_error("Error opening stdin pipe",errno);

	stdin_read = filedes[0];
	stdin_write = filedes[1];

	start_thread(stdin_loop,NULL);
}

VM_C_API void wait_for_stdin()
{
	if(write(control_write,"X",1) != 1)
	{
		if(errno == EINTR)
			wait_for_stdin();
		else
			fatal_error("Error writing control fd",errno);
	}
}

}
<commit_msg>vm: fix compilation on FreeBSD<commit_after>#include "master.hpp"

namespace factor
{

THREADHANDLE start_thread(void *(*start_routine)(void *),void *args)
{
	pthread_attr_t attr;
	pthread_t thread;
	if (pthread_attr_init (&attr) != 0)
		fatal_error("pthread_attr_init() failed",0);
	if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE) != 0)
		fatal_error("pthread_attr_setdetachstate() failed",0);
	if (pthread_create (&thread, &attr, start_routine, args) != 0)
		fatal_error("pthread_create() failed",0);
	pthread_attr_destroy(&attr);
	return thread;
}

pthread_key_t current_vm_tls_key = 0;

void init_platform_globals()
{
	if(pthread_key_create(&current_vm_tls_key, NULL) != 0)
		fatal_error("pthread_key_create() failed",0);
}

void register_vm_with_thread(factor_vm *vm)
{
	pthread_setspecific(current_vm_tls_key,vm);
}

factor_vm *current_vm()
{
	factor_vm *vm = (factor_vm*)pthread_getspecific(current_vm_tls_key);
	assert(vm != NULL);
	return vm;
}

static void *null_dll;

u64 system_micros()
{
	struct timeval t;
	gettimeofday(&t,NULL);
	return (u64)t.tv_sec * 1000000 + t.tv_usec;
}

void sleep_nanos(u64 nsec)
{
	timespec ts;
	timespec ts_rem;
	int ret;
	ts.tv_sec = nsec / 1000000000;
	ts.tv_nsec = nsec % 1000000000;
	ret = nanosleep(&ts,&ts_rem);
	while(ret == -1 && errno == EINTR)
	{
		memcpy(&ts, &ts_rem, sizeof(ts));
		ret = nanosleep(&ts, &ts_rem);
	}

	if(ret == -1)
		fatal_error("nanosleep failed", 0);
}

void factor_vm::init_ffi()
{
	/* NULL_DLL is "libfactor.dylib" for OS X and NULL for generic Unix */
	null_dll = dlopen(NULL_DLL,RTLD_LAZY);
}

void factor_vm::ffi_dlopen(dll *dll)
{
	dll->handle = dlopen(alien_offset(dll->path), RTLD_LAZY);
}

void *factor_vm::ffi_dlsym(dll *dll, symbol_char *symbol)
{
	void *handle = (dll == NULL ? null_dll : dll->handle);
	return dlsym(handle,symbol);
}

void factor_vm::ffi_dlclose(dll *dll)
{
	if(dlclose(dll->handle))
		general_error(ERROR_FFI,false_object,false_object);
	dll->handle = NULL;
}

void factor_vm::primitive_existsp()
{
	struct stat sb;
	char *path = (char *)(untag_check<byte_array>(ctx->pop()) + 1);
	ctx->push(tag_boolean(stat(path,&sb) >= 0));
}

void factor_vm::move_file(const vm_char *path1, const vm_char *path2)
{
	int ret = 0;
	do
	{
		ret = rename((path1),(path2));
	}
	while(ret < 0 && errno == EINTR);

	if(ret < 0)
		general_error(ERROR_IO,tag_fixnum(errno),false_object);
}

segment::segment(cell size_, bool executable_p)
{
	size = size_;

	int pagesize = getpagesize();

	int prot;
	if(executable_p)
		prot = (PROT_READ | PROT_WRITE | PROT_EXEC);
	else
		prot = (PROT_READ | PROT_WRITE);

	char *array = (char *)mmap(NULL,pagesize + size + pagesize,prot,MAP_ANON | MAP_PRIVATE,-1,0);
	if(array == (char*)-1) out_of_memory();

	if(mprotect(array,pagesize,PROT_NONE) == -1)
		fatal_error("Cannot protect low guard page",(cell)array);

	if(mprotect(array + pagesize + size,pagesize,PROT_NONE) == -1)
		fatal_error("Cannot protect high guard page",(cell)array);

	start = (cell)(array + pagesize);
	end = start + size;
}

segment::~segment()
{
	int pagesize = getpagesize();
	int retval = munmap((void*)(start - pagesize),pagesize + size + pagesize);
	if(retval)
		fatal_error("Segment deallocation failed",0);
}

void factor_vm::dispatch_signal(void *uap, void (handler)())
{
	UAP_STACK_POINTER(uap) = (UAP_STACK_POINTER_TYPE)fix_callstack_top((stack_frame *)UAP_STACK_POINTER(uap));
	UAP_PROGRAM_COUNTER(uap) = (cell)handler;

	signal_callstack_top = (stack_frame *)UAP_STACK_POINTER(uap);
}

void memory_signal_handler(int signal, siginfo_t *siginfo, void *uap)
{
	factor_vm *vm = current_vm();
	vm->signal_fault_addr = (cell)siginfo->si_addr;
	vm->dispatch_signal(uap,factor::memory_signal_handler_impl);
}

void misc_signal_handler(int signal, siginfo_t *siginfo, void *uap)
{
	factor_vm *vm = current_vm();
	vm->signal_number = signal;
	vm->dispatch_signal(uap,factor::misc_signal_handler_impl);
}

void fpe_signal_handler(int signal, siginfo_t *siginfo, void *uap)
{
	factor_vm *vm = current_vm();
	vm->signal_number = signal;
	vm->signal_fpu_status = fpu_status(uap_fpu_status(uap));
	uap_clear_fpu_status(uap);

	vm->dispatch_signal(uap,
		(siginfo->si_code == FPE_INTDIV || siginfo->si_code == FPE_INTOVF)
		? factor::misc_signal_handler_impl
		: factor::fp_signal_handler_impl);
}

static void sigaction_safe(int signum, const struct sigaction *act, struct sigaction *oldact)
{
	int ret;
	do
	{
		ret = sigaction(signum, act, oldact);
	}
	while(ret == -1 && errno == EINTR);

	if(ret == -1)
		fatal_error("sigaction failed", 0);
}

void factor_vm::unix_init_signals()
{
	signal_callstack_seg = new segment(callstack_size,false);

	stack_t signal_callstack;
	signal_callstack.ss_sp = (char *)signal_callstack_seg->start;
	signal_callstack.ss_size = signal_callstack_seg->size;
	signal_callstack.ss_flags = 0;

	if(sigaltstack(&signal_callstack,(stack_t *)NULL) < 0)
		fatal_error("sigaltstack() failed",0);

	struct sigaction memory_sigaction;
	struct sigaction misc_sigaction;
	struct sigaction fpe_sigaction;
	struct sigaction ignore_sigaction;

	memset(&memory_sigaction,0,sizeof(struct sigaction));
	sigemptyset(&memory_sigaction.sa_mask);
	memory_sigaction.sa_sigaction = memory_signal_handler;
	memory_sigaction.sa_flags = SA_SIGINFO | SA_ONSTACK;

	sigaction_safe(SIGBUS,&memory_sigaction,NULL);
	sigaction_safe(SIGSEGV,&memory_sigaction,NULL);

	memset(&fpe_sigaction,0,sizeof(struct sigaction));
	sigemptyset(&fpe_sigaction.sa_mask);
	fpe_sigaction.sa_sigaction = fpe_signal_handler;
	fpe_sigaction.sa_flags = SA_SIGINFO | SA_ONSTACK;

	sigaction_safe(SIGFPE,&fpe_sigaction,NULL);

	memset(&misc_sigaction,0,sizeof(struct sigaction));
	sigemptyset(&misc_sigaction.sa_mask);
	misc_sigaction.sa_sigaction = misc_signal_handler;
	misc_sigaction.sa_flags = SA_SIGINFO | SA_ONSTACK;

	sigaction_safe(SIGQUIT,&misc_sigaction,NULL);
	sigaction_safe(SIGILL,&misc_sigaction,NULL);

	memset(&ignore_sigaction,0,sizeof(struct sigaction));
	sigemptyset(&ignore_sigaction.sa_mask);
	ignore_sigaction.sa_handler = SIG_IGN;
	sigaction_safe(SIGPIPE,&ignore_sigaction,NULL);
}

/* On Unix, shared fds such as stdin cannot be set to non-blocking mode
(http://homepages.tesco.net/J.deBoynePollard/FGA/dont-set-shared-file-descriptors-to-non-blocking-mode.html)
so we kludge around this by spawning a thread, which waits on a control pipe
for a signal, upon receiving this signal it reads one block of data from stdin
and writes it to a data pipe. Upon completion, it writes a 4-byte integer to
the size pipe, indicating how much data was written to the data pipe.

The read end of the size pipe can be set to non-blocking. */
extern "C" {
	int stdin_read;
	int stdin_write;

	int control_read;
	int control_write;

	int size_read;
	int size_write;
}

void safe_close(int fd)
{
	if(close(fd) < 0)
		fatal_error("error closing fd",errno);
}

bool check_write(int fd, void *data, ssize_t size)
{
	if(write(fd,data,size) == size)
		return true;
	else
	{
		if(errno == EINTR)
			return check_write(fd,data,size);
		else
			return false;
	}
}

void safe_write(int fd, void *data, ssize_t size)
{
	if(!check_write(fd,data,size))
		fatal_error("error writing fd",errno);
}

bool safe_read(int fd, void *data, ssize_t size)
{
	ssize_t bytes = read(fd,data,size);
	if(bytes < 0)
	{
		if(errno == EINTR)
			return safe_read(fd,data,size);
		else
		{
			fatal_error("error reading fd",errno);
			return false;
		}
	}
	else
		return (bytes == size);
}

void *stdin_loop(void *arg)
{
	unsigned char buf[4096];
	bool loop_running = true;

	while(loop_running)
	{
		if(!safe_read(control_read,buf,1))
			break;

		if(buf[0] != 'X')
			fatal_error("stdin_loop: bad data on control fd",buf[0]);

		for(;;)
		{
			ssize_t bytes = read(0,buf,sizeof(buf));
			if(bytes < 0)
			{
				if(errno == EINTR)
					continue;
				else
				{
					loop_running = false;
					break;
				}
			}
			else if(bytes >= 0)
			{
				safe_write(size_write,&bytes,sizeof(bytes));

				if(!check_write(stdin_write,buf,bytes))
					loop_running = false;
				break;
			}
		}
	}

	safe_close(stdin_write);
	safe_close(control_read);

	return NULL;
}

void open_console()
{
	int filedes[2];

	if(pipe(filedes) < 0)
		fatal_error("Error opening control pipe",errno);

	control_read = filedes[0];
	control_write = filedes[1];

	if(pipe(filedes) < 0)
		fatal_error("Error opening size pipe",errno);

	size_read = filedes[0];
	size_write = filedes[1];

	if(pipe(filedes) < 0)
		fatal_error("Error opening stdin pipe",errno);

	stdin_read = filedes[0];
	stdin_write = filedes[1];

	start_thread(stdin_loop,NULL);
}

VM_C_API void wait_for_stdin()
{
	if(write(control_write,"X",1) != 1)
	{
		if(errno == EINTR)
			wait_for_stdin();
		else
			fatal_error("Error writing control fd",errno);
	}
}

}
<|endoftext|>


<commit_before>struct Point {
  int x;
  int y;
};

struct Base1 {
  int b1;
};

struct Base2 {
  int b2;
};

struct DerivedSI : Base1 {
  int dsi;
};

struct DerivedMI : Base1, Base2 {
  int dmi;
};

struct DerivedVI : virtual Base1 {
  int dvi;
};

void Locals() {
  Point pt = {  //$ussa=pt
    1,  //$ussa=pt[0..4)<int>
    2  //$ussa=pt[4..8)<int>
  };
  int i = pt.x;  //$ussa=pt[0..4)<int>
  i = pt.y;  //$ussa=pt[4..8)<int>
  int* p = &pt.x;
  i = *p;  //$ussa=pt[0..4)<int>
  p = &pt.y;
  i = *p;  //$ussa=pt[4..8)<int>
}

void PointsTo(
  int a,         //$raw,ussa=a
  Point& b,      //$raw,ussa=b $ussa=*b
  Point* c,      //$raw,ussa=c $ussa=*c
  int* d,        //$raw,ussa=d $ussa=*d
  DerivedSI* e,  //$raw,ussa=e $ussa=*e
  DerivedMI* f,  //$raw,ussa=f $ussa=*f
  DerivedVI* g   //$raw,ussa=g $ussa=*g
) {

  int i = a;  //$raw,ussa=a
  i = *&a;  //$raw,ussa=a
  i = *(&a + 0);  //$raw,ussa=a
  i = b.x;  //$raw,ussa=b $ussa=*b[0..4)<int>
  i = b.y;  //$raw,ussa=b $ussa=*b[4..8)<int>
  i = c->x;  //$raw,ussa=c $ussa=*c[0..4)<int>
  i = c->y;  //$raw,ussa=c $ussa=*c[4..8)<int>
  i = *d;  //$raw,ussa=d $ussa=*d[0..4)<int>
  i = *(d + 0);  //$raw,ussa=d $ussa=*d[0..4)<int>
  i = d[5];  //$raw,ussa=d $ussa=*d[20..24)<int>
  i = 5[d];  //$raw,ussa=d $ussa=*d[20..24)<int>
  i = d[a];  //$raw,ussa=d $raw,ussa=a $ussa=*d[?..?)<int>
  i = a[d];  //$raw,ussa=d $raw,ussa=a $ussa=*d[?..?)<int>

  int* p = &b.x;  //$raw,ussa=b
  i = *p;  //$ussa=*b[0..4)<int>
  p = &b.y;  //$raw,ussa=b
  i = *p;  //$ussa=*b[4..8)<int>
  p = &c->x;  //$raw,ussa=c
  i = *p;  //$ussa=*c[0..4)<int>
  p = &c->y;  //$raw,ussa=c
  i = *p;  //$ussa=*c[4..8)<int>
  p = &d[5];  //$raw,ussa=d
  i = *p;  //$ussa=*d[20..24)<int>
  p = &d[a];  //$raw,ussa=d $raw,ussa=a
  i = *p;  //$ussa=*d[?..?)<int>

  Point* q = &c[a];  //$raw,ussa=c $raw,ussa=a
  i = q->x;  //$ussa=*c[?..?)<int>
  i = q->y;  //$ussa=*c[?..?)<int>

  i = e->b1;  //$raw,ussa=e $ussa=*e[0..4)<int>
  i = e->dsi;  //$raw,ussa=e $ussa=*e[4..8)<int>
  i = f->b1;  //$raw,ussa=f $ussa=*f[0..4)<int>
  i = f->b2;  //$raw,ussa=f $ussa=*f[4..8)<int>
  i = f->dmi;  //$raw,ussa=f $ussa=*f[8..12)<int>
  i = g->b1;  //$raw,ussa=g $ussa=*g[?..?)<int>
  i = g->dvi;  //$raw,ussa=g $ussa=*g[8..12)<int>
}<commit_msg>C++: Update IR inline-expectation tests<commit_after>struct Point {
  int x;
  int y;
};

struct Base1 {
  int b1;
};

struct Base2 {
  int b2;
};

struct DerivedSI : Base1 {
  int dsi;
};

struct DerivedMI : Base1, Base2 {
  int dmi;
};

struct DerivedVI : virtual Base1 {
  int dvi;
};

void Locals() {
  Point pt = {  //$ussa=pt
    1,  //$ussa=pt[0..4)<int>
    2  //$ussa=pt[4..8)<int>
  };
  int i = pt.x;  //$ussa=pt[0..4)<int>
  i = pt.y;  //$ussa=pt[4..8)<int>
  int* p = &pt.x;
  i = *p;  //$ussa=pt[0..4)<int>
  p = &pt.y;
  i = *p;  //$ussa=pt[4..8)<int>
}

void PointsTo(
  int a,         //$raw,ussa=a
  Point& b,      //$raw,ussa=b ussa=*b
  Point* c,      //$raw,ussa=c ussa=*c
  int* d,        //$raw,ussa=d ussa=*d
  DerivedSI* e,  //$raw,ussa=e ussa=*e
  DerivedMI* f,  //$raw,ussa=f ussa=*f
  DerivedVI* g   //$raw,ussa=g ussa=*g
) {

  int i = a;  //$raw,ussa=a
  i = *&a;  //$raw,ussa=a
  i = *(&a + 0);  //$raw,ussa=a
  i = b.x;  //$raw,ussa=b ussa=*b[0..4)<int>
  i = b.y;  //$raw,ussa=b ussa=*b[4..8)<int>
  i = c->x;  //$raw,ussa=c ussa=*c[0..4)<int>
  i = c->y;  //$raw,ussa=c ussa=*c[4..8)<int>
  i = *d;  //$raw,ussa=d ussa=*d[0..4)<int>
  i = *(d + 0);  //$raw,ussa=d ussa=*d[0..4)<int>
  i = d[5];  //$raw,ussa=d ussa=*d[20..24)<int>
  i = 5[d];  //$raw,ussa=d ussa=*d[20..24)<int>
  i = d[a];  //$raw,ussa=d raw,ussa=a ussa=*d[?..?)<int>
  i = a[d];  //$raw,ussa=d raw,ussa=a ussa=*d[?..?)<int>

  int* p = &b.x;  //$raw,ussa=b
  i = *p;  //$ussa=*b[0..4)<int>
  p = &b.y;  //$raw,ussa=b
  i = *p;  //$ussa=*b[4..8)<int>
  p = &c->x;  //$raw,ussa=c
  i = *p;  //$ussa=*c[0..4)<int>
  p = &c->y;  //$raw,ussa=c
  i = *p;  //$ussa=*c[4..8)<int>
  p = &d[5];  //$raw,ussa=d
  i = *p;  //$ussa=*d[20..24)<int>
  p = &d[a];  //$raw,ussa=d raw,ussa=a
  i = *p;  //$ussa=*d[?..?)<int>

  Point* q = &c[a];  //$raw,ussa=c raw,ussa=a
  i = q->x;  //$ussa=*c[?..?)<int>
  i = q->y;  //$ussa=*c[?..?)<int>

  i = e->b1;  //$raw,ussa=e ussa=*e[0..4)<int>
  i = e->dsi;  //$raw,ussa=e ussa=*e[4..8)<int>
  i = f->b1;  //$raw,ussa=f ussa=*f[0..4)<int>
  i = f->b2;  //$raw,ussa=f ussa=*f[4..8)<int>
  i = f->dmi;  //$raw,ussa=f ussa=*f[8..12)<int>
  i = g->b1;  //$raw,ussa=g ussa=*g[?..?)<int>
  i = g->dvi;  //$raw,ussa=g ussa=*g[8..12)<int>
}<|endoftext|>


<commit_before>#include "findwidget.h"
#include "ui_findwidget.h"
#include "utils_history.h"
#include "findconfig.h"
#include "mainwindow.h"
#include <QComboBox>
#include <QLineEdit>

void FindWidget::init ()
{
	m_ui->setupUi(this);

	QStyle const * const style = QApplication::style();
	connect(m_ui->findBox, SIGNAL(editTextChanged(QString)), this, SLOT(onEditTextChanged(QString)));

	QLineEdit * le = m_ui->findBox->lineEdit();
	connect(le, SIGNAL(returnPressed()), this, SLOT(onReturnPressed()));
	connect(m_ui->selectButton, SIGNAL(clicked()), this, SLOT(onFindAllSelect()));
	connect(m_ui->refsButton, SIGNAL(clicked()), this, SLOT(onFindAllRefs()));
	connect(m_ui->cloneButton, SIGNAL(clicked()), this, SLOT(onFindAllClone()));
	connect(m_ui->cancelButton, SIGNAL(clicked()), this, SLOT(onCancel()));
	connect(m_ui->nextButton, SIGNAL(clicked()), this, SLOT(onFindNext()));
	connect(m_ui->prevButton, SIGNAL(clicked()), this, SLOT(onFindPrev()));

	setAutoFillBackground(true);
}

FindWidget::FindWidget (MainWindow * mw, QWidget * parent)
	: QWidget(parent)
	, m_ui(new Ui::FindWidget)
	, m_main_window(mw)
	, m_aa(0)
	, m_moving_widget(true)
{
	hide();
	init();
}

FindWidget::FindWidget (QWidget * parent) // widget coming from Qt creator
	: QWidget(parent)
	, m_ui(new Ui::FindWidget)
	, m_main_window(0)
	, m_aa(0)
	, m_moving_widget(false)
{
	init();
}

FindWidget::~FindWidget ()
{
	delete m_ui;
}

void FindWidget::applyConfig (FindConfig & cfg)
{
	m_config = cfg;
	setConfigValuesToUI(m_config);
}

void FindWidget::applyConfig ()
{
	applyConfig(m_config);
}

void FindWidget::onCancel ()
{
	if (isMovingFindWidget())
	{
		if (isVisible())
		{
			QObject * o = parent();
			QWidget * w = qobject_cast<QWidget *>(o);
			w->setFocus();
			hide();
			setParent(m_main_window);
		}
		move(0,0);
	}
	else
	{
	}
}

void FindWidget::onActivate ()
{
	show();
	activateWindow();
	m_ui->findBox->setFocus();
	raise();
}

void FindWidget::onEditTextChanged (QString str)
{
	onResetRegexpState();
	//qDebug("find!");
}

void FindWidget::onReturnPressed ()
{
	//@TODO
	//m_config.saveHistory();
}

void FindWidget::focusNext ()
{
	QWidget * const curr =  qApp->focusWidget();
	QWidget * const next = curr->nextInFocusChain();
	next->setFocus(Qt::TabFocusReason);
}

void FindWidget::focusPrev ()
{
	QWidget * const curr =  qApp->focusWidget();
	QWidget * const prev = curr->previousInFocusChain();
	prev->setFocus(Qt::TabFocusReason);
}

void FindWidget::onFocusChanged (QWidget * old, QWidget * now)
{
	//m_find_widget->onFocusChanged(old, now);
}

void FindWidget::onResetRegexpState ()
{
	m_ui->findBox->setStyleSheet("");
	m_ui->findBox->setToolTip("");
}

void FindWidget::signalRegexpState (E_ExprState state, QString const & reason)
{
	if (state == e_ExprInvalid)
	{
		m_ui->findBox->setStyleSheet(
			"QComboBox {\
				 border: 1px solid red;\
				 border-radius: 3px;\
			}");

		m_ui->findBox->setToolTip(reason);
	}
	else
	{
		m_ui->findBox->setStyleSheet(
			"QComboBox {\
				 border: 1px solid green;\
				 border-radius: 3px;\
			}");
		m_ui->findBox->setToolTip("");
	}
}

void FindWidget::makeActionFind (QString const & str, Action & a)
{
	a.m_type = e_Find;
	//a.m_src_path = path();
	//a.m_src = this;
	if (m_aa)
		a.m_dst_path = m_aa->path();
	QVariant fc;
	fc.setValue(m_config);
	a.m_args.push_back(fc);
}

void FindWidget::find ()
{
	QString const str = m_ui->findBox->currentText();
	if (!str.isEmpty())
	{
		mentionStringInHistory_Ref(str, m_ui->findBox, m_config.m_history);
		m_ui->findBox->setCurrentIndex(m_ui->findBox->findText(str));
		setUIValuesToConfig(m_config);
		m_config.m_str = str;
		if (m_config.m_regexp)
		{
			m_config.m_regexp_val = QRegExp(m_config.m_str);
			if (m_config.m_regexp_val.isValid())
			{
				signalRegexpState(e_ExprValid, "");
			}
			else
			{
				QString const & reason = m_config.m_regexp_val.errorString();
				signalRegexpState(e_ExprInvalid, QString("regexp failed: ") + reason);
				return;
			}
		}
		Action a;
		makeActionFind(str, a);
		m_main_window->dockManager().handleAction(&a, e_Sync);
		QTimer::singleShot(750, this, SLOT(onResetRegexpState()));
	}

}

void FindWidget::find (bool select, bool refs, bool clone)
{
	m_config.m_next = 0;
	m_config.m_prev = 0;
	m_config.m_select = select;
	m_config.m_refs = refs;
	m_config.m_clone = clone;
	find();
}
void FindWidget::onFindAllSelect () { find(1, 0, 0); }
void FindWidget::onFindAllRefs () { find(0, 1, 0); }
void FindWidget::onFindAllClone () { find(0, 0, 1); }

void FindWidget::find (bool prev, bool next)
{
	m_config.m_next = next;
	m_config.m_prev = prev;
	m_config.m_select = 1;
	m_config.m_refs = 0;
	m_config.m_clone = 0;
	find();
}
void FindWidget::onFindNext () { find(0, 1); }
void FindWidget::onFindPrev () { find(1, 0); }

void FindWidget::clearUI ()
{
	m_ui->widgetComboBox->clear();
	m_ui->findBox->clear();
}

void FindWidget::setConfigValuesToUI (FindConfig const & cfg)
{
	clearUI();
	syncHistoryToWidget(m_ui->findBox, cfg.m_history);
	m_ui->caseCheckBox->setChecked(cfg.m_case_sensitive);
	m_ui->wholeWordCheckBox->setChecked(cfg.m_whole_word);
	m_ui->regexCheckBox->setChecked(cfg.m_regexp);
	m_ui->widgetComboBox->addItems(cfg.m_to_widgets);
}

void FindWidget::setUIValuesToConfig (FindConfig & cfg)
{
	cfg.m_case_sensitive = m_ui->caseCheckBox->isChecked();
	cfg.m_whole_word = m_ui->wholeWordCheckBox->isChecked();
	cfg.m_regexp = m_ui->regexCheckBox->isChecked();
	cfg.m_str = m_ui->findBox->currentText();
}

<commit_msg>* findwidget: nonmovable by default<commit_after>#include "findwidget.h"
#include "ui_findwidget.h"
#include "utils_history.h"
#include "findconfig.h"
#include "mainwindow.h"
#include <QComboBox>
#include <QLineEdit>

void FindWidget::init ()
{
	m_ui->setupUi(this);

	QStyle const * const style = QApplication::style();
	connect(m_ui->findBox, SIGNAL(editTextChanged(QString)), this, SLOT(onEditTextChanged(QString)));

	QLineEdit * le = m_ui->findBox->lineEdit();
	connect(le, SIGNAL(returnPressed()), this, SLOT(onReturnPressed()));
	connect(m_ui->selectButton, SIGNAL(clicked()), this, SLOT(onFindAllSelect()));
	connect(m_ui->refsButton, SIGNAL(clicked()), this, SLOT(onFindAllRefs()));
	connect(m_ui->cloneButton, SIGNAL(clicked()), this, SLOT(onFindAllClone()));
	connect(m_ui->cancelButton, SIGNAL(clicked()), this, SLOT(onCancel()));
	connect(m_ui->nextButton, SIGNAL(clicked()), this, SLOT(onFindNext()));
	connect(m_ui->prevButton, SIGNAL(clicked()), this, SLOT(onFindPrev()));

	setAutoFillBackground(true);
}

FindWidget::FindWidget (MainWindow * mw, QWidget * parent)
	: QWidget(parent)
	, m_ui(new Ui::FindWidget)
	, m_main_window(mw)
	, m_aa(0)
	, m_moving_widget(false)
{
	hide();
	init();
}

FindWidget::FindWidget (QWidget * parent) // widget coming from Qt creator
	: QWidget(parent)
	, m_ui(new Ui::FindWidget)
	, m_main_window(0)
	, m_aa(0)
	, m_moving_widget(false)
{
	hide();
	init();
}

FindWidget::~FindWidget ()
{
	delete m_ui;
}

void FindWidget::applyConfig (FindConfig & cfg)
{
	m_config = cfg;
	setConfigValuesToUI(m_config);
}

void FindWidget::applyConfig ()
{
	applyConfig(m_config);
}

void FindWidget::onCancel ()
{
	if (isMovingFindWidget())
	{
		if (isVisible())
		{
			QObject * o = parent();
			QWidget * w = qobject_cast<QWidget *>(o);
			w->setFocus();
			hide();
			setParent(m_main_window);
		}
		move(0,0);
	}
	else
	{
		QObject * o = parent();
		QWidget * w = qobject_cast<QWidget *>(o);
		w->setFocus();
		hide();
	}
}

void FindWidget::onActivate ()
{
	show();
	activateWindow();
	m_ui->findBox->setFocus();
	raise();
}

void FindWidget::onEditTextChanged (QString str)
{
	onResetRegexpState();
	//qDebug("find!");
}

void FindWidget::onReturnPressed ()
{
	//@TODO
	//m_config.saveHistory();
}

void FindWidget::focusNext ()
{
	QWidget * const curr =  qApp->focusWidget();
	QWidget * const next = curr->nextInFocusChain();
	next->setFocus(Qt::TabFocusReason);
}

void FindWidget::focusPrev ()
{
	QWidget * const curr =  qApp->focusWidget();
	QWidget * const prev = curr->previousInFocusChain();
	prev->setFocus(Qt::TabFocusReason);
}

void FindWidget::onFocusChanged (QWidget * old, QWidget * now)
{
	//m_find_widget->onFocusChanged(old, now);
}

void FindWidget::onResetRegexpState ()
{
	m_ui->findBox->setStyleSheet("");
	m_ui->findBox->setToolTip("");
}

void FindWidget::signalRegexpState (E_ExprState state, QString const & reason)
{
	if (state == e_ExprInvalid)
	{
		m_ui->findBox->setStyleSheet(
			"QComboBox {\
				 border: 1px solid red;\
				 border-radius: 3px;\
			}");

		m_ui->findBox->setToolTip(reason);
	}
	else
	{
		m_ui->findBox->setStyleSheet(
			"QComboBox {\
				 border: 1px solid green;\
				 border-radius: 3px;\
			}");
		m_ui->findBox->setToolTip("");
	}
}

void FindWidget::makeActionFind (QString const & str, Action & a)
{
	a.m_type = e_Find;
	//a.m_src_path = path();
	//a.m_src = this;
	if (m_aa)
		a.m_dst_path = m_aa->path();
	QVariant fc;
	fc.setValue(m_config);
	a.m_args.push_back(fc);
}

void FindWidget::find ()
{
	QString const str = m_ui->findBox->currentText();
	if (!str.isEmpty())
	{
		mentionStringInHistory_Ref(str, m_ui->findBox, m_config.m_history);
		m_ui->findBox->setCurrentIndex(m_ui->findBox->findText(str));
		setUIValuesToConfig(m_config);
		m_config.m_str = str;
		if (m_config.m_regexp)
		{
			m_config.m_regexp_val = QRegExp(m_config.m_str);
			if (m_config.m_regexp_val.isValid())
			{
				signalRegexpState(e_ExprValid, "");
			}
			else
			{
				QString const & reason = m_config.m_regexp_val.errorString();
				signalRegexpState(e_ExprInvalid, QString("regexp failed: ") + reason);
				return;
			}
		}
		Action a;
		makeActionFind(str, a);
		m_main_window->dockManager().handleAction(&a, e_Sync);
		QTimer::singleShot(750, this, SLOT(onResetRegexpState()));
	}

}

void FindWidget::find (bool select, bool refs, bool clone)
{
	m_config.m_next = 0;
	m_config.m_prev = 0;
	m_config.m_select = select;
	m_config.m_refs = refs;
	m_config.m_clone = clone;
	find();
}
void FindWidget::onFindAllSelect () { find(1, 0, 0); }
void FindWidget::onFindAllRefs () { find(0, 1, 0); }
void FindWidget::onFindAllClone () { find(0, 0, 1); }

void FindWidget::find (bool prev, bool next)
{
	m_config.m_next = next;
	m_config.m_prev = prev;
	m_config.m_select = 1;
	m_config.m_refs = 0;
	m_config.m_clone = 0;
	find();
}
void FindWidget::onFindNext () { find(0, 1); }
void FindWidget::onFindPrev () { find(1, 0); }

void FindWidget::clearUI ()
{
	m_ui->widgetComboBox->clear();
	m_ui->findBox->clear();
}

void FindWidget::setConfigValuesToUI (FindConfig const & cfg)
{
	clearUI();
	syncHistoryToWidget(m_ui->findBox, cfg.m_history);
	m_ui->caseCheckBox->setChecked(cfg.m_case_sensitive);
	m_ui->wholeWordCheckBox->setChecked(cfg.m_whole_word);
	m_ui->regexCheckBox->setChecked(cfg.m_regexp);
	m_ui->widgetComboBox->addItems(cfg.m_to_widgets);
}

void FindWidget::setUIValuesToConfig (FindConfig & cfg)
{
	cfg.m_case_sensitive = m_ui->caseCheckBox->isChecked();
	cfg.m_whole_word = m_ui->wholeWordCheckBox->isChecked();
	cfg.m_regexp = m_ui->regexCheckBox->isChecked();
	cfg.m_str = m_ui->findBox->currentText();
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: npwrap.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: pl $ $Date: 2002-01-15 10:50:28 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#include <errno.h>
#include <dlfcn.h>

#include <plugin/unx/plugcon.hxx>

PluginConnector* pConnector = NULL;

NPWindow aNPWindow;
NPSetWindowCallbackStruct aNPSetWindowCallbackStruct;

int         nAppArguments = 0;
char**      pAppArguments = NULL;
Display*    pAppDisplay = NULL;

extern void* pPluginLib;

static long GlobalConnectionLostHdl( void* pInst, void* pArg )
{
#ifdef DEBUG
    fprintf( stderr, "xhello exiting due to connection lost\n" );
#endif
    exit( 0 );
    return 0;
}

XtAppContext app_context;
Widget topLevel, hello;

void ThreadEventHandler( Widget widget, XtPointer closure,
                         XEvent* pEvent, XLIB_Boolean* dispatch_further )
{
    if( pEvent->type == ClientMessage &&
        pEvent->xclient.format == 32 &&
        pEvent->xclient.data.l[0] == 1 &&
        pEvent->xclient.data.l[1] == 2 &&
        pEvent->xclient.data.l[2] == 3 &&
        pEvent->xclient.data.l[3] == 4 &&
        pEvent->xclient.data.l[4] == 5 )
    {
        *dispatch_further = False;
        pConnector->CallWorkHandler();
    }
    else
        *dispatch_further = True;
}

IMPL_LINK( PluginConnector, NewMessageHdl, Mediator*, pMediator )
{
    XEvent aEvent;
    aEvent.type = ClientMessage;
    aEvent.xclient.display = XtDisplay( topLevel );
    aEvent.xclient.message_type = XA_STRING;
    aEvent.xclient.window = XtWindow( topLevel );
    aEvent.xclient.format = 32;
    aEvent.xclient.data.l[0] = 1;
    aEvent.xclient.data.l[1] = 2;
    aEvent.xclient.data.l[2] = 3;
    aEvent.xclient.data.l[3] = 4;
    aEvent.xclient.data.l[4] = 5;
    XSendEvent( XtDisplay( topLevel ),
                XtWindow( topLevel ), False,
                0, &aEvent );
    XFlush( XtDisplay( topLevel ) );
    return 0;
}

#if defined USE_MOTIF
Widget createSubWidget( char* pPluginText, Widget shell )
{
    Widget newWidget;
      newWidget = XtVaCreateManagedWidget(
          "hello",
        xmDrawingAreaWidgetClass,
          shell,
          NULL );

    return newWidget;
}
#else
Widget createSubWidget( char* pPluginText, Widget shell )
{
    hello = XtVaCreateManagedWidget(
        pPluginText,
        labelWidgetClass,
        shell,
        NULL );

    return hello;
}
#endif

void* CreateNewShell( void** pShellReturn )
{
    Widget newShell =
        XtVaAppCreateShell( "SOPluginApp", "SOPluginApp",
                            applicationShellWidgetClass,
                            pAppDisplay,
                            NULL );
    char pText[1024];
    sprintf( pText, "starting plugin %s ...", pAppArguments[2] );
    Widget newWidget = createSubWidget( pText, newShell );

    XtRealizeWidget( newShell );

    *pShellReturn = newShell;
    return newWidget;
}

// Unix specific implementation
static void CheckPlugin( const char* pPath )
{
    rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();

    void *pLib = dlopen( pPath, RTLD_LAZY );
    if( ! pLib )
    {
#ifdef DEBUG
        fprintf( stderr, "could not dlopen( %s ) (%s)\n", pPath, dlerror() );
#endif
        return;
    }

    char*(*pNP_GetMIMEDescription)() = (char*(*)())
        dlsym( pLib, "NP_GetMIMEDescription" );
    if( pNP_GetMIMEDescription )
        printf( "%s\n", pNP_GetMIMEDescription() );
#ifdef DEBUG
    else
        fprintf( stderr, "could not dlsym NP_GetMIMEDescription (%s)\n", dlerror() );
#endif
    dlclose( pLib );
}

main( int argc, char **argv)
{
    if( argc < 3 )
    {
        CheckPlugin(argv[1]);
        exit(0);
    }
#if ! ( defined DEBUG || defined DBG_UTIL )
    fclose( stdout );
    fclose( stderr );
#endif
    nAppArguments = argc;
    pAppArguments = argv;

    XInitThreads();

    pPluginLib = dlopen( argv[2], RTLD_LAZY );
    if( ! pPluginLib )
    {
        medDebug( 1, "dlopen on %s failed because of:\n\t%s\n",
                  argv[2], dlerror() );
        exit(255);
    }
    int nSocket = atol( argv[1] );

    pConnector = new PluginConnector( nSocket );
    pConnector->SetConnectionLostHdl( Link( NULL, GlobalConnectionLostHdl ) );

    XtSetLanguageProc( NULL, NULL, NULL );

    topLevel = XtVaAppInitialize(
        &app_context,       /* Application context */
        "SOPlugin",         /* Application class */
        NULL, 0,            /* command line option list */
        &argc, argv,        /* command line args */
        NULL,               /* for missing app-defaults file */
        NULL);              /* terminate varargs list */
    pAppDisplay = XtDisplay( topLevel );
    XtAddRawEventHandler( topLevel, 0, True, ThreadEventHandler, NULL );

    char pText[1024];
    sprintf( pText, "starting plugin %s ...", pAppArguments[2] );
    hello = createSubWidget( pText, topLevel );

    /*
     *  Create windows for widgets and map them.
     */
    XtRealizeWidget(topLevel);

    INT32 nWindow;
    sscanf( argv[3], "%d", &nWindow );
    medDebug( 1, "Reparenting topLevel to %x\n", nWindow );
      XReparentWindow( pAppDisplay,
                       XtWindow( topLevel ),
                       (XLIB_Window)nWindow,
                       0, 0 );

    XSync( XtDisplay( hello ), False );

    // send that we are ready to go
       MediatorMessage* pMessage =
           pConnector->Transact( "init req", 8,
                                 NULL );
       delete pMessage;

    aNPSetWindowCallbackStruct.display      = pAppDisplay;
    aNPSetWindowCallbackStruct.visual       = (Visual*)
        XDefaultVisual( pAppDisplay, XDefaultScreen( pAppDisplay ) );
    aNPSetWindowCallbackStruct.colormap     = (Colormap)
        XDefaultColormap( pAppDisplay, XDefaultScreen( pAppDisplay ) );
    aNPSetWindowCallbackStruct.depth        =
        DefaultDepth( pAppDisplay, XDefaultScreen( pAppDisplay ) );

    /*
     *  Loop for events.
     */
    XtAppMainLoop(app_context);
}
<commit_msg>#95340# do not close stderr and stdout because this breaks at least nppdf.so<commit_after>/*************************************************************************
 *
 *  $RCSfile: npwrap.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: pl $ $Date: 2002-01-19 13:09:33 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#include <errno.h>
#include <dlfcn.h>

#include <plugin/unx/plugcon.hxx>

PluginConnector* pConnector = NULL;

NPWindow aNPWindow;
NPSetWindowCallbackStruct aNPSetWindowCallbackStruct;

int         nAppArguments = 0;
char**      pAppArguments = NULL;
Display*    pAppDisplay = NULL;

extern void* pPluginLib;

static long GlobalConnectionLostHdl( void* pInst, void* pArg )
{
#ifdef DEBUG
    fprintf( stderr, "xhello exiting due to connection lost\n" );
#endif
    exit( 0 );
    return 0;
}

XtAppContext app_context;
Widget topLevel, hello;

void ThreadEventHandler( Widget widget, XtPointer closure,
                         XEvent* pEvent, XLIB_Boolean* dispatch_further )
{
    if( pEvent->type == ClientMessage &&
        pEvent->xclient.format == 32 &&
        pEvent->xclient.data.l[0] == 1 &&
        pEvent->xclient.data.l[1] == 2 &&
        pEvent->xclient.data.l[2] == 3 &&
        pEvent->xclient.data.l[3] == 4 &&
        pEvent->xclient.data.l[4] == 5 )
    {
        *dispatch_further = False;
        pConnector->CallWorkHandler();
    }
    else
        *dispatch_further = True;
}

IMPL_LINK( PluginConnector, NewMessageHdl, Mediator*, pMediator )
{
    XEvent aEvent;
    aEvent.type = ClientMessage;
    aEvent.xclient.display = XtDisplay( topLevel );
    aEvent.xclient.message_type = XA_STRING;
    aEvent.xclient.window = XtWindow( topLevel );
    aEvent.xclient.format = 32;
    aEvent.xclient.data.l[0] = 1;
    aEvent.xclient.data.l[1] = 2;
    aEvent.xclient.data.l[2] = 3;
    aEvent.xclient.data.l[3] = 4;
    aEvent.xclient.data.l[4] = 5;
    XSendEvent( XtDisplay( topLevel ),
                XtWindow( topLevel ), False,
                0, &aEvent );
    XFlush( XtDisplay( topLevel ) );
    return 0;
}

#if defined USE_MOTIF
Widget createSubWidget( char* pPluginText, Widget shell )
{
    Widget newWidget;
      newWidget = XtVaCreateManagedWidget(
          "hello",
        xmDrawingAreaWidgetClass,
          shell,
          NULL );

    return newWidget;
}
#else
Widget createSubWidget( char* pPluginText, Widget shell )
{
    hello = XtVaCreateManagedWidget(
        pPluginText,
        labelWidgetClass,
        shell,
        NULL );

    return hello;
}
#endif

void* CreateNewShell( void** pShellReturn )
{
    Widget newShell =
        XtVaAppCreateShell( "SOPluginApp", "SOPluginApp",
                            applicationShellWidgetClass,
                            pAppDisplay,
                            NULL );
    char pText[1024];
    sprintf( pText, "starting plugin %s ...", pAppArguments[2] );
    Widget newWidget = createSubWidget( pText, newShell );

    XtRealizeWidget( newShell );

    *pShellReturn = newShell;
    return newWidget;
}

// Unix specific implementation
static void CheckPlugin( const char* pPath )
{
    rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();

    void *pLib = dlopen( pPath, RTLD_LAZY );
    if( ! pLib )
    {
#ifdef DEBUG
        fprintf( stderr, "could not dlopen( %s ) (%s)\n", pPath, dlerror() );
#endif
        return;
    }

    char*(*pNP_GetMIMEDescription)() = (char*(*)())
        dlsym( pLib, "NP_GetMIMEDescription" );
    if( pNP_GetMIMEDescription )
        printf( "%s\n", pNP_GetMIMEDescription() );
#ifdef DEBUG
    else
        fprintf( stderr, "could not dlsym NP_GetMIMEDescription (%s)\n", dlerror() );
#endif
    dlclose( pLib );
}

main( int argc, char **argv)
{
    if( argc < 3 )
    {
        CheckPlugin(argv[1]);
        exit(0);
    }
    nAppArguments = argc;
    pAppArguments = argv;

    XInitThreads();

    pPluginLib = dlopen( argv[2], RTLD_LAZY );
    if( ! pPluginLib )
    {
        medDebug( 1, "dlopen on %s failed because of:\n\t%s\n",
                  argv[2], dlerror() );
        exit(255);
    }
    int nSocket = atol( argv[1] );

    pConnector = new PluginConnector( nSocket );
    pConnector->SetConnectionLostHdl( Link( NULL, GlobalConnectionLostHdl ) );

    XtSetLanguageProc( NULL, NULL, NULL );

    topLevel = XtVaAppInitialize(
        &app_context,       /* Application context */
        "SOPlugin",         /* Application class */
        NULL, 0,            /* command line option list */
        &argc, argv,        /* command line args */
        NULL,               /* for missing app-defaults file */
        NULL);              /* terminate varargs list */
    pAppDisplay = XtDisplay( topLevel );
    XtAddRawEventHandler( topLevel, 0, True, ThreadEventHandler, NULL );

    char pText[1024];
    sprintf( pText, "starting plugin %s ...", pAppArguments[2] );
    hello = createSubWidget( pText, topLevel );

    /*
     *  Create windows for widgets and map them.
     */
    XtRealizeWidget(topLevel);

    INT32 nWindow;
    sscanf( argv[3], "%d", &nWindow );
    medDebug( 1, "Reparenting topLevel to %x\n", nWindow );
      XReparentWindow( pAppDisplay,
                       XtWindow( topLevel ),
                       (XLIB_Window)nWindow,
                       0, 0 );

    XSync( XtDisplay( hello ), False );

    // send that we are ready to go
       MediatorMessage* pMessage =
           pConnector->Transact( "init req", 8,
                                 NULL );
       delete pMessage;

    aNPSetWindowCallbackStruct.display      = pAppDisplay;
    aNPSetWindowCallbackStruct.visual       = (Visual*)
        XDefaultVisual( pAppDisplay, XDefaultScreen( pAppDisplay ) );
    aNPSetWindowCallbackStruct.colormap     = (Colormap)
        XDefaultColormap( pAppDisplay, XDefaultScreen( pAppDisplay ) );
    aNPSetWindowCallbackStruct.depth        =
        DefaultDepth( pAppDisplay, XDefaultScreen( pAppDisplay ) );

    /*
     *  Loop for events.
     */
    XtAppMainLoop(app_context);
}
<|endoftext|>