1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-11-24 07:20:37 +00:00

entered into RCS

This commit is contained in:
Jim Blandy 1992-01-13 21:48:03 +00:00
parent b2c9579f17
commit d427b66a66
43 changed files with 3193 additions and 104 deletions

View File

@ -67,8 +67,8 @@ main (argc,argv)
int depth;
Pixmap pix;
char *string = "Kill the head and the body will die.";
char dash_list[] = {6, 4, 6, 4};
int dashes = 4;
char dash_list[] = {4, 4};
int dashes = 2;
if (argc < 2)
dpy_string = "localhost:0.0";
@ -105,24 +105,19 @@ main (argc,argv)
&gc_values);
gc_values.foreground = obtain_color ("red");
gc_values.function = GXor;
gc_values.line_width = 3;
gc_values.line_style = LineOnOffDash;
gc_values.cap_style = CapRound;
gc_values.join_style = JoinRound;
line_xor_gc = XCreateGC (dpy, window,
GCForeground | GCBackground | GCLineStyle
| GCJoinStyle | GCCapStyle | GCLineWidth
| GCFunction,
| GCJoinStyle | GCCapStyle | GCLineWidth,
&gc_values);
XSetDashes (dpy, line_xor_gc, 0, dash_list, dashes);
gc_values.background = WhitePixel (dpy, DefaultScreen (dpy));
gc_values.foreground = obtain_color ("blue");
line_xor_inv_gc = XCreateGC (dpy, window,
GCForeground | GCBackground
| GCLineWidth | GCFunction,
&gc_values);
GCForeground | GCBackground | GCLineWidth,
&gc_values);
depth = DefaultDepthOfScreen (ScreenOfDisplay (dpy, DefaultScreen (dpy)));
pix = XCreateBitmapFromData (dpy, window, page_glyf_bits,
@ -137,25 +132,20 @@ main (argc,argv)
switch (event.type)
{
case ButtonPress:
#if 0
if (event.xbutton.state && ShiftMask)
#endif
switch (event.xbutton.button)
{
case Button1:
XDrawLine (dpy, window, line_xor_gc, 25, 75, 125, 75);
XFlush (dpy);
XDrawLine (dpy, window, line_xor_gc, 25, 75, 125, 75);
break;
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:

7
src/XTests.h Normal file
View File

@ -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};

View File

@ -20,7 +20,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include <stdio.h>
#undef NULL
#include "lisp.h"
#include "commands.h"
#include "buffer.h"
@ -113,9 +112,9 @@ it is called after EXPANSION is inserted.")
Lisp_Object sym, oexp, ohook, tem;
CHECK_VECTOR (table, 0);
CHECK_STRING (name, 1);
if (!NULL (expansion))
if (!NILP (expansion))
CHECK_STRING (expansion, 2);
if (NULL (count))
if (NILP (count))
count = make_number (0);
else
CHECK_NUMBER (count, 0);
@ -126,10 +125,10 @@ it is called after EXPANSION is inserted.")
ohook = XSYMBOL (sym)->function;
if (!((EQ (oexp, expansion)
|| (XTYPE (oexp) == Lisp_String && XTYPE (expansion) == Lisp_String
&& (tem = Fstring_equal (oexp, expansion), !NULL (tem))))
&& (tem = Fstring_equal (oexp, expansion), !NILP (tem))))
&&
(EQ (ohook, hook)
|| (tem = Fequal (ohook, hook), !NULL (tem)))))
|| (tem = Fequal (ohook, hook), !NILP (tem)))))
abbrevs_changed = 1;
Fset (sym, expansion);
@ -156,7 +155,7 @@ DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev, Sdefine_mode_abbrev, 2, 2,
(name, expansion)
Lisp_Object name, expansion;
{
if (NULL (current_buffer->abbrev_table))
if (NILP (current_buffer->abbrev_table))
error ("Major mode has no abbrev table");
Fdefine_abbrev (current_buffer->abbrev_table, Fdowncase (name),
@ -176,19 +175,19 @@ The default is to try buffer's mode-specific abbrev table, then global table.")
{
Lisp_Object sym;
CHECK_STRING (abbrev, 0);
if (!NULL (table))
if (!NILP (table))
sym = Fintern_soft (abbrev, table);
else
{
sym = Qnil;
if (!NULL (current_buffer->abbrev_table))
if (!NILP (current_buffer->abbrev_table))
sym = Fintern_soft (abbrev, current_buffer->abbrev_table);
if (NULL (XSYMBOL (sym)->value))
if (NILP (XSYMBOL (sym)->value))
sym = Qnil;
if (NULL (sym))
if (NILP (sym))
sym = Fintern_soft (abbrev, Vglobal_abbrev_table);
}
if (NULL (XSYMBOL (sym)->value)) return Qnil;
if (NILP (XSYMBOL (sym)->value)) return Qnil;
return sym;
}
@ -201,7 +200,7 @@ then ABBREV is looked up in that table only.")
{
Lisp_Object sym;
sym = Fabbrev_symbol (abbrev, table);
if (NULL (sym)) return sym;
if (NILP (sym)) return sym;
return Fsymbol_value (sym);
}
@ -221,12 +220,12 @@ Returns t if expansion took place.")
register Lisp_Object sym;
Lisp_Object expansion, hook, tem;
if (!NULL (Vrun_hooks))
if (!NILP (Vrun_hooks))
call1 (Vrun_hooks, Qpre_abbrev_expand_hook);
if (XBUFFER (Vabbrev_start_location_buffer) != current_buffer)
Vabbrev_start_location = Qnil;
if (!NULL (Vabbrev_start_location))
if (!NILP (Vabbrev_start_location))
{
tem = Vabbrev_start_location;
CHECK_NUMBER_COERCE_MARKER (tem, 0);
@ -267,9 +266,9 @@ Returns t if expansion took place.")
sym = oblookup (current_buffer->abbrev_table, buffer, p - buffer);
else
XFASTINT (sym) = 0;
if (XTYPE (sym) == Lisp_Int || NULL (XSYMBOL (sym)->value))
if (XTYPE (sym) == Lisp_Int || NILP (XSYMBOL (sym)->value))
sym = oblookup (Vglobal_abbrev_table, buffer, p - buffer);
if (XTYPE (sym) == Lisp_Int || NULL (XSYMBOL (sym)->value))
if (XTYPE (sym) == Lisp_Int || NILP (XSYMBOL (sym)->value))
return Qnil;
if (INTERACTIVE && !EQ (minibuf_window, selected_window))
@ -327,7 +326,7 @@ Returns t if expansion took place.")
}
hook = XSYMBOL (sym)->function;
if (!NULL (hook))
if (!NILP (hook))
call0 (hook);
return Qt;
@ -367,7 +366,7 @@ write_abbrev (sym, stream)
Lisp_Object sym, stream;
{
Lisp_Object name;
if (NULL (XSYMBOL (sym)->value))
if (NILP (XSYMBOL (sym)->value))
return;
insert (" (", 5);
XSET (name, Lisp_String, XSYMBOL (sym)->name);
@ -387,7 +386,7 @@ describe_abbrev (sym, stream)
{
Lisp_Object one;
if (NULL (XSYMBOL (sym)->value))
if (NILP (XSYMBOL (sym)->value))
return;
one = make_number (1);
Fprin1 (Fsymbol_name (sym), stream);
@ -395,7 +394,7 @@ describe_abbrev (sym, stream)
Fprin1 (XSYMBOL (sym)->plist, stream);
Findent_to (make_number (20), one);
Fprin1 (XSYMBOL (sym)->value, stream);
if (!NULL (XSYMBOL (sym)->function))
if (!NILP (XSYMBOL (sym)->function))
{
Findent_to (make_number (45), one);
Fprin1 (XSYMBOL (sym)->function, stream);
@ -424,7 +423,7 @@ define the abbrev table NAME exactly as it is currently defined.")
XSET (stream, Lisp_Buffer, current_buffer);
if (!NULL (readable))
if (!NILP (readable))
{
insert_string ("(");
Fprin1 (name, stream);
@ -457,7 +456,7 @@ of the form (ABBREVNAME EXPANSION HOOK USECOUNT).")
CHECK_SYMBOL (tabname, 0);
table = Fboundp (tabname);
if (NULL (table) || (table = Fsymbol_value (tabname), NULL (table)))
if (NILP (table) || (table = Fsymbol_value (tabname), NILP (table)))
{
table = Fmake_abbrev_table ();
Fset (tabname, table);
@ -466,7 +465,7 @@ of the form (ABBREVNAME EXPANSION HOOK USECOUNT).")
}
CHECK_VECTOR (table, 0);
for (;!NULL (defns); defns = Fcdr (defns))
for (;!NILP (defns); defns = Fcdr (defns))
{
elt = Fcar (defns);
name = Fcar (elt);

40
src/acldef.h Normal file
View File

@ -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

View File

@ -261,7 +261,10 @@ syms_of_casefiddle ()
keys_of_casefiddle ()
{
initial_define_key (control_x_map, Ctl('U'), "upcase-region");
Fput (intern ("upcase-region"), Qdisabled, Qt);
initial_define_key (control_x_map, Ctl('L'), "downcase-region");
Fput (intern ("downcase-region"), Qdisabled, Qt);
initial_define_key (meta_map, 'u', "upcase-word");
initial_define_key (meta_map, 'l', "downcase-word");
initial_define_key (meta_map, 'c', "capitalize-word");

View File

@ -45,8 +45,8 @@ See `set-case-table' for more information on these data structures.")
(XTYPE (obj) == Lisp_String && XSTRING (obj)->size == 256)
return (STRING256_P (down)
&& (NULL (up) || STRING256_P (up))
&& ((NULL (canon) && NULL (eqv))
&& (NILP (up) || STRING256_P (up))
&& ((NILP (canon) && NILP (eqv))
|| (STRING256_P (canon) && STRING256_P (eqv)))
? Qt : Qnil);
}
@ -57,7 +57,7 @@ check_case_table (obj)
{
register Lisp_Object tem;
while (tem = Fcase_table_p (obj), NULL (tem))
while (tem = Fcase_table_p (obj), NILP (tem))
obj = wrong_type_argument (Qcase_table_p, obj, 0);
return (obj);
}
@ -132,13 +132,13 @@ set_case_table (table, standard)
canon = Fcar_safe (Fcdr_safe (Fcdr_safe (table)));
eqv = Fcar_safe (Fcdr_safe (Fcdr_safe (Fcdr_safe (table))));
if (NULL (up))
if (NILP (up))
{
up = Fmake_string (make_number (256), make_number (0));
compute_trt_inverse (XSTRING (down)->data, XSTRING (up)->data);
}
if (NULL (canon))
if (NILP (canon))
{
register int i;
unsigned char *upvec = XSTRING (up)->data;

38
src/chpdef.h Normal file
View File

@ -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

414
src/cm.c Normal file
View File

@ -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;
}

82
src/disptab.h Normal file
View File

@ -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 ();

View File

@ -68,10 +68,10 @@ doprnt (buffer, bufsize, format, format_end, nargs, args)
int size_bound;
fmt++;
/* Copy this one %-spec into fmtcopy. */
/* Copy this one %-spec into fmtcpy. */
string = fmtcpy;
*string++ = '%';
while (1)
while (string < fmtcpy + sizeof fmtcpy - 1)
{
*string++ = *fmt;
if (! (*fmt >= '0' && *fmt <= '9') && *fmt != '-' && *fmt != ' ')

34
src/indent.h Normal file
View File

@ -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;

View File

@ -214,7 +214,7 @@ adjust_markers (from, to, amount)
marker = current_buffer->markers;
while (!NULL (marker))
while (!NILP (marker))
{
m = XMARKER (marker);
mpos = m->bufpos;
@ -352,7 +352,7 @@ insert_from_string (string, pos, length)
GPT += length;
ZV += length;
Z += length;
point += length;
SET_PT (point + length);
signal_after_change (point-length, 0, length);
}
@ -473,22 +473,22 @@ modify_region (start, end)
prepare_to_modify_buffer (start, end)
Lisp_Object start, end;
{
if (!NULL (current_buffer->read_only))
if (!NILP (current_buffer->read_only))
Fbarf_if_buffer_read_only ();
if (check_protected_fields)
Fregion_fields (start, end, Qnil, Qt);
#ifdef CLASH_DETECTION
if (!NULL (current_buffer->filename)
if (!NILP (current_buffer->filename)
&& current_buffer->save_modified >= MODIFF)
lock_file (current_buffer->filename);
#else
/* At least warn if this file has changed on disk since it was visited. */
if (!NULL (current_buffer->filename)
if (!NILP (current_buffer->filename)
&& current_buffer->save_modified >= MODIFF
&& NULL (Fverify_visited_file_modtime (Fcurrent_buffer ()))
&& !NULL (Ffile_exists_p (current_buffer->filename)))
&& NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
&& !NILP (Ffile_exists_p (current_buffer->filename)))
call1 (intern ("ask-user-about-supersession-threat"),
current_buffer->filename);
#endif /* not CLASH_DETECTION */
@ -519,12 +519,12 @@ signal_before_change (start, end)
{
/* If buffer is unmodified, run a special hook for that case. */
if (current_buffer->save_modified >= MODIFF
&& !NULL (Vfirst_change_function))
&& !NILP (Vfirst_change_function))
{
call0 (Vfirst_change_function);
}
/* Now in any case run the before-change-function if any. */
if (!NULL (Vbefore_change_function))
if (!NILP (Vbefore_change_function))
{
int count = specpdl_ptr - specpdl;
Lisp_Object function;
@ -551,7 +551,7 @@ signal_before_change (start, end)
signal_after_change (pos, lendel, lenins)
int pos, lendel, lenins;
{
if (!NULL (Vafter_change_function))
if (!NILP (Vafter_change_function))
{
int count = specpdl_ptr - specpdl;
Lisp_Object function;

1
src/ioctl.h Normal file
View File

@ -0,0 +1 @@
/* Emacs ioctl emulation for VMS */

38
src/lastfile.c Normal file
View File

@ -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;

7
src/line.h Normal file
View File

@ -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};

31
src/macros.h Normal file
View File

@ -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;

View File

@ -36,7 +36,7 @@ Returns nil if MARKER points into a dead buffer.")
{
XSET (buf, Lisp_Buffer, XMARKER (marker)->buffer);
/* Return marker's buffer only if it is not dead. */
if (!NULL (XBUFFER (buf)->name))
if (!NILP (XBUFFER (buf)->name))
return buf;
}
return Qnil;
@ -87,7 +87,7 @@ Returns MARKER.")
CHECK_MARKER (marker, 0);
/* If position is nil or a marker that points nowhere,
make this marker point nowhere. */
if (NULL (pos)
if (NILP (pos)
|| (XTYPE (pos) == Lisp_Marker && !XMARKER (pos)->buffer))
{
unchain_marker (marker);
@ -95,7 +95,7 @@ Returns MARKER.")
}
CHECK_NUMBER_COERCE_MARKER (pos, 1);
if (NULL (buffer))
if (NILP (buffer))
b = current_buffer;
else
{
@ -144,7 +144,7 @@ set_marker_restricted (marker, pos, buffer)
CHECK_MARKER (marker, 0);
/* If position is nil or a marker that points nowhere,
make this marker point nowhere. */
if (NULL (pos) ||
if (NILP (pos) ||
(XTYPE (pos) == Lisp_Marker && !XMARKER (pos)->buffer))
{
unchain_marker (marker);
@ -152,7 +152,7 @@ set_marker_restricted (marker, pos, buffer)
}
CHECK_NUMBER_COERCE_MARKER (pos, 1);
if (NULL (buffer))
if (NILP (buffer))
b = current_buffer;
else
{
@ -215,7 +215,7 @@ unchain_marker (marker)
if (XMARKER (marker) == XMARKER (tail))
{
if (NULL (prev))
if (NILP (prev))
{
b->markers = next;
/* Deleting first marker from the buffer's chain.

View File

@ -32,7 +32,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
* {
* Lisp_Object elt;
*
* while (!NULL (args))
* while (!NILP (args))
* {
* elt = Fcar (args);
* Ffset (Fcar (elt), Fcons (Qmocklisp, Fcdr (elt)));
@ -50,11 +50,11 @@ DEFUN ("ml-if", Fml_if, Sml_if, 0, UNEVALLED, 0, "Mocklisp version of `if'.")
struct gcpro gcpro1;
GCPRO1 (args);
while (!NULL (args))
while (!NILP (args))
{
val = Feval (Fcar (args));
args = Fcdr (args);
if (NULL (args)) break;
if (NILP (args)) break;
if (XINT (val))
{
val = Feval (Fcar (args));
@ -156,7 +156,7 @@ DEFUN ("ml-prefix-argument-loop", Fml_prefix_argument_loop, Sml_prefix_argument_
struct gcpro gcpro1;
/* Set `arg' in case we call a built-in function that looks at it. Still are a few. */
if (NULL (Vcurrent_prefix_arg))
if (NILP (Vcurrent_prefix_arg))
i = 1;
else
{

View File

@ -28,4 +28,4 @@ extern Lisp_Object Fml_arg ();
extern Lisp_Object Fml_interactive ();
extern Lisp_Object Fml_provide_prefix_argument ();
extern Lisp_Object Fml_prefix_argument_loop ();
extern Lisp_Object FInsStr ();
extern Lisp_Object Finsert_string ();

51
src/ndir.h Normal file
View File

@ -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 )

2
src/param.h Normal file
View File

@ -0,0 +1,2 @@
/* This is so that Emacs can run on VMS... */
#define EXEC_PAGESIZE 512

5
src/point.h Normal file
View File

@ -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};

9
src/pre-crt0.c Normal file
View File

@ -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;

View File

@ -21,9 +21,19 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
At one point, this was defined in config.h, meaning that changing
PURESIZE would make Make recompile all of Emacs. But only a few
files actually use PURESIZE, so we split it out to its own .h file. */
files actually use PURESIZE, so we split it out to its own .h file.
Make sure to include this file after config.h, since that tells us
whether we are running X windows, which tells us how much pure
storage to allocate. */
#ifndef PURESIZE
#ifdef HAVE_X_WINDOWS
#define PURESIZE 200000
#else
#define PURESIZE 196000
#endif
#endif
#ifdef VIRT_ADDR_VARIES

91
src/sink.h Normal file
View File

@ -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 */

51
src/sink11.h Normal file
View File

@ -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};

51
src/sink11mask.h Normal file
View File

@ -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};

50
src/terminfo.c Normal file
View File

@ -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;
}

View File

@ -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

601
src/unexconvex.c Normal file
View File

@ -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';
}

703
src/unexelf.c Normal file
View File

@ -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);
}

262
src/unexenix.c Normal file
View File

@ -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);
}

View File

@ -60,6 +60,7 @@ unexec(new_name, old_name, new_end_of_text, dummy1, dummy2)
int old_size, new_size;
struct header hdr;
struct som_exec_auxhdr auxhdr;
long i;
/* For the greatest flexibility, should create a temporary file in
the same directory as the new file. When everything is complete,
@ -81,7 +82,10 @@ unexec(new_name, old_name, new_end_of_text, dummy1, dummy2)
/* Decide how large the new and old data areas are */
old_size = auxhdr.exec_dsize;
new_size = sbrk(0) - auxhdr.exec_dmem;
/* I suspect these two statements are separate
to avoid a compiler bug in hpux version 8. */
i = sbrk (0);
new_size = i - auxhdr.exec_dmem;
/* Copy the old file to the new, up to the data space */
lseek(old, 0, 0);

2
src/vlimit.h Normal file
View File

@ -0,0 +1,2 @@
/* Dummy for Emacs so that we can run on VMS... */
#define LIM_DATA 0

View File

@ -16,7 +16,7 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Usage:

34
src/vms-pwd.h Normal file
View File

@ -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 */

97
src/vmsdir.h Normal file
View File

@ -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

View File

@ -310,7 +310,7 @@ DEFUN ("spawn-subprocess", Fspawn_subprocess, Sspawn_subprocess, 1, 3, 0,
prev->next = next;
else
process_list = next;
if (! NULL (ptr->exit_handler))
if (! NILP (ptr->exit_handler))
Feval (Fcons (ptr->exit_handler, Fcons (make_number (ptr->name),
Qnil)));
sys$dassgn (ptr->mbx_chan);
@ -327,7 +327,7 @@ DEFUN ("spawn-subprocess", Fspawn_subprocess, Sspawn_subprocess, 1, 3, 0,
free (ptr);
return Qnil;
}
if (NULL (input_handler))
if (NILP (input_handler))
input_handler = Qdefault_subproc_input_handler;
ptr->input_handler = input_handler;
ptr->exit_handler = exit_handler;
@ -447,7 +447,7 @@ process_command_input ()
have_process_input = 0;
start_mbx_input ();
clear_waiting_for_input (); /* Otherwise Ctl-g will cause crash. JCB */
if (! NULL (expr))
if (! NILP (expr))
Feval (expr);
}
@ -471,7 +471,7 @@ process_exit ()
prev->next = next;
else
process_list = next;
if (! NULL (ptr->exit_handler))
if (! NILP (ptr->exit_handler))
Feval (Fcons (ptr->exit_handler, Fcons (make_number (ptr->name),
Qnil)));
sys$dassgn (ptr->mbx_chan);
@ -605,9 +605,9 @@ or nil depending upon whether the privilege is already enabled.")
}
if (! found)
error ("Unknown privilege name %s", XSTRING (priv)->data);
if (NULL (getprv))
if (NILP (getprv))
{
if (sys$setprv (NULL (value) ? 0 : 1, prvmask, 0, 0) == SS$_NORMAL)
if (sys$setprv (NILP (value) ? 0 : 1, prvmask, 0, 0) == SS$_NORMAL)
return Qt;
return Qnil;
}
@ -679,7 +679,7 @@ translate_id (pid, owner)
char * p;
int prcnam[2];
if (NULL (pid)
if (NILP (pid)
|| XTYPE (pid) == Lisp_String && XSTRING (pid)->size == 0
|| XTYPE (pid) == Lisp_Int && XFASTINT (pid) == 0)
{

224
src/vmsmap.c Normal file
View File

@ -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 */

15
src/vmspaths.h Normal file
View File

@ -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$$$."

View File

@ -437,7 +437,7 @@ if you quit, the process is killed.")
CHECK_STRING (args[0], 0);
if (nargs <= 1 || NULL (args[1]))
if (nargs <= 1 || NILP (args[1]))
args[1] = build_string ("NLA0:");
else
args[1] = Fexpand_file_name (args[1], current_buffer->directory);
@ -589,12 +589,12 @@ if you quit, the process is killed.")
if (vs->iosb[0] & 1)
{
immediate_quit = 0;
if (!NULL (buffer))
if (!NILP (buffer))
{
vs->iosb[1] = clean_vms_buffer (vs->inputBuffer, vs->iosb[1]);
InsCStr (vs->inputBuffer, vs->iosb[1]);
}
if (!NULL (display) && INTERACTIVE)
if (!NILP (display) && INTERACTIVE)
redisplay_preserve_echo_area ();
immediate_quit = 1;
QUIT;

21
src/vmsproc.h Normal file
View File

@ -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;

123
src/xscrollbar.h Normal file
View File

@ -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 */