Mercurial > emacs
changeset 484:3165b2697c78
entered into RCS
author | Jim Blandy <jimb@redhat.com> |
---|---|
date | Mon, 13 Jan 1992 21:48:03 +0000 |
parents | 00f564a647fa |
children | 8c615e453683 |
files | src/=XTests.c src/=XTests.h src/=xscrollbar.h src/abbrev.c src/acldef.h src/casefiddle.c src/casetab.c src/chpdef.h src/cm.c src/disptab.h src/doprnt.c src/indent.h src/insdel.c src/ioctl.h src/lastfile.c src/line.h src/macros.h src/marker.c src/mocklisp.c src/mocklisp.h src/ndir.h src/param.h src/point.h src/pre-crt0.c src/puresize.h src/sink.h src/sink11.h src/sink11mask.h src/terminfo.c src/uaf.h src/unexconvex.c src/unexelf.c src/unexenix.c src/unexhp9k800.c src/vlimit.h src/vms-pp.c src/vms-pwd.h src/vmsdir.h src/vmsfns.c src/vmsmap.c src/vmspaths.h src/vmsproc.c src/vmsproc.h |
diffstat | 43 files changed, 3193 insertions(+), 104 deletions(-) [+] |
line wrap: on
line diff
--- a/src/=XTests.c Mon Jan 13 06:37:58 1992 +0000 +++ b/src/=XTests.c Mon Jan 13 21:48:03 1992 +0000 @@ -67,8 +67,8 @@ 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 @@ &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 @@ 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; + switch (event.xbutton.button) + { + case Button1: + XDrawLine (dpy, window, line_xor_gc, 25, 75, 300, 75); + break; - case Button2: - XDrawLine (dpy, window, line_xor_gc, 25, 75, 125, 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, 75, 125, 75); - break; - } + case Button3: + XDrawLine (dpy, window, line_xor_gc, 25, 25, 25, 125); + break; + } break; case KeyPress:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/=XTests.h Mon Jan 13 21:48:03 1992 +0000 @@ -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};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/=xscrollbar.h Mon Jan 13 21:48:03 1992 +0000 @@ -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 */
--- a/src/abbrev.c Mon Jan 13 06:37:58 1992 +0000 +++ b/src/abbrev.c Mon Jan 13 21:48:03 1992 +0000 @@ -20,7 +20,6 @@ #include "config.h" #include <stdio.h> -#undef NULL #include "lisp.h" #include "commands.h" #include "buffer.h" @@ -113,9 +112,9 @@ 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 @@ 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 @@ (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 @@ { 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 @@ { Lisp_Object sym; sym = Fabbrev_symbol (abbrev, table); - if (NULL (sym)) return sym; + if (NILP (sym)) return sym; return Fsymbol_value (sym); } @@ -221,12 +220,12 @@ 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 @@ 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 @@ } hook = XSYMBOL (sym)->function; - if (!NULL (hook)) + if (!NILP (hook)) call0 (hook); return Qt; @@ -367,7 +366,7 @@ 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 @@ { 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 @@ 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 @@ XSET (stream, Lisp_Buffer, current_buffer); - if (!NULL (readable)) + if (!NILP (readable)) { insert_string ("("); Fprin1 (name, stream); @@ -457,7 +456,7 @@ 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 @@ } CHECK_VECTOR (table, 0); - for (;!NULL (defns); defns = Fcdr (defns)) + for (;!NILP (defns); defns = Fcdr (defns)) { elt = Fcar (defns); name = Fcar (elt);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/acldef.h Mon Jan 13 21:48:03 1992 +0000 @@ -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
--- a/src/casefiddle.c Mon Jan 13 06:37:58 1992 +0000 +++ b/src/casefiddle.c Mon Jan 13 21:48:03 1992 +0000 @@ -261,7 +261,10 @@ 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");
--- a/src/casetab.c Mon Jan 13 06:37:58 1992 +0000 +++ b/src/casetab.c Mon Jan 13 21:48:03 1992 +0000 @@ -45,8 +45,8 @@ (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 @@ { 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 @@ 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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/chpdef.h Mon Jan 13 21:48:03 1992 +0000 @@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cm.c Mon Jan 13 21:48:03 1992 +0000 @@ -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; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/disptab.h Mon Jan 13 21:48:03 1992 +0000 @@ -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 ();
--- a/src/doprnt.c Mon Jan 13 06:37:58 1992 +0000 +++ b/src/doprnt.c Mon Jan 13 21:48:03 1992 +0000 @@ -68,10 +68,10 @@ 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 != ' ')
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/indent.h Mon Jan 13 21:48:03 1992 +0000 @@ -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;
--- a/src/insdel.c Mon Jan 13 06:37:58 1992 +0000 +++ b/src/insdel.c Mon Jan 13 21:48:03 1992 +0000 @@ -214,7 +214,7 @@ marker = current_buffer->markers; - while (!NULL (marker)) + while (!NILP (marker)) { m = XMARKER (marker); mpos = m->bufpos; @@ -352,7 +352,7 @@ GPT += length; ZV += length; Z += length; - point += length; + SET_PT (point + length); signal_after_change (point-length, 0, length); } @@ -473,22 +473,22 @@ 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 @@ { /* 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_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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ioctl.h Mon Jan 13 21:48:03 1992 +0000 @@ -0,0 +1,1 @@ +/* Emacs ioctl emulation for VMS */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lastfile.c Mon Jan 13 21:48:03 1992 +0000 @@ -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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/line.h Mon Jan 13 21:48:03 1992 +0000 @@ -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};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/macros.h Mon Jan 13 21:48:03 1992 +0000 @@ -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;
--- a/src/marker.c Mon Jan 13 06:37:58 1992 +0000 +++ b/src/marker.c Mon Jan 13 21:48:03 1992 +0000 @@ -36,7 +36,7 @@ { 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 @@ 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 @@ } CHECK_NUMBER_COERCE_MARKER (pos, 1); - if (NULL (buffer)) + if (NILP (buffer)) b = current_buffer; else { @@ -144,7 +144,7 @@ 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 @@ } CHECK_NUMBER_COERCE_MARKER (pos, 1); - if (NULL (buffer)) + if (NILP (buffer)) b = current_buffer; else { @@ -215,7 +215,7 @@ if (XMARKER (marker) == XMARKER (tail)) { - if (NULL (prev)) + if (NILP (prev)) { b->markers = next; /* Deleting first marker from the buffer's chain.
--- a/src/mocklisp.c Mon Jan 13 06:37:58 1992 +0000 +++ b/src/mocklisp.c Mon Jan 13 21:48:03 1992 +0000 @@ -32,7 +32,7 @@ * { * Lisp_Object elt; * -* while (!NULL (args)) +* while (!NILP (args)) * { * elt = Fcar (args); * Ffset (Fcar (elt), Fcons (Qmocklisp, Fcdr (elt))); @@ -50,11 +50,11 @@ 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 @@ 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 {
--- a/src/mocklisp.h Mon Jan 13 06:37:58 1992 +0000 +++ b/src/mocklisp.h Mon Jan 13 21:48:03 1992 +0000 @@ -28,4 +28,4 @@ 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 ();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ndir.h Mon Jan 13 21:48:03 1992 +0000 @@ -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 )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/param.h Mon Jan 13 21:48:03 1992 +0000 @@ -0,0 +1,2 @@ +/* This is so that Emacs can run on VMS... */ +#define EXEC_PAGESIZE 512
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/point.h Mon Jan 13 21:48:03 1992 +0000 @@ -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};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pre-crt0.c Mon Jan 13 21:48:03 1992 +0000 @@ -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;
--- a/src/puresize.h Mon Jan 13 06:37:58 1992 +0000 +++ b/src/puresize.h Mon Jan 13 21:48:03 1992 +0000 @@ -21,9 +21,19 @@ 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sink.h Mon Jan 13 21:48:03 1992 +0000 @@ -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 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sink11.h Mon Jan 13 21:48:03 1992 +0000 @@ -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};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sink11mask.h Mon Jan 13 21:48:03 1992 +0000 @@ -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};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/terminfo.c Mon Jan 13 21:48:03 1992 +0000 @@ -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; +}
--- a/src/uaf.h Mon Jan 13 06:37:58 1992 +0000 +++ b/src/uaf.h Mon Jan 13 21:48:03 1992 +0000 @@ -3,20 +3,19 @@ This file is part of GNU Emacs. -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. +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. -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. */ +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. */ /* * User Authorization File record formats
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/unexconvex.c Mon Jan 13 21:48:03 1992 +0000 @@ -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); +} + +/* **************************************************************** + * 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); + +} + +/* **************************************************************** + * 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; + } +} + +/* **************************************************************** + * 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; +} + +/* **************************************************************** + * 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); +} + +/* 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'; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/unexelf.c Mon Jan 13 21:48:03 1992 +0000 @@ -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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/unexenix.c Mon Jan 13 21:48:03 1992 +0000 @@ -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. */ + + + +/* + 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 + +/* 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); +}
--- a/src/unexhp9k800.c Mon Jan 13 06:37:58 1992 +0000 +++ b/src/unexhp9k800.c Mon Jan 13 21:48:03 1992 +0000 @@ -60,6 +60,7 @@ 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 @@ /* 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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vlimit.h Mon Jan 13 21:48:03 1992 +0000 @@ -0,0 +1,2 @@ +/* Dummy for Emacs so that we can run on VMS... */ +#define LIM_DATA 0
--- a/src/vms-pp.c Mon Jan 13 06:37:58 1992 +0000 +++ b/src/vms-pp.c Mon Jan 13 21:48:03 1992 +0000 @@ -16,7 +16,7 @@ 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:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vms-pwd.h Mon Jan 13 21:48:03 1992 +0000 @@ -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 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vmsdir.h Mon Jan 13 21:48:03 1992 +0000 @@ -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
--- a/src/vmsfns.c Mon Jan 13 06:37:58 1992 +0000 +++ b/src/vmsfns.c Mon Jan 13 21:48:03 1992 +0000 @@ -310,7 +310,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ 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) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vmsmap.c Mon Jan 13 21:48:03 1992 +0000 @@ -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 */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vmspaths.h Mon Jan 13 21:48:03 1992 +0000 @@ -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$$$."
--- a/src/vmsproc.c Mon Jan 13 06:37:58 1992 +0000 +++ b/src/vmsproc.c Mon Jan 13 21:48:03 1992 +0000 @@ -437,7 +437,7 @@ 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 (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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vmsproc.h Mon Jan 13 21:48:03 1992 +0000 @@ -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;