#include <strings.h>
#include <sys/types.h>
#include <a.out.h>
#include "utils.h"
#include "insertor.h"

#define obstack_chunk_free free
#define obstack_chunk_alloc xmalloc
#include "obstack.h"	/* the linux-standard obstack.h is broken */

unsigned int nbr_sym;		/* number of symbols */
struct obstack o_sym_name;	/* table of symbols names */
struct obstack o_sym_offset;	/* table of all beginning of symbols */
struct obstack o_symbols;	/* table of symbols */

struct obstack o_new_offset;
struct obstack o_tmp_reloc;
int nbr_new_reloc = 0;

void
init_sym_gen()
{
  nbr_sym = 0;
  obstack_begin(&o_sym_name, 4096);
  obstack_int_grow(&o_sym_name, 0);	/* number of symbols. */
  
  obstack_begin(&o_sym_offset, 4096);
  obstack_begin(&o_symbols, 4096);
  obstack_begin(&o_new_offset, 4096);
  obstack_begin(&o_tmp_reloc, 4096);
}

long
store_symb(char *symbols)
{
 int i;
 char *base = (char*)obstack_base(&o_sym_name);
 char *res;
 
 if (symbols == (char*)0 || *symbols == '\0')
   return 0;
   
 /* look if the symbol is not already stored */
 for(i = 0; i < nbr_sym; i++)
   {
     res = base + ( (int*)obstack_base(&o_sym_offset) )[i];
     if (strcmp(symbols, res) == 0)
       return ( (int*)obstack_base(&o_sym_offset) )[i];
   }
 res = obstack_next_free(&o_sym_name);
 i = obstack_object_size(&o_sym_name);
 obstack_grow(&o_sym_name, symbols, strlen(symbols) + 1);
 obstack_int_grow(&o_sym_offset, i);
 return i; /* ( (char*)obstack_base(&o_sym_name) )
             + ( (int*)obstack_base(&o_sym_offset) )[i]; */
}

void
stabs(char *str, u_char type, char other, short desc, u_long value)
{
 struct nlist temp;
 
 temp.n_un.n_strx = store_symb(str);
 temp.n_type = type;
 temp.n_other = other;
 temp.n_desc = desc;
 temp.n_value = value;
 obstack_grow(&o_symbols, &temp, sizeof (struct nlist));
}

void
new_offset(u_int old_off, u_int new_off, u_int len)
{
 struct Soffset temp;
 temp.old_offset = old_off;
 temp.new_offset = new_off;
 temp.len = len;
 obstack_grow(&o_new_offset, &temp, sizeof(temp));
 nbr_new_reloc++;
}