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

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

/*
        This file contains functions that deal with C-like expressions
        and built-in IDC language.
*/

/*-------------------------------------------------------------------------*/
/*      T y p e  D e f i n i t i o n s                                     */
/*-------------------------------------------------------------------------*/

/*      Attention!!!
        While allocating value_t variables in the system stack
        (automatic variables), don't forget to initialize them:

                value_t v; v.vtype = VT_LONG;

*/

struct value_t          /* Result of expression */
{
  char vtype;           /* Type                 */
#define  VT_STR         1
#define  VT_LONG        2
#define  VT_FLOAT       3
#define  VT_WILD        4       // used only in function arg type declarations
  union {
    char *str;          /* T_str        */
    long num;           /* T_long       */
    ushort e[6];        /* T_flt        */
  };
};


typedef struct {                /* Element of functions table */
  const char *name;             /* Name of function */
  error_t (*fp)(value_t *argv,value_t *res); /* Pointer to the Function */
  const char *args;             /* Type of arguments. Terminated with 0 */
                                /* VT_WILD means a function with arbitrary
                                   number of arguments. Actual number of
                                   arguments will be passed in res->num */
} extfun_t;

typedef struct {        /* Current execution information */
  const char *fname;    /* Current function name */
  uint idx;             /* Current IP */
  const char *sarg;     /* Offending arg (when applicable) */
  uint iarg;            /* Offending arg (when applicable) */
} execinfo_t;

typedef struct {
  int qnty;             /* Quantity of functions */
  extfun_t *f;          /* Functions table */
  error_t (*startup)(void);
  error_t (*shutdown)(void);
} funcset_t;

/*-------------------------------------------------------------------------*/

// Array of built-in IDA functions

idaman funcset_t ida_export_data IDCFuncs; // external functions


// Area to hold information about execution status.
// This area may be examined if an error occurs during execution
// of an IDC function

extern  execinfo_t ExecInfo;    /* execution information */


/*-------------------------------------------------------------------------*/
// Convert IDC variable to a long (32bit) number

idaman error_t ida_export VarLong(value_t *v);


// Convert IDC variable to a text string

idaman error_t ida_export VarString(value_t *v);


// Convert IDC variable to a floating point

idaman void ida_export VarFloat(value_t *v);


// Free storage used by VT_STR type IDC variables

idaman void ida_export VarFree(value_t *v);            // frees string value only


/*-------------------------------------------------------------------------*/

// Get name of directory that contains IDC scripts.
// This directory is pointed by IDCPATH environment variable or
// it is in IDC subdirectory in IDA directory

idaman const char *ida_export get_idcpath(void);


// set or append a header path
//      path - list of directories to add (separated by ';')
//             may be NULL, in this case nothing is added
//      add  - true: append
//             false: remove old pathes
// return: true if success, false if no memory
// IDA looks in the appended header pathes, after in idcpath and
// at last in the ida.exe directory

idaman bool ida_export set_header_path(const char *path, bool add);


// Get full name of IDC file name.
// Search for file in IDCPATH, IDA directory and PATH
// Returns: NULL is file not found
//          otherwise returns pointer to static buffer

idaman char *ida_export get_idc_filename(const char *file);


// Compile and execute "main" function from system file
//      file    - file name with IDC function(s)
//                The file will be searched in
//                      - the current directory
//                      - IDA.EXE directory
//                      - in PATH
//      flag    - 1: display warning if the file is not found
//                0: don't caomplain if file doesn't exist
// returns: 1-ok, file is compiled and executed
//          0-failure, compilation or execution error, warning is displayed

idaman int ida_export dosysfile(int flag,char *file);


// Compile and calculate IDC expression
//      where - the current linear address in the addressing space of the
//              program being disassembled. If will be used to resolve
//              names of local variables etc.
//              if not applicable, then should be BADADDR
//      line  - a text line with IDC expression
//      res   - pointer to result. The result will be converted
//              to 32bit number. Use another for of calcexpr() if you
//              need the result of any type.
// returns: NULL-ok
//      otherwise returns error string (static storage!)

idaman char *ida_export calcexpr_long(ulong where, const char *line, long *res);


// Compile and calculate IDC expression
//      where - the current linear address in the addressing space of the
//              program being disassembled. If will be used to resolve
//              names of local variables etc.
//              if not applicable, then should be BADADDR
//      line  - a text line with IDC expression
//      rv    - pointer to result value. Its original value is discarded.
// returns: NULL-ok
//      otherwise returns error string (static storage!)

idaman char *ida_export calcexpr(ulong where, const char *line, value_t *rv);


// Compile and execute IDC expression.
//      line  - a text line with IDC expression
// returns: 1-ok
//          0-failure, a warning message is disaplayed

idaman int ida_export execute(const char *line);


// Compile a text file with IDC function(s)
//      file - name of file to compile
//             if NULL, then "File not found" is returned.
// returns: NULL-ok, functions are compiled, otherwise returns error message

idaman char *ida_export Compile(const char *file);


// Compile one text line with IDC function(s)
//      line     - line with IDC function(s) (can't be NULL!)
//      _getname - callback function to get values of undefined variables
//                 This function will be called if IDC function contains
//                 references to a undefined variable. May be NULL.
// returns: NULL-ok, functions are compiled, otherwise returns error message

idaman char *ida_export CompileLine(const char *line,ulong (idaapi*_getname)(const char *name)=NULL);


// Execute a compiled IDC function.
//      fname   - function name
//      argsnum - number of parameters to pass to 'fname'
//                This number should be equal to number of parameters
//                the function expects.
//      args    - array of parameters
//      result  - ptr to value_t to hold result of the function.
//                'result' should not have VT_STR type, otherwise its
//                value will be discarded and the string won't be freed.
//                You may pass NULL if you are not interested in the returned
//                value.
// returns: NULL-ok, function is successfully executed
//      otherwise returns error string (static storage!)

idaman char *ida_export Run(
                const char *fname,              // function name
                int argsnum,
                const value_t args[],
                value_t *result);               // may be NULL. Any previous
                                                // value is DISCARDED (not freed)


// Compile and execute IDC function(s) on one line of text
//      line     - text of IDC functions
//      func     - function name to execute
//      getname  - callback function to get values of undefined variables
//                 This function will be called if IDC function contains
//                 references to a undefined variable. May be NULL.
//      argsnum  - number of parameters to pass to 'fname'
//                 This number should be equal to the number of parameters
//                 the function expects.
//      args     - array of parameters
//      result   - ptr to value_t to hold result of the function.
//                 'result' should not have VT_STR type, otherwise its
//                 value will be discarded and the string won't be freed.
//                 You may pass NULL if you are not interested in the returned
//                 value.
// returns: NULL-ok, function is successfully executed
//      otherwise returns error string (static storage!)

idaman char *ida_export ExecuteLine(
                const char *line,
                const char *func,
                ulong (idaapi*getname)(const char *name),
                int argsnum,
                const value_t args[],
                value_t *result);               // may be NULL. Any previous
                                                // value is DISCARDED (not freed)


// Compile and execute IDC function(s) from file
//      file     - text file containing text of IDC functions
//      func     - function name to execute
//      getname  - callback function to get values of undefined variables
//                 This function will be called if IDC function contains
//                 references to a undefined variable. May be NULL.
//      argsnum - number of parameters to pass to 'fname'
//                This number should be equal to number of parameters
//                the function expects.
//      args    - array of parameters
//      result  - ptr to value_t to hold result of the function.
//                'result' should not have VT_STR type, otherwise its
//                value will be discarded and the string won't be freed.
//                You may pass NULL if you are not interested in the returned
//                value.
// returns: NULL-ok, function is successfully executed
//      otherwise returns error string (static storage!)

idaman char *ida_export ExecuteFile(
                const char *file,
                const char *func,
                int argsnum,
                const value_t args[],
                value_t *result);               // may be NULL. Any previous
                                                // value is DISCARDED (not freed)


// Add a compiled IDC function to a pool of compiled functions
// This function make the input function available to be executed.
// Normally this is not nesessary.
//      name - name of function
//      narg - number of function parameteres
//      body - compiled body of the function
//      len  - length of function body in bytes.

void ExprAddFunction(char *name,int narg,uchar *body,uint len);


// Get text representation of an error code
// Returns: pointer to static storage

char *ExprGetError(error_t code);     /* Returns error message */


/*-------------------------------------------------------------------------*/

extern int idc_stacksize;       // Total number of local variables
extern int idc_calldepth;       // Maximal function call depth

int expr_printf(value_t *argv,value_t *r);
int expr_sprintf(value_t *argv,value_t *r);
int expr_printfer(int (*outer)(void *,char),void *ud,value_t *argv,value_t *r);


void idaapi initSyntax(void);
void idaapi termSyntax(void);
int  idaapi InitFunctions(const char *libname);        /* 1 - ok, 0 - not IDL file */
void idaapi TermFunctions(void);
#pragma pack(pop)
#endif /* _EXPR_H */
