/* omflibcp.c (emx+gcc) */

/* Copy a module from one OMFLIB to another OMFLIB.

Copyright (c) 1993 Eberhard Mattes

This file is part of the emx OMFLIB library.  This library is free
software; you can redistribute it and/or modify it under the terms of
the GNU Library General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.  This library is distributed in the hope
that it will be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.

As a special exception, programs written by Eberhard Mattes can use
this library without restrictions unless changed by someone else. */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "omflib0.h"
#include "omflib.h"


static struct omflib *pubdef_dst_lib;
static word pubdef_page;


static int add_pubdef (const char *name, char *error);


int omflib_copy_module (struct omflib *dst_lib, FILE *dst_file,
                        struct omflib *src_lib, FILE *src_file,
                        const char *mod_name, char *error)
{
  struct omf_rec rec;
  word page;
  long long_page;
  char name[256];
  byte buf[1024];

  if (dst_lib != NULL)
    {
      long_page = ftell (dst_file) / dst_lib->page_size;
      if (long_page > 65535)
        {
          strcpy (error, "Library too big -- increase page size");
          return (-1);
        }
      page = (word)long_page;
    }
  else
    page = 0;
  do
    {
      if (fread (&rec, sizeof (rec), 1, src_file) != 1)
        goto failure_src;
      if (rec.rec_len > sizeof (buf))
        {
          strcpy (error, "Record too long");
          return (-1);
        }
      if (fread (buf, rec.rec_len, 1, src_file) != 1)
        goto failure_src;
      if (!(dst_lib == NULL && rec.rec_type == COMENT && rec.rec_len >= 2
            && buf[1] == LIBMOD_CLASS))
        {
          if (fwrite (&rec, sizeof (rec), 1, dst_file) != 1)
            return (omflib_set_error (error));
          if (fwrite (buf, rec.rec_len, 1, dst_file) != 1)
            return (omflib_set_error (error));
        }
      if (dst_lib != NULL)
        {
          if (rec.rec_type == PUBDEF || rec.rec_type == (PUBDEF|REC32))
            {
              pubdef_dst_lib = dst_lib;
              pubdef_page = page;
              if (omflib_pubdef (&rec, buf, page, add_pubdef, error) != 0)
                return (-1);
            }
          else if (rec.rec_type == COMENT && rec.rec_len >= 2 &&
                   buf[1] == IMPDEF_CLASS && buf[2] == IMPDEF_SUBTYPE)
            {
              pubdef_dst_lib = dst_lib;
              pubdef_page = page;
              if (omflib_impdef (&rec, buf, page, add_pubdef, error) != 0)
                return (-1);
            }
        }
    } while (rec.rec_type != MODEND && rec.rec_type != (MODEND|REC32));
  if (dst_lib != NULL)
    {
      _strncpy (name, mod_name, 255);
      strcat (name, "!");
      if (omflib_add_pub (dst_lib, name, page, error) != 0)
        return (-1);
      if (omflib_pad (dst_file, dst_lib->page_size, FALSE, error) != 0)
        return (-1);
    }
  return (0);
  
failure_src:
  if (ferror (src_file))
    return (omflib_set_error (error));
  strcpy (error, "Unexpected end of file");
  return (-1);
}


static int add_pubdef (const char *name, char *error)
{
  return (omflib_add_pub (pubdef_dst_lib, name, pubdef_page, error));
}
