diff -Naur xemacs-old/config.guess xemacs-21.1.12/config.guess
--- xemacs-old/config.guess	Fri Jul 14 17:44:35 2000
+++ xemacs-21.1.12/config.guess	Mon Jan  8 20:53:36 2001
@@ -219,6 +219,9 @@
     powerpc:machten:*:*)
 	echo powerpc-apple-machten${UNAME_RELEASE}
 	exit 0 ;;
+    *:Darwin:*:*)
+	echo `uname -p`-apple-darwin${UNAME_RELEASE}
+	exit 0 ;;
     RISC*:Mach:*:*)
 	echo mips-dec-mach_bsd4.3
 	exit 0 ;;
diff -Naur xemacs-old/config.sub xemacs-21.1.12/config.sub
--- xemacs-old/config.sub	Fri Jul 14 17:44:35 2000
+++ xemacs-21.1.12/config.sub	Mon Jan  8 20:53:53 2001
@@ -678,7 +678,7 @@
 	      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
 	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
-	      | -cygwin32* | -pe* | -psos* | -moss* | -openbsd* )
+	      | -cygwin32* | -pe* | -psos* | -moss* | -openbsd* | -darwin* )
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-sunos5*)
diff -Naur xemacs-old/configure xemacs-21.1.12/configure
--- xemacs-old/configure	Thu Aug  3 19:49:54 2000
+++ xemacs-21.1.12/configure	Mon Jan  8 20:47:17 2001
@@ -1200,6 +1200,15 @@
     case "$canonical" in *-hp-hpux*shr* ) opsys="${opsys}-shr" ;; esac
   ;;
 
+    *-*-darwin* ) 
+      opsys=darwin
+      RANLIB='ranlib -c'
+      case "$canonical" in
+        powerpc-*-darwin*) machine=powermacintosh ;;
+        i?86-*-darwin*)    machine=intel386 ;;
+      esac
+      ;;
+
     orion-orion-bsd*   ) machine=orion    opsys=bsd4-2 ;;
   clipper-orion-bsd* ) machine=orion105 opsys=bsd4-2 ;;
 
diff -Naur xemacs-old/configure.in xemacs-21.1.12/configure.in
--- xemacs-old/configure.in	Thu Aug  3 19:49:59 2000
+++ xemacs-21.1.12/configure.in	Mon Jan  8 21:27:41 2001
@@ -1247,6 +1247,16 @@
     case "$canonical" in *-hp-hpux*shr* ) opsys="${opsys}-shr" ;; esac
   ;;
 
+  dnl Darwin / Mac OS X
+  *-*-darwin*)
+    opsys=darwin
+    RANLIB='ranlib -c'
+    case "$canonical" in
+      powerpc-*-darwin*) machine=powermacintosh ;;
+      i?86-*-darwin*)    machine=intel386 ;;
+    esac
+  ;;
+
   dnl Orion machines
   orion-orion-bsd*   ) machine=orion    opsys=bsd4-2 ;;
   clipper-orion-bsd* ) machine=orion105 opsys=bsd4-2 ;;
diff -Naur xemacs-old/src/emacs.c xemacs-21.1.12/src/emacs.c
--- xemacs-old/src/emacs.c	Thu Jul 13 04:53:08 2000
+++ xemacs-21.1.12/src/emacs.c	Mon Jan  8 21:19:48 2001
@@ -527,9 +527,6 @@
   int skip_args = 0;
   Lisp_Object load_me;
   int inhibit_window_system;
-#ifdef NeXT
-  extern int malloc_cookie;
-#endif
 
 #if (!defined (SYSTEM_MALLOC) && !defined (HAVE_LIBMCHECK)	\
      && !defined (DOUG_LEA_MALLOC))
@@ -544,19 +541,6 @@
 
   noninteractive = 0;
 
-#ifdef NeXT
-  /* 19-Jun-1995 -baw
-   * NeXT secret magic, ripped from Emacs-for-NS by Carl Edman
-   * <cedman@princeton.edu>.  Note that even Carl doesn't know what this
-   * does; it was provided by NeXT, and it presumable makes NS's mallocator
-   * work with dumping.  But malloc_jumpstart() and malloc_freezedry() in
-   * unexnext.c are both completely undocumented, even in NS header files!
-   * But hey, it solves all NS related memory problems, so who's
-   * complaining? */
-  if (initialized && malloc_jumpstart (malloc_cookie) != 0)
-    fprintf (stderr, "malloc jumpstart failed!\n");
-#endif /* NeXT */
-
   /*
 #if defined (GNU_MALLOC) && \
     defined (ERROR_CHECK_MALLOC) && \
@@ -2049,6 +2033,10 @@
   /* of the XEmacs binary we are running.  This can now be used in a */
   /* definite test for out of date dumped files.  -slb */
   int restarted = 0;
+#if defined(NeXT)  ||  defined(DARWIN)
+  extern int malloc_cookie;
+#endif
+
 #ifdef QUANTIFY
   quantify_stop_recording_data ();
   quantify_clear_data ();
@@ -2063,6 +2051,22 @@
 #ifdef LINUX_SBRK_BUG
   sbrk (1);
 #endif
+
+#if defined(NeXT)  ||  defined(DARWIN)
+  /* 19-Jun-1995 -baw
+   * NeXT secret magic, ripped from Emacs-for-NS by Carl Edman
+   * <cedman@princeton.edu>.  Note that even Carl doesn't know what this
+   * does; it was provided by NeXT, and it presumable makes NS's mallocator
+   * work with dumping.  But malloc_jumpstart() and malloc_freezedry() in
+   * unexnext.c are both completely undocumented, even in NS header files!
+   * But hey, it solves all NS related memory problems, so who's
+   * complaining? */
+  if (initialized && malloc_jumpstart (malloc_cookie) != 0) 
+    {
+      fprintf (stderr, "malloc jumpstart failed!\n");
+      abort();
+    }
+#endif /* NeXT || DARWIN */
 
   if (!initialized)
     {
diff -Naur xemacs-old/src/lisp.h xemacs-21.1.12/src/lisp.h
--- xemacs-old/src/lisp.h	Mon Feb  7 18:54:56 2000
+++ xemacs-21.1.12/src/lisp.h	Mon Jan  8 20:47:17 2001
@@ -1929,6 +1929,8 @@
 
 #ifdef HAVE_INTTYPES_H
 #include <inttypes.h>
+#elif defined(DARWIN_INTPTR_T)
+/* Darwin automatically defines these types, but not in inttypes.h */
 #elif SIZEOF_VOID_P == SIZEOF_INT
 typedef int intptr_t;
 typedef unsigned int uintptr_t;
diff -Naur xemacs-old/src/m/powermacintosh.h xemacs-21.1.12/src/m/powermacintosh.h
--- xemacs-old/src/m/powermacintosh.h	Wed Dec 31 16:00:00 1969
+++ xemacs-21.1.12/src/m/powermacintosh.h	Mon Jan  8 20:47:17 2001
@@ -0,0 +1,45 @@
+/* Apple Power Macintosh machine/system dependent defines
+   Copyright (C) 1997 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs 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 Emacs 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 Emacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+/* The following line tells the configuration script what sort of 
+   operating system this machine is likely to run.
+   USUAL-OPSYS="darwin"  */
+
+/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
+   is the most significant byte.  */
+
+#define WORDS_BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments.  */
+
+#define NO_ARG_ARRAY
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines.	 */
+
+#define NO_UNION_TYPE
+
+/* Define addresses, macros, change some setup for dump */
+
+#define NO_REMAP
+
+#define DATA_SEG_BITS 0
diff -Naur xemacs-old/src/s/darwin.h xemacs-21.1.12/src/s/darwin.h
--- xemacs-old/src/s/darwin.h	Wed Dec 31 16:00:00 1969
+++ xemacs-21.1.12/src/s/darwin.h	Mon Jan  8 20:47:17 2001
@@ -0,0 +1,97 @@
+/* Configuration file for Darwin OS.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs 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 Emacs 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 Emacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* We give these symbols the numeric values found in <sys/param.h> to
+   avoid warnings about redefined macros.  */
+#define BSD 199506
+#define BSD4_3 1
+#define BSD4_4 1
+
+#include "bsd4-3.h"
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+   It sets the Lisp variable system-type.  We'll need to undo the bsd one. */
+
+#undef SYSTEM_TYPE
+#define SYSTEM_TYPE "darwin"
+
+#ifndef DARWIN
+#define DARWIN
+#endif
+
+#define DARWIN_INTPTR_T
+
+#undef KERNEL_FILE
+#define KERNEL_FILE "/mach_kernel"
+
+#define HAVE_ALLOCA
+
+#ifndef HAVE_MACH_MACH_H
+#define HAVE_MACH_MACH_H
+#endif
+
+#define SYSTEM_MALLOC
+
+#define WAIT_USE_INT
+
+#define SOCKLEN_TYPE int
+
+#define GETPGRP_NO_ARG
+
+#define TERMCAP_FILE "/usr/share/misc/termcap"
+
+#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_p - (FILE)->_bf._base)
+
+#define A_OUT_H_FILE <sys/exec.h>
+
+#define UNEXEC unexdyld.o
+
+/* Definitions for how to compile & link.  */
+
+/* Link this program just by running cc.  */
+#define ORDINARY_LINK
+
+/* #define C_SWITCH_SYSTEM */
+
+/* We don't have a g library, so override the -lg LIBS_DEBUG switch */
+#define LIBS_DEBUG
+
+/* Adding -lm confuses the dynamic linker, so omit it. */
+#define LIB_MATH
+
+/* Definitions for how to dump.  */
+
+#define START_FILES pre-crt0.o
+
+/* start_of_text isn't actually used, so make it compile without error.  */
+#define TEXT_START (0)
+
+#ifndef NOT_C_CODE
+extern unsigned long get_etext(void);
+extern unsigned long get_edata(void);
+#endif
+
+/* This seems to be right for end_of_text, but it may not be used anyway.  */
+#define TEXT_END get_etext()
+
+/* This seems to be right for end_of_data, but it may not be used anyway.  */
+#define DATA_END get_edata()
+
+#define TAB3 OXTABS
diff -Naur xemacs-old/src/unexdyld.c xemacs-21.1.12/src/unexdyld.c
--- xemacs-old/src/unexdyld.c	Wed Dec 31 16:00:00 1969
+++ xemacs-21.1.12/src/unexdyld.c	Mon Jan  8 20:48:27 2001
@@ -0,0 +1,943 @@
+/* Dump Emacs in macho format.
+   Copyright (C) 1990, 1993 Free Software Foundation, Inc.
+   Derived from unexnext.c by Bradley Taylor (btaylor@next.com).
+
+This file is part of GNU Emacs.
+
+GNU Emacs 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 Emacs 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 Emacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#include "config.h"
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <libc.h>
+#include <mach-o/nlist.h>
+#include <mach/mach.h>
+#ifndef NeXT
+#include <mach/machine/vm_param.h>
+#endif
+#include <mach-o/ldsyms.h>
+#include <mach-o/loader.h>
+#include <mach-o/reloc.h>
+
+extern int malloc_freezedry (void);
+
+int malloc_cookie = 0;
+
+#define VERBOSE
+
+#ifdef VERBOSE
+#define SHOW_MCOPY_WRITES
+#endif
+
+typedef struct region_t
+{
+  struct region_t *next;
+  vm_address_t address;
+  vm_size_t size;
+  vm_prot_t protection;
+  vm_prot_t max_protection;
+
+  /* And some info about where it was written to disk. */
+  unsigned long file_offset;
+  unsigned long file_size;
+} region_t;
+
+typedef struct section_list_t
+{
+  struct section_list_t *next;
+  struct section section;
+} section_list_t;
+
+static void fatal_unexec (char *format, ...)
+{
+  va_list ap;
+   
+  va_start (ap, format);
+  fprintf (stderr, "unexec: ");
+  vfprintf (stderr, format, ap);
+  fprintf (stderr, "\n");
+  va_end (ap);
+  exit (1);
+}
+
+static void print_region (struct region_t *region)
+{
+  printf ("0x%8lx - 0x%8lx, length: 0x%8lx, protection: %c%c%c, max_protection: %c%c%c\n",
+	  region->address, region->address + region->size, region->size,
+	  (region->protection & VM_PROT_READ) ? 'r' : '-',
+	  (region->protection & VM_PROT_WRITE) ? 'w' : '-',
+	  (region->protection & VM_PROT_EXECUTE) ? 'x' : '-',
+	  (region->max_protection & VM_PROT_READ) ? 'r' : '-',
+	  (region->max_protection & VM_PROT_WRITE) ? 'w' : '-',
+	  (region->max_protection & VM_PROT_EXECUTE) ? 'x' : '-');
+}
+
+static void print_regions (struct region_t *regions)
+{
+  while (regions != NULL)
+    {
+      print_region (regions);
+      regions = regions->next;
+    }
+}
+
+static void print_section (struct section *section)
+{
+  printf ("0x%8lx - 0x%8lx, length: 0x%8lx, offset: 0x%8lx\n",
+	  section->addr, section->addr + section->size, section->size, section->offset);
+}
+
+static void print_sections (section_list_t *sections)
+{
+  while (sections != NULL)
+    {
+      print_section (&(sections->section));
+      sections = sections->next;
+    }
+}
+
+static section_list_t *create_new_section_list(struct section *section_pointer)
+{
+    section_list_t *section_list;
+
+    section_list = malloc (sizeof (section_list_t));
+    section_list->next = NULL;
+    section_list->section = *section_pointer;
+
+    return section_list;
+}
+
+static void append_section_list(section_list_t **first_list, section_list_t *last_list)
+{
+    section_list_t *current;
+
+    if (*first_list == NULL) {
+        *first_list = last_list;
+        return;
+    }
+
+    current = *first_list;
+    while (current->next != NULL)
+        current = current->next;
+
+    current->next = last_list;
+}
+
+static void free_section_list(section_list_t *section_list)
+{
+    section_list_t *next;
+
+    while (section_list != NULL)
+    {
+        next = section_list->next;
+        free(section_list);
+        section_list = next;
+    }
+}
+
+static void add_sections_from_segment(section_list_t **all_sections, struct segment_command *segment)
+{
+    struct section *section_pointer;
+    int index;
+
+    section_pointer = (struct section *)(segment + 1);
+    for (index = 0; index < segment->nsects; index++) {
+        append_section_list (all_sections, create_new_section_list (section_pointer));
+        section_pointer++;
+    }
+}
+
+static int section_with_address (section_list_t *sections, unsigned long address)
+{
+    int current_section, found_section;
+
+    found_section = 0;
+    current_section = 1;
+    while (sections != NULL)
+    {
+        if (address >= sections->section.addr && address < sections->section.addr + sections->section.size) {
+            found_section = current_section;
+            break;
+        }
+        sections = sections->next;
+        current_section++;
+    }
+
+    return found_section;
+}
+
+/*
+ * Copy len bytes from ffd@fpos to tfd@tpos.
+ * If both file descriptors are -1, copy in memory (handles overlapping copies).
+ * If either ffd or tfd are -1, either read or write len bytes.
+ */
+
+static void mcopy (int ffd, int tfd,
+                   unsigned long fpos, unsigned long tpos, unsigned long len, char *reason)
+{
+  if ((ffd == -1) && (tfd == -1))
+    {
+      char *f, *t, *e;
+      if (fpos > tpos)
+        {
+	  f = (char *)fpos;
+	  t = (char *)tpos;
+	  e = (char *)(fpos + len);
+	  while (f < e) *t++ = *f++;
+        }
+      else if (tpos > fpos)
+        {
+	  f = (char *)(fpos + len);
+	  t = (char *)(tpos + len);
+	  e = (char *)fpos;
+	  while (f > e) *--t = *--f;         
+        }   
+      printf ("read: %10lu - %10lu, length: %10lu [from MEM]  (%s)\n", tpos, tpos+len, len, reason);
+    }
+  else if (ffd == -1)
+    {
+      if (lseek (tfd, tpos, L_SET) < 0)
+	fatal_unexec ("cannot seek target");
+      if (write (tfd, (void *)fpos, len) != len)
+	fatal_unexec ("cannot write target");
+#ifdef SHOW_MCOPY_WRITES
+      printf ("write: %10lu - %10lu, length: %10lu [from MEM]  (%s)\n", tpos, tpos+len, len, reason);
+#endif
+    }
+  else if (tfd == -1)
+    {
+      if (lseek (ffd, fpos, L_SET) < 0)
+	fatal_unexec ("cannot seek source");
+      if (read (ffd, (void *)tpos, len) != len)
+	fatal_unexec ("cannot read source");
+      printf ("read: %10lu - %10lu, length: %10lu [from DISK] (%s)\n", tpos, tpos+len, len, reason);
+    }
+  else
+    {
+      int bread;
+      char *buf = alloca (1 << 16);
+
+#ifdef SHOW_MCOPY_WRITES
+      printf ("write: %10lu - %10lu, length: %10lu [from DISK] (%s)\n", tpos, tpos+len, len, reason);
+#endif
+
+      if (lseek (ffd, fpos, L_SET) < 0)
+	fatal_unexec ("cannot seek source");
+      
+      if (lseek (tfd, tpos, L_SET) < 0)
+	fatal_unexec ("cannot seek target");
+      
+      while((len > 0) && (bread = read (ffd, buf, MIN(1 << 16, len))) > 0)
+        {
+	  if (bread < 0)
+	    fatal_unexec ("cannot read source");
+	  if (write (tfd, buf, bread) != bread)
+	    fatal_unexec ("cannot write target");
+	  len -= bread;
+        }
+    }
+}
+
+/*
+ * The process of dumping (or unexecing) is the opposite of exec().
+ * It takes the original executable and parts of memory that have been
+ * loaded with data, and creates a new executable.  This allows
+ * standard lisp files to be loaded "instantly", because they are part
+ * of the executable.
+ *
+ * This involves using vm_region() to build a list of allocated memory
+ * regions, combining adjacent "similar" regions to reduce their
+ * number, skipping read-only regions and parts of regions covered by
+ * non-data segment load commands, and finally replacing the (usually
+ * one) data segment with a new segment for each region.
+ *
+ * File offsets in load commands that follow the data segment must be
+ * adjusted by the change in size of the data segment.  The size of
+ * the load commands can increase without affecting file offsets --
+ * see the note below.
+ *
+ * Data associated with the LC_SYMTAB and LC_DYSYMTAB is found in the
+ * __LINKEDIT segment -- there is no extra data to be written for
+ * these load commands.
+ *
+ * Relocatable symbols from the data segment, which we took from
+ * memory, need to be unrelocated.  The relocatable address is found
+ * in the new mach-o file and then zeroed out.  Failure to do this
+ * typically results in a segmentation fault, with the offending
+ * address being double what it is at the same point in temacs, since
+ * it has been relocated twice.
+ *
+ * Be sure to study the loader.h file if you want to understand this.
+ * otool -lv shows the load commands of the file, and is very useful
+ * when debugging this code.  Also, 'size -m -x -l' gives a short
+ * list of the sections, and 'nm -maxp' and 'nm -map' are useful
+ * for the symbol table stuff.
+ *
+ * Note: This is not obvious, but the __TEXT section usually has a
+ *       file offset of 0, and so when it is written it will overwrite
+ *       any mach headers or load commands that have already been
+ *       written...  How much room is there before critial parts are
+ *       overwritten when we add load commands?
+ *
+ *    -- Steve Nygard
+ */
+
+static void unexec_doit(int infd,int outfd)
+{
+  int i, j, l, header_position, output_position;
+  region_t *regions = NULL, *cregion, **pregions;
+  struct mach_header mach_header;
+  struct load_command *load_command, *original_load_commands;
+  struct segment_command *segment_pointer;
+  struct symtab_command *symtab_pointer;
+  struct section *section_pointer;
+  section_list_t *all_sections = NULL;
+
+  unsigned long delta = 0;
+#if defined(NS_TARGET) || !defined(NeXT)
+  struct dysymtab_command *dysymtab;
+  unsigned long extreloff = 0;
+  unsigned long nextrel = 0;
+  unsigned long locreloff = 0;
+  unsigned long nlocrel = 0;
+  struct relocation_info reloc_info;
+  unsigned long fixed_reloc_count = 0;
+#endif
+
+  struct segment_command new_data_segment;
+  section_list_t *original_sections, *new_sections, **sect_ptr, *section_item;
+
+  malloc_cookie = malloc_freezedry();
+#ifdef VERBOSE
+  printf ("malloc_cookie: %lx\n", malloc_cookie);
+#endif
+   
+  {
+    vm_address_t address;
+    vm_size_t size;
+    mach_port_t object_name;
+#ifdef DARWIN
+    task_t task = mach_task_self();
+    struct vm_region_basic_info info;
+    mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
+#else
+    task_t task = task_self();
+    vm_prot_t protection, max_protection;
+    vm_inherit_t inheritance;
+    boolean_t shared;
+    vm_offset_t offset;
+#endif
+
+    for (address = VM_MIN_ADDRESS, pregions = &regions;
+#ifdef DARWIN
+	 vm_region(task, &address, &size, VM_REGION_BASIC_INFO, 
+		   (vm_region_info_t)&info, &info_count, &object_name) == KERN_SUCCESS;
+#else
+	 vm_region(task, &address, &size, &protection, &max_protection,
+		   &inheritance, &shared, &object_name, &offset) == KERN_SUCCESS;
+#endif
+	 address += size)
+      {
+	(*pregions) = alloca (sizeof(region_t));
+	(*pregions)->address = address;
+	(*pregions)->size = size;
+#ifdef DARWIN
+	(*pregions)->protection = info.protection;
+	(*pregions)->max_protection = info.max_protection;
+#else
+	(*pregions)->protection = protection;
+	(*pregions)->max_protection = max_protection;
+#endif
+	(*pregions)->file_offset = 0;
+	(*pregions)->file_size = 0;
+	(*pregions)->next = 0;
+	pregions = &((*pregions)->next);
+#ifdef DARWIN
+	if (object_name != MACH_PORT_NULL)
+	  mach_port_deallocate(mach_task_self(), object_name);
+	info_count = VM_REGION_BASIC_INFO_COUNT;
+#endif
+      }
+  }
+#ifdef VERBOSE   
+  printf ("Regions.\n");
+  print_regions (regions);
+  printf ("----------------------------------------------------------------------\n");
+#endif
+   
+  /*
+   * Concatenate regions that are adjacent in memory and share the same
+   * protection attributes.
+   */
+
+  for (cregion = regions; cregion; cregion = cregion->next)
+    {
+      while ((cregion->next) &&
+	     (cregion->next->address == cregion->address + cregion->size) &&
+	     (cregion->next->protection == cregion->protection) &&
+	     (cregion->next->max_protection == cregion->max_protection))
+        {
+	  cregion->size += cregion->next->size;
+	  cregion->next = cregion->next->next;
+        }
+    }
+#ifdef VERBOSE   
+  printf ("Concatenated regions.\n");
+  print_regions (regions);
+  printf ("----------------------------------------------------------------------\n");
+#endif
+
+  /*
+   * Remove read-only regions, and regions above a fixed limit.
+   * Could have been done before allocating, but this way we can show
+   * the regions before and after while debugging.
+   */
+
+  for (pregions = &regions; *pregions != NULL;)
+    {
+      if ( !((*pregions)->protection & VM_PROT_WRITE)
+	   || ((*pregions)->address >= 0x3000000))
+        {
+	  *pregions = (*pregions)->next;
+        }
+      else
+        {
+	  pregions = &((*pregions)->next);
+        }
+    }
+#ifdef VERBOSE
+  printf ("Skipped regions.\n");
+  print_regions (regions);
+  printf ("----------------------------------------------------------------------\n");
+#endif
+  /*
+     * Read original mach header and load commands.
+     */
+
+  mcopy (infd, -1, 0, (unsigned long) &mach_header, sizeof(mach_header), "read original mach header");
+  original_load_commands = alloca (mach_header.sizeofcmds);
+  mcopy (infd, -1, sizeof(mach_header), (unsigned long) original_load_commands, mach_header.sizeofcmds,
+         "read original load comands");
+
+  /*
+     * Skip (or adjust) regions that intersect memory represented by non-data
+     * segments from the original load commands.
+     */
+
+  for (pregions = &regions; *pregions;)
+    {
+      for (load_command = original_load_commands, i = 0;
+	   i < mach_header.ncmds;
+	   i++, load_command = (struct load_command *)(((void *)load_command) + load_command->cmdsize))
+        {
+	  unsigned long ob, oe;
+	  segment_pointer = (struct segment_command *)load_command;
+	  if (segment_pointer->cmd != LC_SEGMENT || (strcmp (segment_pointer->segname, SEG_DATA) == 0)) continue;
+	  ob = MAX((*pregions)->address, segment_pointer->vmaddr);
+	  oe = MIN((*pregions)->address + (*pregions)->size, segment_pointer->vmaddr + segment_pointer->vmsize);
+	  if (ob >= oe) continue;
+	  if (ob == (*pregions)->address)
+            {
+	      if (oe == (*pregions)->address + (*pregions)->size)
+                {
+		  goto skip_region;
+                }
+	      else
+                {
+		  (*pregions)->address = oe;
+		  (*pregions)->size -= (oe - ob);
+                }
+            }
+	  else
+            {
+	      if (oe == (*pregions)->address + (*pregions)->size)
+                {
+		  (*pregions)->size -= (oe - ob);
+                }
+	      else
+                {
+		  cregion = alloca (sizeof(*cregion));
+		  cregion->address = oe;
+		  cregion->size = ((*pregions)->address + (*pregions)->size) - oe;
+		  cregion->protection = (*pregions)->protection;
+		  cregion->max_protection = (*pregions)->max_protection;
+		  cregion->file_offset = 0;
+		  cregion->file_size = 0;
+		  cregion->next = (*pregions)->next;
+		  (*pregions)->size = ob - (*pregions)->address;
+		  (*pregions)->next = cregion;
+                }
+            }
+        }
+
+      pregions = &((*pregions)->next);
+      continue;
+
+    skip_region:
+      *pregions = (*pregions)->next;
+    }
+#ifdef VERBOSE
+  printf ("Munged regions (1).\n");
+  print_regions (regions);
+  printf ("----------------------------------------------------------------------\n");
+#endif
+
+  for (load_command = original_load_commands, i = mach_header.ncmds, header_position = sizeof(mach_header), output_position = 0;
+       i > 0;
+       i--, load_command = (struct load_command *)(((void *)load_command) + load_command->cmdsize))
+    {
+      switch (load_command->cmd)
+        {
+	case LC_SEGMENT:
+	  segment_pointer = (struct segment_command *)load_command;
+
+	  if (strcmp (segment_pointer->segname, SEG_DATA) == 0)
+	    {
+#if 1
+	      unsigned long current_address;
+
+	      original_sections = NULL;
+	      new_sections = NULL;
+	      sect_ptr = &original_sections;
+
+	      section_pointer = (struct section *)(segment_pointer + 1);
+	      for (l = 0; l < segment_pointer->nsects; l++)
+		{
+		  if (!strncmp (section_pointer->sectname, "__la_symbol_ptr", 16))
+		    {
+		      section_item = alloca (sizeof (section_list_t));
+		      section_item->next = *sect_ptr;
+		      section_item->section = *section_pointer;
+		      *sect_ptr = section_item;
+		      sect_ptr = &(section_item->next);
+		    }
+		  else if (!strncmp (section_pointer->sectname, "__nl_symbol_ptr", 16))
+		    {
+		      section_item = alloca (sizeof (section_list_t));
+		      section_item->next = *sect_ptr;
+		      section_item->section = *section_pointer;
+		      *sect_ptr = section_item;
+		      sect_ptr = &(section_item->next);
+		    }
+		  else if (!strncmp (section_pointer->sectname, "__dyld", 16))
+		    {
+		      section_item = alloca (sizeof (section_list_t));
+		      section_item->next = *sect_ptr;
+		      section_item->section = *section_pointer;
+		      *sect_ptr = section_item;
+		      sect_ptr = &(section_item->next);
+		    }
+
+		  section_pointer++;
+		}
+
+	      cregion = regions;
+	      /* new_data_segment */
+	      new_data_segment.cmd = LC_SEGMENT;
+	      strncpy (new_data_segment.segname, SEG_DATA, 16);
+	      new_data_segment.vmaddr = cregion->address;
+	      new_data_segment.vmsize = 0;
+	      new_data_segment.fileoff = 0;
+	      new_data_segment.filesize = 0;
+	      new_data_segment.maxprot = cregion->max_protection;
+	      new_data_segment.initprot = cregion->protection;
+	      new_data_segment.flags = segment_pointer->flags;
+	      new_data_segment.nsects = 0;
+	      new_data_segment.cmdsize = sizeof (struct segment_command);
+#ifdef VERBOSE
+	      printf ("Original sections:\n");
+	      print_sections (original_sections);
+	      printf ("----------------------------------------------------------------------\n");
+#endif
+	      /* Create list of new segments */
+	      sect_ptr = &new_sections;
+	      current_address = new_data_segment.vmaddr;
+	      while (original_sections != NULL)
+		{
+		  if (current_address < original_sections->section.addr)
+		    {
+		      /* Create new section for this. */
+		      section_item = alloca (sizeof (section_list_t));
+		      section_item->next = *sect_ptr;
+
+		      section_pointer = &(section_item->section);
+		      strncpy (section_pointer->sectname, "__data", 16);
+		      strncpy (section_pointer->segname, SEG_DATA, 16);
+		      section_pointer->addr = current_address;
+		      section_pointer->size = original_sections->section.addr - current_address;
+		      section_pointer->offset = 0;
+		      section_pointer->align = 2; /* Yuck. */
+		      section_pointer->reloff = 0;
+		      section_pointer->nreloc = 0;
+		      section_pointer->flags = 0; /* S_REGULAR? */
+		      section_pointer->reserved1 = 0;
+		      section_pointer->reserved2 = 0;
+
+		      *sect_ptr = section_item;
+		      sect_ptr = &(section_item->next);
+		      current_address = original_sections->section.addr;
+		    }
+
+		  /* Put/copy this section into new list */
+		  section_item = original_sections;
+		  original_sections = original_sections->next;
+		  section_item->next = *sect_ptr; /* Should be NULL... */
+		  *sect_ptr = section_item;
+		  sect_ptr = &(section_item->next);
+
+		  /* increase current address */
+		  current_address += section_item->section.size;
+		}
+	      /* if current address < end of region, add final section. */
+	      if (current_address < cregion->address + cregion->size)
+		{
+		  /* Create new section for this. */
+		  section_item = alloca (sizeof (section_list_t));
+		  section_item->next = *sect_ptr;
+
+		  section_pointer = &(section_item->section);
+		  strncpy (section_pointer->sectname, "__data", 16);
+		  strncpy (section_pointer->segname, SEG_DATA, 16);
+		  section_pointer->addr = current_address;
+		  section_pointer->size = cregion->address + cregion->size - current_address;
+		  section_pointer->offset = 0;
+		  section_pointer->align = 2; /* Yuck. */
+		  section_pointer->reloff = 0;
+		  section_pointer->nreloc = 0;
+		  section_pointer->flags = 0; /* S_REGULAR? */
+		  section_pointer->reserved1 = 0;
+		  section_pointer->reserved2 = 0;
+
+		  *sect_ptr = section_item;
+		  sect_ptr = &(section_item->next);
+
+		}
+#ifdef VERBOSE
+	      printf ("New sections:\n");
+	      print_sections (new_sections);
+	      printf ("----------------------------------------------------------------------\n");
+#endif
+	      /**
+	       * Go through new list of sections
+	       *  - write section to disk, either from memory or original file
+	       *  - say, if offset == 0, take from memory, otherwise from original file at that offset
+	       *  - set offset of section
+	       *  - set fileoff of segment to be that of the first section
+	       *  - increase output position
+	       **/
+
+	      sect_ptr = &new_sections;
+	      while (*sect_ptr != NULL)
+		{
+		  section_pointer = &((*sect_ptr)->section);
+		  if (new_data_segment.fileoff == 0)
+		    new_data_segment.fileoff = output_position;
+		  new_data_segment.vmsize += section_pointer->size;
+		  new_data_segment.filesize += section_pointer->size;
+		  new_data_segment.nsects++;
+		  new_data_segment.cmdsize += sizeof (struct section);
+                  printf ("section is '%s'\n", section_pointer->sectname);
+		  if (section_pointer->offset == 0)
+		    {
+		      mcopy (-1, outfd, (unsigned long) section_pointer->addr, output_position, section_pointer->size,
+                             "SEG_DATA: write section data from memory");
+		    }
+		  else
+		    {
+		      mcopy (infd, outfd, (unsigned long) section_pointer->offset, output_position, section_pointer->size,
+                             "SEG_DATA: write section data from original file");
+		    }
+		  section_pointer->offset = output_position;
+		  output_position += section_pointer->size;
+
+		  sect_ptr = &((*sect_ptr)->next);
+		}
+
+	      /* Write data segment and sections, increasing the header position */
+	      mcopy (-1, outfd, (unsigned long) &new_data_segment, header_position, sizeof (struct segment_command),
+                     "SEG_DATA: write segment command");
+	      header_position += sizeof (struct segment_command);
+	      while (new_sections != NULL)
+		{
+		  mcopy (-1, outfd, (unsigned long) &(new_sections->section), header_position, sizeof (struct section),
+                         "SEG_DATA: write section command");
+                  // Need to add this section to a list of all the sections
+		  header_position += sizeof (struct section);
+                  append_section_list (&all_sections, create_new_section_list (&(new_sections->section)));
+		  new_sections = new_sections->next;
+		}
+	      mach_header.ncmds++;
+
+	      /* Finally, skip first data segment. */
+	      regions = regions->next;
+#endif
+
+#if 1
+	      /* Write remainder of regions as data segments */
+	      mach_header.ncmds--;
+	      j = segment_pointer->cmdsize; /* Save original command size for loop. */
+	      for (cregion = regions; cregion != NULL; cregion = cregion->next)
+		{
+		  mcopy (-1, outfd, cregion->address, output_position, cregion->size,
+                         "SEG_DATA: write remainder data");
+		  segment_pointer->cmd = LC_SEGMENT;
+		  segment_pointer->cmdsize = sizeof(*segment_pointer);
+		  strncpy (segment_pointer->segname, SEG_DATA, sizeof(segment_pointer->segname));
+		  segment_pointer->vmaddr = cregion->address;
+		  segment_pointer->vmsize = cregion->size;
+		  segment_pointer->filesize = cregion->size;
+		  segment_pointer->maxprot = cregion->max_protection;
+		  segment_pointer->initprot = cregion->protection;
+		  segment_pointer->nsects = 0;
+		  segment_pointer->flags = 0;
+		  segment_pointer->fileoff = output_position;
+		  output_position += segment_pointer->filesize;
+		  mcopy (-1, outfd, (unsigned long)segment_pointer, header_position, segment_pointer->cmdsize,
+                         "SEG_DATA: write segment command for remainder data");
+		  header_position += segment_pointer->cmdsize;
+		  mach_header.ncmds++;
+
+		  cregion->file_offset = segment_pointer->fileoff;
+		  cregion->file_size = segment_pointer->filesize;
+		}
+	      segment_pointer->cmdsize = j;
+
+#endif
+	    }
+	  else
+	    {
+              printf ("segment is '%s':\n", segment_pointer->segname);
+	      mcopy (infd, outfd, segment_pointer->fileoff, output_position, segment_pointer->filesize,
+                     "SEG_OTHER: write segment data");
+	      section_pointer = (struct section *) (((void *)segment_pointer)+sizeof(*segment_pointer));
+	      for(j = 0; j < segment_pointer->nsects; j++)
+		{
+		  if (section_pointer[j].offset != 0)
+		    section_pointer[j].offset = (section_pointer[j].offset - segment_pointer->fileoff) + output_position;
+		  if (section_pointer[j].reloff != 0)
+		    section_pointer[j].reloff = (section_pointer[j].reloff - segment_pointer->fileoff) + output_position;
+		}
+
+	      if (strcmp (segment_pointer->segname, SEG_LINKEDIT) == 0)
+		{
+		  delta = output_position - segment_pointer->fileoff;
+		}
+
+	      segment_pointer->fileoff = output_position;
+	      output_position += segment_pointer->filesize;
+
+	      mcopy (-1, outfd, (unsigned long)load_command, header_position, load_command->cmdsize,
+                     "SEG_OTHER: write segment command and its sections");
+	      header_position += load_command->cmdsize;
+
+              // Now, scan the segments for sections, so we have a list of all the sections to use to fix up
+              // the symbol table entries.
+              add_sections_from_segment(&all_sections, segment_pointer);
+	    }
+	  break;
+
+	case LC_SYMTAB:
+        {
+            struct nlist *symtab;
+
+            symtab_pointer = (struct symtab_command *)load_command;
+
+            symtab = malloc(symtab_pointer->nsyms * sizeof(struct nlist));
+            mcopy(infd, -1, symtab_pointer->symoff, (unsigned long)symtab, symtab_pointer->nsyms * sizeof(struct nlist),
+                  "Read old symbol table into memory");
+
+            symtab_pointer->symoff += delta;
+            symtab_pointer->stroff += delta;
+            mcopy (-1, outfd, (unsigned long)load_command, header_position, load_command->cmdsize,
+                   "write symtab command");
+            header_position += load_command->cmdsize;
+            printf ("LC_SYMTAB: symoff = %ld, nsyms = %ld, stroff = %ld, strsize = %ld\n",
+                    symtab_pointer->symoff, symtab_pointer->nsyms, symtab_pointer->stroff, symtab_pointer->strsize);
+
+            // We've already written out the symbol table, but we're going to read it back in, adjust the
+            // symbol table entries, and write out the result again.
+
+            if (all_sections != NULL)
+            {
+                int index;
+                struct nlist *nlist_pointer;
+                section_list_t *section;
+                int section_index;
+                int changed_symtabs;
+
+                printf ("All sections:\n");
+                print_sections (all_sections);
+
+                changed_symtabs = 0;
+                nlist_pointer = symtab;
+
+                for (index = 0; index < symtab_pointer->nsyms; index++) {
+                    if ((nlist_pointer->n_type & N_TYPE) == N_SECT) {
+                        section_index = section_with_address(all_sections, nlist_pointer->n_value);
+#if 0
+                        printf ("%5d: 0x%08lx 0x%02x 0x%02x (0x%02x) 0x%04x 0x%08lx\n",
+                                index, nlist_pointer->n_un.n_strx, nlist_pointer->n_type & 0xff, nlist_pointer->n_sect & 0xff,
+                                section_index,
+                                nlist_pointer->n_desc & 0xffff, nlist_pointer->n_value);
+#endif
+                        if (nlist_pointer->n_sect != section_index) {
+                            nlist_pointer->n_sect = section_index;
+                            changed_symtabs++;
+                        }
+                    }
+                    nlist_pointer++;
+                }
+
+                printf ("Adjusted n_sect for %d symbol table entries.\n", changed_symtabs);
+                mcopy(-1, outfd, (unsigned long)symtab, symtab_pointer->symoff, symtab_pointer->nsyms * sizeof(struct nlist),
+                      "write updated symbol table");
+
+                free_section_list(all_sections);
+            }
+
+            free(symtab);
+        }
+        break;
+#if defined(NS_TARGET) || !defined(NeXT)
+	case LC_DYSYMTAB:
+	  dysymtab = (struct dysymtab_command *)load_command;
+	  extreloff = dysymtab->extreloff;
+	  nextrel = dysymtab->nextrel;
+
+	  locreloff = dysymtab->locreloff;
+	  nlocrel = dysymtab->nlocrel;
+
+	  if (dysymtab->nindirectsyms > 0) {
+	    dysymtab->indirectsymoff += delta;
+	  }
+	  if (nextrel > 0) {
+	    dysymtab->extreloff += delta;
+	  }
+
+	  if (nlocrel > 0) {
+	    dysymtab->locreloff += delta;
+	  }
+	  mcopy (-1, outfd, (unsigned long)load_command, header_position, load_command->cmdsize,
+                 "write dysymtab command");
+	  header_position += load_command->cmdsize;
+
+	  break;
+#endif
+	default:
+	  mcopy (-1, outfd, (unsigned long)load_command, header_position, load_command->cmdsize,
+                 "write other load command");
+	  header_position += load_command->cmdsize;
+        }
+    }
+
+  mach_header.sizeofcmds = header_position - sizeof(mach_header);
+  mcopy (-1, outfd, (unsigned long) &mach_header, 0, sizeof(mach_header), "write mach header");
+
+#if defined(NS_TARGET) || !defined(NeXT)
+  if (mach_header.flags & MH_PREBOUND) {
+    /* Don't mess with prebound executables */
+    return;
+  }
+
+  /*
+     * Fix up relocation entries in the data segment(s).
+     */
+  if (lseek (infd, locreloff, L_SET) < 0)
+    fatal_unexec ("cannot seek input file");
+
+  fixed_reloc_count = 0;
+  for (i = 0; i < nlocrel; i++)
+    {
+      long zeroval = 0;
+      struct scattered_relocation_info *si;
+
+      if (read (infd, &reloc_info, sizeof(reloc_info)) != sizeof(reloc_info))
+	fatal_unexec ("cannot read input file");
+
+#if 1
+#ifdef VERBOSE
+      printf ("%2d: reloc: %lx, start: %lx, end: %lx\n", i, reloc_info.r_address,
+	      new_data_segment.vmaddr, new_data_segment.vmaddr + new_data_segment.filesize);
+#endif
+      if (reloc_info.r_address >= new_data_segment.vmaddr
+	  && reloc_info.r_address < new_data_segment.vmaddr + new_data_segment.filesize)
+        {
+	  fixed_reloc_count++;
+	  mcopy (-1, outfd, (unsigned long) &zeroval,
+		 new_data_segment.fileoff + reloc_info.r_address - new_data_segment.vmaddr,
+		 1 << reloc_info.r_length, "fix local relocation entry");
+        }
+#endif
+    }
+  printf ("Fixed %lu/%lu local relocation entries in data segment(s).\n", fixed_reloc_count, nlocrel);
+
+  if (lseek (infd, extreloff, L_SET) < 0)
+    fatal_unexec ("cannot seek input file");
+
+  for (i = 0; i < nextrel; i++)
+    {
+      long zeroval = 0;
+
+      if (read (infd, &reloc_info, sizeof(reloc_info)) != sizeof(reloc_info))
+	fatal_unexec ("cannot read input file");
+
+#if 1
+#ifdef VERBOSE
+      printf ("%2d: reloc: %lx, start: %lx, end: %lx\n", i, reloc_info.r_address,
+	      new_data_segment.vmaddr, new_data_segment.vmaddr + new_data_segment.filesize);
+#endif
+      if (reloc_info.r_address >= new_data_segment.vmaddr
+	  && reloc_info.r_address < new_data_segment.vmaddr + new_data_segment.filesize)
+        {
+	  fixed_reloc_count++;
+	  mcopy (-1, outfd, (unsigned long) &zeroval,
+		 new_data_segment.fileoff + reloc_info.r_address - new_data_segment.vmaddr,
+		 1 << reloc_info.r_length, "fix external relocation entry");
+        }
+#endif
+    }
+
+  printf ("Fixed %lu/%lu external relocation entries in data segment(s).\n", fixed_reloc_count, nextrel);
+
+#endif
+}
+
+void unexec (char *outfile, char *infile)
+{
+  char tmpfile[MAXPATHLEN + 1];
+  int infd, outfd;
+   
+  if ((infd = open (infile, O_RDONLY, 0)) < 0)
+    fatal_unexec ("cannot open input file `%s'", infile);
+
+  strcpy (tmpfile, outfile);
+  strcat (tmpfile, "-temp");
+   
+  if ((outfd = open (tmpfile, O_RDWR|O_TRUNC|O_CREAT, 0755)) < 0)
+    fatal_unexec ("cannot open temporary output file `%s'", tmpfile);
+
+  unexec_doit (infd, outfd);
+
+  close (infd);
+  close (outfd);
+  if (rename (tmpfile, outfile) < 0)
+    {
+      unlink (tmpfile);
+      fatal_unexec ("cannot rename `%s' to `%s'", tmpfile, outfile);
+    }  
+}
