<commit_before>/**
 * This file is part of TelepathyQt
 *
 * @copyright Copyright (C) 2011-2012 Collabora Ltd. <http://www.collabora.co.uk/>
 * @license LGPL 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include <TelepathyQt/DebugReceiver>

#include "TelepathyQt/_gen/debug-receiver.moc.hpp"
#include "TelepathyQt/_gen/cli-debug-receiver-body.hpp"
#include "TelepathyQt/_gen/cli-debug-receiver.moc.hpp"

#include "TelepathyQt/debug-internal.h"

#include <TelepathyQt/Constants>
#include <TelepathyQt/PendingDebugMessageList>
#include <TelepathyQt/PendingFailure>
#include <TelepathyQt/PendingVariantMap>
#include <TelepathyQt/ReadinessHelper>

namespace Tp
{

struct TP_QT_NO_EXPORT DebugReceiver::Private
{
    Private(DebugReceiver *parent);

    static void introspectCore(Private *self);

    DebugReceiver *parent;
    Client::DebugInterface *baseInterface;
};

DebugReceiver::Private::Private(DebugReceiver *parent)
    : parent(parent),
      baseInterface(new Client::DebugInterface(parent))
{
    ReadinessHelper::Introspectables introspectables;

    ReadinessHelper::Introspectable introspectableCore(
            QSet<uint>() << 0,                                                      // makesSenseForStatuses
            Features(),                                                             // dependsOnFeatures (core)
            QStringList(),                                                          // dependsOnInterfaces
            (ReadinessHelper::IntrospectFunc) &DebugReceiver::Private::introspectCore,
            this);
    introspectables[DebugReceiver::FeatureCore] = introspectableCore;

    parent->readinessHelper()->addIntrospectables(introspectables);
}

void DebugReceiver::Private::introspectCore(DebugReceiver::Private *self)
{
    // this is done only to verify that the object exists...
    PendingVariantMap *op = self->baseInterface->requestAllProperties();
    self->parent->connect(op,
            SIGNAL(finished(Tp::PendingOperation*)),
            SLOT(onRequestAllPropertiesFinished(Tp::PendingOperation*)));
}

/**
 * \class DebugReceiver
 * \ingroup clientsideproxies
 * \headerfile TelepathyQt/debug-receiver.h <TelepathyQt/DebugReceiver>
 *
 * \brief The DebugReceiver class provides a D-Bus proxy for a Telepathy
 * Debug object.
 *
 * A Debug object provides debugging messages from services.
 */

/**
 * Feature representing the core that needs to become ready to make the DebugReceiver
 * object usable.
 *
 * Note that this feature must be enabled in order to use most DebugReceiver methods.
 * See specific methods documentation for more details.
 *
 * When calling isReady(), becomeReady(), this feature is implicitly added
 * to the requested features.
 */
const Feature DebugReceiver::FeatureCore = Feature(QLatin1String(DebugReceiver::staticMetaObject.className()), 0, true);

DebugReceiverPtr DebugReceiver::create(const QString &busName, const QDBusConnection &bus)
{
    return DebugReceiverPtr(new DebugReceiver(bus, busName));
}

DebugReceiver::DebugReceiver(const QDBusConnection &bus, const QString &busName)
    : StatefulDBusProxy(bus, busName, TP_QT_DEBUG_OBJECT_PATH, DebugReceiver::FeatureCore),
      mPriv(new Private(this))
{
}

DebugReceiver::~DebugReceiver()
{
    delete mPriv;
}

PendingDebugMessageList *DebugReceiver::fetchMessages()
{
    return new PendingDebugMessageList(mPriv->baseInterface->GetMessages(),
            DebugReceiverPtr(this));
}

PendingOperation *DebugReceiver::setMonitoringEnabled(bool enabled)
{
    if (!isReady()) {
        warning() << "DebugReceiver::setMonitoringEnabled called without DebugReceiver being ready";
        return new PendingFailure(TP_QT_ERROR_NOT_AVAILABLE,
                QLatin1String("FeatureCore is not ready"), DebugReceiverPtr(this));
    }

    return mPriv->baseInterface->setPropertyEnabled(enabled);
}

void DebugReceiver::onRequestAllPropertiesFinished(Tp::PendingOperation *op)
{
    if (op->isError()) {
        readinessHelper()->setIntrospectCompleted(
            FeatureCore, false, op->errorName(), op->errorMessage());
    } else {
        connect(mPriv->baseInterface,
                SIGNAL(NewDebugMessage(double,QString,uint,QString)),
                SLOT(onNewDebugMessage(double,QString,uint,QString)));

        readinessHelper()->setIntrospectCompleted(FeatureCore, true);
    }
}

void DebugReceiver::onNewDebugMessage(double time, const QString &domain,
        uint level, const QString &message)
{
    DebugMessage msg;
    msg.timestamp = time;
    msg.domain = domain;
    msg.level = level;
    msg.message = message;

    emit newDebugMessage(msg);
}

} // Tp
<commit_msg>DebugReceiver: Add missing documentation to public methods and signals<commit_after>/**
 * This file is part of TelepathyQt
 *
 * @copyright Copyright (C) 2011-2012 Collabora Ltd. <http://www.collabora.co.uk/>
 * @license LGPL 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include <TelepathyQt/DebugReceiver>

#include "TelepathyQt/_gen/debug-receiver.moc.hpp"
#include "TelepathyQt/_gen/cli-debug-receiver-body.hpp"
#include "TelepathyQt/_gen/cli-debug-receiver.moc.hpp"

#include "TelepathyQt/debug-internal.h"

#include <TelepathyQt/Constants>
#include <TelepathyQt/PendingDebugMessageList>
#include <TelepathyQt/PendingFailure>
#include <TelepathyQt/PendingVariantMap>
#include <TelepathyQt/ReadinessHelper>

namespace Tp
{

struct TP_QT_NO_EXPORT DebugReceiver::Private
{
    Private(DebugReceiver *parent);

    static void introspectCore(Private *self);

    DebugReceiver *parent;
    Client::DebugInterface *baseInterface;
};

DebugReceiver::Private::Private(DebugReceiver *parent)
    : parent(parent),
      baseInterface(new Client::DebugInterface(parent))
{
    ReadinessHelper::Introspectables introspectables;

    ReadinessHelper::Introspectable introspectableCore(
            QSet<uint>() << 0,                                                      // makesSenseForStatuses
            Features(),                                                             // dependsOnFeatures (core)
            QStringList(),                                                          // dependsOnInterfaces
            (ReadinessHelper::IntrospectFunc) &DebugReceiver::Private::introspectCore,
            this);
    introspectables[DebugReceiver::FeatureCore] = introspectableCore;

    parent->readinessHelper()->addIntrospectables(introspectables);
}

void DebugReceiver::Private::introspectCore(DebugReceiver::Private *self)
{
    // this is done only to verify that the object exists...
    PendingVariantMap *op = self->baseInterface->requestAllProperties();
    self->parent->connect(op,
            SIGNAL(finished(Tp::PendingOperation*)),
            SLOT(onRequestAllPropertiesFinished(Tp::PendingOperation*)));
}

/**
 * \class DebugReceiver
 * \ingroup clientsideproxies
 * \headerfile TelepathyQt/debug-receiver.h <TelepathyQt/DebugReceiver>
 *
 * \brief The DebugReceiver class provides a D-Bus proxy for a Telepathy
 * Debug object.
 *
 * A Debug object provides debugging messages from services.
 */

/**
 * Feature representing the core that needs to become ready to make the DebugReceiver
 * object usable.
 *
 * Note that this feature must be enabled in order to use most DebugReceiver methods.
 * See specific methods documentation for more details.
 *
 * When calling isReady(), becomeReady(), this feature is implicitly added
 * to the requested features.
 */
const Feature DebugReceiver::FeatureCore = Feature(QLatin1String(DebugReceiver::staticMetaObject.className()), 0, true);

DebugReceiverPtr DebugReceiver::create(const QString &busName, const QDBusConnection &bus)
{
    return DebugReceiverPtr(new DebugReceiver(bus, busName));
}

DebugReceiver::DebugReceiver(const QDBusConnection &bus, const QString &busName)
    : StatefulDBusProxy(bus, busName, TP_QT_DEBUG_OBJECT_PATH, DebugReceiver::FeatureCore),
      mPriv(new Private(this))
{
}

DebugReceiver::~DebugReceiver()
{
    delete mPriv;
}

/**
 * Retrieves buffered debug messages.
 *
 * This method returns a list of buffered debug messages. Depending on the service side
 * implementation, this may not be the entire list of all messages received during the
 * service's lifetime. Use monitoring instead for getting all the messages being streamed
 * in realtime.
 *
 * \return A pending operation returning a list of buffered debug messages when finished.
 *
 * \sa setMonitoringEnabled
 */
PendingDebugMessageList *DebugReceiver::fetchMessages()
{
    return new PendingDebugMessageList(mPriv->baseInterface->GetMessages(),
            DebugReceiverPtr(this));
}

/**
 * Enables or disables the emission of newDebugMessage.
 *
 * This function either enables or disables the emission of newDebugMessage. If monitoring is
 * enabled, everytime a message will be received, newDebugMessage will be emitted carrying the
 * new message.
 *
 * Monitoring should be disabled when not needed, as it generates a high amount of traffic on
 * the bus. It is always disabled by default.
 *
 * This method requires FeatureCore to be enabled.
 *
 * \param enabled Whether to enable or disable monitoring.
 *
 * \return A pending operation returning whether the operation succeeded or not.
 *
 * \sa newDebugMessage
 */
PendingOperation *DebugReceiver::setMonitoringEnabled(bool enabled)
{
    if (!isReady()) {
        warning() << "DebugReceiver::setMonitoringEnabled called without DebugReceiver being ready";
        return new PendingFailure(TP_QT_ERROR_NOT_AVAILABLE,
                QLatin1String("FeatureCore is not ready"), DebugReceiverPtr(this));
    }

    return mPriv->baseInterface->setPropertyEnabled(enabled);
}

void DebugReceiver::onRequestAllPropertiesFinished(Tp::PendingOperation *op)
{
    if (op->isError()) {
        readinessHelper()->setIntrospectCompleted(
            FeatureCore, false, op->errorName(), op->errorMessage());
    } else {
        connect(mPriv->baseInterface,
                SIGNAL(NewDebugMessage(double,QString,uint,QString)),
                SLOT(onNewDebugMessage(double,QString,uint,QString)));

        readinessHelper()->setIntrospectCompleted(FeatureCore, true);
    }
}

void DebugReceiver::onNewDebugMessage(double time, const QString &domain,
        uint level, const QString &message)
{
    DebugMessage msg;
    msg.timestamp = time;
    msg.domain = domain;
    msg.level = level;
    msg.message = message;

    emit newDebugMessage(msg);
}

/**
 * \fn void DebugReceiver::newDebugMessage(const Tp::DebugMessage &msg)
 *
 * Emitted whenever a new debug message is available. This will be emitted only if
 * monitoring has been previously enabled.
 *
 * \param msg The new debug message.
 *
 * \sa setMonitoringEnabled
 */

} // Tp
<|endoftext|>


<commit_before>//===- WebAssemblyTargetMachine.cpp - Define TargetMachine for WebAssembly -==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file defines the WebAssembly-specific subclass of TargetMachine.
///
//===----------------------------------------------------------------------===//

#include "WebAssemblyTargetMachine.h"
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
#include "WebAssembly.h"
#include "WebAssemblyTargetObjectFile.h"
#include "WebAssemblyTargetTransformInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils.h"
using namespace llvm;

#define DEBUG_TYPE "wasm"

// Emscripten's asm.js-style exception handling
static cl::opt<bool> EnableEmException(
    "enable-emscripten-cxx-exceptions",
    cl::desc("WebAssembly Emscripten-style exception handling"),
    cl::init(false));

// Emscripten's asm.js-style setjmp/longjmp handling
static cl::opt<bool> EnableEmSjLj(
    "enable-emscripten-sjlj",
    cl::desc("WebAssembly Emscripten-style setjmp/longjmp handling"),
    cl::init(false));

extern "C" void LLVMInitializeWebAssemblyTarget() {
  // Register the target.
  RegisterTargetMachine<WebAssemblyTargetMachine> X(
      getTheWebAssemblyTarget32());
  RegisterTargetMachine<WebAssemblyTargetMachine> Y(
      getTheWebAssemblyTarget64());

  // Register backend passes
  auto &PR = *PassRegistry::getPassRegistry();
  initializeWebAssemblyAddMissingPrototypesPass(PR);
  initializeWebAssemblyLowerEmscriptenEHSjLjPass(PR);
  initializeLowerGlobalDtorsPass(PR);
  initializeFixFunctionBitcastsPass(PR);
  initializeOptimizeReturnedPass(PR);
  initializeWebAssemblyArgumentMovePass(PR);
  initializeWebAssemblySetP2AlignOperandsPass(PR);
  initializeWebAssemblyEHRestoreStackPointerPass(PR);
  initializeWebAssemblyReplacePhysRegsPass(PR);
  initializeWebAssemblyPrepareForLiveIntervalsPass(PR);
  initializeWebAssemblyOptimizeLiveIntervalsPass(PR);
  initializeWebAssemblyStoreResultsPass(PR);
  initializeWebAssemblyRegStackifyPass(PR);
  initializeWebAssemblyRegColoringPass(PR);
  initializeWebAssemblyExplicitLocalsPass(PR);
  initializeWebAssemblyFixIrreducibleControlFlowPass(PR);
  initializeWebAssemblyLateEHPreparePass(PR);
  initializeWebAssemblyExceptionInfoPass(PR);
  initializeWebAssemblyCFGSortPass(PR);
  initializeWebAssemblyCFGStackifyPass(PR);
  initializeWebAssemblyLowerBrUnlessPass(PR);
  initializeWebAssemblyRegNumberingPass(PR);
  initializeWebAssemblyPeepholePass(PR);
  initializeWebAssemblyCallIndirectFixupPass(PR);
}

//===----------------------------------------------------------------------===//
// WebAssembly Lowering public interface.
//===----------------------------------------------------------------------===//

static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
  if (!RM.hasValue()) {
    // Default to static relocation model.  This should always be more optimial
    // than PIC since the static linker can determine all global addresses and
    // assume direct function calls.
    return Reloc::Static;
  }
  return *RM;
}

/// Create an WebAssembly architecture model.
///
WebAssemblyTargetMachine::WebAssemblyTargetMachine(
    const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
    const TargetOptions &Options, Optional<Reloc::Model> RM,
    Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT)
    : LLVMTargetMachine(T,
                        TT.isArch64Bit() ? "e-m:e-p:64:64-i64:64-n32:64-S128"
                                         : "e-m:e-p:32:32-i64:64-n32:64-S128",
                        TT, CPU, FS, Options, getEffectiveRelocModel(RM),
                        getEffectiveCodeModel(CM, CodeModel::Large), OL),
      TLOF(new WebAssemblyTargetObjectFile()) {
  // WebAssembly type-checks instructions, but a noreturn function with a return
  // type that doesn't match the context will cause a check failure. So we lower
  // LLVM 'unreachable' to ISD::TRAP and then lower that to WebAssembly's
  // 'unreachable' instructions which is meant for that case.
  this->Options.TrapUnreachable = true;

  // WebAssembly treats each function as an independent unit. Force
  // -ffunction-sections, effectively, so that we can emit them independently.
  this->Options.FunctionSections = true;
  this->Options.DataSections = true;
  this->Options.UniqueSectionNames = true;

  initAsmInfo();

  // Note that we don't use setRequiresStructuredCFG(true). It disables
  // optimizations than we're ok with, and want, such as critical edge
  // splitting and tail merging.
}

WebAssemblyTargetMachine::~WebAssemblyTargetMachine() {}

const WebAssemblySubtarget *
WebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const {
  Attribute CPUAttr = F.getFnAttribute("target-cpu");
  Attribute FSAttr = F.getFnAttribute("target-features");

  std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
                        ? CPUAttr.getValueAsString().str()
                        : TargetCPU;
  std::string FS = !FSAttr.hasAttribute(Attribute::None)
                       ? FSAttr.getValueAsString().str()
                       : TargetFS;

  auto &I = SubtargetMap[CPU + FS];
  if (!I) {
    // This needs to be done before we create a new subtarget since any
    // creation will depend on the TM and the code generation flags on the
    // function that reside in TargetOptions.
    resetTargetOptions(F);
    I = llvm::make_unique<WebAssemblySubtarget>(TargetTriple, CPU, FS, *this);
  }
  return I.get();
}

namespace {
class StripThreadLocal final : public ModulePass {
  // The default thread model for wasm is single, where thread-local variables
  // are identical to regular globals and should be treated the same. So this
  // pass just converts all GlobalVariables to NotThreadLocal
  static char ID;

public:
  StripThreadLocal() : ModulePass(ID) {}
  bool runOnModule(Module &M) override {
    for (auto &GV : M.globals())
      GV.setThreadLocalMode(GlobalValue::ThreadLocalMode::NotThreadLocal);
    return true;
  }
};
char StripThreadLocal::ID = 0;

/// WebAssembly Code Generator Pass Configuration Options.
class WebAssemblyPassConfig final : public TargetPassConfig {
public:
  WebAssemblyPassConfig(WebAssemblyTargetMachine &TM, PassManagerBase &PM)
      : TargetPassConfig(TM, PM) {}

  WebAssemblyTargetMachine &getWebAssemblyTargetMachine() const {
    return getTM<WebAssemblyTargetMachine>();
  }

  FunctionPass *createTargetRegisterAllocator(bool) override;

  void addIRPasses() override;
  bool addInstSelector() override;
  void addPostRegAlloc() override;
  bool addGCPasses() override { return false; }
  void addPreEmitPass() override;
};
} // end anonymous namespace

TargetTransformInfo
WebAssemblyTargetMachine::getTargetTransformInfo(const Function &F) {
  return TargetTransformInfo(WebAssemblyTTIImpl(this, F));
}

TargetPassConfig *
WebAssemblyTargetMachine::createPassConfig(PassManagerBase &PM) {
  return new WebAssemblyPassConfig(*this, PM);
}

FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {
  return nullptr; // No reg alloc
}

//===----------------------------------------------------------------------===//
// The following functions are called from lib/CodeGen/Passes.cpp to modify
// the CodeGen pass sequence.
//===----------------------------------------------------------------------===//

void WebAssemblyPassConfig::addIRPasses() {
  if (TM->Options.ThreadModel == ThreadModel::Single) {
    // In "single" mode, atomics get lowered to non-atomics.
    addPass(createLowerAtomicPass());
    addPass(new StripThreadLocal());
  } else {
    // Expand some atomic operations. WebAssemblyTargetLowering has hooks which
    // control specifically what gets lowered.
    addPass(createAtomicExpandPass());
  }

  // Add signatures to prototype-less function declarations
  addPass(createWebAssemblyAddMissingPrototypes());

  // Lower .llvm.global_dtors into .llvm_global_ctors with __cxa_atexit calls.
  addPass(createWebAssemblyLowerGlobalDtors());

  // Fix function bitcasts, as WebAssembly requires caller and callee signatures
  // to match.
  addPass(createWebAssemblyFixFunctionBitcasts());

  // Optimize "returned" function attributes.
  if (getOptLevel() != CodeGenOpt::None)
    addPass(createWebAssemblyOptimizeReturned());

  // If exception handling is not enabled and setjmp/longjmp handling is
  // enabled, we lower invokes into calls and delete unreachable landingpad
  // blocks. Lowering invokes when there is no EH support is done in
  // TargetPassConfig::addPassesToHandleExceptions, but this runs after this
  // function and SjLj handling expects all invokes to be lowered before.
  if (!EnableEmException &&
      TM->Options.ExceptionModel == ExceptionHandling::None) {
    addPass(createLowerInvokePass());
    // The lower invoke pass may create unreachable code. Remove it in order not
    // to process dead blocks in setjmp/longjmp handling.
    addPass(createUnreachableBlockEliminationPass());
  }

  // Handle exceptions and setjmp/longjmp if enabled.
  if (EnableEmException || EnableEmSjLj)
    addPass(createWebAssemblyLowerEmscriptenEHSjLj(EnableEmException,
                                                   EnableEmSjLj));

  TargetPassConfig::addIRPasses();
}

bool WebAssemblyPassConfig::addInstSelector() {
  (void)TargetPassConfig::addInstSelector();
  addPass(
      createWebAssemblyISelDag(getWebAssemblyTargetMachine(), getOptLevel()));
  // Run the argument-move pass immediately after the ScheduleDAG scheduler
  // so that we can fix up the ARGUMENT instructions before anything else
  // sees them in the wrong place.
  addPass(createWebAssemblyArgumentMove());
  // Set the p2align operands. This information is present during ISel, however
  // it's inconvenient to collect. Collect it now, and update the immediate
  // operands.
  addPass(createWebAssemblySetP2AlignOperands());
  return false;
}

void WebAssemblyPassConfig::addPostRegAlloc() {
  // TODO: The following CodeGen passes don't currently support code containing
  // virtual registers. Consider removing their restrictions and re-enabling
  // them.

  // These functions all require the NoVRegs property.
  disablePass(&MachineCopyPropagationID);
  disablePass(&PostRAMachineSinkingID);
  disablePass(&PostRASchedulerID);
  disablePass(&FuncletLayoutID);
  disablePass(&StackMapLivenessID);
  disablePass(&LiveDebugValuesID);
  disablePass(&PatchableFunctionID);
  disablePass(&ShrinkWrapID);

  TargetPassConfig::addPostRegAlloc();
}

void WebAssemblyPassConfig::addPreEmitPass() {
  TargetPassConfig::addPreEmitPass();

  // Restore __stack_pointer global after an exception is thrown.
  addPass(createWebAssemblyEHRestoreStackPointer());

  // Now that we have a prologue and epilogue and all frame indices are
  // rewritten, eliminate SP and FP. This allows them to be stackified,
  // colored, and numbered with the rest of the registers.
  addPass(createWebAssemblyReplacePhysRegs());

  // Rewrite pseudo call_indirect instructions as real instructions.
  // This needs to run before register stackification, because we change the
  // order of the arguments.
  addPass(createWebAssemblyCallIndirectFixup());

  if (getOptLevel() != CodeGenOpt::None) {
    // LiveIntervals isn't commonly run this late. Re-establish preconditions.
    addPass(createWebAssemblyPrepareForLiveIntervals());

    // Depend on LiveIntervals and perform some optimizations on it.
    addPass(createWebAssemblyOptimizeLiveIntervals());

    // Prepare store instructions for register stackifying.
    addPass(createWebAssemblyStoreResults());

    // Mark registers as representing wasm's value stack. This is a key
    // code-compression technique in WebAssembly. We run this pass (and
    // StoreResults above) very late, so that it sees as much code as possible,
    // including code emitted by PEI and expanded by late tail duplication.
    addPass(createWebAssemblyRegStackify());

    // Run the register coloring pass to reduce the total number of registers.
    // This runs after stackification so that it doesn't consider registers
    // that become stackified.
    addPass(createWebAssemblyRegColoring());
  }

  // Eliminate multiple-entry loops. Do this before inserting explicit get_local
  // and set_local operators because we create a new variable that we want
  // converted into a local.
  addPass(createWebAssemblyFixIrreducibleControlFlow());

  // Insert explicit get_local and set_local operators.
  addPass(createWebAssemblyExplicitLocals());

  // Do various transformations for exception handling
  addPass(createWebAssemblyLateEHPrepare());

  // Sort the blocks of the CFG into topological order, a prerequisite for
  // BLOCK and LOOP markers.
  addPass(createWebAssemblyCFGSort());

  // Insert BLOCK and LOOP markers.
  addPass(createWebAssemblyCFGStackify());

  // Lower br_unless into br_if.
  addPass(createWebAssemblyLowerBrUnless());

  // Perform the very last peephole optimizations on the code.
  if (getOptLevel() != CodeGenOpt::None)
    addPass(createWebAssemblyPeephole());

  // Create a mapping from LLVM CodeGen virtual registers to wasm registers.
  addPass(createWebAssemblyRegNumbering());
}
<commit_msg>[WebAssembly] Move CFG-changing passes before RegStackify<commit_after>//===- WebAssemblyTargetMachine.cpp - Define TargetMachine for WebAssembly -==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file defines the WebAssembly-specific subclass of TargetMachine.
///
//===----------------------------------------------------------------------===//

#include "WebAssemblyTargetMachine.h"
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
#include "WebAssembly.h"
#include "WebAssemblyTargetObjectFile.h"
#include "WebAssemblyTargetTransformInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils.h"
using namespace llvm;

#define DEBUG_TYPE "wasm"

// Emscripten's asm.js-style exception handling
static cl::opt<bool> EnableEmException(
    "enable-emscripten-cxx-exceptions",
    cl::desc("WebAssembly Emscripten-style exception handling"),
    cl::init(false));

// Emscripten's asm.js-style setjmp/longjmp handling
static cl::opt<bool> EnableEmSjLj(
    "enable-emscripten-sjlj",
    cl::desc("WebAssembly Emscripten-style setjmp/longjmp handling"),
    cl::init(false));

extern "C" void LLVMInitializeWebAssemblyTarget() {
  // Register the target.
  RegisterTargetMachine<WebAssemblyTargetMachine> X(
      getTheWebAssemblyTarget32());
  RegisterTargetMachine<WebAssemblyTargetMachine> Y(
      getTheWebAssemblyTarget64());

  // Register backend passes
  auto &PR = *PassRegistry::getPassRegistry();
  initializeWebAssemblyAddMissingPrototypesPass(PR);
  initializeWebAssemblyLowerEmscriptenEHSjLjPass(PR);
  initializeLowerGlobalDtorsPass(PR);
  initializeFixFunctionBitcastsPass(PR);
  initializeOptimizeReturnedPass(PR);
  initializeWebAssemblyArgumentMovePass(PR);
  initializeWebAssemblySetP2AlignOperandsPass(PR);
  initializeWebAssemblyEHRestoreStackPointerPass(PR);
  initializeWebAssemblyReplacePhysRegsPass(PR);
  initializeWebAssemblyPrepareForLiveIntervalsPass(PR);
  initializeWebAssemblyOptimizeLiveIntervalsPass(PR);
  initializeWebAssemblyStoreResultsPass(PR);
  initializeWebAssemblyRegStackifyPass(PR);
  initializeWebAssemblyRegColoringPass(PR);
  initializeWebAssemblyExplicitLocalsPass(PR);
  initializeWebAssemblyFixIrreducibleControlFlowPass(PR);
  initializeWebAssemblyLateEHPreparePass(PR);
  initializeWebAssemblyExceptionInfoPass(PR);
  initializeWebAssemblyCFGSortPass(PR);
  initializeWebAssemblyCFGStackifyPass(PR);
  initializeWebAssemblyLowerBrUnlessPass(PR);
  initializeWebAssemblyRegNumberingPass(PR);
  initializeWebAssemblyPeepholePass(PR);
  initializeWebAssemblyCallIndirectFixupPass(PR);
}

//===----------------------------------------------------------------------===//
// WebAssembly Lowering public interface.
//===----------------------------------------------------------------------===//

static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
  if (!RM.hasValue()) {
    // Default to static relocation model.  This should always be more optimial
    // than PIC since the static linker can determine all global addresses and
    // assume direct function calls.
    return Reloc::Static;
  }
  return *RM;
}

/// Create an WebAssembly architecture model.
///
WebAssemblyTargetMachine::WebAssemblyTargetMachine(
    const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
    const TargetOptions &Options, Optional<Reloc::Model> RM,
    Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT)
    : LLVMTargetMachine(T,
                        TT.isArch64Bit() ? "e-m:e-p:64:64-i64:64-n32:64-S128"
                                         : "e-m:e-p:32:32-i64:64-n32:64-S128",
                        TT, CPU, FS, Options, getEffectiveRelocModel(RM),
                        getEffectiveCodeModel(CM, CodeModel::Large), OL),
      TLOF(new WebAssemblyTargetObjectFile()) {
  // WebAssembly type-checks instructions, but a noreturn function with a return
  // type that doesn't match the context will cause a check failure. So we lower
  // LLVM 'unreachable' to ISD::TRAP and then lower that to WebAssembly's
  // 'unreachable' instructions which is meant for that case.
  this->Options.TrapUnreachable = true;

  // WebAssembly treats each function as an independent unit. Force
  // -ffunction-sections, effectively, so that we can emit them independently.
  this->Options.FunctionSections = true;
  this->Options.DataSections = true;
  this->Options.UniqueSectionNames = true;

  initAsmInfo();

  // Note that we don't use setRequiresStructuredCFG(true). It disables
  // optimizations than we're ok with, and want, such as critical edge
  // splitting and tail merging.
}

WebAssemblyTargetMachine::~WebAssemblyTargetMachine() {}

const WebAssemblySubtarget *
WebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const {
  Attribute CPUAttr = F.getFnAttribute("target-cpu");
  Attribute FSAttr = F.getFnAttribute("target-features");

  std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
                        ? CPUAttr.getValueAsString().str()
                        : TargetCPU;
  std::string FS = !FSAttr.hasAttribute(Attribute::None)
                       ? FSAttr.getValueAsString().str()
                       : TargetFS;

  auto &I = SubtargetMap[CPU + FS];
  if (!I) {
    // This needs to be done before we create a new subtarget since any
    // creation will depend on the TM and the code generation flags on the
    // function that reside in TargetOptions.
    resetTargetOptions(F);
    I = llvm::make_unique<WebAssemblySubtarget>(TargetTriple, CPU, FS, *this);
  }
  return I.get();
}

namespace {
class StripThreadLocal final : public ModulePass {
  // The default thread model for wasm is single, where thread-local variables
  // are identical to regular globals and should be treated the same. So this
  // pass just converts all GlobalVariables to NotThreadLocal
  static char ID;

public:
  StripThreadLocal() : ModulePass(ID) {}
  bool runOnModule(Module &M) override {
    for (auto &GV : M.globals())
      GV.setThreadLocalMode(GlobalValue::ThreadLocalMode::NotThreadLocal);
    return true;
  }
};
char StripThreadLocal::ID = 0;

/// WebAssembly Code Generator Pass Configuration Options.
class WebAssemblyPassConfig final : public TargetPassConfig {
public:
  WebAssemblyPassConfig(WebAssemblyTargetMachine &TM, PassManagerBase &PM)
      : TargetPassConfig(TM, PM) {}

  WebAssemblyTargetMachine &getWebAssemblyTargetMachine() const {
    return getTM<WebAssemblyTargetMachine>();
  }

  FunctionPass *createTargetRegisterAllocator(bool) override;

  void addIRPasses() override;
  bool addInstSelector() override;
  void addPostRegAlloc() override;
  bool addGCPasses() override { return false; }
  void addPreEmitPass() override;
};
} // end anonymous namespace

TargetTransformInfo
WebAssemblyTargetMachine::getTargetTransformInfo(const Function &F) {
  return TargetTransformInfo(WebAssemblyTTIImpl(this, F));
}

TargetPassConfig *
WebAssemblyTargetMachine::createPassConfig(PassManagerBase &PM) {
  return new WebAssemblyPassConfig(*this, PM);
}

FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {
  return nullptr; // No reg alloc
}

//===----------------------------------------------------------------------===//
// The following functions are called from lib/CodeGen/Passes.cpp to modify
// the CodeGen pass sequence.
//===----------------------------------------------------------------------===//

void WebAssemblyPassConfig::addIRPasses() {
  if (TM->Options.ThreadModel == ThreadModel::Single) {
    // In "single" mode, atomics get lowered to non-atomics.
    addPass(createLowerAtomicPass());
    addPass(new StripThreadLocal());
  } else {
    // Expand some atomic operations. WebAssemblyTargetLowering has hooks which
    // control specifically what gets lowered.
    addPass(createAtomicExpandPass());
  }

  // Add signatures to prototype-less function declarations
  addPass(createWebAssemblyAddMissingPrototypes());

  // Lower .llvm.global_dtors into .llvm_global_ctors with __cxa_atexit calls.
  addPass(createWebAssemblyLowerGlobalDtors());

  // Fix function bitcasts, as WebAssembly requires caller and callee signatures
  // to match.
  addPass(createWebAssemblyFixFunctionBitcasts());

  // Optimize "returned" function attributes.
  if (getOptLevel() != CodeGenOpt::None)
    addPass(createWebAssemblyOptimizeReturned());

  // If exception handling is not enabled and setjmp/longjmp handling is
  // enabled, we lower invokes into calls and delete unreachable landingpad
  // blocks. Lowering invokes when there is no EH support is done in
  // TargetPassConfig::addPassesToHandleExceptions, but this runs after this
  // function and SjLj handling expects all invokes to be lowered before.
  if (!EnableEmException &&
      TM->Options.ExceptionModel == ExceptionHandling::None) {
    addPass(createLowerInvokePass());
    // The lower invoke pass may create unreachable code. Remove it in order not
    // to process dead blocks in setjmp/longjmp handling.
    addPass(createUnreachableBlockEliminationPass());
  }

  // Handle exceptions and setjmp/longjmp if enabled.
  if (EnableEmException || EnableEmSjLj)
    addPass(createWebAssemblyLowerEmscriptenEHSjLj(EnableEmException,
                                                   EnableEmSjLj));

  TargetPassConfig::addIRPasses();
}

bool WebAssemblyPassConfig::addInstSelector() {
  (void)TargetPassConfig::addInstSelector();
  addPass(
      createWebAssemblyISelDag(getWebAssemblyTargetMachine(), getOptLevel()));
  // Run the argument-move pass immediately after the ScheduleDAG scheduler
  // so that we can fix up the ARGUMENT instructions before anything else
  // sees them in the wrong place.
  addPass(createWebAssemblyArgumentMove());
  // Set the p2align operands. This information is present during ISel, however
  // it's inconvenient to collect. Collect it now, and update the immediate
  // operands.
  addPass(createWebAssemblySetP2AlignOperands());
  return false;
}

void WebAssemblyPassConfig::addPostRegAlloc() {
  // TODO: The following CodeGen passes don't currently support code containing
  // virtual registers. Consider removing their restrictions and re-enabling
  // them.

  // These functions all require the NoVRegs property.
  disablePass(&MachineCopyPropagationID);
  disablePass(&PostRAMachineSinkingID);
  disablePass(&PostRASchedulerID);
  disablePass(&FuncletLayoutID);
  disablePass(&StackMapLivenessID);
  disablePass(&LiveDebugValuesID);
  disablePass(&PatchableFunctionID);
  disablePass(&ShrinkWrapID);

  TargetPassConfig::addPostRegAlloc();
}

void WebAssemblyPassConfig::addPreEmitPass() {
  TargetPassConfig::addPreEmitPass();

  // Restore __stack_pointer global after an exception is thrown.
  addPass(createWebAssemblyEHRestoreStackPointer());

  // Now that we have a prologue and epilogue and all frame indices are
  // rewritten, eliminate SP and FP. This allows them to be stackified,
  // colored, and numbered with the rest of the registers.
  addPass(createWebAssemblyReplacePhysRegs());

  // Rewrite pseudo call_indirect instructions as real instructions.
  // This needs to run before register stackification, because we change the
  // order of the arguments.
  addPass(createWebAssemblyCallIndirectFixup());

  // Eliminate multiple-entry loops.
  addPass(createWebAssemblyFixIrreducibleControlFlow());

  // Do various transformations for exception handling.
  addPass(createWebAssemblyLateEHPrepare());

  if (getOptLevel() != CodeGenOpt::None) {
    // LiveIntervals isn't commonly run this late. Re-establish preconditions.
    addPass(createWebAssemblyPrepareForLiveIntervals());

    // Depend on LiveIntervals and perform some optimizations on it.
    addPass(createWebAssemblyOptimizeLiveIntervals());

    // Prepare store instructions for register stackifying.
    addPass(createWebAssemblyStoreResults());

    // Mark registers as representing wasm's value stack. This is a key
    // code-compression technique in WebAssembly. We run this pass (and
    // StoreResults above) very late, so that it sees as much code as possible,
    // including code emitted by PEI and expanded by late tail duplication.
    addPass(createWebAssemblyRegStackify());

    // Run the register coloring pass to reduce the total number of registers.
    // This runs after stackification so that it doesn't consider registers
    // that become stackified.
    addPass(createWebAssemblyRegColoring());
  }

  // Insert explicit get_local and set_local operators.
  addPass(createWebAssemblyExplicitLocals());

  // Sort the blocks of the CFG into topological order, a prerequisite for
  // BLOCK and LOOP markers.
  addPass(createWebAssemblyCFGSort());

  // Insert BLOCK and LOOP markers.
  addPass(createWebAssemblyCFGStackify());

  // Lower br_unless into br_if.
  addPass(createWebAssemblyLowerBrUnless());

  // Perform the very last peephole optimizations on the code.
  if (getOptLevel() != CodeGenOpt::None)
    addPass(createWebAssemblyPeephole());

  // Create a mapping from LLVM CodeGen virtual registers to wasm registers.
  addPass(createWebAssemblyRegNumbering());
}
<|endoftext|>


<commit_before>//
// Implements the following classes:
//
// AutoDialog - An improvement to wxDialog which makes validation easier.
//
// AutoPanel - An improvement to wxPanel which makes validation easier.
//
// wxNumericValidator - A validator capable of transfering numeric values.
//
// Copyright (c) 2001-2003 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "AutoDialog.h"
#include "wxString2.h"

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

wxNumericValidator::wxNumericValidator(int *val) : wxValidator()
{
	Initialize();
	m_pValInt = val;
}

wxNumericValidator::wxNumericValidator(float *val, int digits) : wxValidator()
{
	Initialize();
	m_pValFloat = val;
	m_iDigits = digits;
}

wxNumericValidator::wxNumericValidator(double *val, int digits) : wxValidator()
{
	Initialize();
	m_pValDouble = val;
	m_iDigits = digits;
}

wxNumericValidator::wxNumericValidator(const wxNumericValidator& val)
{
	Copy(val);
}

bool wxNumericValidator::Copy(const wxNumericValidator& val)
{
	wxValidator::Copy(val);

	m_pValInt = val.m_pValInt;
	m_pValFloat = val.m_pValFloat;
	m_pValDouble = val.m_pValDouble;
	m_iDigits = val.m_iDigits;

	return TRUE;
}

// Called to transfer data to the window
bool wxNumericValidator::TransferToWindow()
{
	if ( !m_validatorWindow )
		return FALSE;

	wxString str, format;
	if (m_pValInt)
		str.Printf(_T("%d"), *m_pValInt);
	if (m_pValFloat)
	{
		if (m_iDigits != -1)
		{
			format.Printf(_T("%%.%df"), m_iDigits);
			str.Printf(format, *m_pValFloat);
		}
		else
			str.Printf(_T("%f"), *m_pValFloat);
	}
	if (m_pValDouble)
	{
		if (m_iDigits != -1)
		{
			format.Printf(_T("%%.%dlf"), m_iDigits);
			str.Printf(format, *m_pValDouble);
		}
		else
			str.Printf(_T("%lf"), *m_pValDouble);
	}

	if (m_validatorWindow->IsKindOf(CLASSINFO(wxStaticText)) )
	{
		wxStaticText* pControl = (wxStaticText*) m_validatorWindow;
		if (pControl)
		{
			pControl->SetLabel(str) ;
			return TRUE;
		}
	}
	else
	if (m_validatorWindow->IsKindOf(CLASSINFO(wxTextCtrl)) )
	{
		wxTextCtrl* pControl = (wxTextCtrl*) m_validatorWindow;
		if (pControl)
		{
			pControl->SetValue(str) ;
			return TRUE;
		}
	}
	else
		return FALSE;

	// unrecognized control, or bad pointer
	return FALSE;
}

// Called to transfer data from the window
bool wxNumericValidator::TransferFromWindow()
{
	if ( !m_validatorWindow )
		return FALSE;

	wxString2 str = _T("");
	// string controls
	if (m_validatorWindow->IsKindOf(CLASSINFO(wxStaticText)) )
	{
		wxStaticText* pControl = (wxStaticText*) m_validatorWindow;
		if (pControl)
			str = pControl->GetLabel() ;
	} else
	if (m_validatorWindow->IsKindOf(CLASSINFO(wxTextCtrl)) )
	{
		wxTextCtrl* pControl = (wxTextCtrl*) m_validatorWindow;
		if (pControl)
			str = pControl->GetValue() ;
	}
	else // unrecognized control, or bad pointer
		return FALSE;

	if (str != _T(""))
	{
		const char *ccs = str.mb_str();
		if (m_pValInt)
			sscanf(ccs, "%d", m_pValInt);
		if (m_pValFloat)
			sscanf(ccs, "%f", m_pValFloat);
		if (m_pValDouble)
			sscanf(ccs, "%lf", m_pValDouble);
		return TRUE;
	}
	return FALSE;
}

/*
  Called by constructors to initialize ALL data members
*/
void wxNumericValidator::Initialize()
{
	m_pValInt = NULL;
	m_pValFloat = NULL;
	m_pValDouble = NULL;
}

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

BEGIN_EVENT_TABLE(AutoDialog, wxDialog)
EVT_INIT_DIALOG (AutoDialog::OnInitDialog)
END_EVENT_TABLE()

void AutoDialog::AddValidator(long id, wxString *sptr)
{
	wxWindow *pWin = FindWindow(id);
	if (!pWin) return;
	wxGenericValidator *gv = new wxGenericValidator(sptr);
	pWin->SetValidator(*gv);
}

void AutoDialog::AddValidator(long id, bool *bptr)
{
	wxWindow *pWin = FindWindow(id);
	if (!pWin) return;
	wxGenericValidator *gv = new wxGenericValidator(bptr);
	pWin->SetValidator(*gv);
}

void AutoDialog::AddValidator(long id, int *iptr)
{
	wxWindow *pWin = FindWindow(id);
	if (!pWin) return;
	wxGenericValidator *gv = new wxGenericValidator(iptr);
	pWin->SetValidator(*gv);
}

void AutoDialog::AddNumValidator(long id, int *iptr)
{
	wxWindow *pWin = FindWindow(id);
	if (pWin)
	{
		wxNumericValidator *gv = new wxNumericValidator(iptr);
		pWin->SetValidator(*gv);
	}
}

void AutoDialog::AddNumValidator(long id, float *fptr, int digits)
{
	wxWindow *pWin = FindWindow(id);
	if (pWin)
	{
		wxNumericValidator *gv = new wxNumericValidator(fptr, digits);
		pWin->SetValidator(*gv);
	}
}

void AutoDialog::AddNumValidator(long id, double *dptr, int digits)
{
	wxWindow *pWin = FindWindow(id);
	if (pWin)
	{
		wxNumericValidator *gv = new wxNumericValidator(dptr, digits);
		pWin->SetValidator(*gv);
	}
}

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

BEGIN_EVENT_TABLE(AutoPanel, wxPanel)
EVT_INIT_DIALOG (AutoPanel::OnInitDialog)
END_EVENT_TABLE()

void AutoPanel::AddValidator(long id, wxString *sptr)
{
	wxWindow *pWin = FindWindow(id);
	if (!pWin) return;
	wxGenericValidator *gv = new wxGenericValidator(sptr);
	pWin->SetValidator(*gv);
}

void AutoPanel::AddValidator(long id, bool *bptr)
{
	wxWindow *pWin = FindWindow(id);
	if (!pWin) return;
	wxGenericValidator *gv = new wxGenericValidator(bptr);
	pWin->SetValidator(*gv);
}

void AutoPanel::AddValidator(long id, int *iptr)
{
	wxWindow *pWin = FindWindow(id);
	if (!pWin) return;
	wxGenericValidator *gv = new wxGenericValidator(iptr);
	pWin->SetValidator(*gv);
}

void AutoPanel::AddNumValidator(long id, int *iptr)
{
	wxWindow *pWin = FindWindow(id);
	if (pWin)
	{
		wxNumericValidator *gv = new wxNumericValidator(iptr);
		pWin->SetValidator(*gv);
	}
}

void AutoPanel::AddNumValidator(long id, float *fptr)
{
	wxWindow *pWin = FindWindow(id);
	if (pWin)
	{
		wxNumericValidator *gv = new wxNumericValidator(fptr);
		pWin->SetValidator(*gv);
	}
}

void AutoPanel::AddNumValidator(long id, double *dptr)
{
	wxWindow *pWin = FindWindow(id);
	if (pWin)
	{
		wxNumericValidator *gv = new wxNumericValidator(dptr);
		pWin->SetValidator(*gv);
	}
}

<commit_msg>fix to not display pointless trailing zeros<commit_after>//
// Implements the following classes:
//
// AutoDialog - An improvement to wxDialog which makes validation easier.
//
// AutoPanel - An improvement to wxPanel which makes validation easier.
//
// wxNumericValidator - A validator capable of transfering numeric values.
//
// Copyright (c) 2001-2003 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "AutoDialog.h"
#include "wxString2.h"

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

wxNumericValidator::wxNumericValidator(int *val) : wxValidator()
{
	Initialize();
	m_pValInt = val;
}

wxNumericValidator::wxNumericValidator(float *val, int digits) : wxValidator()
{
	Initialize();
	m_pValFloat = val;
	m_iDigits = digits;
}

wxNumericValidator::wxNumericValidator(double *val, int digits) : wxValidator()
{
	Initialize();
	m_pValDouble = val;
	m_iDigits = digits;
}

wxNumericValidator::wxNumericValidator(const wxNumericValidator& val)
{
	Copy(val);
}

bool wxNumericValidator::Copy(const wxNumericValidator& val)
{
	wxValidator::Copy(val);

	m_pValInt = val.m_pValInt;
	m_pValFloat = val.m_pValFloat;
	m_pValDouble = val.m_pValDouble;
	m_iDigits = val.m_iDigits;

	return TRUE;
}

// Called to transfer data to the window
bool wxNumericValidator::TransferToWindow()
{
	if ( !m_validatorWindow )
		return FALSE;

	wxString str, format;
	if (m_pValInt)
		str.Printf(_T("%d"), *m_pValInt);
	if (m_pValFloat)
	{
		if (m_iDigits != -1)
		{
			format.Printf(_T("%%.%df"), m_iDigits);
			str.Printf(format, *m_pValFloat);
		}
		else
			str.Printf(_T("%g"), *m_pValFloat);
	}
	if (m_pValDouble)
	{
		if (m_iDigits != -1)
		{
			format.Printf(_T("%%.%dlf"), m_iDigits);
			str.Printf(format, *m_pValDouble);
		}
		else
			str.Printf(_T("%lg"), *m_pValDouble);
	}

	if (m_validatorWindow->IsKindOf(CLASSINFO(wxStaticText)) )
	{
		wxStaticText* pControl = (wxStaticText*) m_validatorWindow;
		if (pControl)
		{
			pControl->SetLabel(str) ;
			return TRUE;
		}
	}
	else
	if (m_validatorWindow->IsKindOf(CLASSINFO(wxTextCtrl)) )
	{
		wxTextCtrl* pControl = (wxTextCtrl*) m_validatorWindow;
		if (pControl)
		{
			pControl->SetValue(str) ;
			return TRUE;
		}
	}
	else
		return FALSE;

	// unrecognized control, or bad pointer
	return FALSE;
}

// Called to transfer data from the window
bool wxNumericValidator::TransferFromWindow()
{
	if ( !m_validatorWindow )
		return FALSE;

	wxString2 str = _T("");
	// string controls
	if (m_validatorWindow->IsKindOf(CLASSINFO(wxStaticText)) )
	{
		wxStaticText* pControl = (wxStaticText*) m_validatorWindow;
		if (pControl)
			str = pControl->GetLabel() ;
	} else
	if (m_validatorWindow->IsKindOf(CLASSINFO(wxTextCtrl)) )
	{
		wxTextCtrl* pControl = (wxTextCtrl*) m_validatorWindow;
		if (pControl)
			str = pControl->GetValue() ;
	}
	else // unrecognized control, or bad pointer
		return FALSE;

	if (str != _T(""))
	{
		const char *ccs = str.mb_str();
		if (m_pValInt)
			sscanf(ccs, "%d", m_pValInt);
		if (m_pValFloat)
			sscanf(ccs, "%f", m_pValFloat);
		if (m_pValDouble)
			sscanf(ccs, "%lf", m_pValDouble);
		return TRUE;
	}
	return FALSE;
}

/*
  Called by constructors to initialize ALL data members
*/
void wxNumericValidator::Initialize()
{
	m_pValInt = NULL;
	m_pValFloat = NULL;
	m_pValDouble = NULL;
}

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

BEGIN_EVENT_TABLE(AutoDialog, wxDialog)
EVT_INIT_DIALOG (AutoDialog::OnInitDialog)
END_EVENT_TABLE()

void AutoDialog::AddValidator(long id, wxString *sptr)
{
	wxWindow *pWin = FindWindow(id);
	if (!pWin) return;
	wxGenericValidator *gv = new wxGenericValidator(sptr);
	pWin->SetValidator(*gv);
}

void AutoDialog::AddValidator(long id, bool *bptr)
{
	wxWindow *pWin = FindWindow(id);
	if (!pWin) return;
	wxGenericValidator *gv = new wxGenericValidator(bptr);
	pWin->SetValidator(*gv);
}

void AutoDialog::AddValidator(long id, int *iptr)
{
	wxWindow *pWin = FindWindow(id);
	if (!pWin) return;
	wxGenericValidator *gv = new wxGenericValidator(iptr);
	pWin->SetValidator(*gv);
}

void AutoDialog::AddNumValidator(long id, int *iptr)
{
	wxWindow *pWin = FindWindow(id);
	if (pWin)
	{
		wxNumericValidator *gv = new wxNumericValidator(iptr);
		pWin->SetValidator(*gv);
	}
}

void AutoDialog::AddNumValidator(long id, float *fptr, int digits)
{
	wxWindow *pWin = FindWindow(id);
	if (pWin)
	{
		wxNumericValidator *gv = new wxNumericValidator(fptr, digits);
		pWin->SetValidator(*gv);
	}
}

void AutoDialog::AddNumValidator(long id, double *dptr, int digits)
{
	wxWindow *pWin = FindWindow(id);
	if (pWin)
	{
		wxNumericValidator *gv = new wxNumericValidator(dptr, digits);
		pWin->SetValidator(*gv);
	}
}

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

BEGIN_EVENT_TABLE(AutoPanel, wxPanel)
EVT_INIT_DIALOG (AutoPanel::OnInitDialog)
END_EVENT_TABLE()

void AutoPanel::AddValidator(long id, wxString *sptr)
{
	wxWindow *pWin = FindWindow(id);
	if (!pWin) return;
	wxGenericValidator *gv = new wxGenericValidator(sptr);
	pWin->SetValidator(*gv);
}

void AutoPanel::AddValidator(long id, bool *bptr)
{
	wxWindow *pWin = FindWindow(id);
	if (!pWin) return;
	wxGenericValidator *gv = new wxGenericValidator(bptr);
	pWin->SetValidator(*gv);
}

void AutoPanel::AddValidator(long id, int *iptr)
{
	wxWindow *pWin = FindWindow(id);
	if (!pWin) return;
	wxGenericValidator *gv = new wxGenericValidator(iptr);
	pWin->SetValidator(*gv);
}

void AutoPanel::AddNumValidator(long id, int *iptr)
{
	wxWindow *pWin = FindWindow(id);
	if (pWin)
	{
		wxNumericValidator *gv = new wxNumericValidator(iptr);
		pWin->SetValidator(*gv);
	}
}

void AutoPanel::AddNumValidator(long id, float *fptr)
{
	wxWindow *pWin = FindWindow(id);
	if (pWin)
	{
		wxNumericValidator *gv = new wxNumericValidator(fptr);
		pWin->SetValidator(*gv);
	}
}

void AutoPanel::AddNumValidator(long id, double *dptr)
{
	wxWindow *pWin = FindWindow(id);
	if (pWin)
	{
		wxNumericValidator *gv = new wxNumericValidator(dptr);
		pWin->SetValidator(*gv);
	}
}

<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2014 Rapptz

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef JSONPP_PARSER_HPP
#define JSONPP_PARSER_HPP

#include "error.hpp"
#include "value.hpp"
#include <cstring>
#include <iosfwd>

namespace json {
inline namespace v1 {
namespace detail {
struct parser_state {
    unsigned line;
    unsigned column;
    const char* str;
};

inline bool is_space(char ch) {
    switch(ch) {
    case 0x0D: // carriage return
    case 0x09: // tab
    case 0x0A: // line feed
    case 0x20: // space
        return true;
    default:
        return false;
    }
}

inline void skip_white_space(parser_state& ps) {
    while(*ps.str != '\0' && is_space(*ps.str)) {
        if(*ps.str == 0x0A) {
            ++ps.line;
            ps.column = 0;
        }
        ++ps.str;
        ++ps.column;
    }
}

inline void parse_value(parser_state& ps, value& v);

inline void parse_null(parser_state& ps, value& v) {
    static const char null_str[] = "null";
    if(*ps.str == '\0') {
        throw parser_error("expected null, received EOF instead", ps.line, ps.column);
    }

    if(std::strncmp(ps.str, null_str, sizeof(null_str) - 1) != 0) {
        throw parser_error("expected null not found", ps.line, ps.column);
    }

    v = nullptr;
    ps.str = ps.str + sizeof(null_str) - 1;
    ps.column += sizeof(null_str);
}

inline void parse_number(parser_state& ps, value& v) {
    static const std::string lookup = "0123456789eE+-.";
    const char* begin = ps.str;
    if(*begin == '\0') {
        throw parser_error("expected number, received EOF instead", ps.line, ps.column);
    }

    while(lookup.find(*ps.str) != std::string::npos) {
        ++ps.str;
    }

    double val = 0.0;
    try {
        std::string temp(begin, ps.str);
        val = std::stod(temp);
        ps.column += temp.size() + 1;
    }
    catch(const std::exception& e) {
        throw parser_error("number could not be parsed properly", ps.line, ps.column);
    }

    v = val;
}

inline int get_codepoint(parser_state& ps, const char*& str) {
    int codepoint = 0;
    for(unsigned i = 0; i < 4; ++i) {
        char hex = *str;
        if(hex <= 0x1F) {
            throw parser_error("incomplete codepoint provided", ps.line, ps.column);
        }

        // convert the hex character to its integral representation
        // e.g., 'F' -> 15
        if(hex >= '0' && hex <= '9') {
            hex -= '0';
        }
        else if(hex >= 'A' && hex <= 'F') {
            hex -= 'A' - 0xA;
        }
        else if(hex >= 'a' && hex <= 'f') {
            hex -= 'a' - 0xA;
        }
        else {
            throw parser_error("invalid codepoint provided", ps.line, ps.column);
        }

        codepoint = codepoint * 16 + hex;
        ++ps.column;
        ++str;
    }
    return codepoint;
}

inline void parse_codepoint(parser_state& ps, const char*& str, std::string& result) {
    // parse the hex characters
    // in order to do so, we have to increment by one to get these digits.
    // ergo, *str == 'u', ++str = codepoint
    ++str;
    ++ps.column;
    int codepoint = get_codepoint(ps, str);

    // a regular ASCII code point
    if(codepoint < 0x80) {
        result.push_back(codepoint);
        return;
    }

    // handle surrogate pairs
    if(codepoint >= 0xD800 && codepoint <= 0xDFFF) {
        if(codepoint >= 0xDC00) {
            throw parser_error("low surrogate pair found but high surrogate pair expected", ps.line, ps.column);
        }

        // get the  low surrogate pair
        if(*(str + 1) != '\\' && *(str + 2) != 'u') {
            throw parser_error("low surrogate pair expected but not found", ps.line, ps.column);
        }

        str += 2;
        int low_surrogate = get_codepoint(ps, str);
        if(low_surrogate < 0xDC00 || low_surrogate > 0xDFFF) {
            throw parser_error("low surrogate out of range [\\uDC000, \\uDFFF]", ps.line, ps.column);
        }

        codepoint = 0x10000 + (((codepoint - 0xD800) << 10) | ((low_surrogate - 0xDC00) & 0x3FF));
    }

    if(codepoint < 0x800) {
        result.push_back(0xC0 | (codepoint >> 6));
    }
    else if(codepoint < 0x10000) {
        result.push_back(0xE0 | (codepoint >> 12));
    }
    else {
        result.push_back(0xF0 | (codepoint >> 18));
        result.push_back(0x80 | ((codepoint >> 12) & 0x3F));
    }
    result.push_back(0x80 | ((codepoint >> 6) & 0x3F));
    result.push_back(0x80 | (codepoint & 0x3F));
}

template<typename Value>
inline void parse_string(parser_state& ps, Value& v) {
    const char* str = ps.str + 1;
    if(*str == '\0') {
        throw parser_error("expected string, received EOF instead", ps.line, ps.column);
    }

    std::string result;

    // begin parsing
    while(true) {
        ++ps.column;
        bool increment_string = true;
        auto byte = static_cast<unsigned char>(*str);

        if(byte <= 0x1F) {
            throw parser_error("invalid characters found in string or string is incomplete", ps.line, ps.column);
        }

        // end of string found
        if(*str == '"') {
            break;
        }

        // non-escape character is good to go
        if(*str != '\\') {
            result.push_back(*str++);
            continue;
        }

        // at this point *str == '\\'
        // so increment it to check the next character
        ++str;
        switch(*str) {
        case '/':
            result.push_back('/');
            break;
        case '\\':
            result.push_back('\\');
            break;
        case '"':
            result.push_back('\"');
            break;
        case 'f':
            result.push_back('\f');
            break;
        case 'n':
            result.push_back('\n');
            break;
        case 'r':
            result.push_back('\r');
            break;
        case 't':
            result.push_back('\t');
            break;
        case 'b':
            result.push_back('\b');
            break;
        case 'u':
            parse_codepoint(ps, str, result);
            increment_string = false;
            break;
        default:
            throw parser_error("improper or incomplete escape character found", ps.line, ps.column);
        }

        if(increment_string) {
            ++str;
        }
    }

    v = result;
    ++str;
    ps.str = str;
}

inline void parse_bool(parser_state& ps, value& v) {
    if(*ps.str == '\0') {
        throw parser_error("expected boolean, received EOF instead", ps.line, ps.column);
    }

    bool expected_true = *ps.str == 't';
    const char* boolean = expected_true ? "true" : "false";
    const size_t len = expected_true ? 4 : 5;

    if(std::strncmp(ps.str, boolean, len) != 0) {
        throw parser_error("expected boolean not found", ps.line, ps.column);
    }

    v = expected_true;
    ps.str = ps.str + len;
    ps.column += len;
}

inline void parse_array(parser_state& ps, value& v) {
    ++ps.str;
    array arr;
    value elem;
    skip_white_space(ps);

    if(*ps.str == '\0') {
        throw parser_error("expected value, received EOF instead", ps.line, ps.column);
    }

    while (*ps.str && *ps.str != ']') {
        parse_value(ps, elem);
        if(*ps.str != ',') {
            if(*ps.str != ']') {
                throw parser_error("missing comma", ps.line, ps.column);
            }
        }
        else if(*ps.str == ',') {
            ++ps.str;
            // skip whitespace
            skip_white_space(ps);
            // handle missing input
            if(*ps.str && *ps.str == ']') {
                throw parser_error("extraneous comma spotted", ps.line, ps.column);
            }
        }

        arr.push_back(elem);
    }

    v = arr;
    if(*ps.str == ']') {
        ++ps.str;
    }
}

inline void parse_object(parser_state& ps, value& v) {
    ++ps.str;
    object obj;
    std::string key;
    value elem;

    skip_white_space(ps);

    if(*ps.str == '\0') {
        throw parser_error("expected string key, received EOF instead", ps.line, ps.column);
    }

    while(*ps.str) {
        skip_white_space(ps);

        // empty object
        if(*ps.str == '}') {
            break;
        }

        if(*ps.str != '"') {
            throw parser_error("expected string as key not found", ps.line, ps.column);
        }
        parse_string(ps, key);
        skip_white_space(ps);

        if(*ps.str != ':') {
            throw parser_error("missing semicolon", ps.line, ps.column);
        }
        ++ps.str;
        parse_value(ps, elem);

        if(*ps.str != ',') {
            if(*ps.str != '}') {
                throw parser_error("missing comma", ps.line, ps.column);
            }
        }
        else if(*ps.str == ',') {
            ++ps.str;
        }
        obj.emplace(key, elem);
    }

    v = obj;
    if(*ps.str == '}') {
        ++ps.str;
    }
}

inline void parse_value(parser_state& ps, value& v) {
    skip_white_space(ps);
    if(*ps.str == '\0') {
        throw parser_error("unexpected EOF found", ps.line, ps.column);
    }

    if(isdigit(*ps.str) || *ps.str == '+' || *ps.str == '-') {
        parse_number(ps, v);
    }
    else {
        switch(*ps.str) {
        case 'n':
            parse_null(ps, v);
            break;
        case '"':
            parse_string(ps, v);
            break;
        case 't':
        case 'f':
            parse_bool(ps, v);
            break;
        case '[':
            parse_array(ps, v);
            break;
        case '{':
            parse_object(ps, v);
            break;
        default:
            throw parser_error("unexpected token found", ps.line, ps.column);
            break;
        }
    }

    skip_white_space(ps);
}
} // detail

inline void parse(const std::string& str, value& v) {
    detail::parser_state ps = { 1, 1, str.c_str() };
    detail::parse_value(ps, v);
    if(*ps.str != '\0') {
        throw parser_error("unexpected token found", ps.line, ps.column);
    }
}

template<typename IStream, DisableIf<is_string<IStream>> = 0>
inline void parse(IStream& in, value& v) {
    static_assert(std::is_base_of<std::istream, IStream>::value, "Input stream passed must inherit from std::istream");
    if(in) {
        std::ostringstream ss;
        ss << in.rdbuf();
        parse(ss.str(), v);
    }
}
} // v1
} // json

#endif // JSONPP_PARSER_HPP
<commit_msg>Move parsing to its own object.<commit_after>// The MIT License (MIT)

// Copyright (c) 2014 Rapptz

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef JSONPP_PARSER_HPP
#define JSONPP_PARSER_HPP

#include "error.hpp"
#include "value.hpp"
#include <cstring>
#include <iosfwd>

namespace json {
inline namespace v1 {
inline bool is_space(char ch) {
    switch(ch) {
    case 0x0D: // carriage return
    case 0x09: // tab
    case 0x0A: // line feed
    case 0x20: // space
        return true;
    default:
        return false;
    }
}

struct parser {
private:
    unsigned line = 1;
    unsigned column = 1;
    const char* str;

    void skip_white_space() {
        while(*str != '\0' && is_space(*str)) {
            if(*str == 0x0A) {
                ++line;
                column = 0;
            }
            ++str;
            ++column;
        }
    }

    void parse_null(value& v) {
        static const char null_str[] = "null";
        if(*str == '\0') {
            throw parser_error("expected null, received EOF instead", line, column);
        }

        if(std::strncmp(str, null_str, sizeof(null_str) - 1) != 0) {
            throw parser_error("expected null not found", line, column);
        }

        v = nullptr;
        str = str + sizeof(null_str) - 1;
        column += sizeof(null_str);
    }

    void parse_number(value& v) {
        static const std::string lookup = "0123456789eE+-.";
        const char* begin = str;
        if(*begin == '\0') {
            throw parser_error("expected number, received EOF instead", line, column);
        }

        while(lookup.find(*str) != std::string::npos) {
            ++str;
        }

        double val = 0.0;
        try {
            std::string temp(begin, str);
            val = std::stod(temp);
            column += temp.size() + 1;
        }
        catch(const std::exception& e) {
            throw parser_error("number could not be parsed properly", line, column);
        }

        v = val;
    }

    int get_codepoint(const char*& copy) {
        int codepoint = 0;
        for(unsigned i = 0; i < 4; ++i) {
            char hex = *copy;
            if(hex <= 0x1F) {
                throw parser_error("incomplete codepoint provided", line, column);
            }

            // convert the hex character to its integral representation
            // e.g., 'F' -> 15
            if(hex >= '0' && hex <= '9') {
                hex -= '0';
            }
            else if(hex >= 'A' && hex <= 'F') {
                hex -= 'A' - 0xA;
            }
            else if(hex >= 'a' && hex <= 'f') {
                hex -= 'a' - 0xA;
            }
            else {
                throw parser_error("invalid codepoint provided", line, column);
            }

            codepoint = codepoint * 16 + hex;
            ++column;
            ++copy;
        }
        return codepoint;
    }

    void parse_codepoint(const char*& copy, std::string& result) {
        // parse the hex characters
        // in order to do so, we have to increment by one to get these digits.
        // ergo, *copy == 'u', ++copy = codepoint
        ++copy;
        ++column;
        int codepoint = get_codepoint(copy);

        // a regular ASCII code point
        if(codepoint < 0x80) {
            result.push_back(codepoint);
            return;
        }

        // handle surrogate pairs
        if(codepoint >= 0xD800 && codepoint <= 0xDFFF) {
            if(codepoint >= 0xDC00) {
                throw parser_error("low surrogate pair found but high surrogate pair expected", line, column);
            }

            // get the  low surrogate pair
            if(*(copy + 1) != '\\' && *(copy + 2) != 'u') {
                throw parser_error("low surrogate pair expected but not found", line, column);
            }

            copy += 2;
            int low_surrogate = get_codepoint(copy);
            if(low_surrogate < 0xDC00 || low_surrogate > 0xDFFF) {
                throw parser_error("low surrogate out of range [\\uDC000, \\uDFFF]", line, column);
            }

            codepoint = 0x10000 + (((codepoint - 0xD800) << 10) | ((low_surrogate - 0xDC00) & 0x3FF));
        }

        if(codepoint < 0x800) {
            result.push_back(0xC0 | (codepoint >> 6));
        }
        else if(codepoint < 0x10000) {
            result.push_back(0xE0 | (codepoint >> 12));
        }
        else {
            result.push_back(0xF0 | (codepoint >> 18));
            result.push_back(0x80 | ((codepoint >> 12) & 0x3F));
        }
        result.push_back(0x80 | ((codepoint >> 6) & 0x3F));
        result.push_back(0x80 | (codepoint & 0x3F));
    }

    template<typename Value>
    void parse_string(Value& v) {
        const char* copy = str + 1;
        if(*copy == '\0') {
            throw parser_error("expected string, received EOF instead", line, column);
        }

        std::string result;

        // begin parsing
        while(true) {
            ++column;
            bool increment_string = true;
            auto byte = static_cast<unsigned char>(*copy);

            if(byte <= 0x1F) {
                throw parser_error("invalid characters found in string or string is incomplete", line, column);
            }

            // end of string found
            if(*copy == '"') {
                break;
            }

            // non-escape character is good to go
            if(*copy != '\\') {
                result.push_back(*copy++);
                continue;
            }

            // at this point *copy == '\\'
            // so increment it to check the next character
            ++copy;
            switch(*copy) {
            case '/':
                result.push_back('/');
                break;
            case '\\':
                result.push_back('\\');
                break;
            case '"':
                result.push_back('\"');
                break;
            case 'f':
                result.push_back('\f');
                break;
            case 'n':
                result.push_back('\n');
                break;
            case 'r':
                result.push_back('\r');
                break;
            case 't':
                result.push_back('\t');
                break;
            case 'b':
                result.push_back('\b');
                break;
            case 'u':
                parse_codepoint(copy, result);
                increment_string = false;
                break;
            default:
                throw parser_error("improper or incomplete escape character found", line, column);
            }

            if(increment_string) {
                ++copy;
            }
        }

        v = result;
        ++copy;
        str = copy;
    }

    void parse_bool(value& v) {
        if(*str == '\0') {
            throw parser_error("expected boolean, received EOF instead", line, column);
        }

        bool expected_true = *str == 't';
        const char* boolean = expected_true ? "true" : "false";
        const size_t len = expected_true ? 4 : 5;

        if(std::strncmp(str, boolean, len) != 0) {
            throw parser_error("expected boolean not found", line, column);
        }

        v = expected_true;
        str = str + len;
        column += len;
    }

    void parse_array(value& v) {
        ++str;
        array arr;
        value elem;
        skip_white_space();

        if(*str == '\0') {
            throw parser_error("expected value, received EOF instead", line, column);
        }

        while (*str && *str != ']') {
            parse_value(elem);
            if(*str != ',') {
                if(*str != ']') {
                    throw parser_error("missing comma", line, column);
                }
            }
            else if(*str == ',') {
                ++str;
                // skip whitespace
                skip_white_space();
                // handle missing input
                if(*str && *str == ']') {
                    throw parser_error("extraneous comma spotted", line, column);
                }
            }

            arr.push_back(elem);
        }

        v = arr;
        if(*str == ']') {
            ++str;
        }
    }

    void parse_object(value& v) {
        ++str;
        object obj;
        std::string key;
        value elem;

        skip_white_space();

        if(*str == '\0') {
            throw parser_error("expected string key, received EOF instead", line, column);
        }

        while(*str) {
            skip_white_space();

            // empty object
            if(*str == '}') {
                break;
            }

            if(*str != '"') {
                throw parser_error("expected string as key not found", line, column);
            }
            parse_string(key);
            skip_white_space();

            if(*str != ':') {
                throw parser_error("missing semicolon", line, column);
            }
            ++str;
            parse_value(elem);

            if(*str != ',') {
                if(*str != '}') {
                    throw parser_error("missing comma", line, column);
                }
            }
            else if(*str == ',') {
                ++str;
            }
            obj.emplace(key, elem);
        }

        v = obj;
        if(*str == '}') {
            ++str;
        }
    }

    void parse_value(value& v) {
        skip_white_space();
        if(*str == '\0') {
            throw parser_error("unexpected EOF found", line, column);
        }

        if(isdigit(*str) || *str == '+' || *str == '-') {
            parse_number(v);
        }
        else {
            switch(*str) {
            case 'n':
                parse_null(v);
                break;
            case '"':
                parse_string(v);
                break;
            case 't':
            case 'f':
                parse_bool(v);
                break;
            case '[':
                parse_array(v);
                break;
            case '{':
                parse_object(v);
                break;
            default:
                throw parser_error("unexpected token found", line, column);
                break;
            }
        }

        skip_white_space();
    }
public:
    parser(const char* str) noexcept: str(str) {}

    void parse(value& v) {
        parse_value(v);
        if(*str != '\0') {
            throw parser_error("unexpected token found", line, column);
        }
    }
};

inline void parse(const std::string& str, value& v) {
    parser js(str.c_str());
    js.parse(v);
}

template<typename IStream, DisableIf<is_string<IStream>> = 0>
inline void parse(IStream& in, value& v) {
    static_assert(std::is_base_of<std::istream, IStream>::value, "Input stream passed must inherit from std::istream");
    if(in) {
        std::ostringstream ss;
        ss << in.rdbuf();
        parse(ss.str(), v);
    }
}
} // v1
} // json

#endif // JSONPP_PARSER_HPP
<|endoftext|>


<commit_before>#ifndef __WORD_TAG_HPP__
#define __WORD_TAG_HPP__

#include <vector>
#include <map>
#include <set>

#undef assert
#include "lg_assert.h"

extern "C" {
#include "connectors.h"
#include "dict-common/dict-common.h"
#include "tokenize/tok-structures.h"    // gword_set
#include "tokenize/wordgraph.h"         // in_same_alternative()
};

#include "variables.hpp"

struct PositionConnector
{
  PositionConnector(Exp* pe, Exp* e, char d, int w, int p,
                    double cst, double pcst, bool lr, bool ll,
                    const std::vector<int>& er, const std::vector<int>& el, const X_node *w_xnode, Parse_Options opts)
    : exp(pe), dir(d), word(w), position(p),
      cost(cst), parent_cost(pcst),
      leading_right(lr), leading_left(ll),
      eps_right(er), eps_left(el), word_xnode(w_xnode)
  {
    if (word_xnode == NULL) {
       cerr << "Internal error: Word" << w << ": " << "; connector: '" << e->u.condesc->string << "'; X_node: " << (word_xnode?word_xnode->string: "(null)") << endl;
    }

    // Initialize some fields in the connector struct.
    connector.desc = e->u.condesc;
    connector.multi = e->multi;
    set_connector_length_limit(&connector, opts);
    connector.originating_gword = &w_xnode->word->gword_set_head;

    /*
    cout << c->string << " : ." << w << ". : ." << p << ". ";
    if (leading_right) {
      cout << "lr: ";
      copy(er.begin(), er.end(), ostream_iterator<int>(cout, " "));
    }
    if (leading_left) {
      cout << "ll: ";
      copy(el.begin(), el.end(), ostream_iterator<int>(cout, " "));
    }
    cout << endl;
    */
  }

  // Added only to suppress the warning:
  // warning: inlining failed in call to ‘PositionConnector::~PositionConnector() noexcept’: call is unlikely and code size would grow [-Winline]
  // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70328
  // Can be removed when this GCC problem is fixed.
  ~PositionConnector() {};

  // Original expression that this connector came from
  Exp* exp;

  // Connector itself
  Connector connector;
  // Direction
  char dir;
  // word in a sentence that this connector belongs to
  size_t word;
  // position in the word tag
  int position;
  // cost of the connector
  double cost;
  // parent cost
  double parent_cost;

  bool leading_right;
  bool leading_left;
  std::vector<int> eps_right;
  std::vector<int> eps_left;

  // The corresponding X_node - chosen-disjuncts[]
  const X_node *word_xnode;

  // Matches with other words
  std::vector<PositionConnector*> matches;

};

/*
 * Record the SAT variable and cost of costly-null expressions.
 * Their cost is recovered (in sat_extract_links()) if
 * they happen to reside on a participating disjunct.
 */
struct EmptyConnector {
  EmptyConnector(int var, double cst)
    : ec_var(var), ec_cost(cst)
  {
  }
  int ec_var;
  double ec_cost;
};

// XXX TODO: Hash connectors for faster matching

class WordTag
{
private:
  std::vector<PositionConnector> _left_connectors;
  std::vector<PositionConnector> _right_connectors;
  std::vector<EmptyConnector> _empty_connectors;

  std::vector<char> _dir;
  std::vector<int> _position;

  int _word;
  Variables* _variables;

  Sentence _sent;
  Parse_Options _opts;

  // Could this word tag match a connector (wi, pi)?
  // For each word wi I keep a set of positions pi that can be matched
  std::vector< std::set<int> > _match_possible;
  void set_match_possible(int wj, int pj) {
    _match_possible[wj].insert(pj);
  }

public:
  WordTag(int word, Variables* variables, Sentence sent, Parse_Options opts)
    : _word(word), _variables(variables), _sent(sent), _opts(opts) {
    _match_possible.resize(_sent->length);

    verbosity = opts->verbosity;
    debug = opts->debug;
    test = opts->test;
  }

  // Added only to suppress the warning:
  // warning: inlining failed in call to ‘WordTag::~WordTag() noexcept’: call is unlikely and code size would grow [-Winline]
  // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70328
  // Can be removed when this GCC problem is fixed.
  ~WordTag() {};

  const std::vector<PositionConnector>& get_left_connectors() const {
    return _left_connectors;
  }

  const std::vector<PositionConnector>& get_right_connectors() const {
    return _right_connectors;
  }

  const std::vector<EmptyConnector>& get_empty_connectors() const {
    return _empty_connectors;
  }

  PositionConnector* get(int dfs_position)
  {
    switch (_dir[dfs_position - 1]) {
    case '+':
      return &_right_connectors[_position[dfs_position - 1]];
    case '-':
      return &_left_connectors[_position[dfs_position - 1]];
    }
    return NULL;
  }

#define OPTIMIZE_EN
  static bool alt_connectivity_possible(Connector& c1, Connector & c2)
  {
#ifdef OPTIMIZE_EN
  /* Try a shortcut first. */
  if ((c2.originating_gword->o_gword->hier_depth == 0) ||
     (c1.originating_gword->o_gword->hier_depth == 0)) return true;
#endif // OPTIMIZE_EN

    return in_same_alternative(c1.originating_gword->o_gword, c2.originating_gword->o_gword);
  }

  bool match(int w1, Connector& cntr1, char dir, int w2, Connector& cntr2)
  {
      int dist = w2 - w1;
      assert(0 < dist, "match() did not receive words in the natural order.");
      if (dist > cntr1.length_limit || dist > cntr2.length_limit) return false;
      if (!alt_connectivity_possible(cntr1, cntr2)) return false;
      return easy_match_desc(cntr1.desc, cntr2.desc);
  }

  void insert_connectors(Exp* exp, int& dfs_position,
                         bool& leading_right, bool& leading_left,
                         std::vector<int>& eps_right,
                         std::vector<int>& eps_left,
                         char* var, bool root, double parent_cost,
                         Exp* parent, const X_node *word_xnode);

  // Caches information about the found matches to the _matches vector, and also
  // updates the _matches vector of all connectors in the given tag.
  // In order to have all possible matches correctly cached, the function assumes that it is
  // iteratively called for all words in the sentence, where the tag is on the right side of
  // this word
  void add_matches_with_word(WordTag& tag);

  // Find matches in this word tag with the connector (name, dir).
  void find_matches(int w, Connector* C, char dir,  std::vector<PositionConnector*>& matches);

  // A simpler function: Can any connector in this word match a connector wi, pi?
  // It is assumed that
  bool match_possible(int wi, int pi)
  {
    return _match_possible[wi].find(pi) != _match_possible[wi].end();
  }

private:
  int verbosity;
  const char *debug;
  const char *test;
};

#endif
<commit_msg>word-tag.hpp: Reorder include for consistency<commit_after>#ifndef __WORD_TAG_HPP__
#define __WORD_TAG_HPP__

#include <vector>
#include <map>
#include <set>

#include "variables.hpp"

#undef assert
#include "lg_assert.h"

extern "C" {
#include "connectors.h"
#include "dict-common/dict-common.h"
#include "tokenize/tok-structures.h"    // gword_set
#include "tokenize/wordgraph.h"         // in_same_alternative()
};

struct PositionConnector
{
  PositionConnector(Exp* pe, Exp* e, char d, int w, int p,
                    double cst, double pcst, bool lr, bool ll,
                    const std::vector<int>& er, const std::vector<int>& el, const X_node *w_xnode, Parse_Options opts)
    : exp(pe), dir(d), word(w), position(p),
      cost(cst), parent_cost(pcst),
      leading_right(lr), leading_left(ll),
      eps_right(er), eps_left(el), word_xnode(w_xnode)
  {
    if (word_xnode == NULL) {
       cerr << "Internal error: Word" << w << ": " << "; connector: '" << e->u.condesc->string << "'; X_node: " << (word_xnode?word_xnode->string: "(null)") << endl;
    }

    // Initialize some fields in the connector struct.
    connector.desc = e->u.condesc;
    connector.multi = e->multi;
    set_connector_length_limit(&connector, opts);
    connector.originating_gword = &w_xnode->word->gword_set_head;

    /*
    cout << c->string << " : ." << w << ". : ." << p << ". ";
    if (leading_right) {
      cout << "lr: ";
      copy(er.begin(), er.end(), ostream_iterator<int>(cout, " "));
    }
    if (leading_left) {
      cout << "ll: ";
      copy(el.begin(), el.end(), ostream_iterator<int>(cout, " "));
    }
    cout << endl;
    */
  }

  // Added only to suppress the warning:
  // warning: inlining failed in call to ‘PositionConnector::~PositionConnector() noexcept’: call is unlikely and code size would grow [-Winline]
  // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70328
  // Can be removed when this GCC problem is fixed.
  ~PositionConnector() {};

  // Original expression that this connector came from
  Exp* exp;

  // Connector itself
  Connector connector;
  // Direction
  char dir;
  // word in a sentence that this connector belongs to
  size_t word;
  // position in the word tag
  int position;
  // cost of the connector
  double cost;
  // parent cost
  double parent_cost;

  bool leading_right;
  bool leading_left;
  std::vector<int> eps_right;
  std::vector<int> eps_left;

  // The corresponding X_node - chosen-disjuncts[]
  const X_node *word_xnode;

  // Matches with other words
  std::vector<PositionConnector*> matches;

};

/*
 * Record the SAT variable and cost of costly-null expressions.
 * Their cost is recovered (in sat_extract_links()) if
 * they happen to reside on a participating disjunct.
 */
struct EmptyConnector {
  EmptyConnector(int var, double cst)
    : ec_var(var), ec_cost(cst)
  {
  }
  int ec_var;
  double ec_cost;
};

// XXX TODO: Hash connectors for faster matching

class WordTag
{
private:
  std::vector<PositionConnector> _left_connectors;
  std::vector<PositionConnector> _right_connectors;
  std::vector<EmptyConnector> _empty_connectors;

  std::vector<char> _dir;
  std::vector<int> _position;

  int _word;
  Variables* _variables;

  Sentence _sent;
  Parse_Options _opts;

  // Could this word tag match a connector (wi, pi)?
  // For each word wi I keep a set of positions pi that can be matched
  std::vector< std::set<int> > _match_possible;
  void set_match_possible(int wj, int pj) {
    _match_possible[wj].insert(pj);
  }

public:
  WordTag(int word, Variables* variables, Sentence sent, Parse_Options opts)
    : _word(word), _variables(variables), _sent(sent), _opts(opts) {
    _match_possible.resize(_sent->length);

    verbosity = opts->verbosity;
    debug = opts->debug;
    test = opts->test;
  }

  // Added only to suppress the warning:
  // warning: inlining failed in call to ‘WordTag::~WordTag() noexcept’: call is unlikely and code size would grow [-Winline]
  // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70328
  // Can be removed when this GCC problem is fixed.
  ~WordTag() {};

  const std::vector<PositionConnector>& get_left_connectors() const {
    return _left_connectors;
  }

  const std::vector<PositionConnector>& get_right_connectors() const {
    return _right_connectors;
  }

  const std::vector<EmptyConnector>& get_empty_connectors() const {
    return _empty_connectors;
  }

  PositionConnector* get(int dfs_position)
  {
    switch (_dir[dfs_position - 1]) {
    case '+':
      return &_right_connectors[_position[dfs_position - 1]];
    case '-':
      return &_left_connectors[_position[dfs_position - 1]];
    }
    return NULL;
  }

#define OPTIMIZE_EN
  static bool alt_connectivity_possible(Connector& c1, Connector & c2)
  {
#ifdef OPTIMIZE_EN
  /* Try a shortcut first. */
  if ((c2.originating_gword->o_gword->hier_depth == 0) ||
     (c1.originating_gword->o_gword->hier_depth == 0)) return true;
#endif // OPTIMIZE_EN

    return in_same_alternative(c1.originating_gword->o_gword, c2.originating_gword->o_gword);
  }

  bool match(int w1, Connector& cntr1, char dir, int w2, Connector& cntr2)
  {
      int dist = w2 - w1;
      assert(0 < dist, "match() did not receive words in the natural order.");
      if (dist > cntr1.length_limit || dist > cntr2.length_limit) return false;
      if (!alt_connectivity_possible(cntr1, cntr2)) return false;
      return easy_match_desc(cntr1.desc, cntr2.desc);
  }

  void insert_connectors(Exp* exp, int& dfs_position,
                         bool& leading_right, bool& leading_left,
                         std::vector<int>& eps_right,
                         std::vector<int>& eps_left,
                         char* var, bool root, double parent_cost,
                         Exp* parent, const X_node *word_xnode);

  // Caches information about the found matches to the _matches vector, and also
  // updates the _matches vector of all connectors in the given tag.
  // In order to have all possible matches correctly cached, the function assumes that it is
  // iteratively called for all words in the sentence, where the tag is on the right side of
  // this word
  void add_matches_with_word(WordTag& tag);

  // Find matches in this word tag with the connector (name, dir).
  void find_matches(int w, Connector* C, char dir,  std::vector<PositionConnector*>& matches);

  // A simpler function: Can any connector in this word match a connector wi, pi?
  // It is assumed that
  bool match_possible(int wi, int pi)
  {
    return _match_possible[wi].find(pi) != _match_possible[wi].end();
  }

private:
  int verbosity;
  const char *debug;
  const char *test;
};

#endif
<|endoftext|>


<commit_before>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#ifndef __SFI_H__
#define __SFI_H__

// We're migrating to Bse for everything and use Rapicorn core for the lower level stuff
#include <rapicorn-core.hh>
namespace Bse {
using namespace Rapicorn;
} // Bse

/* no bin-compat: #include <sfi/sficomwire.hh> */
#include <sfi/sficomport.hh>
#include <sfi/sfifilecrawler.hh>
#include <sfi/sfiglue.hh>
#include <sfi/sfigluecodec.hh>
#include <sfi/sfiglueproxy.hh>
#include <sfi/sfimemory.hh>
#include <sfi/sfinote.hh>
#include <sfi/sfiparams.hh>
#include <sfi/sfiprimitives.hh>
#include <sfi/sfiring.hh>
/* #include <sfi/sfisclock.hh> */
#include <sfi/sfiserial.hh>
/* no bin-compat: #include <sfi/sfistore.hh> */
#include <sfi/sfitime.hh>
#include <sfi/sfitypes.hh>
#include <sfi/sfiustore.hh>
#include <sfi/sfivalues.hh>
#include <sfi/sfivmarshal.hh>
#include <sfi/sfiwrapper.hh>

#endif /* __SFI_H__ */

/* vim:set ts=8 sts=2 sw=2: */
<commit_msg>SFI: add global 'using' for very common utilities from Rapicorn<commit_after>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#ifndef __SFI_H__
#define __SFI_H__

// == Rapicorn Imports ==
#include <rapicorn-core.hh>     // We move to Rapicorn core for low level stuff
using Rapicorn::printerr;
using Rapicorn::printout;
using Rapicorn::string_format;
using Rapicorn::Any;
typedef std::string String;

namespace Sfi {
using namespace Rapicorn;
} // Sfi
namespace Bse {
using namespace Rapicorn;
} // Bse

/* no bin-compat: #include <sfi/sficomwire.hh> */
#include <sfi/sficomport.hh>
#include <sfi/sfifilecrawler.hh>
#include <sfi/sfiglue.hh>
#include <sfi/sfigluecodec.hh>
#include <sfi/sfiglueproxy.hh>
#include <sfi/sfimemory.hh>
#include <sfi/sfinote.hh>
#include <sfi/sfiparams.hh>
#include <sfi/sfiprimitives.hh>
#include <sfi/sfiring.hh>
/* #include <sfi/sfisclock.hh> */
#include <sfi/sfiserial.hh>
/* no bin-compat: #include <sfi/sfistore.hh> */
#include <sfi/sfitime.hh>
#include <sfi/sfitypes.hh>
#include <sfi/sfiustore.hh>
#include <sfi/sfivalues.hh>
#include <sfi/sfivmarshal.hh>
#include <sfi/sfiwrapper.hh>

#endif /* __SFI_H__ */

/* vim:set ts=8 sts=2 sw=2: */
<|endoftext|>


<commit_before>//===-- SPUTargetAsmInfo.cpp - Cell SPU asm properties ----------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the SPUTargetAsmInfo properties.
//
//===----------------------------------------------------------------------===//

#include "SPUTargetAsmInfo.h"
#include "SPUTargetMachine.h"
#include "llvm/Function.h"
#include "llvm/Support/Compiler.h"

using namespace llvm;

SPULinuxTargetAsmInfo::SPULinuxTargetAsmInfo(const SPUTargetMachine &TM) :
    SPUTargetAsmInfo<ELFTargetAsmInfo>(TM) {
  PCSymbol = ".";
  CommentString = "#";
  GlobalPrefix = "";
  PrivateGlobalPrefix = ".L";
}

/// PreferredEHDataFormat - This hook allows the target to select data
/// format used for encoding pointers in exception handling data. Reason is
/// 0 for data, 1 for code labels, 2 for function pointers. Global is true
/// if the symbol can be relocated.
unsigned
SPULinuxTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
                                             bool Global) const {
  // We really need to write something here.
  return TargetAsmInfo::PreferredEHDataFormat(Reason, Global);
}

// Instantiate default implementation.
TEMPLATE_INSTANTIATION(class SPUTargetAsmInfo<TargetAsmInfo>);
<commit_msg>CellSPU: Ensure that C strings are always put in the .rodata section<commit_after>//===-- SPUTargetAsmInfo.cpp - Cell SPU asm properties ----------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the SPUTargetAsmInfo properties.
//
//===----------------------------------------------------------------------===//

#include "SPUTargetAsmInfo.h"
#include "SPUTargetMachine.h"
#include "llvm/Function.h"
#include "llvm/Support/Compiler.h"

using namespace llvm;

SPULinuxTargetAsmInfo::SPULinuxTargetAsmInfo(const SPUTargetMachine &TM) :
    SPUTargetAsmInfo<ELFTargetAsmInfo>(TM) {
  PCSymbol = ".";
  CommentString = "#";
  GlobalPrefix = "";
  PrivateGlobalPrefix = ".L";
  CStringSection = ".rodata";
}

/// PreferredEHDataFormat - This hook allows the target to select data
/// format used for encoding pointers in exception handling data. Reason is
/// 0 for data, 1 for code labels, 2 for function pointers. Global is true
/// if the symbol can be relocated.
unsigned
SPULinuxTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
                                             bool Global) const {
  // We really need to write something here.
  return TargetAsmInfo::PreferredEHDataFormat(Reason, Global);
}

// Instantiate default implementation.
TEMPLATE_INSTANTIATION(class SPUTargetAsmInfo<TargetAsmInfo>);
<|endoftext|>