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

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

//
//      This file contains functions that deal with names.
//      A non-tail address of the program may have a name.
//

#include <help.h>
#include <lines.hpp>

class func_t;                   // #include <funcs.hpp>


// Maximum length of a name in IDA (with the trailing zero)

#define MAXNAMELEN      512     // limitation posed by netnodes


// Name prefix used by IDA for the imported functions

#define FUNC_IMPORT_PREFIX "__imp_"


// Translation used to build meaningful names of ascii strings.
// Ascii strings are given a 'meaningful' name based on first characters
// of the string itself.
// This array is used to translate characters which can't appear in
// identifiers to valid ones.
// This array is initialized with information from ida.cfg.

idaman char ida_export_data XlatAsciiName[256];


// Set or delete name of a byte
// Include name into the list of names
//      ea   - linear address
//             do nothing if ea is not valid (return 0)
//             tail bytes can't have names
//      name - new name
//              NULL: do nothing (return 0)
//              ""  : delete name
//              otherwise this is a new name
//      flag - name type and checks:
#define SN_CHECK        0x01    // Fail if the name contains invalid characters
                                // If this bit is clear, all invalid chars
                                // (those !is_ident_char()) will be replaced
                                // by SubstChar (usually '_')
                                // List of valid characters is defined in ida.cfg
#define SN_NOCHECK      0x00    // Replace invalid chars with SubstChar
#define SN_PUBLIC       0x02    // if set, make name public
#define SN_NON_PUBLIC   0x04    // if set, make name non-public
#define SN_WEAK         0x08    // if set, make name weak
#define SN_NON_WEAK     0x10    // if set, make name non-weak
#define SN_AUTO         0x20    // if set, make name autogenerated
#define SN_NON_AUTO     0x40    // if set, make name non-autogenerated
#define SN_NOLIST       0x80    // if set, exclude name from the list
                                // if not set, then include the name into
                                // the list (however, if other bits are set,
                                // the name might be immediately excluded
                                // from the list)
#define SN_NOWARN       0x100   // don't display a warning if failed
#define SN_LOCAL        0x200   // create local name. a function should exist.
                                // local names can't be public or weak.
                                // also they are not included into the list of names
                                // they can't have dummy prefixes
// If a bit is not specified, then the appropriate action is not performed
// and the name will retain the same bits as before calling this function.
// For new names, default is: non-public, non-weak, non-auto.
// returns: 1-ok, name is changed
//          0-failure, a warning is displayed

idaman bool ida_export set_name(ea_t ea,const char *name,int flag);


// Set or delete a name of byte
// This function is shortcut for set_name(ea,name,SN_CHECK);

inline bool set_name(ea_t ea,const char *name) // Giveth a name (and taketh it back)
{
  return set_name(ea,name,SN_CHECK);
}


// Delete a name
//      ea - linear address
// returns: 1-ok, name is deleted
//          0-failure, invalid address

inline bool del_global_name(ea_t ea) { return set_name(ea,"", SN_NOWARN); }
inline bool del_local_name(ea_t ea)  { return set_name(ea,"", SN_LOCAL|SN_NOWARN);}


// Give an autogenerated (dummy) name
// Autogenerated names have special prefixes (loc_...)
//      from  - linear address of the operand which references to the address
//      ea    - linear address
// returns: 1-ok, dummy name is generated or the byte already had a name
//          0-failure, invalid address or tail byte

idaman bool ida_export set_dummy_name(ea_t from, ea_t ea); // give dummy name


// Set/clear bit in flags for 'autogenerated but meaningful name'
//      ea - linear address
// This bit affects value of has_user_name(), has_auto_name() functions
// returns: 1-ok, 0-no meaningful name is present at the specified address

idaman bool ida_export make_name_auto(ea_t ea);
idaman bool ida_export make_name_user(ea_t ea);


// Give a name anyway
// This function tries to give the specified name the specified addresss
// and tries to modify the name with a postfix ("_00") if the name
// already exists.
// It will try 100 different postfixes and fail only if all such names
// are already in use. For example, if the specified name is "xxx",
// the function will try to give names "xxx","xxx_0","xxx_2",... "xxx_99"
//      ea     - linear address
//      name   - new name
//                 NULL: return 0
//                 ""  : return 0
//      maxlen - if specified, the name will be truncated to have the specified
//               maximum length
// returns: 1-ok
//          0-failure

idaman bool ida_export do_name_anyway(ea_t ea,const char *name,int maxlen=0); // give a name: try 100 times with different suffixes (_##)


// Validate a name
// This function replaces all invalid characters in the name with SubstChar
// However, it will return NULL if name is valid but not allowed to be an
// identifier (is a register name)
//      name - ptr to name. the name will be modified
// returns: NULL-can't validate
//          name-ok,validated name

idaman char *ida_export validate_name(char *name);// returns NULL if can't validate


// Can a character appear in a name? (present in NameChars or MangleChars)

idaman bool ida_export is_ident_char(char c);


// Can a character be displayed in a name? (present in NameChars)

idaman bool ida_export is_visible_char(char c);


// Substitute all MangleChars in a name with SubstChar.
// This function replaces all non-visible characters in the name with SubstChar
//      srcname - pointer to source name.
//      dstname - pointer to target name buffer.
// srcname and dstname may point to the same buffer.
// returns: dstname

idaman char *ida_export make_visible_name(char *dstname,const char *srcname);


// Is a valid name? (including MangleChars)

idaman bool ida_export isident(const char *name);         // is valid identifier?


// Is user-specified name? (valid name & !dummy prefix)
//      name - name to test. may be NULL.
// returns: 1-yes, 0-no

idaman bool ida_export is_uname(const char *name);


// Extract a name or address from the specified string
//      line - input string
//      x    - x coordinate of cursor
//      buf  - output buffer for the identifier
//      bufsize - sizeof(buf)
// returns: NULL - failure, can't extract
//          otherwise - extracted name or address. It is not guaranteed
//                      that the extracted name or address is valid.

idaman char *ida_export extract_name(const char *line,
                                     int x,
                                     char *buf,
                                     size_t bufsize);


// Remove name from the list of names
//      ea - address of the name

idaman void ida_export hide_name(ea_t ea);    // remove name from names list


// Insert name to the list of names

idaman void ida_export show_name(ea_t ea);    // add name to names list


// Get address of the name
// This function works only with regular names
//      from  - linear address where the name is used
//              if not applicable, then should be BADADDR
//      name  - any name in the program or NULL
// returns: address of the name or BADADDR

idaman ea_t ida_export get_name_ea(ea_t from, const char *name);    // Get address by name


// Get address of the name used in the expression for the address
//      from  - address of the operand which references to the address
//      to    - the referenced address
// returns: address of the name used to represent the operand

idaman ea_t ida_export get_name_base_ea(ea_t from, ea_t to);


// Get value of the name
// This function knows about: regular names, enums, special segments etc.
//      from  - linear address where the name is used
//              if not applicable, then should be BADADDR
//      name  - any name in the program or NULL
//      value - pointer to variable with answer
// returns:
#define NT_NONE         0       // name doesn't exist or has no value
#define NT_BYTE         1       // name is byte name (regular name)
#define NT_LOCAL        2       // name is local label
#define NT_STKVAR       3       // name is stack variable name
#define NT_ENUM         4       // name is symbolic constant
#define NT_ABS          5       // name is absolute symbol (SEG_ABSSYM)
#define NT_SEG          6       // name is segment or segment register name
#define NT_STROFF       7       // name is structure member
#define NT_BMASK        8       // name is a bit group mask name

idaman int ida_export get_name_value(ea_t from,const char *name, uval_t *value); // Get value by name


// Get true (uncolored) name at the specified address
//      from - linear address where the name is used
//             if not applicable, then should be BADADDR
//             The kernel tries to return a local name if the reference is
//             within a function, i.e. 'from' and 'ea' belong to the same function
//      ea   - linear address
//      buf  - buffer to hold the name
//      bufsize - size of the output buffer
// returns: NULL - if address is not valid or doesn't have a name
//          otherwise - ptr to name
// The difference between get_name() and get_true_name() is that
// get_name() substitutes characters not present in NameChars[]
// with 'SubstChar' while get_true_name() returns the name as is.

idaman char *ida_export get_true_name(ea_t from, ea_t ea, char *buf, size_t bufsize);


// Get plain (uncolored) name at the specified address
//      from - linear address where the name is used
//             if not applicable, then should be BADADDR
//             The kernel tries to return a local name if the reference is
//             within a function, i.e. 'from' and 'ea' belong to the same function
//      ea   - linear address
//      buf  - buffer to hold the name
//      bufsize - size of the output buffer
// returns: NULL - if address is not valid or doesn't have a name
//          otherwise - ptr to name
// The difference between get_name() and get_true_name() is that
// get_name() substitutes characters not present in NameChars[]
// with 'SubstChar' while get_true_name() returns the name as is.

idaman char *ida_export get_name(ea_t from, ea_t ea, char *buf, size_t bufsize);


// Get colored name at the specified address
//      from - linear address where the name is used
//             if not applicable, then should be BADADDR
//             The kernel tries to return a local name if the reference is
//             within a function, i.e. 'from' and 'ea' belong to the same function
//      ea   - linear address
//      buf  - buffer to hold the name
//      bufsize - size of the output buffer
// returns: NULL - if address is not valid or doesn't have a name
//          otherwise - ptr to name
// The resulting name will have color escape characters
// (see lines.hpp for color definitions)

idaman char *ida_export get_colored_name(ea_t from, ea_t ea, char *buf, size_t bufsize);


// Get short/long forms of demangled name
//      from - linear address where the name is used
//             if not applicable, then should be BADADDR
//             The kernel tries to return a local name if the reference is
//             within a function, i.e. 'from' and 'ea' belong to the same function
//      ea   - linear address
//      buf  - buffer for the name
//      bufsize - size of the output buffer
// returns: demangled name or plain name or NULL

char *get_short_name(ea_t from, ea_t ea, char *buf, size_t bufsize);
char *get_long_name(ea_t from, ea_t ea, char *buf, size_t bufsize);


// Get colored short/long forms of demangled name
//      from - linear address where the name is used
//             if not applicable, then should be BADADDR
//             The kernel tries to return a local name if the reference is
//             within a function, i.e. 'from' and 'ea' belong to the same function
//      ea   - linear address
//      buf  - buffer for the name
//      bufsize - size of the output buffer
// returns: demangled name or plain name or NULL

char *get_colored_short_name(ea_t from, ea_t ea, char *buf, size_t bufsize);
char *get_colored_long_name(ea_t from, ea_t ea, char *buf, size_t bufsize);


// Get name color
//      from - linear address where the name is used
//             if not applicable, then should be BADADDR
//             The kernel returns a local name color if the reference is
//             within a function, i.e. 'from' and 'ea' belong to the same function
//      ea   - linear address

idaman color_t ida_export get_name_color(ea_t from, ea_t ea);         // get color of a name

// Get uncolored name in the current format (mangled/demangled)
// This function tried to demangle the name. If it is not possible
// and strict==0 then it returns plain name.
// Otherwise returns output of get_name()
//      from      - linear address where the name is used
//                  if not applicable, then should be BADADDR
//                  The kernel tries to return a local name if the reference is
//                  within a function, i.e. 'from' and 'ea' belong to the same function
//      ea        - linear address
//      buf       - buffer for the name
//      bufsize   - size of the output buffer
//      inhibitor - codes to inhibit parts of demangled name
//                  see MNG_.. from demangle.hpp
//                  Usually this is one of inf.short_demnames or inf.long_demnames
//      demform   - demangle only if inf.demnames is equal to 'demform'.
//                  For possible values of inf.demnames see ida.hpp
//      strict    - 1: return NULL if can't demangle
//                  0: return unmangled name if can't demangle
// returns: formatted name or NULL

idaman char *ida_export get_demangled_name(ea_t from, ea_t ea, char *buf, size_t bufsize,
                         long inhibitor, int demform, bool strict);


// Get colored name in the current format (mangled/demangled)
// This function tried to demangle the name. If it is not possible
// and strict==0 then it returns plain name.
// Otherwise returns output of get_name()
//      from      - linear address where the name is used
//                  if not applicable, then should be BADADDR
//                  The kernel tries to return a local name if the reference is
//                  within a function, i.e. 'from' and 'ea' belong to the same function
//      ea        - linear address
//      buf       - buffer for the name
//      bufsize   - size of the output buffer
//      inhibitor - codes to inhibit parts of demangled name
//                  see MNG_.. from demangle.hpp
//                  Usually this is one of inf.short_demnames or inf.long_demnames
//      demform   - demangle only if inf.demnames is equal to 'demform'.
//                  For possible values of inf.demnames see ida.hpp
//      strict    - 1: return NULL if can't demangle
//                  0: return unmangled name if can't demangle
// returns: formatted name or NULL

idaman char *ida_export get_colored_demangled_name(ea_t from,
                                                   ea_t ea,
                                                   char *buf,
                                                   size_t bufsize,
                                                   long inhibitor,
                                                   int demform,
                                                   bool strict);


// Convert address to name expression (name with a displacement)
// This function takes into account fixup information and returns
// a colored name expression (in the form  <name> +/- <offset>)
// Also it knows about structure members and arrays.
// If the specified address doesn't have a name, a dummy name is generated.
//      from - linear address of instruction operand or data referring to
//             the name. This address will be used to get fixup information,
//             so it should point to exact position of the operand in the
//             instruction.
//      n    - number of referencing operand. for data items specify 0.
//      ea   - address to convert to name expression
//      off  - the value of name expression. this parameter is used only to
//             check that the name expression will have the wanted value.
//             You may pass BADADDR for this parameter but I discourage it
//             because it prohibits checks.
//   flags   - combination of the following bits:
#define GETN_APPZERO  0x0001  // meaningful only if the name refers to a structure.
                              // append a struct field name if the field offset is zero?
#define GETN_NOFIXUP  0x0002  // ignore the fixup information when producing the name
// returns: NULL - if address is not valid, no segment or other failure
//          otherwise - ptr to name in a static storage
//                 you should copy it to another place before
//                 working with other name-related functions

idaman char *ida_export get_name_expr(ea_t from,
                                      int n,
                                      ea_t ea,
                                      adiff_t off,
                                      int flags=GETN_APPZERO);
                                // get name expression at 'ea' for item 'from'
                                // the value of name expression should
                                // be equal to 'off'
                                // off == BADADDR - don't check


// Get a nice colored name at the specified address, like:
//   segment:sub+offset
//   segment:sub:local_label
//   segment:label
//   segment:address
//   segment:address+offset
//      from - linear address where the name is used
//             if not applicable, then should be BADADDR
//             The kernel tries to return a local name if the reference is
//             within a function, i.e. 'from' and 'ea' belong to the same function
//      ea   - linear address
//      buf  - buffer to hold the name
//      bufsize - size of the output buffer
//      flags   - combination of the following bits:
#define GNCN_NOSEG    0x0001 // ignore the segment prefix when producing the name
#define GNCN_NOCOLOR  0x0002 // generate an uncolored name
#define GNCN_NOLABEL  0x0004 // don't generate labels
#define GNCN_NOFUNC   0x0008 // don't generate funcname+... expressions
#define GNCN_SEG_FUNC 0x0010 // generate both segment and function names (default is to omit segment name if a function name is present)
#define GNCN_SEGNUM   0x0020 // segment part is displayed as aa hex number
#define GNCN_REQFUNC  0x0040 // return 0 if the address does not belong to a function
#define GNCN_REQNAME  0x0080 // return 0 if the address can only be represented as a hex number
// returns: the length of the generated name in bytes
// The resulting name will have color escape characters if GETN_NOCOLOR was not specified
// (see lines.hpp for color definitions)

idaman int ida_export get_nice_colored_name(ea_t ea,
                                            char *buf,
                                            size_t bufsize,
                                            int flags=0);


// Append names of struct fields to a name if the name is a struct name
//      n       - number of operand n which the name appears
//      path    - path in the struct. path is an array of id's.
//                maximal length of array is MAXSTRUCPATH
//                the first element of the array is the structure id
//                consequtive elements are id's of used union members (if any).
//      plen    - size of path array
//      flags   - the input flags. they will be returned if the struct
//                cannot be found.
//      ptr     - pointer to the end of the name (to the output buffer)
//      end     - pointer to the end of the output buffer
//      disp    - displacement from the name
//      delta   - delta to add to displacement
//      appzero - should append a struct field name if the displacement is zero?
// returns: flags of the innermost struct member or the input flags

idaman flags_t ida_export append_struct_fields(
                        int n,
                        const tid_t *path,
                        int plen,
                        flags_t flags,
                        char *ptr,
                        char *end,
                        adiff_t *disp,
                        adiff_t delta,
                        bool appzero);


// Get offset within a structure if the operand refers to structure
//      ea      - linear address of instruction/data
//      n       - number of operand
//      path    - existing strpath (if any)
//      disp    - pointer to displacement (answer will be here)
//      delta   - pointer to displacement delta (answer will be here)
// example:
//            mov ax, somedata.field5-2 (before it was max ax, 3)
// for this instruction, op #1 the function will return
//                                      disp: the value of 'field5', i.e. 5
//                                      delta: -2
//                                      path: the existing path if any
// returns: if success, then length of path + 1
//          if failed, then 0

idaman int ida_export get_struct_operand(ea_t ea,
                                         int n,
                                         tid_t *path,
                                         adiff_t *disp,
                                         adiff_t *delta);


// Work with publicness of a name.

idaman bool ida_export is_public_name(ea_t ea);
idaman void ida_export make_name_public(ea_t ea);
idaman void ida_export make_name_non_public(ea_t ea);


// Generate declaration of publicness/weakness of a name if nesessary
//      ea     - address of the name
//      name   - colored name. If name==NULL then is will be retrieved
//               from the database
// returns:
//          0 - declaration is generated
//          1 - overflow of the line buffer occured during declaration
//          2 - nothing is done: name is not public

idaman int ida_export gen_name_decl(ea_t ea,const char *name);


// Work with weak names.

idaman bool ida_export is_weak_name(ea_t ea);
idaman void ida_export make_name_weak(ea_t ea);
idaman void ida_export make_name_non_weak(ea_t ea);


// Work with the list of names

idaman size_t ida_export get_nlist_size(void);  // get number of names in the list
idaman size_t ida_export get_nlist_idx(ea_t ea);// get index of the name in the list
                                                // returns 0..n
                                                // beware: returns the closest match
                                                //         may return idx >= size
idaman bool ida_export is_in_nlist(ea_t ea);    // is name included into names list?
idaman ea_t ida_export get_nlist_ea(size_t idx);// return address from the list at 'idx'
idaman const char *ida_export get_nlist_name(size_t idx); // get name using idx

idaman void ida_export rebuild_nlist(void);


// Renumber dummy names

idaman void ida_export reorder_dummy_names(void);


// debug names
// these names exist during the debugging session
// the kernel does not verify them for anything and happily accepts
// any string as a name

enum debug_name_how_t
{
  DEBNAME_EXACT,        // find a name at exactly the specified address
  DEBNAME_LOWER,        // find a name with the address <= the specified address
  DEBNAME_UPPER,        // find a name with the address >  the specified address
};

idaman int  ida_export set_debug_names(const ea_t *addrs, const char *const *names, int qty);
idaman bool ida_export set_debug_name(ea_t ea, const char *name);
idaman bool ida_export get_debug_name(ea_t *ea_ptr, debug_name_how_t how,
                                                char *buf, size_t bufsize);
idaman void ida_export del_debug_names(ea_t ea1, ea_t ea2);
idaman ea_t ida_export get_debug_name_ea(const char *name);


//      Kernel only functions and data

size_t addDummyName(ea_t ea);   // don't call this directly!

void convert_debug_names_to_normal(ea_t ea1, ea_t ea2);
void convert_name_formats(void); // should be called when processor type is changed
void showhide_name(ea_t ea);   // show or hide name from the list depending
                                // on the type of the name

bool clear_lname_bit(ea_t ea, bool setflags);
void fix_new_name(ea_t ea,const char *oldname,const char *newname, bool lname);
bool rename(tid_t id,const char *name);  // rename structure member
void move_names(ea_t from, ea_t to, asize_t size); // move name list and dummy names

typedef int ignore_name_def_t;
const ignore_name_def_t
  ignore_none   = 0,
  ignore_regvar = 1,
  ignore_llabel = 2,
  ignore_stkvar = 3,
  ignore_glabel = 4;
idaman bool ida_export is_name_defined_locally(func_t *pfn, const char *name,
                   ignore_name_def_t ignore, ea_t ea1=BADADDR, ea_t ea2=BADADDR);


idaman signed long ida_export demangle_name(char *buf,
                          int bufsize,
                          const char *name,
                          ulong disable_mask);

class Varray;
extern Varray *nameVa;

// Array of valid identifier characters.
// The kernel doesn't allow digits as first character of a name anyway.
// This array is initialized with information from ida.cfg.
// The following characters are allowed in user-defined names:

idaman ida_export_data char NameChars[256];


// the following characters are allowed in mangled names.
// they will be substituted with the SubstChar during output.

idaman ida_export_data char MangleChars[256];
idaman ida_export_data char SubstChar;

// inline definitions

inline char *get_short_name(ea_t from, ea_t ea, char *buf, size_t bufsize)
{
  return get_demangled_name(from, ea, buf, bufsize,
                                long(inf.short_demnames), inf.demnames, false);
}

inline char *get_long_name(ea_t from,ea_t ea,char *buf, size_t bufsize)
{
  return get_demangled_name(from, ea, buf, bufsize,
                                long(inf.long_demnames), inf.demnames, false);
}
inline char *get_colored_short_name(ea_t from, ea_t ea, char *buf, size_t bufsize)
{
  return get_colored_demangled_name(from, ea, buf, bufsize,
                                long(inf.short_demnames), inf.demnames, false);
}

inline char *get_colored_long_name(ea_t from,ea_t ea,char *buf, size_t bufsize)
{
  return get_colored_demangled_name(from, ea, buf, bufsize,
                                int(inf.long_demnames), inf.demnames, false);
}


#pragma pack(pop)
#endif // _NAME_HPP
