<commit_before>/**************************************************************************
 *
 * Copyright 2009-2011 VMware, Inc.
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 **************************************************************************/

#include <stddef.h>

#include <llvm-c/Core.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/Target/TargetInstrInfo.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Support/MemoryObject.h>

#if HAVE_LLVM >= 0x0300
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Support/TargetSelect.h>
#else /* HAVE_LLVM < 0x0300 */
#include <llvm/Target/TargetRegistry.h>
#include <llvm/Target/TargetSelect.h>
#endif /* HAVE_LLVM < 0x0300 */

#if HAVE_LLVM >= 0x0209
#include <llvm/Support/Host.h>
#else /* HAVE_LLVM < 0x0209 */
#include <llvm/System/Host.h>
#endif /* HAVE_LLVM < 0x0209 */

#if HAVE_LLVM >= 0x0207
#include <llvm/MC/MCDisassembler.h>
#include <llvm/MC/MCAsmInfo.h>
#include <llvm/MC/MCInst.h>
#include <llvm/MC/MCInstPrinter.h>
#endif /* HAVE_LLVM >= 0x0207 */

#include "util/u_math.h"
#include "util/u_debug.h"

#include "lp_bld_debug.h"

/**
 * Check alignment.
 *
 * It is important that this check is not implemented as a macro or inlined
 * function, as the compiler assumptions in respect to alignment of global
 * and stack variables would often make the check a no op, defeating the
 * whole purpose of the exercise.
 */
extern "C" boolean
lp_check_alignment(const void *ptr, unsigned alignment)
{
   assert(util_is_power_of_two(alignment));
   return ((uintptr_t)ptr & (alignment - 1)) == 0;
}

class raw_debug_ostream :
   public llvm::raw_ostream
{
   uint64_t pos;

   void write_impl(const char *Ptr, size_t Size);
   uint64_t current_pos() { return pos; }
   uint64_t current_pos() const { return pos; }

#if HAVE_LLVM >= 0x207
   uint64_t preferred_buffer_size() { return 512; }
#else
   size_t preferred_buffer_size() { return 512; }
#endif
};

void
raw_debug_ostream::write_impl(const char *Ptr, size_t Size)
{
   if (Size > 0) {
      char *lastPtr = (char *)&Ptr[Size];
      char last = *lastPtr;
      *lastPtr = 0;
      _debug_printf("%*s", Size, Ptr);
      *lastPtr = last;
      pos += Size;
   }
}

/**
 * Same as LLVMDumpValue, but through our debugging channels.
 */
extern "C" void
lp_debug_dump_value(LLVMValueRef value)
{
#if (defined(PIPE_OS_WINDOWS) && !defined(PIPE_CC_MSVC)) || defined(PIPE_OS_EMBDDED)
   raw_debug_ostream os;
   llvm::unwrap(value)->print(os);
   os.flush();
#else
   LLVMDumpValue(value);
#endif
}

#if HAVE_LLVM >= 0x0207
/*
 * MemoryObject wrapper around a buffer of memory, to be used by MC
 * disassembler.
 */
class BufferMemoryObject:
   public llvm::MemoryObject
{
private:
   const uint8_t *Bytes;
   uint64_t Length;
public:
   BufferMemoryObject(const uint8_t *bytes, uint64_t length) :
      Bytes(bytes), Length(length)
   {
   }

   uint64_t getBase() const
   {
      return 0;
   }

   uint64_t getExtent() const
   {
      return Length;
   }

   int readByte(uint64_t addr, uint8_t *byte) const
   {
      if (addr > getExtent())
         return -1;
      *byte = Bytes[addr];
      return 0;
   }
};
#endif /* HAVE_LLVM >= 0x0207 */

/*
 * Disassemble a function, using the LLVM MC disassembler.
 *
 * See also:
 * - http://blog.llvm.org/2010/01/x86-disassembler.html
 * - http://blog.llvm.org/2010/04/intro-to-llvm-mc-project.html
 */
extern "C" void
lp_disassemble(const void* func)
{
#if HAVE_LLVM >= 0x0207
   using namespace llvm;

   const uint8_t *bytes = (const uint8_t *)func;

   /*
    * Limit disassembly to this extent
    */
   const uint64_t extent = 0x10000;

   uint64_t max_pc = 0;

   /*
    * Initialize all used objects.
    */

#if HAVE_LLVM >= 0x0301
   std::string Triple = sys::getDefaultTargetTriple();
#else
   std::string Triple = sys::getHostTriple();
#endif

   std::string Error;
   const Target *T = TargetRegistry::lookupTarget(Triple, Error);

#if HAVE_LLVM >= 0x0208
   InitializeNativeTargetAsmPrinter();
#elif defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
   LLVMInitializeX86AsmPrinter();
#elif defined(PIPE_ARCH_ARM)
   LLVMInitializeARMAsmPrinter();
#elif defined(PIPE_ARCH_PPC)
   LLVMInitializePowerPCAsmPrinter();
#endif

#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
   LLVMInitializeX86Disassembler();
#elif defined(PIPE_ARCH_ARM)
   LLVMInitializeARMDisassembler();
#endif

#if HAVE_LLVM >= 0x0300
   OwningPtr<const MCAsmInfo> AsmInfo(T->createMCAsmInfo(Triple));
#else
   OwningPtr<const MCAsmInfo> AsmInfo(T->createAsmInfo(Triple));
#endif

   if (!AsmInfo) {
      debug_printf("error: no assembly info for target %s\n", Triple.c_str());
      return;
   }

#if HAVE_LLVM >= 0x0300
   const MCSubtargetInfo *STI = T->createMCSubtargetInfo(Triple, sys::getHostCPUName(), "");
   OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler(*STI));
#else
   OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler());
#endif
   if (!DisAsm) {
      debug_printf("error: no disassembler for target %s\n", Triple.c_str());
      return;
   }

   raw_debug_ostream Out;

#if HAVE_LLVM >= 0x0300
   unsigned int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
#else
   int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
#endif

#if HAVE_LLVM >= 0x0301
   OwningPtr<const MCRegisterInfo> MRI(T->createMCRegInfo(Triple));
   if (!MRI) {
      debug_printf("error: no register info for target %s\n", Triple.c_str());
      return;
   }
#endif

#if HAVE_LLVM >= 0x0301
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *MRI, *STI));
#elif HAVE_LLVM == 0x0300
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *STI));
#elif HAVE_LLVM >= 0x0208
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo));
#else
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, Out));
#endif
   if (!Printer) {
      debug_printf("error: no instruction printer for target %s\n", Triple.c_str());
      return;
   }

#if HAVE_LLVM >= 0x0301
   TargetOptions options;
#if defined(DEBUG)
   options.JITEmitDebugInfo = true;
#endif
#if defined(PIPE_ARCH_X86)
   options.StackAlignmentOverride = 4;
#endif
#if defined(DEBUG) || defined(PROFILE)
   options.NoFramePointerElim = true;
#endif
   TargetMachine *TM = T->createTargetMachine(Triple, sys::getHostCPUName(), "", options);
#elif HAVE_LLVM == 0x0300
   TargetMachine *TM = T->createTargetMachine(Triple, sys::getHostCPUName(), "");
#else
   TargetMachine *TM = T->createTargetMachine(Triple, "");
#endif

   const TargetInstrInfo *TII = TM->getInstrInfo();

   /*
    * Wrap the data in a MemoryObject
    */
   BufferMemoryObject memoryObject((const uint8_t *)bytes, extent);

   uint64_t pc;
   pc = 0;
   while (true) {
      MCInst Inst;
      uint64_t Size;

      /*
       * Print address.  We use addresses relative to the start of the function,
       * so that between runs.
       */

      debug_printf("%6lu:\t", (unsigned long)pc);

      if (!DisAsm->getInstruction(Inst, Size, memoryObject,
                                 pc,
#if HAVE_LLVM >= 0x0300
				  nulls(), nulls())) {
#else
				  nulls())) {
#endif
         debug_printf("invalid\n");
         pc += 1;
      }

      /*
       * Output the bytes in hexidecimal format.
       */

      if (0) {
         unsigned i;
         for (i = 0; i < Size; ++i) {
            debug_printf("%02x ", ((const uint8_t*)bytes)[pc + i]);
         }
         for (; i < 16; ++i) {
            debug_printf("   ");
         }
      }

      /*
       * Print the instruction.
       */

#if HAVE_LLVM >= 0x0300
      Printer->printInst(&Inst, Out, "");
#elif HAVE_LLVM >= 0x208
      Printer->printInst(&Inst, Out);
#else
      Printer->printInst(&Inst);
#endif
      Out.flush();

      /*
       * Advance.
       */

      pc += Size;

#if HAVE_LLVM >= 0x0300
      const MCInstrDesc &TID = TII->get(Inst.getOpcode());
#else
      const TargetInstrDesc &TID = TII->get(Inst.getOpcode());
#endif

      /*
       * Keep track of forward jumps to a nearby address.
       */

      if (TID.isBranch()) {
         for (unsigned i = 0; i < Inst.getNumOperands(); ++i) {
            const MCOperand &operand = Inst.getOperand(i);
            if (operand.isImm()) {
               uint64_t jump;

               /*
                * FIXME: Handle both relative and absolute addresses correctly.
                * EDInstInfo actually has this info, but operandTypes and
                * operandFlags enums are not exposed in the public interface.
                */

               if (1) {
                  /*
                   * PC relative addr.
                   */

                  jump = pc + operand.getImm();
               } else {
                  /*
                   * Absolute addr.
                   */

                  jump = (uint64_t)operand.getImm();
               }

               /*
                * Output the address relative to the function start, given
                * that MC will print the addresses relative the current pc.
                */
               debug_printf("\t\t; %lu", (unsigned long)jump);

               /*
                * Ignore far jumps given it could be actually a tail return to
                * a random address.
                */

               if (jump > max_pc &&
                   jump < extent) {
                  max_pc = jump;
               }
            }
         }
      }

      debug_printf("\n");

      /*
       * Stop disassembling on return statements, if there is no record of a
       * jump to a successive address.
       */

      if (TID.isReturn()) {
         if (pc > max_pc) {
            break;
         }
      }
   }

   /*
    * Print GDB command, useful to verify output.
    */

   if (0) {
      debug_printf("disassemble %p %p\n", bytes, bytes + pc);
   }

   debug_printf("\n");
#else /* HAVE_LLVM < 0x0207 */
   (void)func;
#endif /* HAVE_LLVM < 0x0207 */
}

<commit_msg>gallivm: Use InitializeNativeTargetDisassembler().<commit_after>/**************************************************************************
 *
 * Copyright 2009-2011 VMware, Inc.
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 **************************************************************************/

#include <stddef.h>

#include <llvm-c/Core.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/Target/TargetInstrInfo.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Support/MemoryObject.h>

#if HAVE_LLVM >= 0x0300
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Support/TargetSelect.h>
#else /* HAVE_LLVM < 0x0300 */
#include <llvm/Target/TargetRegistry.h>
#include <llvm/Target/TargetSelect.h>
#endif /* HAVE_LLVM < 0x0300 */

#if HAVE_LLVM >= 0x0209
#include <llvm/Support/Host.h>
#else /* HAVE_LLVM < 0x0209 */
#include <llvm/System/Host.h>
#endif /* HAVE_LLVM < 0x0209 */

#if HAVE_LLVM >= 0x0207
#include <llvm/MC/MCDisassembler.h>
#include <llvm/MC/MCAsmInfo.h>
#include <llvm/MC/MCInst.h>
#include <llvm/MC/MCInstPrinter.h>
#endif /* HAVE_LLVM >= 0x0207 */

#include "util/u_math.h"
#include "util/u_debug.h"

#include "lp_bld_debug.h"

/**
 * Check alignment.
 *
 * It is important that this check is not implemented as a macro or inlined
 * function, as the compiler assumptions in respect to alignment of global
 * and stack variables would often make the check a no op, defeating the
 * whole purpose of the exercise.
 */
extern "C" boolean
lp_check_alignment(const void *ptr, unsigned alignment)
{
   assert(util_is_power_of_two(alignment));
   return ((uintptr_t)ptr & (alignment - 1)) == 0;
}

class raw_debug_ostream :
   public llvm::raw_ostream
{
   uint64_t pos;

   void write_impl(const char *Ptr, size_t Size);
   uint64_t current_pos() { return pos; }
   uint64_t current_pos() const { return pos; }

#if HAVE_LLVM >= 0x207
   uint64_t preferred_buffer_size() { return 512; }
#else
   size_t preferred_buffer_size() { return 512; }
#endif
};

void
raw_debug_ostream::write_impl(const char *Ptr, size_t Size)
{
   if (Size > 0) {
      char *lastPtr = (char *)&Ptr[Size];
      char last = *lastPtr;
      *lastPtr = 0;
      _debug_printf("%*s", Size, Ptr);
      *lastPtr = last;
      pos += Size;
   }
}

/**
 * Same as LLVMDumpValue, but through our debugging channels.
 */
extern "C" void
lp_debug_dump_value(LLVMValueRef value)
{
#if (defined(PIPE_OS_WINDOWS) && !defined(PIPE_CC_MSVC)) || defined(PIPE_OS_EMBDDED)
   raw_debug_ostream os;
   llvm::unwrap(value)->print(os);
   os.flush();
#else
   LLVMDumpValue(value);
#endif
}

#if HAVE_LLVM >= 0x0207
/*
 * MemoryObject wrapper around a buffer of memory, to be used by MC
 * disassembler.
 */
class BufferMemoryObject:
   public llvm::MemoryObject
{
private:
   const uint8_t *Bytes;
   uint64_t Length;
public:
   BufferMemoryObject(const uint8_t *bytes, uint64_t length) :
      Bytes(bytes), Length(length)
   {
   }

   uint64_t getBase() const
   {
      return 0;
   }

   uint64_t getExtent() const
   {
      return Length;
   }

   int readByte(uint64_t addr, uint8_t *byte) const
   {
      if (addr > getExtent())
         return -1;
      *byte = Bytes[addr];
      return 0;
   }
};
#endif /* HAVE_LLVM >= 0x0207 */

/*
 * Disassemble a function, using the LLVM MC disassembler.
 *
 * See also:
 * - http://blog.llvm.org/2010/01/x86-disassembler.html
 * - http://blog.llvm.org/2010/04/intro-to-llvm-mc-project.html
 */
extern "C" void
lp_disassemble(const void* func)
{
#if HAVE_LLVM >= 0x0207
   using namespace llvm;

   const uint8_t *bytes = (const uint8_t *)func;

   /*
    * Limit disassembly to this extent
    */
   const uint64_t extent = 0x10000;

   uint64_t max_pc = 0;

   /*
    * Initialize all used objects.
    */

#if HAVE_LLVM >= 0x0301
   std::string Triple = sys::getDefaultTargetTriple();
#else
   std::string Triple = sys::getHostTriple();
#endif

   std::string Error;
   const Target *T = TargetRegistry::lookupTarget(Triple, Error);

#if HAVE_LLVM >= 0x0208
   InitializeNativeTargetAsmPrinter();
#elif defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
   LLVMInitializeX86AsmPrinter();
#elif defined(PIPE_ARCH_ARM)
   LLVMInitializeARMAsmPrinter();
#elif defined(PIPE_ARCH_PPC)
   LLVMInitializePowerPCAsmPrinter();
#endif

#if HAVE_LLVM >= 0x0301
   InitializeNativeTargetDisassembler();
#elif defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
   LLVMInitializeX86Disassembler();
#elif defined(PIPE_ARCH_ARM)
   LLVMInitializeARMDisassembler();
#endif

#if HAVE_LLVM >= 0x0300
   OwningPtr<const MCAsmInfo> AsmInfo(T->createMCAsmInfo(Triple));
#else
   OwningPtr<const MCAsmInfo> AsmInfo(T->createAsmInfo(Triple));
#endif

   if (!AsmInfo) {
      debug_printf("error: no assembly info for target %s\n", Triple.c_str());
      return;
   }

#if HAVE_LLVM >= 0x0300
   const MCSubtargetInfo *STI = T->createMCSubtargetInfo(Triple, sys::getHostCPUName(), "");
   OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler(*STI));
#else
   OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler());
#endif
   if (!DisAsm) {
      debug_printf("error: no disassembler for target %s\n", Triple.c_str());
      return;
   }

   raw_debug_ostream Out;

#if HAVE_LLVM >= 0x0300
   unsigned int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
#else
   int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
#endif

#if HAVE_LLVM >= 0x0301
   OwningPtr<const MCRegisterInfo> MRI(T->createMCRegInfo(Triple));
   if (!MRI) {
      debug_printf("error: no register info for target %s\n", Triple.c_str());
      return;
   }
#endif

#if HAVE_LLVM >= 0x0301
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *MRI, *STI));
#elif HAVE_LLVM == 0x0300
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *STI));
#elif HAVE_LLVM >= 0x0208
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo));
#else
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, Out));
#endif
   if (!Printer) {
      debug_printf("error: no instruction printer for target %s\n", Triple.c_str());
      return;
   }

#if HAVE_LLVM >= 0x0301
   TargetOptions options;
#if defined(DEBUG)
   options.JITEmitDebugInfo = true;
#endif
#if defined(PIPE_ARCH_X86)
   options.StackAlignmentOverride = 4;
#endif
#if defined(DEBUG) || defined(PROFILE)
   options.NoFramePointerElim = true;
#endif
   TargetMachine *TM = T->createTargetMachine(Triple, sys::getHostCPUName(), "", options);
#elif HAVE_LLVM == 0x0300
   TargetMachine *TM = T->createTargetMachine(Triple, sys::getHostCPUName(), "");
#else
   TargetMachine *TM = T->createTargetMachine(Triple, "");
#endif

   const TargetInstrInfo *TII = TM->getInstrInfo();

   /*
    * Wrap the data in a MemoryObject
    */
   BufferMemoryObject memoryObject((const uint8_t *)bytes, extent);

   uint64_t pc;
   pc = 0;
   while (true) {
      MCInst Inst;
      uint64_t Size;

      /*
       * Print address.  We use addresses relative to the start of the function,
       * so that between runs.
       */

      debug_printf("%6lu:\t", (unsigned long)pc);

      if (!DisAsm->getInstruction(Inst, Size, memoryObject,
                                 pc,
#if HAVE_LLVM >= 0x0300
				  nulls(), nulls())) {
#else
				  nulls())) {
#endif
         debug_printf("invalid\n");
         pc += 1;
      }

      /*
       * Output the bytes in hexidecimal format.
       */

      if (0) {
         unsigned i;
         for (i = 0; i < Size; ++i) {
            debug_printf("%02x ", ((const uint8_t*)bytes)[pc + i]);
         }
         for (; i < 16; ++i) {
            debug_printf("   ");
         }
      }

      /*
       * Print the instruction.
       */

#if HAVE_LLVM >= 0x0300
      Printer->printInst(&Inst, Out, "");
#elif HAVE_LLVM >= 0x208
      Printer->printInst(&Inst, Out);
#else
      Printer->printInst(&Inst);
#endif
      Out.flush();

      /*
       * Advance.
       */

      pc += Size;

#if HAVE_LLVM >= 0x0300
      const MCInstrDesc &TID = TII->get(Inst.getOpcode());
#else
      const TargetInstrDesc &TID = TII->get(Inst.getOpcode());
#endif

      /*
       * Keep track of forward jumps to a nearby address.
       */

      if (TID.isBranch()) {
         for (unsigned i = 0; i < Inst.getNumOperands(); ++i) {
            const MCOperand &operand = Inst.getOperand(i);
            if (operand.isImm()) {
               uint64_t jump;

               /*
                * FIXME: Handle both relative and absolute addresses correctly.
                * EDInstInfo actually has this info, but operandTypes and
                * operandFlags enums are not exposed in the public interface.
                */

               if (1) {
                  /*
                   * PC relative addr.
                   */

                  jump = pc + operand.getImm();
               } else {
                  /*
                   * Absolute addr.
                   */

                  jump = (uint64_t)operand.getImm();
               }

               /*
                * Output the address relative to the function start, given
                * that MC will print the addresses relative the current pc.
                */
               debug_printf("\t\t; %lu", (unsigned long)jump);

               /*
                * Ignore far jumps given it could be actually a tail return to
                * a random address.
                */

               if (jump > max_pc &&
                   jump < extent) {
                  max_pc = jump;
               }
            }
         }
      }

      debug_printf("\n");

      /*
       * Stop disassembling on return statements, if there is no record of a
       * jump to a successive address.
       */

      if (TID.isReturn()) {
         if (pc > max_pc) {
            break;
         }
      }
   }

   /*
    * Print GDB command, useful to verify output.
    */

   if (0) {
      debug_printf("disassemble %p %p\n", bytes, bytes + pc);
   }

   debug_printf("\n");
#else /* HAVE_LLVM < 0x0207 */
   (void)func;
#endif /* HAVE_LLVM < 0x0207 */
}

<|endoftext|>


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

#ifndef _UCBHELPER_INTERCEPTEDINTERACTION_HXX_
#define _UCBHELPER_INTERCEPTEDINTERACTION_HXX_

//_______________________________________________
// includes

#include <vector>

#ifndef __COM_SUN_STAR_TASK_XINTERACTIONHANDLER_HPP__
#include <com/sun/star/task/XInteractionHandler.hpp>
#endif

#ifndef __COM_SUN_STAR_TASK_XINTERACTIONREQUEST_HPP__
#include <com/sun/star/task/XInteractionRequest.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif
#ifndef INCLUDED_UCBHELPERDLLAPI_H
#include "ucbhelper/ucbhelperdllapi.h"
#endif

//_______________________________________________
// namespace

namespace ucbhelper{

//_______________________________________________
// definitions

/** @short  it wraps any other interaction handler and intercept
            its handle() requests.

    @descr  This class can be used as:
            - instance if special interactions must be supressed
              only
            - or as base class if interactions must be modified.
 */
class UCBHELPER_DLLPUBLIC InterceptedInteraction : public ::cppu::WeakImplHelper1< ::com::sun::star::task::XInteractionHandler >
{
    //-------------------------------------------
    // types
    public:

        struct InterceptedRequest
        {
            //-----------------------------------
            /** @short  marks an Handle as invalid.
             */
            static const sal_Int32 INVALID_HANDLE = -1;

            //-----------------------------------
            /** @short  contains the interaction request, which should be intercepted. */
            ::com::sun::star::uno::Any Request;

            //-----------------------------------
            /** @short  specify the fix continuation, which must be selected, if the
                        interaction could be intercepted successfully.
              */
            ::com::sun::star::uno::Type Continuation;

            //-----------------------------------
            /** @short  specify, if both interactions must have the same type
                        or can be derived from.

                @descr  Interaction base on exceptions - and exceptions are real types.
                        So they can be checked in its type. These parameter "MatchExact"
                        influence the type-check in the following way:
                            TRUE  => the exception will be intercepted only
                                     if it supports exactly the same type ...
                                     or
                            FALSE => derived exceptions will be intercepted too.

                @attention  This parameter does not influence the check of the continuation
                            type! The continuation must be matched exactly everytimes ...
             */
            sal_Bool MatchExact;

            //-----------------------------------
            /** @short  its an unique identifier, which must be managed by the outside code.

                @descr  If there is a derived class, which overwrites the InterceptedInteraction::intercepted()
                        method, it will be called with a reference to an InterceptedRequest struct.
                        Then it can use the handle to react without checking the request type again.
             */
            sal_Int32 Handle;

            //-----------------------------------
            /** @short  default ctor.

                @descr  Such constructed object cant be used realy.
                        Might it will crash if its used!
                        Dont forget to initialize all(!) members ...
             */
            InterceptedRequest()
            {
                MatchExact = sal_False;
                Handle     = INVALID_HANDLE;
            }

            //-----------------------------------
            /** @short  initialize this instance.

                @param  nHandle
                        used to identify every intercepted request

                @param  aRequest
                        must contain an exception object, which can be checked
                        in its uno-type against the later handled interaction.

                @param  aContinuation
                        must contain a continuation object, which is used
                        in its uno-type to locate the same continuation
                        inside the list of possible ones.

                @param  bMatchExact
                        influence the type check of the interception request.
                        Its not used to check the continuation!
             */
            InterceptedRequest(      sal_Int32                    nHandle      ,
                               const ::com::sun::star::uno::Any&  aRequest     ,
                               const ::com::sun::star::uno::Type& aContinuation,
                                     sal_Bool                     bMatchExact  )
            {
                Handle       = nHandle;
                Request      = aRequest;
                Continuation = aContinuation;
                MatchExact   = bMatchExact;
            }
        };

        //---------------------------------------
        /** @short  represent the different states, which can occure
                    as result of an interception.

            @see    impl_interceptRequest()
         */
        enum EInterceptionState
        {
            /** none of the specified interceptions match the incoming request */
            E_NOT_INTERCEPTED,
            /** the request could be intercepted - but the specified continuation could not be located.
                Thats normaly an error of the programmer. May be the interaction request does not use
                the right set of continuations ... or the interception list contains the wrong continuation. */
            E_NO_CONTINUATION_FOUND,
            /** the request could be intercepted and the specified continuation could be selected successfully. */
            E_INTERCEPTED
        };

    //-------------------------------------------
    // member
    protected:

        //---------------------------------------
        /** @short  reference to the intercepted interaction handler.

            @descr  NULL is allowed for this member!
                    All interaction will be aborted then ...
                    expecting th handle() was overwritten by
                    a derived class.
         */
        ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > m_xInterceptedHandler;

        //---------------------------------------
        /** @short  these list contains the requests, which should be intercepted.
         */
        ::std::vector< InterceptedRequest > m_lInterceptions;

    //-------------------------------------------
    // native interface
    public:

        //---------------------------------------
        /** @short  initialize a new instance with default values.
         */
        InterceptedInteraction();

        //---------------------------------------
        /** @short  initialize a new instance with real values.

            @param  xInterceptedHandler
                    the outside interaction handler, which should
                    be intercepted here.

            @param  lInterceptions
                    the list of intercepted requests.
         */
        InterceptedInteraction(const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xInterceptedHandler,
                               const ::std::vector< InterceptedRequest >&                                             lInterceptions     );

        //---------------------------------------
        /** @short  initialize a new instance with the interaction handler,
                    which should be intercepted.

            @attention  If such interaction handler isnt set here,
                        all incoming requests will be aborted ...
                        if the right continuation is available!

            @param  xInterceptedHandler
                    the outside interaction handler, which should
                    be intercepted here.
         */
        void setInterceptedHandler(const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xInterceptedHandler);

        //---------------------------------------
        /** @short  set a new list of intercepted interactions.

            @attention  If the interface method handle() will be overwritten by
                        a derived class, the functionality behind these static list
                        cant be used.

            @param  lInterceptions
                    the list of intercepted requests.
         */
        void setInterceptions(const ::std::vector< InterceptedRequest >& lInterceptions);

        //---------------------------------------
        /** @short  extract a requested continuation from te list of available ones.

            @param  lContinuations
                    the list of available continuations.

            @param  aType
                    is used to locate the right continuation,
                    by checking its interface type.

            @return A valid reference to the continuation, if it could be located ...
                    or an empty reference otherwhise.
         */
        static ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionContinuation > extractContinuation(
                    const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionContinuation > >& lContinuations,
                    const ::com::sun::star::uno::Type&                                                                                aType         );

    //-------------------------------------------
    // useable for derived classes
    protected:

        //---------------------------------------
        /** @short  can be overwritten by a derived class to handle interceptions
                    outside.

            @descr  This base implementation checks, if the request could be intercepted
                    successfully. Then this method intercepted() is called.
                    The default implementation returns "NOT_INTERCEPTED" everytimes.
                    So the method impl_interceptRequest() uses the right continuation automaticly.

                    If this method was overwritten and something different "NO_INTERCEPTED"
                    is returned, the method impl_interceptRequest() will return immediatly with
                    the result, which is returned by this intercepted() method.
                    Then the continuations must be selected inside the intercepted() call!

            @param  rRequest
                    it points to the intercepted request (means the item of the
                    set interception list). e.g. its "Handle" member can be used
                    to identify it and react very easy, without the need to check the
                    type of the exception ...

            @param  xOrgRequest
                    points to the original interaction, which was intercepted.
                    It provides access to the exception and the list of possible
                    continuations.

            @return The result of this operation.
                    Note: If E_NOT_INTERCEPTED is returned the default handling of the base class
                    will be used automaticly for this request!
         */
        virtual EInterceptionState intercepted(const InterceptedRequest&                                                             rRequest   ,
                                               const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionRequest >& xOrgRequest);

    //-------------------------------------------
    // uno interface
    public:

        //---------------------------------------
        /** @short  implements the default handling of this class ....
                    or can be overwritten by any derived class.

            @descr  If no further class is derived from this one
                    -> the default implementation is used. Then the
                    internal list of requests is used to handle different
                    interactions automaticly.
                    (see impl_interceptRequest())

                    If this method was overwritten by a derived implementation
                    -> the new implementation has to do everything by itself.
                    Of course it can access all members/helpers and work with it.
                    But the default implementation isnt used automaticly then.

            @param  xRequest
                    the interaction request, which should be intercepted.
         */
        virtual void SAL_CALL handle(const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionRequest >& xRequest)
            throw(::com::sun::star::uno::RuntimeException);

    //-------------------------------------------
    // helper
    private:

        //---------------------------------------
        /** @short  implements the default handling:
                    - intercept or forward to internal handler.
         */
        UCBHELPER_DLLPRIVATE void impl_handleDefault(const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionRequest >& xRequest);

        //---------------------------------------
        /** @short  implements the interception of requests.

            @descr  The incoming request will be analyzed, if it match
                    any request of the m_lIntercepions list.
                    If an interception could be found, its continuation will be
                    searched and selected.

                    The method return the state of that operation.
                    But it doesnt call the intercepted and here set
                    interaction handler. That has to be done in the outside method.

            @param  xRequest
                    the interaction request, which should be intercepted.

            @return A identifier, which inidicates if the request was intercepted,
                    the continuation was found and selected ... or not.
         */
        UCBHELPER_DLLPRIVATE EInterceptionState impl_interceptRequest(const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionRequest >& xRequest);
};

} // namespace ucbhelper

#endif // _UCBHELPER_INTERCEPTEDINTERACTION_HXX_
<commit_msg>INTEGRATION: CWS ooo19126 (1.3.14); FILE MERGED 2005/09/05 13:13:45 rt 1.3.14.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: interceptedinteraction.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 16:28:57 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _UCBHELPER_INTERCEPTEDINTERACTION_HXX_
#define _UCBHELPER_INTERCEPTEDINTERACTION_HXX_

//_______________________________________________
// includes

#include <vector>

#ifndef __COM_SUN_STAR_TASK_XINTERACTIONHANDLER_HPP__
#include <com/sun/star/task/XInteractionHandler.hpp>
#endif

#ifndef __COM_SUN_STAR_TASK_XINTERACTIONREQUEST_HPP__
#include <com/sun/star/task/XInteractionRequest.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif
#ifndef INCLUDED_UCBHELPERDLLAPI_H
#include "ucbhelper/ucbhelperdllapi.h"
#endif

//_______________________________________________
// namespace

namespace ucbhelper{

//_______________________________________________
// definitions

/** @short  it wraps any other interaction handler and intercept
            its handle() requests.

    @descr  This class can be used as:
            - instance if special interactions must be supressed
              only
            - or as base class if interactions must be modified.
 */
class UCBHELPER_DLLPUBLIC InterceptedInteraction : public ::cppu::WeakImplHelper1< ::com::sun::star::task::XInteractionHandler >
{
    //-------------------------------------------
    // types
    public:

        struct InterceptedRequest
        {
            //-----------------------------------
            /** @short  marks an Handle as invalid.
             */
            static const sal_Int32 INVALID_HANDLE = -1;

            //-----------------------------------
            /** @short  contains the interaction request, which should be intercepted. */
            ::com::sun::star::uno::Any Request;

            //-----------------------------------
            /** @short  specify the fix continuation, which must be selected, if the
                        interaction could be intercepted successfully.
              */
            ::com::sun::star::uno::Type Continuation;

            //-----------------------------------
            /** @short  specify, if both interactions must have the same type
                        or can be derived from.

                @descr  Interaction base on exceptions - and exceptions are real types.
                        So they can be checked in its type. These parameter "MatchExact"
                        influence the type-check in the following way:
                            TRUE  => the exception will be intercepted only
                                     if it supports exactly the same type ...
                                     or
                            FALSE => derived exceptions will be intercepted too.

                @attention  This parameter does not influence the check of the continuation
                            type! The continuation must be matched exactly everytimes ...
             */
            sal_Bool MatchExact;

            //-----------------------------------
            /** @short  its an unique identifier, which must be managed by the outside code.

                @descr  If there is a derived class, which overwrites the InterceptedInteraction::intercepted()
                        method, it will be called with a reference to an InterceptedRequest struct.
                        Then it can use the handle to react without checking the request type again.
             */
            sal_Int32 Handle;

            //-----------------------------------
            /** @short  default ctor.

                @descr  Such constructed object cant be used realy.
                        Might it will crash if its used!
                        Dont forget to initialize all(!) members ...
             */
            InterceptedRequest()
            {
                MatchExact = sal_False;
                Handle     = INVALID_HANDLE;
            }

            //-----------------------------------
            /** @short  initialize this instance.

                @param  nHandle
                        used to identify every intercepted request

                @param  aRequest
                        must contain an exception object, which can be checked
                        in its uno-type against the later handled interaction.

                @param  aContinuation
                        must contain a continuation object, which is used
                        in its uno-type to locate the same continuation
                        inside the list of possible ones.

                @param  bMatchExact
                        influence the type check of the interception request.
                        Its not used to check the continuation!
             */
            InterceptedRequest(      sal_Int32                    nHandle      ,
                               const ::com::sun::star::uno::Any&  aRequest     ,
                               const ::com::sun::star::uno::Type& aContinuation,
                                     sal_Bool                     bMatchExact  )
            {
                Handle       = nHandle;
                Request      = aRequest;
                Continuation = aContinuation;
                MatchExact   = bMatchExact;
            }
        };

        //---------------------------------------
        /** @short  represent the different states, which can occure
                    as result of an interception.

            @see    impl_interceptRequest()
         */
        enum EInterceptionState
        {
            /** none of the specified interceptions match the incoming request */
            E_NOT_INTERCEPTED,
            /** the request could be intercepted - but the specified continuation could not be located.
                Thats normaly an error of the programmer. May be the interaction request does not use
                the right set of continuations ... or the interception list contains the wrong continuation. */
            E_NO_CONTINUATION_FOUND,
            /** the request could be intercepted and the specified continuation could be selected successfully. */
            E_INTERCEPTED
        };

    //-------------------------------------------
    // member
    protected:

        //---------------------------------------
        /** @short  reference to the intercepted interaction handler.

            @descr  NULL is allowed for this member!
                    All interaction will be aborted then ...
                    expecting th handle() was overwritten by
                    a derived class.
         */
        ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > m_xInterceptedHandler;

        //---------------------------------------
        /** @short  these list contains the requests, which should be intercepted.
         */
        ::std::vector< InterceptedRequest > m_lInterceptions;

    //-------------------------------------------
    // native interface
    public:

        //---------------------------------------
        /** @short  initialize a new instance with default values.
         */
        InterceptedInteraction();

        //---------------------------------------
        /** @short  initialize a new instance with real values.

            @param  xInterceptedHandler
                    the outside interaction handler, which should
                    be intercepted here.

            @param  lInterceptions
                    the list of intercepted requests.
         */
        InterceptedInteraction(const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xInterceptedHandler,
                               const ::std::vector< InterceptedRequest >&                                             lInterceptions     );

        //---------------------------------------
        /** @short  initialize a new instance with the interaction handler,
                    which should be intercepted.

            @attention  If such interaction handler isnt set here,
                        all incoming requests will be aborted ...
                        if the right continuation is available!

            @param  xInterceptedHandler
                    the outside interaction handler, which should
                    be intercepted here.
         */
        void setInterceptedHandler(const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xInterceptedHandler);

        //---------------------------------------
        /** @short  set a new list of intercepted interactions.

            @attention  If the interface method handle() will be overwritten by
                        a derived class, the functionality behind these static list
                        cant be used.

            @param  lInterceptions
                    the list of intercepted requests.
         */
        void setInterceptions(const ::std::vector< InterceptedRequest >& lInterceptions);

        //---------------------------------------
        /** @short  extract a requested continuation from te list of available ones.

            @param  lContinuations
                    the list of available continuations.

            @param  aType
                    is used to locate the right continuation,
                    by checking its interface type.

            @return A valid reference to the continuation, if it could be located ...
                    or an empty reference otherwhise.
         */
        static ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionContinuation > extractContinuation(
                    const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionContinuation > >& lContinuations,
                    const ::com::sun::star::uno::Type&                                                                                aType         );

    //-------------------------------------------
    // useable for derived classes
    protected:

        //---------------------------------------
        /** @short  can be overwritten by a derived class to handle interceptions
                    outside.

            @descr  This base implementation checks, if the request could be intercepted
                    successfully. Then this method intercepted() is called.
                    The default implementation returns "NOT_INTERCEPTED" everytimes.
                    So the method impl_interceptRequest() uses the right continuation automaticly.

                    If this method was overwritten and something different "NO_INTERCEPTED"
                    is returned, the method impl_interceptRequest() will return immediatly with
                    the result, which is returned by this intercepted() method.
                    Then the continuations must be selected inside the intercepted() call!

            @param  rRequest
                    it points to the intercepted request (means the item of the
                    set interception list). e.g. its "Handle" member can be used
                    to identify it and react very easy, without the need to check the
                    type of the exception ...

            @param  xOrgRequest
                    points to the original interaction, which was intercepted.
                    It provides access to the exception and the list of possible
                    continuations.

            @return The result of this operation.
                    Note: If E_NOT_INTERCEPTED is returned the default handling of the base class
                    will be used automaticly for this request!
         */
        virtual EInterceptionState intercepted(const InterceptedRequest&                                                             rRequest   ,
                                               const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionRequest >& xOrgRequest);

    //-------------------------------------------
    // uno interface
    public:

        //---------------------------------------
        /** @short  implements the default handling of this class ....
                    or can be overwritten by any derived class.

            @descr  If no further class is derived from this one
                    -> the default implementation is used. Then the
                    internal list of requests is used to handle different
                    interactions automaticly.
                    (see impl_interceptRequest())

                    If this method was overwritten by a derived implementation
                    -> the new implementation has to do everything by itself.
                    Of course it can access all members/helpers and work with it.
                    But the default implementation isnt used automaticly then.

            @param  xRequest
                    the interaction request, which should be intercepted.
         */
        virtual void SAL_CALL handle(const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionRequest >& xRequest)
            throw(::com::sun::star::uno::RuntimeException);

    //-------------------------------------------
    // helper
    private:

        //---------------------------------------
        /** @short  implements the default handling:
                    - intercept or forward to internal handler.
         */
        UCBHELPER_DLLPRIVATE void impl_handleDefault(const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionRequest >& xRequest);

        //---------------------------------------
        /** @short  implements the interception of requests.

            @descr  The incoming request will be analyzed, if it match
                    any request of the m_lIntercepions list.
                    If an interception could be found, its continuation will be
                    searched and selected.

                    The method return the state of that operation.
                    But it doesnt call the intercepted and here set
                    interaction handler. That has to be done in the outside method.

            @param  xRequest
                    the interaction request, which should be intercepted.

            @return A identifier, which inidicates if the request was intercepted,
                    the continuation was found and selected ... or not.
         */
        UCBHELPER_DLLPRIVATE EInterceptionState impl_interceptRequest(const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionRequest >& xRequest);
};

} // namespace ucbhelper

#endif // _UCBHELPER_INTERCEPTEDINTERACTION_HXX_
<|endoftext|>


<commit_before>#define THRUST_DEBUG 1

#include "lcp/ChLcpVariablesGeneric.h"
#include "lcp/ChLcpVariablesBody.h"
#include "lcp/ChLcpConstraintTwoGeneric.h"
#include "lcp/ChLcpSystemDescriptor.h"
#include "lcp/ChLcpIterativeSOR.h"
#include "lcp/ChLcpIterativePMINRES.h"
#include "lcp/ChLcpIterativeBB.h"
#include "lcp/ChLcpSimplexSolver.h"
#include "core/ChLinearAlgebra.h"
#include "physics/ChSystemOpenMP.h"
#include "assets/ChSphereShape.h"
#include "physics/ChApidll.h"
#include "physics/ChSystem.h"
#include "lcp/ChLcpIterativeMINRES.h"
#include "core/ChRealtimeStep.h"
#include "lcp/ChLcpIterativeSOR.h"
#include "lcp/ChLcpIterativeJacobi.h"
#include "collision/ChCModelBullet.h"
#include "collision/ChCCollisionSystemBullet.h"
#include "physics/ChContactContainer.h"
// #include "unit_OPENGL/ChOpenGL.h"
#include "unit_POSTPROCESS/ChMitsubaRender.h"

#include "unit_GPU/ChSystemGPU.h"

// Remember to use the namespace 'chrono' because all classes
// of Chrono::Engine belong to this namespace and its children...

using namespace chrono;
using namespace postprocess;
//#define CHBODYSHAREDPTR ChSharedBodyPtr
//#define CHBODY ChBody
//#define CHCOLLISIONSYS ChCollisionSystemBullet
//#define CHLCPDESC ChLcpSystemDescriptor
//#define CHCONTACTCONT ChContactContainer
//#define CHSOLVER ChLcpIterativeJacobi
//#define CHMODEL ChModelBullet
//#define CHSYS ChSystem
#define CHBODYSHAREDPTR ChSharedBodyGPUPtr
#define CHBODY ChBodyGPU
#define CHCOLLISIONSYS ChCollisionSystemGPU
#define CHLCPDESC ChLcpSystemDescriptorGPU
#define CHCONTACTCONT ChContactContainerGPUsimple
#define CHSOLVER ChLcpIterativeJacobi
#define CHMODEL ChModelGPU
#define CHSYS ChSystemGPU
uint num_objects=0;
void dump_matricies(ChLcpSystemDescriptor& mdescriptor) {
	chrono::ChSparseMatrix mdM;
	chrono::ChSparseMatrix mdCq;
	chrono::ChSparseMatrix mdE;
	chrono::ChMatrixDynamic<double> mdf;
	chrono::ChMatrixDynamic<double> mdb;
	chrono::ChMatrixDynamic<double> mdfric;
	mdescriptor.ConvertToMatrixForm(&mdCq, &mdM, &mdE, &mdf, &mdb, &mdfric);
	chrono::ChStreamOutAsciiFile file_M("dump_M.dat");
	mdM.StreamOUTsparseMatlabFormat(file_M);
	chrono::ChStreamOutAsciiFile file_Cq("dump_Cq.dat");
	mdCq.StreamOUTsparseMatlabFormat(file_Cq);
	chrono::ChStreamOutAsciiFile file_E("dump_E.dat");
	mdE.StreamOUTsparseMatlabFormat(file_E);
	chrono::ChStreamOutAsciiFile file_f("dump_f.dat");
	mdf.StreamOUTdenseMatlabFormat(file_f);
	chrono::ChStreamOutAsciiFile file_b("dump_b.dat");
	mdb.StreamOUTdenseMatlabFormat(file_b);
	chrono::ChStreamOutAsciiFile file_fric("dump_fric.dat");
	mdfric.StreamOUTdenseMatlabFormat(file_fric);
}
template<class T>
void RunTimeStep(T* mSys, const int frame){
	Vector lpos(0, 0, 0);
	ChQuaternion<> quat(1, 0, 0, 0);
	CHBODYSHAREDPTR sphere;

    if(frame%10==0){
    for (int i = 0; i < 10; i++) {
		sphere = CHBODYSHAREDPTR(new CHBODY);
        Vector pos=Vector((rand() % 10000 / 1000.0 - 5), (10), (rand() % 10000 / 1000.0 - 5));
		InitObject(sphere, 1.0, pos*.5 , quat, 1, 1, 0, true, false, 32, 17+num_objects);
		AddCollisionGeometry(sphere, SPHERE, Vector(.3, .3, .3), lpos, quat);
		FinalizeObject(sphere, (CHSYS*) mSys);
		num_objects++;
	}
    }

}

int main(int argc, char* argv[]) {
	feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
	omp_set_num_threads(6);
    CHSYS* mSys = new CHSYS();
	CHLCPDESC *mdescriptor = new CHLCPDESC();
	CHCONTACTCONT *mcontactcontainer = new CHCONTACTCONT();
	CHCOLLISIONSYS *mcollisionengine = new CHCOLLISIONSYS();
	//ChLcpIterativeJacobi *msolver = new ChLcpIterativeJacobi();
	//ChLcpIterativeSOR *msolver = new ChLcpIterativeSOR();
	//ChLcpIterativeMINRES *msolver = new ChLcpIterativeMINRES();
	//ChLcpIterativePMINRES *msolver = new ChLcpIterativePMINRES();
	//ChLcpIterativeBB *msolver = new ChLcpIterativeBB();

	mSys->ChangeLcpSystemDescriptor(mdescriptor);
	mSys->ChangeContactContainer(mcontactcontainer);
	//mSys->ChangeLcpSolverSpeed(msolver);
	mSys->ChangeCollisionSystem(mcollisionengine);

	mSys->SetIntegrationType(ChSystem::INT_ANITESCU);
	mSys->Set_G_acc(Vector(0, -9.80665, 0));

	Vector lpos(0, 0, 0);
	ChQuaternion<> quat(1, 0, 0, 0);
//	ChSharedBodyPtr sphere;
//	for (int i = 0; i < 1000; i++) {
//		sphere = ChSharedBodyPtr(new ChBody);
//		InitObject(sphere, 1.0, Vector((rand() % 10000 / 1000.0 - 5), (rand() % 10000 / 1000.0 - 5), (rand() % 10000 / 1000.0 - 5)), quat, 1, 1, 0, true, false, 32, 17 + i);
//		AddCollisionGeometry(sphere, SPHERE, Vector(.3, .3, .3), lpos, quat);
//		FinalizeObject(sphere, mSys);
//	}

	float mWallMu = 1, container_width = 7.0, container_thickness = .5, container_height = 7.0, wscale = 1;
	CHBODYSHAREDPTR L = CHBODYSHAREDPTR(new CHBODY);
	CHBODYSHAREDPTR R = CHBODYSHAREDPTR(new CHBODY);
	CHBODYSHAREDPTR F = CHBODYSHAREDPTR(new CHBODY);
	CHBODYSHAREDPTR B = CHBODYSHAREDPTR(new CHBODY);
	CHBODYSHAREDPTR BTM = CHBODYSHAREDPTR(new CHBODY);

	InitObject(L, 100000, Vector(-container_width + container_thickness, 0, 0), quat, mWallMu, mWallMu, 0, true, true, -20, -20);
	InitObject(R, 100000, Vector(container_width - container_thickness, 0, 0), quat, mWallMu, mWallMu, 0, true, true, -20, -20);
	InitObject(F, 100000, Vector(0, 0, -container_width + container_thickness), quat, mWallMu, mWallMu, 0, true, true, -20, -20);
	InitObject(B, 100000, Vector(0, 0, container_width - container_thickness), quat, mWallMu, mWallMu, 0, true, true, -20, -20);
	InitObject(BTM, 100000, Vector(0, -container_height + container_thickness, 0), quat, mWallMu, mWallMu, 0, true, true, -20, -20);

	AddCollisionGeometry(L, BOX, Vector(container_thickness, container_height, container_width), lpos, quat);
	AddCollisionGeometry(R, BOX, Vector(container_thickness, container_height, container_width), lpos, quat);
	AddCollisionGeometry(F, BOX, Vector(container_width * wscale, container_height, container_thickness), lpos, quat);
	AddCollisionGeometry(B, BOX, Vector(container_width * wscale, container_height, container_thickness), lpos, quat);
	AddCollisionGeometry(BTM, BOX, Vector(container_width * wscale, container_thickness , container_width), lpos, quat);

	FinalizeObject(L, mSys);
	FinalizeObject(R, mSys);
	FinalizeObject(F, mSys);
	FinalizeObject(B, mSys);
	FinalizeObject(BTM, mSys);

	mSys->SetStep(0.01);
// 	ChOpenGLManager * window_manager = new ChOpenGLManager();
// 	ChOpenGL openGLView(window_manager, mSys, 800, 600, 0, 0, "Test_Solvers");
//     openGLView.SetCustomCallback(RunTimeStep);
// 	openGLView.StartSpinning(window_manager);
// 	window_manager->CallGlutMainLoop();
//
//	//msolver->Solve(*mdescriptor,true);
//	//dump_matricies(*mdescriptor);
//	//ChLcpIterativePMINRES msolver_krylov(20, false, 0.00001);
//	//msolver_krylov.Solve(mdescriptor);
//
//    ChMitsubaRender output(mSys);
//
//	output.SetIntegrator("photonmapper");
//	output.SetIntegratorOption("integer", "maxDepth", "32");
//	output.SetFilm("ldrfilm");
//	output.SetFilmOption("integer", "height", "1200");
//	output.SetFilmOption("integer", "width", "1920");
//
//	output.camera_target = ChVector<>(0, 0, 0);
//	output.camera_origin = ChVector<>(0, 0, -10);
//	output.camera_up = ChVector<>(0, 1, 0);
//
//	output.SetDataFolder("data");
//	output.ExportScript("test.xml");
//    output.SetRenderFolder("render");
//    output.ExportDriver("driver.sh");

    int counter=0;

    while(counter<1000){
        RunTimeStep(mSys, counter);
        mSys->DoStepDynamics(.01);

        stringstream ss;
		ss << "data/" << counter << ".xml";
		//output.ExportData(ss.str());

       cout<<counter<<endl;
        counter++;

    }

	return 0;
}

<commit_msg>Made stability changes to code<commit_after>#define THRUST_DEBUG 1

#include "lcp/ChLcpVariablesGeneric.h"
#include "lcp/ChLcpVariablesBody.h"
#include "lcp/ChLcpConstraintTwoGeneric.h"
#include "lcp/ChLcpSystemDescriptor.h"
#include "lcp/ChLcpIterativeSOR.h"
#include "lcp/ChLcpIterativePMINRES.h"
#include "lcp/ChLcpIterativeBB.h"
#include "lcp/ChLcpSimplexSolver.h"
#include "core/ChLinearAlgebra.h"
#include "physics/ChSystemOpenMP.h"
#include "assets/ChSphereShape.h"
#include "physics/ChApidll.h"
#include "physics/ChSystem.h"
#include "lcp/ChLcpIterativeMINRES.h"
#include "core/ChRealtimeStep.h"
#include "lcp/ChLcpIterativeSOR.h"
#include "lcp/ChLcpIterativeJacobi.h"
#include "collision/ChCModelBullet.h"
#include "collision/ChCCollisionSystemBullet.h"
#include "physics/ChContactContainer.h"
// #include "unit_OPENGL/ChOpenGL.h"
#include "unit_POSTPROCESS/ChMitsubaRender.h"

#include "unit_GPU/ChSystemGPU.h"

// Remember to use the namespace 'chrono' because all classes
// of Chrono::Engine belong to this namespace and its children...

using namespace chrono;
using namespace postprocess;
//#define CHBODYSHAREDPTR ChSharedBodyPtr
//#define CHBODY ChBody
//#define CHCOLLISIONSYS ChCollisionSystemBullet
//#define CHLCPDESC ChLcpSystemDescriptor
//#define CHCONTACTCONT ChContactContainer
//#define CHSOLVER ChLcpIterativeJacobi
//#define CHMODEL ChModelBullet
//#define CHSYS ChSystem
#define CHBODYSHAREDPTR ChSharedBodyGPUPtr
#define CHBODY ChBodyGPU
#define CHCOLLISIONSYS ChCollisionSystemGPU
#define CHLCPDESC ChLcpSystemDescriptorGPU
#define CHCONTACTCONT ChContactContainerGPUsimple
#define CHSOLVER ChLcpIterativeJacobi
#define CHMODEL ChModelGPU
#define CHSYS ChSystemGPU
uint num_objects=0;
void dump_matricies(ChLcpSystemDescriptor& mdescriptor) {
	chrono::ChSparseMatrix mdM;
	chrono::ChSparseMatrix mdCq;
	chrono::ChSparseMatrix mdE;
	chrono::ChMatrixDynamic<double> mdf;
	chrono::ChMatrixDynamic<double> mdb;
	chrono::ChMatrixDynamic<double> mdfric;
	mdescriptor.ConvertToMatrixForm(&mdCq, &mdM, &mdE, &mdf, &mdb, &mdfric);
	chrono::ChStreamOutAsciiFile file_M("dump_M.dat");
	mdM.StreamOUTsparseMatlabFormat(file_M);
	chrono::ChStreamOutAsciiFile file_Cq("dump_Cq.dat");
	mdCq.StreamOUTsparseMatlabFormat(file_Cq);
	chrono::ChStreamOutAsciiFile file_E("dump_E.dat");
	mdE.StreamOUTsparseMatlabFormat(file_E);
	chrono::ChStreamOutAsciiFile file_f("dump_f.dat");
	mdf.StreamOUTdenseMatlabFormat(file_f);
	chrono::ChStreamOutAsciiFile file_b("dump_b.dat");
	mdb.StreamOUTdenseMatlabFormat(file_b);
	chrono::ChStreamOutAsciiFile file_fric("dump_fric.dat");
	mdfric.StreamOUTdenseMatlabFormat(file_fric);
}
template<class T>
void RunTimeStep(T* mSys, const int frame){
	Vector lpos(0, 0, 0);
	ChQuaternion<> quat(1, 0, 0, 0);
	CHBODYSHAREDPTR sphere;

    if(frame%10==0){
    for (int i = 0; i < 10; i++) {
		sphere = CHBODYSHAREDPTR(new CHBODY);
        Vector pos=Vector((rand() % 10000 / 1000.0 - 5), (10), (rand() % 10000 / 1000.0 - 5));
		InitObject(sphere, 1.0, pos*.5 , quat, 1, 1, 0, true, false, 32, 17+num_objects);
		AddCollisionGeometry(sphere, SPHERE, Vector(.3, .3, .3), lpos, quat);
		FinalizeObject(sphere, (CHSYS*) mSys);
		num_objects++;
	}
    }

}

int main(int argc, char* argv[]) {
	feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
	omp_set_num_threads(6);
    CHSYS* mSys = new CHSYS();
	CHLCPDESC *mdescriptor = new CHLCPDESC();
	CHCONTACTCONT *mcontactcontainer = new CHCONTACTCONT();
	CHCOLLISIONSYS *mcollisionengine = new CHCOLLISIONSYS();
	//ChLcpIterativeJacobi *msolver = new ChLcpIterativeJacobi();
	//ChLcpIterativeSOR *msolver = new ChLcpIterativeSOR();
	//ChLcpIterativeMINRES *msolver = new ChLcpIterativeMINRES();
	//ChLcpIterativePMINRES *msolver = new ChLcpIterativePMINRES();
	//ChLcpIterativeBB *msolver = new ChLcpIterativeBB();

	mSys->ChangeLcpSystemDescriptor(mdescriptor);
	mSys->ChangeContactContainer(mcontactcontainer);
	//mSys->ChangeLcpSolverSpeed(msolver);
	mSys->ChangeCollisionSystem(mcollisionengine);

	mSys->SetIntegrationType(ChSystem::INT_ANITESCU);
	mSys->Set_G_acc(Vector(0, -9.80665, 0));

	Vector lpos(0, 0, 0);
	ChQuaternion<> quat(1, 0, 0, 0);
//	ChSharedBodyPtr sphere;
//	for (int i = 0; i < 1000; i++) {
//		sphere = ChSharedBodyPtr(new ChBody);
//		InitObject(sphere, 1.0, Vector((rand() % 10000 / 1000.0 - 5), (rand() % 10000 / 1000.0 - 5), (rand() % 10000 / 1000.0 - 5)), quat, 1, 1, 0, true, false, 32, 17 + i);
//		AddCollisionGeometry(sphere, SPHERE, Vector(.3, .3, .3), lpos, quat);
//		FinalizeObject(sphere, mSys);
//	}

	float mWallMu = 1, container_width = 7.0, container_thickness = .5, container_height = 7.0, wscale = 1;
	CHBODYSHAREDPTR L = CHBODYSHAREDPTR(new CHBODY);
	CHBODYSHAREDPTR R = CHBODYSHAREDPTR(new CHBODY);
	CHBODYSHAREDPTR F = CHBODYSHAREDPTR(new CHBODY);
	CHBODYSHAREDPTR B = CHBODYSHAREDPTR(new CHBODY);
	CHBODYSHAREDPTR BTM = CHBODYSHAREDPTR(new CHBODY);

	InitObject(L, 100000, Vector(-container_width + container_thickness, 0, 0), quat, mWallMu, mWallMu, 0, true, true, -20, -20);
	InitObject(R, 100000, Vector(container_width - container_thickness, 0, 0), quat, mWallMu, mWallMu, 0, true, true, -20, -20);
	InitObject(F, 100000, Vector(0, 0, -container_width + container_thickness), quat, mWallMu, mWallMu, 0, true, true, -20, -20);
	InitObject(B, 100000, Vector(0, 0, container_width - container_thickness), quat, mWallMu, mWallMu, 0, true, true, -20, -20);
	InitObject(BTM, 100000, Vector(0, -container_height + container_thickness, 0), quat, mWallMu, mWallMu, 0, true, true, -20, -20);

	AddCollisionGeometry(L, BOX, Vector(container_thickness, container_height, container_width), lpos, quat);
	AddCollisionGeometry(R, BOX, Vector(container_thickness, container_height, container_width), lpos, quat);
	AddCollisionGeometry(F, BOX, Vector(container_width * wscale, container_height, container_thickness), lpos, quat);
	AddCollisionGeometry(B, BOX, Vector(container_width * wscale, container_height, container_thickness), lpos, quat);
	AddCollisionGeometry(BTM, BOX, Vector(container_width * wscale, container_thickness , container_width), lpos, quat);

	FinalizeObject(L, mSys);
	FinalizeObject(R, mSys);
	FinalizeObject(F, mSys);
	FinalizeObject(B, mSys);
	FinalizeObject(BTM, mSys);

	mSys->SetStep(0.01);
// //	ChOpenGLManager * window_manager = new ChOpenGLManager();
// //	ChOpenGL openGLView(window_manager, mSys, 800, 600, 0, 0, "Test_Solvers");
// //    openGLView.SetCustomCallback(RunTimeStep);
// //	openGLView.StartSpinning(window_manager);
// //	window_manager->CallGlutMainLoop();
//
//	//msolver->Solve(*mdescriptor,true);
//	//dump_matricies(*mdescriptor);
//	//ChLcpIterativePMINRES msolver_krylov(20, false, 0.00001);
//	//msolver_krylov.Solve(mdescriptor);
//
//    ChMitsubaRender output(mSys);
//
//	output.SetIntegrator("photonmapper");
//	output.SetIntegratorOption("integer", "maxDepth", "32");
//	output.SetFilm("ldrfilm");
//	output.SetFilmOption("integer", "height", "1200");
//	output.SetFilmOption("integer", "width", "1920");
//
//	output.camera_target = ChVector<>(0, 0, 0);
//	output.camera_origin = ChVector<>(0, 0, -10);
//	output.camera_up = ChVector<>(0, 1, 0);
//
//	output.SetDataFolder("data");
//	output.ExportScript("test.xml");
//    output.SetRenderFolder("render");
//    output.ExportDriver("driver.sh");

    int counter=0;

    while(counter<1000){
        RunTimeStep(mSys, counter);
        mSys->DoStepDynamics(.01);

        stringstream ss;
		ss << "data/" << counter << ".xml";
		//output.ExportData(ss.str());

       cout<<counter<<endl;
        counter++;

    }

	return 0;
}

<|endoftext|>


<commit_before>
#include <togo/core/error/assert.hpp>
#include <togo/core/utility/utility.hpp>
#include <togo/core/log/log.hpp>
#include <togo/core/collection/array.hpp>
#include <togo/core/string/string.hpp>
#include <togo/core/io/memory_stream.hpp>

#include <quanta/core/object/object.hpp>

#include <togo/support/test.hpp>

#include <cmath>

using namespace quanta;

#define TSN(d) {true, d, {}},
#define TSE(d, e) {true, d, e},
#define TF(d) {false, d, {}},

struct Test {
	bool success;
	StringRef data;
	StringRef expected_output;
} const tests[]{
// whitespace
	TSN("")
	TSN(" ")
	TSN("\n")
	TSN(" \t\n")

// comments
	TF("/")
	TF("/*")
	TSN("//")
	TSN("/**/")
	TSN("/*\nblah\n*/")

// constants
	TSE("null", "null")
	TSE("false", "false")
	TSE("true", "true")

// identifiers
	TSE("a", "a")
	TSE("á", "á")
	TSE(".á", ".á")
	TSE("_", "_")
	TSE("a\nb", "a\nb")

// markers
	TSE("~", "~")
	TSE("~x", "~x")
	TSE("~~x", "~~x")
	TSE("~~~x", "~~~x")

	TSE("^", "^")
	TSE("^x", "^x")
	TSE("^^x", "^^x")
	TSE("^^^x", "^^^x")

	TSE("G~~x", "G~~x")
	TSE(" G~x",  "G~x")
	TSE("G~^x", "G~^x")

	TSE("?",  "?")
	TSE("?~x", "?~x")
	TSE(" ?x",  "?x")
	TSE("?^x", "?^x")

// source
	TSE("x$0", "x")
	TSE("x$0$0", "x")
	TSE("x$0$1", "x")
	TSE("x$0$?", "x")

	TSE("x$1", "x$1")
	TSE("x$1$0", "x$1")
	TSE("x$1$?", "x$1$?")
	TSE("x$1$2", "x$1$2")

	TSE("x$?1", "x$?1")
	TSE("x$?1$0", "x$?1")
	TSE("x$?1$?", "x$?1$?")
	TSE("x$?1$2", "x$?1$2")

	TSE("x$?$?", "x$?$?")

// numerics
	TSE(" 1",  "1")
	TSE("+1",  "1")
	TSE("-1", "-1")

	// . is actually a valid identifier lead here, so this is not true
	// TSE(" .1", "0.1")
	TSE("+.1",  "0.1")
	TSE("-.1", "-0.1")

	TSE(" 1.1",  "1.1")
	TSE("+1.1",  "1.1")
	TSE("-1.1", "-1.1")

	TSE(" 1.1e1",  "11")
	TSE("+1.1e1",  "11")
	TSE("-1.1e1", "-11")

	TSE(" 1.1e+1",  "11")
	TSE("+1.1e+1",  "11")
	TSE("-1.1e+1", "-11")

	TSE(" 1.1e-1",  "0.11")
	TSE("+1.1e-1",  "0.11")
	TSE("-1.1e-1", "-0.11")

// units
	TSE("1a", "1a")
	TSE("1µg", "1µg")

// strings
	TSE("\"\"", "\"\"")
	TSE("\"a\"", "a")
	TSE("``````", "\"\"")
	TSE("```a```", "a")

	TSE("\"\\t\"", "\"\t\"")
	TSE("\"\\n\"", "```\n```")

// names
	TF("=")
	TF("a=")
	TF("=,")
	TF("=;")
	TF("=\n")
	TSE("a=1", "a = 1")
	TSE("a=b", "a = b")
	TSE("a = 1", "a = 1")
	TSE("a = b", "a = b")

	TSE("a=\"\"", "a = \"\"")
	TSE("a=\"ab\"", "a = ab")
	TSE("a=\"a b\"", "a = \"a b\"")
	TF("a=\"\n")

	TSE("a=```ab```", "a = ab")
	TSE("a=```a b```", "a = \"a b\"")
	TSE("a=```a\nb```", "a = ```a\nb```")

// tags
	TF(":")
	TF("::")
	TF(":,")
	TF(":;")
	TF(":\n")
	TF(":\"a\"")
	TF(":```a```")
	TF(":1")
	TSE(":x", ":x")
	TF(":x:")
	TF(":x=")
	TF("x=:")
	TSE("x:y", "x:y")
	TSE(":x:y", ":x:y")

	TSE(":?x", ":?x")
	TSE(":G~x", ":G~x")

	TSE(":~x", ":~x")
	TSE(":~~x", ":~~x")
	TSE(":~~~x", ":~~~x")

	TSE(":^x", ":^x")
	TSE(":^^x", ":^^x")
	TSE(":^^^x", ":^^^x")

	TSE(":?~x", ":?~x")
	TSE(":?~~x", ":?~~x")
	TSE(":?~~~x", ":?~~~x")

	TSE(":?^x", ":?^x")
	TSE(":?^^x", ":?^^x")
	TSE(":?^^^x", ":?^^^x")

	TSE(":G~~x", ":G~~x")
	TSE(":G~~~x", ":G~~~x")
	TSE(":G~~~~x", ":G~~~~x")

	TSE(":G~^x", ":G~^x")
	TSE(":G~^^x", ":G~^^x")
	TSE(":G~^^^x", ":G~^^^x")

	TF(":x(")
	TSE(":x()", ":x")
	TSE(":x( )", ":x")
	TSE(":x(\t)", ":x")
	TSE(":x(\n)", ":x")
	TSE(":x(1)", ":x(1)")
	TSE(":x(y)", ":x(y)")
	TSE(":x(y,z)", ":x(y, z)")
	TSE(":x(y;z)", ":x(y, z)")
	TSE(":x(y\nz)", ":x(y, z)")

// scopes
	TF("{")
	TF("(")
	TF("[")
	TSE("{}", "null")
	TSE("{{}}", "{\n\tnull\n}")
	TSE("x{}", "x")
	TSE("x[]", "x")
	TSE("x[1]", "x[1]")
	TSE("x[y]", "x[y]")
};

void check(Test const& test) {
	TOGO_LOGF(
		"reading (%3u): <%.*s>\n",
		test.data.size, test.data.size, test.data.data
	);
	Object root;
	MemoryReader in_stream{test.data};
	ObjectParserInfo pinfo;
	if (object::read_text(root, in_stream, pinfo)) {
		MemoryStream out_stream{memory::default_allocator(), test.expected_output.size + 1};
		TOGO_ASSERTE(object::write_text(root, out_stream));
		StringRef output{
			reinterpret_cast<char*>(array::begin(out_stream.data())),
			static_cast<unsigned>(out_stream.size())
		};
		// Remove trailing newline
		if (output.size > 0) {
			--output.size;
		}
		TOGO_LOGF(
			"rewritten (%3u): <%.*s>\n",
			output.size, output.size, output.data
		);
		TOGO_ASSERT(test.success, "read succeeded when it should have failed");
		TOGO_ASSERT(
			string::compare_equal(test.expected_output, output),
			"output does not match"
		);
	} else {
		TOGO_LOGF(
			"failed to read%s: [%2u,%2u]: %s\n",
			test.success ? " (UNEXPECTED)" : "",
			pinfo.line,
			pinfo.column,
			pinfo.message
		);
		TOGO_ASSERT(!test.success, "read failed when it should have succeeded");
	}
	TOGO_LOG("\n");
}

signed main() {
	memory_init();

	for (auto& test : tests) {
		check(test);
	}
	return 0;
}
<commit_msg>lib/core/test/object/io_text: added tests for nested comment blocks; tidy.<commit_after>
#include <togo/core/error/assert.hpp>
#include <togo/core/utility/utility.hpp>
#include <togo/core/log/log.hpp>
#include <togo/core/collection/array.hpp>
#include <togo/core/string/string.hpp>
#include <togo/core/io/memory_stream.hpp>

#include <quanta/core/object/object.hpp>

#include <togo/support/test.hpp>

#include <cmath>

using namespace quanta;

#define TSN(d) {true, d, {}},
#define TSE(d, e) {true, d, e},
#define TF(d) {false, d, {}},

struct Test {
	bool success;
	StringRef data;
	StringRef expected_output;
} const tests[]{
// whitespace
	TSN("")
	TSN(" ")
	TSN("\n")
	TSN(" \t\n")

// comments
	TF("\\")
	TF("\\*")
	TSN("\\\\")
	TSN("\\**\\")
	TSN("\\*\nblah\n*\\")

	// nested
	TF("\\* \\* *\\")
	TSN("\\* \\**\\ *\\")

// constants
	TSE("null", "null")
	TSE("false", "false")
	TSE("true", "true")

// identifiers
	TSE("a", "a")
	TSE("á", "á")
	TSE(".á", ".á")
	TSE("_", "_")
	TSE("a\nb", "a\nb")

// markers
	TSE("~", "~")
	TSE("~x", "~x")
	TSE("~~x", "~~x")
	TSE("~~~x", "~~~x")

	TSE("^", "^")
	TSE("^x", "^x")
	TSE("^^x", "^^x")
	TSE("^^^x", "^^^x")

	TSE("G~~x", "G~~x")
	TSE(" G~x",  "G~x")
	TSE("G~^x", "G~^x")

	TSE("?",  "?")
	TSE("?~x", "?~x")
	TSE(" ?x",  "?x")
	TSE("?^x", "?^x")

// source
	TSE("x$0", "x")
	TSE("x$0$0", "x")
	TSE("x$0$1", "x")
	TSE("x$0$?", "x")

	TSE("x$1", "x$1")
	TSE("x$1$0", "x$1")
	TSE("x$1$?", "x$1$?")
	TSE("x$1$2", "x$1$2")

	TSE("x$?1", "x$?1")
	TSE("x$?1$0", "x$?1")
	TSE("x$?1$?", "x$?1$?")
	TSE("x$?1$2", "x$?1$2")

	TSE("x$?$?", "x$?$?")

// integer & decimal
	TSE(" 1",  "1")
	TSE("+1",  "1")
	TSE("-1", "-1")

	TSE("+.1",  "0.1")
	TSE("-.1", "-0.1")

	TSE(" 1.1",  "1.1")
	TSE("+1.1",  "1.1")
	TSE("-1.1", "-1.1")

	TSE(" 1.1e1",  "11")
	TSE("+1.1e1",  "11")
	TSE("-1.1e1", "-11")

	TSE(" 1.1e+1",  "11")
	TSE("+1.1e+1",  "11")
	TSE("-1.1e+1", "-11")

	TSE(" 1.1e-1",  "0.11")
	TSE("+1.1e-1",  "0.11")
	TSE("-1.1e-1", "-0.11")

// units
	TSE("1a", "1a")
	TSE("1µg", "1µg")

// strings
	TSE("\"\"", "\"\"")
	TSE("\"a\"", "a")
	TSE("``````", "\"\"")
	TSE("```a```", "a")

	TSE("\"\\t\"", "\"\t\"")
	TSE("\"\\n\"", "```\n```")

// names
	TF("=")
	TF("a=")
	TF("=,")
	TF("=;")
	TF("=\n")
	TSE("a=1", "a = 1")
	TSE("a=b", "a = b")
	TSE("a = 1", "a = 1")
	TSE("a = b", "a = b")

	TSE("a=\"\"", "a = \"\"")
	TSE("a=\"ab\"", "a = ab")
	TSE("a=\"a b\"", "a = \"a b\"")
	TF("a=\"\n")

	TSE("a=```ab```", "a = ab")
	TSE("a=```a b```", "a = \"a b\"")
	TSE("a=```a\nb```", "a = ```a\nb```")

// tags
	TF(":")
	TF("::")
	TF(":,")
	TF(":;")
	TF(":\n")
	TF(":\"a\"")
	TF(":```a```")
	TF(":1")
	TSE(":x", ":x")
	TF(":x:")
	TF(":x=")
	TF("x=:")
	TSE("x:y", "x:y")
	TSE(":x:y", ":x:y")

	TSE(":?x", ":?x")
	TSE(":G~x", ":G~x")

	TSE(":~x", ":~x")
	TSE(":~~x", ":~~x")
	TSE(":~~~x", ":~~~x")

	TSE(":^x", ":^x")
	TSE(":^^x", ":^^x")
	TSE(":^^^x", ":^^^x")

	TSE(":?~x", ":?~x")
	TSE(":?~~x", ":?~~x")
	TSE(":?~~~x", ":?~~~x")

	TSE(":?^x", ":?^x")
	TSE(":?^^x", ":?^^x")
	TSE(":?^^^x", ":?^^^x")

	TSE(":G~~x", ":G~~x")
	TSE(":G~~~x", ":G~~~x")
	TSE(":G~~~~x", ":G~~~~x")

	TSE(":G~^x", ":G~^x")
	TSE(":G~^^x", ":G~^^x")
	TSE(":G~^^^x", ":G~^^^x")

	TF(":x(")
	TSE(":x()", ":x")
	TSE(":x( )", ":x")
	TSE(":x(\t)", ":x")
	TSE(":x(\n)", ":x")
	TSE(":x(1)", ":x(1)")
	TSE(":x(y)", ":x(y)")
	TSE(":x(y,z)", ":x(y, z)")
	TSE(":x(y;z)", ":x(y, z)")
	TSE(":x(y\nz)", ":x(y, z)")

// scopes
	TF("{")
	TF("(")
	TF("[")
	TSE("{}", "null")
	TSE("{{}}", "{\n\tnull\n}")
	TSE("x{}", "x")
	TSE("x[]", "x")
	TSE("x[1]", "x[1]")
	TSE("x[y]", "x[y]")
};

void check(Test const& test) {
	TOGO_LOGF(
		"reading (%3u): <%.*s>\n",
		test.data.size, test.data.size, test.data.data
	);
	Object root;
	MemoryReader in_stream{test.data};
	ObjectParserInfo pinfo;
	if (object::read_text(root, in_stream, pinfo)) {
		MemoryStream out_stream{memory::default_allocator(), test.expected_output.size + 1};
		TOGO_ASSERTE(object::write_text(root, out_stream));
		StringRef output{
			reinterpret_cast<char*>(array::begin(out_stream.data())),
			static_cast<unsigned>(out_stream.size())
		};
		// Remove trailing newline
		if (output.size > 0) {
			--output.size;
		}
		TOGO_LOGF(
			"rewritten (%3u): <%.*s>\n",
			output.size, output.size, output.data
		);
		TOGO_ASSERT(test.success, "read succeeded when it should have failed");
		TOGO_ASSERT(
			string::compare_equal(test.expected_output, output),
			"output does not match"
		);
	} else {
		TOGO_LOGF(
			"failed to read%s: [%2u,%2u]: %s\n",
			test.success ? " (UNEXPECTED)" : "",
			pinfo.line,
			pinfo.column,
			pinfo.message
		);
		TOGO_ASSERT(!test.success, "read failed when it should have succeeded");
	}
	TOGO_LOG("\n");
}

signed main() {
	memory_init();

	for (auto& test : tests) {
		check(test);
	}
	return 0;
}
<|endoftext|>