entered into RCS
authorJim Blandy <jimb@redhat.com>
Mon, 13 Jan 1992 21:48:03 +0000 (21:48 +0000)
committerJim Blandy <jimb@redhat.com>
Mon, 13 Jan 1992 21:48:03 +0000 (21:48 +0000)
43 files changed:
src/XTests.c
src/XTests.h [new file with mode: 0644]
src/abbrev.c
src/acldef.h [new file with mode: 0644]
src/casefiddle.c
src/casetab.c
src/chpdef.h [new file with mode: 0644]
src/cm.c [new file with mode: 0644]
src/disptab.h [new file with mode: 0644]
src/doprnt.c
src/indent.h [new file with mode: 0644]
src/insdel.c
src/ioctl.h [new file with mode: 0644]
src/lastfile.c [new file with mode: 0644]
src/line.h [new file with mode: 0644]
src/macros.h [new file with mode: 0644]
src/marker.c
src/mocklisp.c
src/mocklisp.h
src/ndir.h [new file with mode: 0644]
src/param.h [new file with mode: 0644]
src/point.h [new file with mode: 0644]
src/pre-crt0.c [new file with mode: 0644]
src/puresize.h
src/sink.h [new file with mode: 0644]
src/sink11.h [new file with mode: 0644]
src/sink11mask.h [new file with mode: 0644]
src/terminfo.c [new file with mode: 0644]
src/uaf.h
src/unexconvex.c [new file with mode: 0644]
src/unexelf.c [new file with mode: 0644]
src/unexenix.c [new file with mode: 0644]
src/unexhp9k800.c
src/vlimit.h [new file with mode: 0644]
src/vms-pp.c
src/vms-pwd.h [new file with mode: 0644]
src/vmsdir.h [new file with mode: 0644]
src/vmsfns.c
src/vmsmap.c [new file with mode: 0644]
src/vmspaths.h [new file with mode: 0644]
src/vmsproc.c
src/vmsproc.h [new file with mode: 0644]
src/xscrollbar.h [new file with mode: 0644]

index 9c1d366..4147ecd 100644 (file)
@@ -67,8 +67,8 @@ main (argc,argv)
   int depth;
   Pixmap pix;
   char *string = "Kill the head and the body will die.";
-  char dash_list[] = {6, 4, 6, 4};
-  int dashes = 4;
+  char dash_list[] = {4, 4};
+  int dashes = 2;
 
   if (argc < 2)
     dpy_string = "localhost:0.0";
@@ -105,24 +105,19 @@ main (argc,argv)
                       &gc_values);
 
   gc_values.foreground = obtain_color ("red");
-  gc_values.function = GXor;
   gc_values.line_width = 3;
   gc_values.line_style = LineOnOffDash;
   gc_values.cap_style = CapRound;
   gc_values.join_style = JoinRound;
   line_xor_gc = XCreateGC (dpy, window,
                           GCForeground | GCBackground | GCLineStyle
-                          | GCJoinStyle | GCCapStyle | GCLineWidth
-                          | GCFunction,
+                          | GCJoinStyle | GCCapStyle | GCLineWidth,
                           &gc_values);
   XSetDashes (dpy, line_xor_gc, 0, dash_list, dashes);
 
-  gc_values.background = WhitePixel (dpy, DefaultScreen (dpy));
-  gc_values.foreground = obtain_color ("blue");
   line_xor_inv_gc = XCreateGC (dpy, window,
-                              GCForeground | GCBackground
-                              | GCLineWidth | GCFunction,
-                              &gc_values);
+                          GCForeground | GCBackground | GCLineWidth,
+                          &gc_values);
 
   depth = DefaultDepthOfScreen (ScreenOfDisplay (dpy, DefaultScreen (dpy)));
   pix = XCreateBitmapFromData (dpy, window, page_glyf_bits,
@@ -137,25 +132,20 @@ main (argc,argv)
       switch (event.type)
        {
        case ButtonPress:
-#if 0
-         if (event.xbutton.state && ShiftMask)
-#endif
-           switch (event.xbutton.button)
-             {
-             case Button1:
-               XDrawLine (dpy, window, line_xor_gc, 25, 75, 125, 75);
-               XFlush (dpy);
-               XDrawLine (dpy, window, line_xor_gc, 25, 75, 125, 75);
-               break;
-
-             case Button2:
-               XDrawLine (dpy, window, line_xor_gc, 25, 75, 125, 75);
-               break;
-
-             case Button3:
-               XDrawLine (dpy, window, line_xor_gc, 25, 75, 125, 75);
-               break;
-             }
+         switch (event.xbutton.button)
+           {
+           case Button1:
+             XDrawLine (dpy, window, line_xor_gc, 25, 75, 300, 75);
+             break;
+
+           case Button2:
+             XDrawLine (dpy, window, line_xor_inv_gc, 25, 25, 300, 25);
+             break;
+
+           case Button3:
+             XDrawLine (dpy, window, line_xor_gc, 25, 25, 25, 125);
+             break;
+           }
          break;
 
        case KeyPress:
diff --git a/src/XTests.h b/src/XTests.h
new file mode 100644 (file)
index 0000000..e91445a
--- /dev/null
@@ -0,0 +1,7 @@
+#define page_glyf_width 30
+#define page_glyf_height 10
+static char page_glyf_bits[] = {
+   0xf0, 0xff, 0xff, 0x03, 0x08, 0x00, 0x00, 0x04, 0xc4, 0x19, 0xf3, 0x08,
+   0x42, 0xa5, 0x14, 0x10, 0xc1, 0xa5, 0x70, 0x20, 0x41, 0xbc, 0x16, 0x20,
+   0x42, 0xa4, 0x14, 0x10, 0x44, 0x24, 0xf3, 0x08, 0x08, 0x00, 0x00, 0x04,
+   0xf0, 0xff, 0xff, 0x03};
index 74c0e80..9a7640b 100644 (file)
@@ -20,7 +20,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "config.h"
 #include <stdio.h>
-#undef NULL
 #include "lisp.h"
 #include "commands.h"
 #include "buffer.h"
@@ -113,9 +112,9 @@ it is called after EXPANSION is inserted.")
   Lisp_Object sym, oexp, ohook, tem;
   CHECK_VECTOR (table, 0);
   CHECK_STRING (name, 1);
-  if (!NULL (expansion))
+  if (!NILP (expansion))
     CHECK_STRING (expansion, 2);
-  if (NULL (count))
+  if (NILP (count))
     count = make_number (0);
   else
     CHECK_NUMBER (count, 0);
@@ -126,10 +125,10 @@ it is called after EXPANSION is inserted.")
   ohook = XSYMBOL (sym)->function;
   if (!((EQ (oexp, expansion)
         || (XTYPE (oexp) == Lisp_String && XTYPE (expansion) == Lisp_String
-            && (tem = Fstring_equal (oexp, expansion), !NULL (tem))))
+            && (tem = Fstring_equal (oexp, expansion), !NILP (tem))))
        &&
        (EQ (ohook, hook)
-        || (tem = Fequal (ohook, hook), !NULL (tem)))))
+        || (tem = Fequal (ohook, hook), !NILP (tem)))))
     abbrevs_changed = 1;
 
   Fset (sym, expansion);
@@ -156,7 +155,7 @@ DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev, Sdefine_mode_abbrev, 2, 2,
   (name, expansion)
      Lisp_Object name, expansion;
 {
-  if (NULL (current_buffer->abbrev_table))
+  if (NILP (current_buffer->abbrev_table))
     error ("Major mode has no abbrev table");
 
   Fdefine_abbrev (current_buffer->abbrev_table, Fdowncase (name),
@@ -176,19 +175,19 @@ The default is to try buffer's mode-specific abbrev table, then global table.")
 {
   Lisp_Object sym;
   CHECK_STRING (abbrev, 0);
-  if (!NULL (table))
+  if (!NILP (table))
     sym = Fintern_soft (abbrev, table);
   else
     {
       sym = Qnil;
-      if (!NULL (current_buffer->abbrev_table))
+      if (!NILP (current_buffer->abbrev_table))
        sym = Fintern_soft (abbrev, current_buffer->abbrev_table);
-      if (NULL (XSYMBOL (sym)->value))
+      if (NILP (XSYMBOL (sym)->value))
        sym = Qnil;
-      if (NULL (sym))
+      if (NILP (sym))
        sym = Fintern_soft (abbrev, Vglobal_abbrev_table);
     }
-  if (NULL (XSYMBOL (sym)->value)) return Qnil;
+  if (NILP (XSYMBOL (sym)->value)) return Qnil;
   return sym;
 }
 
@@ -201,7 +200,7 @@ then ABBREV is looked up in that table only.")
 {
   Lisp_Object sym;
   sym = Fabbrev_symbol (abbrev, table);
-  if (NULL (sym)) return sym;
+  if (NILP (sym)) return sym;
   return Fsymbol_value (sym);
 }
 \f
@@ -221,12 +220,12 @@ Returns t if expansion took place.")
   register Lisp_Object sym;
   Lisp_Object expansion, hook, tem;
 
-  if (!NULL (Vrun_hooks))
+  if (!NILP (Vrun_hooks))
     call1 (Vrun_hooks, Qpre_abbrev_expand_hook);
 
   if (XBUFFER (Vabbrev_start_location_buffer) != current_buffer)
     Vabbrev_start_location = Qnil;
-  if (!NULL (Vabbrev_start_location))
+  if (!NILP (Vabbrev_start_location))
     {
       tem = Vabbrev_start_location;
       CHECK_NUMBER_COERCE_MARKER (tem, 0);
@@ -267,9 +266,9 @@ Returns t if expansion took place.")
     sym = oblookup (current_buffer->abbrev_table, buffer, p - buffer);
   else
     XFASTINT (sym) = 0;
-  if (XTYPE (sym) == Lisp_Int || NULL (XSYMBOL (sym)->value))
+  if (XTYPE (sym) == Lisp_Int || NILP (XSYMBOL (sym)->value))
     sym = oblookup (Vglobal_abbrev_table, buffer, p - buffer);
-  if (XTYPE (sym) == Lisp_Int || NULL (XSYMBOL (sym)->value))
+  if (XTYPE (sym) == Lisp_Int || NILP (XSYMBOL (sym)->value))
     return Qnil;
 
   if (INTERACTIVE && !EQ (minibuf_window, selected_window))
@@ -327,7 +326,7 @@ Returns t if expansion took place.")
     }
 
   hook = XSYMBOL (sym)->function;
-  if (!NULL (hook))
+  if (!NILP (hook))
     call0 (hook);
 
   return Qt;
@@ -367,7 +366,7 @@ write_abbrev (sym, stream)
      Lisp_Object sym, stream;
 {
   Lisp_Object name;
-  if (NULL (XSYMBOL (sym)->value))
+  if (NILP (XSYMBOL (sym)->value))
     return;
   insert ("    (", 5);
   XSET (name, Lisp_String, XSYMBOL (sym)->name);
@@ -387,7 +386,7 @@ describe_abbrev (sym, stream)
 {
   Lisp_Object one;
 
-  if (NULL (XSYMBOL (sym)->value))
+  if (NILP (XSYMBOL (sym)->value))
     return;
   one = make_number (1);
   Fprin1 (Fsymbol_name (sym), stream);
@@ -395,7 +394,7 @@ describe_abbrev (sym, stream)
   Fprin1 (XSYMBOL (sym)->plist, stream);
   Findent_to (make_number (20), one);
   Fprin1 (XSYMBOL (sym)->value, stream);
-  if (!NULL (XSYMBOL (sym)->function))
+  if (!NILP (XSYMBOL (sym)->function))
     {
       Findent_to (make_number (45), one);
       Fprin1 (XSYMBOL (sym)->function, stream);
@@ -424,7 +423,7 @@ define the abbrev table NAME exactly as it is currently defined.")
 
   XSET (stream, Lisp_Buffer, current_buffer);
 
-  if (!NULL (readable))
+  if (!NILP (readable))
     {
       insert_string ("(");
       Fprin1 (name, stream);
@@ -457,7 +456,7 @@ of the form (ABBREVNAME EXPANSION HOOK USECOUNT).")
 
   CHECK_SYMBOL (tabname, 0);
   table = Fboundp (tabname);
-  if (NULL (table) || (table = Fsymbol_value (tabname), NULL (table)))
+  if (NILP (table) || (table = Fsymbol_value (tabname), NILP (table)))
     {
       table = Fmake_abbrev_table ();
       Fset (tabname, table);
@@ -466,7 +465,7 @@ of the form (ABBREVNAME EXPANSION HOOK USECOUNT).")
     }
   CHECK_VECTOR (table, 0);
 
-  for (;!NULL (defns); defns = Fcdr (defns))
+  for (;!NILP (defns); defns = Fcdr (defns))
     {
       elt = Fcar (defns);
       name = Fcar (elt);
diff --git a/src/acldef.h b/src/acldef.h
new file mode 100644 (file)
index 0000000..cc4085c
--- /dev/null
@@ -0,0 +1,40 @@
+#define        ACL$K_LENGTH    12
+#define        ACL$C_LENGTH    12
+#define        ACL$C_FILE      1
+#define        ACL$C_DEVICE    2
+#define        ACL$C_JOBCTL_QUEUE      3
+#define        ACL$C_COMMON_EF_CLUSTER 4
+#define        ACL$C_LOGICAL_NAME_TABLE        5
+#define        ACL$C_PROCESS   6
+#define        ACL$C_GROUP_GLOBAL_SECTION      7
+#define        ACL$C_SYSTEM_GLOBAL_SECTION     8
+#define        ACL$C_ADDACLENT 1
+#define        ACL$C_DELACLENT 2
+#define        ACL$C_MODACLENT 3
+#define        ACL$C_FNDACLENT 4
+#define        ACL$C_FNDACETYP 5
+#define        ACL$C_DELETEACL 6
+#define        ACL$C_READACL   7
+#define        ACL$C_ACLLENGTH 8
+#define        ACL$C_READACE   9
+#define        ACL$C_RLOCK_ACL 10
+#define        ACL$C_WLOCK_ACL 11
+#define        ACL$C_UNLOCK_ACL        12
+#define        ACL$S_ADDACLENT 255
+#define        ACL$S_DELACLENT 255
+#define        ACL$S_MODACLENT 255
+#define        ACL$S_FNDACLENT 255
+#define        ACL$S_FNDACETYP 255
+#define        ACL$S_DELETEACL 255
+#define        ACL$S_READACL   512
+#define        ACL$S_ACLLENGTH 4
+#define        ACL$S_READACE   255
+#define        ACL$S_RLOCK_ACL 4
+#define        ACL$S_WLOCK_ACL 4
+#define        ACL$S_UNLOCK_ACL        4
+#define        ACL$S_ACLDEF    16
+#define        ACL$L_FLINK     0
+#define        ACL$L_BLINK     4
+#define        ACL$W_SIZE      8
+#define        ACL$B_TYPE      10
+#define        ACL$L_LIST      12
index d508deb..87dd1c7 100644 (file)
@@ -261,7 +261,10 @@ syms_of_casefiddle ()
 keys_of_casefiddle ()
 {
   initial_define_key (control_x_map, Ctl('U'), "upcase-region");
+  Fput (intern ("upcase-region"), Qdisabled, Qt);
   initial_define_key (control_x_map, Ctl('L'), "downcase-region");
+  Fput (intern ("downcase-region"), Qdisabled, Qt);
+
   initial_define_key (meta_map, 'u', "upcase-word");
   initial_define_key (meta_map, 'l', "downcase-word");
   initial_define_key (meta_map, 'c', "capitalize-word");
index 6d419bf..fa8375c 100644 (file)
@@ -45,8 +45,8 @@ See `set-case-table' for more information on these data structures.")
   (XTYPE (obj) == Lisp_String && XSTRING (obj)->size == 256)
 
   return (STRING256_P (down)
-         && (NULL (up) || STRING256_P (up))
-         && ((NULL (canon) && NULL (eqv))
+         && (NILP (up) || STRING256_P (up))
+         && ((NILP (canon) && NILP (eqv))
              || (STRING256_P (canon) && STRING256_P (eqv)))
          ? Qt : Qnil);
 }
@@ -57,7 +57,7 @@ check_case_table (obj)
 {
   register Lisp_Object tem;
 
-  while (tem = Fcase_table_p (obj), NULL (tem))
+  while (tem = Fcase_table_p (obj), NILP (tem))
     obj = wrong_type_argument (Qcase_table_p, obj, 0);
   return (obj);
 }   
@@ -132,13 +132,13 @@ set_case_table (table, standard)
   canon = Fcar_safe (Fcdr_safe (Fcdr_safe (table)));
   eqv = Fcar_safe (Fcdr_safe (Fcdr_safe (Fcdr_safe (table))));
 
-  if (NULL (up))
+  if (NILP (up))
     {
       up = Fmake_string (make_number (256), make_number (0));
       compute_trt_inverse (XSTRING (down)->data, XSTRING (up)->data);
     }
 
-  if (NULL (canon))
+  if (NILP (canon))
     {
       register int i;
       unsigned char *upvec = XSTRING (up)->data;
diff --git a/src/chpdef.h b/src/chpdef.h
new file mode 100644 (file)
index 0000000..43f7bbf
--- /dev/null
@@ -0,0 +1,38 @@
+#define        CHP$_END        0
+#define        CHP$_ACCESS     1
+#define        CHP$_FLAGS      2
+#define        CHP$_PRIV       3
+#define        CHP$_ACMODE     4
+#define        CHP$_ACCLASS    5
+#define        CHP$_RIGHTS     6
+#define        CHP$_ADDRIGHTS  7
+#define        CHP$_MODE       8
+#define        CHP$_MODES      9
+#define        CHP$_MINCLASS   10
+#define        CHP$_MAXCLASS   11
+#define        CHP$_OWNER      12
+#define        CHP$_PROT       13
+#define        CHP$_ACL        14
+#define        CHP$_AUDITNAME  15
+#define        CHP$_ALARMNAME  16
+#define        CHP$_MATCHEDACE 17
+#define        CHP$_PRIVUSED   18
+#define        CHP$_MAX_CODE   19
+#define        CHP$M_SYSPRV    1
+#define        CHP$M_BYPASS    2
+#define        CHP$M_UPGRADE   4
+#define        CHP$M_DOWNGRADE 8
+#define        CHP$M_GRPPRV    16
+#define        CHP$M_READALL   32
+#define        CHP$V_SYSPRV    0
+#define        CHP$V_BYPASS    1
+#define        CHP$V_UPGRADE   2
+#define        CHP$V_DOWNGRADE 3
+#define        CHP$V_GRPPRV    4
+#define        CHP$V_READALL   5
+#define        CHP$M_READ      1
+#define        CHP$M_WRITE     2
+#define        CHP$M_USEREADALL        4
+#define        CHP$V_READ      0
+#define        CHP$V_WRITE     1
+#define        CHP$V_USEREADALL        2
diff --git a/src/cm.c b/src/cm.c
new file mode 100644 (file)
index 0000000..f88acff
--- /dev/null
+++ b/src/cm.c
@@ -0,0 +1,414 @@
+/* Cursor motion subroutines for GNU Emacs.
+   Copyright (C) 1985 Free Software Foundation, Inc.
+    based primarily on public domain code written by Chris Torek
+
+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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+#include "config.h"
+#include <stdio.h>
+#include "cm.h"
+#include "termhooks.h"
+
+#define        BIG     9999            /* 9999 good on VAXen.  For 16 bit machines
+                                  use about 2000.... */
+
+char *tgoto ();
+
+extern char *BC, *UP;
+
+int cost;              /* sums up costs */
+
+/* ARGSUSED */
+evalcost (c)
+     char c;
+{
+  cost++;
+}
+
+void
+cmputc (c)
+     char c;
+{
+  if (termscript)
+    fputc (c & 0177, termscript);
+  putchar (c & 0177);
+}
+
+/* NEXT TWO ARE DONE WITH MACROS */
+#if 0
+/*
+ * Assume the cursor is at row row, column col.  Normally used only after
+ * clearing the screen, when the cursor is at (0, 0), but what the heck,
+ * let's let the guy put it anywhere.
+ */
+
+static
+at (row, col) {
+    curY = row;
+    curX = col;
+}
+
+/*
+ * Add n columns to the current cursor position.
+ */
+
+static
+addcol (n) {
+    curX += n;
+
+    /*
+     * If cursor hit edge of screen, what happened?
+     * N.B.: DO NOT!! write past edge of screen.  If you do, you
+     * deserve what you get.  Furthermore, on terminals with
+     * autowrap (but not magicwrap), don't write in the last column
+     * of the last line.
+     */
+
+    if (curX == Wcm.cm_cols) {
+       /*
+        * Well, if magicwrap, still there, past the edge of the
+        * screen (!).  If autowrap, on the col 0 of the next line.
+        * Otherwise on last column.
+        */
+
+       if (Wcm.cm_magicwrap)
+           ;                   /* "limbo" */
+       else if (Wcm.cm_autowrap) {
+           curX = 0;
+           curY++;             /* Beware end of screen! */
+       }
+       else
+           curX--;
+    }
+}
+#endif
+
+/*
+ * (Re)Initialize the cost factors, given the output speed of the terminal
+ * in the variable ospeed.  (Note: this holds B300, B9600, etc -- ie stuff
+ * out of <sgtty.h>.)
+ */
+
+cmcostinit ()
+{
+    char *p;
+
+#define        COST(x,e)       (x ? (cost = 0, tputs (x, 1, e), cost) : BIG)
+#define CMCOST(x,e)    ((x == 0) ? BIG : (p = tgoto(x, 0, 0), COST(p ,e)))
+
+    Wcm.cc_up =                COST (Wcm.cm_up, evalcost);
+    Wcm.cc_down =      COST (Wcm.cm_down, evalcost);
+    Wcm.cc_left =      COST (Wcm.cm_left, evalcost);
+    Wcm.cc_right =     COST (Wcm.cm_right, evalcost);
+    Wcm.cc_home =      COST (Wcm.cm_home, evalcost);
+    Wcm.cc_cr =                COST (Wcm.cm_cr, evalcost);
+    Wcm.cc_ll =                COST (Wcm.cm_ll, evalcost);
+    Wcm.cc_tab =       Wcm.cm_tabwidth ? COST (Wcm.cm_tab, evalcost) : BIG;
+
+    /*
+     * These last three are actually minimum costs.  When (if) they are
+     * candidates for the least-cost motion, the real cost is computed.
+     * (Note that "0" is the assumed to generate the minimum cost.
+     * While this is not necessarily true, I have yet to see a terminal
+     * for which is not; all the terminals that have variable-cost
+     * cursor motion seem to take straight numeric values.  --ACT)
+     */
+
+    Wcm.cc_abs =  CMCOST (Wcm.cm_abs, evalcost);
+    Wcm.cc_habs = CMCOST (Wcm.cm_habs, evalcost);
+    Wcm.cc_vabs = CMCOST (Wcm.cm_vabs, evalcost);
+
+#undef CMCOST
+#undef COST
+}
+
+/*
+ * Calculate the cost to move from (srcy, srcx) to (dsty, dstx) using
+ * up and down, and left and right, motions, and tabs.  If doit is set
+ * actually perform the motion.
+ */
+
+static
+calccost (srcy, srcx, dsty, dstx, doit)
+{
+    register int    deltay,
+                    deltax,
+                    c,
+                    totalcost;
+    int     ntabs,
+            n2tabs,
+            tabx,
+            tab2x,
+            tabcost;
+    register char  *p;
+
+    /* If have just wrapped on a terminal with xn,
+       don't believe the cursor position: give up here
+       and force use of absolute positioning.  */
+
+    if (curX == Wcm.cm_cols)
+      goto fail;
+
+    totalcost = 0;
+    if ((deltay = dsty - srcy) == 0)
+       goto x;
+    if (deltay < 0)
+       p = Wcm.cm_up, c = Wcm.cc_up, deltay = -deltay;
+    else
+       p = Wcm.cm_down, c = Wcm.cc_down;
+    if (c == BIG) {            /* caint get thar from here */
+       if (doit)
+           printf ("OOPS");
+       return c;
+    }
+    totalcost = c * deltay;
+    if (doit)
+       while (--deltay >= 0)
+           tputs (p, 1, cmputc);
+x: 
+    if ((deltax = dstx - srcx) == 0)
+       goto done;
+    if (deltax < 0) {
+       p = Wcm.cm_left, c = Wcm.cc_left, deltax = -deltax;
+       goto dodelta;           /* skip all the tab junk */
+    }
+    /* Tabs (the toughie) */
+    if (Wcm.cc_tab >= BIG || !Wcm.cm_usetabs)
+       goto olddelta;          /* forget it! */
+
+    /* 
+     * ntabs is # tabs towards but not past dstx; n2tabs is one more
+     * (ie past dstx), but this is only valid if that is not past the
+     * right edge of the screen.  We can check that at the same time
+     * as we figure out where we would be if we use the tabs (which
+     * we will put into tabx (for ntabs) and tab2x (for n2tabs)).
+     */
+
+    ntabs = (deltax + srcx % Wcm.cm_tabwidth) / Wcm.cm_tabwidth;
+    n2tabs = ntabs + 1;
+    tabx = (srcx / Wcm.cm_tabwidth + ntabs) * Wcm.cm_tabwidth;
+    tab2x = tabx + Wcm.cm_tabwidth;
+
+    if (tab2x >= Wcm.cm_cols)  /* too far (past edge) */
+       n2tabs = 0;
+
+    /* 
+     * Now set tabcost to the cost for using ntabs, and c to the cost
+     * for using n2tabs, then pick the minimum.
+     */
+
+                  /* cost for ntabs     +    cost for right motion */
+    tabcost = ntabs ? ntabs * Wcm.cc_tab + (dstx - tabx) * Wcm.cc_right
+                   : BIG;
+
+                  /* cost for n2tabs    +    cost for left motion */
+    c = n2tabs  ?    n2tabs * Wcm.cc_tab + (tab2x - dstx) * Wcm.cc_left
+               : BIG;
+
+    if (c < tabcost)           /* then cheaper to overshoot & back up */
+       ntabs = n2tabs, tabcost = c, tabx = tab2x;
+
+    if (tabcost >= BIG)                /* caint use tabs */
+       goto newdelta;
+
+    /* 
+     * See if tabcost is less than just moving right
+     */
+
+    if (tabcost < (deltax * Wcm.cc_right)) {
+       totalcost += tabcost;   /* use the tabs */
+       if (doit)
+           while (--ntabs >= 0)
+               tputs (Wcm.cm_tab, 1, cmputc);
+       srcx = tabx;
+    }
+
+    /* 
+     * Now might as well just recompute the delta.
+     */
+
+newdelta: 
+    if ((deltax = dstx - srcx) == 0)
+       goto done;
+olddelta: 
+    if (deltax > 0)
+       p = Wcm.cm_right, c = Wcm.cc_right;
+    else
+       p = Wcm.cm_left, c = Wcm.cc_left, deltax = -deltax;
+
+dodelta: 
+    if (c == BIG) {            /* caint get thar from here */
+fail:
+       if (doit)
+           printf ("OOPS");
+       return BIG;
+    }
+    totalcost += c * deltax;
+    if (doit)
+       while (--deltax >= 0)
+           tputs (p, 1, cmputc);
+done: 
+    return totalcost;
+}
+
+#if 0
+losecursor ()
+{
+  curY = -1;
+}
+#endif
+
+#define        USEREL  0
+#define        USEHOME 1
+#define        USELL   2
+#define        USECR   3
+
+cmgoto (row, col)
+{
+    int     homecost,
+            crcost,
+            llcost,
+            relcost,
+            directcost;
+    int     use;
+    char   *p,
+           *dcm;
+
+  /* First the degenerate case */
+  if (row == curY && col == curX) /* already there */
+    return;
+
+  if (curY >= 0 && curX >= 0)
+    {
+      /* We may have quick ways to go to the upper-left, bottom-left,
+       * start-of-line, or start-of-next-line.  Or it might be best to
+       * start where we are.  Examine the options, and pick the cheapest.
+       */
+
+      relcost = calccost (curY, curX, row, col, 0);
+      use = USEREL;
+      if ((homecost = Wcm.cc_home) < BIG)
+         homecost += calccost (0, 0, row, col, 0);
+      if (homecost < relcost)
+         relcost = homecost, use = USEHOME;
+      if ((llcost = Wcm.cc_ll) < BIG)
+         llcost += calccost (Wcm.cm_rows - 1, 0, row, col, 0);
+      if (llcost < relcost)
+         relcost = llcost, use = USELL;
+      if ((crcost = Wcm.cc_cr) < BIG) {
+         if (Wcm.cm_autolf)
+             if (curY + 1 >= Wcm.cm_rows)
+                 crcost = BIG;
+             else
+                 crcost += calccost (curY + 1, 0, row, col, 0);
+         else
+             crcost += calccost (curY, 0, row, col, 0);
+      }
+      if (crcost < relcost)
+         relcost = crcost, use = USECR;
+      directcost = Wcm.cc_abs, dcm = Wcm.cm_abs;
+      if (row == curY && Wcm.cc_habs < BIG)
+         directcost = Wcm.cc_habs, dcm = Wcm.cm_habs;
+      else if (col == curX && Wcm.cc_vabs < BIG)
+         directcost = Wcm.cc_vabs, dcm = Wcm.cm_vabs;
+    }
+  else
+    {
+      directcost = 0, relcost = 100000;
+      dcm = Wcm.cm_abs;
+    }
+
+  /* 
+   * In the following comparison, the = in <= is because when the costs
+   * are the same, it looks nicer (I think) to move directly there.
+   */
+  if (directcost <= relcost)
+    {
+      /* compute REAL direct cost */
+      cost = 0;
+      p = dcm == Wcm.cm_habs ? tgoto (dcm, row, col) :
+                              tgoto (dcm, col, row);
+      tputs (p, 1, evalcost);
+      if (cost <= relcost)
+       {       /* really is cheaper */
+         tputs (p, 1, cmputc);
+         curY = row, curX = col;
+         return;
+       }
+    }
+
+  switch (use)
+    {
+    case USEHOME: 
+      tputs (Wcm.cm_home, 1, cmputc);
+      curY = 0, curX = 0;
+      break;
+
+    case USELL: 
+      tputs (Wcm.cm_ll, 1, cmputc);
+      curY = Wcm.cm_rows - 1, curX = 0;
+      break;
+
+    case USECR: 
+      tputs (Wcm.cm_cr, 1, cmputc);
+      if (Wcm.cm_autolf)
+       curY++;
+      curX = 0;
+      break;
+    }
+
+  (void) calccost (curY, curX, row, col, 1);
+  curY = row, curX = col;
+}
+
+/* Clear out all terminal info.
+   Used before copying into it the info on the actual terminal.
+ */
+
+Wcm_clear ()
+{
+  bzero (&Wcm, sizeof Wcm);
+  UP = 0;
+  BC = 0;
+}
+
+/*
+ * Initialized stuff
+ * Return 0 if can do CM.
+ * Return -1 if cannot.
+ * Return -2 if size not specified.
+ */
+
+Wcm_init ()
+{
+#if 0
+  if (Wcm.cm_abs && !Wcm.cm_ds)
+    return 0;
+#endif
+  if (Wcm.cm_abs)
+    return 0;
+  /* Require up and left, and, if no absolute, down and right */
+  if (!Wcm.cm_up || !Wcm.cm_left)
+    return - 1;
+  if (!Wcm.cm_abs && (!Wcm.cm_down || !Wcm.cm_right))
+    return - 1;
+  /* Check that we know the size of the screen.... */
+  if (Wcm.cm_rows <= 0 || Wcm.cm_cols <= 0)
+    return - 2;
+  return 0;
+}
diff --git a/src/disptab.h b/src/disptab.h
new file mode 100644 (file)
index 0000000..67d3619
--- /dev/null
@@ -0,0 +1,82 @@
+/* Things for GLYPHS and glyph tables.
+   Copyright (C) 1990 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Access the slots of a display-table, according to their purpose.  */
+
+#define DISP_TABLE_SIZE 261
+#define DISP_TRUNC_GLYPH(dp) ((dp)->contents[256])
+#define DISP_CONTINUE_GLYPH(dp) ((dp)->contents[257])
+#define DISP_ESCAPE_GLYPH(dp) ((dp)->contents[258])
+#define DISP_CTRL_GLYPH(dp) ((dp)->contents[259])
+#define DISP_INVIS_ROPE(dp) ((dp)->contents[260])
+#define DISP_CHAR_ROPE(dp, c) ((dp)->contents[c])
+
+extern struct Lisp_Vector *window_display_table ();
+
+/* Display table to use for vectors that don't specify their own.  */
+extern Lisp_Object Vstandard_display_table;
+
+/* Vector of GLYPH definitions.  Indexed by GLYPH number,
+   the contents are a string which is how to output the GLYPH.  */
+extern Lisp_Object Vglyph_table;
+
+/* Return the current length of the GLYPH table,
+   or 0 if the table isn't currently valid.  */
+#define GLYPH_TABLE_LENGTH  \
+  ((XTYPE (Vglyph_table) == Lisp_Vector) \
+   ? XVECTOR (Vglyph_table)->size : 0)
+
+/* Return the current base (for indexing) of the GLYPH table,
+   or 0 if the table isn't currently valid.  */
+#define GLYPH_TABLE_BASE  \
+  ((XTYPE (Vglyph_table) == Lisp_Vector) \
+   ? XVECTOR (Vglyph_table)->contents : 0)
+
+/* Given BASE and LEN returned by the two previous macros,
+   return nonzero if the GLYPH code G should be output as a single
+   character with code G.  Return zero if G has a string in the table.  */
+#define GLYPH_SIMPLE_P(base,len,g)  \
+  ((g) >= (len) || XTYPE (base[g]) != Lisp_String)
+
+/* Given BASE and LEN returned by the two previous macros,
+   return nonzero if GLYPH code G is aliased to a different code.  */
+#define GLYPH_ALIAS_P(base,len,g)  \
+  ((g) < (len) && XTYPE (base[g]) == Lisp_Int)
+
+/* Assuming that GLYPH_SIMPLE_P (BASE, LEN, G) is 1,
+   return the alias for G.  */
+#define GLYPH_ALIAS(base, g) XINT (base[g])
+
+/* Assuming that GLYPH_SIMPLE_P (BASE, LEN, G) is 0,
+   return the length and the address of the character-sequence
+   used for outputting GLYPH G.  */
+#define GLYPH_LENGTH(base,g)   XSTRING (base[g])->size
+#define GLYPH_STRING(base,g)   XSTRING (base[g])->data
+
+/* GLYPH for a space character.  */
+
+#define SPACEGLYPH 040
+#define NULL_GLYPH 00
+
+#define GLYPH_FROM_CHAR(c) (c)
+
+extern int glyphlen ();
+extern void str_to_glyph_cpy ();
+extern void str_to_glyph_ncpy ();
+extern void glyph_to_str_cpy ();
index 731afe4..0258455 100644 (file)
@@ -68,10 +68,10 @@ doprnt (buffer, bufsize, format, format_end, nargs, args)
          int size_bound;
 
          fmt++;
-         /* Copy this one %-spec into fmtcopy.  */
+         /* Copy this one %-spec into fmtcpy.  */
          string = fmtcpy;
          *string++ = '%';
-         while (1)
+         while (string < fmtcpy + sizeof fmtcpy - 1)
            {
              *string++ = *fmt;
              if (! (*fmt >= '0' && *fmt <= '9') && *fmt != '-' && *fmt != ' ')
diff --git a/src/indent.h b/src/indent.h
new file mode 100644 (file)
index 0000000..ec6dcae
--- /dev/null
@@ -0,0 +1,34 @@
+/* Definitions for interface to indent.c
+   Copyright (C) 1985, 1986 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+struct position
+  {
+    int bufpos;
+    int hpos;
+    int vpos;
+    int prevhpos;
+    int contin;
+  };
+
+struct position *compute_motion ();
+struct position *vmotion ();
+
+/* Value of point when current_column was called */
+extern int last_known_column_point;
index 80f1d67..1deda9d 100644 (file)
@@ -214,7 +214,7 @@ adjust_markers (from, to, amount)
 
   marker = current_buffer->markers;
 
-  while (!NULL (marker))
+  while (!NILP (marker))
     {
       m = XMARKER (marker);
       mpos = m->bufpos;
@@ -352,7 +352,7 @@ insert_from_string (string, pos, length)
   GPT += length;
   ZV += length;
   Z += length;
-  point += length;
+  SET_PT (point + length);
 
   signal_after_change (point-length, 0, length);
 }
@@ -473,22 +473,22 @@ modify_region (start, end)
 prepare_to_modify_buffer (start, end)
      Lisp_Object start, end;
 {
-  if (!NULL (current_buffer->read_only))
+  if (!NILP (current_buffer->read_only))
     Fbarf_if_buffer_read_only ();
 
   if (check_protected_fields)
     Fregion_fields (start, end, Qnil, Qt);
 
 #ifdef CLASH_DETECTION
-  if (!NULL (current_buffer->filename)
+  if (!NILP (current_buffer->filename)
       && current_buffer->save_modified >= MODIFF)
     lock_file (current_buffer->filename);
 #else
   /* At least warn if this file has changed on disk since it was visited.  */
-  if (!NULL (current_buffer->filename)
+  if (!NILP (current_buffer->filename)
       && current_buffer->save_modified >= MODIFF
-      && NULL (Fverify_visited_file_modtime (Fcurrent_buffer ()))
-      && !NULL (Ffile_exists_p (current_buffer->filename)))
+      && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
+      && !NILP (Ffile_exists_p (current_buffer->filename)))
     call1 (intern ("ask-user-about-supersession-threat"),
           current_buffer->filename);
 #endif /* not CLASH_DETECTION */
@@ -519,12 +519,12 @@ signal_before_change (start, end)
 {
   /* If buffer is unmodified, run a special hook for that case.  */
   if (current_buffer->save_modified >= MODIFF
-      && !NULL (Vfirst_change_function))
+      && !NILP (Vfirst_change_function))
     {
       call0 (Vfirst_change_function);
     }
   /* Now in any case run the before-change-function if any.  */
-  if (!NULL (Vbefore_change_function))
+  if (!NILP (Vbefore_change_function))
     {
       int count = specpdl_ptr - specpdl;
       Lisp_Object function;
@@ -551,7 +551,7 @@ signal_before_change (start, end)
 signal_after_change (pos, lendel, lenins)
      int pos, lendel, lenins;
 {
-  if (!NULL (Vafter_change_function))
+  if (!NILP (Vafter_change_function))
     {
       int count = specpdl_ptr - specpdl;
       Lisp_Object function;
diff --git a/src/ioctl.h b/src/ioctl.h
new file mode 100644 (file)
index 0000000..0366f6d
--- /dev/null
@@ -0,0 +1 @@
+/* Emacs ioctl emulation for VMS */
diff --git a/src/lastfile.c b/src/lastfile.c
new file mode 100644 (file)
index 0000000..6588a59
--- /dev/null
@@ -0,0 +1,38 @@
+/* Mark end of data space to dump as pure, for GNU Emacs.
+   Copyright (C) 1985 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+/* How this works:
+
+ Fdump_emacs dumps everything up to my_edata as text space (pure).
+
+ The files of Emacs are written so as to have no initialized
+ data that can ever need to be altered except at the first startup.
+ This is so that those words can be dumped as sharable text.
+
+ It is not possible to exercise such control over library files.
+ So it is necessary to refrain from making their data areas shared.
+ Therefore, this file is loaded following all the files of Emacs
+ but before library files.
+ As a result, the symbol my_edata indicates the point
+ in data space between data coming from Emacs and data
+ coming from libraries.
+*/
+
+char my_edata = 0;
diff --git a/src/line.h b/src/line.h
new file mode 100644 (file)
index 0000000..e3441aa
--- /dev/null
@@ -0,0 +1,7 @@
+#define line_width 30
+#define line_height 10
+static char line_bits[] = {
+   0xf0, 0xff, 0xff, 0x03, 0x08, 0x00, 0x00, 0x04, 0x44, 0x48, 0xf4, 0x08,
+   0x42, 0xc8, 0x14, 0x10, 0x41, 0x48, 0x75, 0x20, 0x41, 0x48, 0x15, 0x20,
+   0x42, 0x48, 0x16, 0x10, 0xc4, 0x4b, 0xf4, 0x08, 0x08, 0x00, 0x00, 0x04,
+   0xf0, 0xff, 0xff, 0x03};
diff --git a/src/macros.h b/src/macros.h
new file mode 100644 (file)
index 0000000..36d6689
--- /dev/null
@@ -0,0 +1,31 @@
+/* Definitions for keyboard macro interpretation in GNU Emacs.
+   Copyright (C) 1985 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+/* Kbd macro currently being executed (a string) */
+
+extern Lisp_Object Vexecuting_macro;
+
+/* Index of next character to fetch from that macro */
+
+extern int executing_macro_index;
+
+/* Nonzero while defining a kbd macro */
+
+extern int defining_kbd_macro;
index d8c0a89..6c26e72 100644 (file)
@@ -36,7 +36,7 @@ Returns nil if MARKER points into a dead buffer.")
     {
       XSET (buf, Lisp_Buffer, XMARKER (marker)->buffer);
       /* Return marker's buffer only if it is not dead.  */
-      if (!NULL (XBUFFER (buf)->name))
+      if (!NILP (XBUFFER (buf)->name))
        return buf;
     }
   return Qnil;
@@ -87,7 +87,7 @@ Returns MARKER.")
   CHECK_MARKER (marker, 0);
   /* If position is nil or a marker that points nowhere,
      make this marker point nowhere.  */
-  if (NULL (pos)
+  if (NILP (pos)
       || (XTYPE (pos) == Lisp_Marker && !XMARKER (pos)->buffer))
     {
       unchain_marker (marker);
@@ -95,7 +95,7 @@ Returns MARKER.")
     }
 
   CHECK_NUMBER_COERCE_MARKER (pos, 1);
-  if (NULL (buffer))
+  if (NILP (buffer))
     b = current_buffer;
   else
     {
@@ -144,7 +144,7 @@ set_marker_restricted (marker, pos, buffer)
   CHECK_MARKER (marker, 0);
   /* If position is nil or a marker that points nowhere,
      make this marker point nowhere.  */
-  if (NULL (pos) ||
+  if (NILP (pos) ||
       (XTYPE (pos) == Lisp_Marker && !XMARKER (pos)->buffer))
     {
       unchain_marker (marker);
@@ -152,7 +152,7 @@ set_marker_restricted (marker, pos, buffer)
     }
 
   CHECK_NUMBER_COERCE_MARKER (pos, 1);
-  if (NULL (buffer))
+  if (NILP (buffer))
     b = current_buffer;
   else
     {
@@ -215,7 +215,7 @@ unchain_marker (marker)
 
       if (XMARKER (marker) == XMARKER (tail))
        {
-         if (NULL (prev))
+         if (NILP (prev))
            {
              b->markers = next;
              /* Deleting first marker from the buffer's chain.
index 5f0800f..353d4da 100644 (file)
@@ -32,7 +32,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 * {
 *  Lisp_Object elt;
 *
-*   while (!NULL (args))
+*   while (!NILP (args))
 *     {
 *       elt = Fcar (args);
 *       Ffset (Fcar (elt), Fcons (Qmocklisp, Fcdr (elt)));
@@ -50,11 +50,11 @@ DEFUN ("ml-if", Fml_if, Sml_if, 0, UNEVALLED, 0, "Mocklisp version of `if'.")
   struct gcpro gcpro1;
 
   GCPRO1 (args);
-  while (!NULL (args))
+  while (!NILP (args))
     {
       val = Feval (Fcar (args));
       args = Fcdr (args);
-      if (NULL (args)) break;
+      if (NILP (args)) break;
       if (XINT (val))
        {
          val = Feval (Fcar (args));
@@ -156,7 +156,7 @@ DEFUN ("ml-prefix-argument-loop", Fml_prefix_argument_loop, Sml_prefix_argument_
   struct gcpro gcpro1;
 
   /* Set `arg' in case we call a built-in function that looks at it.  Still are a few. */
-  if (NULL (Vcurrent_prefix_arg))
+  if (NILP (Vcurrent_prefix_arg))
     i = 1;
   else
     {
index e381bb2..56ff3f7 100644 (file)
@@ -28,4 +28,4 @@ extern Lisp_Object Fml_arg ();
 extern Lisp_Object Fml_interactive ();
 extern Lisp_Object Fml_provide_prefix_argument ();
 extern Lisp_Object Fml_prefix_argument_loop ();
-extern Lisp_Object FInsStr ();
+extern Lisp_Object Finsert_string ();
diff --git a/src/ndir.h b/src/ndir.h
new file mode 100644 (file)
index 0000000..438d5c2
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+       <dir.h> -- definitions for 4.2BSD-compatible directory access
+
+       last edit:      09-Jul-1983     D A Gwyn
+*/
+
+#ifdef VMS
+#ifndef FAB$C_BID
+#include <fab.h>
+#endif
+#ifndef NAM$C_BID
+#include <nam.h>
+#endif
+#ifndef RMS$_SUC
+#include <rmsdef.h>
+#endif
+#include "dir.h"
+#endif /* VMS */
+
+#define DIRBLKSIZ      512             /* size of directory block */
+#ifdef VMS
+#define MAXNAMLEN      (DIR$S_NAME + 7) /* 80 plus room for version #.  */
+#define MAXFULLSPEC    NAM$C_MAXRSS /* Maximum full spec */
+#else
+#define MAXNAMLEN      15              /* maximum filename length */
+#endif /* VMS */
+       /* NOTE:  MAXNAMLEN must be one less than a multiple of 4 */
+
+struct direct                          /* data from readdir() */
+       {
+       long            d_ino;          /* inode number of entry */
+       unsigned short  d_reclen;       /* length of this record */
+       unsigned short  d_namlen;       /* length of string in d_name */
+       char            d_name[MAXNAMLEN+1];    /* name of file */
+       };
+
+typedef struct
+       {
+       int     dd_fd;                  /* file descriptor */
+       int     dd_loc;                 /* offset in block */
+       int     dd_size;                /* amount of valid data */
+       char    dd_buf[DIRBLKSIZ];      /* directory block */
+       }       DIR;                    /* stream data from opendir() */
+
+extern DIR             *opendir();
+extern struct direct   *readdir();
+extern long            telldir();
+extern void            seekdir();
+extern void            closedir();
+
+#define rewinddir( dirp )      seekdir( dirp, 0L )
diff --git a/src/param.h b/src/param.h
new file mode 100644 (file)
index 0000000..1b27b50
--- /dev/null
@@ -0,0 +1,2 @@
+/* This is so that Emacs can run on VMS... */
+#define EXEC_PAGESIZE 512
diff --git a/src/point.h b/src/point.h
new file mode 100644 (file)
index 0000000..7bae693
--- /dev/null
@@ -0,0 +1,5 @@
+#define point_width 5
+#define point_height 19
+static char point_bits[] = {
+   0x1f, 0x0e, 0x0e, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x04, 0x04, 0x0e, 0x0e, 0x1f};
diff --git a/src/pre-crt0.c b/src/pre-crt0.c
new file mode 100644 (file)
index 0000000..67fd31c
--- /dev/null
@@ -0,0 +1,9 @@
+/* This file is loaded before crt0.o on machines where we do not
+   remap part of the data space into text space in unexec.
+   On these machines, there is no problem with standard crt0.o's
+   that make environ an initialized variable.  However, we do
+   need to make sure the label data_start exists anyway.  */
+
+/* Create a label to appear at the beginning of data space.  */
+
+int data_start = 0;
index 4934ba5..9473d3d 100644 (file)
@@ -21,9 +21,19 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
    At one point, this was defined in config.h, meaning that changing
    PURESIZE would make Make recompile all of Emacs.  But only a few
-   files actually use PURESIZE, so we split it out to its own .h file.  */
+   files actually use PURESIZE, so we split it out to its own .h file.
 
+   Make sure to include this file after config.h, since that tells us
+   whether we are running X windows, which tells us how much pure
+   storage to allocate.  */
+
+#ifndef PURESIZE
+#ifdef HAVE_X_WINDOWS
 #define PURESIZE 200000
+#else
+#define PURESIZE 196000
+#endif
+#endif
 
 #ifdef VIRT_ADDR_VARIES
 
diff --git a/src/sink.h b/src/sink.h
new file mode 100644 (file)
index 0000000..1eb6770
--- /dev/null
@@ -0,0 +1,91 @@
+#define sink_width 48
+#define sink_height 48
+#ifdef HAVE_X11
+static char sink_bits[] = {
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+   0xff, 0xff, 0xff, 0xff, 0x80, 0x9f, 
+   0xff, 0xff, 0xff, 0xff, 0x9f, 0x9f, 
+   0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 
+   0xff, 0xff, 0xff, 0x7f, 0xfe, 0xbf, 
+   0xff, 0xff, 0xff, 0x7f, 0x03, 0xa0, 
+   0xff, 0xff, 0xff, 0x7f, 0xfd, 0xaf, 
+   0xff, 0xff, 0xff, 0x3f, 0xf9, 0xaf, 
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 
+   0xff, 0xff, 0xff, 0xff, 0xfc, 0xaf, 
+   0xff, 0xff, 0xff, 0x7f, 0xf8, 0xaf, 
+   0xff, 0xff, 0xff, 0xff, 0xfc, 0xaf, 
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 
+   0xff, 0xff, 0xff, 0xbf, 0xf7, 0xaf, 
+   0xff, 0xff, 0xff, 0x3f, 0xf3, 0xaf, 
+   0xff, 0xff, 0xff, 0xff, 0xfc, 0xaf, 
+   0x3f, 0x00, 0x00, 0x00, 0x00, 0x20, 
+   0x7f, 0x00, 0x00, 0x00, 0x00, 0xe0, 
+   0xdf, 0xf8, 0xff, 0xff, 0xff, 0x07, 
+   0xcf, 0xf9, 0x0f, 0xff, 0xff, 0xe7, 
+   0xcf, 0xf9, 0xf7, 0xff, 0xff, 0xe7, 
+   0xff, 0xf9, 0xf7, 0x63, 0xfb, 0xe7, 
+   0xff, 0xf9, 0x37, 0x5a, 0xfb, 0xe7, 
+   0xcf, 0xf9, 0xf7, 0x5a, 0xfb, 0xe7, 
+   0xcf, 0xf9, 0xf7, 0x5a, 0xf9, 0xe7, 
+   0xef, 0xf9, 0x0f, 0xdb, 0xfa, 0xe7, 
+   0xff, 0xf9, 0xff, 0xff, 0xff, 0xe7, 
+   0xdf, 0xf9, 0xff, 0xff, 0xff, 0xe7, 
+   0xcf, 0x19, 0xfc, 0xff, 0xff, 0xe7, 
+   0xcf, 0xd9, 0xff, 0xff, 0xff, 0xe7, 
+   0xff, 0xd9, 0x47, 0xce, 0x73, 0xe6, 
+   0xff, 0x19, 0xb6, 0xb5, 0xad, 0xe7, 
+   0xcf, 0xd9, 0xb7, 0xb5, 0x7d, 0xe6, 
+   0xc7, 0xd9, 0xb7, 0xb5, 0xed, 0xe5, 
+   0xef, 0x19, 0xb4, 0x4d, 0x73, 0xe6, 
+   0xff, 0xf1, 0xff, 0xff, 0xff, 0xe3, 
+   0xff, 0x03, 0x80, 0x03, 0x00, 0xf0, 
+   0xef, 0x07, 0x00, 0x01, 0x00, 0xf8, 
+   0xc7, 0xff, 0x3f, 0xf9, 0xff, 0xff, 
+   0xe7, 0xff, 0x7f, 0xfd, 0xe0, 0xff, 
+   0xff, 0xff, 0x7f, 0x7d, 0xdf, 0xff, 
+   0xff, 0xff, 0x7f, 0xbd, 0xb1, 0xff, 
+   0xff, 0xff, 0x7f, 0xbb, 0xae, 0xff, 
+   0xef, 0xff, 0xff, 0xda, 0xae, 0xff, 
+   0xc7, 0xff, 0xff, 0x66, 0xaf, 0xff, 
+   0xe7, 0xff, 0xff, 0xbd, 0xaf, 0xff, 
+   0xff, 0xff, 0xff, 0xc3, 0xaf, 0xff, 
+   0xff, 0xff, 0xff, 0xff, 0xaf, 0xff};
+#else
+short sink_bits[] = {
+   0xffff, 0xffff, 0xffff, 0xffff,
+   0xffff, 0x9f80, 0xffff, 0xffff,
+   0x9f9f, 0xffff, 0xffff, 0x8000,
+   0xffff, 0x7fff, 0xbffe, 0xffff,
+   0x7fff, 0xa003, 0xffff, 0x7fff,
+   0xaffd, 0xffff, 0x3fff, 0xaff9,
+   0xffff, 0xffff, 0xafff, 0xffff,
+   0xffff, 0xaffc, 0xffff, 0x7fff,
+   0xaff8, 0xffff, 0xffff, 0xaffc,
+   0xffff, 0xffff, 0xafff, 0xffff,
+   0xbfff, 0xaff7, 0xffff, 0x3fff,
+   0xaff3, 0xffff, 0xffff, 0xaffc,
+   0x003f, 0x0000, 0x2000, 0x007f,
+   0x0000, 0xe000, 0xf8df, 0xffff,
+   0x07ff, 0xf9cf, 0xff0f, 0xe7ff,
+   0xf9cf, 0xfff7, 0xe7ff, 0xf9ff,
+   0x63f7, 0xe7fb, 0xf9ff, 0x5a37,
+   0xe7fb, 0xf9cf, 0x5af7, 0xe7fb,
+   0xf9cf, 0x5af7, 0xe7f9, 0xf9ef,
+   0xdb0f, 0xe7fa, 0xf9ff, 0xffff,
+   0xe7ff, 0xf9df, 0xffff, 0xe7ff,
+   0x19cf, 0xfffc, 0xe7ff, 0xd9cf,
+   0xffff, 0xe7ff, 0xd9ff, 0xce47,
+   0xe673, 0x19ff, 0xb5b6, 0xe7ad,
+   0xd9cf, 0xb5b7, 0xe67d, 0xd9c7,
+   0xb5b7, 0xe5ed, 0x19ef, 0x4db4,
+   0xe673, 0xf1ff, 0xffff, 0xe3ff,
+   0x03ff, 0x0380, 0xf000, 0x07ef,
+   0x0100, 0xf800, 0xffc7, 0xf93f,
+   0xffff, 0xffe7, 0xfd7f, 0xffe0,
+   0xffff, 0x7d7f, 0xffdf, 0xffff,
+   0xbd7f, 0xffb1, 0xffff, 0xbb7f,
+   0xffae, 0xffef, 0xdaff, 0xffae,
+   0xffc7, 0x66ff, 0xffaf, 0xffe7,
+   0xbdff, 0xffaf, 0xffff, 0xc3ff,
+   0xffaf, 0xffff, 0xffff, 0xffaf};
+#endif /* HAVE_X11 */
diff --git a/src/sink11.h b/src/sink11.h
new file mode 100644 (file)
index 0000000..dec0280
--- /dev/null
@@ -0,0 +1,51 @@
+#define sink_width 48
+#define sink_height 48
+static char sink_bits[] = {
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+   0xff, 0xff, 0xff, 0xff, 0x80, 0x9f, 
+   0xff, 0xff, 0xff, 0xff, 0x9f, 0x9f, 
+   0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 
+   0xff, 0xff, 0xff, 0x7f, 0xfe, 0xbf, 
+   0xff, 0xff, 0xff, 0x7f, 0x03, 0xa0, 
+   0xff, 0xff, 0xff, 0x7f, 0xfd, 0xaf, 
+   0xff, 0xff, 0xff, 0x3f, 0xf9, 0xaf, 
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 
+   0xff, 0xff, 0xff, 0xff, 0xfc, 0xaf, 
+   0xff, 0xff, 0xff, 0x7f, 0xf8, 0xaf, 
+   0xff, 0xff, 0xff, 0xff, 0xfc, 0xaf, 
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 
+   0xff, 0xff, 0xff, 0xbf, 0xf7, 0xaf, 
+   0xff, 0xff, 0xff, 0x3f, 0xf3, 0xaf, 
+   0xff, 0xff, 0xff, 0xff, 0xfc, 0xaf, 
+   0x3f, 0x00, 0x00, 0x00, 0x00, 0x20, 
+   0x7f, 0x00, 0x00, 0x00, 0x00, 0xe0, 
+   0xdf, 0xf8, 0xff, 0xff, 0xff, 0x07, 
+   0xcf, 0xf9, 0x0f, 0xff, 0xff, 0xe7, 
+   0xcf, 0xf9, 0xf7, 0xff, 0xff, 0xe7, 
+   0xff, 0xf9, 0xf7, 0x63, 0xfb, 0xe7, 
+   0xff, 0xf9, 0x37, 0x5a, 0xfb, 0xe7, 
+   0xcf, 0xf9, 0xf7, 0x5a, 0xfb, 0xe7, 
+   0xcf, 0xf9, 0xf7, 0x5a, 0xf9, 0xe7, 
+   0xef, 0xf9, 0x0f, 0xdb, 0xfa, 0xe7, 
+   0xff, 0xf9, 0xff, 0xff, 0xff, 0xe7, 
+   0xdf, 0xf9, 0xff, 0xff, 0xff, 0xe7, 
+   0xcf, 0x19, 0xfc, 0xff, 0xff, 0xe7, 
+   0xcf, 0xd9, 0xff, 0xff, 0xff, 0xe7, 
+   0xff, 0xd9, 0x47, 0xce, 0x73, 0xe6, 
+   0xff, 0x19, 0xb6, 0xb5, 0xad, 0xe7, 
+   0xcf, 0xd9, 0xb7, 0xb5, 0x7d, 0xe6, 
+   0xc7, 0xd9, 0xb7, 0xb5, 0xed, 0xe5, 
+   0xef, 0x19, 0xb4, 0x4d, 0x73, 0xe6, 
+   0xff, 0xf1, 0xff, 0xff, 0xff, 0xe3, 
+   0xff, 0x03, 0x80, 0x03, 0x00, 0xf0, 
+   0xef, 0x07, 0x00, 0x01, 0x00, 0xf8, 
+   0xc7, 0xff, 0x3f, 0xf9, 0xff, 0xff, 
+   0xe7, 0xff, 0x7f, 0xfd, 0xe0, 0xff, 
+   0xff, 0xff, 0x7f, 0x7d, 0xdf, 0xff, 
+   0xff, 0xff, 0x7f, 0xbd, 0xb1, 0xff, 
+   0xff, 0xff, 0x7f, 0xbb, 0xae, 0xff, 
+   0xef, 0xff, 0xff, 0xda, 0xae, 0xff, 
+   0xc7, 0xff, 0xff, 0x66, 0xaf, 0xff, 
+   0xe7, 0xff, 0xff, 0xbd, 0xaf, 0xff, 
+   0xff, 0xff, 0xff, 0xc3, 0xaf, 0xff, 
+   0xff, 0xff, 0xff, 0xff, 0xaf, 0xff};
diff --git a/src/sink11mask.h b/src/sink11mask.h
new file mode 100644 (file)
index 0000000..b0a6e0c
--- /dev/null
@@ -0,0 +1,51 @@
+#define sink_mask_width 48
+#define sink_mask_height 48
+static char sink_mask_bits[] = {
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 
diff --git a/src/terminfo.c b/src/terminfo.c
new file mode 100644 (file)
index 0000000..af05713
--- /dev/null
@@ -0,0 +1,50 @@
+/* Interface from Emacs to terminfo.
+   Copyright (C) 1985, 1986 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Define these variables that serve as global parameters to termcap,
+   so that we do not need to conditionalize the places in Emacs
+   that set them.  */
+
+char *UP, *BC, PC;
+short ospeed;
+
+static buffer[512];
+
+/* Interface to curses/terminfo library.
+   Turns out that all of the terminfo-level routines look
+   like their termcap counterparts except for tparm, which replaces
+   tgoto.  Not only is the calling sequence different, but the string
+   format is different too.
+*/
+
+char *
+tparam (string, outstring, len, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
+     char *string;
+     char *outstring;
+     int arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9;
+{
+  char *temp;
+  extern char *tparm();
+
+  temp = tparm (string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+  if (outstring == 0)
+    outstring = ((char *) (malloc ((strlen (temp)) + 1)));
+  strcpy (outstring, temp);
+  return outstring;
+}
index 2b351a2..2c9387e 100644 (file)
--- a/src/uaf.h
+++ b/src/uaf.h
@@ -3,20 +3,19 @@
 
 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 1, or (at your option)
+any later version.
+
 GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY.  No author or distributor
-accepts responsibility to anyone for the consequences of using it
-or for whether it serves any particular purpose or works at all,
-unless he says so in writing.  Refer to the GNU Emacs General Public
-License for full details.
+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.
 
-Everyone is granted permission to copy, modify and redistribute
-GNU Emacs, but only under the conditions described in the
-GNU Emacs General Public License.   A copy of this license is
-supposed to have been given to you along with GNU Emacs so you
-can know your rights and responsibilities.  It should be in a
-file named COPYING.  Among other things, the copyright notice
-and this notice must be preserved on all copies.  */
+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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /*
  * User Authorization File record formats
diff --git a/src/unexconvex.c b/src/unexconvex.c
new file mode 100644 (file)
index 0000000..09a7dff
--- /dev/null
@@ -0,0 +1,601 @@
+/* Modified version of unexec for convex machines.
+   Note that the GNU project considers support for the peculiarities
+   of the Convex operating system a peripheral activity which should
+   not be allowed to divert effort from development of the GNU system.
+   Changes in this code will be installed when Convex system
+   maintainers send them in, but aside from that we don't plan to
+   think about it, or about whether other Emacs maintenance might
+   break it.
+
+   Copyright (C) 1985, 1986, 1988 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+/* modified for C-1 arch by jthomp@convex 871103 */
+/* Corrected to support convex SOFF object file formats and thread specific
+ * regions.  streepy@convex 890302
+*/
+
+/*
+ * unexec.c - Convert a running program into an a.out file.
+ *
+ * Author:     Spencer W. Thomas
+ *             Computer Science Dept.
+ *             University of Utah
+ * Date:       Tue Mar  2 1982
+ * Modified heavily since then.
+ *
+ * Synopsis:
+ *     unexec (new_name, a_name, data_start, bss_start, entry_address)
+ *     char *new_name, *a_name;
+ *     unsigned data_start, bss_start, entry_address;
+ *
+ * Takes a snapshot of the program and makes an a.out format file in the
+ * file named by the string argument new_name.
+ * If a_name is non-NULL, the symbol table will be taken from the given file.
+ * On some machines, an existing a_name file is required.
+ *
+ * The boundaries within the a.out file may be adjusted with the data_start
+ * and bss_start arguments.  Either or both may be given as 0 for defaults.
+ *
+ * Data_start gives the boundary between the text segment and the data
+ * segment of the program.  The text segment can contain shared, read-only
+ * program code and literal data, while the data segment is always unshared
+ * and unprotected.  Data_start gives the lowest unprotected address.
+ * The value you specify may be rounded down to a suitable boundary
+ * as required by the machine you are using.
+ *
+ * Specifying zero for data_start means the boundary between text and data
+ * should not be the same as when the program was loaded.
+ * If NO_REMAP is defined, the argument data_start is ignored and the
+ * segment boundaries are never changed.
+ *
+ * Bss_start indicates how much of the data segment is to be saved in the
+ * a.out file and restored when the program is executed.  It gives the lowest
+ * unsaved address, and is rounded up to a page boundary.  The default when 0
+ * is given assumes that the entire data segment is to be stored, including
+ * the previous data and bss as well as any additional storage allocated with
+ * break (2).
+ *
+ * The new file is set up to start at entry_address.
+ *
+ * If you make improvements I'd like to get them too.
+ * harpo!utah-cs!thomas, thomas@Utah-20
+ *
+ */
+
+/* There are several compilation parameters affecting unexec:
+
+* COFF
+
+Define this if your system uses COFF for executables.
+Otherwise we assume you use Berkeley format.
+
+* NO_REMAP
+
+Define this if you do not want to try to save Emacs's pure data areas
+as part of the text segment.
+
+Saving them as text is good because it allows users to share more.
+
+However, on machines that locate the text area far from the data area,
+the boundary cannot feasibly be moved.  Such machines require
+NO_REMAP.
+
+Also, remapping can cause trouble with the built-in startup routine
+/lib/crt0.o, which defines `environ' as an initialized variable.
+Dumping `environ' as pure does not work!  So, to use remapping,
+you must write a startup routine for your machine in Emacs's crt0.c.
+If NO_REMAP is defined, Emacs uses the system's crt0.o.
+
+* SECTION_ALIGNMENT
+
+Some machines that use COFF executables require that each section
+start on a certain boundary *in the COFF file*.  Such machines should
+define SECTION_ALIGNMENT to a mask of the low-order bits that must be
+zero on such a boundary.  This mask is used to control padding between
+segments in the COFF file.
+
+If SECTION_ALIGNMENT is not defined, the segments are written
+consecutively with no attempt at alignment.  This is right for
+unmodified system V.
+
+* SEGMENT_MASK
+
+Some machines require that the beginnings and ends of segments
+*in core* be on certain boundaries.  For most machines, a page
+boundary is sufficient.  That is the default.  When a larger
+boundary is needed, define SEGMENT_MASK to a mask of
+the bits that must be zero on such a boundary.
+
+* A_TEXT_OFFSET(HDR)
+
+Some machines count the a.out header as part of the size of the text
+segment (a_text); they may actually load the header into core as the
+first data in the text segment.  Some have additional padding between
+the header and the real text of the program that is counted in a_text.
+
+For these machines, define A_TEXT_OFFSET(HDR) to examine the header
+structure HDR and return the number of bytes to add to `a_text'
+before writing it (above and beyond the number of bytes of actual
+program text).  HDR's standard fields are already correct, except that
+this adjustment to the `a_text' field has not yet been made;
+thus, the amount of offset can depend on the data in the file.
+  
+* A_TEXT_SEEK(HDR)
+
+If defined, this macro specifies the number of bytes to seek into the
+a.out file before starting to write the text segment.a
+
+* EXEC_MAGIC
+
+For machines using COFF, this macro, if defined, is a value stored
+into the magic number field of the output file.
+
+* ADJUST_EXEC_HEADER
+
+This macro can be used to generate statements to adjust or
+initialize nonstandard fields in the file header
+
+* ADDR_CORRECT(ADDR)
+
+Macro to correct an int which is the bit pattern of a pointer to a byte
+into an int which is the number of a byte.
+
+This macro has a default definition which is usually right.
+This default definition is a no-op on most machines (where a
+pointer looks like an int) but not on all machines.
+
+*/
+
+#include "config.h"
+#define PERROR(file) report_error (file, new)
+
+#include <a.out.h>
+/* Define getpagesize () if the system does not.
+   Note that this may depend on symbols defined in a.out.h
+ */
+#include "getpagesize.h"
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+extern char *start_of_text ();         /* Start of text */
+extern char *start_of_data ();         /* Start of initialized data */
+
+#include <machine/filehdr.h>
+#include <machine/opthdr.h>
+#include <machine/scnhdr.h>
+#include <machine/pte.h>
+
+static long block_copy_start;  /* Old executable start point */
+static struct filehdr f_hdr;   /* File header */
+static struct opthdr f_ohdr;   /* Optional file header (a.out) */
+long bias;                     /* Bias to add for growth */
+#define SYMS_START block_copy_start
+
+static long text_scnptr;
+static long data_scnptr;
+
+static int pagemask;
+static int pagesz;
+
+static
+report_error (file, fd)
+     char *file;
+     int fd;
+{
+    if (fd)
+       close (fd);
+    error ("Failure operating on %s", file);
+}
+
+#define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1
+#define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1
+#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1
+
+static
+report_error_1 (fd, msg, a1, a2)
+int fd;
+char *msg;
+int a1, a2;
+{
+    close (fd);
+    error (msg, a1, a2);
+}
+\f
+/* ****************************************************************
+ * unexec
+ *
+ * driving logic.
+ */
+unexec (new_name, a_name, data_start, bss_start, entry_address)
+char *new_name, *a_name;
+unsigned data_start, bss_start, entry_address;
+{
+    int new, a_out = -1;
+
+    if (a_name && (a_out = open (a_name, 0)) < 0) {
+       PERROR (a_name);
+    }
+    if ((new = creat (new_name, 0666)) < 0) {
+       PERROR (new_name);
+    }
+
+    if (make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) < 0
+      || copy_text_and_data (new) < 0
+      || copy_sym (new, a_out, a_name, new_name) < 0 ) {
+       close (new);
+       return -1;      
+    }
+
+    close (new);
+    if (a_out >= 0)
+       close (a_out);
+    mark_x (new_name);
+    return 0;
+}
+
+/* ****************************************************************
+ * make_hdr
+ *
+ * Make the header in the new a.out from the header in core.
+ * Modify the text and data sizes.
+ */
+
+ struct scnhdr *stbl;          /* Table of all scnhdr's */
+ struct scnhdr *f_thdr;                /* Text section header */
+ struct scnhdr *f_dhdr;                /* Data section header */
+ struct scnhdr *f_tdhdr;       /* Thread Data section header */
+ struct scnhdr *f_bhdr;                /* Bss section header */
+ struct scnhdr *f_tbhdr;       /* Thread Bss section header */
+
+static int
+make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
+     int new, a_out;
+     unsigned data_start, bss_start, entry_address;
+     char *a_name;
+     char *new_name;
+{
+    register int scns;
+    unsigned int bss_end;
+    unsigned int eo_data;      /* End of initialized data in new exec file */
+    int scntype;               /* Section type */
+    int i;                     /* Var for sorting by vaddr */
+    struct scnhdr scntemp;     /* For swapping entries in sort */
+    extern char *start_of_data();
+
+    pagemask = (pagesz = getpagesize()) - 1;
+
+    /* Adjust text/data boundary. */
+    if (!data_start)
+       data_start = (unsigned) start_of_data ();
+
+    data_start = data_start & ~pagemask; /* (Down) to page boundary. */
+
+    bss_end = (sbrk(0) + pagemask) & ~pagemask;
+
+    /* Adjust data/bss boundary. */
+    if (bss_start != 0) {
+       bss_start = (bss_start + pagemask) & ~pagemask;/* (Up) to page bdry. */
+       if (bss_start > bss_end) {
+           ERROR1 ("unexec: Specified bss_start (%x) is past end of program",
+                   bss_start);
+       }
+    } else
+       bss_start = bss_end;
+
+    if (data_start > bss_start)        { /* Can't have negative data size. */
+       ERROR2 ("unexec: data_start (%x) can't be greater than bss_start (%x)",
+               data_start, bss_start);
+    }
+
+    /* Salvage as much info from the existing file as possible */
+    if (a_out < 0) {
+       ERROR0 ("can't build a COFF file from scratch yet");
+       /*NOTREACHED*/
+    }
+
+    if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)) {
+       PERROR (a_name);
+    }
+    block_copy_start += sizeof (f_hdr);
+    if (f_hdr.h_opthdr > 0) {
+       if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr)) {
+           PERROR (a_name);
+       }
+       block_copy_start += sizeof (f_ohdr);
+    }
+
+    /* Allocate room for scn headers */
+    stbl = (struct scnhdr *)malloc( sizeof(struct scnhdr) * f_hdr.h_nscns );
+    if( stbl == NULL ) {
+       ERROR0( "unexec: malloc of stbl failed" );
+    }
+
+    f_tdhdr = f_tbhdr = NULL;
+
+    /* Loop through section headers, copying them in */
+    for (scns = 0; scns < f_hdr.h_nscns; scns++) {
+
+       if( read( a_out, &stbl[scns], sizeof(*stbl)) != sizeof(*stbl)) {
+           PERROR (a_name);
+       }
+
+       scntype = stbl[scns].s_flags & S_TYPMASK; /* What type of section */
+
+       if( stbl[scns].s_scnptr > 0L) {
+           if( block_copy_start < stbl[scns].s_scnptr + stbl[scns].s_size )
+               block_copy_start = stbl[scns].s_scnptr + stbl[scns].s_size;
+       }
+
+       if( scntype == S_TEXT) {
+           f_thdr = &stbl[scns];
+       } else if( scntype == S_DATA) {
+           f_dhdr = &stbl[scns];
+#ifdef S_TDATA
+       } else if( scntype == S_TDATA ) {
+           f_tdhdr = &stbl[scns];
+       } else if( scntype == S_TBSS ) {
+           f_tbhdr = &stbl[scns];
+#endif /* S_TDATA (thread stuff) */
+
+       } else if( scntype == S_BSS) {
+           f_bhdr = &stbl[scns];
+       }
+
+    }
+
+    /* We will now convert TEXT and DATA into TEXT, BSS into DATA, and leave
+     * all thread stuff alone.
+     */
+
+    /* Now we alter the contents of all the f_*hdr variables
+       to correspond to what we want to dump.  */
+
+    f_thdr->s_vaddr = (long) start_of_text ();
+    f_thdr->s_size = data_start - f_thdr->s_vaddr;
+    f_thdr->s_scnptr = pagesz;
+    f_thdr->s_relptr = 0;
+    f_thdr->s_nrel = 0;
+
+    eo_data = f_thdr->s_scnptr + f_thdr->s_size;
+
+    if( f_tdhdr ) {            /* Process thread data */
+
+       f_tdhdr->s_vaddr = data_start;
+       f_tdhdr->s_size += f_dhdr->s_size - (data_start - f_dhdr->s_vaddr);
+       f_tdhdr->s_scnptr = eo_data;
+       f_tdhdr->s_relptr = 0;
+       f_tdhdr->s_nrel = 0;
+
+       eo_data += f_tdhdr->s_size;
+
+       /* And now for DATA */
+
+       f_dhdr->s_vaddr = f_bhdr->s_vaddr; /* Take BSS start address */
+       f_dhdr->s_size = bss_end - f_bhdr->s_vaddr;
+       f_dhdr->s_scnptr = eo_data;
+       f_dhdr->s_relptr = 0;
+       f_dhdr->s_nrel = 0;
+
+       eo_data += f_dhdr->s_size;
+
+    } else {
+
+       f_dhdr->s_vaddr = data_start;
+       f_dhdr->s_size = bss_start - data_start;
+       f_dhdr->s_scnptr = eo_data;
+       f_dhdr->s_relptr = 0;
+       f_dhdr->s_nrel = 0;
+
+       eo_data += f_dhdr->s_size;
+
+    }
+
+    f_bhdr->s_vaddr = bss_start;
+    f_bhdr->s_size = bss_end - bss_start + pagesz /* fudge */;
+    f_bhdr->s_scnptr = 0;
+    f_bhdr->s_relptr = 0;
+    f_bhdr->s_nrel = 0;
+
+    text_scnptr = f_thdr->s_scnptr;
+    data_scnptr = f_dhdr->s_scnptr;
+    bias = eo_data - block_copy_start;
+
+    if (f_ohdr.o_symptr > 0L) {
+       f_ohdr.o_symptr += bias;
+    }
+
+    if (f_hdr.h_strptr > 0) {
+       f_hdr.h_strptr += bias;
+    }
+
+    if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)) {
+       PERROR (new_name);
+    }
+
+    if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr)) {
+       PERROR (new_name);
+    }
+
+    for( scns = 0; scns < f_hdr.h_nscns; scns++ ) {
+
+       /* This is a cheesey little loop to write out the section headers
+        * in order of increasing virtual address. Dull but effective.
+        */
+
+       for( i = scns+1; i < f_hdr.h_nscns; i++ ) {
+           if( stbl[i].s_vaddr < stbl[scns].s_vaddr ) { /* Swap */
+               scntemp = stbl[i];
+               stbl[i] = stbl[scns];
+               stbl[scns] = scntemp;
+           }
+       }
+
+    }
+
+    for( scns = 0; scns < f_hdr.h_nscns; scns++ ) {
+
+       if( write( new, &stbl[scns], sizeof(*stbl)) != sizeof(*stbl)) {
+           PERROR (new_name);
+       }
+
+    }
+
+    return (0);
+
+}
+\f
+/* ****************************************************************
+ * copy_text_and_data
+ *
+ * Copy the text and data segments from memory to the new a.out
+ */
+static int
+copy_text_and_data (new)
+int new;
+{
+    register int scns;
+
+    for( scns = 0; scns < f_hdr.h_nscns; scns++ )
+       write_segment( new, &stbl[scns] );
+
+    return 0;
+}
+
+write_segment( new, sptr )
+int new;
+struct scnhdr *sptr;
+{
+    register char *ptr, *end;
+    register int nwrite, ret;
+    char buf[80];
+    extern int errno;
+    char zeros[128];
+
+    if( sptr->s_scnptr == 0 )
+       return;                 /* Nothing to do */
+
+    if( lseek( new, (long) sptr->s_scnptr, 0 ) == -1 )
+       PERROR( "unexecing" );
+
+    bzero (zeros, sizeof zeros);
+
+    ptr = (char *) sptr->s_vaddr;
+    end = ptr + sptr->s_size;
+
+    while( ptr < end ) {
+
+       /* distance to next multiple of 128.  */
+       nwrite = (((int) ptr + 128) & -128) - (int) ptr;
+       /* But not beyond specified end.  */
+       if (nwrite > end - ptr) nwrite = end - ptr;
+       ret = write (new, ptr, nwrite);
+       /* If write gets a page fault, it means we reached
+          a gap between the old text segment and the old data segment.
+          This gap has probably been remapped into part of the text segment.
+          So write zeros for it.  */
+       if (ret == -1 && errno == EFAULT)
+           write (new, zeros, nwrite);
+       else if (nwrite != ret) {
+           sprintf (buf,
+                    "unexec write failure: addr 0x%x, fileno %d, size 0x%x, wrote 0x%x, errno %d",
+                    ptr, new, nwrite, ret, errno);
+           PERROR (buf);
+       }
+       ptr += nwrite;
+    }
+}
+\f
+/* ****************************************************************
+ * copy_sym
+ *
+ * Copy the relocation information and symbol table from the a.out to the new
+ */
+static int
+copy_sym (new, a_out, a_name, new_name)
+     int new, a_out;
+     char *a_name, *new_name;
+{
+    char page[1024];
+    int n;
+
+    if (a_out < 0)
+       return 0;
+
+    if (SYMS_START == 0L)
+       return 0;
+
+    lseek (a_out, SYMS_START, 0);      /* Position a.out to symtab. */
+    lseek( new, (long)f_ohdr.o_symptr, 0 );
+
+    while ((n = read (a_out, page, sizeof page)) > 0) {
+       if (write (new, page, n) != n) {
+           PERROR (new_name);
+       }
+    }
+    if (n < 0) {
+       PERROR (a_name);
+    }
+    return 0;
+}
+\f
+/* ****************************************************************
+ * mark_x
+ *
+ * After succesfully building the new a.out, mark it executable
+ */
+static
+mark_x (name)
+char *name;
+{
+    struct stat sbuf;
+    int um;
+    int new = 0;  /* for PERROR */
+
+    um = umask (777);
+    umask (um);
+    if (stat (name, &sbuf) == -1) {
+       PERROR (name);
+    }
+    sbuf.st_mode |= 0111 & ~um;
+    if (chmod (name, sbuf.st_mode) == -1)
+       PERROR (name);
+}
+\f
+/* Find the first pty letter.  This is usually 'p', as in ptyp0, but
+   is sometimes configured down to 'm', 'n', or 'o' for some reason. */
+
+first_pty_letter ()
+{
+  struct stat buf;
+  char pty_name[16];
+  char c;
+
+  for (c = 'o'; c >= 'a'; c--)
+    {
+      sprintf (pty_name, "/dev/pty%c0", c);
+      if (stat (pty_name, &buf) < 0)
+       return c + 1;
+    }
+  return 'a';
+}
+
diff --git a/src/unexelf.c b/src/unexelf.c
new file mode 100644 (file)
index 0000000..784fab1
--- /dev/null
@@ -0,0 +1,703 @@
+/* Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
+
+                      NO WARRANTY
+
+  BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
+NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW.  EXCEPT
+WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
+RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
+WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY
+AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE
+DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
+STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
+WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
+OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
+DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
+A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
+PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
+
+               GENERAL PUBLIC LICENSE TO COPY
+
+  1. You may copy and distribute verbatim copies of this source file
+as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy a valid copyright notice "Copyright
+(C) 1987 Free Software Foundation, Inc."; and include following the
+copyright notice a verbatim copy of the above disclaimer of warranty
+and of this License.  You may charge a distribution fee for the
+physical act of transferring a copy.
+
+  2. You may modify your copy or copies of this source file or
+any portion of it, and copy and distribute such modifications under
+the terms of Paragraph 1 above, provided that you also do the following:
+
+    a) cause the modified files to carry prominent notices stating
+    that you changed the files and the date of any change; and
+
+    b) cause the whole of any work that you distribute or publish,
+    that in whole or in part contains or is a derivative of this
+    program or any part thereof, to be licensed at no charge to all
+    third parties on terms identical to those contained in this
+    License Agreement (except that you may choose to grant more extensive
+    warranty protection to some or all third parties, at your option).
+
+    c) You may charge a distribution fee for the physical act of
+    transferring a copy, and you may at your option offer warranty
+    protection in exchange for a fee.
+
+Mere aggregation of another unrelated program with this program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other program under the scope of these terms.
+
+  3. You may copy and distribute this program (or a portion or derivative
+of it, under Paragraph 2) in object code or executable form under the terms
+of Paragraphs 1 and 2 above provided that you also do one of the following:
+
+    a) accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    b) accompany it with a written offer, valid for at least three
+    years, to give any third party free (except for a nominal
+    shipping charge) a complete machine-readable copy of the
+    corresponding source code, to be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    c) accompany it with the information you received as to where the
+    corresponding source code may be obtained.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form alone.)
+
+For an executable file, complete source code means all the source code for
+all modules it contains; but, as a special exception, it need not include
+source code for modules which are standard libraries that accompany the
+operating system on which the executable file runs.
+
+  4. You may not copy, sublicense, distribute or transfer this program
+except as expressly provided under this License Agreement.  Any attempt
+otherwise to copy, sublicense, distribute or transfer this program is void and
+your rights to use the program under this License agreement shall be
+automatically terminated.  However, parties who have received computer
+software programs from you with this License Agreement will not have
+their licenses terminated so long as such parties remain in full compliance.
+
+  5. If you wish to incorporate parts of this program into other free
+programs whose distribution conditions are different, write to the Free
+Software Foundation at 675 Mass Ave, Cambridge, MA 02139.  We have not yet
+worked out a simple rule that can be stated here, but we will often permit
+this.  We will be guided by the two goals of preserving the free status of
+all derivatives of our free software and of promoting the sharing and reuse of
+software.
+
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them.   Help stamp out software-hoarding!  */
+
+
+/*
+ * unexec.c - Convert a running program into an a.out file.
+ *
+ * Author:     Spencer W. Thomas
+ *             Computer Science Dept.
+ *             University of Utah
+ * Date:       Tue Mar  2 1982
+ * Modified heavily since then.
+ *
+ * Synopsis:
+ *     unexec (new_name, a_name, data_start, bss_start, entry_address)
+ *     char *new_name, *a_name;
+ *     unsigned data_start, bss_start, entry_address;
+ *
+ * Takes a snapshot of the program and makes an a.out format file in the
+ * file named by the string argument new_name.
+ * If a_name is non-NULL, the symbol table will be taken from the given file.
+ * On some machines, an existing a_name file is required.
+ *
+ * The boundaries within the a.out file may be adjusted with the data_start
+ * and bss_start arguments.  Either or both may be given as 0 for defaults.
+ *
+ * Data_start gives the boundary between the text segment and the data
+ * segment of the program.  The text segment can contain shared, read-only
+ * program code and literal data, while the data segment is always unshared
+ * and unprotected.  Data_start gives the lowest unprotected address.
+ * The value you specify may be rounded down to a suitable boundary
+ * as required by the machine you are using.
+ *
+ * Specifying zero for data_start means the boundary between text and data
+ * should not be the same as when the program was loaded.
+ * If NO_REMAP is defined, the argument data_start is ignored and the
+ * segment boundaries are never changed.
+ *
+ * Bss_start indicates how much of the data segment is to be saved in the
+ * a.out file and restored when the program is executed.  It gives the lowest
+ * unsaved address, and is rounded up to a page boundary.  The default when 0
+ * is given assumes that the entire data segment is to be stored, including
+ * the previous data and bss as well as any additional storage allocated with
+ * break (2).
+ *
+ * The new file is set up to start at entry_address.
+ *
+ * If you make improvements I'd like to get them too.
+ * harpo!utah-cs!thomas, thomas@Utah-20
+ *
+ */
+
+/* Even more heavily modified by james@bigtex.cactus.org of Dell Computer Co.
+ * ELF support added.
+ *
+ * Basic theory: the data space of the running process needs to be
+ * dumped to the output file.  Normally we would just enlarge the size
+ * of .data, scooting everything down.  But we can't do that in ELF,
+ * because there is often something between the .data space and the
+ * .bss space.
+ *
+ * In the temacs dump below, notice that the Global Offset Table
+ * (.got) and the Dynamic link data (.dynamic) come between .data1 and
+ * .bss.  It does not work to overlap .data with these fields.
+ *
+ * The solution is to create a new .data segment.  This segment is
+ * filled with data from the current process.  Since the contents of
+ * various sections refer to sections by index, the new .data segment
+ * is made the last in the table to avoid changing any existing index.
+
+ * This is an example of how the section headers are changed.  "Addr"
+ * is a process virtual address.  "Offset" is a file offset.
+
+raid:/nfs/raid/src/dist-18.56/src> dump -h temacs
+
+temacs:
+
+           **** SECTION HEADER TABLE ****
+[No]    Type    Flags   Addr         Offset       Size          Name
+        Link    Info    Adralgn      Entsize
+
+[1]     1       2       0x80480d4    0xd4         0x13          .interp
+        0       0       0x1          0            
+
+[2]     5       2       0x80480e8    0xe8         0x388         .hash
+        3       0       0x4          0x4          
+
+[3]     11      2       0x8048470    0x470        0x7f0         .dynsym
+        4       1       0x4          0x10         
+
+[4]     3       2       0x8048c60    0xc60        0x3ad         .dynstr
+        0       0       0x1          0            
+
+[5]     9       2       0x8049010    0x1010       0x338         .rel.plt
+        3       7       0x4          0x8          
+
+[6]     1       6       0x8049348    0x1348       0x3           .init
+        0       0       0x4          0            
+
+[7]     1       6       0x804934c    0x134c       0x680         .plt
+        0       0       0x4          0x4          
+
+[8]     1       6       0x80499cc    0x19cc       0x3c56f       .text
+        0       0       0x4          0            
+
+[9]     1       6       0x8085f3c    0x3df3c      0x3           .fini
+        0       0       0x4          0            
+
+[10]    1       2       0x8085f40    0x3df40      0x69c         .rodata
+        0       0       0x4          0            
+
+[11]    1       2       0x80865dc    0x3e5dc      0xd51         .rodata1
+        0       0       0x4          0            
+
+[12]    1       3       0x8088330    0x3f330      0x20afc       .data
+        0       0       0x4          0            
+
+[13]    1       3       0x80a8e2c    0x5fe2c      0x89d         .data1
+        0       0       0x4          0            
+
+[14]    1       3       0x80a96cc    0x606cc      0x1a8         .got
+        0       0       0x4          0x4          
+
+[15]    6       3       0x80a9874    0x60874      0x80          .dynamic
+        4       0       0x4          0x8          
+
+[16]    8       3       0x80a98f4    0x608f4      0x449c        .bss
+        0       0       0x4          0            
+
+[17]    2       0       0            0x608f4      0x9b90        .symtab
+        18      371     0x4          0x10         
+
+[18]    3       0       0            0x6a484      0x8526        .strtab
+        0       0       0x1          0            
+
+[19]    3       0       0            0x729aa      0x93          .shstrtab
+        0       0       0x1          0            
+
+[20]    1       0       0            0x72a3d      0x68b7        .comment
+        0       0       0x1          0            
+
+raid:/nfs/raid/src/dist-18.56/src> dump -h xemacs
+
+xemacs:
+
+           **** SECTION HEADER TABLE ****
+[No]    Type    Flags   Addr         Offset       Size          Name
+        Link    Info    Adralgn      Entsize
+
+[1]     1       2       0x80480d4    0xd4         0x13          .interp
+        0       0       0x1          0            
+
+[2]     5       2       0x80480e8    0xe8         0x388         .hash
+        3       0       0x4          0x4          
+
+[3]     11      2       0x8048470    0x470        0x7f0         .dynsym
+        4       1       0x4          0x10         
+
+[4]     3       2       0x8048c60    0xc60        0x3ad         .dynstr
+        0       0       0x1          0            
+
+[5]     9       2       0x8049010    0x1010       0x338         .rel.plt
+        3       7       0x4          0x8          
+
+[6]     1       6       0x8049348    0x1348       0x3           .init
+        0       0       0x4          0            
+
+[7]     1       6       0x804934c    0x134c       0x680         .plt
+        0       0       0x4          0x4          
+
+[8]     1       6       0x80499cc    0x19cc       0x3c56f       .text
+        0       0       0x4          0            
+
+[9]     1       6       0x8085f3c    0x3df3c      0x3           .fini
+        0       0       0x4          0            
+
+[10]    1       2       0x8085f40    0x3df40      0x69c         .rodata
+        0       0       0x4          0            
+
+[11]    1       2       0x80865dc    0x3e5dc      0xd51         .rodata1
+        0       0       0x4          0            
+
+[12]    1       3       0x8088330    0x3f330      0x20afc       .data
+        0       0       0x4          0            
+
+[13]    1       3       0x80a8e2c    0x5fe2c      0x89d         .data1
+        0       0       0x4          0            
+
+[14]    1       3       0x80a96cc    0x606cc      0x1a8         .got
+        0       0       0x4          0x4          
+
+[15]    6       3       0x80a9874    0x60874      0x80          .dynamic
+        4       0       0x4          0x8          
+
+[16]    8       3       0x80c6800    0x7d800      0             .bss
+        0       0       0x4          0            
+
+[17]    2       0       0            0x7d800      0x9b90        .symtab
+        18      371     0x4          0x10         
+
+[18]    3       0       0            0x87390      0x8526        .strtab
+        0       0       0x1          0            
+
+[19]    3       0       0            0x8f8b6      0x93          .shstrtab
+        0       0       0x1          0            
+
+[20]    1       0       0            0x8f949      0x68b7        .comment
+        0       0       0x1          0            
+
+[21]    1       3       0x80a98f4    0x608f4      0x1cf0c       .data
+        0       0       0x4          0            
+
+ * This is an example of how the file header is changed.  "Shoff" is
+ * the section header offset within the file.  Since that table is
+ * after the new .data section, it is moved.  "Shnum" is the number of
+ * sections, which we increment.
+ *
+ * "Phoff" is the file offset to the program header.  "Phentsize" and
+ * "Shentsz" are the program and section header entries sizes respectively.
+ * These can be larger than the apparent struct sizes.
+
+raid:/nfs/raid/src/dist-18.56/src> dump -f temacs
+
+temacs:
+
+                    **** ELF HEADER ****
+Class        Data       Type         Machine     Version
+Entry        Phoff      Shoff        Flags       Ehsize
+Phentsize    Phnum      Shentsz      Shnum       Shstrndx
+
+1            1          2            3           1
+0x80499cc    0x34       0x792f4      0           0x34
+0x20         5          0x28         21          19
+
+raid:/nfs/raid/src/dist-18.56/src> dump -f xemacs
+
+xemacs:
+
+                    **** ELF HEADER ****
+Class        Data       Type         Machine     Version
+Entry        Phoff      Shoff        Flags       Ehsize
+Phentsize    Phnum      Shentsz      Shnum       Shstrndx
+
+1            1          2            3           1
+0x80499cc    0x34       0x96200      0           0x34
+0x20         5          0x28         22          19
+
+ * These are the program headers.  "Offset" is the file offset to the
+ * segment.  "Vaddr" is the memory load address.  "Filesz" is the
+ * segment size as it appears in the file, and "Memsz" is the size in
+ * memory.  Below, the third segment is the code and the fourth is the
+ * data: the difference between Filesz and Memsz is .bss
+
+raid:/nfs/raid/src/dist-18.56/src> dump -o temacs
+
+temacs:
+ ***** PROGRAM EXECUTION HEADER *****
+Type        Offset      Vaddr       Paddr
+Filesz      Memsz       Flags       Align
+
+6           0x34        0x8048034   0           
+0xa0        0xa0        5           0           
+
+3           0xd4        0           0           
+0x13        0           4           0           
+
+1           0x34        0x8048034   0           
+0x3f2f9     0x3f2f9     5           0x1000      
+
+1           0x3f330     0x8088330   0           
+0x215c4     0x25a60     7           0x1000      
+
+2           0x60874     0x80a9874   0           
+0x80        0           7           0           
+
+raid:/nfs/raid/src/dist-18.56/src> dump -o xemacs
+
+xemacs:
+ ***** PROGRAM EXECUTION HEADER *****
+Type        Offset      Vaddr       Paddr
+Filesz      Memsz       Flags       Align
+
+6           0x34        0x8048034   0           
+0xa0        0xa0        5           0           
+
+3           0xd4        0           0           
+0x13        0           4           0           
+
+1           0x34        0x8048034   0           
+0x3f2f9     0x3f2f9     5           0x1000      
+
+1           0x3f330     0x8088330   0           
+0x3e4d0     0x3e4d0     7           0x1000      
+
+2           0x60874     0x80a9874   0           
+0x80        0           7           0           
+
+
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <memory.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <elf.h>
+#include <sys/mman.h>
+
+#ifndef emacs
+#define fatal(a, b, c) fprintf(stderr, a, b, c), exit(1)
+#else
+extern void fatal(char *, ...);
+#endif
+
+/* Get the address of a particular section or program header entry,
+ * accounting for the size of the entries.
+ */
+
+#define OLD_SECTION_H(n) \
+     (*(Elf32_Shdr *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
+#define NEW_SECTION_H(n) \
+     (*(Elf32_Shdr *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))
+#define OLD_PROGRAM_H(n) \
+     (*(Elf32_Phdr *) ((byte *) old_program_h + old_file_h->e_phentsize * (n)))
+#define NEW_PROGRAM_H(n) \
+     (*(Elf32_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
+
+typedef unsigned char byte;
+
+/* ****************************************************************
+ * unexec
+ *
+ * driving logic.
+ *
+ * In ELF, this works by replacing the old .bss section with a new
+ * .data section, and inserting an empty .bss immediately afterwards.
+ *
+ */
+void
+unexec (new_name, old_name, data_start, bss_start, entry_address)
+     char *new_name, *old_name;
+     unsigned data_start, bss_start, entry_address;
+{
+  extern unsigned int bss_end;
+  int new_file, old_file, new_file_size;
+
+  /* Pointers to the base of the image of the two files. */
+  caddr_t old_base, new_base;
+
+  /* Pointers to the file, program and section headers for the old and new
+   * files.
+   */
+  Elf32_Ehdr *old_file_h, *new_file_h;
+  Elf32_Phdr *old_program_h, *new_program_h;
+  Elf32_Shdr *old_section_h, *new_section_h;
+
+  /* Point to the section name table in the old file */
+  char *old_section_names;
+
+  Elf32_Addr old_bss_addr, new_bss_addr;
+  Elf32_Word old_bss_size, new_data2_size;
+  Elf32_Off  new_data2_offset;
+  Elf32_Addr new_data2_addr;
+
+  int n, old_bss_index, old_data_index, new_data2_index;
+  struct stat stat_buf;
+
+  /* Open the old file & map it into the address space. */
+
+  old_file = open (old_name, O_RDONLY);
+
+  if (old_file < 0)
+    fatal ("Can't open %s for reading: errno %d\n", old_name, errno);
+
+  if (fstat (old_file, &stat_buf) == -1)
+    fatal ("Can't fstat(%s): errno %d\n", old_name, errno);
+
+  old_base = mmap (0, stat_buf.st_size, PROT_READ, MAP_SHARED, old_file, 0);
+
+  if (old_base == (caddr_t) -1)
+    fatal ("Can't mmap(%s): errno %d\n", old_name, errno);
+
+#ifdef DEBUG
+  fprintf (stderr, "mmap(%s, %x) -> %x\n", old_name, stat_buf.st_size,
+          old_base);
+#endif
+
+  /* Get pointers to headers & section names */
+
+  old_file_h = (Elf32_Ehdr *) old_base;
+  old_program_h = (Elf32_Phdr *) ((byte *) old_base + old_file_h->e_phoff);
+  old_section_h = (Elf32_Shdr *) ((byte *) old_base + old_file_h->e_shoff);
+  old_section_names = (char *) old_base
+    + OLD_SECTION_H(old_file_h->e_shstrndx).sh_offset;
+
+  /* Find the old .bss section.  Figure out parameters of the new
+   * data2 and bss sections.
+   */
+
+  for (old_bss_index = 1; old_bss_index < old_file_h->e_shnum; old_bss_index++)
+    {
+#ifdef DEBUG
+      fprintf (stderr, "Looking for .bss - found %s\n",
+              old_section_names + OLD_SECTION_H(old_bss_index).sh_name);
+#endif
+      if (!strcmp (old_section_names + OLD_SECTION_H(old_bss_index).sh_name,
+                  ".bss"))
+       break;
+    }
+  if (old_bss_index == old_file_h->e_shnum)
+    fatal ("Can't find .bss in %s.\n", old_name, 0);
+
+  old_bss_addr = OLD_SECTION_H(old_bss_index).sh_addr;
+  old_bss_size = OLD_SECTION_H(old_bss_index).sh_size;
+#if defined(emacs) || !defined(DEBUG)
+  bss_end = (unsigned int) sbrk (0);
+  new_bss_addr = (Elf32_Addr) bss_end;
+#else
+  new_bss_addr = old_bss_addr + old_bss_size + 0x1234;
+#endif
+  new_data2_addr = old_bss_addr;
+  new_data2_size = new_bss_addr - old_bss_addr;
+  new_data2_offset = OLD_SECTION_H(old_bss_index).sh_offset;
+
+#ifdef DEBUG
+  fprintf (stderr, "old_bss_index %d\n", old_bss_index);
+  fprintf (stderr, "old_bss_addr %x\n", old_bss_addr);
+  fprintf (stderr, "old_bss_size %x\n", old_bss_size);
+  fprintf (stderr, "new_bss_addr %x\n", new_bss_addr);
+  fprintf (stderr, "new_data2_addr %x\n", new_data2_addr);
+  fprintf (stderr, "new_data2_size %x\n", new_data2_size);
+  fprintf (stderr, "new_data2_offset %x\n", new_data2_offset);
+#endif
+
+  if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
+    fatal (".bss shrank when undumping???\n", 0, 0);
+
+  /* Set the output file to the right size and mmap(2) it.  Set
+   * pointers to various interesting objects.  stat_buf still has
+   * old_file data.
+   */
+
+  new_file = open (new_name, O_RDWR | O_CREAT, 0666);
+  if (new_file < 0)
+    fatal ("Can't creat(%s): errno %d\n", new_name, errno);
+
+  new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;
+
+  if (ftruncate (new_file, new_file_size))
+    fatal ("Can't ftruncate(%s): errno %d\n", new_name, errno);
+
+  new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+                  new_file, 0);
+
+  if (new_base == (caddr_t) -1)
+    fatal ("Can't mmap(%s): errno %d\n", new_name, errno);
+
+  new_file_h = (Elf32_Ehdr *) new_base;
+  new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff);
+  new_section_h = (Elf32_Shdr *)
+    ((byte *) new_base + old_file_h->e_shoff + new_data2_size);
+
+  /* Make our new file, program and section headers as copies of the
+   * originals.
+   */
+
+  memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
+  memcpy (new_program_h, old_program_h,
+         old_file_h->e_phnum * old_file_h->e_phentsize);
+  memcpy (new_section_h, old_section_h,
+         old_file_h->e_shnum * old_file_h->e_shentsize);
+
+  /* Fix up file header.  We'll add one section.  Section header is
+   * further away now.
+   */
+
+  new_file_h->e_shoff += new_data2_size;
+  new_file_h->e_shnum += 1;
+
+#ifdef DEBUG
+  fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff);
+  fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum);
+  fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff);
+  fprintf (stderr, "New section count %d\n", new_file_h->e_shnum);
+#endif
+
+  /* Fix up a new program header.  Extend the writable data segment so
+   * that the bss area is covered too. Find that segment by looking
+   * for a segment that ends just before the .bss area.  Make sure
+   * that no segments are above the new .data2.  Put a loop at the end
+   * to adjust the offset and address of any segment that is above
+   * data2, just in case we decide to allow this later.
+   */
+
+  for (n = new_file_h->e_phnum - 1; n >= 0; n--)
+    {
+      if (NEW_PROGRAM_H(n).p_vaddr + NEW_PROGRAM_H(n).p_filesz > old_bss_addr)
+       fatal ("Program segment above .bss in %s\n", old_name, 0);
+
+      if (NEW_PROGRAM_H(n).p_type == PT_LOAD
+         && (NEW_PROGRAM_H(n).p_vaddr + NEW_PROGRAM_H(n).p_filesz
+             == old_bss_addr))
+       break;
+    }
+  if (n < 0)
+    fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);
+
+  NEW_PROGRAM_H(n).p_filesz += new_data2_size;
+  NEW_PROGRAM_H(n).p_memsz = NEW_PROGRAM_H(n).p_filesz;
+
+#if 0 /* Maybe allow section after data2 - does this ever happen? */
+  for (n = new_file_h->e_phnum - 1; n >= 0; n--)
+    {
+      if (NEW_PROGRAM_H(n).p_vaddr
+         && NEW_PROGRAM_H(n).p_vaddr >= new_data2_addr)
+       NEW_PROGRAM_H(n).p_vaddr += new_data2_size - old_bss_size;
+
+      if (NEW_PROGRAM_H(n).p_offset >= new_data2_offset)
+       NEW_PROGRAM_H(n).p_offset += new_data2_size;
+    }
+#endif
+
+  /* Fix up section headers based on new .data2 section.  Any section
+   * whose offset or virtual address is after the new .data2 section
+   * gets its value adjusted.  .bss size becomes zero and new address
+   * is set.  data2 section header gets added by copying the existing
+   * .data header and modifying the offset, address and size.
+   */
+
+  for (n = 1; n < new_file_h->e_shnum; n++)
+    {
+      if (NEW_SECTION_H(n).sh_offset >= new_data2_offset)
+       NEW_SECTION_H(n).sh_offset += new_data2_size;
+
+      if (NEW_SECTION_H(n).sh_addr
+         && NEW_SECTION_H(n).sh_addr >= new_data2_addr)
+       NEW_SECTION_H(n).sh_addr += new_data2_size - old_bss_size;
+    }
+
+  new_data2_index = old_file_h->e_shnum;
+
+  for (old_data_index = 1; old_data_index < old_file_h->e_shnum;
+       old_data_index++)
+    if (!strcmp (old_section_names + OLD_SECTION_H(old_data_index).sh_name,
+                ".data"))
+      break;
+  if (old_data_index == old_file_h->e_shnum)
+    fatal ("Can't find .data in %s.\n", old_name, 0);
+
+  memcpy (&NEW_SECTION_H(new_data2_index), &OLD_SECTION_H(old_data_index),
+         new_file_h->e_shentsize);
+
+  NEW_SECTION_H(new_data2_index).sh_addr = new_data2_addr;
+  NEW_SECTION_H(new_data2_index).sh_offset = new_data2_offset;
+  NEW_SECTION_H(new_data2_index).sh_size = new_data2_size;
+
+  NEW_SECTION_H(old_bss_index).sh_size = 0;
+  NEW_SECTION_H(old_bss_index).sh_addr = new_data2_addr + new_data2_size;
+
+  /* Write out the sections. .data and .data1 (and data2, called
+   * ".data" in the strings table) get copied from the current process
+   * instead of the old file.
+   */
+
+  for (n = new_file_h->e_shnum - 1; n; n--)
+    {
+      caddr_t src;
+
+      if (NEW_SECTION_H(n).sh_type == SHT_NULL
+         || NEW_SECTION_H(n).sh_type == SHT_NOBITS)
+       continue;
+
+      if (!strcmp (old_section_names + NEW_SECTION_H(n).sh_name, ".data")
+         || !strcmp ((old_section_names + NEW_SECTION_H(n).sh_name),
+                     ".data1"))
+       src = (caddr_t) NEW_SECTION_H(n).sh_addr;
+      else
+       src = old_base + OLD_SECTION_H(n).sh_offset;
+
+      memcpy (NEW_SECTION_H(n).sh_offset + new_base, src,
+             NEW_SECTION_H(n).sh_size);
+    }
+
+  /* Close the files and make the new file executable */
+
+  if (close (old_file))
+    fatal ("Can't close(%s): errno %d\n", old_name, errno);
+
+  if (close (new_file))
+    fatal ("Can't close(%s): errno %d\n", new_name, errno);
+
+  if (stat (new_name, &stat_buf) == -1)
+    fatal ("Can't stat(%s): errno %d\n", new_name, errno);
+
+  n = umask (777);
+  umask (n);
+  stat_buf.st_mode |= 0111 & ~n;
+  if (chmod (new_name, stat_buf.st_mode) == -1)
+    fatal ("Can't chmod(%s): errno %d\n", new_name, errno);
+}
diff --git a/src/unexenix.c b/src/unexenix.c
new file mode 100644 (file)
index 0000000..ea6cd7d
--- /dev/null
@@ -0,0 +1,262 @@
+/* Unexec for Xenix.
+   Note that the GNU project considers support for Xenix operation
+   a peripheral activity which should not be allowed to divert effort
+   from development of the GNU system.  Changes in this code will be
+   installed when Xenix users send them in, but aside from that
+   we don't plan to think about it, or about whether other Emacs
+   maintenance might break it.
+
+   Copyright (C) 1988 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+\f
+
+/*
+  On 80386 Xenix, segmentation screws prevent us from modifying the text
+  segment at all.  We basically just plug a new value for "data segment
+  size" into the countless headers and copy the other records straight
+  through.  The data segment is ORG'ed at the xs_rbase value of the data
+  segment's xseg record (always @ 0x1880000, thanks to the "sophisticated
+  memory management hardware" of the chip) and extends to sbrk(0), exactly.
+  This code is afraid to malloc (should it be?), and alloca has to be the
+  wimpy, malloc-based version; consequently, data is usually copied in
+  smallish chunks.
+
+  gb@entity.com
+*/
+
+#include "config.h"
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <varargs.h>
+#include <a.out.h>
+
+static void fatal_unexec ();
+
+#define READ(_fd, _buffer, _size, _error_message, _error_arg) \
+       errno = EEOF; \
+       if (read(_fd, _buffer, _size) != _size) \
+         fatal_unexec(_error_message, _error_arg);
+
+#define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \
+       if (write(_fd, _buffer, _size) != _size) \
+         fatal_unexec(_error_message, _error_arg);
+
+#define SEEK(_fd, _position, _error_message, _error_arg) \
+       errno = EEOF; \
+       if (lseek(_fd, _position, L_SET) != _position) \
+         fatal_unexec(_error_message, _error_arg);
+
+extern int errno;
+extern int sys_nerr;
+extern char *sys_errlist[];
+#define EEOF -1
+
+#ifndef L_SET
+#define L_SET 0
+#endif
+\f
+/* Should check the magic number of the old executable;
+   not yet written.  */
+check_exec (x)
+     struct xexec *x;
+{
+}
+
+
+unexec (new_name, a_name, data_start, bss_start, entry_address)
+     char *new_name, *a_name;
+     unsigned data_start, bss_start, entry_address;
+{
+  char *sbrk (), *datalim = sbrk (0), *data_org;
+  long segpos, textseen, textpos, textlen, datapos, datadiff, datalen;
+
+  struct xexec u_xexec,       /*  a.out header */
+              *u_xexecp = &u_xexec;
+  struct xext  u_xext,        /*  extended header */
+              *u_xextp  = &u_xext;
+  struct xseg  u_xseg,        /*  segment table entry */
+              *u_xsegp  = &u_xseg;
+  int i, nsegs, isdata = 0, infd, outfd;
+
+  infd = open (a_name, O_RDONLY, 0);
+  if (infd < 0) fatal_unexec ("opening %s", a_name);
+
+  outfd = creat (new_name, 0666);
+  if (outfd < 0) fatal_unexec ("creating %s", new_name);
+
+  READ (infd, u_xexecp, sizeof (struct xexec),
+       "error reading %s", a_name);
+  check_exec (u_xexecp);
+  READ (infd, u_xextp, sizeof (struct xext),
+       "error reading %s", a_name);
+  segpos = u_xextp->xe_segpos;
+  nsegs = u_xextp->xe_segsize / sizeof (struct xseg);
+  SEEK (infd, segpos, "seek error on %s", a_name);
+  for (i = 0; i < nsegs; i ++)
+    {
+      READ (infd, u_xsegp, sizeof (struct xseg),
+           "error reading %s", a_name);
+      switch (u_xsegp->xs_type)
+       {
+       case XS_TTEXT:
+         {
+           if (i == 0)
+             {
+               textpos = u_xsegp->xs_filpos;
+               textlen = u_xsegp->xs_psize;
+               break;
+             }
+           fatal_unexec ("invalid text segment in %s", a_name);
+         }
+       case XS_TDATA:
+         {
+           if (i == 1)
+             {
+               datapos = u_xsegp->xs_filpos;
+               datalen = datalim - (data_org = (char *)(u_xsegp->xs_rbase));
+               datadiff = datalen - u_xsegp->xs_psize;
+               break;
+             }
+           fatal_unexec ("invalid data segment in %s", a_name);
+         }
+       default:
+         {
+           if (i > 1) break;
+           fatal_unexec ("invalid segment record in %s", a_name);
+         }
+       }
+    }
+  u_xexecp->x_data = datalen;
+  u_xexecp->x_bss = 0;
+  WRITE (outfd, u_xexecp, sizeof (struct xexec),
+        "error writing %s", new_name);
+  WRITE (outfd, u_xextp, sizeof (struct xext),
+        "error writing %s", new_name);
+  SEEK (infd, segpos, "seek error on %s", a_name);
+  SEEK (outfd, segpos, "seek error on %s", new_name);
+
+  /* Copy the text segment record verbatim. */
+
+  copyrec (infd, outfd, sizeof (struct xseg), a_name, new_name);
+
+  /* Read, modify, write the data segment record. */
+
+  READ (infd, u_xsegp, sizeof (struct xseg),
+       "error reading %s", a_name);
+  u_xsegp->xs_psize = u_xsegp->xs_vsize = datalen;
+  u_xsegp->xs_attr &= (~XS_AITER & ~XS_ABSS);
+  WRITE (outfd, u_xsegp, sizeof (struct xseg),
+        "error writing %s", new_name);
+
+  /* Now copy any additional segment records, adjusting their
+     file position field */
+
+  for (i = 2; i < nsegs; i++)
+    {
+      READ (infd, u_xsegp, sizeof (struct xseg),
+           "error reading %s", a_name);
+      u_xsegp->xs_filpos += datadiff;
+      WRITE (outfd, u_xsegp, sizeof (struct xseg),
+            "error writing %s", new_name);
+    }
+
+  SEEK (infd, textpos, "seek error on %s", a_name);
+  SEEK (outfd, textpos, "seek error on %s", new_name);
+  copyrec (infd, outfd, textlen, a_name, new_name);
+
+  SEEK (outfd, datapos, "seek error on %s", new_name);
+  WRITE (outfd, data_org, datalen,
+        "write error on %s", new_name);
+
+  for (i = 2, segpos += (2 * sizeof (struct xseg)); 
+       i < nsegs;
+       i++, segpos += sizeof (struct xseg))
+    {
+      SEEK (infd, segpos, "seek error on %s", a_name);
+      READ (infd, u_xsegp, sizeof (struct xseg),
+           "read error on %s", a_name);
+      SEEK (infd, u_xsegp->xs_filpos, "seek error on %s", a_name);
+      /* We should be at eof in the output file here, but we must seek
+         because the xs_filpos and xs_psize fields in symbol table
+        segments are inconsistent. */
+      SEEK (outfd, u_xsegp->xs_filpos + datadiff, "seek error on %s", new_name);
+      copyrec (infd, outfd, u_xsegp->xs_psize, a_name, new_name);
+    }
+  close (infd);
+  close (outfd);
+  mark_x (new_name);
+  return 0;
+}
+
+copyrec (infd, outfd, len, in_name, out_name)
+     int infd, outfd, len;
+     char *in_name, *out_name;
+{
+  char buf[BUFSIZ];
+  int chunk;
+
+  while (len)
+    {
+      chunk = BUFSIZ;
+      if (chunk > len)
+       chunk = len;
+      READ (infd, buf, chunk, "error reading %s", in_name);
+      WRITE (outfd, buf, chunk, "error writing %s", out_name);
+      len -= chunk;
+    }
+}
+
+/*
+ * mark_x
+ *
+ * After succesfully building the new a.out, mark it executable
+ */
+static
+mark_x (name)
+     char *name;
+{
+  struct stat sbuf;
+  int um = umask (777);
+  umask (um);
+  if (stat (name, &sbuf) < 0)
+    fatal_unexec ("getting protection on %s", name);
+  sbuf.st_mode |= 0111 & ~um;
+  if (chmod (name, sbuf.st_mode) < 0)
+    fatal_unexec ("setting protection on %s", name);
+}
+
+static void
+fatal_unexec (s, va_alist)
+    va_dcl
+{
+  va_list ap;
+  if (errno == EEOF)
+    fputs ("unexec: unexpected end of file, ", stderr);
+  else if (errno < sys_nerr)
+    fprintf (stderr, "unexec: %s, ", sys_errlist[errno]);
+  else
+    fprintf (stderr, "unexec: error code %d, ", errno);
+  va_start (ap);
+  _doprnt (s, ap, stderr);
+  fputs (".\n", stderr);
+  exit (1);
+}
index 259b931..8d34a3a 100644 (file)
@@ -60,6 +60,7 @@ unexec(new_name, old_name, new_end_of_text, dummy1, dummy2)
   int old_size, new_size;
   struct header hdr;
   struct som_exec_auxhdr auxhdr;
+  long i;
   
   /* For the greatest flexibility, should create a temporary file in
      the same directory as the new file.  When everything is complete,
@@ -81,7 +82,10 @@ unexec(new_name, old_name, new_end_of_text, dummy1, dummy2)
   
   /* Decide how large the new and old data areas are */
   old_size = auxhdr.exec_dsize;
-  new_size = sbrk(0) - auxhdr.exec_dmem;
+  /* I suspect these two statements are separate
+     to avoid a compiler bug in hpux version 8.  */
+  i = sbrk (0);
+  new_size = i - auxhdr.exec_dmem;
   
   /* Copy the old file to the new, up to the data space */
   lseek(old, 0, 0);
diff --git a/src/vlimit.h b/src/vlimit.h
new file mode 100644 (file)
index 0000000..c347dc7
--- /dev/null
@@ -0,0 +1,2 @@
+/* Dummy for Emacs so that we can run on VMS... */
+#define LIM_DATA 0
index fdfcd9c..2ff47d1 100644 (file)
@@ -16,7 +16,7 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
  *
  * Usage:
diff --git a/src/vms-pwd.h b/src/vms-pwd.h
new file mode 100644 (file)
index 0000000..6c29197
--- /dev/null
@@ -0,0 +1,34 @@
+/* GNU Emacs password definition file.
+   Copyright (C) 1986 Free Software Foundation.
+
+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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifdef VMS
+/* On VMS, we read the UAF file and emulate some of the necessary
+   fields for Emacs. */
+#include "uaf.h"
+
+struct passwd {
+  char pw_name[UAF$S_USERNAME+1];
+  char pw_passwd[UAF$S_PWD];
+  short pw_uid;
+  short pw_gid;
+  char pw_gecos[UAF$S_OWNER+1];
+  char pw_dir[UAF$S_DEFDEV+UAF$S_DEFDIR+1];
+  char pw_shell[UAF$S_DEFCLI+1];
+};
+#endif /* VMS */
diff --git a/src/vmsdir.h b/src/vmsdir.h
new file mode 100644 (file)
index 0000000..7ea632d
--- /dev/null
@@ -0,0 +1,97 @@
+/* GNU Emacs VMS directory definition file.
+   Copyright (C) 1986 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * Files-11 Ver. 2 directory structure (VMS V4.x - long names)
+ */
+#ifndef DIR$K_LENGTH
+
+#define        DIR$C_FID       0
+#define        DIR$C_LINKNAME  1
+#define        DIR$K_LENGTH    6
+#define        DIR$C_LENGTH    6
+#define        DIR$S_DIRDEF    6
+#define        DIR$W_SIZE      0
+#define        DIR$W_VERLIMIT  2
+#define        DIR$B_FLAGS     4
+#define        DIR$S_TYPE      3
+#define        DIR$V_TYPE      0
+#define        DIR$V_NEXTREC   6
+#define        DIR$V_PREVREC   7
+#define        DIR$B_NAMECOUNT 5
+#define        DIR$S_NAME      80
+#define        DIR$T_NAME      6
+
+#define        DIR$K_VERSION   8
+#define        DIR$C_VERSION   8
+#define        DIR$S_DIRDEF1   8
+#define        DIR$W_VERSION   0
+#define        DIR$S_FID       6
+#define        DIR$W_FID       2
+#define        DIR$W_FID_NUM   2
+#define        DIR$W_FID_SEQ   4
+#define        DIR$W_FID_RVN   6
+#define        DIR$B_FID_RVN   6
+#define        DIR$B_FID_NMX   7
+
+#define        DIR$S_DIRDEF2   1
+#define        DIR$T_LINKNAME  0
+
+typedef struct dir$_name {
+/*  short dir$w_size;          /* if you read with RMS, it eats this... */
+  short dir$w_verlimit;                        /* maximum number of versions */
+  union {
+    unsigned char dir_b_flags;
+#define dir$b_flags dir__b_flags.dir_b_flags
+    struct {
+      unsigned char dir_v_type: DIR$S_TYPE;
+#define dir$v_type dir__b_flags.dir___b_flags.dir_v_type
+      unsigned char: 3;
+      unsigned char dir_v_nextrec: 1;
+#define dir$v_nextrec dir__b_flags.dir___b_flags.dir_v_nextrec
+      unsigned char dir_v_prevrec: 1;
+#define dir$v_prevrec dir__b_flags.dir___b_flags.dir_v_prevrec
+    } dir___b_flags;
+  } dir__b_flags;
+  unsigned char dir$b_namecount;
+  char dir$t_name[];
+} dir$_dirdef;         /* only the fixed first part */
+
+typedef struct dir$_version {
+  short dir$w_version;
+  short dir$w_fid_num;
+  short dir$w_fid_seq;
+  union {
+    short dir_w_fid_rvn;
+#define dir$w_fid_rvn dir__w_fid_rvn.dir_w_fid_rvn
+    struct {
+      char dir_b_fid_rvn;
+#define dir$b_fid_rvn dir__w_fid_rvn.dir___w_fid_rvn.dir_b_fid_rvn
+      char dir_b_fid_nmx;
+#define dir$b_fid_nmx dir__w_fid_rvn.dir___w_fid_rvn.dir_b_fid_nmx
+    } dir___w_fid_rvn;
+  } dir__w_fid_rvn;
+} dir$_dirdef1;                /* one for each version of the file */
+
+typedef
+struct dir$_linkname {
+  char    dir$t_linkname[];
+} dir$_dirdef2;
+
+#endif
index 512ab21..0885fb6 100644 (file)
@@ -310,7 +310,7 @@ DEFUN ("spawn-subprocess", Fspawn_subprocess, Sspawn_subprocess, 1, 3, 0,
            prev->next = next;
          else
            process_list = next;
-         if (! NULL (ptr->exit_handler))
+         if (! NILP (ptr->exit_handler))
            Feval (Fcons (ptr->exit_handler, Fcons (make_number (ptr->name),
                                                    Qnil)));
          sys$dassgn (ptr->mbx_chan);
@@ -327,7 +327,7 @@ DEFUN ("spawn-subprocess", Fspawn_subprocess, Sspawn_subprocess, 1, 3, 0,
       free (ptr);
       return Qnil;
     }
-  if (NULL (input_handler))
+  if (NILP (input_handler))
     input_handler = Qdefault_subproc_input_handler;
   ptr->input_handler = input_handler;
   ptr->exit_handler = exit_handler;
@@ -447,7 +447,7 @@ process_command_input ()
   have_process_input = 0;
   start_mbx_input ();
   clear_waiting_for_input ();    /* Otherwise Ctl-g will cause crash. JCB */
-  if (! NULL (expr))
+  if (! NILP (expr))
     Feval (expr);
 }
 
@@ -471,7 +471,7 @@ process_exit ()
            prev->next = next;
          else
            process_list = next;
-         if (! NULL (ptr->exit_handler))
+         if (! NILP (ptr->exit_handler))
            Feval (Fcons (ptr->exit_handler, Fcons (make_number (ptr->name),
                                                    Qnil)));
          sys$dassgn (ptr->mbx_chan);
@@ -605,9 +605,9 @@ or nil depending upon whether the privilege is already enabled.")
     }
   if (! found)
     error ("Unknown privilege name %s", XSTRING (priv)->data);
-  if (NULL (getprv))
+  if (NILP (getprv))
     {
-      if (sys$setprv (NULL (value) ? 0 : 1, prvmask, 0, 0) == SS$_NORMAL)
+      if (sys$setprv (NILP (value) ? 0 : 1, prvmask, 0, 0) == SS$_NORMAL)
        return Qt;
       return Qnil;
     }
@@ -679,7 +679,7 @@ translate_id (pid, owner)
   char * p;
   int prcnam[2];
 
-  if (NULL (pid)
+  if (NILP (pid)
       || XTYPE (pid) == Lisp_String && XSTRING (pid)->size == 0
       || XTYPE (pid) == Lisp_Int && XFASTINT (pid) == 0)
     {
diff --git a/src/vmsmap.c b/src/vmsmap.c
new file mode 100644 (file)
index 0000000..aa13530
--- /dev/null
@@ -0,0 +1,224 @@
+/* VMS mapping of data and alloc arena for GNU Emacs.
+   Copyright (C) 1986, 1987 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Written by Mukesh Prasad.  */
+
+#ifdef VMS
+
+#include "config.h"
+#include "lisp.h"
+#include <rab.h>
+#include <fab.h>
+#include <rmsdef.h>
+#include <secdef.h>
+
+/* RMS block size */
+#define        BLOCKSIZE       512
+
+/* Maximum number of bytes to be written in one RMS write.
+ * Must be a multiple of BLOCKSIZE.
+ */
+#define        MAXWRITE        (BLOCKSIZE * 30)
+
+/* This funniness is to ensure that sdata occurs alphabetically BEFORE the
+   $DATA psect and that edata occurs after ALL Emacs psects.  This is
+   because the VMS linker sorts all psects in a cluster alphabetically
+   during the linking, unless you use the cluster_psect command.  Emacs
+   uses the cluster command to group all Emacs psects into one cluster;
+   this keeps the dumped data separate from any loaded libraries. */
+
+globaldef {"$D$ATA"} char sdata[512]; /* Start of saved data area */
+globaldef {"__DATA"} char edata[512]; /* End of saved data area */
+
+/* Structure to write into first block of map file.
+ */
+
+struct map_data
+{
+  char * sdata;                        /* Start of data area */
+  char * edata;                        /* End of data area */
+  int  datablk;                        /* Block in file to map data area from/to */
+};
+
+static void fill_fab (), fill_rab ();
+static int write_data ();
+
+extern char *start_of_data ();
+extern int vms_out_initial;    /* Defined in malloc.c */
+
+/* Maps in the data and alloc area from the map file.
+ */
+
+int
+mapin_data (name)
+     char * name;
+{
+  struct FAB fab;
+  struct RAB rab;
+  int status, size;
+  int inadr[2];
+  struct map_data map_data;
+  
+  /* Open map file. */
+  fab = cc$rms_fab;
+  fab.fab$b_fac = FAB$M_BIO|FAB$M_GET;
+  fab.fab$l_fna = name;
+  fab.fab$b_fns = strlen (name);
+  status = sys$open (&fab);
+  if (status != RMS$_NORMAL)
+    {
+      printf ("Map file not available, running bare Emacs....\n");
+      return 0;                        /* Map file not available */
+    }
+  /* Connect the RAB block */
+  rab = cc$rms_rab;
+  rab.rab$l_fab = &fab;
+  rab.rab$b_rac = RAB$C_SEQ;
+  rab.rab$l_rop = RAB$M_BIO;
+  status = sys$connect (&rab);
+  if (status != RMS$_NORMAL)
+    lib$stop (status);
+  /* Read the header data */
+  rab.rab$l_ubf = &map_data;
+  rab.rab$w_usz = sizeof (map_data);
+  rab.rab$l_bkt = 0;
+  status = sys$read (&rab);
+  if (status != RMS$_NORMAL)
+    lib$stop (status);
+  status = sys$close (&fab);
+  if (status != RMS$_NORMAL)
+    lib$stop (status);
+  if (map_data.sdata != start_of_data ())
+    {
+      printf ("Start of data area has moved: cannot map in data.\n");
+      return 0;
+    }
+  if (map_data.edata != edata)
+    {
+      printf ("End of data area has moved: cannot map in data.\n");
+      return 0;
+    }
+  fab.fab$l_fop |= FAB$M_UFO;
+  status = sys$open (&fab);
+  if (status != RMS$_NORMAL)
+    lib$stop (status);
+  /* Map data area. */
+  inadr[0] = map_data.sdata;
+  inadr[1] = map_data.edata;
+  status = sys$crmpsc (inadr, 0, 0, SEC$M_CRF | SEC$M_WRT, 0, 0, 0,
+                      fab.fab$l_stv, 0, map_data.datablk, 0, 0);
+  if (! (status & 1))
+    lib$stop (status);
+}
+
+/* Writes the data and alloc area to the map file.
+ */
+mapout_data (into)
+     char * into;
+{
+  struct FAB fab;
+  struct RAB rab;
+  int status;
+  struct map_data map_data;
+  int datasize, msize;
+  if (vms_out_initial)
+    {
+      error ("Out of initial allocation. Must rebuild emacs with more memory (VMS_ALLOCATION_SIZE).");
+      return 0;
+    }
+  map_data.sdata = start_of_data ();
+  map_data.edata = edata;
+  datasize = map_data.edata - map_data.sdata + 1;
+  map_data.datablk = 2 + (sizeof (map_data) + BLOCKSIZE - 1) / BLOCKSIZE;
+  /* Create map file. */
+  fab = cc$rms_fab;
+  fab.fab$b_fac = FAB$M_BIO|FAB$M_PUT;
+  fab.fab$l_fna = into;
+  fab.fab$b_fns = strlen (into);
+  fab.fab$l_fop = FAB$M_CBT;
+  fab.fab$b_org = FAB$C_SEQ;
+  fab.fab$b_rat = 0;
+  fab.fab$b_rfm = FAB$C_VAR;
+  fab.fab$l_alq = 1 + map_data.datablk +
+                     ((datasize + BLOCKSIZE - 1) / BLOCKSIZE);
+  status = sys$create (&fab);
+  if (status != RMS$_NORMAL)
+    {
+      error ("Could not create map file");
+      return 0;
+    }
+  /* Connect the RAB block */
+  rab = cc$rms_rab;
+  rab.rab$l_fab = &fab;
+  rab.rab$b_rac = RAB$C_SEQ;
+  rab.rab$l_rop = RAB$M_BIO;
+  status = sys$connect (&rab);
+  if (status != RMS$_NORMAL)
+    {
+      error ("RMS connect to map file failed");
+      return 0;
+    }
+  /* Write the header */
+  rab.rab$l_rbf = &map_data;
+  rab.rab$w_rsz = sizeof (map_data);
+  status = sys$write (&rab);
+  if (status != RMS$_NORMAL)
+    {
+      error ("RMS write (header) to map file failed");
+      return 0;
+    }
+  if (! write_data (&rab, map_data.datablk, map_data.sdata, datasize))
+    return 0;
+  status = sys$close (&fab);
+  if (status != RMS$_NORMAL)
+    {
+      error ("RMS close on map file failed");
+      return 0;
+    }
+  return 1;
+}
+
+static int
+write_data (rab, firstblock, data, length)
+     struct RAB * rab;
+     char * data;
+{
+  int status;
+  
+  rab->rab$l_bkt = firstblock;
+  while (length > 0)
+    {
+      rab->rab$l_rbf = data;
+      rab->rab$w_rsz = length > MAXWRITE ? MAXWRITE : length;
+      status = sys$write (rab, 0, 0);
+      if (status != RMS$_NORMAL)
+       {
+         error ("RMS write to map file failed");
+         return 0;
+       }
+      data = &data[MAXWRITE];
+      length -= MAXWRITE;
+      rab->rab$l_bkt = 0;
+    }
+  return 1;
+}                              /* write_data */
+
+#endif /* VMS */
+
diff --git a/src/vmspaths.h b/src/vmspaths.h
new file mode 100644 (file)
index 0000000..ac16c07
--- /dev/null
@@ -0,0 +1,15 @@
+/* the default search path for Lisp function "load" */
+#define PATH_LOADSEARCH "EMACS_LIBRARY:[LISP]"
+
+/* the extra search path for programs to invoke.
+  This is appended to whatever the PATH environment variable says. */
+#define PATH_EXEC "EMACS_LIBRARY:[ETC]"
+
+/* the name of the directory that contains lock files
+  with which we record what files are being modified in Emacs.
+  This directory should be writable by everyone.  */
+#define PATH_LOCK "EMACS_LIBRARY:[LOCK]"
+
+/* the name of the file !!!SuperLock!!! in the directory
+  specified by PATH_LOCK.  Yes, this is redundant.  */
+#define PATH_SUPERLOCK "EMACS_LIBRARY:[LOCK]$$$SUPERLOCK$$$."
index ec9678f..fff0aec 100644 (file)
@@ -437,7 +437,7 @@ if you quit, the process is killed.")
 
   CHECK_STRING (args[0], 0);
 
-  if (nargs <= 1 || NULL (args[1]))
+  if (nargs <= 1 || NILP (args[1]))
     args[1] = build_string ("NLA0:");
   else
     args[1] = Fexpand_file_name (args[1], current_buffer->directory);
@@ -589,12 +589,12 @@ if you quit, the process is killed.")
       if (vs->iosb[0] & 1)
        {
          immediate_quit = 0;
-         if (!NULL (buffer))
+         if (!NILP (buffer))
            {
              vs->iosb[1] = clean_vms_buffer (vs->inputBuffer, vs->iosb[1]);
              InsCStr (vs->inputBuffer, vs->iosb[1]);
            }
-         if (!NULL (display) && INTERACTIVE)
+         if (!NILP (display) && INTERACTIVE)
          redisplay_preserve_echo_area ();
          immediate_quit = 1;
          QUIT;
diff --git a/src/vmsproc.h b/src/vmsproc.h
new file mode 100644 (file)
index 0000000..f6faddf
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+    Structure for storing VMS specific information for an EMACS process
+
+    We use the event flags 1-23 for processes, keyboard input and timer
+*/
+
+/*
+    Same as MAXDESC in process.c
+*/
+#define        MAX_EVENT_FLAGS         23
+
+typedef  struct {
+    char       inputBuffer[1024];
+    short      inputChan;
+    short      outputChan;
+    short      busy;
+    int                pid;
+    int                eventFlag;
+    int                exitStatus;
+    short       iosb[4];
+} VMS_PROC_STUFF;
diff --git a/src/xscrollbar.h b/src/xscrollbar.h
new file mode 100644 (file)
index 0000000..e1a3f45
--- /dev/null
@@ -0,0 +1,123 @@
+/* Bitmaps and things for scrollbars.
+   Copyright (C) 1989 Free Software Foundation.
+
+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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+static void install_vertical_scrollbar ();
+static void install_horizontal_scrollbar ();
+static void x_set_horizontal_scrollbar ();
+static void x_set_vertical_scrollbar ();
+
+/* Prefix-characters for scroll bar commands in Vglobal_mouse_map.
+   Choice of prefix depends on which region of the scroll bar.  */
+
+enum scroll_bar_prefix
+  { VSCROLL_BAR_PREFIX = 050, VSCROLL_SLIDER_PREFIX /* unused */,
+    VSCROLL_THUMBUP_PREFIX, VSCROLL_THUMBDOWN_PREFIX,
+    HSCROLL_BAR_PREFIX, HSCROLL_SLIDER_PREFIX /* unused */,
+    HSCROLL_THUMBLEFT_PREFIX, HSCROLL_THUMBRIGHT_PREFIX };
+
+#define CROSS_WIDTH 16
+#define CROSS_HEIGHT 16
+
+#define CROSS_MASK_WIDTH 16
+#define CROSS_MASK_HEIGHT 16
+
+/* Vertical and Horizontal scroll bar widths. */
+#define VSCROLL_WIDTH 18
+#define HSCROLL_HEIGHT 18
+
+#ifdef HAVE_X11
+
+/* Arrow cursors for scroll bars.  */
+
+Cursor up_arrow_cursor, down_arrow_cursor, v_double_arrow_cursor;
+Cursor left_arrow_cursor, right_arrow_cursor, h_double_arrow_cursor;
+
+static char cross_bits[] =
+ {
+   0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
+   0x80, 0x01, 0xfe, 0x7f, 0xfe, 0x7f, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
+   0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00
+ };
+
+static char gray_bits[] =
+ {
+   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
+   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
+   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
+   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa
+ };
+
+static char up_arrow_bits[] =
+  {
+    0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf8, 0x1f,
+    0xfc, 0x3f, 0xfe, 0x7f, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
+    0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xff, 0xff
+  };
+
+static char down_arrow_bits[] =
+  {
+    0xff, 0xff, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
+    0x80, 0x01, 0x80, 0x01, 0xfe, 0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xf0, 0x0f,
+    0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00
+  };
+
+static char left_arrow_bits[] =
+  {
+    0x00, 0x80, 0x80, 0x80, 0xc0, 0x80, 0xe0, 0x80, 0xf0, 0x80, 0xf8, 0x80,
+    0xfc, 0x80, 0xfe, 0xff, 0xfe, 0xff, 0xfc, 0x80, 0xf8, 0x80, 0xf0, 0x80,
+    0xe0, 0x80, 0xc0, 0x80, 0x80, 0x80, 0x00, 0x80
+  };
+
+static char right_arrow_bits[] =
+  {
+    0x01, 0x00, 0x01, 0x01, 0x01, 0x03, 0x01, 0x07, 0x01, 0x0f, 0x01, 0x1f,
+    0x01, 0x3f, 0xff, 0x7f, 0xff, 0x7f, 0x01, 0x3f, 0x01, 0x1f, 0x01, 0x0f,
+    0x01, 0x07, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00
+  };
+
+static char cross_mask_bits[] =
+ {
+   0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xc0, 0x03,
+   0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03
+ };
+#else /* not HAVE_X11 */
+static short cross_bits[] =
+  {
+    0x0000, 0x0180, 0x0180, 0x0180,
+    0x0180, 0x0180, 0x0180, 0x7ffe,
+    0x7ffe, 0x0180, 0x0180, 0x0180,
+    0x0180, 0x0180, 0x0180, 0x0000,
+  };
+
+static short gray_bits[] = {
+    0xaaaa, 0x5555, 0xaaaa, 0x5555,
+    0xaaaa, 0x5555, 0xaaaa, 0x5555,
+    0xaaaa, 0x5555, 0xaaaa, 0x5555,
+    0xaaaa, 0x5555, 0xaaaa, 0x5555};
+
+static short cross_mask_bits[] =
+  {
+    0x03c0, 0x03c0, 0x03c0, 0x03c0,
+    0x03c0, 0x03c0, 0xffff, 0xffff,
+    0xffff, 0xffff, 0x03c0, 0x03c0,
+    0x03c0, 0x03c0, 0x03c0, 0x03c0,
+  };
+#endif /* X10 */