#include <api/api_main.h>

extern struct DISASM_TGT target;
extern struct DISASM_ENV disasm_env;
extern struct DISASM_PREFS disasm_prefs;

/* API sections:
 *    11. Functions            :: Creating/manipulating FUNCTION objects
 *    12. Inline               :: Creating/manipulating INLINE functions
 * /


/* ---------------------------------------------------------------Functions */
   int DefineFunc( long rva, char * name, int size, int flags ){
      struct address *a;
      struct function f = {0};
      struct name n;
      char buf[16];
      long pa = 0;
      int sz_addr = 1;
   
      f.id = ++seq.func;
      f.rva = rva;
      f.size = size;
      if (! f.size) f.size = 1;
   /* add check : if size == NULL, look for next ret */
      
      a = GetAddressObject(rva);
      /* Create address ... this will change the flags on an existng addr */
      if ( a ) {
         sz_addr = a->size;
         pa = a->pa;
         free(a);
      } 
      DefineAddr(rva, sz_addr, pa, ADDR_CODE | ADDR_FUNCTION | ADDR_NAME);

      if ( d_keyfind(FUNCTION_RVA, &f.rva) != S_OKAY){
         /* Do not create a function if one already exists! */
         d_fillnew(FUNCTION, &f);
         if (db_status != S_OKAY) { 
            return(SetLastError(dbError()));
         }
         /* create name for addr */
         if ( DBIndexFind(NAME_RVA, &rva, &n)){
            /* Preserve existing symbol and user names */
            if (n.type & NAME_USER || n.type & NAME_SYMBOL ) {
               n.type |= NAME_SUB;
               DBRecordUpdate(NAME_RVA, &rva, &n);
               return(1); /* Bail out early, we are done naming */
            } 
         }

         if (! flags ) flags = NAME_AUTO | NAME_SUB;
         else flags |= NAME_SUB;

         if (! name ) {
            sprintf( buf, "sub_%08X", rva);
            name = buf;
         }

         SetName( rva, name, flags); 
      } 

      return(1);
   }

   int GetFuncName( long rva, char *buf){
      struct name n;
   
      if ( d_keyfind(NAME_RVA, &rva) == S_OKAY) {
         d_recread(&n);
         strncpy(buf, n.name, 63);
         return(1);
      }
      return(SetLastError(4310));
   }

   int GetFuncStart( long rva){
      struct function f;
   
      if ( d_keyfind(FUNCTION_RVA, &rva) == S_NOTFOUND){
         d_keynext(FUNCTION_RVA);
         d_keyprev(FUNCTION_RVA);
      }
      if ( db_status != S_OKAY)
         return(SetLastError(dbError()));
      d_recread(&f);
      return(f.rva);
   }

   int GetFuncEnd( long rva){
      struct function f;
   
      if ( d_keyfind(FUNCTION_RVA, &rva) == S_NOTFOUND){
         d_keynext(FUNCTION_RVA);
         d_keyprev(FUNCTION_RVA);
      }
      if ( db_status != S_OKAY)
         return(SetLastError(dbError()));
      d_recread(&f);
      return(f.rva + f.size);
   }

   int GetFuncByName( char *name) {
      int rva;
      
      rva = GetAddrByName( name );
      if ( rva && d_keyfind(FUNCTION_RVA, &rva) == S_OKAY){
         return(rva);
      }

      return(SetLastError(4320));
   }

   int SetFuncName( long rva, char *name){
      struct function f;
   
      if ( d_keyfind(FUNCTION_RVA, &rva) != S_OKAY)
         return(SetLastError(4310));
      return(SetName( rva, name, NAME_AUTO)); 
   }

   int SetFuncSize( long rva, int size){
      struct function f;
   
      if ( d_keyfind(FUNCTION_RVA, &rva) == S_OKAY){
         d_recread(&f);
         f.size = size;
         d_recwrite(&f);
         return(1);
      }
      return(SetLastError(4310));
   }

/* ---------------------------------------------------------------Inline */
/* Flags to add : paginate, hide libs, hide inline */
/* Note : f;ags should be changed in Seer to avoid parsing :) */

