<commit_before>/*
 * API for aborting asynchronous operations.
 *
 * The idea behind it is that functions starting an asynchronous
 * operation return a pointer to a struct async_operation, which can
 * be used to call async_operation_ref::Abort().
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

/*
 * How to implement and use it:
 *
 * The code starts an asynchronous operation by calling a C function.
 * It passes an operation specific callback function and a pointer to
 * a struct async_operation_ref.
 *
 * When the operation completes (either success or failure), the
 * callback is invoked (note that the callback may be invoked before
 * the function which initiated the operation returns).  The callback
 * is invoked exactly once.
 *
 * There is one exception to this rule: the async_operation_ref struct
 * can be used to abort the operation by calling
 * async_operation_ref::Abort().  In this case, the callback is not
 * invoked.
 *
 */

#ifndef ASYNC_HXX
#define ASYNC_HXX

#include "util/Cast.hxx"

#include <inline/compiler.h>

#include <assert.h>

struct async_operation;

struct async_operation_class {
    void (*abort)(struct async_operation *ao);
};

struct async_operation {
    struct async_operation_class cls;

#ifndef NDEBUG
    bool finished;

    bool aborted;
#endif

    void Init(const struct async_operation_class &_cls) {
        cls = _cls;

#ifndef NDEBUG
        finished = false;
        aborted = false;
#endif
    }

    template<typename T,
             async_operation T::*operation_member = &T::operation,
             void (T::*abort_member)() = &T::Abort>
    struct Generator {
        static void Abort(async_operation *ao) {
            T &t = ContainerCast2<T, async_operation>(*ao, operation_member);
            (t.*abort_member)();
        }

        static const struct async_operation_class cls;
    };

    template<typename T,
             async_operation T::*operation_member = &T::operation,
             void (T::*abort_member)() = &T::Abort>
    void Init2() {
        Init(Generator<T, operation_member, abort_member>::cls);
    }

    void Abort() {
        assert(!finished);
        assert(!aborted);

#ifndef NDEBUG
        aborted = true;
#endif

        cls.abort(this);
    }

    /**
     * Mark this operation as "finished".  This is a no-op in the
     * NDEBUG build.
     */
    void Finished() {
        assert(!finished);
        assert(!aborted);

#ifndef NDEBUG
        finished = true;
#endif
    }
};

template<class T,
         async_operation T::*operation_member,
         void (T::*abort_member)()>
const struct async_operation_class async_operation::Generator<T, operation_member, abort_member>::cls = {
    .abort = Abort,
};

struct async_operation_ref {
    struct async_operation *operation;

#ifndef NDEBUG
    /**
     * A copy of the "operation" pointer, for post-mortem debugging.
     */
    struct async_operation *copy;
#endif

    constexpr bool IsDefined() const {
        return operation != nullptr;
    }

    void Clear() {
        operation = nullptr;
    }

    void Poison() {
#ifndef NDEBUG
        operation = (struct async_operation *)0x03030303;
#endif
    }

    void Set(struct async_operation &ao) {
        assert(!ao.finished);
        assert(!ao.aborted);

        operation = &ao;
#ifndef NDEBUG
        copy = &ao;
#endif
    }

    void Abort() {
        assert(operation != nullptr);
        assert(operation == copy);

        struct async_operation &ao = *operation;
#ifndef NDEBUG
        operation = nullptr;
#endif

        ao.Abort();
    }

    void AbortAndClear() {
        assert(operation != nullptr);
        assert(operation == copy);

        struct async_operation &ao = *operation;
        operation = nullptr;

        ao.Abort();
    }
};

#endif
<commit_msg>async: interoperability with class Cancellable<commit_after>/*
 * API for aborting asynchronous operations.
 *
 * The idea behind it is that functions starting an asynchronous
 * operation return a pointer to a struct async_operation, which can
 * be used to call async_operation_ref::Abort().
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

/*
 * How to implement and use it:
 *
 * The code starts an asynchronous operation by calling a C function.
 * It passes an operation specific callback function and a pointer to
 * a struct async_operation_ref.
 *
 * When the operation completes (either success or failure), the
 * callback is invoked (note that the callback may be invoked before
 * the function which initiated the operation returns).  The callback
 * is invoked exactly once.
 *
 * There is one exception to this rule: the async_operation_ref struct
 * can be used to abort the operation by calling
 * async_operation_ref::Abort().  In this case, the callback is not
 * invoked.
 *
 */

#ifndef ASYNC_HXX
#define ASYNC_HXX

#include "util/Cancellable.hxx"
#include "util/Cast.hxx"

#include <inline/compiler.h>

#include <assert.h>

struct async_operation;

struct async_operation_class {
    void (*abort)(struct async_operation *ao);
};

struct async_operation {
    struct async_operation_class cls;

#ifndef NDEBUG
    bool finished;

    bool aborted;
#endif

    void Init(const struct async_operation_class &_cls) {
        cls = _cls;

#ifndef NDEBUG
        finished = false;
        aborted = false;
#endif
    }

    template<typename T,
             async_operation T::*operation_member = &T::operation,
             void (T::*abort_member)() = &T::Abort>
    struct Generator {
        static void Abort(async_operation *ao) {
            T &t = ContainerCast2<T, async_operation>(*ao, operation_member);
            (t.*abort_member)();
        }

        static const struct async_operation_class cls;
    };

    template<typename T,
             async_operation T::*operation_member = &T::operation,
             void (T::*abort_member)() = &T::Abort>
    void Init2() {
        Init(Generator<T, operation_member, abort_member>::cls);
    }

    void Abort() {
        assert(!finished);
        assert(!aborted);

#ifndef NDEBUG
        aborted = true;
#endif

        cls.abort(this);
    }

    /**
     * Mark this operation as "finished".  This is a no-op in the
     * NDEBUG build.
     */
    void Finished() {
        assert(!finished);
        assert(!aborted);

#ifndef NDEBUG
        finished = true;
#endif
    }
};

template<class T,
         async_operation T::*operation_member,
         void (T::*abort_member)()>
const struct async_operation_class async_operation::Generator<T, operation_member, abort_member>::cls = {
    .abort = Abort,
};

struct async_operation_ref {
    struct async_operation *operation;

#ifndef NDEBUG
    /**
     * A copy of the "operation" pointer, for post-mortem debugging.
     */
    struct async_operation *copy;
#endif

    CancellablePointer cancellable;

    constexpr bool IsDefined() const {
        return operation != nullptr || cancellable;
    }

    void Clear() {
        operation = nullptr;
        cancellable = nullptr;
    }

    void Poison() {
#ifndef NDEBUG
        operation = (struct async_operation *)0x03030303;
#endif
    }

    void Set(struct async_operation &ao) {
        assert(!ao.finished);
        assert(!ao.aborted);

        operation = &ao;
#ifndef NDEBUG
        copy = &ao;
#endif
        cancellable = nullptr;
    }

    async_operation_ref &operator=(Cancellable &_cancellable) {
        Clear();
        cancellable = _cancellable;
        return *this;
    }

    void Abort() {
        if (cancellable) {
            cancellable.Cancel();
        } else {
            assert(operation != nullptr);
            assert(operation == copy);

            struct async_operation &ao = *operation;
#ifndef NDEBUG
            operation = nullptr;
#endif

            ao.Abort();
        }
    }

    void AbortAndClear() {
        if (cancellable) {
            cancellable.CancelAndClear();
        } else {
            assert(operation != nullptr);
            assert(operation == copy);

            struct async_operation &ao = *operation;
            operation = nullptr;

            ao.Abort();
        }
    }
};

#endif
<|endoftext|>


<commit_before>#include "../aq_base.h"

#include <sstream>
#include <string>

#include "gtest/gtest.h"
#include "../../test_helpers/bart_test_helper.h"

class AQBaseTest : public ::testing::Test {
 protected:
  void SetUp();

  template<int dim>
  void OutputAQ();

  dealii::ParameterHandler prm;
};

void AQBaseTest::SetUp() {
  prm.declare_entry("have reflective BC", "false",
                     dealii::Patterns::Bool(), "");
  prm.declare_entry("angular quadrature order", "4",
                     dealii::Patterns::Integer(), "");
  prm.declare_entry("angular quadrature name", "gl",
                     dealii::Patterns::Selection("gl"), "");
  prm.declare_entry("number of groups", "1", dealii::Patterns::Integer(), "");
  prm.declare_entry("transport model", "regular",
                     dealii::Patterns::Selection("regular|ep"), "");
}

template<int dim>
void AQBaseTest::OutputAQ() {
  // Outputs AQData generated by MakeAQ to the deallog
  std::unique_ptr<AQBase<dim>> gl_ptr =
      std::unique_ptr<AQBase<dim>> (new AQBase<dim>(prm));
  //gl_ptr->MakeAQ();
  gl_ptr->ProduceAQ();
  auto wi = gl_ptr->GetAQWeights();
  auto omega_i = gl_ptr->GetAQDirs();
  for (size_t i=0; i<wi.size(); ++i) {
    dealii::deallog << "Weight: " << wi[i] << "; Omega: ";
    for (int j=0; j<dim; ++j)
      dealii::deallog << omega_i[i][j] << " ";
    dealii::deallog << std::endl;
  }
}

TEST_F(AQBaseTest, AQBase1DProduceAQ) {
  std::string filename = "aq_base_1d";
  btest::GoldTestInit(filename); // Opens deal log
  OutputAQ<1>();

  btest::GoldTestRun(filename); // Closes deal log
}

TEST_F(AQBaseTest, AQBase1DEpProduceAQ) {
  std::string filename = "aq_base_1d_ep";
  prm.set("transport model", "ep");
  btest::GoldTestInit(filename); // Opens deal log
  OutputAQ<1>();

  btest::GoldTestRun(filename); // Closes deal log
}

TEST_F(AQBaseTest, AQBaseBadDimProduceAQ) {
  AQBase<2> test_AQ(prm);
  ASSERT_THROW(test_AQ.ProduceAQ(), dealii::ExcMessage);
}

TEST_F(AQBaseTest, AQBaseBadDimReflectiveBC) {
  prm.set("have reflective BC", "true");
  AQBase<1> test_AQ(prm);
  ASSERT_THROW(test_AQ.MakeAQ(), dealii::ExcMessage);
}

TEST_F(AQBaseTest, AQBaseSNOrderGetter) {
  AQBase<1> test_AQ(prm);
  ASSERT_EQ(test_AQ.GetSnOrder(), 4);
}

TEST_F(AQBaseTest, AQBaseGetNDir) {
  AQBase<1> test_AQ(prm);
  test_AQ.MakeAQ();
  ASSERT_EQ(test_AQ.GetNDir(), 4);
}

TEST_F(AQBaseTest, AQBaseGetNDirEp) {
  prm.set("transport model", "ep");
  AQBase<1> test_AQ(prm);
  test_AQ.MakeAQ();
  ASSERT_EQ(test_AQ.GetNDir(), 2);
}

TEST_F(AQBaseTest, AQBaseGetTotalHOVars) {
  AQBase<1> test_AQ(prm);
  test_AQ.MakeAQ();
  ASSERT_EQ(test_AQ.GetNTotalHOVars(), 4);
}

TEST_F(AQBaseTest, AQBaseGetTotalHOVarsEq) {
  prm.set("transport model", "ep");
  AQBase<1> test_AQ(prm);
  test_AQ.MakeAQ();
  ASSERT_EQ(test_AQ.GetNTotalHOVars(), 2);
}

TEST_F(AQBaseTest, PrintAQ) {
  AQBase<1> test_AQ(prm);
  test_AQ.MakeAQ();

  std::ostringstream output_string_stream;
  test_AQ.PrintAQ(&output_string_stream);

  std::string output = "transport model: regular; output_streamature name: None\n"
                       "Dim = 1, SN order = 4\n"
                       "Weights | Omega_x | Omega_y | mu\n"
                       "0.347854845137454  -0.861136311594053  \n"
                       "0.652145154862546  -0.339981043584856  \n"
                       "0.652145154862546  0.339981043584856  \n"
                       "0.347854845137454  0.861136311594052  \n";
  EXPECT_EQ(output, output_string_stream.str());
}

TEST_F(AQBaseTest, RefDirInt) {
  AQBase<1> test_AQ(prm);
  test_AQ.MakeAQ();
  std::map<std::pair<int, int>, int> component_index_map(test_AQ.GetCompInd());

  for (auto const& mapping : component_index_map) {
    EXPECT_EQ(mapping.first.first, 0);
    EXPECT_EQ(mapping.first.second, mapping.second);
  }

}

TEST_F(AQBaseTest, InvDirInd) {
  AQBase<1> test_AQ(prm);
  std::unordered_map<int, std::pair<int, int>>
      inv_component_map(test_AQ.GetInvCompInd());

  for (size_t i; i < inv_component_map.size(); ++i) {
    EXPECT_EQ(inv_component_map[i].first, 0);
    EXPECT_EQ(inv_component_map[i].second, i);
  }
}
<commit_msg>added initialization to i in aq_base_tests<commit_after>#include "../aq_base.h"

#include <sstream>
#include <string>

#include "gtest/gtest.h"
#include "../../test_helpers/bart_test_helper.h"

class AQBaseTest : public ::testing::Test {
 protected:
  void SetUp() override;

  template<int dim>
  void OutputAQ();

  dealii::ParameterHandler prm;
};

void AQBaseTest::SetUp() {
  prm.declare_entry("have reflective BC", "false",
                     dealii::Patterns::Bool(), "");
  prm.declare_entry("angular quadrature order", "4",
                     dealii::Patterns::Integer(), "");
  prm.declare_entry("angular quadrature name", "gl",
                     dealii::Patterns::Selection("gl"), "");
  prm.declare_entry("number of groups", "1", dealii::Patterns::Integer(), "");
  prm.declare_entry("transport model", "regular",
                     dealii::Patterns::Selection("regular|ep"), "");
}

template<int dim>
void AQBaseTest::OutputAQ() {
  // Outputs AQData generated by MakeAQ to the deallog
  std::unique_ptr<AQBase<dim>> gl_ptr = std::make_unique<AQBase<dim>>(prm);
  //gl_ptr->MakeAQ();
  gl_ptr->ProduceAQ();
  auto wi = gl_ptr->GetAQWeights();
  auto omega_i = gl_ptr->GetAQDirs();
  for (size_t i=0; i<wi.size(); ++i) {
    dealii::deallog << "Weight: " << wi[i] << "; Omega: ";
    for (int j=0; j<dim; ++j)
      dealii::deallog << omega_i[i][j] << " ";
    dealii::deallog << std::endl;
  }
}

TEST_F(AQBaseTest, AQBase1DProduceAQ) {
  std::string filename = "aq_base_1d";
  btest::GoldTestInit(filename); // Opens deal log
  OutputAQ<1>();

  btest::GoldTestRun(filename); // Closes deal log
}

TEST_F(AQBaseTest, AQBase1DEpProduceAQ) {
  std::string filename = "aq_base_1d_ep";
  prm.set("transport model", "ep");
  btest::GoldTestInit(filename); // Opens deal log
  OutputAQ<1>();

  btest::GoldTestRun(filename); // Closes deal log
}

TEST_F(AQBaseTest, AQBaseBadDimProduceAQ) {
  AQBase<2> test_AQ(prm);
  ASSERT_THROW(test_AQ.ProduceAQ(), dealii::ExcMessage);
}

TEST_F(AQBaseTest, AQBaseBadDimReflectiveBC) {
  prm.set("have reflective BC", "true");
  AQBase<1> test_AQ(prm);
  ASSERT_THROW(test_AQ.MakeAQ(), dealii::ExcMessage);
}

TEST_F(AQBaseTest, AQBaseSNOrderGetter) {
  AQBase<1> test_AQ(prm);
  ASSERT_EQ(test_AQ.GetSnOrder(), 4);
}

TEST_F(AQBaseTest, AQBaseGetNDir) {
  AQBase<1> test_AQ(prm);
  test_AQ.MakeAQ();
  ASSERT_EQ(test_AQ.GetNDir(), 4);
}

TEST_F(AQBaseTest, AQBaseGetNDirEp) {
  prm.set("transport model", "ep");
  AQBase<1> test_AQ(prm);
  test_AQ.MakeAQ();
  ASSERT_EQ(test_AQ.GetNDir(), 2);
}

TEST_F(AQBaseTest, AQBaseGetTotalHOVars) {
  AQBase<1> test_AQ(prm);
  test_AQ.MakeAQ();
  ASSERT_EQ(test_AQ.GetNTotalHOVars(), 4);
}

TEST_F(AQBaseTest, AQBaseGetTotalHOVarsEq) {
  prm.set("transport model", "ep");
  AQBase<1> test_AQ(prm);
  test_AQ.MakeAQ();
  ASSERT_EQ(test_AQ.GetNTotalHOVars(), 2);
}

TEST_F(AQBaseTest, PrintAQ) {
  AQBase<1> test_AQ(prm);
  test_AQ.MakeAQ();

  std::ostringstream output_string_stream;
  test_AQ.PrintAQ(&output_string_stream);

  std::string output = "transport model: regular; output_streamature name: None\n"
                       "Dim = 1, SN order = 4\n"
                       "Weights | Omega_x | Omega_y | mu\n"
                       "0.347854845137454  -0.861136311594053  \n"
                       "0.652145154862546  -0.339981043584856  \n"
                       "0.652145154862546  0.339981043584856  \n"
                       "0.347854845137454  0.861136311594052  \n";
  EXPECT_EQ(output, output_string_stream.str());
}

TEST_F(AQBaseTest, RefDirInt) {
  AQBase<1> test_AQ(prm);
  test_AQ.MakeAQ();
  std::map<std::pair<int, int>, int> component_index_map(test_AQ.GetCompInd());

  for (auto const& mapping : component_index_map) {
    EXPECT_EQ(mapping.first.first, 0);
    EXPECT_EQ(mapping.first.second, mapping.second);
  }

}

TEST_F(AQBaseTest, InvDirInd) {
  AQBase<1> test_AQ(prm);
  std::unordered_map<int, std::pair<int, int>>
      inv_component_map(test_AQ.GetInvCompInd());

  for (size_t i = 0; i < inv_component_map.size(); ++i) {
    EXPECT_EQ(inv_component_map[i].first, 0);
    EXPECT_EQ(inv_component_map[i].second, i);
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use of this software in source and binary forms,
 * with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * The software must be used only for Non-Commercial Use which means any
 * use which is NOT directed to receiving any direct monetary
 * compensation for, or commercial advantage from such use.  Illustrative
 * examples of non-commercial use are academic research, personal study,
 * teaching, education and corporate research & development.
 * Illustrative examples of commercial use are distributing products for
 * commercial advantage and providing services using the software for
 * commercial advantage.
 *
 * If you wish to use this software or functionality therein that may be
 * covered by patents for commercial use, please contact:
 *     Director of Intellectual Property Licensing
 *     Office of Strategy and Technology
 *     Hewlett-Packard Company
 *     1501 Page Mill Road
 *     Palo Alto, California  94304
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.  Redistributions
 * in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.  Neither the name of
 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.  No right of
 * sublicense is granted herewith.  Derivatives of the software and
 * output created using the software may be prepared, but only for
 * Non-Commercial Uses.  Derivatives of the software may be shared with
 * others provided: (i) the others agree to abide by the list of
 * conditions herein which includes the Non-Commercial Use restrictions;
 * and (ii) such Derivatives of the software include the above copyright
 * notice to acknowledge the contribution from this software where
 * applicable, this list of conditions and the disclaimer below.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include "arch/x86/insts/microregop.hh"
#include "arch/x86/miscregs.hh"
#include "base/condcodes.hh"
#include <string>

namespace X86ISA
{
    uint64_t RegOpBase::genFlags(uint64_t oldFlags, uint64_t flagMask,
            uint64_t _dest, uint64_t _src1, uint64_t _src2,
            bool subtract) const
    {
        DPRINTF(Sparc, "flagMask = %#x\n", flagMask);
        uint64_t flags = oldFlags & ~flagMask;
        if(flagMask & CFBit)
            if(findCarry(dataSize*8, _dest, _src1, _src2))
                flags |= CFBit;
            if(subtract)
                flags ^= CFBit;
        if(flagMask & PFBit && findParity(dataSize*8, _dest))
            flags |= PFBit;
        if(flagMask & ECFBit && findCarry(dataSize*8, _dest, _src1, _src2))
            flags |= ECFBit;
        if(flagMask & AFBit)
            if(findCarry(4, _dest, _src1, _src2))
                flags |= AFBit;
            if(subtract)
                flags ^= AFBit;
        if(flagMask & EZFBit && findZero(dataSize*8, _dest))
            flags |= EZFBit;
        if(flagMask & ZFBit && findZero(dataSize*8, _dest))
            flags |= ZFBit;
        if(flagMask & SFBit && findNegative(dataSize*8, _dest))
            flags |= SFBit;
        if(flagMask & OFBit && findOverflow(dataSize*8, _dest, _src1, _src2))
            flags |= OFBit;
        return flags;
    }

    bool RegOpBase::checkCondition(uint64_t flags) const
    {
        CCFlagBits ccflags = flags;
        switch(ext)
        {
          case ConditionTests::True:
            return true;
          case ConditionTests::ECF:
            return ccflags.ECF;
          case ConditionTests::EZF:
            return ccflags.EZF;
          case ConditionTests::SZnZF:
            return !(!ccflags.EZF & ccflags.ZF);
          case ConditionTests::MSTRZ:
            panic("This condition is not implemented!");
          case ConditionTests::STRZ:
            panic("This condition is not implemented!");
          case ConditionTests::MSTRC:
            panic("This condition is not implemented!");
          case ConditionTests::STRZnEZF:
            return !ccflags.EZF & ccflags.ZF;
                //And no interrupts or debug traps are waiting
          case ConditionTests::OF:
            return ccflags.OF;
          case ConditionTests::CF:
            return ccflags.CF;
          case ConditionTests::ZF:
            return ccflags.ZF;
          case ConditionTests::CvZF:
            return ccflags.CF | ccflags.ZF;
          case ConditionTests::SF:
            return ccflags.SF;
          case ConditionTests::PF:
            return ccflags.PF;
          case ConditionTests::SxOF:
            return ccflags.SF ^ ccflags.OF;
          case ConditionTests::SxOvZF:
            return ccflags.SF ^ ccflags.OF | ccflags.ZF;
          case ConditionTests::False:
            return false;
          case ConditionTests::NotECF:
            return !ccflags.ECF;
          case ConditionTests::NotEZF:
            return !ccflags.EZF;
          case ConditionTests::NotSZnZF:
            return !ccflags.EZF & ccflags.ZF;
          case ConditionTests::NotMSTRZ:
            panic("This condition is not implemented!");
          case ConditionTests::NotSTRZ:
            panic("This condition is not implemented!");
          case ConditionTests::NotMSTRC:
            panic("This condition is not implemented!");
          case ConditionTests::STRnZnEZF:
            return !ccflags.EZF & !ccflags.ZF;
                //And no interrupts or debug traps are waiting
          case ConditionTests::NotOF:
            return !ccflags.OF;
          case ConditionTests::NotCF:
            return !ccflags.CF;
          case ConditionTests::NotZF:
            return !ccflags.ZF;
          case ConditionTests::NotCvZF:
            return !(ccflags.CF | ccflags.ZF);
          case ConditionTests::NotSF:
            return !ccflags.SF;
          case ConditionTests::NotPF:
            return !ccflags.PF;
          case ConditionTests::NotSxOF:
            return !(ccflags.SF ^ ccflags.OF);
          case ConditionTests::NotSxOvZF:
            return !(ccflags.SF ^ ccflags.OF | ccflags.ZF);
        }
        panic("Unknown condition: %d\n", ext);
        return true;
    }

    std::string RegOp::generateDisassembly(Addr pc,
            const SymbolTable *symtab) const
    {
        std::stringstream response;

        printMnemonic(response, instMnem, mnemonic);
        printDestReg(response, 0, dataSize);
        response << ", ";
        printSrcReg(response, 0, dataSize);
        response << ", ";
        printSrcReg(response, 1, dataSize);
        return response.str();
    }

    std::string RegOpImm::generateDisassembly(Addr pc,
            const SymbolTable *symtab) const
    {
        std::stringstream response;

        printMnemonic(response, instMnem, mnemonic);
        printDestReg(response, 0, dataSize);
        response << ", ";
        printSrcReg(response, 0, dataSize);
        ccprintf(response, ", %#x", imm8);
        return response.str();
    }
}
<commit_msg>X86: Added some missing parenthesis in the condition code calculation function.<commit_after>/*
 * Copyright (c) 2007 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use of this software in source and binary forms,
 * with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * The software must be used only for Non-Commercial Use which means any
 * use which is NOT directed to receiving any direct monetary
 * compensation for, or commercial advantage from such use.  Illustrative
 * examples of non-commercial use are academic research, personal study,
 * teaching, education and corporate research & development.
 * Illustrative examples of commercial use are distributing products for
 * commercial advantage and providing services using the software for
 * commercial advantage.
 *
 * If you wish to use this software or functionality therein that may be
 * covered by patents for commercial use, please contact:
 *     Director of Intellectual Property Licensing
 *     Office of Strategy and Technology
 *     Hewlett-Packard Company
 *     1501 Page Mill Road
 *     Palo Alto, California  94304
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.  Redistributions
 * in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.  Neither the name of
 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.  No right of
 * sublicense is granted herewith.  Derivatives of the software and
 * output created using the software may be prepared, but only for
 * Non-Commercial Uses.  Derivatives of the software may be shared with
 * others provided: (i) the others agree to abide by the list of
 * conditions herein which includes the Non-Commercial Use restrictions;
 * and (ii) such Derivatives of the software include the above copyright
 * notice to acknowledge the contribution from this software where
 * applicable, this list of conditions and the disclaimer below.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include "arch/x86/insts/microregop.hh"
#include "arch/x86/miscregs.hh"
#include "base/condcodes.hh"
#include <string>

namespace X86ISA
{
    uint64_t RegOpBase::genFlags(uint64_t oldFlags, uint64_t flagMask,
            uint64_t _dest, uint64_t _src1, uint64_t _src2,
            bool subtract) const
    {
        DPRINTF(Sparc, "flagMask = %#x\n", flagMask);
        uint64_t flags = oldFlags & ~flagMask;
        if(flagMask & CFBit)
        {
            if(findCarry(dataSize*8, _dest, _src1, _src2))
                flags |= CFBit;
            if(subtract)
                flags ^= CFBit;
        }
        if(flagMask & PFBit && findParity(dataSize*8, _dest))
            flags |= PFBit;
        if(flagMask & ECFBit && findCarry(dataSize*8, _dest, _src1, _src2))
            flags |= ECFBit;
        if(flagMask & AFBit)
        {
            if(findCarry(4, _dest, _src1, _src2))
                flags |= AFBit;
            if(subtract)
                flags ^= AFBit;
        }
        if(flagMask & EZFBit && findZero(dataSize*8, _dest))
            flags |= EZFBit;
        if(flagMask & ZFBit && findZero(dataSize*8, _dest))
            flags |= ZFBit;
        if(flagMask & SFBit && findNegative(dataSize*8, _dest))
            flags |= SFBit;
        if(flagMask & OFBit && findOverflow(dataSize*8, _dest, _src1, _src2))
            flags |= OFBit;
        return flags;
    }

    bool RegOpBase::checkCondition(uint64_t flags) const
    {
        CCFlagBits ccflags = flags;
        switch(ext)
        {
          case ConditionTests::True:
            return true;
          case ConditionTests::ECF:
            return ccflags.ECF;
          case ConditionTests::EZF:
            return ccflags.EZF;
          case ConditionTests::SZnZF:
            return !(!ccflags.EZF & ccflags.ZF);
          case ConditionTests::MSTRZ:
            panic("This condition is not implemented!");
          case ConditionTests::STRZ:
            panic("This condition is not implemented!");
          case ConditionTests::MSTRC:
            panic("This condition is not implemented!");
          case ConditionTests::STRZnEZF:
            return !ccflags.EZF & ccflags.ZF;
                //And no interrupts or debug traps are waiting
          case ConditionTests::OF:
            return ccflags.OF;
          case ConditionTests::CF:
            return ccflags.CF;
          case ConditionTests::ZF:
            return ccflags.ZF;
          case ConditionTests::CvZF:
            return ccflags.CF | ccflags.ZF;
          case ConditionTests::SF:
            return ccflags.SF;
          case ConditionTests::PF:
            return ccflags.PF;
          case ConditionTests::SxOF:
            return ccflags.SF ^ ccflags.OF;
          case ConditionTests::SxOvZF:
            return ccflags.SF ^ ccflags.OF | ccflags.ZF;
          case ConditionTests::False:
            return false;
          case ConditionTests::NotECF:
            return !ccflags.ECF;
          case ConditionTests::NotEZF:
            return !ccflags.EZF;
          case ConditionTests::NotSZnZF:
            return !ccflags.EZF & ccflags.ZF;
          case ConditionTests::NotMSTRZ:
            panic("This condition is not implemented!");
          case ConditionTests::NotSTRZ:
            panic("This condition is not implemented!");
          case ConditionTests::NotMSTRC:
            panic("This condition is not implemented!");
          case ConditionTests::STRnZnEZF:
            return !ccflags.EZF & !ccflags.ZF;
                //And no interrupts or debug traps are waiting
          case ConditionTests::NotOF:
            return !ccflags.OF;
          case ConditionTests::NotCF:
            return !ccflags.CF;
          case ConditionTests::NotZF:
            return !ccflags.ZF;
          case ConditionTests::NotCvZF:
            return !(ccflags.CF | ccflags.ZF);
          case ConditionTests::NotSF:
            return !ccflags.SF;
          case ConditionTests::NotPF:
            return !ccflags.PF;
          case ConditionTests::NotSxOF:
            return !(ccflags.SF ^ ccflags.OF);
          case ConditionTests::NotSxOvZF:
            return !(ccflags.SF ^ ccflags.OF | ccflags.ZF);
        }
        panic("Unknown condition: %d\n", ext);
        return true;
    }

    std::string RegOp::generateDisassembly(Addr pc,
            const SymbolTable *symtab) const
    {
        std::stringstream response;

        printMnemonic(response, instMnem, mnemonic);
        printDestReg(response, 0, dataSize);
        response << ", ";
        printSrcReg(response, 0, dataSize);
        response << ", ";
        printSrcReg(response, 1, dataSize);
        return response.str();
    }

    std::string RegOpImm::generateDisassembly(Addr pc,
            const SymbolTable *symtab) const
    {
        std::stringstream response;

        printMnemonic(response, instMnem, mnemonic);
        printDestReg(response, 0, dataSize);
        response << ", ";
        printSrcReg(response, 0, dataSize);
        ccprintf(response, ", %#x", imm8);
        return response.str();
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use of this software in source and binary forms,
 * with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * The software must be used only for Non-Commercial Use which means any
 * use which is NOT directed to receiving any direct monetary
 * compensation for, or commercial advantage from such use.  Illustrative
 * examples of non-commercial use are academic research, personal study,
 * teaching, education and corporate research & development.
 * Illustrative examples of commercial use are distributing products for
 * commercial advantage and providing services using the software for
 * commercial advantage.
 *
 * If you wish to use this software or functionality therein that may be
 * covered by patents for commercial use, please contact:
 *     Director of Intellectual Property Licensing
 *     Office of Strategy and Technology
 *     Hewlett-Packard Company
 *     1501 Page Mill Road
 *     Palo Alto, California  94304
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.  Redistributions
 * in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.  Neither the name of
 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.  No right of
 * sublicense is granted herewith.  Derivatives of the software and
 * output created using the software may be prepared, but only for
 * Non-Commercial Uses.  Derivatives of the software may be shared with
 * others provided: (i) the others agree to abide by the list of
 * conditions herein which includes the Non-Commercial Use restrictions;
 * and (ii) such Derivatives of the software include the above copyright
 * notice to acknowledge the contribution from this software where
 * applicable, this list of conditions and the disclaimer below.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include "arch/x86/insts/microregop.hh"
#include "arch/x86/miscregs.hh"
#include "base/condcodes.hh"
#include <string>

namespace X86ISA
{
    uint64_t RegOpBase::genFlags(uint64_t oldFlags, uint64_t flagMask,
            uint64_t _dest, uint64_t _src1, uint64_t _src2,
            bool subtract) const
    {
        DPRINTF(X86, "flagMask = %#x\n", flagMask);
        if (_destRegIdx[0] & IntFoldBit) {
            _dest >>= 8;
        }
        uint64_t flags = oldFlags & ~flagMask;
        if(flagMask & (ECFBit | CFBit))
        {
            if(findCarry(dataSize*8, _dest, _src1, _src2))
                flags |= (flagMask & (ECFBit | CFBit));
            if(subtract)
                flags ^= (flagMask & (ECFBit | CFBit));
        }
        if(flagMask & PFBit && findParity(dataSize*8, _dest))
            flags |= PFBit;
        if(flagMask & AFBit)
        {
            if(findCarry(4, _dest, _src1, _src2))
                flags |= AFBit;
            if(subtract)
                flags ^= AFBit;
        }
        if(flagMask & (EZFBit | ZFBit) && findZero(dataSize*8, _dest))
            flags |= (flagMask & (EZFBit | ZFBit));
        if(flagMask & SFBit && findNegative(dataSize*8, _dest))
            flags |= SFBit;
        if(flagMask & OFBit && findOverflow(dataSize*8, _dest, _src1, _src2))
            flags |= OFBit;
        return flags;
    }

    std::string RegOp::generateDisassembly(Addr pc,
            const SymbolTable *symtab) const
    {
        std::stringstream response;

        printMnemonic(response, instMnem, mnemonic);
        printDestReg(response, 0, dataSize);
        response << ", ";
        printSrcReg(response, 0, dataSize);
        response << ", ";
        printSrcReg(response, 1, dataSize);
        return response.str();
    }

    std::string RegOpImm::generateDisassembly(Addr pc,
            const SymbolTable *symtab) const
    {
        std::stringstream response;

        printMnemonic(response, instMnem, mnemonic);
        printDestReg(response, 0, dataSize);
        response << ", ";
        printSrcReg(response, 0, dataSize);
        ccprintf(response, ", %#x", imm8);
        return response.str();
    }
}
<commit_msg>X86: Fix how the parity flag is computed. It's only for the lowest order byte, and I had the polarity wrong.<commit_after>/*
 * Copyright (c) 2007 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use of this software in source and binary forms,
 * with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * The software must be used only for Non-Commercial Use which means any
 * use which is NOT directed to receiving any direct monetary
 * compensation for, or commercial advantage from such use.  Illustrative
 * examples of non-commercial use are academic research, personal study,
 * teaching, education and corporate research & development.
 * Illustrative examples of commercial use are distributing products for
 * commercial advantage and providing services using the software for
 * commercial advantage.
 *
 * If you wish to use this software or functionality therein that may be
 * covered by patents for commercial use, please contact:
 *     Director of Intellectual Property Licensing
 *     Office of Strategy and Technology
 *     Hewlett-Packard Company
 *     1501 Page Mill Road
 *     Palo Alto, California  94304
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.  Redistributions
 * in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.  Neither the name of
 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.  No right of
 * sublicense is granted herewith.  Derivatives of the software and
 * output created using the software may be prepared, but only for
 * Non-Commercial Uses.  Derivatives of the software may be shared with
 * others provided: (i) the others agree to abide by the list of
 * conditions herein which includes the Non-Commercial Use restrictions;
 * and (ii) such Derivatives of the software include the above copyright
 * notice to acknowledge the contribution from this software where
 * applicable, this list of conditions and the disclaimer below.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include "arch/x86/insts/microregop.hh"
#include "arch/x86/miscregs.hh"
#include "base/condcodes.hh"
#include <string>

namespace X86ISA
{
    uint64_t RegOpBase::genFlags(uint64_t oldFlags, uint64_t flagMask,
            uint64_t _dest, uint64_t _src1, uint64_t _src2,
            bool subtract) const
    {
        DPRINTF(X86, "flagMask = %#x\n", flagMask);
        if (_destRegIdx[0] & IntFoldBit) {
            _dest >>= 8;
        }
        uint64_t flags = oldFlags & ~flagMask;
        if(flagMask & (ECFBit | CFBit))
        {
            if(findCarry(dataSize*8, _dest, _src1, _src2))
                flags |= (flagMask & (ECFBit | CFBit));
            if(subtract)
                flags ^= (flagMask & (ECFBit | CFBit));
        }
        if(flagMask & PFBit && !findParity(8, _dest))
            flags |= PFBit;
        if(flagMask & AFBit)
        {
            if(findCarry(4, _dest, _src1, _src2))
                flags |= AFBit;
            if(subtract)
                flags ^= AFBit;
        }
        if(flagMask & (EZFBit | ZFBit) && findZero(dataSize*8, _dest))
            flags |= (flagMask & (EZFBit | ZFBit));
        if(flagMask & SFBit && findNegative(dataSize*8, _dest))
            flags |= SFBit;
        if(flagMask & OFBit && findOverflow(dataSize*8, _dest, _src1, _src2))
            flags |= OFBit;
        return flags;
    }

    std::string RegOp::generateDisassembly(Addr pc,
            const SymbolTable *symtab) const
    {
        std::stringstream response;

        printMnemonic(response, instMnem, mnemonic);
        printDestReg(response, 0, dataSize);
        response << ", ";
        printSrcReg(response, 0, dataSize);
        response << ", ";
        printSrcReg(response, 1, dataSize);
        return response.str();
    }

    std::string RegOpImm::generateDisassembly(Addr pc,
            const SymbolTable *symtab) const
    {
        std::stringstream response;

        printMnemonic(response, instMnem, mnemonic);
        printDestReg(response, 0, dataSize);
        response << ", ";
        printSrcReg(response, 0, dataSize);
        ccprintf(response, ", %#x", imm8);
        return response.str();
    }
}
<|endoftext|>


<commit_before>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/base/logging.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/objects/xuser_module.h"
#include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/util/xex2.h"
#include "xenia/kernel/xboxkrnl_private.h"
#include "xenia/xbox.h"

#include "xenia/cpu/processor.h"

namespace xe {
namespace kernel {

X_STATUS xeExGetXConfigSetting(uint16_t category, uint16_t setting,
                               void* buffer, uint16_t buffer_size,
                               uint16_t* required_size) {
  uint16_t setting_size = 0;
  uint32_t value = 0;

  // TODO(benvanik): have real structs here that just get copied from.
  // http://free60.org/XConfig
  // http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/Generic/ExConfig.h
  switch (category) {
    case 0x0002:
      // XCONFIG_SECURED_CATEGORY
      switch (setting) {
        case 0x0002:  // XCONFIG_SECURED_AV_REGION
          setting_size = 4;
          value = 0x00001000;  // USA/Canada
          break;
        default:
          assert_unhandled_case(setting);
          return X_STATUS_INVALID_PARAMETER_2;
      }
      break;
    case 0x0003:
      // XCONFIG_USER_CATEGORY
      switch (setting) {
        case 0x0001:  // XCONFIG_USER_TIME_ZONE_BIAS
        case 0x0002:  // XCONFIG_USER_TIME_ZONE_STD_NAME
        case 0x0003:  // XCONFIG_USER_TIME_ZONE_DLT_NAME
        case 0x0004:  // XCONFIG_USER_TIME_ZONE_STD_DATE
        case 0x0005:  // XCONFIG_USER_TIME_ZONE_DLT_DATE
        case 0x0006:  // XCONFIG_USER_TIME_ZONE_STD_BIAS
        case 0x0007:  // XCONFIG_USER_TIME_ZONE_DLT_BIAS
          setting_size = 4;
          // TODO(benvanik): get this value.
          value = 0;
          break;
        case 0x0009:  // XCONFIG_USER_LANGUAGE
          setting_size = 4;
          value = 0x00000001;  // English
          break;
        case 0x000A:  // XCONFIG_USER_VIDEO_FLAGS
          setting_size = 4;
          value = 0x00040000;
          break;
        case 0x000C:  // XCONFIG_USER_RETAIL_FLAGS
          setting_size = 4;
          // TODO(benvanik): get this value.
          value = 0;
          break;
        case 0x000E:  // XCONFIG_USER_COUNTRY
          setting_size = 4;
          // TODO(benvanik): get this value.
          value = 0;
          break;
        default:
          assert_unhandled_case(setting);
          return X_STATUS_INVALID_PARAMETER_2;
      }
      break;
    default:
      assert_unhandled_case(category);
      return X_STATUS_INVALID_PARAMETER_1;
  }

  if (buffer_size < setting_size) {
    return X_STATUS_BUFFER_TOO_SMALL;
  }
  if (!buffer && buffer_size) {
    return X_STATUS_INVALID_PARAMETER_3;
  }

  if (buffer) {
    xe::store_and_swap<uint32_t>(buffer, value);
  }
  if (required_size) {
    *required_size = setting_size;
  }

  return X_STATUS_SUCCESS;
}

SHIM_CALL ExGetXConfigSetting_shim(PPCContext* ppc_state, KernelState* state) {
  uint16_t category = SHIM_GET_ARG_16(0);
  uint16_t setting = SHIM_GET_ARG_16(1);
  uint32_t buffer_ptr = SHIM_GET_ARG_32(2);
  uint16_t buffer_size = SHIM_GET_ARG_16(3);
  uint32_t required_size_ptr = SHIM_GET_ARG_32(4);

  XELOGD("ExGetXConfigSetting(%.4X, %.4X, %.8X, %.4X, %.8X)", category, setting,
         buffer_ptr, buffer_size, required_size_ptr);

  void* buffer = buffer_ptr ? SHIM_MEM_ADDR(buffer_ptr) : NULL;
  uint16_t required_size = 0;
  X_STATUS result = xeExGetXConfigSetting(category, setting, buffer,
                                          buffer_size, &required_size);

  if (required_size_ptr) {
    SHIM_SET_MEM_16(required_size_ptr, required_size);
  }

  SHIM_SET_RETURN_32(result);
}

SHIM_CALL XexCheckExecutablePrivilege_shim(PPCContext* ppc_state,
                                           KernelState* state) {
  uint32_t privilege = SHIM_GET_ARG_32(0);

  XELOGD("XexCheckExecutablePrivilege(%.8X)", privilege);

  // BOOL
  // DWORD Privilege

  // Privilege is bit position in xe_xex2_system_flags enum - so:
  // Privilege=6 -> 0x00000040 -> XEX_SYSTEM_INSECURE_SOCKETS
  uint32_t mask = 1 << privilege;

  XUserModule* module = state->GetExecutableModule();
  if (!module) {
    SHIM_SET_RETURN_32(0);
    return;
  }
  xe_xex2_ref xex = module->xex();

  const xe_xex2_header_t* header = xe_xex2_get_header(xex);
  uint32_t result = (header->system_flags & mask) > 0;

  module->Release();

  SHIM_SET_RETURN_32(result);
}

SHIM_CALL XexGetModuleHandle_shim(PPCContext* ppc_state, KernelState* state) {
  uint32_t module_name_ptr = SHIM_GET_ARG_32(0);
  const char* module_name = (const char*)SHIM_MEM_ADDR(module_name_ptr);
  uint32_t module_handle_ptr = SHIM_GET_ARG_32(1);

  XELOGD("XexGetModuleHandle(%s, %.8X)", module_name, module_handle_ptr);

  XModule* module = nullptr;
  if (!module_name) {
    module = state->GetExecutableModule();
  } else {
    module = state->GetModule(module_name);
  }
  if (!module) {
    SHIM_SET_MEM_32(module_handle_ptr, 0);
    SHIM_SET_RETURN_32(X_ERROR_NOT_FOUND);
    return;
  }

  // NOTE: we don't retain the handle for return.
  SHIM_SET_MEM_32(module_handle_ptr, module->handle());

  module->Release();

  SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}

SHIM_CALL XexGetModuleSection_shim(PPCContext* ppc_state, KernelState* state) {
  uint32_t handle = SHIM_GET_ARG_32(0);
  uint32_t name_ptr = SHIM_GET_ARG_32(1);
  const char* name = (const char*)SHIM_MEM_ADDR(name_ptr);
  uint32_t data_ptr = SHIM_GET_ARG_32(2);
  uint32_t size_ptr = SHIM_GET_ARG_32(3);

  XELOGD("XexGetModuleSection(%.8X, %s, %.8X, %.8X)", handle, name, data_ptr,
         size_ptr);

  XModule* module = NULL;
  X_STATUS result =
      state->object_table()->GetObject(handle, (XObject**)&module);
  if (XSUCCEEDED(result)) {
    uint32_t section_data = 0;
    uint32_t section_size = 0;
    result = module->GetSection(name, &section_data, &section_size);
    if (XSUCCEEDED(result)) {
      SHIM_SET_MEM_32(data_ptr, section_data);
      SHIM_SET_MEM_32(size_ptr, section_size);
    }

    module->Release();
  }

  SHIM_SET_RETURN_32(result);
}

SHIM_CALL XexLoadImage_shim(PPCContext* ppc_state, KernelState* state) {
  uint32_t module_name_ptr = SHIM_GET_ARG_32(0);
  const char* module_name = (const char*)SHIM_MEM_ADDR(module_name_ptr);
  uint32_t module_flags = SHIM_GET_ARG_32(1);
  uint32_t min_version = SHIM_GET_ARG_32(2);
  uint32_t handle_ptr = SHIM_GET_ARG_32(3);

  XELOGD("XexLoadImage(%s, %.8X, %.8X, %.8X)", module_name, module_flags,
         min_version, handle_ptr);

  X_STATUS result = X_STATUS_NO_SUCH_FILE;

  XModule* module = state->GetModule(module_name);
  if (module) {
    module->RetainHandle();
    SHIM_SET_MEM_32(handle_ptr, module->handle());
    module->Release();

    result = X_STATUS_SUCCESS;
  } else {
    XUserModule* usermod = state->LoadUserModule(module_name);
    if (usermod) {
      // If the module has an entry point function, we have to call it.
      const xe_xex2_header_t* header = usermod->xex_header();
      if (header->exe_entry_point) {
        state->processor()->Execute(ppc_state->thread_state,
                                    header->exe_entry_point);
      }

      result = X_STATUS_SUCCESS;

      usermod->RetainHandle();
      SHIM_SET_MEM_32(handle_ptr, usermod->handle());
      usermod->Release();
    }
  }

  SHIM_SET_RETURN_32(result);
}

SHIM_CALL XexUnloadImage_shim(PPCContext* ppc_state, KernelState* state) {
  uint32_t handle = SHIM_GET_ARG_32(0);

  XELOGD("XexUnloadImage(%.8X)", handle);

  X_STATUS result = X_STATUS_INVALID_HANDLE;

  result = state->object_table()->RemoveHandle(handle);

  SHIM_SET_RETURN_32(result);
}

SHIM_CALL XexGetProcedureAddress_shim(PPCContext* ppc_state,
                                      KernelState* state) {
  uint32_t module_handle = SHIM_GET_ARG_32(0);
  uint32_t ordinal = SHIM_GET_ARG_32(1);
  const char* name = (const char*)SHIM_MEM_ADDR(ordinal);
  uint32_t out_function_ptr = SHIM_GET_ARG_32(2);

  if (ordinal < 0x10000) {
    XELOGD("XexGetProcedureAddress(%.8X, %.8X, %.8X)", module_handle, ordinal,
           out_function_ptr);
  } else {
    XELOGD("XexGetProcedureAddress(%.8X, %.8X(%s), %.8X)", module_handle,
           ordinal, name, out_function_ptr);
  }

  X_STATUS result = X_STATUS_INVALID_HANDLE;
  SHIM_SET_MEM_32(out_function_ptr, 0xDEADF00D);

  XModule* module = NULL;

  if (!module_handle) {
    module = state->GetExecutableModule();
  } else {
    result =
        state->object_table()->GetObject(module_handle, (XObject**)&module);
  }

  if (XSUCCEEDED(result)) {
    if (ordinal < 0x10000) {
      // Ordinal.
      uint32_t ptr = module->GetProcAddressByOrdinal(ordinal);
      if (ptr) {
        SHIM_SET_MEM_32(out_function_ptr, ptr);
        result = X_STATUS_SUCCESS;
      }
    } else {
      // It's a name pointer instead.
      uint32_t ptr = module->GetProcAddressByName(name);

      // FYI: We don't need to generate this function now. It'll
      // be done automatically by xenia when it gets called.
      if (ptr) {
        SHIM_SET_MEM_32(out_function_ptr, ptr);
        result = X_STATUS_SUCCESS;
      }
    }
  }

  if (module) {
    module->Release();
  }

  SHIM_SET_RETURN_32(result);
}

SHIM_CALL ExRegisterTitleTerminateNotification_shim(PPCContext* ppc_state,
                                                    KernelState* state) {
  uint32_t registration_ptr = SHIM_GET_ARG_32(0);
  uint32_t create = SHIM_GET_ARG_32(1);

  uint32_t routine = SHIM_MEM_32(registration_ptr + 0);
  uint32_t priority = SHIM_MEM_32(registration_ptr + 4);
  // list entry flink
  // list entry blink

  XELOGD("ExRegisterTitleTerminateNotification(%.8X(%.8X), %.1X)",
         registration_ptr, routine, create);

  if (create) {
    // Adding.
    // TODO(benvanik): add to master list (kernel?).
  } else {
    // Removing.
    // TODO(benvanik): remove from master list.
  }
}

}  // namespace kernel
}  // namespace xe

void xe::kernel::xboxkrnl::RegisterModuleExports(
    xe::cpu::ExportResolver* export_resolver, KernelState* state) {
  SHIM_SET_MAPPING("xboxkrnl.exe", ExGetXConfigSetting, state);

  SHIM_SET_MAPPING("xboxkrnl.exe", XexCheckExecutablePrivilege, state);

  SHIM_SET_MAPPING("xboxkrnl.exe", XexGetModuleHandle, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", XexGetModuleSection, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", XexLoadImage, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", XexUnloadImage, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", XexGetProcedureAddress, state);

  SHIM_SET_MAPPING("xboxkrnl.exe", ExRegisterTitleTerminateNotification, state);
}
<commit_msg>Call a DLL's entry-point function in XexLoadImage<commit_after>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/base/logging.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/objects/xuser_module.h"
#include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/util/xex2.h"
#include "xenia/kernel/xboxkrnl_private.h"
#include "xenia/xbox.h"

#include "xenia/cpu/processor.h"

namespace xe {
namespace kernel {

X_STATUS xeExGetXConfigSetting(uint16_t category, uint16_t setting,
                               void* buffer, uint16_t buffer_size,
                               uint16_t* required_size) {
  uint16_t setting_size = 0;
  uint32_t value = 0;

  // TODO(benvanik): have real structs here that just get copied from.
  // http://free60.org/XConfig
  // http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/Generic/ExConfig.h
  switch (category) {
    case 0x0002:
      // XCONFIG_SECURED_CATEGORY
      switch (setting) {
        case 0x0002:  // XCONFIG_SECURED_AV_REGION
          setting_size = 4;
          value = 0x00001000;  // USA/Canada
          break;
        default:
          assert_unhandled_case(setting);
          return X_STATUS_INVALID_PARAMETER_2;
      }
      break;
    case 0x0003:
      // XCONFIG_USER_CATEGORY
      switch (setting) {
        case 0x0001:  // XCONFIG_USER_TIME_ZONE_BIAS
        case 0x0002:  // XCONFIG_USER_TIME_ZONE_STD_NAME
        case 0x0003:  // XCONFIG_USER_TIME_ZONE_DLT_NAME
        case 0x0004:  // XCONFIG_USER_TIME_ZONE_STD_DATE
        case 0x0005:  // XCONFIG_USER_TIME_ZONE_DLT_DATE
        case 0x0006:  // XCONFIG_USER_TIME_ZONE_STD_BIAS
        case 0x0007:  // XCONFIG_USER_TIME_ZONE_DLT_BIAS
          setting_size = 4;
          // TODO(benvanik): get this value.
          value = 0;
          break;
        case 0x0009:  // XCONFIG_USER_LANGUAGE
          setting_size = 4;
          value = 0x00000001;  // English
          break;
        case 0x000A:  // XCONFIG_USER_VIDEO_FLAGS
          setting_size = 4;
          value = 0x00040000;
          break;
        case 0x000C:  // XCONFIG_USER_RETAIL_FLAGS
          setting_size = 4;
          // TODO(benvanik): get this value.
          value = 0;
          break;
        case 0x000E:  // XCONFIG_USER_COUNTRY
          setting_size = 4;
          // TODO(benvanik): get this value.
          value = 0;
          break;
        default:
          assert_unhandled_case(setting);
          return X_STATUS_INVALID_PARAMETER_2;
      }
      break;
    default:
      assert_unhandled_case(category);
      return X_STATUS_INVALID_PARAMETER_1;
  }

  if (buffer_size < setting_size) {
    return X_STATUS_BUFFER_TOO_SMALL;
  }
  if (!buffer && buffer_size) {
    return X_STATUS_INVALID_PARAMETER_3;
  }

  if (buffer) {
    xe::store_and_swap<uint32_t>(buffer, value);
  }
  if (required_size) {
    *required_size = setting_size;
  }

  return X_STATUS_SUCCESS;
}

SHIM_CALL ExGetXConfigSetting_shim(PPCContext* ppc_state, KernelState* state) {
  uint16_t category = SHIM_GET_ARG_16(0);
  uint16_t setting = SHIM_GET_ARG_16(1);
  uint32_t buffer_ptr = SHIM_GET_ARG_32(2);
  uint16_t buffer_size = SHIM_GET_ARG_16(3);
  uint32_t required_size_ptr = SHIM_GET_ARG_32(4);

  XELOGD("ExGetXConfigSetting(%.4X, %.4X, %.8X, %.4X, %.8X)", category, setting,
         buffer_ptr, buffer_size, required_size_ptr);

  void* buffer = buffer_ptr ? SHIM_MEM_ADDR(buffer_ptr) : NULL;
  uint16_t required_size = 0;
  X_STATUS result = xeExGetXConfigSetting(category, setting, buffer,
                                          buffer_size, &required_size);

  if (required_size_ptr) {
    SHIM_SET_MEM_16(required_size_ptr, required_size);
  }

  SHIM_SET_RETURN_32(result);
}

SHIM_CALL XexCheckExecutablePrivilege_shim(PPCContext* ppc_state,
                                           KernelState* state) {
  uint32_t privilege = SHIM_GET_ARG_32(0);

  XELOGD("XexCheckExecutablePrivilege(%.8X)", privilege);

  // BOOL
  // DWORD Privilege

  // Privilege is bit position in xe_xex2_system_flags enum - so:
  // Privilege=6 -> 0x00000040 -> XEX_SYSTEM_INSECURE_SOCKETS
  uint32_t mask = 1 << privilege;

  XUserModule* module = state->GetExecutableModule();
  if (!module) {
    SHIM_SET_RETURN_32(0);
    return;
  }
  xe_xex2_ref xex = module->xex();

  const xe_xex2_header_t* header = xe_xex2_get_header(xex);
  uint32_t result = (header->system_flags & mask) > 0;

  module->Release();

  SHIM_SET_RETURN_32(result);
}

SHIM_CALL XexGetModuleHandle_shim(PPCContext* ppc_state, KernelState* state) {
  uint32_t module_name_ptr = SHIM_GET_ARG_32(0);
  const char* module_name = (const char*)SHIM_MEM_ADDR(module_name_ptr);
  uint32_t module_handle_ptr = SHIM_GET_ARG_32(1);

  XELOGD("XexGetModuleHandle(%s, %.8X)", module_name, module_handle_ptr);

  XModule* module = nullptr;
  if (!module_name) {
    module = state->GetExecutableModule();
  } else {
    module = state->GetModule(module_name);
  }
  if (!module) {
    SHIM_SET_MEM_32(module_handle_ptr, 0);
    SHIM_SET_RETURN_32(X_ERROR_NOT_FOUND);
    return;
  }

  // NOTE: we don't retain the handle for return.
  SHIM_SET_MEM_32(module_handle_ptr, module->handle());

  module->Release();

  SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}

SHIM_CALL XexGetModuleSection_shim(PPCContext* ppc_state, KernelState* state) {
  uint32_t handle = SHIM_GET_ARG_32(0);
  uint32_t name_ptr = SHIM_GET_ARG_32(1);
  const char* name = (const char*)SHIM_MEM_ADDR(name_ptr);
  uint32_t data_ptr = SHIM_GET_ARG_32(2);
  uint32_t size_ptr = SHIM_GET_ARG_32(3);

  XELOGD("XexGetModuleSection(%.8X, %s, %.8X, %.8X)", handle, name, data_ptr,
         size_ptr);

  XModule* module = NULL;
  X_STATUS result =
      state->object_table()->GetObject(handle, (XObject**)&module);
  if (XSUCCEEDED(result)) {
    uint32_t section_data = 0;
    uint32_t section_size = 0;
    result = module->GetSection(name, &section_data, &section_size);
    if (XSUCCEEDED(result)) {
      SHIM_SET_MEM_32(data_ptr, section_data);
      SHIM_SET_MEM_32(size_ptr, section_size);
    }

    module->Release();
  }

  SHIM_SET_RETURN_32(result);
}

SHIM_CALL XexLoadImage_shim(PPCContext* ppc_state, KernelState* state) {
  uint32_t module_name_ptr = SHIM_GET_ARG_32(0);
  const char* module_name = (const char*)SHIM_MEM_ADDR(module_name_ptr);
  uint32_t module_flags = SHIM_GET_ARG_32(1);
  uint32_t min_version = SHIM_GET_ARG_32(2);
  uint32_t handle_ptr = SHIM_GET_ARG_32(3);

  XELOGD("XexLoadImage(%s, %.8X, %.8X, %.8X)", module_name, module_flags,
         min_version, handle_ptr);

  X_STATUS result = X_STATUS_NO_SUCH_FILE;

  XModule* module = state->GetModule(module_name);
  if (module) {
    module->RetainHandle();
    SHIM_SET_MEM_32(handle_ptr, module->handle());
    module->Release();

    result = X_STATUS_SUCCESS;
  } else {
    XUserModule* usermod = state->LoadUserModule(module_name);
    if (usermod) {
      // If the module has an entry point function, we have to call it.
      const xe_xex2_header_t* header = usermod->xex_header();
      if (header->exe_entry_point) {
        // Return address
        uint32_t lr = ppc_state->thread_state->context()->lr;

        // TODO: What are these args for?
        // param 2: val 1 seems to make CRT initialize
        uint64_t args[] = { 0, 1, 0 };
        state->processor()->Execute(ppc_state->thread_state,
                                    header->exe_entry_point,
                                    args, xe::countof(args));

        ppc_state->thread_state->context()->lr = lr;
      }

      result = X_STATUS_SUCCESS;

      usermod->RetainHandle();
      SHIM_SET_MEM_32(handle_ptr, usermod->handle());
      usermod->Release();
    }
  }

  SHIM_SET_RETURN_32(result);
}

SHIM_CALL XexUnloadImage_shim(PPCContext* ppc_state, KernelState* state) {
  uint32_t handle = SHIM_GET_ARG_32(0);

  XELOGD("XexUnloadImage(%.8X)", handle);

  X_STATUS result = X_STATUS_INVALID_HANDLE;

  result = state->object_table()->RemoveHandle(handle);

  SHIM_SET_RETURN_32(result);
}

SHIM_CALL XexGetProcedureAddress_shim(PPCContext* ppc_state,
                                      KernelState* state) {
  uint32_t module_handle = SHIM_GET_ARG_32(0);
  uint32_t ordinal = SHIM_GET_ARG_32(1);
  const char* name = (const char*)SHIM_MEM_ADDR(ordinal);
  uint32_t out_function_ptr = SHIM_GET_ARG_32(2);

  if (ordinal < 0x10000) {
    XELOGD("XexGetProcedureAddress(%.8X, %.8X, %.8X)", module_handle, ordinal,
           out_function_ptr);
  } else {
    XELOGD("XexGetProcedureAddress(%.8X, %.8X(%s), %.8X)", module_handle,
           ordinal, name, out_function_ptr);
  }

  X_STATUS result = X_STATUS_INVALID_HANDLE;
  SHIM_SET_MEM_32(out_function_ptr, 0xDEADF00D);

  XModule* module = NULL;

  if (!module_handle) {
    module = state->GetExecutableModule();
  } else {
    result =
        state->object_table()->GetObject(module_handle, (XObject**)&module);
  }

  if (XSUCCEEDED(result)) {
    if (ordinal < 0x10000) {
      // Ordinal.
      uint32_t ptr = module->GetProcAddressByOrdinal(ordinal);
      if (ptr) {
        SHIM_SET_MEM_32(out_function_ptr, ptr);
        result = X_STATUS_SUCCESS;
      }
    } else {
      // It's a name pointer instead.
      uint32_t ptr = module->GetProcAddressByName(name);

      // FYI: We don't need to generate this function now. It'll
      // be done automatically by xenia when it gets called.
      if (ptr) {
        SHIM_SET_MEM_32(out_function_ptr, ptr);
        result = X_STATUS_SUCCESS;
      }
    }
  }

  if (module) {
    module->Release();
  }

  SHIM_SET_RETURN_32(result);
}

SHIM_CALL ExRegisterTitleTerminateNotification_shim(PPCContext* ppc_state,
                                                    KernelState* state) {
  uint32_t registration_ptr = SHIM_GET_ARG_32(0);
  uint32_t create = SHIM_GET_ARG_32(1);

  uint32_t routine = SHIM_MEM_32(registration_ptr + 0);
  uint32_t priority = SHIM_MEM_32(registration_ptr + 4);
  // list entry flink
  // list entry blink

  XELOGD("ExRegisterTitleTerminateNotification(%.8X(%.8X), %.1X)",
         registration_ptr, routine, create);

  if (create) {
    // Adding.
    // TODO(benvanik): add to master list (kernel?).
  } else {
    // Removing.
    // TODO(benvanik): remove from master list.
  }
}

}  // namespace kernel
}  // namespace xe

void xe::kernel::xboxkrnl::RegisterModuleExports(
    xe::cpu::ExportResolver* export_resolver, KernelState* state) {
  SHIM_SET_MAPPING("xboxkrnl.exe", ExGetXConfigSetting, state);

  SHIM_SET_MAPPING("xboxkrnl.exe", XexCheckExecutablePrivilege, state);

  SHIM_SET_MAPPING("xboxkrnl.exe", XexGetModuleHandle, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", XexGetModuleSection, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", XexLoadImage, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", XexUnloadImage, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", XexGetProcedureAddress, state);

  SHIM_SET_MAPPING("xboxkrnl.exe", ExRegisterTitleTerminateNotification, state);
}
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2013 Heiko Strathmann
 */
#include <shogun/kernel/string/DistantSegmentsKernel.h>
#include <shogun/labels/BinaryLabels.h>
#include <shogun/features/StringFeatures.h>
#include <shogun/classifier/svm/SVMLight.h>
#include <shogun/classifier/svm/LibSVM.h>

using namespace shogun;

void test_svmlight()
{
	/* data is random length strings with only zeros (A) or ones (B) */
	index_t num_train=100;
	index_t num_test=50;
	index_t max_length=100;
	float64_t p_x=0.5; // probability for class A
	float64_t mostly_prob=0.8;
	CDenseLabels* labels=new CBinaryLabels(num_train+num_test);
	CMath::init_random(17);

	SGStringList<char> data(num_train+num_test, max_length);
	for (index_t i=0; i<num_train+num_test; ++i)
	{
		/* determine length */
		index_t length=CMath::random(1, max_length);

		/* allocate string */
		data.strings[i]=SGString<char>(length);

		/* fill with elements and set label */
		if (p_x<CMath::random(0.0, 1.0))
		{
			labels->set_label(i, 1);
			for (index_t j=0; j<length; ++j)
			{
				char c=mostly_prob<CMath::random(0.0, 1.0) ? '0' : '1';
				data.strings[i].string[j]=c;
			}
		}
		else
		{
			labels->set_label(i, -1);
			for (index_t j=0; j<length; ++j)
			{
				char c=mostly_prob<CMath::random(0.0, 1.0) ? '1' : '0';
				data.strings[i].string[j]=c;
			}
		}

		SG_SPRINT("datum %d, class %d:\t", i, labels->get_int_label(i));
		for (index_t j=0; j<length; ++j)
			SG_SPRINT("%c", data.strings[i].string[j]);
		SG_SPRINT("\n");

	}
	CStringFeatures<char>* feats=new CStringFeatures<char>(data, BINARY);

	/* copy training and test data */
	SGVector<index_t> train_inds(num_train);
	train_inds.range_fill();
	SGVector<index_t> test_inds(num_test);
	test_inds.range_fill();
	test_inds.add(num_train);

	CStringFeatures<char>* feats_train=
			(CStringFeatures<char>*)feats->copy_subset(train_inds);
	CStringFeatures<char>* feats_test=
			(CStringFeatures<char>*)feats->copy_subset(test_inds);

	labels->add_subset(train_inds);
	CLabels* labels_train=new CBinaryLabels(labels->get_labels_copy());
	labels->remove_subset();
	labels->add_subset(test_inds);
	CLabels* labels_test=new CBinaryLabels(labels->get_labels_copy());
	labels->remove_subset();

	/* string kernel */
	CDistantSegmentsKernel* kernel=new CDistantSegmentsKernel(10, 2, 2);

	/* SVM training and testing without precomputing the kernel */
	float64_t C=1;
	CSVM* svm=new CSVMLight(C, kernel, labels_train);
//	CSVM* svm=new CLibSVM(C, kernel, labels_train);
	svm->parallel->set_num_threads(1);
	svm->set_store_model_features(false);
	svm->train(feats_train);
	SGVector<float64_t> alphas=svm->get_alphas();
	SGVector<index_t> svs=svm->get_support_vectors();
	float64_t bias=svm->get_bias();
	CBinaryLabels* predictions=(CBinaryLabels*)svm->apply(feats_test);
	alphas.display_vector("alphas");
	svs.display_vector("svs");
	SG_SPRINT("bias: %f\n", bias);

	/* now the same with a precopumputed kernel */
	kernel->init(feats, feats);
	CCustomKernel* precomputed=new CCustomKernel(kernel);
	precomputed->add_row_subset(train_inds);
	precomputed->add_col_subset(train_inds);
	SGMatrix<float64_t> km_train=precomputed->get_kernel_matrix();
	precomputed->remove_col_subset();
	precomputed->add_col_subset(test_inds);
	SGMatrix<float64_t> km_test=precomputed->get_kernel_matrix();
	precomputed->remove_row_subset();
	precomputed->remove_col_subset();
	SGMatrix<float64_t> km=precomputed->get_kernel_matrix();

//	km.display_matrix("FULL");
//	km_train.display_matrix("TRAIN");
//	km_test.display_matrix("TEST");

	/* make sure matrices are correct */
	for (index_t i=0; i<km_train.num_rows; ++i)
	{
		for (index_t j=0; j<km_train.num_cols; ++j)
			ASSERT(km_train(i, j)==km(i, j));
	}

	for (index_t i=0; i<km_test.num_rows; ++i)
	{
		for (index_t j=0; j<km_test.num_cols; ++j)
			ASSERT(km_test(i, j)==km(i, j+num_train));
	}

	/* train and test again on custom kernel */
	svm->set_kernel(new CCustomKernel(km_train));
	svm->train();
	SGVector<float64_t> alphas_precomputed=svm->get_alphas();
	SGVector<index_t> svs_precomputed=svm->get_support_vectors();
	float64_t bias_precomputed=svm->get_bias();
	alphas_precomputed.display_vector("alphas_precomputed");
	svs_precomputed.display_vector("svs_precomputed");
	SG_SPRINT("bias_precomputed: %f\n", bias_precomputed);
	svm->set_kernel(new CCustomKernel(km_test));
	CBinaryLabels* predictions_precomputed=(CBinaryLabels*)svm->apply();

	/* assert that the SV, alphas and b are equal, sort before (they may have
	 * a different ordering */
	CMath::qsort(alphas.vector, alphas.vlen);
	CMath::qsort(alphas_precomputed.vector, alphas_precomputed.vlen);
	CMath::qsort(svs.vector, svs.vlen);
	CMath::qsort(svs_precomputed.vector, svs_precomputed.vlen);

	ASSERT(alphas.vlen==alphas_precomputed.vlen);
	ASSERT(svs.vlen==svs_precomputed.vlen);
	for (index_t i=0; i<alphas.vlen; ++i)
	{
		ASSERT(CMath::abs(alphas[i]-alphas_precomputed[i])<1E-3);
		ASSERT(svs[i]==svs_precomputed[i]);
	}

	ASSERT(CMath::abs(bias-bias_precomputed)<1E-3);

	/* assert that predictions are the same */
	predictions->get_int_labels().display_vector("predictions");
	predictions_precomputed->get_int_labels().
			display_vector("predictions_precomputed");

	for (index_t i=0; i<predictions->get_num_labels(); ++i)
	{
		ASSERT(predictions->get_int_label(i)==
				predictions_precomputed->get_int_label(i));
	}

	/* clean up */
	SG_SPRINT("cleaning up\n");
	SG_UNREF(svm);
	SG_UNREF(precomputed);
	SG_UNREF(labels);
	SG_UNREF(labels_test);
	SG_UNREF(predictions);
	SG_UNREF(predictions_precomputed);
	SG_UNREF(feats_train);
	SG_UNREF(feats_test);
}

int main()
{
	init_shogun_with_defaults();
//	sg_io->set_loglevel(MSG_DEBUG);

	test_svmlight();

	exit_shogun();
	return 0;
}

<commit_msg>ifdef svmlight example to not fail when svmlight is not available<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2013 Heiko Strathmann
 */
#include <shogun/lib/config.h>

#include <shogun/kernel/string/DistantSegmentsKernel.h>
#include <shogun/labels/BinaryLabels.h>
#include <shogun/features/StringFeatures.h>
#include <shogun/classifier/svm/SVMLight.h>
#include <shogun/classifier/svm/LibSVM.h>

using namespace shogun;

#ifdef USE_SVMLIGHT
void test_svmlight()
{
	/* data is random length strings with only zeros (A) or ones (B) */
	index_t num_train=100;
	index_t num_test=50;
	index_t max_length=100;
	float64_t p_x=0.5; // probability for class A
	float64_t mostly_prob=0.8;
	CDenseLabels* labels=new CBinaryLabels(num_train+num_test);
	CMath::init_random(17);

	SGStringList<char> data(num_train+num_test, max_length);
	for (index_t i=0; i<num_train+num_test; ++i)
	{
		/* determine length */
		index_t length=CMath::random(1, max_length);

		/* allocate string */
		data.strings[i]=SGString<char>(length);

		/* fill with elements and set label */
		if (p_x<CMath::random(0.0, 1.0))
		{
			labels->set_label(i, 1);
			for (index_t j=0; j<length; ++j)
			{
				char c=mostly_prob<CMath::random(0.0, 1.0) ? '0' : '1';
				data.strings[i].string[j]=c;
			}
		}
		else
		{
			labels->set_label(i, -1);
			for (index_t j=0; j<length; ++j)
			{
				char c=mostly_prob<CMath::random(0.0, 1.0) ? '1' : '0';
				data.strings[i].string[j]=c;
			}
		}

		SG_SPRINT("datum %d, class %d:\t", i, labels->get_int_label(i));
		for (index_t j=0; j<length; ++j)
			SG_SPRINT("%c", data.strings[i].string[j]);
		SG_SPRINT("\n");

	}
	CStringFeatures<char>* feats=new CStringFeatures<char>(data, BINARY);

	/* copy training and test data */
	SGVector<index_t> train_inds(num_train);
	train_inds.range_fill();
	SGVector<index_t> test_inds(num_test);
	test_inds.range_fill();
	test_inds.add(num_train);

	CStringFeatures<char>* feats_train=
			(CStringFeatures<char>*)feats->copy_subset(train_inds);
	CStringFeatures<char>* feats_test=
			(CStringFeatures<char>*)feats->copy_subset(test_inds);

	labels->add_subset(train_inds);
	CLabels* labels_train=new CBinaryLabels(labels->get_labels_copy());
	labels->remove_subset();
	labels->add_subset(test_inds);
	CLabels* labels_test=new CBinaryLabels(labels->get_labels_copy());
	labels->remove_subset();

	/* string kernel */
	CDistantSegmentsKernel* kernel=new CDistantSegmentsKernel(10, 2, 2);

	/* SVM training and testing without precomputing the kernel */
	float64_t C=1;
	CSVM* svm=new CSVMLight(C, kernel, labels_train);
//	CSVM* svm=new CLibSVM(C, kernel, labels_train);
	svm->parallel->set_num_threads(1);
	svm->set_store_model_features(false);
	svm->train(feats_train);
	SGVector<float64_t> alphas=svm->get_alphas();
	SGVector<index_t> svs=svm->get_support_vectors();
	float64_t bias=svm->get_bias();
	CBinaryLabels* predictions=(CBinaryLabels*)svm->apply(feats_test);
	alphas.display_vector("alphas");
	svs.display_vector("svs");
	SG_SPRINT("bias: %f\n", bias);

	/* now the same with a precopumputed kernel */
	kernel->init(feats, feats);
	CCustomKernel* precomputed=new CCustomKernel(kernel);
	precomputed->add_row_subset(train_inds);
	precomputed->add_col_subset(train_inds);
	SGMatrix<float64_t> km_train=precomputed->get_kernel_matrix();
	precomputed->remove_col_subset();
	precomputed->add_col_subset(test_inds);
	SGMatrix<float64_t> km_test=precomputed->get_kernel_matrix();
	precomputed->remove_row_subset();
	precomputed->remove_col_subset();
	SGMatrix<float64_t> km=precomputed->get_kernel_matrix();

//	km.display_matrix("FULL");
//	km_train.display_matrix("TRAIN");
//	km_test.display_matrix("TEST");

	/* make sure matrices are correct */
	for (index_t i=0; i<km_train.num_rows; ++i)
	{
		for (index_t j=0; j<km_train.num_cols; ++j)
			ASSERT(km_train(i, j)==km(i, j));
	}

	for (index_t i=0; i<km_test.num_rows; ++i)
	{
		for (index_t j=0; j<km_test.num_cols; ++j)
			ASSERT(km_test(i, j)==km(i, j+num_train));
	}

	/* train and test again on custom kernel */
	svm->set_kernel(new CCustomKernel(km_train));
	svm->train();
	SGVector<float64_t> alphas_precomputed=svm->get_alphas();
	SGVector<index_t> svs_precomputed=svm->get_support_vectors();
	float64_t bias_precomputed=svm->get_bias();
	alphas_precomputed.display_vector("alphas_precomputed");
	svs_precomputed.display_vector("svs_precomputed");
	SG_SPRINT("bias_precomputed: %f\n", bias_precomputed);
	svm->set_kernel(new CCustomKernel(km_test));
	CBinaryLabels* predictions_precomputed=(CBinaryLabels*)svm->apply();

	/* assert that the SV, alphas and b are equal, sort before (they may have
	 * a different ordering */
	CMath::qsort(alphas.vector, alphas.vlen);
	CMath::qsort(alphas_precomputed.vector, alphas_precomputed.vlen);
	CMath::qsort(svs.vector, svs.vlen);
	CMath::qsort(svs_precomputed.vector, svs_precomputed.vlen);

	ASSERT(alphas.vlen==alphas_precomputed.vlen);
	ASSERT(svs.vlen==svs_precomputed.vlen);
	for (index_t i=0; i<alphas.vlen; ++i)
	{
		ASSERT(CMath::abs(alphas[i]-alphas_precomputed[i])<1E-3);
		ASSERT(svs[i]==svs_precomputed[i]);
	}

	ASSERT(CMath::abs(bias-bias_precomputed)<1E-3);

	/* assert that predictions are the same */
	predictions->get_int_labels().display_vector("predictions");
	predictions_precomputed->get_int_labels().
			display_vector("predictions_precomputed");

	for (index_t i=0; i<predictions->get_num_labels(); ++i)
	{
		ASSERT(predictions->get_int_label(i)==
				predictions_precomputed->get_int_label(i));
	}

	/* clean up */
	SG_SPRINT("cleaning up\n");
	SG_UNREF(svm);
	SG_UNREF(precomputed);
	SG_UNREF(labels);
	SG_UNREF(labels_test);
	SG_UNREF(predictions);
	SG_UNREF(predictions_precomputed);
	SG_UNREF(feats_train);
	SG_UNREF(feats_test);
}

int main()
{
	init_shogun_with_defaults();
//	sg_io->set_loglevel(MSG_DEBUG);

	test_svmlight();

	exit_shogun();
	return 0;
}
#else
int main(int argc, char **argv)
{
	return 0;
}
#endif
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 2004 by Stanislav Karchebny                             *
 *   Stanislav.Karchebny@kdemail.net                                       *
 *                                                                         *
 *   Licensed under GPL.                                                   *
 ***************************************************************************/

#include "akregator_part.h"
#include "akregator_view.h"
#include "akregatorconfig.h"

#include <kparts/genericfactory.h>
#include <kapplication.h>
#include <kinstance.h>
#include <kaction.h>
#include <kactionclasses.h>

#include <kstandarddirs.h>
#include <kstdaction.h>
#include <kfiledialog.h>

#include <qfile.h>

using namespace Akregator;

typedef KParts::GenericFactory< aKregatorPart > aKregatorFactory;
K_EXPORT_COMPONENT_FACTORY( libakregatorpart, aKregatorFactory )

aKregatorPart::aKregatorPart( QWidget *parentWidget, const char * /*widgetName*/,
                              QObject *parent, const char *name, const QStringList& )
    : KParts::ReadWritePart(parent, name)
{
    // we need an instance
    setInstance( aKregatorFactory::instance() );

    m_view=new aKregatorView(this, parentWidget, "Akregator View");
    extension=new KParts::BrowserExtension(this, "ak_extension");

    // notify the part that this is our internal widget
    setWidget(m_view);

    // create our actions
    KStdAction::open(this, SLOT(fileOpen()), actionCollection());
    KStdAction::saveAs(this, SLOT(fileSaveAs()), actionCollection());
    KStdAction::save(this, SLOT(save()), actionCollection());
    recentFilesAction = KStdAction::openRecent( this, SLOT(openURL(const KURL&)), actionCollection(), "file_open_recent" );

    new KAction(i18n("&Import Feeds..."), "", "", this, SLOT(fileImport()), actionCollection(), "file_import");

    /* -- ACTIONS */

    /* --- Feed popup menu */
    new KAction(i18n("&Add..."), "bookmark_add", "Alt+Insert", m_view, SLOT(slotFeedAdd()), actionCollection(), "feed_add");
    new KAction(i18n("New &Folder..."), "folder_new", "Alt+Shift+Insert", m_view, SLOT(slotFeedAddGroup()), actionCollection(), "feed_add_group");
    new KAction(i18n("&Delete"), "editdelete", "Shift+Delete", m_view, SLOT(slotFeedRemove()), actionCollection(), "feed_remove");
    new KAction(i18n("&Edit"), "edit", "F2", m_view, SLOT(slotFeedModify()), actionCollection(), "feed_modify");
    new KAction(i18n("&Fetch"), "down", "Alt+Ctrl+F", m_view, SLOT(slotFetchCurrentFeed()), actionCollection(), "feed_fetch");
    new KAction(i18n("Fe&tch All"), "bottom", "Alt+Ctrl+A", m_view, SLOT(slotFetchAllFeeds()), actionCollection(), "feed_fetch_all");
    new KAction(i18n("Mark All as Read"), "", "Ctrl+R", m_view, SLOT(slotMarkAllRead()), actionCollection(), "feed_mark_all_as_read");

    KRadioAction *ra=new KRadioAction(i18n("&Normal View"), "view_top_bottom", "Alt+Ctrl+1", m_view, SLOT(slotNormalView()), actionCollection(), "normal_view");
    ra->setExclusiveGroup( "ViewMode" );

    ra=new KRadioAction(i18n("&Widescreen View"), "view_left_right", "Alt+Ctrl+2", m_view, SLOT(slotWidescreenView()), actionCollection(), "widescreen_view");
    ra->setExclusiveGroup( "ViewMode" );

    ra=new KRadioAction(i18n("&Combined View"), "view_text", "Alt+Ctrl+3", m_view, SLOT(slotCombinedView()), actionCollection(), "combined_view");
    ra->setExclusiveGroup( "ViewMode" );

    // set our XML-UI resource file
    setXMLFile("akregator_part.rc");

    readRecentFileEntries();

    // we are read-write by default
    setReadWrite(true);

    // we are not modified since we haven't done anything yet
    setModified(false);
}

aKregatorPart::~aKregatorPart()
{
   Settings::writeConfig();
}

void aKregatorPart::readRecentFileEntries()
{
   KConfig *config = new KConfig("akregatorrc"); // move to shell!
   recentFilesAction->loadEntries(config,"Recent Files");
   delete config;
}

void aKregatorPart::setReadWrite(bool rw)
{
    ReadWritePart::setReadWrite(rw);
}

void aKregatorPart::setModified(bool modified)
{
    // get a handle on our Save action and make sure it is valid
    KAction *save = actionCollection()->action(KStdAction::stdName(KStdAction::Save));
    if (!save)
        return;

    // if so, we either enable or disable it based on the current
    // state
    if (modified)
        save->setEnabled(true);
    else
        save->setEnabled(false);

    // in any event, we want our parent to do it's thing
    ReadWritePart::setModified(modified);
}

void aKregatorPart::changePart(KParts::Part *p)
{
    emit partChanged(p);
}

void aKregatorPart::setStatusBar(const QString &text)
{
   emit setStatusBarText(text);
}

void aKregatorPart::setProgress(int percent)
{
    emit extension->loadingProgress(percent);
}

/*************************************************************************************************/
/* LOAD                                                                                */
/*************************************************************************************************/

bool aKregatorPart::openURL(const KURL& url)
{
   recentFilesAction->addURL(url);
   return inherited::openURL(url);
}

bool aKregatorPart::openFile()
{
    // m_file is always local so we can use QFile on it
    QFile file(m_file);
    if (file.open(IO_ReadOnly) == false)
        return false;

    setProgress(0);
    kapp->processEvents();

    // Read OPML feeds list and build QDom tree.
    QTextStream stream(&file);
    stream.setEncoding(QTextStream::UnicodeUTF8); // FIXME not all opmls are in utf8
    QDomDocument doc;
    QString str;

    str = stream.read();

    file.close();

    if (!doc.setContent(str))
    {
        emit extension->loadingProgress(-1);
        return false;
    }

    if (!m_view->loadFeeds(doc)) // will take care of building feeds tree and loading archive
    {
        emit extension->loadingProgress(-1);
        return false;
    }

    // just for fun, set the status bar
    setStatusBar( m_url.prettyURL() );

    return true;
}

/*************************************************************************************************/
/* SAVE                                                                                */
/*************************************************************************************************/

bool aKregatorPart::saveFile()
{
    // if we aren't read-write, return immediately
    if (isReadWrite() == false)
        return false;

    // m_file is always local, so we use QFile
    QFile file(m_file);
    if (file.open(IO_WriteOnly) == false)
        return fileSaveAs();

    // use QTextStream to dump the text to the file
    QTextStream stream(&file);
    stream.setEncoding(QTextStream::UnicodeUTF8);

    // Write OPML data file.
    // Archive data files are saved elsewhere.

    QDomDocument newdoc;
    QDomElement root = newdoc.createElement( "opml" );
    root.setAttribute( "version", "1.0" );
    newdoc.appendChild( root );

    QDomElement head = newdoc.createElement( "head" );
    root.appendChild( head );

    QDomElement title = newdoc.createElement( "text" );
    head.appendChild( title );

    QDomText t = newdoc.createTextNode( "aKregator Feeds" );
    title.appendChild( t );

    QDomElement body = newdoc.createElement( "body" );
    root.appendChild( body );

    m_view->storeTree( body, newdoc);

    stream << newdoc.toString();

    file.close();

    return true;
}

void aKregatorPart::importFile(QString file_name)
{
    QFile file(file_name);
    if (file.open(IO_ReadOnly) == false)
        return;

    // Read OPML feeds list and build QDom tree.
    QDomDocument doc;
    if (!doc.setContent(file.readAll())) {
        kdDebug() << "Failed to build DOM tree, is " << file_name << " valid XML?" << endl;
        return;
    }

    if (m_view->importFeeds(doc))
        setModified(true);
}

/*************************************************************************************************/
/* SLOTS                                                                                */
/*************************************************************************************************/

void aKregatorPart::fileOpen()
{
    // this slot is called whenever the File->Open menu is selected,
    // the Open shortcut is pressed (usually CTRL+O) or the Open toolbar
    // button is clicked
    QString file_name = KFileDialog::getOpenFileName( QString::null,
                        "*.opml *.xml|" + i18n("OPML Outlines (*.opml, *.xml)")
                        +"\n*|" + i18n("All Files") );

    if (file_name.isEmpty() == false)
        openURL(file_name);
}

bool aKregatorPart::fileSaveAs()
{
    // this slot is called whenever the File->Save As menu is selected,
    QString file_name = KFileDialog::getSaveFileName( QString::null,
                        "*.opml *.xml|" + i18n("OPML Outlines (*.opml, *.xml)")
                        +"\n*|" + i18n("All Files") );
    if (file_name.isEmpty() == false)
    {
        saveAs(file_name);
        return true;
    }
    return false;
}

void aKregatorPart::fileImport()
{
    QString file_name = KFileDialog::getOpenFileName( locate( "appdata", "kde.opml" ),
                        "*.opml *.xml|" + i18n("OPML Outlines (*.opml, *.xml)")
                        +"\n*|" + i18n("All Files") );

    if (file_name.isEmpty() == false)
        importFile(file_name);
}

/*************************************************************************************************/
/* STATIC METHODS                                                                                */
/*************************************************************************************************/

KAboutData* aKregatorPart::s_about = 0L;

KAboutData *aKregatorPart::createAboutData()
{
    if ( !s_about ) {
        s_about = new KAboutData("akregatorpart", I18N_NOOP("aKregatorPart"), "0.9",
                                 I18N_NOOP("This is a KPart for RSS aggregator"),
                                 KAboutData::License_GPL, "(C) 2004 Stanislav Karchebny", 0,
                                 "http://berk.upnet.ru/projects/kde/akregator",
                                 "Stanislav.Karchebny@kdemail.net");
        s_about->addAuthor("Stanislav Karchebny", I18N_NOOP("Author, Developer, Maintainer"),
                           "Stanislav.Karchebny@kdemail.net");
        s_about->addAuthor("Sashmit Bhaduri", I18N_NOOP("Developer"), "smt@vfemail.net");
    }
    return s_about;
}

#include "akregator_part.moc"
<commit_msg>tried to simplify some of the shortcuts.. hopefully it doesn't muck up too much<commit_after>/***************************************************************************
 *   Copyright (C) 2004 by Stanislav Karchebny                             *
 *   Stanislav.Karchebny@kdemail.net                                       *
 *                                                                         *
 *   Licensed under GPL.                                                   *
 ***************************************************************************/

#include "akregator_part.h"
#include "akregator_view.h"
#include "akregatorconfig.h"

#include <kparts/genericfactory.h>
#include <kapplication.h>
#include <kinstance.h>
#include <kaction.h>
#include <kactionclasses.h>

#include <kstandarddirs.h>
#include <kstdaction.h>
#include <kfiledialog.h>

#include <qfile.h>

using namespace Akregator;

typedef KParts::GenericFactory< aKregatorPart > aKregatorFactory;
K_EXPORT_COMPONENT_FACTORY( libakregatorpart, aKregatorFactory )

aKregatorPart::aKregatorPart( QWidget *parentWidget, const char * /*widgetName*/,
                              QObject *parent, const char *name, const QStringList& )
    : KParts::ReadWritePart(parent, name)
{
    // we need an instance
    setInstance( aKregatorFactory::instance() );

    m_view=new aKregatorView(this, parentWidget, "Akregator View");
    extension=new KParts::BrowserExtension(this, "ak_extension");

    // notify the part that this is our internal widget
    setWidget(m_view);

    // create our actions
    KStdAction::open(this, SLOT(fileOpen()), actionCollection());
    KStdAction::saveAs(this, SLOT(fileSaveAs()), actionCollection());
    KStdAction::save(this, SLOT(save()), actionCollection());
    recentFilesAction = KStdAction::openRecent( this, SLOT(openURL(const KURL&)), actionCollection(), "file_open_recent" );

    new KAction(i18n("&Import Feeds..."), "", "", this, SLOT(fileImport()), actionCollection(), "file_import");

    /* -- ACTIONS */

    /* --- Feed popup menu */
    new KAction(i18n("&Add..."), "bookmark_add", "Insert", m_view, SLOT(slotFeedAdd()), actionCollection(), "feed_add");
    new KAction(i18n("New &Folder..."), "folder_new", "Shift+Insert", m_view, SLOT(slotFeedAddGroup()), actionCollection(), "feed_add_group");
    new KAction(i18n("&Delete"), "editdelete", "Delete", m_view, SLOT(slotFeedRemove()), actionCollection(), "feed_remove");
    new KAction(i18n("&Edit"), "edit", "F2", m_view, SLOT(slotFeedModify()), actionCollection(), "feed_modify");
    new KAction(i18n("&Fetch"), "down", "Ctrl+R", m_view, SLOT(slotFetchCurrentFeed()), actionCollection(), "feed_fetch");
    new KAction(i18n("Fe&tch All"), "bottom", "Shift+Ctrl+R", m_view, SLOT(slotFetchAllFeeds()), actionCollection(), "feed_fetch_all");
    new KAction(i18n("Mark All as Read"), "", "Ctrl+M", m_view, SLOT(slotMarkAllRead()), actionCollection(), "feed_mark_all_as_read");

    KRadioAction *ra=new KRadioAction(i18n("&Normal View"), "view_top_bottom", "Shift+Ctrl+1", m_view, SLOT(slotNormalView()), actionCollection(), "normal_view");
    ra->setExclusiveGroup( "ViewMode" );

    ra=new KRadioAction(i18n("&Widescreen View"), "view_left_right", "Shift+Ctrl+2", m_view, SLOT(slotWidescreenView()), actionCollection(), "widescreen_view");
    ra->setExclusiveGroup( "ViewMode" );

    ra=new KRadioAction(i18n("&Combined View"), "view_text", "Shift+Ctrl+3", m_view, SLOT(slotCombinedView()), actionCollection(), "combined_view");
    ra->setExclusiveGroup( "ViewMode" );

    // set our XML-UI resource file
    setXMLFile("akregator_part.rc");

    readRecentFileEntries();

    // we are read-write by default
    setReadWrite(true);

    // we are not modified since we haven't done anything yet
    setModified(false);
}

aKregatorPart::~aKregatorPart()
{
   Settings::writeConfig();
}

void aKregatorPart::readRecentFileEntries()
{
   KConfig *config = new KConfig("akregatorrc"); // move to shell!
   recentFilesAction->loadEntries(config,"Recent Files");
   delete config;
}

void aKregatorPart::setReadWrite(bool rw)
{
    ReadWritePart::setReadWrite(rw);
}

void aKregatorPart::setModified(bool modified)
{
    // get a handle on our Save action and make sure it is valid
    KAction *save = actionCollection()->action(KStdAction::stdName(KStdAction::Save));
    if (!save)
        return;

    // if so, we either enable or disable it based on the current
    // state
    if (modified)
        save->setEnabled(true);
    else
        save->setEnabled(false);

    // in any event, we want our parent to do it's thing
    ReadWritePart::setModified(modified);
}

void aKregatorPart::changePart(KParts::Part *p)
{
    emit partChanged(p);
}

void aKregatorPart::setStatusBar(const QString &text)
{
   emit setStatusBarText(text);
}

void aKregatorPart::setProgress(int percent)
{
    emit extension->loadingProgress(percent);
}

/*************************************************************************************************/
/* LOAD                                                                                */
/*************************************************************************************************/

bool aKregatorPart::openURL(const KURL& url)
{
   recentFilesAction->addURL(url);
   return inherited::openURL(url);
}

bool aKregatorPart::openFile()
{
    // m_file is always local so we can use QFile on it
    QFile file(m_file);
    if (file.open(IO_ReadOnly) == false)
        return false;

    setProgress(0);
    kapp->processEvents();

    // Read OPML feeds list and build QDom tree.
    QTextStream stream(&file);
    stream.setEncoding(QTextStream::UnicodeUTF8); // FIXME not all opmls are in utf8
    QDomDocument doc;
    QString str;

    str = stream.read();

    file.close();

    if (!doc.setContent(str))
    {
        emit extension->loadingProgress(-1);
        return false;
    }

    if (!m_view->loadFeeds(doc)) // will take care of building feeds tree and loading archive
    {
        emit extension->loadingProgress(-1);
        return false;
    }

    // just for fun, set the status bar
    setStatusBar( m_url.prettyURL() );

    return true;
}

/*************************************************************************************************/
/* SAVE                                                                                */
/*************************************************************************************************/

bool aKregatorPart::saveFile()
{
    // if we aren't read-write, return immediately
    if (isReadWrite() == false)
        return false;

    // m_file is always local, so we use QFile
    QFile file(m_file);
    if (file.open(IO_WriteOnly) == false)
        return fileSaveAs();

    // use QTextStream to dump the text to the file
    QTextStream stream(&file);
    stream.setEncoding(QTextStream::UnicodeUTF8);

    // Write OPML data file.
    // Archive data files are saved elsewhere.

    QDomDocument newdoc;
    QDomElement root = newdoc.createElement( "opml" );
    root.setAttribute( "version", "1.0" );
    newdoc.appendChild( root );

    QDomElement head = newdoc.createElement( "head" );
    root.appendChild( head );

    QDomElement title = newdoc.createElement( "text" );
    head.appendChild( title );

    QDomText t = newdoc.createTextNode( "aKregator Feeds" );
    title.appendChild( t );

    QDomElement body = newdoc.createElement( "body" );
    root.appendChild( body );

    m_view->storeTree( body, newdoc);

    stream << newdoc.toString();

    file.close();

    return true;
}

void aKregatorPart::importFile(QString file_name)
{
    QFile file(file_name);
    if (file.open(IO_ReadOnly) == false)
        return;

    // Read OPML feeds list and build QDom tree.
    QDomDocument doc;
    if (!doc.setContent(file.readAll())) {
        kdDebug() << "Failed to build DOM tree, is " << file_name << " valid XML?" << endl;
        return;
    }

    if (m_view->importFeeds(doc))
        setModified(true);
}

/*************************************************************************************************/
/* SLOTS                                                                                */
/*************************************************************************************************/

void aKregatorPart::fileOpen()
{
    // this slot is called whenever the File->Open menu is selected,
    // the Open shortcut is pressed (usually CTRL+O) or the Open toolbar
    // button is clicked
    QString file_name = KFileDialog::getOpenFileName( QString::null,
                        "*.opml *.xml|" + i18n("OPML Outlines (*.opml, *.xml)")
                        +"\n*|" + i18n("All Files") );

    if (file_name.isEmpty() == false)
        openURL(file_name);
}

bool aKregatorPart::fileSaveAs()
{
    // this slot is called whenever the File->Save As menu is selected,
    QString file_name = KFileDialog::getSaveFileName( QString::null,
                        "*.opml *.xml|" + i18n("OPML Outlines (*.opml, *.xml)")
                        +"\n*|" + i18n("All Files") );
    if (file_name.isEmpty() == false)
    {
        saveAs(file_name);
        return true;
    }
    return false;
}

void aKregatorPart::fileImport()
{
    QString file_name = KFileDialog::getOpenFileName( locate( "appdata", "kde.opml" ),
                        "*.opml *.xml|" + i18n("OPML Outlines (*.opml, *.xml)")
                        +"\n*|" + i18n("All Files") );

    if (file_name.isEmpty() == false)
        importFile(file_name);
}

/*************************************************************************************************/
/* STATIC METHODS                                                                                */
/*************************************************************************************************/

KAboutData* aKregatorPart::s_about = 0L;

KAboutData *aKregatorPart::createAboutData()
{
    if ( !s_about ) {
        s_about = new KAboutData("akregatorpart", I18N_NOOP("aKregatorPart"), "0.9",
                                 I18N_NOOP("This is a KPart for RSS aggregator"),
                                 KAboutData::License_GPL, "(C) 2004 Stanislav Karchebny", 0,
                                 "http://berk.upnet.ru/projects/kde/akregator",
                                 "Stanislav.Karchebny@kdemail.net");
        s_about->addAuthor("Stanislav Karchebny", I18N_NOOP("Author, Developer, Maintainer"),
                           "Stanislav.Karchebny@kdemail.net");
        s_about->addAuthor("Sashmit Bhaduri", I18N_NOOP("Developer"), "smt@vfemail.net");
    }
    return s_about;
}

#include "akregator_part.moc"
<|endoftext|>