/*
 *      Interactive disassembler (IDA).
 *      Copyright (c) 1990-97 by Ilfak Guilfanov.
 *      ALL RIGHTS RESERVED.
 *                              E-mail: ig@estar.msk.su
 *                              FIDO:   2:5020/209
 *
 */

#ifndef BYTES_HPP
#define BYTES_HPP

#include <llong.hpp>    // for long long
#include <idp.hpp>      // ph.nbits
#include <lines.hpp>
#include <segment.hpp>  // for is_visible_segm()
#pragma pack(push, 1)   // IDA uses 1 byte alignments!

typedef ulong enum_t;   // #include <enum.hpp>


//
//      This file contains functions that deal with individual byte
//      characteristics.
//      Each byte of a program being disassembled is represented by a 32-bit
//      quantity. We will call it 'flags'. Structure of flags is represented
//      below. You are not allowed to inspect individual bits of flags
//      and modify them directly. Use special function to inspect and/or
//      modify flags.
//      Flags are kept in a virtual array file (*.id1)
//      Addresses (ea) are all 32-bit quantities.
//
//        Each byte of a disassembled program is stored 32-bit value called 
//        "flags" which also stores addtional information about the byte. The
//        structure of "flags" is presented below. You are not allowed to
//        inspect or modify the individual bits of flags directly. Use the
//        special functions provided to inspect and/or modify flags.
//--------------------------------------------------------------------------
// ida virtual memory configuration:
// (not reachable from modules)
extern ushort ida_vpagesize;    // Virtual memory page size       (*.id1)
extern ushort ida_vpages;       // Size of virtual memory window  (*.id1)
extern ushort ida_npagesize;    // Name pointers page size        (*.nam)
extern ushort ida_npages;       // Number of name pointer pages   (*.nam)

//--------------------------------------------------------------------------
// initialize virtual array (*.id1)
//     input_size - input file size (used only if database didn't exist before)

void FlagsInit(ulong input_size);


// terminate virtual array

void FlagsTerm(void);


// make virtual array empty.
// returns: 1-ok, 0-failure(never should occur)

bool FlagsReset(void);


// allocate flags for address range (startEA..endEA)
// startEA should be lower than endEA.
// endEA does not belong to the range.
// exit with an error message if not enough disk space
// return 0 if ok
// otherwise return error code

idaman int ida_export FlagsEnable(ea_t startEA,ea_t endEA);


// deallocate flags for address range (startEA..endEA)
// startEA should be lower than endEA.
// endEA does not belong to the range.
// exit with an error message if not enough disk space (this may occur too)
// return 0 if ok
// otherwise return error code

idaman int ida_export FlagsDisable(ea_t startEA,ea_t endEA);


// Get next address in the program. (i.e. address which has flags)
// Return BADADDR if no such address exist.

idaman ea_t ida_export nextaddr(ea_t ea);


// Get previous address in the program.
// Return BADADDR if no such address exist.

idaman ea_t ida_export prevaddr(ea_t ea);


// Get start of next contiguous addresses in the program.
// (a block of addresses without holes)
// Return BADADDR if next chunk doesn't exist.

idaman ea_t ida_export nextchunk(ea_t ea);


// Get start of previous contiguous addresses in the program.
// Return BADADDR if previous chunk doesn't exist.

idaman ea_t ida_export prevchunk(ea_t ea);


// Get start of the contiguous address block containing 'ea'.
// Return BADADDR if 'ea' doesn't belong to the program.

idaman ea_t ida_export chunkstart(ea_t ea);


// Get size of the contiguous address block containing 'ea'.
// Return 0 if 'ea' doesn't belong to the program.

idaman ulong ida_export chunksize(ea_t ea);


// Search for a hole in the addressing space of the program.
// bottom - address to start searching
// size   - size of desired block
// step   - bit mask for the start of hole (0xF would align hole to a paragraph)
//          if 'step' is negative, the bottom address with be aligned
//          otherwise the kernel will try to use it as is and align it
//          only the hole is too small.
// Return start of the hole or BADADDR

idaman ea_t ida_export freechunk(ea_t bottom,ulong size,long step);


// Find next address with a flag satisfying the function 'testf'.
// Start searching from address 'ea'+1 and inspect bytes up to 'maxea'.
// maxea is not included in the search range
// Return the found address or BADADDR.

idaman ea_t ida_export nextthat(ea_t ea,ea_t maxea,bool (idaapi*testf)(flags_t flags));


// Find previous address with a flag satisfying the function 'testf'.
// Start searching from address 'ea'+1 and inspect bytes up to 'minea'.
// minea is included in the search range
// Return the found address or BADADDR.

idaman ea_t ida_export prevthat(ea_t ea,ea_t minea,bool (idaapi*testf)(flags_t flags));


// Get start of previous defined item. Return BADADDR if none exist.
// minea is included in the search range

idaman ea_t ida_export prev_head(ea_t ea, ea_t minea);


// Get start of next defined item. Return BADADDR if none exist.
// maxea is not included in the search range

idaman ea_t ida_export next_head(ea_t ea, ea_t maxea);


// Get address of previous non-tail byte. Return BADADDR if none exist.

idaman ea_t ida_export prev_not_tail(ea_t ea);


// Get address of next non-tail byte. Return BADADDR if none exist.

idaman ea_t ida_export next_not_tail(ea_t ea);


// Adjust the address and get the nearest visible address
// (i.e. an adress which will appear in the disassembly)
// This function returns BADADDR only if no addresses are valid

ea_t adjust_visea(ea_t ea);


// Get previous visible address
// Returns BADADDR if none exists.

idaman ea_t ida_export prev_visea(ea_t ea);


// Get next visible address
// Returns BADADDR if none exists.

idaman ea_t ida_export next_visea(ea_t ea);


// Is an address the first visible address?

bool is_first_visea(ea_t ea);


// Is an address the last visible address?

bool is_last_visea(ea_t ea);


// Is the address visible on the screen (not hidden)?

bool is_visible_finally(ea_t ea); // do we need to show anything
                                  // at this address?

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

inline bool is_finally_visible_func(func_t *pfn) // is function visible?
 { return (inf.s_cmtflg & SW_SHHID_FUNC) != 0 || is_visible_func(pfn); }

inline bool is_finally_visible_segm(segment_t *s) // is segment visible?
 { return (inf.s_cmtflg & SW_SHHID_SEGM) != 0 || is_visible_segm(s); }


// this function is only for the kernel
idaman void ida_export invalidate_visea_cache(void);


// Get the start address of the item at 'ea'.
// If there is no current item, then 'ea' will be returned
// (see definition at the end of this file)

inline ea_t idaapi get_item_head(ea_t ea);


// Get the end address of the item at 'ea'. The returned address
// doesn't belong to the current item. Unexplored bytes are counted as
// 1 byte entities.

idaman ea_t ida_export get_item_end(ea_t ea);


// Calculate maximal reasonable end address of a new item.
// This function will limit the item with the current segment bounds.
//      ea      - linear address.
//      how     - when to stop the search. A combination of ITEM_END...
// returns: end of new item. If it is not possible to create an item,
//          it will return 'ea'.

#define ITEM_END_FIXUP  0x0001          // stop at the first fixup
#define ITEM_END_INITED 0x0002          // if  isLoaded(ea): stop if uninitialized byte is encountered
                                        // if !isLoaded(ea): stop if   initialized byte is encountered
#define ITEM_END_NAME   0x0004          // stop at the first named location
#define ITEM_END_XREF   0x0008          // stop at the first referenced location
idaman ea_t ida_export calc_max_item_end(ea_t ea, int how=15);


// Get size of item (instruction/data) in bytes. Unexplored bytes have
// length of 1 byte. This function never returns 0.

inline ulong get_item_size(ea_t ea) { return get_item_end(ea) - ea; }


// Flush virtual array to disk

void fluFlags(void);


// Is the specified address 'ea' present in the program?

idaman bool ida_export isEnabled(ea_t ea);


// Get flags value for address 'ea'. If address is not present in the program,
// return 0.

idaman flags_t ida_export getFlags(ea_t ea);


// Get flag of the item at 'ea' even if it is a tail byte of some
// array or structure. This function is used to get flags of structure members
// or array elements.
//      from    - linear address of the instruction which refers to 'ea'
//      n       - number of operand which refers to 'ea'
//      ea      - the referenced address
//      appzero - meaningful only if the name refers to a structure.
//                append a struct field name if the field offset is zero?
// returns: flags or 0 (if failed)

idaman flags_t ida_export get_item_flag(ea_t from, int n, ea_t ea, bool appzero);


// Modify flags value for address 'ea'.  (ONLY KERNEL MAY USE THIS FUNCTION!)

idaman void ida_export setFlags(ea_t ea,flags_t flags);


// Set the specified bits of flags (ONLY KERNEL MAY USE THIS FUNCTION!)

idaman void ida_export setFlbits(ea_t EA,flags_t bits);


// Clear the specified bits of flags (ONLY KERNEL MAY USE THIS FUNCTION!)

idaman void ida_export clrFlbits(ea_t EA,flags_t bits);


//--------------------------------------------------------------------------
//
//      Here we define structure of flags.
//      Low 8 bits contain value of corresponding byte of the program.
//      The next bit is set if the byte is initialized
//

#define MS_VAL  0x000000FFL             // Mask for byte value
#define FF_IVL  0x00000100L             // Byte has value ?

// Do flags contain byte value?

inline bool idaapi hasValue(flags_t F)  { return (F & FF_IVL) != 0; }


// Get byte value from flags (only 8 bits from the database)
// Use get_byte() instead

inline uchar idaapi _byteValue(flags_t F) { return ((uchar)(F & MS_VAL)); }


// Delete byte value from flags. The corresponding byte becomes
// uninitialized.

inline void idaapi delValue(ea_t ea) { clrFlbits(ea,FF_IVL); }


// Does the specified address have a byte value (is initialized?)

inline bool idaapi isLoaded(ea_t ea) { return hasValue(getFlags(ea)); }


// Get one byte (8-bit) of the program at 'ea'
// This function works only for 8bit byte processors.

idaman uchar ida_export get_byte(ea_t ea);


// Get one word (16-bit) of the program at 'ea'
// This function takes into account order of bytes specified in inf.mf
// This function works only for 8bit byte processors.

idaman ushort ida_export get_word(ea_t ea);

// Get one dword (32-bit) of the program at 'ea'
// This function takes into account order of bytes specified in inf.mf
// This function works only for 8bit byte processors.

idaman ulong ida_export get_long(ea_t ea);


// Get one qword (64-bit) of the program at 'ea'
// This function takes into account order of bytes specified in inf.mf
// This function works only for 8bit byte processors.

idaman ulonglong ida_export get_qword(ea_t ea);


// Get one wide byte of the program at 'ea'
// Some processors may access more than 8bit quantity at an address.
// These processors have 32-bit byte organization from the IDA's point of view.

idaman ulong ida_export get_full_byte(ea_t ea);


// Get one wide word (64-bit) of the program at 'ea'
// Some processors may access more than 8bit quantity at an address.
// These processors have 32-bit byte organization from the IDA's point of view.
// This function takes into account order of bytes specified in inf.mf

idaman ulonglong ida_export get_full_word(ea_t ea);


// Get two wide words (128-bit) of the program at 'ea'
// Some processors may access more than 8bit quantity at an address.
// These processors have 32-bit byte organization from the IDA's point of view.
// This function takes into account order of bytes specified in inf.mf
// Note: this function works incorrectly if ph.nbits > 16

idaman ulonglong ida_export get_full_long(ea_t ea);


// Get 8 bits of the program at 'ea'
// The main usage of this function is to iterate range of bytes.
// Here is an example:
//      ulong v;
//      int nbit = 0;
//      for ( .... ) {
//        uchar byte = get_8bit(ea,v,nbit);
//        ...
//      }
// 'ea' is incremented each time when a new byte is read.
// In the above example, it will be incremented in the first loop iteration.

idaman uchar ida_export get_8bit(ea_t &ea,ulong &v,int &nbit);


// Get 16bits of the program at 'ea'
// If the current processor has 16-bit byte, return 1 byte (getFullByte())
// Otherwise return getWord()

idaman ulong ida_export get_16bit(ea_t ea);


// Get not more than 32bits of the program at 'ea'
// Depending on the ph.nbits, returns 32 bit value
//   if ( nbits <= 8 ) return get_long(ea);
//   if ( nbits <= 16) return get_full_word(ea);
//   return get_full_byte(ea);

idaman ulong ida_export get_32bit(ea_t ea);


// Get original byte value (that was before patching)
// This function works for wide byte processors too.

idaman ulong ida_export get_original_byte(ea_t ea);


// Get original word value (that was before patching)
// This function works for wide byte processors too.
// This function takes into account order of bytes specified in inf.mf

idaman ulonglong ida_export get_original_word(ea_t ea);


// Get original long value (that was before patching)
// This function works for wide byte processors too.
// This function takes into account order of bytes specified in inf.mf

idaman ulonglong ida_export get_original_long(ea_t ea);


// Set value of one byte of the program.
// This function works for wide byte processors too.
//      ea - linear address
//      x  - byte value
// Note: The original value of the byte is completely lost and can't 
// be recovered by the get_original_byte() function.

idaman void ida_export put_byte(ea_t ea,ulong x);

// Set value of one word of the program.
// This function takes into account order of bytes specified in inf.mf
// This function works for wide byte processors too.
//      ea - linear address
//      x  - word value
// Note: The original value of the word is completely lost and can't 
// be recovered by the get_original_word() function.

idaman void ida_export put_word(ea_t ea,ulonglong x);


// Set value of one dword of the program.
// This function takes into account order of bytes specified in inf.mf
// This function works for wide byte processors too.
//      ea - linear address
//      x  - dword value
// Note: The original value of the dword is completely lost and can't 
// be recovered by the get_original_long() function.

idaman void ida_export put_long(ea_t ea,ulonglong x);


// Set value of one qword (8 bytes) of the program.
// This function takes into account order of bytes specified in inf.mf
// This function works for wide byte processors too.
//      ea - linear address
//      x  - qword value

idaman void ida_export put_qword(ea_t ea,ulonglong x);


// Patch a byte of the program. The original value of the byte is saved
// and can be obtained by get_original_byte() function.
// This function works for wide byte processors too.

idaman void ida_export patch_byte(ea_t ea,ulong x);


// Patch a word of the program. The original value of the word is saved
// and can be obtained by get_original_word() function.
// This function works for wide byte processors too.
// This function takes into account order of bytes specified in inf.mf

idaman void ida_export patch_word(ea_t ea,ulonglong x);


// Patch a dword of the program. The original value of the dword is saved
// and can be obtained by get_original_long() function.
// This function DOESN'T work for wide byte processors.
// This function takes into account order of bytes specified in inf.mf

idaman void ida_export patch_long(ea_t ea,ulonglong x);


// Add a value to one byte of the program.
// This function works for wide byte processors too.
//      ea     - linear address
//      value  - byte value

idaman void ida_export add_byte(ea_t ea,ulong value);


// Add a value to one word of the program.
// This function works for wide byte processors too.
// This function takes into account order of bytes specified in inf.mf
//      ea     - linear address
//      value  - byte value

idaman void ida_export add_word(ea_t ea,ulonglong value);


// Add a value to one dword of the program.
// This function works for wide byte processors too.
// This function takes into account order of bytes specified in inf.mf
//      ea     - linear address
//      value  - byte value
// Note: this function works incrrectly if ph.nbits > 16

idaman void ida_export add_long(ea_t ea,ulonglong value);


// Get the specified number of bytes of the program into the buffer.
//       ea - linear address
//       buf - buffer to hold bytes
//       size - size of buffer in normal 8-bit bytes (sizeof(buf))
// returns: 1-ok
//          0-failure
//            (out of program address space or uninited bytes, for example)

idaman bool ida_export get_many_bytes(ea_t ea,void *buf,int size);


// Modify the specified number of bytes of the program.
// This function does not save the original values of bytes.
// (this function is for the kernel only)
//       ea - linear address
//       buf - buffer with new values of bytes
//       size - size of buffer in normal 8-bit bytes (sizeof(buf))
// See also patch_many_bytes() function.

idaman void ida_export put_many_bytes(ea_t ea,const void *buf,int size);


// Patch the specified number of bytes of the program.
// Original values of bytes are saved and are available with get_original...()
// functions.
// (this function is for the kernel only)
//       ea - linear address
//       buf - buffer with new values of bytes
//       size - size of buffer in normal 8-bit bytes (sizeof(buf))
// See also put_many_bytes() function.

idaman void ida_export patch_many_bytes(ea_t ea,const void *buf,int size);


//-------------------------------------------------------------------------
//      Each byte of the program may be in one of four states:
//        - unexplored
//        - start of instruction
//        - start of data
//        - second, third (tail) byte of instruction or data.
//      Initially all bytes of the program are unexplored.
//      IDA modifies flags and doing so converts bytes to instructions
//      and data.

#define MS_CLS  0x00000600L             // Mask for typing
#define FF_CODE 0x00000600L             // Code ?
#define FF_DATA 0x00000400L             // Data ?
#define FF_TAIL 0x00000200L             // Tail ?
#define FF_UNK  0x00000000L             // Unknown ?

// Does flag denote start of an instruction?

inline bool idaapi isCode(flags_t F)  { return (F & MS_CLS) == FF_CODE; }


// Does flag denote start of data?

inline bool idaapi isData(flags_t F)  { return (F & MS_CLS) == FF_DATA; }


// Does flag denote tail byte?

inline bool idaapi isTail(flags_t F)  { return (F & MS_CLS) == FF_TAIL; }


// Does flag denote unexplored byte?

inline bool idaapi isUnknown(flags_t F){return (F & MS_CLS) == FF_UNK;  }


// Does flag denote start of instruction OR data?

inline bool idaapi isHead(flags_t F)  { return (F & FF_DATA) != 0; }


// Convert item (instruction/data) to unexplored bytes
// The whole item (including the head and tail bytes) will be destroyed
// It is allowed to pass any address in the item to this function
//      expand - propogate undefined items, for example removing an instruction
//               removes all references to the next instruction, then plan
//               to convert to unexplored the next instruction too.

idaman void ida_export do_unknown(ea_t ea, bool expand);

// Convert range of addresses to unexplored bytes
// The whole items (including the head and tail bytes) will be destroyed
//      ea     - starting linear address
//      size   - number of bytes in the area to be undefined
//      expand - propogate undefined items, for example removing an instruction
//               removes all references to the next instruction, then plan
//               to convert to unexplored the next instruction too.

idaman void ida_export do_unknown_range(ea_t ea, size_t size, bool expand);


//-------------------------------------------------------------------------
// Manual instructions (they are used to completely override an automatically
// generated instruction by a user specified string).

// Is the instruction overridden?
//      ea - linear address of the instruction or data item

idaman bool ida_export is_manual_insn(ea_t ea);        // Is the instruction overridden?


// Retrieve the user-specified string for the manual instruction
//      ea       - linear address of the instruction or data item
//      buf      - the input buffer for the string
//                 if NULL, the buffer will be allocated in heap
//      bufsize  - size of the buffer if buf != NULL
//                 bufsize may be NULL
// returns: NULL - no user-specified string

idaman char *ida_export get_manual_insn(ea_t ea,char *buf,ulong bufsize);
                                // Get the user-specified instruction string


// Set manual instruction string
//      ea - linear address of the instruction or data item
//      manual_insn -   ""   - delete manual string
//                      NULL - do nothing
// If "manual_insn" is equal to an empty string, then the
// manual instruction string will be deleted

idaman void ida_export set_manual_insn(ea_t ea,const char *manual_insn); // Set user-speficied string


//-------------------------------------------------------------------------
//
//      Flags keep information common to all four states of bytes.
//      This information will not be automatically discarded during
//      transitions between different states.
//

#define MS_COMM  0x000FF800L            // Mask of common bits
#define FF_COMM  0x00000800L            // Has comment ?
#define FF_REF   0x00001000L            // has references
#define FF_LINE  0x00002000L            // Has next or prev lines ?
#define FF_NAME  0x00004000L            // Has name ?
#define FF_LABL  0x00008000L            // Has dummy name?
#define FF_FLOW  0x00010000L            // Exec flow from prev instruction
#define FF_SIGN0 0x00020000L            // Inverted signness of operand 0
#define FF_SIGN1 0x00040000L            // Inverted signness of operand 1
#define FF_VAR   0x00080000L            // is variable byte?

// Does the previous instruction exist and pass execution flow to the current
// byte?

inline bool idaapi isFlow(flags_t F)     { return (F & FF_FLOW) != 0; }


// Is the current byte marked as variable? (this is not used by IDA itself and
// may become obsolete, please don't use it)

inline bool idaapi isVar(flags_t F)      { return (F & FF_VAR ) != 0; }


// Does the current byte have additional anterior or posterior lines?

inline bool idaapi hasExtra(flags_t F)   { return (F & FF_LINE) != 0; }


// Does the current byte have an indented comment?

inline bool idaapi has_cmt(flags_t F)    { return (F & FF_COMM) != 0; }


// Does the current byte have cross-references to it?

inline bool idaapi hasRef(flags_t F)     { return (F & FF_REF)  != 0; }


// Does the current byte have non-trivial (non-dummy) name?

inline bool idaapi has_name(flags_t F)   { return (F & FF_NAME) != 0; }


// Does the current byte have dummy (auto-generated, with special prefix) name?

#define FF_ANYNAME      (FF_LABL|FF_NAME)
inline bool idaapi has_dummy_name(flags_t F){ return (F & FF_ANYNAME) == FF_LABL; }


// Does the current byte have auto-generated (no special prefix) name?

inline bool idaapi has_auto_name(flags_t F){ return (F & FF_ANYNAME) == FF_ANYNAME; }


// Does the current byte have any name?

inline bool idaapi has_any_name(flags_t F){ return (F & FF_ANYNAME) != 0; }


// Does the current byte have user-specified name?

inline bool idaapi has_user_name(flags_t F){ return (F & FF_ANYNAME) == FF_NAME; }


// signness deals with the form of operands of the current instruction/data.
// inverted signness means the following:
//    if the bit is clear       |then when the bit is set
//    and the output is         |the output should be:
//    ------------              |----------
//    unsigned                  |signed
//    signed                    |unsigned
//

// Should signness of the first operand inverted during output?

inline bool idaapi inverted_signness0(flags_t F){ return (F & FF_SIGN0) != 0; }


// Should signness of other operands inverted during output?

inline bool idaapi inverted_signness1(flags_t F){ return (F & FF_SIGN1) != 0; }


// Should signness of n-th operand inverted during output?
// allowed values of n: 0-first operand, 1-other operands

idaman bool ida_export inverted_signness(flags_t F,int n);


// Toggle signness of the first operand

inline void idaapi toggle_signness0(ea_t ea) { setFlags(ea,getFlags(ea)^FF_SIGN0); }


// Toggle signness of the other operands

inline void idaapi toggle_signness1(ea_t ea) { setFlags(ea,getFlags(ea)^FF_SIGN1); }


// Toggle signness of n-th operand
// allowed values of n: 0-first operand, 1-other operands

inline bool idaapi toggle_signness(ea_t ea,int n)
  { if ( n == 0 ) toggle_signness0(ea); else toggle_signness1(ea); return 1;}


// get bits for signness (this function is used by kernel only)

inline flags_t signflag(void) { return FF_SIGN0|FF_SIGN1; }


// Work with binary negation of operands
// ash.bnot should be defined in the idp module in order to work
// with this functions

idaman bool ida_export is_bnot(ea_t ea, int n);           // should negate the operand?
idaman bool ida_export set_bnot(ea_t ea, int n);          // set negation bit
idaman bool ida_export clr_bnot(ea_t ea, int n);          // clear negation bit
inline bool idaapi toggle_bnot(ea_t ea, int n)
{
  return (is_bnot(ea,n) ? clr_bnot : set_bnot)(ea,n);
}

// Display leading zeroes in operands
// The global switch for the leading zeroes is in inf.s_genflags
// The leading zeroes doesn't work if the octal numbers start with 0

idaman bool ida_export is_lzero(ea_t ea, int n);          // display leading zeroes?
                                                          // (takes into account inf.s_genflags)
idaman bool ida_export set_lzero(ea_t ea, int n);         // set toggle lzero bit
idaman bool ida_export clr_lzero(ea_t ea, int n);         // clear toggle lzero bit
inline bool idaapi toggle_lzero(ea_t ea, int n)
{
  return (is_lzero(ea,n) ? clr_lzero : set_lzero)(ea,n);
}

// Set the variableness of an address
// The variable addresses are marked with '*' in the disassembly
//      ea    - linear address
//      isvar - 0: clear 'variable' mark
//              1: set 'variable' mark

idaman void ida_export doVar(ea_t ea,bool isvar=true);


//-------------------------------------------------------------------------
//
//      Type of instruction/data operands is kept in flags too.
//      IDA keeps 2 type values:
//        - type of the first operand
//        - type of other operands (I will call this 'type of second operand'
//          althrough it is apllied to third, fourth operands too)
//      For data bytes, only the first type is used (i.e. all elements of
//      an array have the same type). Type of second operand is not used for
//      data bytes.
//

#define MS_0TYPE 0x00F00000L            // Mask for 1st arg typing
#define FF_0VOID 0x00000000L            // Void (unknown)?
#define FF_0NUMH 0x00100000L            // Hexadecimal number?
#define FF_0NUMD 0x00200000L            // Decimal number?
#define FF_0CHAR 0x00300000L            // Char ('x')?
#define FF_0SEG  0x00400000L            // Segment?
#define FF_0OFF  0x00500000L            // Offset?
#define FF_0NUMB 0x00600000L            // Binary number?
#define FF_0NUMO 0x00700000L            // Octal number?
#define FF_0ENUM 0x00800000L            // Enumeration?
#define FF_0FOP  0x00900000L            // Forced operand?
#define FF_0STRO 0x00A00000L            // Struct offset?
#define FF_0STK  0x00B00000L            // Stack variable?
#define FF_0FLT  0x00C00000L            // Floating point number?

#define MS_1TYPE 0x0F000000L            // Mask for 2nd arg typing
#define FF_1VOID 0x00000000L            // Void (unknown)?
#define FF_1NUMH 0x01000000L            // Hexadecimal number?
#define FF_1NUMD 0x02000000L            // Decimal number?
#define FF_1CHAR 0x03000000L            // Char ('x')?
#define FF_1SEG  0x04000000L            // Segment?
#define FF_1OFF  0x05000000L            // Offset?
#define FF_1NUMB 0x06000000L            // Binary number?
#define FF_1NUMO 0x07000000L            // Octal number?
#define FF_1ENUM 0x08000000L            // Enumeration?
#define FF_1FOP  0x09000000L            // Forced operand?
#define FF_1STRO 0x0A000000L            // Struct offset?
#define FF_1STK  0x0B000000L            // Stack variable?
#define FF_1FLT  0x0C000000L            // Floating point number?

// Is the first operand defined? Initially operand has no type (i.e. void)

inline bool idaapi isDefArg0(flags_t F) { return (F & MS_0TYPE) != FF_0VOID; }


// Is the second operand defined? Initially operand has no type (i.e. void)

inline bool idaapi isDefArg1(flags_t F) { return (F & MS_1TYPE) != FF_1VOID; }


// Is the first operand offset? (example: push offset xxx)

inline bool idaapi isOff0(flags_t F)    { return (F & MS_0TYPE) == FF_0OFF;  }


// Is the second operand offset? (example: mov ax, offset xxx)

inline bool idaapi isOff1(flags_t F)    { return (F & MS_1TYPE) == FF_1OFF;  }


// Is the first operand character constant? (example: push 'a')

inline bool idaapi isChar0(flags_t F)   { return (F & MS_0TYPE) == FF_0CHAR; }


// Is the second operand character constant? (example: mov al, 'a')

inline bool idaapi isChar1(flags_t F)   { return (F & MS_1TYPE) == FF_1CHAR; }


// Is the first operand segment selector? (example: push seg seg001)

inline bool idaapi isSeg0(flags_t F)    { return (F & MS_0TYPE) == FF_0SEG;  }


// Is the second operand segment selector? (example: mov dx, seg dseg)

inline bool idaapi isSeg1(flags_t F)    { return (F & MS_1TYPE) == FF_1SEG;  }


// Is the first operand a symbolic constant (enum member)?

inline bool idaapi isEnum0(flags_t F)   { return (F & MS_0TYPE) == FF_0ENUM;  }


// Is the second operand a symbolic constant (enum member)?

inline bool idaapi isEnum1(flags_t F)   { return (F & MS_1TYPE) == FF_1ENUM;  }


// Is the first operand manually defined? (for kernel only)

inline bool idaapi isFop0(flags_t F)    { return (F & MS_0TYPE) == FF_0FOP;  }


// Is the second operand manually defined? (for kernel only)

inline bool idaapi isFop1(flags_t F)    { return (F & MS_1TYPE) == FF_1FOP;  }


// Is the first operand an offset within a struct?

inline bool idaapi isStroff0(flags_t F) { return (F & MS_0TYPE) == FF_0STRO;  }


// Is the second operand an offset within a struct?

inline bool idaapi isStroff1(flags_t F) { return (F & MS_1TYPE) == FF_1STRO;  }


// Is the first operand a stack variable?

inline bool idaapi isStkvar0(flags_t F) { return (F & MS_0TYPE) == FF_0STK;  }


// Is the second operand a stack variable?

inline bool idaapi isStkvar1(flags_t F) { return (F & MS_1TYPE) == FF_1STK;  }


// Is the first operand a floating point number?

inline bool idaapi isFloat0(flags_t F) { return (F & MS_0TYPE) == FF_0FLT;  }


// Is the second operand a floating point number?

inline bool idaapi isFloat1(flags_t F) { return (F & MS_1TYPE) == FF_1FLT;  }


// Is the first or second operand a number (i.e. binary,octal,decimal or hex?)

idaman bool ida_export isNum0(flags_t F);
idaman bool ida_export isNum1(flags_t F);

//-------------------------------------------------------------------------
//
//      The following 2 masks are used with operand numbers
//
#define OPND_OUTER      0x80            // outer offset base (combined with
                                        //  operand number)
                                        // used only in set,get,del_offset()
                                        // functions
#define OPND_MASK       0x07            // mask for operand number
#define OPND_ALL        OPND_MASK       // all operands

// Examine flags for the specified operand type.
// 'n' may be 0         - first operand
//            1         - second operand
//            OPND_ALL  - both operands: function returns 1 if the first
//                        OR the second operand satisfies the condition

idaman bool ida_export isDefArg(flags_t F,int n);          // is defined?
idaman bool ida_export isOff(flags_t F,int n);             // is offset?
idaman bool ida_export isChar(flags_t F,int n);            // is character constant?
idaman bool ida_export isSeg(flags_t F,int n);             // is segment?
idaman bool ida_export isEnum(flags_t F,int n);            // is enum?
idaman bool ida_export isFop(flags_t F,int n);             // is forced operand? (use is_forced_operand())
idaman bool ida_export isStroff(flags_t F,int n);          // is struct offset?
idaman bool ida_export isStkvar(flags_t F,int n);          // is stack variable?
idaman bool ida_export isFltnum(flags_t F,int n);          // is floating point number?
idaman bool ida_export isNum(flags_t F,int n);             // is number (bin,oct,dec,hex)?
idaman bool ida_export isVoid(ea_t ea,flags_t F,int n);    // is 'void' operand?


// (internal function) change type of operand(s)
//      ea   - linear address
//      type - new flag value (should be got from charflag(), numflag() and
//             similar functions. see below.)
//      n    - number of operand (0,1,-1)
// returns: 1-ok, 0-failed (applied to a tail byte)

idaman bool ida_export set_op_type(ea_t ea,flags_t type,int n);


// (internal function) destroys old type information and returns
// new flags value. this function is called from the kernel only.
//      ea   - linear address
//      type - new flag value (should be got from ....flag() functions)
//      n    - number of operand (0,1,-1)

idaman flags_t ida_export typeflag(ea_t ea,flags_t oldflag,flags_t type,int n);


// set operand type 'segment'
// if applied to unexplored bytes, converts them to 16/32bit word data
//      ea   - linear address
//      n    - number of operand (0,1,-1)
// returns 1-ok, 0-failure

idaman bool ida_export op_seg(ea_t ea,int n);


// set operand type 'enum'
// if applied to unexplored bytes, converts them to 16/32bit word data
//      ea   - linear address
//      n    - number of operand (0,1,-1)
//      id   - id of enum
//      serial - the serial number of the constant in the enumeration
//               usually 0. the serial numbers are used if the enumeration
//               contains several constants with the same value

// returns 1-ok, 0-failure

idaman bool ida_export op_enum(ea_t ea,int n,enum_t id, uchar serial);


// set enum id of 'enum' operand
//      ea   - linear address
//      n    - number of operand (0,1,-1)
//      id   - enumeration id
//      serial - the serial number of the constant in the enumeration
//               usually 0. the serial numbers are used if the enumeration
//               contains several constants with the same value
// this is low level function and shouldn't be used. use op_enum().

idaman void ida_export set_enum_id(ea_t ea, int n, enum_t id, uchar serial);


// get enum id of 'enum' operand
//      ea   - linear address
//      n    - number of operand (0,1,-1)
//      serial - pointer to variable to hold the serial number of the
//               constant in the enumeration
// returns: id of enum or BADNODE

idaman enum_t ida_export get_enum_id(ea_t ea,int n, uchar *serial);


// set operand type 'struct offset'
// if applied to unexplored bytes, converts them to 16/32bit word data
//      ea   - linear address
//      n    - number of operand (0,1,-1)
//      path - structure path (strpath). see nalt.hpp for more info.
//      path_len - length of the structure path
//      delta- struct offset delta. usually 0. denotes the difference
//             between the structure base and the pointer into the structure.
// returns 1-ok, 0-failure

idaman bool ida_export op_stroff(ea_t ea, int n, const tid_t *path, int path_len, long delta);


// set struct path for operand
//      ea   - linear address
//      n    - number of operand (0,1,-1)
//      path - structure path (strpath). see nalt.hpp for more info.
//      path_len - length of the structure path
//      delta- struct offset delta
// returns 1-ok, 0-failure

idaman bool ida_export set_stroff_path(ea_t ea, int n, const tid_t *path, int plen, long delta);


// get struct path of operand
//      ea   - linear address
//      n    - number of operand (0,1,-1)
//      path - buffer for structure path (strpath). see nalt.hpp for more info.
//      delta- struct offset delta
// returns: length of strpath

idaman int ida_export get_stroff_path(ea_t ea, int n, tid_t *path, long *delta);


// delete struct path information
//      ea   - linear address
//      n    - number of operand (0,1,-1)
// returns: true

idaman bool ida_export del_stroff_path(ea_t ea, int n);


// set operand type 'stack variable'
//      ea   - linear address
//      n    - number of operand (0,1,-1)
// returns 1-ok, 0-failure
// should be applied to an instruction within a function
// should be applied after creating a stack var using ua_stkvar()

idaman bool ida_export op_stkvar(ea_t ea,int n);


// Set forced operand
//      ea - linear address
//      n  - number of operand (0,1,2)
//      op - text of operand
// returns: 1-ok, 0-failure

idaman bool ida_export set_forced_operand(ea_t ea,int n,const char *op);


// Get forced operand
//      ea - linear address
//      n  - number of operand (0,1,2)

idaman char *ida_export get_forced_operand(ea_t ea,int n);


// Is operand manually defined?
//      ea - linear address
//      n  - number of operand (0,1,2)

idaman bool ida_export is_forced_operand(ea_t ea,int n);


//-------------------------------------------------------------------------
//      Type information bits for flags
//      Values of these functions are used as input to set_op_type() function

inline flags_t idaapi charflag(void) { return FF_1CHAR|FF_0CHAR; }
inline flags_t idaapi offflag (void) { return FF_1OFF |FF_0OFF ; }
inline flags_t idaapi enumflag(void) { return FF_1ENUM|FF_0ENUM; }
inline flags_t idaapi stroffflag(void) { return FF_1STRO|FF_0STRO; }
inline flags_t idaapi stkvarflag(void) { return FF_1STK|FF_0STK; }
inline flags_t idaapi fltflag(void)  { return FF_1FLT |FF_0FLT;  }
inline flags_t idaapi segflag (void) { return FF_1SEG |FF_0SEG;  }
idaman flags_t ida_export numflag(void); // returns number of default base (bin,oct,dec,hex)
                                // the following 4 functions return number
                                // flag of the specified base, regardless
                                // of the current default base for the current
                                // processor. Better to use numflag(), than to
                                // use these functions:
inline flags_t idaapi hexflag (void) { return FF_1NUMH|FF_0NUMH; }
inline flags_t idaapi decflag (void) { return FF_1NUMD|FF_0NUMD; }
inline flags_t idaapi octflag (void) { return FF_1NUMO|FF_0NUMO; }
inline flags_t idaapi binflag (void) { return FF_1NUMB|FF_0NUMB; }

// the following functions set operand type.
// if they are applied to unexplored bytes, they convert them
//                              no segment   : fail
//                              16bit segment: to 16bit word data
//                              32bit segment: to dword
//      ea   - linear address
//      n    - number of operand (0,1,-1)
// return 1-ok, 0-failure

inline bool idaapi op_chr(ea_t ea,int n) { return set_op_type(ea,charflag(),n); }
inline bool idaapi op_num(ea_t ea,int n) { return set_op_type(ea,numflag (),n); }
inline bool idaapi op_hex(ea_t ea,int n) { return set_op_type(ea,hexflag (),n); }
inline bool idaapi op_dec(ea_t ea,int n) { return set_op_type(ea,decflag (),n); }
inline bool idaapi op_oct(ea_t ea,int n) { return set_op_type(ea,octflag (),n); }
inline bool idaapi op_bin(ea_t ea,int n) { return set_op_type(ea,binflag (),n); }
inline bool idaapi op_flt(ea_t ea,int n) { return set_op_type(ea,fltflag (),n); }

// Remove type information about the specified operand from the database
//      ea   - linear address
//      n    - number of operand (0,1,-1)
// returns: 1

idaman bool ida_export noType(ea_t ea,int n);

// Get default base of number for the current processor
// returns: 2,8,10,16

idaman int ida_export getDefaultRadix(void);


// Get radix of the operand, in: flags
//      F    - flags
//      n    - number of operand (0,1,-1)
// returns: 2,8,10,16
// if the operand is not a number, returns getDefaultRadix()

idaman int ida_export getRadix(flags_t F,int n);


// Get radix of the operand, in: address
//      ea   - linear address
//      n    - number of operand (0,1,-1)
// returns: 2,8,10,16
// if the operand is not a number, returns getDefaultRadix()

idaman int ida_export getRadixEA(ea_t ea,int n);


//-------------------------------------------------------------------------
//
//      Bits for DATA bytes
//      They specify type of data (byte, word, dword, etc)
//

#define DT_TYPE 0xF0000000L             // Mask for DATA typing

#define FF_BYTE     0x00000000L         // byte
#define FF_WORD     0x10000000L         // word
#define FF_DWRD     0x20000000L         // double word
#define FF_QWRD     0x30000000L         // quadro word
#define FF_TBYT     0x40000000L         // tbyte
#define FF_ASCI     0x50000000L         // ASCII ?
#define FF_STRU     0x60000000L         // Struct ?
#define FF_OWRD     0x70000000L         // octaword (16 bytes)
#define FF_FLOAT    0x80000000L         // float
#define FF_DOUBLE   0x90000000L         // double
#define FF_PACKREAL 0xA0000000L         // packed decimal real
#define FF_ALIGN    0xB0000000L         // alignment directive

// The following functions return bit masks to be used as input for doData()

inline flags_t idaapi codeflag(void) { return FF_CODE; }
inline flags_t idaapi byteflag(void) { return FF_DATA|FF_BYTE; }
inline flags_t idaapi wordflag(void) { return FF_DATA|FF_WORD; }
inline flags_t idaapi dwrdflag(void) { return FF_DATA|FF_DWRD; }
inline flags_t idaapi qwrdflag(void) { return FF_DATA|FF_QWRD; }
inline flags_t idaapi owrdflag(void) { return FF_DATA|FF_OWRD; }
inline flags_t idaapi tbytflag(void) { return FF_DATA|FF_TBYT; }
inline flags_t idaapi asciflag(void) { return FF_DATA|FF_ASCI; }
inline flags_t idaapi struflag(void) { return FF_DATA|FF_STRU; }
inline flags_t idaapi alignflag(void) { return FF_DATA|FF_ALIGN; }
inline flags_t idaapi floatflag(void) { return FF_DATA|FF_FLOAT; }
inline flags_t idaapi doubleflag(void) { return FF_DATA|FF_DOUBLE; }
inline flags_t idaapi packrealflag(void) { return FF_DATA|FF_PACKREAL; }

// Convert to data array
// If 'ea' is unexplored, then define array of bytes
//      ea   - linear address
//      size - size of array in bytes. should be divisible by the size of
//             current item.
//      tid  - type id. If the current item is a structure instance,
//             then tid is structure id. Otherwise should be BADNODE.
// return 1-ok, 0-failure

idaman bool ida_export doData(ea_t ea,ulong size,tid_t tid);


// Convert to data (byte,word,dword,etc)
//      ea   - linear address
//      dataflag - type of data. Value of function byteflag(), wordflag(), etc.
//      size - size of array in bytes. should be divisible by the size of
//             one item of the specified type.
//      tid  - type id. If the specified type is a structure,
//             then tid is structure id. Otherwise should be BADNODE.
// return 1-ok, 0-failure

idaman bool ida_export do_data_ex(ea_t ea,flags_t dataflag,ulong size,tid_t tid);


// Convert to specified data type. (convenience functions)
//      ea   - linear address
//      size - size of array in bytes. should be dividable to size of
//             one item of the specified type.
// return 1-ok, 0-failure

idaman bool ida_export doByte(ea_t ea,ulong size);             // 1-byte
idaman bool ida_export doWord(ea_t ea,ulong size);             // 2-byte
idaman bool ida_export doDwrd(ea_t ea,ulong size);             // 4-byte
idaman bool ida_export doQwrd(ea_t ea,ulong size);             // 8-byte
idaman bool ida_export doOwrd(ea_t ea,ulong size);             // 16-byte
idaman bool ida_export doTbyt(ea_t ea,ulong size);             // ?-byte (defined in IDP)
idaman bool ida_export doFloat(ea_t ea,ulong size);            // 4-byte
idaman bool ida_export doDouble(ea_t ea,ulong size);           // 8-byte
idaman bool ida_export doPackReal(ea_t ea,ulong size); // ?-byte (defined in IDP)
idaman bool ida_export doASCI(ea_t ea,ulong size);              // don't use this! use make_ascii_string()
idaman bool ida_export doStruct(ea_t ea,ulong size,tid_t tid);
idaman bool ida_export doAlign(ea_t ea,ulong length,int alignment);
                                                // alignment: 0 or 2..32
                                                // if it is 0, is will be calculated
idaman int  ida_export calc_min_align(ulong length);    // returns: 1..32
idaman int  ida_export calc_max_align(ea_t endea);     // returns: 0..32
idaman bool ida_export do16bit(ea_t ea,ulong length);  // convert to 16-bit quanztity
                                                // (depending on the byte size)


// Check flags for the specified data type

inline bool idaapi isByte  (flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_BYTE; }
inline bool idaapi isWord  (flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_WORD; }
inline bool idaapi isDwrd  (flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_DWRD; }
inline bool idaapi isQwrd  (flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_QWRD; }
inline bool idaapi isOwrd  (flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_OWRD; }
inline bool idaapi isTbyt  (flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_TBYT; }
inline bool idaapi isFloat (flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_FLOAT; }
inline bool idaapi isDouble(flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_DOUBLE; }
inline bool idaapi isPackReal(flags_t F) { return isData(F) && (F & DT_TYPE) == FF_PACKREAL; }
inline bool idaapi isASCII (flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_ASCI; }
inline bool idaapi isStruct(flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_STRU; }
inline bool idaapi isAlign(flags_t F)    { return isData(F) && (F & DT_TYPE) == FF_ALIGN; }

inline bool idaapi is_same_data_type(flags_t F1, flags_t F2) { return ((F1 ^ F2) & DT_TYPE) == 0; }


// determine maximum length of ascii string
//      ea           - starting address
//      strtype      - string type. ASCSTR_... constant (see nalt.hpp)
//      ignore_heads - 1: don't stop if another data item is encountered
//                     0: take into account other data items

idaman size_t ida_export get_max_ascii_length(ea_t ea, long strtype, bool ignore_heads=false);


// Get contents of ascii string
// This function returns the displayed part of the string
// It works even if the string is not created in the database yet.
//      ea      - linear address of the string
//      len     - length of the string
//      type    - type of the string
//      buf     - output buffer
//      bufsize - size of output buffer
// returns 1-ok, 0-ascii string is too long and was truncated

idaman bool ida_export get_ascii_contents(ea_t ea, size_t len, long type, char *buf, size_t bufsize);


// convert to ascii string and give a meaningful name
// 'start' may be higher than 'end', the kernel will swap them in this case
//      start - starting address
//      len   - length of the string
//              if 0, then get_max_ascii_length() will be used
//              to determine the length
//      strtype - string type. ASCSTR_... constant (see nalt.hpp)
// returns: 1-ok,0-failure

idaman bool ida_export make_ascii_string(ea_t start, size_t len, long strtype);


// print the string type name
//      long - the string type
//      buf  - the output buffer. 20 bytes is enough
// returns: ptr to buf

idaman char *ida_export print_ascii_string_type(char *buf, long strtype);


// Get additional information about a type
//      ea      - linear address of item
//      n       - number of operand, 0 or 1
//      flags   - flags of the item
//      buf     - buffer to receive the result. may not be NULL
// Returns: NULL - no additional type information

idaman typeinfo_t *ida_export get_typeinfo(ea_t ea, int n, flags_t flags, typeinfo_t *buf);


// Set additional information about a data type
//      ea      - linear address of item
//      n       - number of operand, 0 or 1
//      flags   - flags of the item
//      ti      - additional type information
// This function is a low level one. Only the kernel should use it.
// Returns: 1-ok, 0-ti is NULL while it shouldn't be NULL

idaman bool ida_export set_typeinfo(ea_t ea, int n, flags_t flag, const typeinfo_t *ti);


// Delete additional information about a data type
//      ea      - linear address of item
//      n       - number of operand, 0 or 1
//      flags   - flags of the item
// This function is a low level one. Only the kernel should use it.

void del_typeinfo(ea_t ea, flags_t flag);
void del_operand_typeinfo(ea_t ea, int n, flags_t flag);


// get size of data type specified in flags 'F'.
//      F    - flags
//      ti   - additional information about the data type. For example,
//             if the current item is a structure instance,
//             then ti->tid is structure id. Otherwise is ignored (may be NULL).
// returns:     byte - 1
//              word - 2
//              etc.
// If flags doesn't specify a data, then return 1

idaman ulong ida_export get_data_type_size(flags_t flags,const typeinfo_t *ti);
inline ulong idaapi get_data_type_size_by_flags(ea_t ea, flags_t flags)
{
  typeinfo_t ti;
  return get_data_type_size(flags, get_typeinfo(ea, 0, flags, &ti));
}


// Can define item (instruction/data) of the specified 'length'
// starting at 'ea'?
//      flags - if not 0, then the kernel will ignore the data types
//              specified by the flags and destroy them. For example:
//                 1000 dw 5
//                 1002 db 5 ; undef
//                 1003 db 5 ; undef
//                 1004 dw 5
//                 1006 dd 5
//              can_define_item(1000,6,0) - false because of dw at 1004
//              can_define_item(1000,6,wordflag()) - true, word at 1004 is destroyed
// Returns: 1-yes, 0-no
// This function may return 0 if:
//      - a new item would cross segment boundaries
//      - a new item would overlap with existing items (except items specified by 'flags')
// NOTE: if there is an item starting at 'ea', this function ignores it
// NOTE: this function converts to unexplored all encountered data items
//       with fixup information. Should be fixed in the future.

idaman bool ida_export can_define_item(ea_t ea, ulong length, flags_t flags);


//-------------------------------------------------------------------------
//
//      Bits for CODE bytes
//      They specify characteristics of instructions
//

#define MS_CODE 0xF0000000L
#define FF_FUNC 0x10000000L             // function start?
//              0x20000000L             // not used
#define FF_IMMD 0x40000000L             // Has Immediate value ?
#define FF_JUMP 0x80000000L             // Has jump table or switch_info?

// Convert to an instruction
// (internal function, should not be used in modules, never)
// use ua_code() instead.
//      ea     - linear address
//      length - length of instruction
// Returns: 1-ok, 0-failure

bool doCode(ea_t ea,int length);


// Has immediate value?

inline bool idaapi isImmd(flags_t F)      { return isCode(F) && (F & FF_IMMD) != 0; }


// Is function start?

inline bool idaapi isFunc(flags_t F)      { return isCode(F) && (F & FF_FUNC) != 0; }


// Set 'has immediate operand' flag

idaman void ida_export doImmd(ea_t ea);


// Clear 'has immediate operand' flag

idaman void ida_export noImmd(ea_t ea);


//-------------------------------------------------------------------------
//
//      Bits for TAIL bytes
//      Modules don't change or use tail bytes, so all the following
//      definitions are for the kernel only.
//

#define MS_TAIL 0xFFF00000LU            // Mask of tail byte bits
#define TL_TSFT (4*5)                   // number of bits to shift to get
                                        // tail offsets
#define TL_TOFF MS_TAIL                 // Offset to next NOT-tail byte
#define MAX_TOFF (TL_TOFF>>TL_TSFT)     // Max offset can be written to flags

inline ushort idaapi gettof(flags_t F) { return ushort((F & TL_TOFF) >> TL_TSFT); }

//--------------------------------------------------------------------------
//      I N D E N T E D  C O M M E N T S
//--------------------------------------------------------------------------

// Set an indented comment
//      ea     - linear address
//      comm   - comment string (max len MAXSTR)
//      rptble - is repeatable?
// returns: 1-ok, 0-failure

idaman bool ida_export set_cmt(ea_t ea,const char *comm,bool rptble);


// Get an indented comment
//      ea     - linear address. may point to tail byte, the function
//               will find start of the item
//      rptble - get repeatable comment?
// returns: comment or NULL

idaman char *ida_export get_cmt(ea_t ea,bool rptble);


// Get a repeatable comment of any type (indented or function comment)
// This function is used to display an indented comment if no regular
// (non-repeatable) comment is present.
//      ea     - linear address. may point to tail byte, the function
//               will find start of the item
// returns: comment or NULL

idaman char *ida_export get_rpt_cmt(ea_t ea);


// Get any indented comment (regular or repeatable indented or function)
// This function is used to display an indented comment for an item.
// It looks for a regular comment and calls get_rpt_cmt() if it is not found.
//      ea      - linear address
//      cmttype - will contain color of the comment. The color depends on
//                the type of the comment.
// returns: comment or NULL

idaman char *ida_export get_any_cmt(ea_t ea,color_t *cmttype);


// Append to an indented comment
// Creates a new comment if none exists.
// Appends a newline character and the specified string otherwise.
//      ea      - linear address
//      str     - comment string to append
//      rptble  - append to repeatable comment?
// returns: 1-ok, 0-failure

idaman bool ida_export append_cmt(ea_t ea,const char *str,bool rptble);


// Delete an indented comment attached to an instruction
// when the instruction is deleted

extern bool del_code_comments;


//--------------------------------------------------------------------------
//      S E A R C H  F U N C T I O N S
//--------------------------------------------------------------------------
// Find forward a byte with the specified value (only 8-bit value from the database)
//      ea         - linear address
//      size       - number of bytes to inspect
//      value      - value to find
//      sense_case - case sensitive search
// returns: address of byte or BADADDR

idaman ea_t ida_export find_byte(ea_t sEA,ulong size,uchar value,bool sense_case);


// Find reverse a byte with the specified value (only 8-bit value from the database)
//      ea         - linear address (it is not inspected)
//      size       - number of bytes to inspect
//      value      - value to find
//      sense_case - case sensitive search
// returns: address of byte or BADADDR

idaman ea_t ida_export find_byter(ea_t sEA,ulong size,uchar value,bool sense_case);


// search for a string in the program
//      startEA - linear address, start of area to search
//      endEA   - linear address, end of area to search (inclusive)
//      image   - stream of bytes to search
//      mask    - array of 1/0 bytes, it's length is 'len'. 1 means to perform
//                the comparision of the corresponding byte. 0 means not to perform.
//                if mask == NULL, then all bytes of 'image' will be compared.
//      len     - length of srchStr in bytes
//      step    - direction of search
//      flags   - search flags. combination of:
//                  BIN_SEARCH_CASE    - case sensitive
//                  BIN_SEARCH_NOCASE  - case insensitive
//                  BIN_SEARCH_NOBREAK - don't check for Ctrl-Break
// returns BADADDR (if pressed Ctrl-Break or not found) or string address.

idaman ea_t ida_export bin_search(
                 ea_t startEA,         // area to search
                 ea_t endEA,
                 const uchar *image,   // string to search
                 const uchar *mask,    // comparision mask
                 int len,              // length of string to search
                 int step,             // direction:
#define BIN_SEARCH_FORWARD      1
#define BIN_SEARCH_BACKWARD     (-1)
                 int flags);
#define BIN_SEARCH_CASE         0x01
#define BIN_SEARCH_NOCASE       0x00
#define BIN_SEARCH_NOBREAK      0x02


// Compare 'len' bytes of the program starting from 'ea' with 'image'.
//      ea         - linear address
//      image      - bytes to compare with
//      len        - length of block to compare in bytes.
//      sense_case - case-sensitive comparison?
//      mask       - array of 1/0 bytes, it's length is 'len'. 1 means to perform
//                   the comparision of the corresponding byte. 0 means not to perform.
//                   if mask == NULL, then all bytes of 'image' will be compared.
//                   if mask == SKIP_FF_MASK than 0xFF bytes will be skipped
// Returns: 1- equal, 0-no

idaman bool ida_export equal_bytes(ea_t ea,const uchar *image,const uchar *mask,
                                                        int len,bool sense_case);
#define SKIP_FF_MASK  ((const uchar *)0xFF)


//--------------------------------------------------------------------------
idaman const ulong ida_export_data power2[32];    // Powers of 2, from 2^0 to 2^31
idaman const ulong ida_export_data lowbits[33];   // Low-order bits, from 0 to 32


//--------------------------------------------------------------------------
//      D E B U G G E R  M E M O R Y  F U N C T I O N S  F O R  U I
//--------------------------------------------------------------------------

// Set the memory information source for IDA kernel
// This function allows the kernel to use information coming from somewhere
// else than the database (from the debugger, for example)
//   dbg_get_memory_config - returns current memory configuration
//                           in the dynamic memory allocated by qalloc()
//                           The kernel will qfree() is automatically
//                           n - number of area_t elements in the answer
//                           If dbg_get_memory_config == NULL, then the debugged
//                           process memory is not used
//   memory_read           - read bytes from the debugged process memory
//   memory_write          - write bytes to the debugged process memory

idaman void ida_export set_dbgmem_source(
        area_t *(idaapi*dbg_get_memory_config)(int *n),
        int (idaapi*memory_read) (ea_t ea, void *buffer, int size),
        int (idaapi*memory_write)(ea_t ea, const void *buffer, int size));

// Invalidate the debugged process memory configuration
// Call this function if the debugged process might have changed its memory
// layout (allocated more memory, for example)

idaman void ida_export invalidate_dbgmem_config(void);


// Invalidate the debugged process memory contents
// Call this function each time the process has been stopped

idaman void ida_export invalidate_dbgmem_contents(void);


// Is the debugger currently running?

idaman bool ida_export is_debugger_on(void);


//------------------------------------------------------------------------
//      H I D D E N  A R E A S
//------------------------------------------------------------------------

// Hidden areas - address ranges which can be replaced by their descriptions
// There is also a possibility to hide individual items completely (nalt.hpp, hide_item)

struct hidden_area_t : public area_t
{
  // After modifying any of these fields please call update_hidden_area()
  char *description;    // description to display if the area is collapsed
  char *header;         // header lines to display if the area is expanded
  char *footer;         // footer lines to display if the area is expanded
  bool visible;         // the area state
};

idaman areacb_t ida_export_data hidden_areas;

// Update hidden area information in the database
// You can not use this function to change the area boundaries
//      ha - area to update
// returns: 1-ok,0-failure

inline bool idaapi update_hidden_area(hidden_area_t *ha)
  { invalidate_visea_cache(); return hidden_areas.update(ha) != 0; }

// Mark a range of addresses as hidden
//      ea1         - linear address of start of the address range
//      ea2         - linear address of end of the address range
//      description, header, footer - area parameters
// The area will be created in the invisible state
// returns: 1-ok,0-failure

idaman bool ida_export add_hidden_area(ea_t ea1,
                                       ea_t ea2,
                                       const char *description,
                                       const char *header,
                                       const char *footer);


// Get pointer to hidden area structure, in: linear address
//      ea - any address in the hidden area

inline hidden_area_t *idaapi get_hidden_area(ea_t ea)
  { return (hidden_area_t *)hidden_areas.get_area(ea); }


// Get pointer to hidden area structure, in: number of hidden area
//      n - number of hidden area, is in range 0..get_hidden_area_qty()-1

inline hidden_area_t *idaapi getn_hidden_area(int n)
  { return (hidden_area_t *)hidden_areas.getn_area(n); }


// Get number of hidden areas

inline int idaapi get_hidden_area_qty(void)
  { return hidden_areas.get_area_qty(); }


// Get number of a hidden area
//      ea - any address in the hidden area
// Returns number of hidden area (0..get_hidden_area_qty()-1)

inline int idaapi get_hidden_area_num(ea_t ea)
  { return hidden_areas.get_area_num(ea); }


// Get pointer to previous hidden area
//      ea - any address in the program
// Returns ptr to hidden area or NULL if previous hidden area doesn't exist

inline hidden_area_t *idaapi get_prev_hidden_area(ea_t ea)
  { return getn_hidden_area(hidden_areas.get_prev_area(ea)); }


// Get pointer to next hidden area
//      ea - any address in the program
// Returns ptr to hidden area or NULL if next hidden area doesn't exist

inline hidden_area_t *idaapi get_next_hidden_area(ea_t ea)
  { return getn_hidden_area(hidden_areas.get_next_area(ea)); }


// Delete hidden area
//      ea - any address in the hidden area
// returns: 1-ok,0-failure

inline bool idaapi del_hidden_area(ea_t ea)
  { return hidden_areas.del_area(ea); }


//--------------------------------------------------------------------------
//      L O W  L E V E L  F U N C T I O N S (kernel only)
//--------------------------------------------------------------------------

inline void idaapi doFlow(ea_t ea)      { setFlbits(ea, FF_FLOW);  }
inline void idaapi noFlow(ea_t ea)      { clrFlbits(ea, FF_FLOW);  }

void doRef(ea_t ea);
void noRef(ea_t ea);

inline void idaapi doExtra(ea_t ea) { setFlbits(ea, FF_LINE); }
inline void idaapi noExtra(ea_t ea) { clrFlbits(ea, FF_LINE); }

//--------------------------------------------------------------------------
ulong coagulate(ea_t ea);
bool coagulate_dref(ea_t From,ea_t To,flags_t F, bool may_define);

//--------------------------------------------------------------------------
inline ea_t idaapi get_item_head(ea_t ea)
{
  if ( isTail(getFlags(ea)) ) ea = prev_not_tail(ea);
  return ea;
}

// init/save/term work with hidden areas
// These functions are called from the kernel at the start.

void init_hidden_areas(void);
void save_hidden_areas(void);
void term_hidden_areas(void);


// Move chunk of flags information to the new address (kernel only)
int check_move_args(ea_t from, ea_t to, ulong size); // returns VAMOVE_...
int movechunk(ea_t from, ea_t to, ulong size);

// internal kernel functions to lock the debugger memory configuration updates
void lock_dbgmem_config(void);
void unlock_dbgmem_config(void);


#ifndef BYTES_SOURCE    // undefined bit masks so no one can use them directly
#undef MS_VAL
#undef FF_IVL
#undef MS_CLS
#undef FF_CODE
#undef FF_DATA
#undef FF_TAIL
#undef FF_UNK
#undef MS_COMM
#undef FF_COMM
#undef FF_REF
#undef FF_LINE
#undef FF_NAME
#undef FF_LABL
#undef FF_ANYNAME
#undef FF_FLOW
#undef FF_SIGN0
#undef FF_SIGN1
#undef FF_VAR
#undef MS_0TYPE
#undef FF_0VOID
#undef FF_0NUMH
#undef FF_0NUMD
#undef FF_0CHAR
#undef FF_0SEG
#undef FF_0OFF
#undef FF_0NUMB
#undef FF_0NUMO
#undef FF_0ENUM
#undef FF_0FOP
#undef FF_0STRO
#undef FF_0STK
#undef FF_0HIGH
#undef MS_1TYPE
#undef FF_1VOID
#undef FF_1NUMH
#undef FF_1NUMD
#undef FF_1CHAR
#undef FF_1SEG
#undef FF_1OFF
#undef FF_1NUMB
#undef FF_1NUMO
#undef FF_1ENUM
#undef FF_1FOP
#undef FF_1STRO
#undef FF_1STK
#undef FF_1HIGH
#undef DT_TYPE
#undef FF_BYTE
#undef FF_WORD
#undef FF_DWRD
#undef FF_QWRD
#undef FF_FLOAT
#undef FF_DOUBLE
#undef FF_TBYT
#undef FF_PACKREAL
#undef FF_ASCI
#undef FF_STRU
#undef FF_ALIGN
#undef MS_CODE
#undef FF_FUNC
#undef FF_IMMD
//#undef FF_JUMP
#undef MS_TAIL
#undef TL_TSFT
#undef TL_TOFF
#undef MAX_TOFF
#endif // BYTES_SOURCE

#pragma pack(pop)
#endif // BYTES_HPP
