/* Search.c -- API routines for searching the DB 
               These routines are for dealing with non-unique columns;
               DB columns for mnemonic, operand, etc will return tens to
               hundreds of results -- thus they are given special
               treatment here.
*/
#include <bastard.h>

   struct search {
      DB_ADDR curr_rec;		/* current record in DB */
      unsigned char *pos;	/* position in target image */
      long bytes_read;
      int count;				/* total number of records returned */
   };
   typedef struct search *SEARCH;


/* +++ This is just 10 kinds of ugly. Don't say you weren't warned +++ */

   int FindBytes( unsigned char *bytes, int len, int **s){
   /* find sequence of bytes : returns search ptr */
      struct address a;
      int i, pa, found = 0;
   
      if (! *s) {
      /* this is the 'find first' */
         *s = (int *)calloc(sizeof(struct search), 1);
         ((SEARCH)*s)->pos = (unsigned char *) target.image;
      } 
      while( ((SEARCH)*s)->bytes_read < target.size ){
         if ( ((SEARCH)*s)->pos[0] == bytes[0]) {
         /* check for a full match */
            for (i = 0; i < len; i++)
               if ( ((SEARCH)*s)->pos[i] == bytes[i])	found++;
            if (found == len){
            /* lookup addr for this pa and return it */
               if (d_keyfind(PA, &((SEARCH)*s)->bytes_read) 
               == S_OKAY) {
               /* there is a valid program address for this sequence */
                  d_recread(&a);
                  return(a.rva);
               }
            }
         }
         ((SEARCH)*s)->pos++;
         ((SEARCH)*s)->bytes_read++;
      }
      free(*s); /* free search handle if nothing found */
      return(0);
   }

   void PrepDBSearch( int table, struct search **search){
      if (! *search) {
      /* this is the 'find first' */
         *search = (SEARCH) calloc(sizeof(struct search), 1);
         d_recfrst(table);
      } 
      else {
      /* this is a 'find next' -- restore current record in DB */
         (*search)->count++;
         d_crset(&(*search)->curr_rec);
         d_recnext(table);
      }
      return;
   }

   int FindOperand( char *str, int **s) {
      struct code c;
   
      PrepDBSearch( CODE, (SEARCH*)s );
      while( db_status == S_OKAY ){
         d_crget(&((SEARCH)*s)->curr_rec); /* save current record in DB */
         d_recread(&c);
         if (! strcmp(c.dest, str)) 
            return(c.rva);
         if (! strcmp(c.src, str)) 
            return(c.rva);
         if (! strcmp(c.aux, str)) 
            return(c.rva);
         d_recnext(CODE);
      }
      free(*s); /* free search handle if nothing found */
      return(0);
   }

   int FindMnemonic( char *str, int **s){
      struct code c;
   
      PrepDBSearch( CODE, (SEARCH*)s );
      while( db_status == S_OKAY ){
         d_crget(&((SEARCH)*s)->curr_rec); /* save current record in DB */
         d_recread(&c);
         if (! strcmp(c.mnemonic, str)) 
            return(c.rva);
         d_recnext(CODE);
      }
      free(*s); /* free search handle if nothing found */
      return(0);
   }

   int FindConstant( long value, int **s){
      struct constant c;
   
      PrepDBSearch( CODE, (SEARCH*)s );
      while( db_status == S_OKAY ){
         d_crget(&((SEARCH)*s)->curr_rec); /* save current record in DB */
         d_recread(&c);
         if (! c.value == value ) 
            return(c.id);
         d_recnext(CODE);
      }
      free(*s); /* free search handle if nothing found */
      return(0);
   }

   int FreeSearchHandle( int **search ){
      int count = 0;
   
      if (*search) {
         count = ((SEARCH)*search)->count;
         free(*search);
      }
      return(count);
   }
