/*
 *      Interactive disassembler (IDA).
 *      Copyright (c) 1990-2002 by Ilfak Guilfanov.
 *      ALL RIGHTS RESERVED.
 *                              E-mail: ig@datarescue.com
 *
 */

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

//
//      This file contains definitions of various information kept in netnodes.
//      Each address in the program has a corresponding netnode: netnode(ea)
//      If we have no information about an address, the corresponding
//      netnode is not created.
//      Otherwise we will create a netnode and save information in it.
//      All variable length information (names, comments, offset information, etc)
//      is stored in the netnode.
//      Don't forget that some information is already stored in the flags (bytes.hpp)
//
//      IMPORTANT NOTE:
//      Many of functions in this file are very low level (they are marked
//      as low level functions). Use them only if you can't find higher level
//      function to set/get/del information.
//
//      You can create your own nodes in IDP module and store information
//      in them. Look at netnode.hpp for the definition of netnodes.
//

#include <netnode.hpp>

//--------------------------------------------------------------------------
// Some information is kept in separate netnodes (all these nodes are used
// only by the kernel):

// these nodes keep information about serial autogenerated names,
// like loc_1, loc_2, etc.
extern netnode nmSerEA;     // translation loc(n) -> EA
extern netnode nmSerN;      // translation EA -> n, loc(n)
extern size_t maxSerialName;

idaman netnode ida_export_data net_patch;
                            // node with information about patched bytes
                            // altval(ea)<-(oldval)
                            // charval(ea, 'P')==1 => byte has been patched
idaman netnode ida_export_data import_node;
                            // node with information about imported modules
                            // supval(i) -> module name; altval(i) -> module node
                            // altval(-1) -> number of modules
                            // the module node is:
                            //   supval(ea) -> function name
                            //   altval(ord) -> import ea

//--------------------------------------------------------------------------

// Macro definitions used in this header file (internal)

#define _N_PASTE(x,y)   x ## y
#define N_PASTE(x,y)    _N_PASTE(x,y)
#define NSUP_TYPE(name,type,code,size)                                  \
inline ssize_t N_PASTE(get_,name)(ea_t ea, type *buf, size_t bufsize)   \
        { return netnode(ea).supval(code, buf, bufsize); }              \
inline void N_PASTE(set_,name)(ea_t ea,const type *oi)                  \
        { netnode(ea).supset(code,oi,size); }                           \
inline void N_PASTE(del_,name)(ea_t ea) { netnode(ea).supdel(code); }

#define NSUP_CHAR(name,code)                                            \
inline ssize_t N_PASTE(get_,name)(ea_t ea, char *buf, size_t bufsize)   \
        { return netnode(ea).supstr(code, buf, bufsize); }              \
inline void N_PASTE(set_,name)(ea_t ea,const char *oi)                  \
        { netnode(ea).supset(code,oi); }                                \
inline void N_PASTE(del_,name)(ea_t ea) { netnode(ea).supdel(code); }

#define NSUP_VTYPE(name,type,code)                                      \
inline ssize_t N_PASTE(get_,name)(ea_t ea, type *buf, size_t bufsize)   \
        { return netnode(ea).supval(code, buf, bufsize); }              \
inline void N_PASTE(set_,name)(ea_t ea,const type *oi,int size)         \
        { netnode(ea).supset(code,oi,size); }                           \
inline void N_PASTE(del_,name)(ea_t ea) { netnode(ea).supdel(code); }

#define NSUP_BLOB(name,type,code)                                       \
inline type *N_PASTE(get_,name)(ea_t ea,type *buf,size_t *bufsize)      \
        { return (type *)netnode(ea).getblob(buf,bufsize,code,stag); }  \
inline void N_PASTE(set_,name)(ea_t ea,const type *oi,size_t size)      \
        { netnode(ea).setblob(oi,size,code,stag); }                     \
inline void N_PASTE(del_,name)(ea_t ea) { netnode(ea).delblob(code,stag); }

#define NALT_TYPE(get,set,del,type,code)                                \
inline type get(ea_t ea) { type x; return netnode(ea).supval(code, &x, sizeof(x), atag) > 0 ? type(x-1) : type(-1); } \
inline void set(ea_t ea,type x) { x++; netnode(ea).supset(code, &x, sizeof(x), atag); } \
inline void del(ea_t ea) { netnode(ea).supdel(code, atag); }

#define NSUP_STRUCT(name,code)  NSUP_TYPE(name,N_PASTE(name,_t),code,sizeof(N_PASTE(name,_t)))
#define NSUP_STRING(name,code)  NSUP_CHAR(name,code)
#define NSUP_VAR(name,code,t)   NSUP_VTYPE(name,t,code)
#define NALT_EA(    get,set,del,code) NALT_TYPE(get,set,del,ea_t,  code)
#define NALT_ULONG( get,set,del,code) NALT_TYPE(get,set,del,ulong, code)
#define NALT_USHORT(get,set,del,code) NALT_TYPE(get,set,del,ushort,code)
#define NALT_UCHAR( get,set,del,code) NALT_TYPE(get,set,del,uchar, code)
//--------------------------------------------------------------------------

// Structure of altvals array of netnode(ea)
// altvals is a virtual array of 32-bit longs attached to a netnode.
// the size of this array is unlimited. Unused indexes are not kept in the
// database. We use only first several indexes to this array:
// (commented values are not used anymore)

#define  NALT_ENUM      uval_t(-2)// reserved for enums, see enum.hpp
#define  NALT_WIDE      uval_t(-1)// 16-bit byte value
#define  NALT_SWITCH    1         // switch idiom address (used at jump targets)
//#define  NALT_OBASE1    2       // offset base 2
#define  NALT_STRUCT    3         // struct id
#define  NALT_SEENF     4         // 'seen' flag (used in structures)
//#define  NALT_OOBASE0   5       // outer offset base 1
//#define  NALT_OOBASE1   6       // outer offset base 2
#define  NALT_XREFPOS   7         // saved xref address in the xrefs window
#define  NALT_AFLAGS    8         // additional flags for an item
#define  NALT_LINNUM    9         // source line number
#define  NALT_ABSBASE  10         // absolute segment location
#define  NALT_ENUM0    11         // enum id for the first operand
#define  NALT_ENUM1    12         // enum id for the second operand
//#define  NALT_STROFF0  13       // struct offset, struct id for the first operand
//#define  NALT_STROFF1  14       // struct offset, struct id for the second operand
#define  NALT_PURGE    15         // number of bytes purged from the stack
                                  // when a function is called indirectly
#define  NALT_STRTYPE  16         // type of string item
#define  NALT_ALIGN    17         // alignment value if the item is FF_ALIGN
                                  // (should by equal to power of 2)
//#define  NALT_HIGH0    18       // linear address of byte referenced by
//                                // high 16 bits of an offset (FF_0HIGH)
//#define  NALT_HIGH1    19       // linear address of byte referenced by
//                                // high 16 bits of an offset (FF_1HIGH)
#define  NALT_COLOR    20         // instruction/data background color

// Structure of supvals array of netnode(ea)
// Supvals is a virtual array of objects of arbitrary length attached
// to a netnode (length of one element is limited by MAXSPECSIZE, though)
// We use first several indexes to this array:

#define  NSUP_CMT       0       // regular comment
#define  NSUP_REPCMT    1       // repeatable comment
#define  NSUP_FOP1      2       // forced operand 1
#define  NSUP_FOP2      3       // forced operand 2
#define  NSUP_JINFO     4       // jump table info
#define  NSUP_ARRAY     5       // array parameters
#define  NSUP_OMFGRP    6       // OMF: group of segments (not used anymore)
#define  NSUP_FOP3      7       // forced operand 3
#define  NSUP_SWITCH    8       // switch information
#define  NSUP_REF0      9       // complex reference information for operand 1
#define  NSUP_REF1      10      // complex reference information for operand 2
#define  NSUP_REF2      11      // complex reference information for operand 3
#define  NSUP_OREF0     12      // outer complex reference information for operand 1
#define  NSUP_OREF1     13      // outer complex reference information for operand 2
#define  NSUP_OREF2     14      // outer complex reference information for operand 3
#define  NSUP_STROFF0   15      // stroff: struct path for the first operand
#define  NSUP_STROFF1   16      // stroff: struct path for the second operand
#define  NSUP_SEGTRANS  17      // segment translations
#define  NSUP_FOP4      18      // forced operand 4
#define  NSUP_FOP5      19      // forced operand 5
#define  NSUP_FOP6      20      // forced operand 6
#define  NSUP_REF3      21      // complex reference information for operand 4
#define  NSUP_REF4      22      // complex reference information for operand 5
#define  NSUP_REF5      23      // complex reference information for operand 6
#define  NSUP_OREF3     24      // outer complex reference information for operand 4
#define  NSUP_OREF4     25      // outer complex reference information for operand 5
#define  NSUP_OREF5     26      // outer complex reference information for operand 6

// values E_PREV..E_NEXT+1000 are reserved (1000..2000..3000 decimal)

// values NSUP_POINTS..NSUP_POINTS+0x1000 are reserved
#define  NSUP_POINTS    0x1000  // SP change points blob (see funcs.cpp)

// values NSUP_MANUAL..NSUP_MANUAL+0x1000 are reserved
#define  NSUP_MANUAL    0x2000  // manual instruction

// values NSUP_TYPEINFO..NSUP_TYPEINFO+0x1000 are reserved
#define  NSUP_TYPEINFO  0x3000  // type information

// values NSUP_REGVAR..NSUP_REGVAR+0x1000 are reserved
#define  NSUP_REGVAR    0x4000  // register variables

// values NSUP_LLABEL..NSUP_LLABEL+0x1000 are reserved
#define  NSUP_LLABEL    0x5000  // local labels

// values NSUP_REGARG..NSUP_REGARG+0x1000 are reserved
#define  NSUP_REGARG    0x6000  // register argument type/name descriptions

// values NSUP_FTAILS..NSUP_FTAILS+0x1000 are reserved
#define  NSUP_FTAILS    0x7000  // function tails or tail referers

// values NSUP_GROUP..NSUP_GROUP+0x1000 are reserved
#define  NSUP_GROUP     0x8000  // graph group information

// values NSUP_OPTYPES..NSUP_OPTYPES+0x100000 are reserved
#define  NSUP_OPTYPES   0x9000  // operand type information

// Tag values to store xrefs (see cref.cpp)
#define NALT_CREF_TO         'X'     // code xref to, idx: target address
#define NALT_CREF_FROM       'x'     // code xref from, idx: source address
#define NALT_DREF_TO         'D'     // data xref to, idx: target address
#define NALT_DREF_FROM       'd'     // data xref from, idx: source address

// Tag values to store graph info
#define NSUP_GR_INFO         'g'     // group node info: color, ea, text
#define NALT_GR_LAYX         'p'     // group layout ptrs, hash: md5 of 'belongs'
#define NSUP_GR_LAYT         'l'     // group layouts, idx: layout pointer

//--------------------------------------------------------------------------
//      C O N V E N I E N C E   F U N C T I O N S
//--------------------------------------------------------------------------

// up to 32bit value for wide (more than 8-bit) byte processors
// (low level functions, see bytes.hpp for higher level functions)
// this macro will generate functions
//      ulong  get_wide_value(ea_t ea);
//      void   set_wide_value(ea_t ea,ulong x);
//      void   del_wide_value(ea_t ea);
// Don't use, look at: get_full_byte(), get_full_word(), get_full_long()
NALT_ULONG(get_wide_value,set_wide_value,del_wide_value,NALT_WIDE)

// Structure ID for structures in structure definitions.
// Don't use, see: get_typeinfo()
NALT_EA(get_strid,_set_strid,_del_strid, NALT_STRUCT)
void set_strid(ea_t ea, tid_t tid);
void del_strid(ea_t ea);

// 'seen' flags (used internally by the kernel)
// Don't use.
NALT_UCHAR(get_seenf,  set_seenf,   del_seenf,   NALT_SEENF)


// position of cursor in the window with cross-references to the address
// Used by the user-interface.
NALT_EA(get_xrefpos, set_xrefpos, del_xrefpos, NALT_XREFPOS)

// Additional flags for the location.
// All 32-bits of the main flags (see bytes.hpp) are used up.
// Additional flags keep more information about addresses.
// DO NOT use these flags directly unless there is absoletely no way.
// They are too low level and may corrupt the database.
inline void  set_aflags0(ea_t ea, ulong flags) { netnode(ea).altset(NALT_AFLAGS,flags); }
inline ulong get_aflags0(ea_t ea)              { return flags_t(netnode(ea).altval(NALT_AFLAGS)); }
inline void  del_aflags0(ea_t ea)              { netnode(ea).altdel(NALT_AFLAGS); }
idaman void  ida_export set_aflags(ea_t ea, ulong flags);
idaman void  ida_export set_abits(ea_t ea,ulong bits);
idaman void  ida_export clr_abits(ea_t ea,ulong bits);
idaman ulong ida_export get_aflags(ea_t ea);
idaman void  ida_export del_aflags(ea_t ea);

#define AFL_LINNUM      0x00000001L     // has line number info
#define AFL_USERSP      0x00000002L     // user-defined SP value
#define AFL_PUBNAM      0x00000004L     // name is public (inter-file linkage)
#define AFL_WEAKNAM     0x00000008L     // name is weak
#define AFL_HIDDEN      0x00000010L     // the item is hidden completely
#define AFL_MANUAL      0x00000020L     // the instruction/data is specified by the user
#define AFL_NOBRD       0x00000040L     // the code/data border is hidden
#define AFL_ZSTROFF     0x00000080L     // display struct field name at 0 offset
                                        // when displaying an offset. example:
                                        //   offset somestruct.field_0
                                        // if this flag is clear, then
                                        //   offset somestruct
#define AFL_BNOT0       0x00000100L     // the 1st operand is bitwise negated
#define AFL_BNOT1       0x00000200L     // the 2nd operand is bitwise negated
#define AFL_LIB         0x00000400L     // item from the standard library
                                        // low level flag, is used to set
                                        // FUNC_LIB of func_t
#define AFL_TI          0x00000800L     // has typeinfo? (NSUP_TYPEINFO)
#define AFL_TI0         0x00001000L     // has typeinfo for operand 0? (NSUP_OPTYPES)
#define AFL_TI1         0x00002000L     // has typeinfo for operand 1? (NSUP_OPTYPES+1)
#define AFL_LNAME       0x00004000L     // has local name too (FF_NAME should be set)
#define AFL_TILCMT      0x00008000L     // has type comment? (such a comment
                                        // may be changed by IDA)
#define AFL_LZERO0      0x00010000L     // toggle leading zeroes for the 1st operand
#define AFL_LZERO1      0x00020000L     // toggle leading zeroes for the 2nd operand
#define AFL_COLORED     0x00040000L     // has user defined instruction color?
#define AFL_TERSESTR    0x00080000L     // terse structure variable display?
#define AFL_SIGN0       0x00100000L     // code: toggle sign of the 1st operand
#define AFL_SIGN1       0x00200000L     // code: toggle sign of the 2nd operand
#define AFL_NORET       0x00400000L     // for imported function pointers: doesn't return
                                        // this flag can also be used for any instruction
                                        // which halts or finishes the program execution
#define AFL_FIXEDSPD    0x00800000L     // sp delta value is fixed by analysis
                                        // and should not be modified by modules
#define AFL_ALIGNFLOW   0x01000000L     // the previous insn was created for alignment
                                        // purposes only
#define AFL_USERTI      0x02000000L     // the type information is definitive
                                        // (comes from the user or type library)

// The following macro is used to define 3 functions to work with a bit:
//      int  test(ea_t ea);    - test if the bit is set
//      void set(ea_t ea);     - set bit
//      void clear(ea_t ea);   - clear bit

#define IMPLEMENT_AFLAG_FUNCTIONS(bit, test, set, clear)            \
inline bool test(ea_t ea)   { return (get_aflags(ea) & bit) != 0; } \
inline void set(ea_t ea)    { set_abits(ea, bit); }                 \
inline void clear(ea_t ea)  { clr_abits(ea, bit); }


#define IMPL__IS_AFLAG_FUNCS(bit, name) \
 IMPLEMENT_AFLAG_FUNCTIONS(bit, is_ ## name, set_ ## name, clr_ ## name)
#define IMPL_HAS_AFLAG_FUNCS(bit, name) \
 IMPLEMENT_AFLAG_FUNCTIONS(bit, has_ ## name, set_has_ ## name, clr_has_ ## name)

IMPLEMENT_AFLAG_FUNCTIONS(AFL_HIDDEN,   is_hidden_item, hide_item, unhide_item)
IMPLEMENT_AFLAG_FUNCTIONS(AFL_NOBRD,    is_hidden_border, hide_border, unhide_border)

IMPL__IS_AFLAG_FUNCS(AFL_ZSTROFF,  zstroff)
IMPL__IS_AFLAG_FUNCS(AFL_BNOT0,    _bnot0)
IMPL__IS_AFLAG_FUNCS(AFL_BNOT1,    _bnot1)
IMPL__IS_AFLAG_FUNCS(AFL_LIB,      libitem)
IMPL_HAS_AFLAG_FUNCS(AFL_TI,       ti)
IMPL_HAS_AFLAG_FUNCS(AFL_TI0,      ti0)
IMPL_HAS_AFLAG_FUNCS(AFL_TI1,      ti1)
IMPL_HAS_AFLAG_FUNCS(AFL_LNAME,    lname)
IMPL__IS_AFLAG_FUNCS(AFL_TILCMT,   tilcmt)
IMPL__IS_AFLAG_FUNCS(AFL_USERSP,   usersp)
IMPL__IS_AFLAG_FUNCS(AFL_LZERO0,   lzero0)
IMPL__IS_AFLAG_FUNCS(AFL_LZERO1,   lzero1)
IMPL__IS_AFLAG_FUNCS(AFL_COLORED,  colored_item)
IMPL__IS_AFLAG_FUNCS(AFL_TERSESTR, terse_struc)
IMPL__IS_AFLAG_FUNCS(AFL_SIGN0,    _invsign0)
IMPL__IS_AFLAG_FUNCS(AFL_SIGN1,    _invsign1)
IMPL__IS_AFLAG_FUNCS(AFL_NORET,    noret)
IMPL__IS_AFLAG_FUNCS(AFL_FIXEDSPD, fixed_spd)
IMPL__IS_AFLAG_FUNCS(AFL_ALIGNFLOW,align_flow)
IMPL__IS_AFLAG_FUNCS(AFL_USERTI,   userti)

inline void set_visible_item(ea_t ea, bool visible)
{
  if ( visible )
     unhide_item(ea);
  else
      hide_item(ea);
}

inline bool is_visible_item(ea_t ea) { return !is_hidden_item(ea); }

inline bool is_finally_visible_item(ea_t ea) // is instruction visible?
 { return (inf.s_cmtflg & SW_SHHID_ITEM) != 0 || is_visible_item(ea); }


// source line numbers (they are sometimes present in object files)
// Thes functions may be used if necessary.
NALT_EA(get_linnum0,set_linnum0, del_linnum0, NALT_LINNUM)
idaman void   ida_export set_source_linnum(ea_t ea, uval_t lnnum);
idaman uval_t ida_export get_source_linnum(ea_t ea);      // returns BADADDR if no lnnum
idaman void   ida_export del_source_linnum(ea_t ea);

// absolute segment base address
// These functions may be used if necessary.
NALT_EA(get_absbase,set_absbase, del_absbase, NALT_ABSBASE)

// enum id for the first operand (low level)
// Don't use, see get_enum_id()
NALT_EA(get_enum_id0,set_enum_id0,del_enum_id0,NALT_ENUM0)

// enum id for the second operand (low level)
// Don't use, see get_enum_id()
NALT_EA(get_enum_id1,set_enum_id1,del_enum_id1,NALT_ENUM1)

// number of bytes purged from the stack when a function is called indirectly
// get_ind_purged() may be used if necessary.
// Use set_purged() to modify this value (do not use set_ind_purged)
NALT_EA(get_ind_purged,set_ind_purged,del_ind_purged,NALT_PURGE)

// type of string
// Don't use, see: get_typeinfo()
NALT_ULONG(get_str_type,set_str_type,del_str_type,NALT_STRTYPE)

inline char idaapi get_str_type_code(uval_t strtype) { return char(strtype); }

#define ASCSTR_C        ASCSTR_TERMCHR // C-style ASCII string
#define ASCSTR_TERMCHR  0       // Character-terminated ASCII string
                                // The termination characters are kept in
                                // the next bytes of string type
inline char get_str_term1(long strtype) { return char(strtype>>8); }
inline char get_str_term2(long strtype) { return char(strtype>>16); }
                                // if the second termination character is
                                // '\0', then it doesn't exist.
#define ASCSTR_PASCAL   1       // Pascal-style ASCII string (length byte)
#define ASCSTR_LEN2     2       // Pascal-style, length is 2 bytes
#define ASCSTR_UNICODE  3       // Unicode string
#define ASCSTR_LEN4     4       // Pascal-style, length is 4 bytes
#define ASCSTR_ULEN2    5       // Pascal-style Unicode, length is 2 bytes
#define ASCSTR_ULEN4    6       // Pascal-style Unicode, length is 4 bytes
#define ASCSTR_LAST     6       // Last string type

inline bool is_unicode(long strtype)
{
  char code = get_str_type_code(strtype);
  return code == ASCSTR_UNICODE
      || code == ASCSTR_ULEN2
      || code == ASCSTR_ULEN4;
}

inline bool is_pascal(long strtype)
{
  char code = get_str_type_code(strtype);
  return code == ASCSTR_PASCAL
      || code == ASCSTR_LEN2
      || code >= ASCSTR_LEN4;
}


// alignment value (should be power of 2)
// These functions may be used if necessary.
NALT_ULONG(get_alignment,set_alignment,del_alignment,NALT_ALIGN)

// instruction/data background color
NALT_ULONG(_get_item_color,_set_item_color,_del_item_color,NALT_COLOR)
idaman void      ida_export set_item_color(ea_t ea, bgcolor_t color);
idaman bgcolor_t ida_export get_item_color(ea_t ea);      // returns DEFCOLOR if no color
idaman void      ida_export del_item_color(ea_t ea);

//----------------------------------------------------------------------
NSUP_STRING(nalt_cmt,NSUP_CMT)          // regular comment       (low level, don't use)
NSUP_STRING(nalt_rptcmt,NSUP_REPCMT)    // repeatable comment    (low level, don't use)
NSUP_STRING(fop1,NSUP_FOP1)             // first forced operand  (low level, don't use)
NSUP_STRING(fop2,NSUP_FOP2)             // second forced operand (low level, don't use)
NSUP_STRING(fop3,NSUP_FOP3)             // third forced operand  (low level, don't use)
NSUP_STRING(fop4,NSUP_FOP4)             // 4 forced operand      (low level, don't use)
NSUP_STRING(fop5,NSUP_FOP5)             // 5 forced operand      (low level, don't use)
NSUP_STRING(fop6,NSUP_FOP6)             // 6 forced operand      (low level, don't use)
NSUP_BLOB(manual_insn0,char,NSUP_MANUAL)// manual instruction    (low level, don't use)
NSUP_BLOB(graph_groups0,uchar,NSUP_GROUP)// graph group          (low level, don't use)

//--------------------------------------------------------------------------
struct jumptable_info_t
{
  ea_t table;
  asize_t size;
};
NSUP_STRUCT(jumptable_info,NSUP_JINFO)  // information about jump tables

//--------------------------------------------------------------------------
struct array_parameters_t
{
  long flags;
#define AP_ALLOWDUPS    0x00000001L     // use 'dup' construct
#define AP_SIGNED       0x00000002L     // treats numbers as signed
#define AP_INDEX        0x00000004L     // display array element indexes as comments
  long lineitems;                       // number of items on a line
  long alignment;                       // -1 - don't align
                                        // 0  - align automatically
                                        // else item width
};
NSUP_STRUCT(array_parameters,NSUP_ARRAY)

//--------------------------------------------------------------------------
struct switch_info_t
{
  ushort flags;
#define SWI_SPARSE      0x01    // sparse switch (value table present)
                                // otherwise lowcase present
#define SWI_V32         0x02    // 32-bit values in table
#define SWI_J32         0x04    // 32-bit jump offsets
#define SWI_VSPLIT      0x08    // value table is split (only for 32-bit values)
#define SWI_DEFAULT     0x10    // default case is present
#define SWI_END_IN_TBL  0x20    // switchend in table (default entry)
#define SWI_JMP_INV     0x40    // jumptable is inversed (last entry is
                                // for first entry in values table)
#define SWI_SHIFT_MASK  0x180   // use formula (element*shift + elbase)
                                // to find jump targets
  int get_shift(void) const { return ((flags & SWI_SHIFT_MASK) >> 7); }
                                // possible answers: 0..3
  void set_shift(int shift)
  {
    flags &= ~SWI_SHIFT_MASK;
    flags = ushort(flags | ((shift & 3) << 7));
  }
#define SWI_ELBASE      0x200   // elbase is present (if not and shift!=0, endof(jumpea) is used)
#define SWI_JSIZE       0x400   // jump offset expansion bit
  int get_jtable_element_size(void) const
  { // this brain damaged logic is needed for compatibility with old versions
    int code = flags & (SWI_J32|SWI_JSIZE);
    if ( code == 0 )
      return 2;
    if ( code == SWI_J32 )
      return 4;
    if ( code == SWI_JSIZE )
      return 1;
    return 8;
  }
  void set_jtable_element_size(int size)
  {
    flags &= ~SWI_J32|SWI_JSIZE;
    if ( size == 4 ) { flags |= SWI_J32; return; }
    if ( size == 1 ) { flags |= SWI_JSIZE; return; }
    if ( size == 8 ) { flags |= SWI_J32|SWI_JSIZE; return; }
    if ( size != 2 ) abort();
  }
#define SWI_VSIZE       0x800   // value table element size expansion bit
  int get_vtable_element_size(void) const
  {
    int code = flags & (SWI_V32|SWI_VSIZE);
    if ( code == 0 )
      return 2;
    if ( code == SWI_V32 )
      return 4;
    if ( code == SWI_VSIZE )
      return 1;
    return 8;
  }
  void set_vtable_element_size(int size)
  {
    flags &= ~SWI_V32|SWI_VSIZE;
    if ( size == 4 ) { flags |= SWI_V32; return; }
    if ( size == 1 ) { flags |= SWI_VSIZE; return; }
    if ( size == 8 ) { flags |= SWI_V32|SWI_VSIZE; return; }
    if ( size != 2 ) abort();
  }
#define SWI_SEPARATE    0x1000  // do not create an array of individual dwords
#define SWI_SIGNED      0x2000  // jump table entries are signed
#define SWI_CUSTOM      0x4000  // custom jump table - ph.create_switch_xrefs will be
                                // called to create code xrefs for the table.
                                // it must return 2.
                                // custom jump table must be created by the module
#define SWI_EXTENDED    0x8000  // this is switch_info_ex_t
  ushort ncases;                // number of cases (excluding default)
  ea_t jumps;                   // jump table address
  union
  {
    ea_t values;                // values table address (SWI_SPARSE)
    uval_t lowcase;             // the lowest value in cases
  };
  ea_t defjump;                 // default jump address
  ea_t startea;                 // start of switch idiom
};

struct switch_info_ex_t : public switch_info_t
{
  size_t cb;                    // sizeof(this)
  int flags2;
#define SWI2_INDIRECT 0x0001    // value table elements are used as indexes into the jump table
  int jcases;                   // number of entries in the jump table (SWI2_INDIRECT)
  bool is_indirect(void) const { return (flags & SWI_EXTENDED) != 0 && (flags2 & SWI2_INDIRECT) != 0; }
  int get_jtable_size(void) const { return is_indirect() ? jcases : ncases; }
  sval_t ind_lowcase;
  sval_t get_lowcase(void) const { return is_indirect() ? ind_lowcase : lowcase; }
  ea_t elbase;                  // element base
  int regnum;                   // the switch expression as a register number
                                // of the instruction at 'startea'. -1 means 'unknown'
  char regdtyp;                  // size of the switch expression register as dtyp
  void set_expr(int r, char dt) { regnum = r; regdtyp = dt; }
  uval_t custom;                // information for custom tables (filled and used by modules)
  switch_info_ex_t(void) { clear(); }
  void clear(void)
  {
    memset(this, 0, sizeof(switch_info_ex_t));
    cb = sizeof(switch_info_ex_t);
    flags = SWI_EXTENDED;
    defjump = BADADDR;
    startea = BADADDR;
    regnum = -1;
  }
};

NSUP_STRUCT(switch_info_ex,NSUP_SWITCH)  // see xref.hpp for related functions

// Address which holds the switch info. Used at the jump targets.
NALT_EA(get_switch_parent,set_switch_parent,del_switch_parent, NALT_SWITCH)


//--------------------------------------------------------------------------
//
//      References are represented in the following form:
//
//              target + tdelta - base
//
//      If the target is not present, then it will be calculated using
//
//              target = operand_value - tdelta + base
//
//      The target must be present for LOW and HIGH reference types

typedef uchar reftype_t;
const reftype_t                  // type of reference
  REF_OFF8   = 0,    // 8bit full offset
  REF_OFF16  = 1,    // 16bit full offset
  REF_OFF32  = 2,    // 32bit full offset
  REF_LOW8   = 3,    // low 8bits of 16bit offset
  REF_LOW16  = 4,    // low 16bits of 32bit offset
  REF_HIGH8  = 5,    // high 8bits of 16bit offset
  REF_HIGH16 = 6,    // high 16bits of 32bit offset
  REF_VHIGH  = 7,    // high ph.high_fixup_bits of 32bit offset
  REF_VLOW   = 8,    // low  ph.high_fixup_bits of 32bit offset
  REF_OFF64  = 9,    // 64bit full offset
  REF_LAST = REF_OFF64;

// Get REF_... constant from size
// Supported sizes: 1,2,4,8,16
// For other sizes returns reftype(-1)

idaman reftype_t ida_export get_reftype_by_size(size_t size);


struct refinfo_t                // information about a reference
{
  ea_t target;                  // reference target (BADADDR-none)
  ea_t base;                    // base of reference
  adiff_t tdelta;               // offset from the target
  uchar flags;
#define REFINFO_TYPE    0x0F    // reference type
#define REFINFO_RVAOFF  0x10    // based reference (rva)
                                // refinfo_t.base will be forced to get_imagebase()
                                // such a reference is displayed with the ash.a_rva keyword
#define REFINFO_PASTEND 0x20    // reference past an item
                                // it may point to an nonexistitng address
                                // do not destroy alignment dirs
#define REFINFO_NOBASE  0x80    // don't create base xref?
                                // implies that base have be any value
                                // nb: base xrefs are created only if base
                                // points to the middle of a segment
  reftype_t type(void) const { return reftype_t(flags & REFINFO_TYPE); }
  bool no_base_xref(void) const { return (flags & REFINFO_NOBASE) != 0; }
  bool is_pastend(void) const { return (flags & REFINFO_PASTEND) != 0; }
  bool is_rvaoff(void) const { return (flags & REFINFO_RVAOFF) != 0; }

  void set_type(reftype_t t) { flags &= ~REFINFO_TYPE; flags |= t; }
};

#define MAXSTRUCPATH  32        // maximal inclusion depth of unions

// Information for structure offsets.
// ids[0] contains the id of the structure.
// ids[1..len-1] contain ids of the structure members used in the structure offset
// expression.
// len is the length of the path, i.e. the number of elements in 'ids'
struct strpath_t
{
  int len;
  tid_t ids[MAXSTRUCPATH]; // for union member ids
  adiff_t delta;
};

struct enum_const_t
{
  tid_t tid;
  uchar serial;
};

union typeinfo_t        // additional information about a data type
{
  refinfo_t ri;         // for offset members
  tid_t tid;            // for struct, etc. members
  strpath_t path;       // for stroff
  long strtype;         // for strings (ASCSTR_...)
  enum_const_t ec;      // for enums
};

// n may be 0, 1, 2, OPND_MASK
// OPND_OUTER may be used too
// Don't use these functions, see get_typeinfo(), set_typeinfo()

idaman int ida_export set_refinfo_ex(ea_t ea, int n, const refinfo_t *ri);  // 1-ok, 0-bad refinfo
idaman int ida_export set_refinfo(ea_t ea, int n,
          reftype_t type, ea_t target=BADADDR, ea_t base=0, adiff_t tdelta=0);
idaman int ida_export get_refinfo(ea_t ea, int n, refinfo_t *ri);        // 1-ok, 0-no refinfo
idaman int ida_export del_refinfo(ea_t ea, int n);


//--------------------------------------------------------------------------
// structure pathes for unions and structures with unions (strpath)

// a structure path is an array of id's.
// the first id is the id of the structure itself
// additional id's (if any) specify which member of a union we should select
// the maximal size of array is MAXSTRUCPATH
// strpaths are used to determine how to display structure offsets

idaman void ida_export write_struc_path(netnode node, int idx, const tid_t *path, int plen, adiff_t delta);
idaman int  ida_export read_struc_path(netnode node, int idx, tid_t *path, adiff_t *delta);  // returns plen

#define DEFINE_PATH_FUNCS(name, code)                                \
inline int  N_PASTE(get_,name)(ea_t ea, tid_t *path, adiff_t *delta) \
 { return read_struc_path(netnode(ea), code, path, delta); }         \
inline void N_PASTE(set_,name)(ea_t ea, const tid_t *path, int plen, adiff_t delta) \
 { write_struc_path(netnode(ea), code, path, plen, delta); }         \
inline void N_PASTE(del_,name)(ea_t ea)                              \
 { netnode(ea).supdel(code); }

DEFINE_PATH_FUNCS(stroff0, NSUP_STROFF0)
DEFINE_PATH_FUNCS(stroff1, NSUP_STROFF1)

//--------------------------------------------------------------------------
// low level segment translation functions
// please use function from segment.hpp
NSUP_VAR(_segtrans, NSUP_SEGTRANS, ea_t)

//--------------------------------------------------------------------------
// type information (ti) storage
// up to 256 operands are supported for ti.

typedef uchar type_t;
typedef uchar p_list;

// work with function/data types
// These functions may be used if necessary.
idaman bool ida_export get_tinfo(ea_t ea, qtype *type, qtype *fields);
idaman bool ida_export set_tinfo(ea_t ea, const type_t *ti, const p_list *fnames); // see apply_type()
inline void idaapi del_tinfo(ea_t ea) { set_tinfo(ea, NULL, NULL); }

// work with operand types
// These functions may be used if necessary.
idaman bool ida_export get_op_tinfo(ea_t ea, int n, qtype *type, qtype *fnames);
idaman bool ida_export set_op_tinfo(ea_t ea, int n, const type_t *ti, const p_list *fnames);
inline void idaapi del_tinfo(ea_t ea, int n) { set_op_tinfo(ea, n, NULL, NULL); }

//------------------------------------------------------------------------//
// Rootnode indexes:

// supvals
#define RIDX_FILE_FORMAT_NAME        1  // file format name for loader modules
#define RIDX_SELECTORS               2  // 2..63 are for selector_t blob (see init_selectors())
#define RIDX_GROUPS                 64  // segment group information (see init_groups())
#define RIDX_H_PATH                 65  // C header path
#define RIDX_C_MACROS               66  // C predefined macros
#define RIDX_SMALL_IDC_OLD          67  // Instant IDC statements (obsolete)
#define RIDX_NOTEPAD                68  // notepad blob, occupies 1000 indexes (1MB of text)
#define RIDX_INCLUDE              1100  // assembler include file name
#define RIDX_SMALL_IDC            1200  // Instant IDC statements, blob
#define RIDX_DUALOP_GRAPH         1300  // Graph text representation options
#define RIDX_DUALOP_TEXT          1301  // Text text representation options
#define RIDX_MD5                  1302  // MD5 of the input file
#define RIDX_IDA_VERSION          1303  // version of ida which created the database

// altvals
#define RIDX_ALT_VERSION        uval_t(-1) // initial version of database
#define RIDX_ALT_CTIME          uval_t(-2) // database creation timestamp
#define RIDX_ALT_ELAPSED        uval_t(-3) // seconds database stayed open
#define RIDX_ALT_NOPENS         uval_t(-4) // how many times the database is opened
#define RIDX_ALT_CRC32          uval_t(-5) // input file crc32
#define RIDX_ALT_IMAGEBASE      uval_t(-6) // image base
#define RIDX_ALT_IDSNODE        uval_t(-7) // ids modnode id (for import_module)

//--------------------------------------------------------------------------
// Get full path of the input file
inline ssize_t idaapi get_input_file_path(char *buf, size_t bufsize)
{
  return RootNode.valstr(buf, bufsize);
}

// Get file name only of the input file
idaman ssize_t ida_export get_root_filename(char *buf, size_t bufsize);

// Set full path of the input file
inline void set_root_filename(const char *file) { RootNode.set(file); }

// get input file crc32 stored in the database
// it can be used to check that the input file has not been changed
inline ulong idaapi retrieve_input_file_crc32(void) { return ulong(RootNode.altval(RIDX_ALT_CRC32)); }

// get input file md5
inline bool idaapi retrieve_input_file_md5(uchar hash[16]) { return RootNode.supval(RIDX_MD5, hash, 16) == 16; }

// Get/set name of the include file
inline ssize_t idaapi get_asm_inc_file(char *buf, size_t bufsize) { return RootNode.supstr(RIDX_INCLUDE, buf, bufsize); }
inline void idaapi set_asm_inc_file(const char *file) { RootNode.supset(RIDX_INCLUDE, file); }

// get/set image base address
inline ea_t idaapi get_imagebase(void) { return RootNode.altval(RIDX_ALT_IMAGEBASE); }
inline void idaapi set_imagebase(ea_t base) { RootNode.altset(RIDX_ALT_IMAGEBASE, base); }

// get/set ids modnode
inline netnode idaapi get_ids_modnode(void) { return RootNode.altval(RIDX_ALT_IDSNODE); }
inline void idaapi set_ids_modnode(netnode id) { RootNode.altset(RIDX_ALT_IDSNODE, id); }

// Anterioir/posterior lines (see also lines.hpp)
inline void idaapi ExtraUpdate(ea_t ea, const char *str, int what) { netnode(ea).supset(what, str); }
inline void idaapi ExtraDel(ea_t ea, int what) { netnode(ea).supdel(what); }
inline ssize_t idaapi ExtraGet(ea_t ea, int what, char *buf, size_t bufsize) { return netnode(ea).supstr(what, buf, bufsize); }

inline size_t dbg_get_input_path(char *buf, size_t bufsize)
{
  if ( (inf.lflags & LFLG_DBG_NOPATH) != 0 )
    return get_root_filename(buf, bufsize);
  else
    return get_input_file_path(buf, bufsize);
}

#ifndef NO_OBSOLETE_FUNCS
#define SWI_SHIFT1      0x80    // use formula (element*2 + elbase)
                                // to find jump targets (obsolete)
NSUP_STRUCT(switch_info,NSUP_SWITCH)

idaman bool ida_export get_ti(ea_t ea, type_t *buf, size_t bufsize, p_list *fnames, size_t fnsize);
idaman bool ida_export set_ti(ea_t ea, const type_t *ti, const p_list *fnames); // see apply_type()
inline void idaapi del_ti(ea_t ea) { set_ti(ea, (type_t *)"", NULL); }
idaman bool ida_export get_op_ti(ea_t ea, int n, type_t *buf, size_t bufsize, p_list *fnames, size_t fnsize);
idaman bool ida_export set_op_ti(ea_t ea, int n, const type_t *ti, const p_list *fnames);
inline void idaapi del_ti(ea_t ea, int n) { set_op_ti(ea, n, (type_t *)"", NULL); }
#endif

#ifndef BYTES_SOURCE    // undefined bit masks so no one can use them directly
#undef AFL_LINNUM
#undef AFL_USERSP
#undef AFL_PUBNAM
#undef AFL_WEAKNAM
#undef AFL_HIDDEN
#undef AFL_MANUAL
#undef AFL_NOBRD
#undef AFL_ZSTROFF
#undef AFL_BNOT0
#undef AFL_BNOT1
#undef AFL_LIB
#undef AFL_TI
#undef AFL_TI0
#undef AFL_TI1
#undef AFL_LNAME
#undef AFL_TILCMT
#undef AFL_LZERO0
#undef AFL_LZERO1
#undef AFL_COLORED
#undef AFL_TERSESTR
#undef AFL_SIGN0
#undef AFL_SIGN1
#undef AFL_NORET
#undef AFL_FIXEDSPD
#undef NALT_ENUM
#undef NALT_WIDE
#undef NALT_SWITCH
#undef NALT_STRUCT
#undef NALT_SEENF
#undef NALT_XREFPOS
#undef NALT_AFLAGS
#undef NALT_LINNUM
#undef NALT_ABSBASE
#undef NALT_ENUM0
#undef NALT_ENUM1
#undef NALT_PURGE
#undef NALT_STRTYPE
#undef NALT_ALIGN
#undef NALT_COLOR
#undef NSUP_CMT
#undef NSUP_REPCMT
#undef NSUP_FOP1
#undef NSUP_FOP2
#undef NSUP_JINFO
#undef NSUP_ARRAY
#undef NSUP_OMFGRP
#undef NSUP_FOP3
#undef NSUP_SWITCH
#undef NSUP_REF0
#undef NSUP_REF1
#undef NSUP_REF2
#undef NSUP_OREF0
#undef NSUP_OREF1
#undef NSUP_OREF2
#undef NSUP_STROFF0
#undef NSUP_STROFF1
#undef NSUP_SEGTRANS
#undef NSUP_FOP4
#undef NSUP_FOP5
#undef NSUP_FOP6
#undef NSUP_REF3
#undef NSUP_REF4
#undef NSUP_REF5
#undef NSUP_OREF3
#undef NSUP_OREF4
#undef NSUP_OREF5
#undef NSUP_MANUAL
#undef NSUP_FTAILS
#undef NSUP_GROUP
#endif

#pragma pack(pop)
#endif // NALT_HPP
