/* Convert and concatenate MS-Windows resource files (*.resource)
  before linking.

  Copyright (C) 2003 Free Software Foundation, Inc.

  Authors: Frank Heckenbach <frank@pascal.gnu.de>
	   Prof. Abimbola Olowofoyeku <african_chief@bigfoot.com>
	   
  This file is part of GNU Pascal.

  GNU Pascal is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2, or (at your option)
  any later version.

  GNU Pascal 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 General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with GNU Pascal; see the file COPYING. If not, write to the
  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  02111-1307, USA. */

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifndef __MINGW32__
#include <sys/wait.h>
#endif /* __MINGW32__ */
  
#if defined (MSDOS) || defined (__MINGW32__)  || defined (__MSYS__)  || defined (__CYGWIN32__)
 #include <process.h>
 #ifdef __MSYS__
   #define P_WAIT _P_WAIT
 #endif
 #ifdef __CYGWIN32__
   #define P_WAIT _P_WAIT
 #endif
#else
#define P_WAIT 1

static int spawnvp (int mode, const char *filename, const char *argv[])
{
  pid_t pid;
  int status;
  if (mode != P_WAIT)
    {
      errno = EINVAL;
      return -1;
    }
  pid = fork ();
  if (pid < 0)
    return pid;
  if (pid == 0)
    {
      execvp (filename, (char **) argv);
      perror (filename);
      _exit (127);
    }
  if (waitpid (pid, &status, 0) < 0)
    return -1;
  if (WIFEXITED (status))
    return WEXITSTATUS (status);
  else if (WIFSIGNALED (status))
    return WTERMSIG (status);
  else
    return 127;
}
#endif

int main (int argc, char **argv)
{
  const char *new_argv[argc + 1];
  char *tmp = NULL, *tmp_o = NULL;
  int IsRes;
  int status = 0, i, j = 1, fi, fo;
  new_argv[0] = argv[0];
  for (i = 1; i < argc; i++)
    {
      char *s = argv[i], buf [0x1000];
      int l = strlen (s);

      strcpy (buf, s);
      strlwr (buf);
      if (strstr (buf, ".resource") || strstr (buf, ".res"))  
         IsRes = 1;
      else IsRes = 0;   
      
      /* if (l < 10 || strcmp (s + l - 9, ".resource")) */
      /*
      if ((l < 5 || strcmp (s + l - 4, ".res"))&& (l < 10 || strcmp (s + l - 9, ".resource")))
      */
      if (!IsRes)
        new_argv[j++] = s;
      else
        {
          char sn[l + 1];
          strcpy (sn, s);

          /*
          first check for "filename.resource" - if not found,
          then remove the ".resource" extension
          */
          if (strstr (sn, ".resource"))
          {
            if (access (sn, F_OK) != 0) sn[l - 9] = 0;
          }
	 /* printf ("Filename=%s\n", sn); */
 
          if ((fi = open (sn, O_RDONLY)) < 0)
            {
              fprintf (stderr, "%s: cannot read %s\n", argv[0], sn);
              status = 1;
              break;
            }
          if (!tmp)
            {
              if (!(tmp = tmpnam (NULL)))
                {
                  perror ("tmpnam");
                  return 1;
                }
              if (!(tmp_o = malloc (strlen (tmp) + 3)))
                {
                  fprintf (stderr, "%s: out of memory\n", argv[0]);
                  return 1;
                }
              strcpy (tmp_o, tmp);
              strcat (tmp_o, ".o");
              if ((fo = open (tmp, O_WRONLY | O_CREAT | O_EXCL, 0600)) < 0)
                {
                  perror (tmp);
                  return 1;
                }
            }
          else if (lseek (fi, 32, SEEK_SET) < 0)
            {
              perror ("lseek");
              status = 1;
            }
          while (1)
            {
              int ci, co;
              ci = read (fi, buf, sizeof (buf));
              if (ci == 0)
                break;
              if (ci < 0)
                {
                  perror ("read");
                  status = 1;
                  break;
                }
              co = write (fo, buf, ci);
              if (co != ci)
                {
                  if (co < 0)
                    perror ("write");
                  else
                    fprintf (stderr, "%s: could not write all data to %s\n", argv[0], tmp);
                  status = 1;
                  break;
                }
            }
          if (status != 0)
            break;
        }
    }
    
  if (tmp && status == 0)
    {
      const char *windres_args[6] = { "windres", "-i", tmp, "-o", tmp_o, NULL };
      close (fo);
      new_argv[j++] = tmp_o;
      status = spawnvp (P_WAIT, "windres", windres_args);
      if (status < 0)
        perror ("windres");
      if (status != 0)
        tmp_o = NULL;
    }
  new_argv[j] = NULL;
  if (status == 0)
    status = spawnvp (P_WAIT, "ld.exe", new_argv);
  if (status < 0)
    {
      perror ("ld-orig");
      status = 1;
    }
  if (tmp && remove (tmp) < 0)
    perror (tmp);
  if (tmp_o && remove (tmp_o) < 0)
    perror (tmp_o);
  return status;
}


