/*
 *      Interactive disassembler (IDA).
 *      Copyright (c) 1990-99 by Ilfak Guilfanov, <ig@datarescue.com>
 *      ALL RIGHTS RESERVED.
 *
 */

#ifndef _UA_HPP
#define _UA_HPP
#pragma pack(push, 1)   // IDA uses 1 byte alignments!

//      This file contains functions that deal with the disassembling
//      of program instructions. There are 2 kinds of functions:
//              - functions that are called from the kernel
//                to disassemble an instruction. These functions
//                call IDP module for it.
//              - functions that are called from IDP module to
//                disassemble an instruction. We will call them
//                'helper functions'
//      Disassembly of an instruction is made in three steps:
//              A. analysis             ana.cpp
//              B. emulation            emu.cpp
//              C. convertion to text   out.cpp
//      The kernel calls IDP module to perform these steps.
//      At first, the kernel always calls analysis. The analyser
//      must decode the instruction and fill 'cmd' structure.
//      It has no rights to change anything in the database.
//      The second step, emulation, is called for each instruction.
//      This step must make nesessary changes to the database,
//      plan analysis of subsequent instructions, it may track register
//      values, memory contents, etc. However, the kernel may call the
//      emulation step for any address in the program, there is no
//      ordering of addresses. Usually, the emulation is called for
//      sequentally for subsequent addresses but this is not guaranteed.
//      The main goal of emulation step is to track down execution flow
//      and to plan conversion of nesessary bytes to instructions.
//      The last step, conversion to text, is called each time when
//      an instruction is displayed on the screen. The kernel will always
//      call the analysis step first (the analysis should be very fast)
//      and then will call conversion to text.
//      The emulation and conversion steps should use information stored
//      in 'cmd' structure. They should not access to bytes of instruction
//      and decode it again - this should be done in the analysis step.

#include <kernwin.hpp>  // for btoa()
#include <lines.hpp>    // for color_t
#include <xref.hpp>     // add_cref()
#include <llong.hpp>    // longlong

//--------------------------------------------------------------------------
//      T Y P E   O F   O P E R A N D
//--------------------------------------------------------------------------

// Type of an operand
// An operand of an instruction has a type. The kernel knows about
// some operand types and accordingly interprets some fields of op_t
// structure. The fields used by the kernel is shown below.
// There are some IDP specific types (o_idpspec?). You are free to
// give any meaning to these types. I suggest you to create a #define
// to use mnemonic names. However, don't forget that the kernel will
// know nothing about operands of those types.
// As about "data field", you may use any additional fields to store
// processor specific operand information

typedef uchar optype_t;
const optype_t     // Description                          Data field
  o_void     =  0, // No Operand                           ----------
  o_reg      =  1, // General Register (al,ax,es,ds...)    reg
  o_mem      =  2, // Direct Memory Reference  (DATA)      addr
  o_phrase   =  3, // Memory Ref [Base Reg + Index Reg]    phrase
  o_displ    =  4, // Memory Reg [Base Reg + Index Reg + Displacement] phrase+addr
  o_imm      =  5, // Immediate Value                      value
  o_far      =  6, // Immediate Far Address  (CODE)        addr
  o_near     =  7, // Immediate Near Address (CODE)        addr
  o_idpspec0 =  8, // IDP specific type
  o_idpspec1 =  9, // IDP specific type
  o_idpspec2 = 10, // IDP specific type
  o_idpspec3 = 11, // IDP specific type
  o_idpspec4 = 12, // IDP specific type
  o_idpspec5 = 13, // IDP specific type
  o_last     = 14; // first unused type

// How to assign the operand types
// -------------------------------
//
//o_reg    denotes a simple register, the register number should
//         be stored in x.reg. All processor registers, including special
//         registers, can be represented by this operand type
//o_mem    a direct memory data reference whose target address is known at the compliation time.
//         The target virtual address is stored in x.addr and the full address
//         is calculated as toEA(cmd.cs, x.addr). For the processors with
//         complex memory organization the final address can be calculated
//         using other segment registers. For flat memories, x.addr is the final
//         address and cmd.cs is usually equal to zero. In any case, the address
//         within the segment should be stored in x.addr.
//o_phrase a memory reference using register contents. indexed, register based,
//         and other addressing modes can be represented with the operand type.
//         This addressing mode can not contain immediate values (use o_displ for them)
//         The phrase number should be stored in x.phrase. To denote the preincrement
//         and similar features please use additional operand fields like specflags.
//         Usually x.phrase contains the register number and additional information
//         is stored in x.specflags. Please note that this operand type can not
//         contain immediate values (except the scaling coefficients)
//o_displ  a memory reference using register contents with displacement.
//         The displacement should be stored in the x.addr field. The rest of information
//         is stored the same way as in o_phrase.
//o_imm    an immediate value. Any operand consisting of only a number is represented
//         by this operand type. The value should be stored in x.value. You may sign
//         extend short (1-2 byte) values. In any case don't forget to specify x.dtyp
//         (x.dtyp should be set for all operand types)
//o_near   a direct memory code reference whose target address is known at the compliation time.
//         The target virtual address is stored in x.addr and the final address
//         is always toEA(cmd.cs, x.addr). Usually this operand type is used for
//         the branches and calls whose target address is known. If the current
//         processor has 2 different types of references for intersegment and intrasegment
//         references, then o_near should be used only for intrasegment references.
//o_far    If the current processor has a special addressing mode for intersegment
//         references, then this operand type should be used instead of o_near.
//         If you want, you may use PR_CHK_XREF in ph.flag to disable intersegment
//         calls if o_near operand type is used. Currently only IBM PC uses this flag.
//
//      If the above operand types do not cover all possible addressing modes,
//      then use o_idpspec operand types.

//--------------------------------------------------------------------------
//      O P E R A N D   O F   I N S T R U C T I O N
//--------------------------------------------------------------------------

// Operand of an instruction. This structure is filled by the analyser.
// Upon entrance to the analyser, some fields of this structure are initialized:
//      type    - o_void
//      offb    - 0
//      offo    - 0
//      flags   - OF_SHOW

class op_t
{
public:
// Number of operand. Initialized once at the start of work.
// You have no right to change its value.

  char          n;              // number of operand (0,1,2)


// Type of operand. See above for explanations

  optype_t      type;           // type of operand


// Offset of operand value from the instruction start.
// Of course this field is meaningful only for certain types of operands.
// Leave it equal to zero if the operand has no offset.
// This offset should point to the 'interesting' part of operand.
// For example, it may point to the address of a function in
//      call func
// or it may point to bytes holding '5' in
//      mov  ax, [bx+5]
// Usually bytes pointed to this offset are relocated (have fixup information)

  char          offb;           // offset of operand relative to instruction start
                                // 0 - unknown


// The same as above. Some operands have 2 numeric values used to
// form operand. 'offo' is used for the second part of operand if it exists.
// Currently this field is used only for outer offsets of Motorla processors.
// Leave it equal to zero if the operand has no offset

  char          offo;           // offset of operand relative to instruction start
                                // 0 - unknown


// Some characteristics of operand

  uchar         flags;
#define OF_NO_BASE_DISP 0x80    // o_displ: base displacement doesn't exist
                                // meaningful only for o_displ type
                                // if set, base displacement (x.addr)
                                // doesn't exist.
#define OF_OUTER_DISP   0x40    // o_displ: outer displacement exists
                                // meaningful only for o_displ type
                                // if set, outer displacement (x.value) exists.
#define PACK_FORM_DEF   0x20    // !o_reg + dt_packreal: packed factor defined
#define OF_NUMBER       0x10    // can be output as number only
                                // if set, the operand can be converted to a
                                // number only
#define OF_SHOW         0x08    // should the operand be displayed?
                                // if clear, the operand is hidden and should
                                // not be displayed


// Convenience functions:

  void set_showed()     { flags |=  OF_SHOW; }
  void clr_showed()     { flags &= ~OF_SHOW; }
  int  showed()         { return (flags & OF_SHOW) != 0; }


// Type of operand value. Usually first 9 types are used.
// This is the type of the operand itself, not the size of the addressing mode.
// for example, byte ptr [epb+32_bit_offset]  will have dt_byte type.

  char          dtyp;
// Отсюда...
#define dt_byte         0       // 8 bit
#define dt_word         1       // 16 bit
#define dt_dword        2       // 32 bit
#define dt_float        3       // 4 byte
#define dt_double       4       // 8 byte
#define dt_tbyte        5       // variable size (ph.tbyte_size)
#define dt_packreal     6       // packed real format for mc68040
// ...досюда порядок не менять! - mc68000
#define dt_qword        7       // 64 bit
#define dt_byte16       8       // 128 bit
#define dt_code         9       // ptr to code (not used?)
#define dt_void         10      // none
#define dt_fword        11      // 48 bit
#define dt_bitfild      12      // bit field (mc680x0)
#define dt_string       13      // pointer to asciiz string
#define dt_unicode      14      // pointer to unicode string


// The following unions keep other information about the operand

  union
  {
    ushort reg;                 // number of register (o_reg)
    ushort phrase;              // number of register phrase (o_phrase,o_displ)
                                // you yourself define numbers of phrases
                                // as you like
  };


//  следующие 12 байт используются в mc подряд при типе o_fpdat !


// VALUE

  union {
    ulong value;                // value of operand (o_imm)
                                // outer displacement (o_displ+OF_OUTER_DISP)

    struct {                    // this structure is defined for
        ushort low;             // your convenience only
        ushort high;
    } value_shorts;
  };


// VIRTUAL ADDRESS (OFFSET WITHIN THE SEGMENT)

  union {
    ulong  addr;                // virtual address pointed or used by the operand
                                // (o_mem,o_displ,o_far,o_near)

    struct {                    // this structure is defined for
        ushort low;             // your convenience only
        ushort high;
    } addr_shorts;
  };


// IDP SPECIFIC INFORMATION

  union {
    ulong specval;              // This field may be used as you want.
    struct {                    // this structure is defined for your convenience only
        ushort low;             // IBM PC: segment register number (o_mem,o_far,o_near)
        ushort high;            // IBM PC: segment selector value  (o_mem,o_far,o_near)
    } specval_shorts;
  };

// The following fields are used only in idp modules
// You may use them as you want to store additional information about
// the operand

  char          specflag1;
  char          specflag2;
  char          specflag3;
  char          specflag4;

};


//--------------------------------------------------------------------------
//      I N S T R U C T I O N
//--------------------------------------------------------------------------

// Structure to hold information about an instruction. This structure is
// filled by the analysis step of IDP and used by the emulation and
// conversion to text steps. The kernel uses this structure too.

class insn_t
{
public:
// Internal code of instruction. IDP should define its own instruction
// codes. These codes are usually defined in ins.hpp. Array of instruction
// names and features (ins.cpp) is accessed using this code.
// Initialized by the kernel to zero.

  ushort itype;                 // instruction code (see ins.hpp)


// Current segment base paragraph. Initialized by the kernel.

  ulong cs;                     // segment base (in paragraphs)


// Virtual address of the instruction (address within the segment)
// Initialized by the kernel.

  ulong ip;                     // offset in the segment


// Linear address of the instruction.
// Initialized by the kernel.

  ea_t ea;                      // instruction start addresses


// Size of instruction in bytes.
// Initialized by the kernel to zero. The analyser should put
// actual size of the instruction.

  ushort size;                  // instruction size in bytes


// Additinal information about the instruction.
// Initialized by the kernel to zero.
// You may use these field as you want.

  union {
    ushort auxpref;             // processor dependent field
    struct {
      uchar low;
      uchar high;
    } auxpref_chars;
  };
  char segpref;                 // processor dependent field


// Information about instruction operands.

#define UA_MAXOP        6
  op_t Operands[UA_MAXOP];
#define Op1 Operands[0]
#define Op2 Operands[1]
#define Op3 Operands[2]
#define Op4 Operands[3]
#define Op5 Operands[4]
#define Op6 Operands[5]

};


//--------------------------------------------------------------------------
//      V A L U E   O F   O P E R A N D
//--------------------------------------------------------------------------

// This structure is used to pass values of bytes to helper functions.

union value_u
{
  uchar v_char;
  ushort v_short;
  ulong v_long;
  struct dq_t { ulong low; ulong high; } dq;
  struct dt_t { ulong low; ulong high; ushort upper; } dt;
  uchar byte16[16];
  ulong dword3[3];
};


// Get immediate values used in the operand if it fits in 32bits.
//      ea - linear address
//      n  - number of operand:(0..UA_MAXOP-1) (-1 - all operands)
//      v  - array of immediate values (at least 2*UA_MAXOP elements)
// returns: number of immediate values (0..2*UA_MAXOP)

idaman int ida_export get_operand_immvals(ulong ea,int n,ulong *v);

//--------------------------------------------------------------------------
//      T H E   M A I N   S T R U C T U R E
//--------------------------------------------------------------------------

// Structure holding information about an instruction
// Analyser should fill this structure.

idaman insn_t ida_export_data cmd;      // current instruction


// Undocumented variable. It is not used by the kernel.
// Its value may be specified in IDA.CFG:
//      LOOKBACK = <number>
// IDP may use it as you like it.
// TMS module uses it as commented below.

idaman int ida_export_data lookback;    // number of instructions to look back


//--------------------------------------------------------------------------
//      I D P   H E L P E R   F U N C T I O N S  -  C O M M O N
//--------------------------------------------------------------------------

// Flags value for the byte at the start of the current instruction.
// (see bytes.hpp for explanation of flags)
// The kernel retrieves flags value and stores it in this variable for
// your convenience. Anytime you change the database by calling functions
// that change flags value you should refresh it using getFlags()

idaman flags_t ida_export_data uFlag;    // features flag


// The following functions return segment base linear addresses of
// the data or code segment for the current instruction.
// They use values of segment registers, operand types, etc.

idaman ea_t ida_export dataSeg_opreg(int opnum,int rgnum);
                                          // get data segment by operand
                                          // number and the specified
                                          // segment register number
                                          // meaningful only if the processor
                                          // has segment registers
idaman ea_t ida_export dataSeg_op(int opnum);    // get data segment by operand
                                          // number.
idaman ea_t ida_export dataSeg(void);            // get data segment regardless of
                                          // operand number
idaman ea_t ida_export codeSeg(ea_t addr,int opnum); // get code segment. this function
                                          // takes into account the segment
                                          // translations.
                                          // addr - the referenced address
                                          //        used by translations
                                          // opnum- operand number


//--------------------------------------------------------------------------
//      I D P   H E L P E R   F U N C T I O N S  -  A N A L Y S I S
//--------------------------------------------------------------------------

// The following three functions return next byte,2bytes and 4bytes of the
// instruction accordingly.
// They use and modify size of instruction field (cmd.size).
// Normally they are used in the analyser to get bytes of the instruction.
// ATTENTION: These functions work only for normal (8bit) byte processors!

idaman uchar  ida_export ua_next_byte(void);
idaman ushort ida_export ua_next_word(void);
idaman ulong  ida_export ua_next_long(void);


//--------------------------------------------------------------------------
//      I D P   H E L P E R   F U N C T I O N S  -  O U T P U T
//--------------------------------------------------------------------------

// All output functions use 'cmd' structure to get information.
// Almost all output functions use pointer to output string 'u_line'.
// You should initialize this pointer before using output functions

idaman ida_export_data char *u_line;   // Pointer into line being generated


// Output instruction mnemonics using information in 'cmd'
// This function outputs a colored text.
//      width   - width of field with mnemonics
//                if width < 0 then 'postfix' will be output before
//                             the mnemonics, i.e. as a prefix
//      postfix - optional postfix added to the instruction mnemonics
// This function will output at least one space after the instruction
// mnemonics even if the specified 'width' is not enough.

idaman int ida_export OutMnem(int width=8,const char *postfix=NULL);
                                        // output instruction mnemonics
                                        // width - width of mnemonics field
                                        // postfix may be NULL
                                        // returns 0-displayed as bytes
                                        // returns 1-displayed as instruction


// Output instruction as a sequence of bytes
// followed by a comment character and instruction mnemonics
// This function is used to display undocumented instructions or
// instructions that are improperly handled by the target assembler.
// OutMnem() calls this function if the current instruction is present
// in the array of bad instructions (ash.badworks)
// This function outputs a colored text.

idaman void ida_export OutBadInstruction(void);           // Display instruction as bytes


// Use this function to output an operand of an instruction
//      n - number of operand
// This function check for the existence of manually defined operand
// and will output manually defined operand if it exists.
// Otherwise it will call ph.outop() to output operand.
// This function outputs a colored text.
// returns: 1-operand is displayed
//          o-operand is hidden

idaman int ida_export out_one_operand(int n);  // should be used in IDP modules.
                                        // outs forced operand or calls outop()
                                        // returns 1 if something was output


// Output immediate value
// This function outputs a number from x.addr or x.value in the form
// determined by 'uFlag'.
// This function outputs a colored text.
// returns: flags of the output value
//      -1: value is output with COLOR_ERROR
//      0:  value is output as a number or character or segment
// Try to use this function to output all constants of instruction operands

idaman flags_t ida_export OutValue(op_t &x,int outflags=0);

// 'outflags' parameter is combination of the following bits:
// (don't use OOF_SIGNMASK and OOF_WIDTHMASK, they are for the kernel)

#define OOF_SIGNMASK    0x0003      // sign output:
#define   OOFS_IFSIGN   0x0000      //   output sign if needed
#define   OOFS_NOSIGN   0x0001      //   don't output sign, forbid the user to change the sign
#define   OOFS_NEEDSIGN 0x0002      //   always out sign         (+-)
#define OOF_SIGNED      0x0004      // output as signed if < 0
#define OOF_NUMBER      0x0008      // always as a number
#define OOF_WIDTHMASK   0x0030      // width of value in bits:
#define   OOFW_IMM      0x0000      //   take from x.dtyp
#define   OOFW_16       0x0010      //   16 bit width
#define   OOFW_32       0x0020      //   32 bit width
#define   OOFW_8        0x0030      //   8 bit width
#define OOF_ADDR        0x0040      // output x.addr, otherwise x.value
#define OOF_OUTER       0x0080      // output outer operand
#define OOF_ZSTROFF     0x0100      // meaningful only if isStroff(uFlag)
                                    // append a struct field name if
                                    // the field offset is zero?
                                    // if AFL_ZSTROFF is set, then this flag
                                    // is ignored.
#define OOF_NOBNOT      0x0200      // prohibit use of binary not


// Output a character with COLOR_SYMBOL color.

idaman void ida_export out_symbol(char c);


// Output a string with the specified color.

idaman void ida_export out_line(const char *str,color_t color);


// Output a string with COLOR_KEYWORD color.

inline void out_keyword(const char *str)
{
  out_line(str, COLOR_KEYWORD);
}


// Output a character with COLOR_REG color.

inline void out_register(const char *str)
{
  out_line(str, COLOR_REG);
}


// Output "turn color on" escape sequence

idaman void ida_export out_tagon(color_t tag);


// Output "turn color off" escape sequence

idaman void ida_export out_tagoff(color_t tag);


// Output a colored line with register names in it
// The register names will be substituted by user-defined names (regvar_t)
// Please note that out_tagoff tries to make substitutions too (when called with COLOR_REG)

idaman void ida_export out_colored_register_line(const char *str);


// Output uncolored plain text.
// see also out_line()

inline void OutLine(const char *s) { u_line = stpcpy(u_line,s); }


// Output one character.
// The character is output uncolored.
// see also out_symbol()

inline void OutChar(const char c)  { *u_line++ = c; }


// Output a number with the specified base (binary,octal,decimal,hex)
// The number is output uncolored.
// see also out_long()

inline void OutLong(const ulong Word,const char radix)
                        { u_line = stpcpy(u_line,btoa32(Word,radix)); }


// Output operand value as a commented character constant
// This function is used to comment void operands with their representation
// in the form of character contants.
// This function outputs a colored text.

idaman void ida_export OutImmChar(op_t &x);    // Out comment for small immediates


// Try to display value as a character constant.
// This is low level function, it is called from OutValue()
// This function outputs uncolored text.
//      v    - value to convert
//      buf  - output buffer
//      size - size of input value in bytes
// returns: 1-ok, the buffer contains character constant
//                its form depends on ash.flags
//          0-failed, probably the constant is invalid for the target
//                assembler

idaman int ida_export showAsChar(value_u *v,char *buf,int size);
                                                // try to show as character constant
                                                // return 1 - ok, 0 - can't


// Output a floating point value
// Low level function. Use OutValue() if you can.
// This function outputs uncolored text.
//      v    - floating point value in processor native format
//      size - wanted length of output number
//      buf  - output buffer
// return 1-ok,0-can't represent as floating point number

idaman int ida_export out_real(void *v,int size,char *buf);


// Output a number with appropriate color.
// Low level function. Use OutValue() if you can.
//      v     - value to output
//      radix - base (2,8,10,16)
// if 'voidop' is set then
//   out_long() uses COLOR_VOIDOP instead of COLOR_NUMBER
// 'voidop' is initialized
//      in out_one_operand()
//      and in ..\ida\gl.cpp (before calling ph.d_out())
// voidop==0: operand is ok
// voidop==1: operand is void and should be output with COLOR_VOIDOP
// voidop==2: operand can't be output as requested and should be output with COLOR_ERROR

idaman int ida_export_data voidop;
idaman void ida_export out_long(long v,char radix);


//--------------------------------------------------------------------------
//      I D P   H E L P E R   F U N C T I O N S  -  E M U L A T O R
//--------------------------------------------------------------------------

// Convert to data using information about operand value type (op.dtyp)
// This function creates data only if the address was unexplored
//      ea    - linear address to be converted to data
//      dtype - operand value type (from op.dtyp)
// Emulator could use this function to convert unexplored bytes to data
// when an instruction references them.

idaman void ida_export ua_dodata(ea_t ea,int dtype);


// Create or modify a stack variable in the function frame
//      x - operand (used to determine the addressing type)
//      v - a displacement in the operand
// The emulator could use this function to create stack variables
// in the function frame before converting the operand to a stack variable.
// Please check with may_create_stkvars() before calling this function.
// returns: 1 - ok, a stack variable exists now
//          0 - no, couldn't create stack variable

idaman int ida_export ua_stkvar(const op_t &x, ulong v);


// Add a code cross-reference from the current instruction (cmd.ea)
//      opoff - offset of the operand from the start of instruction
//              if the offset is unknown, then 0
//      to    - target linear address
//      type  - type of xref

idaman void ida_export ua_add_cref(int opoff,ea_t to,cref_t type);


// Add a data cross-reference from the current instruction (cmd.ea)
//      opoff - offset of the operand from the start of instruction
//              if the offset is unknown, then 0
//      to    - target linear address
//      type  - type of xref
// See the next function - usually it can be used in most cases.

idaman void ida_export ua_add_dref(int opoff,ea_t to,dref_t type);


// Add xrefs for offset operand of the current instruction (cmd.ea)
// This function creates all references for an operand with isOff() flag
// It doesn't work with outer offsets.
//      x     - reference to operand
//      type  - type of xref
// Returns: the reference target address (the same as calc_reference_target)

idaman ea_t ida_export ua_add_off_drefs(const op_t &x, dref_t type);


// Get size and flags for op_t.dtyp field.

idaman flags_t ida_export get_dtyp_flag(int dtype);
idaman int ida_export get_dtyp_size(int dtype);
idaman char ida_export get_dtyp_by_size(int size);


//--------------------------------------------------------------------------
//      K E R N E L   I N T E R F A C E   T O   I D P   F U N C T I O N S
//--------------------------------------------------------------------------
idaman int ida_export ua_code(ulong ea); // Convert to code, top level function
                                  // Returns length of instruction
idaman int ida_export ua_ana0(ea_t ea);  // low level function: call ph.u_ana and fill 'cmd'
                                  // return length of instruction in bytes
idaman int ida_export ua_emu(ulong ea);  // Emulate instruction, detect execution
                                  // flows, data references etc.
                                  // Returns length of instruction in bytes.
idaman int ida_export ua_out(ulong ea);  // Returns length of instruction in bytes
                                  // 0 - bad instruction
                                  // Also sets bytes if isCode()
idaman int ida_export ua_outop(ulong ea,char *buf,int n); // out text for operand <n>.
                                  // calls ua_ana()
idaman const char *ida_export ua_mnem(ea_t ea, char *buf, size_t bufsize); // Returns instruction mnemonics
idaman ea_t ida_export decode_prev_insn(ea_t ea);// if previous item is instruction
                                  // then decode it and returns its address
int ua_ana(ulong ea);             // Analyse bytes, fill cmd structure
                                  // Returns length of command. 0 - bad op
                                  // Also converts to code, uses fixups, increases segments etc
                                  // This function is only for the kernel
                                  // Use ua_code() instead

idaman ea_t ida_export guessTableAddress(void);
idaman ulong ida_export guessTableSize(ea_t Table);

bool is_ret(ea_t ea);              // is return instruction?

bool ua_use_fixup(void);           // apply fixups to the instruction
                                   // 'cmd' should be valid

#pragma pack(pop)
#endif // _UA_HPP
