# include <h.stdio>
# include "c.libdef"

extern tree_ptr tree ;          /* the tree */
extern FILE *fp,*new_fp ;
extern char filename[] ;
extern int modified, amount_to_add ;
extern void add_amount(tree_ptr) ;

int next_dir_entry, first_dir_entry, current_ptr ;
static int module_number ;


/* traverse the tree in 'pre-order'.  This ensures the new directory is not
   sorted 'in-order' to create a better balanced tree */

traverse_pre_order (tree_ptr cursor, int (*function)())
   {
   if (cursor == NULL)
      return ;
   (*function)(cursor) ;
   traverse_pre_order (cursor->right,function) ;
   traverse_pre_order (cursor->left,function) ;
   }

copy_header(void)
   {
   char ch, ans[10], library_id[255] ;

   do
      fputc (ch=fgetc(fp),new_fp) ;
   while (ch != '\n') ;
   printf ("Change identification text ? ") ;
   scanf ("%s",ans) ;
   if (toupper(ans[0]) == 'Y')
      {
      fflush (stdin) ;
      printf ("Enter new identification text:") ;
      gets (library_id) ;
      fprintf (new_fp,"%s",library_id) ;
      fputc (0,new_fp) ;
      while (bget(fp)) ;
      }
   else
      do
         bput (new_fp,ch=bget(fp)) ;
      while (ch) ;
   do
      bput (new_fp,ch=bget(fp)) ;  /* copy copyright text */
   while (ch) ;
   amount_to_add = first_dir_entry = (int)ftell(new_fp) ;
   traverse_tree (tree,add_amount) ;   /* adjust to proper offset */
   }


create_dir_entry(tree_ptr cursor)
   {
   if (!cursor->deleted)
      {
      fputc (0,new_fp) ;
      fprintf (new_fp,"%s\r",cursor->name) ;
      bput (new_fp,cursor->new_offset &0xff);
      bput (new_fp,cursor->new_offset >> 8) ;
      next_dir_entry = (int)ftell (new_fp) ;
      }
   }

copy_module (tree_ptr cursor)
   {
   int loop ;

   if (cursor->deleted == FALSE && cursor->new == FALSE)
      {
      printf ("Committing...%d\r",++module_number) ;
      fseek (fp,cursor->old_offset,SEEK_SET) ;      /* set ptr to old module */
      for (loop = 0 ; loop < cursor->length ; loop++)  /* copy module */
         bput (new_fp,bget(fp)) ;
      }
   }

skip_to_cr(FILE *obj_fp)
   {
   while (fgetc(obj_fp) != '\n') ;
   }


insert_new_module(tree_ptr cursor)
   {
   FILE *obj_fp ;
   int ch ;
   int length ;

   fseek (new_fp,next_dir_entry,SEEK_SET) ;   /* set ptr# to next dir entry */
   create_dir_entry (cursor) ;                /* rewrite directory entry */
   if (!cursor->new)                          /* new ? */
      return ;
   if ((obj_fp = fopen (cursor->filename,"r")) == NULL)
      {
      fprintf (stderr,"Unable to reopen object file %s\n",cursor->filename) ;
      return ;
      }
   printf ("Inserting...%d\r",++module_number) ;
   skip_to_cr(obj_fp) ;                       /* skip header */
   skip_to_cr(obj_fp) ;                       /* skip debug flag + filename */
   fseek (new_fp,-2,SEEK_CUR) ;               /* point to offset for entry */
   bput (new_fp,current_ptr &0xff) ;         /* write new offset */
   bput (new_fp,current_ptr >> 8) ;
   fseek (new_fp,current_ptr,SEEK_SET) ;      /* reset ptr# */
   length = 1 ;
   while ((ch=bget(obj_fp)) != EOF)          /* copy object file */
      {
      bput (new_fp,ch) ;
      length ++ ;
      }
   fputc (0xff,new_fp) ;                      /* terminate module */
   fclose (obj_fp) ;
   cursor->length = length ;                  /* set length */
   cursor->new = FALSE ;                      /* is committed now */
   cursor->old_offset = cursor->new_offset = current_ptr ;    /* set offsets */
   current_ptr = (int)ftell(new_fp) ;         /* save ptr# */
   }

build_temp_name(char *temp)
   {
   int i ;

   for (i=strlen(filename); filename[i] != '.' && i > 0 ; i--) ;
   if (i)                  /* directory found */
      strncpy (temp,filename,i+1) ;    /* include the . */
   else
      temp[0] = '\0' ;
   strcat (temp,"!!!!!!!") ;
   }


commit_changes(void)
   {
   char temp_name [100] ;

   module_number = 0 ;
   build_temp_name (temp_name) ;                 /* build the temp name */
   new_fp = fopen (temp_name,"w") ;              /* open temp file */
   rewind (fp) ;
   copy_header() ;                               /* copy the library header */
   traverse_pre_order (tree,create_dir_entry) ;  /* create the directory */
   fputc (0xff,new_fp) ;                         /* terminate directory */
   traverse_tree (tree,copy_module) ;            /* copy all non-new modules */
   current_ptr = (int) ftell (new_fp) ;
   next_dir_entry = first_dir_entry ;
   if (module_number)
      putchar ('\n');
   module_number = 0 ;
   traverse_pre_order (tree,insert_new_module) ; /* insert new modules at end*/
   if (module_number)
      putchar ('\n') ;
   fclose (new_fp) ;
   fclose (fp) ;
   remove (filename) ;
   rename (temp_name,filename) ;
   }

