diff options
| author | Ken Raeburn | 2001-07-06 08:41:36 +0000 |
|---|---|---|
| committer | Ken Raeburn | 2001-07-06 08:41:36 +0000 |
| commit | ad782551325b7c694ee234b5ff4c5688d90e561c (patch) | |
| tree | f4355f141142b6018183518fa1761b53e295ede2 /src | |
| parent | f25cfe53951f57e1b2c3972877297df3d86bb980 (diff) | |
| download | emacs-ad782551325b7c694ee234b5ff4c5688d90e561c.tar.gz emacs-ad782551325b7c694ee234b5ff4c5688d90e561c.zip | |
properly mark Attic files as deleted
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.in | 1226 | ||||
| -rw-r--r-- | src/XTests.c | 179 | ||||
| -rw-r--r-- | src/XTests.h | 7 | ||||
| -rw-r--r-- | src/convexos.h | 10 | ||||
| -rw-r--r-- | src/environ.c | 316 | ||||
| -rw-r--r-- | src/m/dos386.h | 115 | ||||
| -rw-r--r-- | src/mach2.h | 48 | ||||
| -rw-r--r-- | src/old-ralloc.c | 1069 | ||||
| -rw-r--r-- | src/sol2-2.h | 18 | ||||
| -rw-r--r-- | src/unexelf1.c | 952 | ||||
| -rw-r--r-- | src/unexsgi.c | 900 | ||||
| -rw-r--r-- | src/x11term.h | 24 | ||||
| -rw-r--r-- | src/xscrollbar.h | 123 | ||||
| -rw-r--r-- | src/xselect.c.old | 950 |
14 files changed, 0 insertions, 5937 deletions
diff --git a/src/Makefile.in b/src/Makefile.in deleted file mode 100644 index 03faaae332b..00000000000 --- a/src/Makefile.in +++ /dev/null | |||
| @@ -1,1226 +0,0 @@ | |||
| 1 | # Makefile for GNU Emacs. | ||
| 2 | # Copyright (C) 1985, 87, 88, 93, 94, 95, 99, 2000, 2001 | ||
| 3 | # Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | # This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | # GNU Emacs is free software; you can redistribute it and/or modify | ||
| 8 | # it under the terms of the GNU General Public License as published by | ||
| 9 | # the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | # any later version. | ||
| 11 | |||
| 12 | # GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | # GNU General Public License for more details. | ||
| 16 | |||
| 17 | # You should have received a copy of the GNU General Public License | ||
| 18 | # along with GNU Emacs; see the file COPYING. If not, write to | ||
| 19 | # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 20 | # Boston, MA 02111-1307, USA. | ||
| 21 | |||
| 22 | |||
| 23 | # Note that this file is edited by msdos/sed1v2.inp for MSDOS. That | ||
| 24 | # script may need modifying in sync with changes made here. Try to | ||
| 25 | # avoid shell-ism because the DOS build has to use the DOS shell. | ||
| 26 | |||
| 27 | # Don't try to replace the ccp processing using autoconf facilities, | ||
| 28 | # says rms. | ||
| 29 | |||
| 30 | # Here are the things that we expect ../configure to edit. | ||
| 31 | # We use $(srcdir) explicitly in dependencies so as not to depend on VPATH. | ||
| 32 | srcdir=@srcdir@ | ||
| 33 | VPATH=@srcdir@ | ||
| 34 | CC=@CC@ | ||
| 35 | CPP=@CPP@ | ||
| 36 | CFLAGS=@CFLAGS@ | ||
| 37 | CPPFLAGS=@CPPFLAGS@ | ||
| 38 | LDFLAGS=@LDFLAGS@ | ||
| 39 | LN_S=@LN_S@ | ||
| 40 | # Substitute an assignment for the MAKE variable, because | ||
| 41 | # BSD doesn't have it as a default. | ||
| 42 | @SET_MAKE@ | ||
| 43 | # Don't use LIBS. configure puts stuff in it that either shouldn't be | ||
| 44 | # linked with Emacs or is duplicated by the cpp stuff below. | ||
| 45 | # LIBS = @LIBS@ | ||
| 46 | LIBOBJS = @LIBOBJS@ | ||
| 47 | |||
| 48 | # On Xenix and the IBM RS6000, double-dot gets screwed up. | ||
| 49 | dot = . | ||
| 50 | dotdot = ${dot}${dot} | ||
| 51 | lispsource = ${srcdir}/$(dot)$(dot)/lisp/ | ||
| 52 | libsrc = $(dot)$(dot)/lib-src/ | ||
| 53 | etc = $(dot)$(dot)/etc/ | ||
| 54 | oldXMenudir = $(dot)$(dot)/oldXMenu/ | ||
| 55 | lwlibdir = $(dot)$(dot)/lwlib/ | ||
| 56 | |||
| 57 | # Configuration files for .o files to depend on. | ||
| 58 | M_FILE = ${srcdir}/@machfile@ | ||
| 59 | S_FILE = ${srcdir}/@opsysfile@ | ||
| 60 | config_h = config.h $(M_FILE) $(S_FILE) | ||
| 61 | |||
| 62 | # ========================== start of cpp stuff ======================= | ||
| 63 | /* From here on, comments must be done in C syntax. */ | ||
| 64 | |||
| 65 | C_SWITCH_SYSTEM= | ||
| 66 | |||
| 67 | /* just to be sure the sh is used */ | ||
| 68 | SHELL=/bin/sh | ||
| 69 | |||
| 70 | #define THIS_IS_MAKEFILE | ||
| 71 | #define NO_SHORTNAMES | ||
| 72 | #define NOT_C_CODE | ||
| 73 | #include "config.h" | ||
| 74 | |||
| 75 | /* We won't really call alloca; | ||
| 76 | don't let the file name alloca.c get messed up. */ | ||
| 77 | #ifdef alloca | ||
| 78 | #undef alloca | ||
| 79 | #endif | ||
| 80 | |||
| 81 | /* Don't let the file name mktime.c get messed up. */ | ||
| 82 | #ifdef mktime | ||
| 83 | #undef mktime | ||
| 84 | #endif | ||
| 85 | |||
| 86 | /* Use HAVE_X11 as an alias for X11 in this file | ||
| 87 | to avoid problems with X11 as a subdirectory name | ||
| 88 | in -I and other such options which pass through this file. */ | ||
| 89 | |||
| 90 | #ifdef X11 | ||
| 91 | #define HAVE_X11 | ||
| 92 | #undef X11 | ||
| 93 | #endif | ||
| 94 | |||
| 95 | /* On some machines #define register is done in config; | ||
| 96 | don't let it interfere with this file. */ | ||
| 97 | #undef register | ||
| 98 | |||
| 99 | /* On some systems we may not be able to use the system make command. */ | ||
| 100 | #ifdef MAKE_COMMAND | ||
| 101 | MAKE = MAKE_COMMAND | ||
| 102 | #endif | ||
| 103 | |||
| 104 | #ifdef C_COMPILER | ||
| 105 | CC = C_COMPILER | ||
| 106 | #endif | ||
| 107 | |||
| 108 | /* GNU libc requires ORDINARY_LINK so that its own crt0 is used. | ||
| 109 | Linux is an exception because it uses a funny variant of GNU libc. */ | ||
| 110 | #ifdef __GNU_LIBRARY__ | ||
| 111 | #ifndef LINUX | ||
| 112 | #define ORDINARY_LINK | ||
| 113 | #endif | ||
| 114 | #endif | ||
| 115 | |||
| 116 | /* Some machines don't find the standard C libraries in the usual place. */ | ||
| 117 | #ifndef ORDINARY_LINK | ||
| 118 | #ifndef LIB_STANDARD | ||
| 119 | #define LIB_STANDARD -lc | ||
| 120 | #endif | ||
| 121 | #else | ||
| 122 | #ifndef LIB_STANDARD | ||
| 123 | #define LIB_STANDARD | ||
| 124 | #endif | ||
| 125 | #endif | ||
| 126 | |||
| 127 | /* Unless inhibited or changed, use -lg to link for debugging. */ | ||
| 128 | #ifndef LIBS_DEBUG | ||
| 129 | #define LIBS_DEBUG -lg | ||
| 130 | #endif | ||
| 131 | |||
| 132 | /* Some s/SYSTEM.h files define this to request special libraries. */ | ||
| 133 | #ifndef LIBS_SYSTEM | ||
| 134 | #define LIBS_SYSTEM | ||
| 135 | #endif | ||
| 136 | |||
| 137 | /* Some m/MACHINE.h files define this to request special libraries. */ | ||
| 138 | #ifndef LIBS_MACHINE | ||
| 139 | #define LIBS_MACHINE | ||
| 140 | #endif | ||
| 141 | |||
| 142 | #ifndef LIB_MATH | ||
| 143 | # define LIB_MATH -lm | ||
| 144 | #endif /* LIB_MATH */ | ||
| 145 | |||
| 146 | /* Some s/SYSTEM.h files define this to request special switches in ld. */ | ||
| 147 | #ifndef LD_SWITCH_SYSTEM | ||
| 148 | #if !defined (__GNUC__) && (defined(COFF_ENCAPSULATE) || (defined (BSD_SYSTEM) && !defined (COFF))) | ||
| 149 | #define LD_SWITCH_SYSTEM -X | ||
| 150 | #else /* ! defined(COFF_ENCAPSULATE) || (defined (BSD_SYSTEM) && !defined (COFF)) */ | ||
| 151 | #define LD_SWITCH_SYSTEM | ||
| 152 | #endif /* ! defined(COFF_ENCAPSULATE) || (defined (BSD_SYSTEM) && !defined (COFF)) */ | ||
| 153 | #endif /* LD_SWITCH_SYSTEM */ | ||
| 154 | |||
| 155 | /* This holds special options for linking temacs | ||
| 156 | that should be used for linking anything else. */ | ||
| 157 | #ifndef LD_SWITCH_SYSTEM_TEMACS | ||
| 158 | #define LD_SWITCH_SYSTEM_TEMACS | ||
| 159 | #endif | ||
| 160 | |||
| 161 | /* Some m/MACHINE.h files define this to request special switches in ld. */ | ||
| 162 | #ifndef LD_SWITCH_MACHINE | ||
| 163 | #define LD_SWITCH_MACHINE | ||
| 164 | #endif | ||
| 165 | |||
| 166 | /* This holds special options for linking temacs | ||
| 167 | that should be used for linking anything else. */ | ||
| 168 | #ifndef LD_SWITCH_MACHINE_TEMACS | ||
| 169 | #define LD_SWITCH_MACHINE_TEMACS | ||
| 170 | #endif | ||
| 171 | |||
| 172 | /* Some m/MACHINE.h files define this to request special switches in cc. */ | ||
| 173 | #ifndef C_SWITCH_MACHINE | ||
| 174 | #define C_SWITCH_MACHINE | ||
| 175 | #endif | ||
| 176 | |||
| 177 | /* Some s/SYSTEM.h files define this to request special switches in cc. */ | ||
| 178 | #ifndef C_SWITCH_SYSTEM | ||
| 179 | #define C_SWITCH_SYSTEM | ||
| 180 | #endif | ||
| 181 | |||
| 182 | /* These macros are for switches specifically related to X Windows. */ | ||
| 183 | #ifndef C_SWITCH_X_MACHINE | ||
| 184 | #define C_SWITCH_X_MACHINE | ||
| 185 | #endif | ||
| 186 | |||
| 187 | #ifndef C_SWITCH_X_SYSTEM | ||
| 188 | #define C_SWITCH_X_SYSTEM | ||
| 189 | #endif | ||
| 190 | |||
| 191 | #ifndef C_SWITCH_X_SITE | ||
| 192 | #define C_SWITCH_X_SITE | ||
| 193 | #endif | ||
| 194 | |||
| 195 | #ifndef LD_SWITCH_X_SITE | ||
| 196 | #define LD_SWITCH_X_SITE | ||
| 197 | #endif | ||
| 198 | |||
| 199 | #ifndef LD_SWITCH_X_DEFAULT | ||
| 200 | #define LD_SWITCH_X_DEFAULT | ||
| 201 | #endif | ||
| 202 | |||
| 203 | /* These can be passed in from config.h to define special load and | ||
| 204 | compile switches needed by individual sites */ | ||
| 205 | #ifndef LD_SWITCH_SITE | ||
| 206 | #define LD_SWITCH_SITE | ||
| 207 | #endif | ||
| 208 | |||
| 209 | #ifndef C_SWITCH_SITE | ||
| 210 | #define C_SWITCH_SITE | ||
| 211 | #endif | ||
| 212 | |||
| 213 | #ifndef ORDINARY_LINK | ||
| 214 | |||
| 215 | #ifndef CRT0_COMPILE | ||
| 216 | #define CRT0_COMPILE $(CC) -c $(ALL_CFLAGS) C_SWITCH_ASM | ||
| 217 | #endif | ||
| 218 | |||
| 219 | #ifndef START_FILES | ||
| 220 | #ifdef NO_REMAP | ||
| 221 | #ifdef COFF_ENCAPSULATE | ||
| 222 | #define START_FILES pre-crt0.o /usr/local/lib/gcc-crt0.o | ||
| 223 | #else /* ! defined (COFF_ENCAPSULATE) */ | ||
| 224 | #define START_FILES pre-crt0.o /lib/crt0.o | ||
| 225 | #endif /* ! defined (COFF_ENCAPSULATE) */ | ||
| 226 | #else /* ! defined (NO_REMAP) */ | ||
| 227 | #define START_FILES ecrt0.o | ||
| 228 | #endif /* ! defined (NO_REMAP) */ | ||
| 229 | #endif /* START_FILES */ | ||
| 230 | STARTFILES = START_FILES | ||
| 231 | |||
| 232 | #else /* ORDINARY_LINK */ | ||
| 233 | |||
| 234 | /* config.h might want to force START_FILES anyway */ | ||
| 235 | #ifdef START_FILES | ||
| 236 | STARTFILES = START_FILES | ||
| 237 | #endif /* START_FILES */ | ||
| 238 | |||
| 239 | #endif /* not ORDINARY_LINK */ | ||
| 240 | |||
| 241 | |||
| 242 | /* cc switches needed to make `asm' keyword work. | ||
| 243 | Nothing special needed on most machines. */ | ||
| 244 | #ifndef C_SWITCH_ASM | ||
| 245 | #define C_SWITCH_ASM | ||
| 246 | #endif | ||
| 247 | |||
| 248 | #ifdef USE_X_TOOLKIT | ||
| 249 | #define USE_@X_TOOLKIT_TYPE@ | ||
| 250 | TOOLKIT_DEFINES = -DUSE_@X_TOOLKIT_TYPE@ | ||
| 251 | #else | ||
| 252 | TOOLKIT_DEFINES = | ||
| 253 | #endif | ||
| 254 | |||
| 255 | /* DO NOT use -R. There is a special hack described in lastfile.c | ||
| 256 | which is used instead. Some initialized data areas are modified | ||
| 257 | at initial startup, then labeled as part of the text area when | ||
| 258 | Emacs is dumped for the first time, and never changed again. */ | ||
| 259 | |||
| 260 | /* -Demacs is needed to make some files produce the correct version | ||
| 261 | for use in Emacs. | ||
| 262 | |||
| 263 | -DHAVE_CONFIG_H is needed for some other files to take advantage of | ||
| 264 | the information in `config.h'. */ | ||
| 265 | |||
| 266 | /* C_SWITCH_X_SITE must come before C_SWITCH_X_MACHINE and C_SWITCH_X_SYSTEM | ||
| 267 | since it may have -I options that should override those two. */ | ||
| 268 | ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(TOOLKIT_DEFINES) $(MYCPPFLAG) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_SITE C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM ${CFLAGS} | ||
| 269 | .c.o: | ||
| 270 | $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $< | ||
| 271 | |||
| 272 | #ifndef LIBX10_MACHINE | ||
| 273 | #define LIBX10_MACHINE | ||
| 274 | #endif | ||
| 275 | |||
| 276 | #ifndef LIBX11_MACHINE | ||
| 277 | #define LIBX11_MACHINE | ||
| 278 | #endif | ||
| 279 | |||
| 280 | #ifndef LIBX10_SYSTEM | ||
| 281 | #define LIBX10_SYSTEM | ||
| 282 | #endif | ||
| 283 | |||
| 284 | #ifndef LIBX11_SYSTEM | ||
| 285 | #define LIBX11_SYSTEM | ||
| 286 | #endif | ||
| 287 | |||
| 288 | #ifndef LIB_X11_LIB | ||
| 289 | #define LIB_X11_LIB -lX11 | ||
| 290 | #endif | ||
| 291 | |||
| 292 | #ifdef HAVE_X_WINDOWS | ||
| 293 | #ifdef HAVE_MENUS | ||
| 294 | |||
| 295 | /* Include xmenu.o in the list of X object files. */ | ||
| 296 | XOBJ= xterm.o xfns.o xselect.o xrdb.o fontset.o | ||
| 297 | |||
| 298 | /* The X Menu stuff is present in the X10 distribution, but missing | ||
| 299 | from X11. If we have X10, just use the installed library; | ||
| 300 | otherwise, use our own copy. */ | ||
| 301 | #ifdef HAVE_X11 | ||
| 302 | #ifdef USE_X_TOOLKIT | ||
| 303 | OLDXMENU=${lwlibdir}liblw.a | ||
| 304 | LIBXMENU= $(OLDXMENU) | ||
| 305 | #else /* not USE_X_TOOLKIT */ | ||
| 306 | OLDXMENU= ${oldXMenudir}libXMenu11.a | ||
| 307 | LIBXMENU= $(OLDXMENU) | ||
| 308 | #endif /* not USE_X_TOOLKIT */ | ||
| 309 | #else /* not HAVE_X11 */ | ||
| 310 | LIBXMENU= -lXMenu | ||
| 311 | #endif /* not HAVE_X11 */ | ||
| 312 | |||
| 313 | #else /* not HAVE_MENUS */ | ||
| 314 | |||
| 315 | /* Otherwise, omit xmenu.o from the list of X object files, and | ||
| 316 | don't worry about the menu library at all. */ | ||
| 317 | XOBJ= xterm.o xfns.o xselect.o xrdb.o fontset.o | ||
| 318 | LIBXMENU= | ||
| 319 | #endif /* not HAVE_MENUS */ | ||
| 320 | |||
| 321 | #ifdef USE_X_TOOLKIT | ||
| 322 | #define @X_TOOLKIT_TYPE@ | ||
| 323 | #if defined (LUCID) || defined (ATHENA) | ||
| 324 | #if HAVE_XAW3D | ||
| 325 | LIBW= -lXaw3d | ||
| 326 | #else | ||
| 327 | LIBW= -lXaw | ||
| 328 | #endif | ||
| 329 | #endif | ||
| 330 | #ifdef MOTIF | ||
| 331 | #if defined (HAVE_MOTIF_2_1) && defined (HAVE_LIBXP) | ||
| 332 | #define LIB_MOTIF_EXTRA -lXp | ||
| 333 | #else | ||
| 334 | #define LIB_MOTIF_EXTRA | ||
| 335 | #endif | ||
| 336 | #ifdef LIB_MOTIF | ||
| 337 | LIBW= LIB_MOTIF LIB_MOTIF_EXTRA | ||
| 338 | #else | ||
| 339 | LIBW= -lXm LIB_MOTIF_EXTRA | ||
| 340 | #endif | ||
| 341 | #endif | ||
| 342 | #ifdef OPEN_LOOK | ||
| 343 | LIBW= -lXol | ||
| 344 | #endif | ||
| 345 | |||
| 346 | #ifdef HAVE_X11XTR6 | ||
| 347 | #ifdef NEED_LIBW | ||
| 348 | LIBXTR6 = -lSM -lICE -lw | ||
| 349 | #else | ||
| 350 | LIBXTR6 = -lSM -lICE | ||
| 351 | #endif | ||
| 352 | #endif | ||
| 353 | |||
| 354 | #ifndef LIBXMU | ||
| 355 | #define LIBXMU -lXmu | ||
| 356 | #endif | ||
| 357 | |||
| 358 | #ifdef LIBXT_STATIC | ||
| 359 | /* We assume the config files have defined STATIC_OPTION | ||
| 360 | since that might depend on the operating system. | ||
| 361 | (Don't forget you need different definitions with and without __GNUC__.) */ | ||
| 362 | LIBXT= STATIC_OPTION $(LIBW) LIBXMU -lXt $(LIBXTR6) -lXext DYNAMIC_OPTION | ||
| 363 | #else /* not LIBXT_STATIC */ | ||
| 364 | LIBXT= $(LIBW) LIBXMU -lXt $(LIBXTR6) -lXext | ||
| 365 | #endif /* not LIBXT_STATIC */ | ||
| 366 | |||
| 367 | #else /* not USE_X_TOOLKIT */ | ||
| 368 | LIBXT= | ||
| 369 | #endif /* not USE_X_TOOLKIT */ | ||
| 370 | |||
| 371 | #if HAVE_XPM | ||
| 372 | #ifndef LIBXPM | ||
| 373 | #define LIBXPM -lXpm | ||
| 374 | #endif /* not defined LIBXPM */ | ||
| 375 | #else /* not HAVE_XPM */ | ||
| 376 | #define LIBXPM | ||
| 377 | #endif /* not HAVE_XPM */ | ||
| 378 | |||
| 379 | #if HAVE_JPEG | ||
| 380 | #ifndef LIBJPEG | ||
| 381 | #define LIBJPEG -ljpeg | ||
| 382 | #endif /* not defined LIBJPEG */ | ||
| 383 | #else /* not HAVE_JPEG */ | ||
| 384 | #define LIBJPEG | ||
| 385 | #endif /* not HAVE_JPEG */ | ||
| 386 | |||
| 387 | #if HAVE_PNG | ||
| 388 | #ifndef LIBPNG | ||
| 389 | #define LIBPNG -lpng -lz -lm | ||
| 390 | #endif /* not defined LIBPNG */ | ||
| 391 | #else /* not HAVE_PNG */ | ||
| 392 | #define LIBPNG | ||
| 393 | #endif /* not HAVE_PNG */ | ||
| 394 | |||
| 395 | #if HAVE_TIFF | ||
| 396 | #ifndef LIBTIFF | ||
| 397 | #define LIBTIFF -ltiff | ||
| 398 | #endif /* not defined LIBTIFF */ | ||
| 399 | #else /* not HAVE_TIFF */ | ||
| 400 | #define LIBTIFF | ||
| 401 | #endif /* not HAVE_TIFF */ | ||
| 402 | |||
| 403 | #if HAVE_GIF | ||
| 404 | #ifndef LIBGIF | ||
| 405 | #define LIBGIF -lungif | ||
| 406 | #endif /* not defined LIBGIF */ | ||
| 407 | #else /* not HAVE_GIF */ | ||
| 408 | #define LIBGIF | ||
| 409 | #endif /* not HAVE_GIF */ | ||
| 410 | |||
| 411 | #ifdef HAVE_X11 | ||
| 412 | /* LD_SWITCH_X_DEFAULT comes after everything else that specifies | ||
| 413 | options for where to find X libraries, but before those libraries. */ | ||
| 414 | X11_LDFLAGS = LD_SWITCH_X_SITE LD_SWITCH_X_DEFAULT | ||
| 415 | LIBX= $(LIBXMENU) $(X11_LDFLAGS) $(LIBXT) LIBTIFF LIBJPEG LIBPNG LIBGIF LIBXPM LIB_X11_LIB LIBX11_MACHINE LIBX11_SYSTEM | ||
| 416 | #else /* not HAVE_X11 */ | ||
| 417 | LIBX= $(LIBXMENU) LD_SWITCH_X_SITE -lX10 LIBX10_MACHINE LIBX10_SYSTEM | ||
| 418 | #endif /* not HAVE_X11 */ | ||
| 419 | #endif /* not HAVE_X_WINDOWS */ | ||
| 420 | |||
| 421 | LIBSOUND= @LIBSOUND@ | ||
| 422 | |||
| 423 | #ifndef ORDINARY_LINK | ||
| 424 | /* Fix linking if compiled with GCC. */ | ||
| 425 | #ifdef __GNUC__ | ||
| 426 | |||
| 427 | #if __GNUC__ > 1 | ||
| 428 | |||
| 429 | #ifdef LINKER | ||
| 430 | #define LINKER_WAS_SPECIFIED | ||
| 431 | #endif | ||
| 432 | |||
| 433 | /* Versions of GCC >= 2.0 put their library, libgcc.a, in obscure | ||
| 434 | places that are difficult to figure out at make time. Fortunately, | ||
| 435 | these same versions allow you to pass arbitrary flags on to the | ||
| 436 | linker, so there's no reason not to use it as a linker. | ||
| 437 | |||
| 438 | Well, it's not quite perfect. The `-nostdlib' keeps GCC from | ||
| 439 | searching for libraries in its internal directories, so we have to | ||
| 440 | ask GCC explicitly where to find libgcc.a. */ | ||
| 441 | |||
| 442 | #ifndef LINKER | ||
| 443 | #define LINKER $(CC) -nostdlib | ||
| 444 | #endif | ||
| 445 | |||
| 446 | #ifndef LIB_GCC | ||
| 447 | /* Ask GCC where to find libgcc.a. */ | ||
| 448 | #define LIB_GCC `$(CC) -print-libgcc-file-name` | ||
| 449 | #endif /* not LIB_GCC */ | ||
| 450 | |||
| 451 | GNULIB_VAR = LIB_GCC | ||
| 452 | |||
| 453 | #ifndef LINKER_WAS_SPECIFIED | ||
| 454 | /* GCC passes any argument prefixed with -Xlinker directly to the | ||
| 455 | linker. See prefix-args.c for an explanation of why we don't do | ||
| 456 | this with the shell's `for' construct. | ||
| 457 | Note that some people don't have '.' in their paths, so we must | ||
| 458 | use ./prefix-args. */ | ||
| 459 | #define YMF_PASS_LDFLAGS(flags) `./prefix-args -Xlinker flags` | ||
| 460 | #else | ||
| 461 | #define YMF_PASS_LDFLAGS(flags) flags | ||
| 462 | #endif | ||
| 463 | |||
| 464 | #else /* __GNUC__ < 2 */ | ||
| 465 | |||
| 466 | #ifndef LIB_GCC | ||
| 467 | #define LIB_GCC /usr/local/lib/gcc-gnulib | ||
| 468 | #endif /* not LIB_GCC */ | ||
| 469 | GNULIB_VAR = `if [ -f LIB_GCC ] ; then echo LIB_GCC; else echo; fi` | ||
| 470 | #endif /* __GNUC__ < 2 */ | ||
| 471 | #else /* not __GNUC__ */ | ||
| 472 | GNULIB_VAR = | ||
| 473 | |||
| 474 | #endif /* not __GNUC__ */ | ||
| 475 | #endif /* not ORDINARY_LINK */ | ||
| 476 | |||
| 477 | /* Specify address for ld to start loading at, | ||
| 478 | if requested by configuration. */ | ||
| 479 | #ifdef LD_TEXT_START_ADDR | ||
| 480 | STARTFLAGS = -T LD_TEXT_START_ADDR -e __start | ||
| 481 | #endif | ||
| 482 | |||
| 483 | #ifdef ORDINARY_LINK | ||
| 484 | LD = $(CC) | ||
| 485 | #else | ||
| 486 | #ifdef COFF_ENCAPSULATE | ||
| 487 | LD=$(CC) -nostdlib | ||
| 488 | #else /* not ORDINARY_LINK */ | ||
| 489 | #ifdef LINKER | ||
| 490 | LD=LINKER | ||
| 491 | #else /* not LINKER */ | ||
| 492 | LD=ld | ||
| 493 | #endif /* not LINKER */ | ||
| 494 | #endif /* not COFF_ENCAPSULATE */ | ||
| 495 | #endif /* not ORDINARY_LINK */ | ||
| 496 | |||
| 497 | ALL_LDFLAGS = LD_SWITCH_SYSTEM LD_SWITCH_SYSTEM_TEMACS LD_SWITCH_MACHINE \ | ||
| 498 | LD_SWITCH_MACHINE_TEMACS LD_SWITCH_SITE $(LDFLAGS) | ||
| 499 | |||
| 500 | /* A macro which other sections of Makefile can redefine to munge the | ||
| 501 | flags before they're passed to LD. This is helpful if you have | ||
| 502 | redefined LD to something odd, like "gcc". | ||
| 503 | (The YMF prefix is a holdover from the old name "ymakefile".) | ||
| 504 | */ | ||
| 505 | #ifndef YMF_PASS_LDFLAGS | ||
| 506 | #define YMF_PASS_LDFLAGS(flags) flags | ||
| 507 | #endif | ||
| 508 | |||
| 509 | /* Allow config.h to specify a replacement file for unexec.c. */ | ||
| 510 | #ifndef UNEXEC | ||
| 511 | #define UNEXEC unexec.o | ||
| 512 | #endif | ||
| 513 | #ifndef UNEXEC_SRC | ||
| 514 | #define UNEXEC_SRC unexec.c | ||
| 515 | #endif | ||
| 516 | |||
| 517 | INTERVAL_SRC = intervals.h composite.h | ||
| 518 | |||
| 519 | GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ | ||
| 520 | |||
| 521 | #ifdef MSDOS | ||
| 522 | #ifdef HAVE_X_WINDOWS | ||
| 523 | MSDOS_OBJ = dosfns.o msdos.o | ||
| 524 | #else | ||
| 525 | MSDOS_OBJ = dosfns.o msdos.o w16select.o | ||
| 526 | #endif | ||
| 527 | #endif | ||
| 528 | |||
| 529 | |||
| 530 | /* lastfile must follow all files | ||
| 531 | whose initialized data areas should be dumped as pure by dump-emacs. */ | ||
| 532 | obj= dispnew.o frame.o scroll.o xdisp.o xmenu.o window.o \ | ||
| 533 | charset.o coding.o category.o ccl.o\ | ||
| 534 | cm.o term.o xfaces.o $(XOBJ) \ | ||
| 535 | emacs.o keyboard.o macros.o keymap.o sysdep.o \ | ||
| 536 | buffer.o filelock.o insdel.o marker.o \ | ||
| 537 | minibuf.o fileio.o dired.o filemode.o \ | ||
| 538 | cmds.o casetab.o casefiddle.o indent.o search.o regex.o undo.o \ | ||
| 539 | alloc.o data.o doc.o editfns.o callint.o \ | ||
| 540 | eval.o floatfns.o fns.o print.o lread.o \ | ||
| 541 | abbrev.o syntax.o UNEXEC mocklisp.o bytecode.o \ | ||
| 542 | process.o callproc.o \ | ||
| 543 | region-cache.o sound.o atimer.o \ | ||
| 544 | doprnt.o strftime.o intervals.o textprop.o composite.o md5.o \ | ||
| 545 | $(MSDOS_OBJ) | ||
| 546 | |||
| 547 | /* Object files used on some machine or other. | ||
| 548 | These go in the DOC file on all machines | ||
| 549 | in case they are needed there. */ | ||
| 550 | SOME_MACHINE_OBJECTS = sunfns.o dosfns.o msdos.o \ | ||
| 551 | xterm.o xfns.o xmenu.o xselect.o xrdb.o | ||
| 552 | |||
| 553 | |||
| 554 | #ifdef TERMINFO | ||
| 555 | /* Used to be -ltermcap here. If your machine needs that, | ||
| 556 | define LIBS_TERMCAP in the m/MACHINE.h file. */ | ||
| 557 | #ifndef LIBS_TERMCAP | ||
| 558 | #define LIBS_TERMCAP -lcurses | ||
| 559 | #endif /* LIBS_TERMCAP */ | ||
| 560 | termcapobj = terminfo.o | ||
| 561 | #else /* ! defined (TERMINFO) */ | ||
| 562 | #ifndef LIBS_TERMCAP | ||
| 563 | #define LIBS_TERMCAP | ||
| 564 | termcapobj = termcap.o tparam.o | ||
| 565 | #else /* LIBS_TERMCAP */ | ||
| 566 | termcapobj = tparam.o | ||
| 567 | #endif /* LIBS_TERMCAP */ | ||
| 568 | #endif /* ! defined (TERMINFO) */ | ||
| 569 | |||
| 570 | |||
| 571 | #ifndef SYSTEM_MALLOC | ||
| 572 | |||
| 573 | #ifdef DOUG_LEA_MALLOC | ||
| 574 | #ifdef REL_ALLOC | ||
| 575 | mallocobj = ralloc.o vm-limit.o | ||
| 576 | #else /* ! defined (REL_ALLOC) */ | ||
| 577 | mallocobj = vm-limit.o | ||
| 578 | #endif /* ! defined (REL_ALLOC) */ | ||
| 579 | #else /* ! defined (DOUG_LEA_MALLOC) */ | ||
| 580 | #ifdef REL_ALLOC | ||
| 581 | mallocobj = gmalloc.o ralloc.o vm-limit.o | ||
| 582 | #else /* ! defined (REL_ALLOC) */ | ||
| 583 | mallocobj = gmalloc.o vm-limit.o | ||
| 584 | #endif /* ! defined (REL_ALLOC) */ | ||
| 585 | #endif /* ! defined (DOUG_LEA_MALLOC) */ | ||
| 586 | |||
| 587 | #endif /* SYSTEM_MALLOC */ | ||
| 588 | |||
| 589 | |||
| 590 | #ifndef HAVE_ALLOCA | ||
| 591 | allocaobj = alloca.o | ||
| 592 | #else | ||
| 593 | allocaobj = | ||
| 594 | #endif | ||
| 595 | |||
| 596 | #ifdef USE_X_TOOLKIT | ||
| 597 | widgetobj= widget.o | ||
| 598 | #else /* not USE_X_TOOLKIT */ | ||
| 599 | widgetobj= | ||
| 600 | #endif /* not USE_X_TOOLKIT */ | ||
| 601 | |||
| 602 | |||
| 603 | /* define otherobj as list of object files that make-docfile | ||
| 604 | should not be told about. */ | ||
| 605 | otherobj= $(termcapobj) lastfile.o $(mallocobj) $(allocaobj) $(widgetobj) $(LIBOBJS) | ||
| 606 | |||
| 607 | #ifdef HAVE_MOUSE | ||
| 608 | #define MOUSE_SUPPORT ${lispsource}mouse.elc \ | ||
| 609 | ${lispsource}select.elc ${lispsource}scroll-bar.elc | ||
| 610 | #else | ||
| 611 | #define MOUSE_SUPPORT | ||
| 612 | #endif | ||
| 613 | |||
| 614 | #ifdef VMS | ||
| 615 | #define VMS_SUPPORT ${lispsource}vmsproc.elc ${lispsource}vms-patch.elc | ||
| 616 | #else | ||
| 617 | #define VMS_SUPPORT | ||
| 618 | #endif | ||
| 619 | |||
| 620 | #ifdef MSDOS | ||
| 621 | #define MSDOS_SUPPORT ${lispsource}ls-lisp.elc ${lispsource}disp-table.elc \ | ||
| 622 | ${lispsource}dos-fns.elc ${lispsource}dos-w32.elc ${lispsource}dos-vars.elc \ | ||
| 623 | ${lispsource}international/ccl.elc ${lispsource}international/codepage.elc | ||
| 624 | |||
| 625 | #else | ||
| 626 | #define MSDOS_SUPPORT | ||
| 627 | #endif | ||
| 628 | |||
| 629 | #ifdef WINDOWSNT | ||
| 630 | #define WINNT_SUPPORT ${lispsource}ls-lisp.elc ${lispsource}w32-fns.elc \ | ||
| 631 | ${lispsource}dos-w32.elc | ||
| 632 | #else | ||
| 633 | #define WINNT_SUPPORT | ||
| 634 | #endif | ||
| 635 | |||
| 636 | /* List of Lisp files loaded into the dumped Emacs. It's arranged | ||
| 637 | like this because it's easier to generate it semi-mechanically from | ||
| 638 | loadup.el this way. | ||
| 639 | |||
| 640 | Note that this list should not include lisp files which might not | ||
| 641 | be present, like site-load.el and site-init.el; this makefile | ||
| 642 | expects them all to be either present or buildable. | ||
| 643 | |||
| 644 | Files which are loaded unconditionally should be in shortlisp as well. | ||
| 645 | Files included conditionally here should be included (unconditionally) | ||
| 646 | in SOME_MACHINE_LISP. */ | ||
| 647 | |||
| 648 | lisp= \ | ||
| 649 | ${lispsource}abbrev.elc \ | ||
| 650 | ${lispsource}buff-menu.elc \ | ||
| 651 | ${lispsource}byte-run.elc \ | ||
| 652 | ${lispsource}cus-start.el \ | ||
| 653 | ${lispsource}custom.elc \ | ||
| 654 | ${lispsource}emacs-lisp/lisp-mode.elc \ | ||
| 655 | ${lispsource}emacs-lisp/lisp.elc \ | ||
| 656 | ${lispsource}env.elc \ | ||
| 657 | ${lispsource}faces.elc \ | ||
| 658 | ${lispsource}files.elc \ | ||
| 659 | ${lispsource}format.elc \ | ||
| 660 | ${lispsource}facemenu.elc \ | ||
| 661 | MOUSE_SUPPORT \ | ||
| 662 | ${lispsource}float-sup.elc \ | ||
| 663 | ${lispsource}frame.elc\ | ||
| 664 | ${lispsource}help.elc \ | ||
| 665 | ${lispsource}indent.elc \ | ||
| 666 | ${lispsource}isearch.elc \ | ||
| 667 | ${lispsource}loadup.el \ | ||
| 668 | ${lispsource}loaddefs.el \ | ||
| 669 | ${lispsource}bindings.el \ | ||
| 670 | ${lispsource}map-ynp.elc \ | ||
| 671 | ${lispsource}menu-bar.elc \ | ||
| 672 | ${lispsource}international/mule.elc \ | ||
| 673 | ${lispsource}international/mule-conf.el \ | ||
| 674 | ${lispsource}international/mule-cmds.elc \ | ||
| 675 | ${lispsource}international/characters.elc \ | ||
| 676 | ${lispsource}international/utf-8.elc \ | ||
| 677 | ${lispsource}case-table.elc \ | ||
| 678 | ${lispsource}language/chinese.elc \ | ||
| 679 | ${lispsource}language/cyrillic.elc \ | ||
| 680 | ${lispsource}language/indian.elc \ | ||
| 681 | ${lispsource}language/devanagari.elc \ | ||
| 682 | ${lispsource}language/english.elc \ | ||
| 683 | ${lispsource}language/ethiopic.elc \ | ||
| 684 | ${lispsource}language/european.elc \ | ||
| 685 | ${lispsource}language/czech.elc \ | ||
| 686 | ${lispsource}language/slovak.elc \ | ||
| 687 | ${lispsource}language/romanian.elc \ | ||
| 688 | ${lispsource}language/greek.elc \ | ||
| 689 | ${lispsource}language/hebrew.elc \ | ||
| 690 | ${lispsource}language/japanese.elc \ | ||
| 691 | ${lispsource}language/korean.elc \ | ||
| 692 | ${lispsource}language/lao.elc \ | ||
| 693 | ${lispsource}language/thai.elc \ | ||
| 694 | ${lispsource}language/tibetan.elc \ | ||
| 695 | ${lispsource}language/vietnamese.elc \ | ||
| 696 | ${lispsource}language/misc-lang.elc \ | ||
| 697 | ${lispsource}paths.el \ | ||
| 698 | ${lispsource}register.elc \ | ||
| 699 | ${lispsource}replace.elc \ | ||
| 700 | ${lispsource}simple.elc \ | ||
| 701 | ${lispsource}startup.elc \ | ||
| 702 | ${lispsource}subr.elc \ | ||
| 703 | ${lispsource}term/tty-colors.elc \ | ||
| 704 | ${lispsource}textmodes/fill.elc \ | ||
| 705 | ${lispsource}textmodes/page.elc \ | ||
| 706 | ${lispsource}textmodes/paragraphs.elc \ | ||
| 707 | ${lispsource}textmodes/text-mode.elc \ | ||
| 708 | ${lispsource}vc-hooks.elc \ | ||
| 709 | ${lispsource}ediff-hook.elc \ | ||
| 710 | VMS_SUPPORT \ | ||
| 711 | MSDOS_SUPPORT \ | ||
| 712 | WINNT_SUPPORT \ | ||
| 713 | ${lispsource}widget.elc \ | ||
| 714 | ${lispsource}window.elc \ | ||
| 715 | ${lispsource}version.el | ||
| 716 | |||
| 717 | /* These are relative file names for the Lisp files | ||
| 718 | that are loaded unconditionally. This is used in make-docfile. | ||
| 719 | It need not contain the files that are loaded conditionally | ||
| 720 | because SOME_MACHINE_LISP has those. */ | ||
| 721 | shortlisp= \ | ||
| 722 | ../lisp/abbrev.elc \ | ||
| 723 | ../lisp/buff-menu.elc \ | ||
| 724 | ../lisp/byte-run.elc \ | ||
| 725 | ../lisp/cus-start.el \ | ||
| 726 | ../lisp/custom.elc \ | ||
| 727 | ../lisp/emacs-lisp/lisp-mode.elc \ | ||
| 728 | ../lisp/emacs-lisp/lisp.elc \ | ||
| 729 | ../lisp/facemenu.elc \ | ||
| 730 | ../lisp/faces.elc \ | ||
| 731 | ../lisp/files.elc \ | ||
| 732 | ../lisp/float-sup.elc \ | ||
| 733 | ../lisp/format.elc \ | ||
| 734 | ../lisp/frame.elc \ | ||
| 735 | ../lisp/help.elc \ | ||
| 736 | ../lisp/indent.elc \ | ||
| 737 | ../lisp/isearch.elc \ | ||
| 738 | ../lisp/loadup.el \ | ||
| 739 | ../lisp/loaddefs.el \ | ||
| 740 | ../lisp/bindings.el \ | ||
| 741 | ../lisp/map-ynp.elc \ | ||
| 742 | ../lisp/international/mule.elc \ | ||
| 743 | ../lisp/international/mule-conf.el \ | ||
| 744 | ../lisp/international/mule-cmds.elc \ | ||
| 745 | ../lisp/international/characters.elc \ | ||
| 746 | ../lisp/case-table.elc \ | ||
| 747 | ../lisp/language/chinese.elc \ | ||
| 748 | ../lisp/language/cyrillic.elc \ | ||
| 749 | ../lisp/language/indian.elc \ | ||
| 750 | ../lisp/language/devanagari.elc \ | ||
| 751 | ../lisp/language/english.elc \ | ||
| 752 | ../lisp/language/ethiopic.elc \ | ||
| 753 | ../lisp/language/european.elc \ | ||
| 754 | ../lisp/language/czech.elc \ | ||
| 755 | ../lisp/language/slovak.elc \ | ||
| 756 | ../lisp/language/romanian.elc \ | ||
| 757 | ../lisp/language/greek.elc \ | ||
| 758 | ../lisp/language/hebrew.elc \ | ||
| 759 | ../lisp/language/japanese.elc \ | ||
| 760 | ../lisp/language/korean.elc \ | ||
| 761 | ../lisp/language/lao.elc \ | ||
| 762 | ../lisp/language/thai.elc \ | ||
| 763 | ../lisp/language/tibetan.elc \ | ||
| 764 | ../lisp/language/vietnamese.elc \ | ||
| 765 | ../lisp/language/misc-lang.elc \ | ||
| 766 | ../lisp/paths.el \ | ||
| 767 | ../lisp/register.elc \ | ||
| 768 | ../lisp/replace.elc \ | ||
| 769 | ../lisp/simple.elc \ | ||
| 770 | ../lisp/startup.elc \ | ||
| 771 | ../lisp/subr.elc \ | ||
| 772 | ../lisp/term/tty-colors.elc \ | ||
| 773 | ../lisp/textmodes/fill.elc \ | ||
| 774 | ../lisp/textmodes/page.elc \ | ||
| 775 | ../lisp/textmodes/paragraphs.elc \ | ||
| 776 | ../lisp/textmodes/text-mode.elc \ | ||
| 777 | ../lisp/vc-hooks.elc \ | ||
| 778 | ../lisp/ediff-hook.elc \ | ||
| 779 | ../lisp/widget.elc \ | ||
| 780 | ../lisp/window.elc \ | ||
| 781 | ../lisp/version.el | ||
| 782 | |||
| 783 | /* Lisp files that may or may not be used. | ||
| 784 | We must unconditionally put them in the DOC file. | ||
| 785 | We use ../lisp/ to start the file names | ||
| 786 | to reduce the size of the argument list for make-docfile | ||
| 787 | for the sake of systems which can't handle large ones. */ | ||
| 788 | SOME_MACHINE_LISP = ${dotdot}/lisp/menu-bar.elc ${dotdot}/lisp/mouse.elc \ | ||
| 789 | ${dotdot}/lisp/select.elc ${dotdot}/lisp/scroll-bar.elc \ | ||
| 790 | ${dotdot}/lisp/vmsproc.elc ${dotdot}/lisp/vms-patch.elc \ | ||
| 791 | ${dotdot}/lisp/ls-lisp.elc ${dotdot}/lisp/dos-fns.elc \ | ||
| 792 | ${dotdot}/lisp/w32-fns.elc ${dotdot}/lisp/dos-w32.elc \ | ||
| 793 | ${dotdot}/lisp/disp-table.elc ${dotdot}/lisp/dos-vars.elc \ | ||
| 794 | ${dotdot}/lisp/international/ccl.elc \ | ||
| 795 | ${dotdot}/lisp/international/codepage.elc | ||
| 796 | |||
| 797 | /* Construct full set of libraries to be linked. | ||
| 798 | Note that SunOS needs -lm to come before -lc; otherwise, you get | ||
| 799 | duplicated symbols. If the standard libraries were compiled | ||
| 800 | with GCC, we might need gnulib again after them. */ | ||
| 801 | LIBES = $(LOADLIBES) $(LIBS) $(LIBX) $(LIBSOUND) \ | ||
| 802 | LIBS_SYSTEM LIBS_MACHINE LIBS_TERMCAP \ | ||
| 803 | LIBS_DEBUG $(GETLOADAVG_LIBS) $(GNULIB_VAR) LIB_MATH LIB_STANDARD \ | ||
| 804 | $(GNULIB_VAR) | ||
| 805 | |||
| 806 | /* Enable recompilation of certain other files depending on system type. */ | ||
| 807 | |||
| 808 | #ifndef OTHER_FILES | ||
| 809 | #define OTHER_FILES | ||
| 810 | #endif | ||
| 811 | |||
| 812 | #ifndef OBJECTS_MACHINE | ||
| 813 | #define OBJECTS_MACHINE | ||
| 814 | #endif | ||
| 815 | |||
| 816 | all: emacs OTHER_FILES | ||
| 817 | |||
| 818 | emacs: temacs ${etc}DOC ${lisp} | ||
| 819 | #ifdef CANNOT_DUMP | ||
| 820 | rm -f emacs | ||
| 821 | ln temacs emacs | ||
| 822 | #else | ||
| 823 | #ifdef HAVE_SHM | ||
| 824 | LC_ALL=C ./temacs -nl -batch -l loadup dump | ||
| 825 | #else /* ! defined (HAVE_SHM) */ | ||
| 826 | LC_ALL=C ./temacs -batch -l loadup dump | ||
| 827 | #endif /* ! defined (HAVE_SHM) */ | ||
| 828 | #endif /* ! defined (CANNOT_DUMP) */ | ||
| 829 | -./emacs -q -batch -f list-load-path-shadows | ||
| 830 | |||
| 831 | /* We run make-docfile twice because the command line may get too long | ||
| 832 | on some systems. */ | ||
| 833 | /* ${SOME_MACHINE_OBJECTS} comes before ${obj} because some files may | ||
| 834 | or may not be included in ${obj}, but they are always included in | ||
| 835 | ${SOME_MACHINE_OBJECTS}. Since a file is processed when it is mentioned | ||
| 836 | for the first time, this prevents any variation between configurations | ||
| 837 | in the contents of the DOC file. | ||
| 838 | Likewise for ${SOME_MACHINE_LISP}. */ | ||
| 839 | ${etc}DOC: ${libsrc}make-docfile ${obj} ${shortlisp} ${SOME_MACHINE_LISP} | ||
| 840 | -rm -f ${etc}DOC | ||
| 841 | ${libsrc}make-docfile -d ${srcdir} ${SOME_MACHINE_OBJECTS} ${obj} > ${etc}DOC | ||
| 842 | ${libsrc}make-docfile -a ${etc}DOC -d ${srcdir} ${SOME_MACHINE_LISP} ${shortlisp} | ||
| 843 | |||
| 844 | ${libsrc}make-docfile: | ||
| 845 | cd ${libsrc}; ${MAKE} ${MFLAGS} make-docfile | ||
| 846 | |||
| 847 | /* Some systems define this to cause parallel Make-ing. */ | ||
| 848 | #ifndef MAKE_PARALLEL | ||
| 849 | #define MAKE_PARALLEL | ||
| 850 | #endif | ||
| 851 | |||
| 852 | temacs: MAKE_PARALLEL $(LOCALCPP) $(STARTFILES) stamp-oldxmenu ${obj} ${otherobj} OBJECTS_MACHINE prefix-args | ||
| 853 | $(LD) YMF_PASS_LDFLAGS (${STARTFLAGS} ${ALL_LDFLAGS}) \ | ||
| 854 | -o temacs ${STARTFILES} ${obj} ${otherobj} \ | ||
| 855 | OBJECTS_MACHINE ${LIBES} | ||
| 856 | |||
| 857 | /* We don't use ALL_LDFLAGS because LD_SWITCH_SYSTEM and LD_SWITCH_MACHINE | ||
| 858 | often contain options that have to do with using Emacs's crt0, | ||
| 859 | which are only good with temacs. */ | ||
| 860 | prefix-args: prefix-args.c $(config_h) | ||
| 861 | $(CC) $(ALL_CFLAGS) $(LDFLAGS) ${srcdir}/prefix-args.c -o prefix-args | ||
| 862 | |||
| 863 | /* Don't lose if this was not defined. */ | ||
| 864 | #ifndef OLDXMENU_OPTIONS | ||
| 865 | #define OLDXMENU_OPTIONS | ||
| 866 | #endif | ||
| 867 | |||
| 868 | /* Don't lose if this was not defined. */ | ||
| 869 | #ifndef LWLIB_OPTIONS | ||
| 870 | #define LWLIB_OPTIONS | ||
| 871 | #endif | ||
| 872 | |||
| 873 | #if defined (HAVE_X_WINDOWS) && defined (HAVE_X11) && defined (HAVE_MENUS) | ||
| 874 | |||
| 875 | /* We use stamp-xmenu with these two deps | ||
| 876 | to both ensure that lwlib gets remade based on its dependencies | ||
| 877 | in its own makefile, | ||
| 878 | and remake temacs if lwlib gets changed by this. */ | ||
| 879 | stamp-oldxmenu: ${OLDXMENU} ../src/$(OLDXMENU) | ||
| 880 | touch stamp-oldxmenu | ||
| 881 | /* Supply an ordering for parallel make. */ | ||
| 882 | ../src/$(OLDXMENU): ${OLDXMENU} | ||
| 883 | |||
| 884 | #ifdef USE_X_TOOLKIT | ||
| 885 | $(OLDXMENU): really-lwlib | ||
| 886 | |||
| 887 | /* Encode the values of these two macros in Make variables, | ||
| 888 | so we can use $(...) to substitute their values within "...". */ | ||
| 889 | C_SWITCH_MACHINE_1 = C_SWITCH_MACHINE | ||
| 890 | C_SWITCH_SYSTEM_1 = C_SWITCH_SYSTEM | ||
| 891 | C_SWITCH_SITE_1 = C_SWITCH_SITE | ||
| 892 | C_SWITCH_X_SITE_1 = C_SWITCH_X_SITE | ||
| 893 | C_SWITCH_X_MACHINE_1 = C_SWITCH_X_MACHINE | ||
| 894 | C_SWITCH_X_SYSTEM_1 = C_SWITCH_X_SYSTEM | ||
| 895 | really-lwlib: | ||
| 896 | cd ${lwlibdir}; ${MAKE} ${MFLAGS} LWLIB_OPTIONS \ | ||
| 897 | CC='${CC}' CFLAGS='${CFLAGS}' MAKE='${MAKE}' \ | ||
| 898 | "C_SWITCH_X_SITE=$(C_SWITCH_X_SITE_1)" \ | ||
| 899 | "C_SWITCH_X_MACHINE=$(C_SWITCH_X_MACHINE_1)" \ | ||
| 900 | "C_SWITCH_X_SYSTEM=$(C_SWITCH_X_SYSTEM_1)" \ | ||
| 901 | "C_SWITCH_SITE=$(C_SWITCH_SITE_1)" \ | ||
| 902 | "C_SWITCH_MACHINE=$(C_SWITCH_MACHINE_1)" \ | ||
| 903 | "C_SWITCH_SYSTEM=$(C_SWITCH_SYSTEM_1)" | ||
| 904 | @true /* make -t should not create really-lwlib. */ | ||
| 905 | .PHONY: really-lwlib | ||
| 906 | #else /* not USE_X_TOOLKIT */ | ||
| 907 | $(OLDXMENU): really-oldXMenu | ||
| 908 | |||
| 909 | /* Encode the values of these two macros in Make variables, | ||
| 910 | so we can use $(...) to substitute their values within "...". */ | ||
| 911 | C_SWITCH_MACHINE_1 = C_SWITCH_MACHINE | ||
| 912 | C_SWITCH_SYSTEM_1 = C_SWITCH_SYSTEM | ||
| 913 | C_SWITCH_SITE_1 = C_SWITCH_SITE | ||
| 914 | C_SWITCH_X_SITE_1 = C_SWITCH_X_SITE | ||
| 915 | C_SWITCH_X_MACHINE_1 = C_SWITCH_X_MACHINE | ||
| 916 | C_SWITCH_X_SYSTEM_1 = C_SWITCH_X_SYSTEM | ||
| 917 | really-oldXMenu: | ||
| 918 | cd ${oldXMenudir}; ${MAKE} ${MFLAGS} OLDXMENU_OPTIONS \ | ||
| 919 | CC='${CC}' CFLAGS='${CFLAGS}' MAKE='${MAKE}' \ | ||
| 920 | "C_SWITCH_X_SITE=$(C_SWITCH_X_SITE_1)" \ | ||
| 921 | "C_SWITCH_X_MACHINE=$(C_SWITCH_X_MACHINE_1)" \ | ||
| 922 | "C_SWITCH_X_SYSTEM=$(C_SWITCH_X_SYSTEM_1)" \ | ||
| 923 | "C_SWITCH_SITE=$(C_SWITCH_SITE_1)" \ | ||
| 924 | "C_SWITCH_MACHINE=$(C_SWITCH_MACHINE_1)" \ | ||
| 925 | "C_SWITCH_SYSTEM=$(C_SWITCH_SYSTEM_1)" | ||
| 926 | @true /* make -t should not create really-oldXMenu. */ | ||
| 927 | .PHONY: really-oldXMenu | ||
| 928 | #endif /* not USE_X_TOOLKIT */ | ||
| 929 | #else /* not (HAVE_X_WINDOWS && HAVE_X11 && HAVE_MENUS) */ | ||
| 930 | |||
| 931 | /* We don't really need this, but satisfy the dependency. */ | ||
| 932 | stamp-oldxmenu: | ||
| 933 | touch stamp-oldxmenu | ||
| 934 | #endif /* not (HAVE_X_WINDOWS && HAVE_X11 && HAVE_MENUS) */ | ||
| 935 | |||
| 936 | ../config.status:: epaths.in | ||
| 937 | @echo "The file epaths.h needs to be set up from epaths.in." | ||
| 938 | @echo "Please run the `configure' script again." | ||
| 939 | exit 1 | ||
| 940 | |||
| 941 | ../config.status:: config.in | ||
| 942 | @echo "The file config.h needs to be set up from config.in." | ||
| 943 | @echo "Please run the `configure' script again." | ||
| 944 | exit 1 | ||
| 945 | |||
| 946 | /* Some machines have alloca built-in. | ||
| 947 | They should define HAVE_ALLOCA, or may just let alloca.s | ||
| 948 | be used but generate no code. | ||
| 949 | Some have it written in assembler in alloca.s. | ||
| 950 | Some use the C version in alloca.c (these define C_ALLOCA in config.h). | ||
| 951 | */ | ||
| 952 | |||
| 953 | #ifdef C_ALLOCA | ||
| 954 | /* We could put something in alloca.c to #define free and malloc | ||
| 955 | whenever emacs was #defined, but that's not appropriate for all | ||
| 956 | users of alloca in Emacs. Check out ../lib-src/getopt.c. */ | ||
| 957 | alloca.o : alloca.c | ||
| 958 | $(CC) -c $(CPPFLAGS) -DEMACS_FREE=xfree \ | ||
| 959 | $(ALL_CFLAGS) ${srcdir}/alloca.c | ||
| 960 | #else | ||
| 961 | #ifndef HAVE_ALLOCA | ||
| 962 | alloca.o : alloca.s $(config_h) | ||
| 963 | /* $(CPP) is cc -E, which may get confused by filenames | ||
| 964 | that do not end in .c. So copy file to a safe name. */ | ||
| 965 | -rm -f allocatem.c | ||
| 966 | cp ${srcdir}/alloca.s allocatem.c | ||
| 967 | /* Remove any ^L, blank lines, and preprocessor comments, | ||
| 968 | since some assemblers barf on them. Use a different basename for the | ||
| 969 | output file, since some stupid compilers (Green Hill's) use that | ||
| 970 | name for the intermediate assembler file. */ | ||
| 971 | $(CPP) $(CPPFLAGS) $(ALL_CFLAGS) allocatem.c | \ | ||
| 972 | sed -e 's///' -e 's/^#.*//' | \ | ||
| 973 | sed -n -e '/^..*$$/p' > allocax.s | ||
| 974 | -rm -f alloca.o | ||
| 975 | /* Xenix, in particular, needs to run assembler via cc. */ | ||
| 976 | $(CC) -c allocax.s | ||
| 977 | mv allocax.o alloca.o | ||
| 978 | -rm -f allocax.s allocatem.c | ||
| 979 | #endif /* HAVE_ALLOCA */ | ||
| 980 | #endif /* ! defined (C_ALLOCA) */ | ||
| 981 | |||
| 982 | /* Nearly all the following files depend on lisp.h, | ||
| 983 | but it is not included as a dependency because | ||
| 984 | it is so often changed in ways that do not require any recompilation | ||
| 985 | and so rarely changed in ways that do require any. */ | ||
| 986 | |||
| 987 | abbrev.o: abbrev.c buffer.h window.h dispextern.h commands.h charset.h \ | ||
| 988 | $(config_h) | ||
| 989 | buffer.o: buffer.c buffer.h region-cache.h commands.h window.h \ | ||
| 990 | dispextern.h $(INTERVAL_SRC) blockinput.h atimer.h systime.h charset.h \ | ||
| 991 | $(config_h) | ||
| 992 | callint.o: callint.c window.h commands.h buffer.h mocklisp.h \ | ||
| 993 | keyboard.h dispextern.h $(config_h) | ||
| 994 | callproc.o: callproc.c epaths.h buffer.h commands.h $(config_h) \ | ||
| 995 | process.h systty.h syssignal.h charset.h coding.h ccl.h msdos.h \ | ||
| 996 | composite.h | ||
| 997 | casefiddle.o: casefiddle.c syntax.h commands.h buffer.h composite.h $(config_h) | ||
| 998 | casetab.o: casetab.c buffer.h $(config_h) | ||
| 999 | category.o: category.c category.h buffer.h charset.h $(config_h) | ||
| 1000 | ccl.o: ccl.c ccl.h charset.h coding.h $(config_h) | ||
| 1001 | charset.o: charset.c charset.h buffer.h coding.h composite.h disptab.h \ | ||
| 1002 | $(config_h) | ||
| 1003 | coding.o: coding.c coding.h ccl.h buffer.h charset.h $(config_h) | ||
| 1004 | cm.o: cm.c cm.h termhooks.h $(config_h) | ||
| 1005 | cmds.o: cmds.c syntax.h buffer.h charset.h commands.h window.h $(config_h) \ | ||
| 1006 | msdos.h dispextern.h | ||
| 1007 | pre-crt0.o: pre-crt0.c | ||
| 1008 | ecrt0.o: ecrt0.c $(config_h) | ||
| 1009 | CRT0_COMPILE ${srcdir}/ecrt0.c | ||
| 1010 | dired.o: dired.c commands.h buffer.h $(config_h) charset.h coding.h regex.h \ | ||
| 1011 | systime.h | ||
| 1012 | dispnew.o: dispnew.c commands.h frame.h window.h buffer.h dispextern.h \ | ||
| 1013 | termchar.h termopts.h termhooks.h cm.h disptab.h systty.h systime.h \ | ||
| 1014 | xterm.h blockinput.h atimer.h charset.h msdos.h composite.h keyboard.h \ | ||
| 1015 | $(config_h) | ||
| 1016 | doc.o: doc.c $(config_h) epaths.h buffer.h keyboard.h charset.h | ||
| 1017 | doprnt.o: doprnt.c charset.h $(config_h) | ||
| 1018 | dosfns.o: buffer.h termchar.h termhooks.h frame.h msdos.h dosfns.h $(config_h) | ||
| 1019 | editfns.o: editfns.c window.h buffer.h systime.h $(INTERVAL_SRC) charset.h \ | ||
| 1020 | coding.h dispextern.h $(config_h) | ||
| 1021 | emacs.o: emacs.c commands.h systty.h syssignal.h blockinput.h process.h \ | ||
| 1022 | termhooks.h buffer.h atimer.h systime.h $(INTERVAL_SRC) $(config_h) | ||
| 1023 | fileio.o: fileio.c window.h buffer.h systime.h $(INTERVAL_SRC) charset.h \ | ||
| 1024 | coding.h ccl.h msdos.h dispextern.h $(config_h) | ||
| 1025 | filelock.o: filelock.c buffer.h systime.h epaths.h $(config_h) | ||
| 1026 | filemode.o: filemode.c $(config_h) | ||
| 1027 | frame.o: frame.c xterm.h window.h frame.h termhooks.h commands.h keyboard.h \ | ||
| 1028 | buffer.h charset.h fontset.h msdos.h dosfns.h dispextern.h $(config_h) | ||
| 1029 | fontset.o: dispextern.h fontset.h fontset.c ccl.h charset.h frame.h \ | ||
| 1030 | keyboard.h $(config_h) | ||
| 1031 | getloadavg.o: getloadavg.c $(config_h) | ||
| 1032 | indent.o: indent.c frame.h window.h indent.h buffer.h $(config_h) termchar.h \ | ||
| 1033 | termopts.h disptab.h region-cache.h charset.h composite.h dispextern.h \ | ||
| 1034 | keyboard.h | ||
| 1035 | insdel.o: insdel.c window.h buffer.h $(INTERVAL_SRC) blockinput.h charset.h\ | ||
| 1036 | dispextern.h atimer.h systime.h $(config_h) | ||
| 1037 | keyboard.o: keyboard.c termchar.h termhooks.h termopts.h buffer.h charset.h \ | ||
| 1038 | commands.h frame.h window.h macros.h disptab.h keyboard.h syssignal.h \ | ||
| 1039 | systty.h systime.h dispextern.h syntax.h $(INTERVAL_SRC) blockinput.h \ | ||
| 1040 | atimer.h xterm.h puresize.h msdos.h $(config_h) | ||
| 1041 | keymap.o: keymap.c buffer.h commands.h keyboard.h termhooks.h blockinput.h \ | ||
| 1042 | atimer.h systime.h puresize.h charset.h intervals.h $(config_h) | ||
| 1043 | lastfile.o: lastfile.c $(config_h) | ||
| 1044 | macros.o: macros.c window.h buffer.h commands.h macros.h keyboard.h \ | ||
| 1045 | dispextern.h $(config_h) | ||
| 1046 | malloc.o: malloc.c $(config_h) | ||
| 1047 | gmalloc.o: gmalloc.c $(config_h) | ||
| 1048 | ralloc.o: ralloc.c $(config_h) | ||
| 1049 | vm-limit.o: vm-limit.c mem-limits.h $(config_h) | ||
| 1050 | marker.o: marker.c buffer.h charset.h $(config_h) | ||
| 1051 | minibuf.o: minibuf.c syntax.h dispextern.h frame.h window.h keyboard.h \ | ||
| 1052 | buffer.h commands.h charset.h msdos.h $(config_h) | ||
| 1053 | mktime.o: mktime.c $(config_h) | ||
| 1054 | mocklisp.o: mocklisp.c buffer.h $(config_h) | ||
| 1055 | msdos.o: msdos.c msdos.h dosfns.h systime.h termhooks.h dispextern.h frame.h \ | ||
| 1056 | termopts.h termchar.h charset.h coding.h ccl.h disptab.h window.h \ | ||
| 1057 | keyboard.h $(config_h) | ||
| 1058 | process.o: process.c process.h buffer.h window.h termhooks.h termopts.h \ | ||
| 1059 | commands.h syssignal.h systime.h systty.h syswait.h frame.h dispextern.h \ | ||
| 1060 | blockinput.h atimer.h charset.h coding.h ccl.h msdos.h composite.h \ | ||
| 1061 | keyboard.h $(config_h) | ||
| 1062 | regex.o: regex.c syntax.h buffer.h $(config_h) regex.h category.h charset.h | ||
| 1063 | region-cache.o: region-cache.c buffer.h region-cache.h | ||
| 1064 | scroll.o: scroll.c termchar.h dispextern.h frame.h msdos.h keyboard.h \ | ||
| 1065 | $(config_h) | ||
| 1066 | search.o: search.c regex.h commands.h buffer.h region-cache.h syntax.h \ | ||
| 1067 | blockinput.h atimer.h systime.h category.h charset.h composite.h $(config_h) | ||
| 1068 | strftime.o: strftime.c $(config_h) | ||
| 1069 | syntax.o: syntax.c syntax.h buffer.h commands.h category.h charset.h \ | ||
| 1070 | composite.h $(config_h) | ||
| 1071 | sysdep.o: sysdep.c $(config_h) dispextern.h termhooks.h termchar.h termopts.h \ | ||
| 1072 | frame.h syssignal.h systty.h systime.h syswait.h blockinput.h atimer.h \ | ||
| 1073 | window.h msdos.h dosfns.h keyboard.h | ||
| 1074 | term.o: term.c termchar.h termhooks.h termopts.h $(config_h) cm.h frame.h \ | ||
| 1075 | disptab.h dispextern.h keyboard.h charset.h coding.h ccl.h msdos.h | ||
| 1076 | termcap.o: termcap.c $(config_h) | ||
| 1077 | terminfo.o: terminfo.c $(config_h) | ||
| 1078 | tparam.o: tparam.c $(config_h) | ||
| 1079 | undo.o: undo.c buffer.h commands.h $(config_h) | ||
| 1080 | /* This hack is to discard any space that cpp might put at the beginning | ||
| 1081 | of UNEXEC when substituting it in. */ | ||
| 1082 | UNEXEC_ALIAS=UNEXEC | ||
| 1083 | $(UNEXEC_ALIAS): UNEXEC_SRC $(config_h) | ||
| 1084 | w16select.o: w16select.c dispextern.h frame.h blockinput.h atimer.h systime.h \ | ||
| 1085 | msdos.h $(config_h) | ||
| 1086 | widget.o: widget.c xterm.h frame.h dispextern.h widgetprv.h \ | ||
| 1087 | $(srcdir)/../lwlib/lwlib.h $(config_h) | ||
| 1088 | window.o: window.c indent.h commands.h frame.h window.h buffer.h termchar.h \ | ||
| 1089 | termhooks.h disptab.h keyboard.h dispextern.h msdos.h composite.h \ | ||
| 1090 | $(config_h) | ||
| 1091 | xdisp.o: xdisp.c macros.h commands.h indent.h buffer.h dispextern.h coding.h \ | ||
| 1092 | termchar.h frame.h window.h disptab.h termhooks.h charset.h $(config_h) \ | ||
| 1093 | msdos.h composite.h fontset.h | ||
| 1094 | xfaces.o: xfaces.c dispextern.h frame.h xterm.h buffer.h blockinput.h \ | ||
| 1095 | window.h charset.h msdos.h dosfns.h composite.h atimer.h systime.h $(config_h) | ||
| 1096 | xfns.o: xfns.c buffer.h frame.h window.h keyboard.h xterm.h dispextern.h \ | ||
| 1097 | $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h epaths.h \ | ||
| 1098 | charset.h $(config_h) | ||
| 1099 | xmenu.o: xmenu.c xterm.h termhooks.h window.h dispextern.h frame.h keyboard.h \ | ||
| 1100 | $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h msdos.h \ | ||
| 1101 | $(config_h) | ||
| 1102 | xterm.o: xterm.c xterm.h termhooks.h termopts.h termchar.h window.h \ | ||
| 1103 | dispextern.h frame.h disptab.h blockinput.h atimer.h systime.h syssignal.h \ | ||
| 1104 | keyboard.h gnu.h sink.h sinkmask.h charset.h ccl.h fontset.h composite.h \ | ||
| 1105 | coding.h $(config_h) | ||
| 1106 | xselect.o: xselect.c dispextern.h frame.h xterm.h blockinput.h charset.h \ | ||
| 1107 | coding.h ccl.h buffer.h atimer.h systime.h $(config_h) | ||
| 1108 | xrdb.o: xrdb.c $(config_h) epaths.h | ||
| 1109 | hftctl.o: hftctl.c $(config_h) | ||
| 1110 | sound.o: sound.c dispextern.h $(config_h) | ||
| 1111 | atimer.o: atimer.c atimer.h systime.h $(config_h) | ||
| 1112 | |||
| 1113 | /* The files of Lisp proper */ | ||
| 1114 | |||
| 1115 | alloc.o: alloc.c frame.h window.h buffer.h puresize.h syssignal.h keyboard.h \ | ||
| 1116 | blockinput.h atimer.h systime.h charset.h dispextern.h $(config_h) $(INTERVAL_SRC) | ||
| 1117 | bytecode.o: bytecode.c buffer.h syntax.h charset.h $(config_h) | ||
| 1118 | data.o: data.c buffer.h puresize.h charset.h syssignal.h keyboard.h $(config_h) | ||
| 1119 | eval.o: eval.c commands.h keyboard.h blockinput.h atimer.h systime.h \ | ||
| 1120 | $(config_h) | ||
| 1121 | floatfns.o: floatfns.c $(config_h) | ||
| 1122 | fns.o: fns.c commands.h $(config_h) frame.h buffer.h charset.h keyboard.h \ | ||
| 1123 | frame.h window.h dispextern.h $(INTERVAL_SRC) | ||
| 1124 | print.o: print.c process.h frame.h window.h buffer.h keyboard.h charset.h\ | ||
| 1125 | $(config_h) dispextern.h msdos.h composite.h | ||
| 1126 | lread.o: lread.c commands.h keyboard.h buffer.h epaths.h charset.h $(config_h) \ | ||
| 1127 | termhooks.h msdos.h | ||
| 1128 | |||
| 1129 | /* Text properties support */ | ||
| 1130 | textprop.o: textprop.c buffer.h window.h dispextern.h $(INTERVAL_SRC) \ | ||
| 1131 | $(config_h) | ||
| 1132 | intervals.o: intervals.c buffer.h $(INTERVAL_SRC) keyboard.h puresize.h $(config_h) | ||
| 1133 | composite.o: composite.c buffer.h charset.h $(INTERVAL_SRC) $(config_h) | ||
| 1134 | |||
| 1135 | /* System-specific programs to be made. | ||
| 1136 | OTHER_FILES and OBJECTS_MACHINE | ||
| 1137 | select which of these should be compiled. */ | ||
| 1138 | |||
| 1139 | sunfns.o: sunfns.c buffer.h window.h dispextern.h $(config_h) | ||
| 1140 | |||
| 1141 | ${libsrc}emacstool: ${libsrc}emacstool.c | ||
| 1142 | cd ${libsrc}; ${MAKE} ${MFLAGS} emacstool | ||
| 1143 | mostlyclean: | ||
| 1144 | rm -f temacs prefix-args core *.core \#* *.o libXMenu11.a liblw.a | ||
| 1145 | rm -f ../etc/DOC | ||
| 1146 | clean: mostlyclean | ||
| 1147 | rm -f emacs-* emacs bootstrap-emacs | ||
| 1148 | /**/# This is used in making a distribution. | ||
| 1149 | /**/# Do not use it on development directories! | ||
| 1150 | distclean: clean | ||
| 1151 | rm -f epaths.h config.h Makefile Makefile.c config.stamp stamp-oldxmenu ../etc/DOC-* | ||
| 1152 | maintainer-clean: distclean | ||
| 1153 | @echo "This command is intended for maintainers to use;" | ||
| 1154 | @echo "it deletes files that may require special tools to rebuild." | ||
| 1155 | rm -f TAGS | ||
| 1156 | versionclean: | ||
| 1157 | -rm -f emacs emacs-* ../etc/DOC* | ||
| 1158 | extraclean: distclean | ||
| 1159 | -rm -f *~ \#* m/?*~ s/?*~ | ||
| 1160 | |||
| 1161 | /* The rule for the [sm] files has to be written a little funny to | ||
| 1162 | avoid looking like a C comment to CPP. */ | ||
| 1163 | SOURCES = *.[ch] [sm]/?* COPYING Makefile.in \ | ||
| 1164 | config.in epaths.in README COPYING ChangeLog vms.pp-trans | ||
| 1165 | unlock: | ||
| 1166 | chmod u+w $(SOURCES) | ||
| 1167 | |||
| 1168 | relock: | ||
| 1169 | chmod -w $(SOURCES) | ||
| 1170 | chmod +w epaths.h | ||
| 1171 | |||
| 1172 | /* Arrange to make a tags table TAGS-LISP for ../lisp, | ||
| 1173 | plus TAGS for the C files, which includes ../lisp/TAGS by reference. */ | ||
| 1174 | |||
| 1175 | ctagsfiles1 = [xyzXYZ]*.[hc] | ||
| 1176 | ctagsfiles2 = [a-wA-W]*.[hc] | ||
| 1177 | |||
| 1178 | TAGS: $(srcdir)/$(ctagsfiles1) $(srcdir)/$(ctagsfiles2) | ||
| 1179 | ../lib-src/etags --include=TAGS-LISP --include=${lwlibdir}/TAGS \ | ||
| 1180 | --regex='/[ ]*DEFVAR_[A-Z_ (]+"\([^"]+\)"/' \ | ||
| 1181 | $(srcdir)/$(ctagsfiles1) $(srcdir)/$(ctagsfiles2) | ||
| 1182 | frc: | ||
| 1183 | TAGS-LISP: frc | ||
| 1184 | $(MAKE) -f ${lispsource}Makefile TAGS-LISP ETAGS=../lib-src/etags | ||
| 1185 | |||
| 1186 | $(lwlibdir)TAGS: | ||
| 1187 | (cd $(lwlibdir); $(MAKE) -f $(lwlibdir)Makefile tags ETAGS=../lib-src/etags) | ||
| 1188 | |||
| 1189 | tags: TAGS TAGS-LISP $(lwlibdir)TAGS | ||
| 1190 | .PHONY: tags | ||
| 1191 | |||
| 1192 | |||
| 1193 | /* Bootstrapping. */ | ||
| 1194 | |||
| 1195 | bootstrap: bootstrap-emacs | ||
| 1196 | |||
| 1197 | /* Build a temacs with a sufficiently large PURESIZE to load the | ||
| 1198 | Lisp files from loadup.el in source form. */ | ||
| 1199 | |||
| 1200 | bootstrap-temacs: | ||
| 1201 | LC_ALL=C $(MAKE) $(MFLAGS) temacs ALL_CFLAGS="$(ALL_CFLAGS) -DPURESIZE=5000000 -I../src" | ||
| 1202 | |||
| 1203 | /* Build a DOC file. */ | ||
| 1204 | |||
| 1205 | bootstrap-doc: ${libsrc}make-docfile | ||
| 1206 | -rm -f ${etc}DOC | ||
| 1207 | els=`echo ${shortlisp} ${SOME_MACHINE_LISP} \ | ||
| 1208 | | sed -e "s/\\.elc/.el/g"`; \ | ||
| 1209 | ${libsrc}make-docfile -d ${srcdir} $$els ${obj} > ${etc}DOC | ||
| 1210 | |||
| 1211 | /* Dump an Emacs executable named bootstrap-emacs containing the | ||
| 1212 | files from loadup.el in source form. */ | ||
| 1213 | |||
| 1214 | bootstrap-emacs: bootstrap-temacs bootstrap-doc | ||
| 1215 | #ifdef CANNOT_DUMP | ||
| 1216 | ln temacs bootstrap-emacs | ||
| 1217 | #else | ||
| 1218 | #ifdef HAVE_SHM | ||
| 1219 | ./temacs -nl -batch -l loadup bootstrap | ||
| 1220 | #else /* ! defined (HAVE_SHM) */ | ||
| 1221 | ./temacs --batch --load loadup bootstrap | ||
| 1222 | #endif /* ! defined (HAVE_SHM) */ | ||
| 1223 | #endif /* ! defined (CANNOT_DUMP) */ | ||
| 1224 | mv -f emacs bootstrap-emacs | ||
| 1225 | rm -f temacs | ||
| 1226 | |||
diff --git a/src/XTests.c b/src/XTests.c deleted file mode 100644 index 4147ecd35d6..00000000000 --- a/src/XTests.c +++ /dev/null | |||
| @@ -1,179 +0,0 @@ | |||
| 1 | #include <X11/Xlib.h> | ||
| 2 | #include <X11/X.h> | ||
| 3 | #include <X11/Xutil.h> | ||
| 4 | #include <X11/Xresource.h> | ||
| 5 | #include "XTests.h" | ||
| 6 | #include <stdio.h> | ||
| 7 | |||
| 8 | static Display *dpy; | ||
| 9 | |||
| 10 | static void | ||
| 11 | quit (dpy) | ||
| 12 | Display *dpy; | ||
| 13 | { | ||
| 14 | XCloseDisplay (dpy); | ||
| 15 | exit (0); | ||
| 16 | } | ||
| 17 | |||
| 18 | static Colormap screen_colormap; | ||
| 19 | |||
| 20 | static unsigned long | ||
| 21 | obtain_color (color) | ||
| 22 | char *color; | ||
| 23 | { | ||
| 24 | int exists; | ||
| 25 | XColor color_def; | ||
| 26 | |||
| 27 | if (!screen_colormap) | ||
| 28 | screen_colormap = DefaultColormap (dpy, DefaultScreen (dpy)); | ||
| 29 | |||
| 30 | exists = XParseColor (dpy, screen_colormap, color, &color_def) | ||
| 31 | && XAllocColor (dpy, screen_colormap, &color_def); | ||
| 32 | if (exists) | ||
| 33 | return color_def.pixel; | ||
| 34 | |||
| 35 | fprintf (stderr, "Can't get color; using black."); | ||
| 36 | return BlackPixel (dpy, DefaultScreen (dpy)); | ||
| 37 | } | ||
| 38 | |||
| 39 | static char *visual_strings[] = | ||
| 40 | { | ||
| 41 | "StaticGray ", | ||
| 42 | "GrayScale ", | ||
| 43 | "StaticColor", | ||
| 44 | "PseudoColor", | ||
| 45 | "TrueColor ", | ||
| 46 | "DirectColor" | ||
| 47 | }; | ||
| 48 | |||
| 49 | main (argc,argv) | ||
| 50 | int argc; | ||
| 51 | char *argv[]; | ||
| 52 | { | ||
| 53 | char *dpy_string; | ||
| 54 | int n; | ||
| 55 | long mask; | ||
| 56 | Visual *my_visual; | ||
| 57 | XVisualInfo *vinfo, visual_template; | ||
| 58 | XEvent event; | ||
| 59 | Window window; | ||
| 60 | Screen *scr; | ||
| 61 | XGCValues gc_values; | ||
| 62 | GC fill_gc, pix_gc, line_xor_gc, line_xor_inv_gc; | ||
| 63 | int i; | ||
| 64 | int x, y, width, height, geometry, gravity; | ||
| 65 | char *geo; | ||
| 66 | char default_geo[] = "80x40+0+0"; | ||
| 67 | int depth; | ||
| 68 | Pixmap pix; | ||
| 69 | char *string = "Kill the head and the body will die."; | ||
| 70 | char dash_list[] = {4, 4}; | ||
| 71 | int dashes = 2; | ||
| 72 | |||
| 73 | if (argc < 2) | ||
| 74 | dpy_string = "localhost:0.0"; | ||
| 75 | else | ||
| 76 | dpy_string = argv[1]; | ||
| 77 | |||
| 78 | if (argc >= 3) | ||
| 79 | { | ||
| 80 | XSizeHints hints; | ||
| 81 | |||
| 82 | printf ("Geometry: %s\t(default: %s)\n", argv[2], default_geo); | ||
| 83 | geo = argv[2]; | ||
| 84 | XWMGeometry (dpy, DefaultScreen (dpy), geo, default_geo, | ||
| 85 | 3, &hints, &x, &y, &width, &height, &gravity); | ||
| 86 | } | ||
| 87 | |||
| 88 | dpy = XOpenDisplay (dpy_string); | ||
| 89 | if (!dpy) | ||
| 90 | { | ||
| 91 | printf ("Can' open display %s\n", dpy_string); | ||
| 92 | exit (1); | ||
| 93 | } | ||
| 94 | |||
| 95 | window = XCreateSimpleWindow (dpy, DefaultRootWindow (dpy), | ||
| 96 | 300, 300, 300, 300, 1, | ||
| 97 | BlackPixel (dpy, DefaultScreen (dpy)), | ||
| 98 | WhitePixel (dpy, DefaultScreen (dpy))); | ||
| 99 | XSelectInput (dpy, window, ButtonPressMask | KeyPressMask | ||
| 100 | | EnterWindowMask | LeaveWindowMask); | ||
| 101 | |||
| 102 | gc_values.foreground = obtain_color ("blue"); | ||
| 103 | gc_values.background = WhitePixel (dpy, DefaultScreen (dpy)); | ||
| 104 | fill_gc = XCreateGC (dpy, window, GCForeground | GCBackground, | ||
| 105 | &gc_values); | ||
| 106 | |||
| 107 | gc_values.foreground = obtain_color ("red"); | ||
| 108 | gc_values.line_width = 3; | ||
| 109 | gc_values.line_style = LineOnOffDash; | ||
| 110 | gc_values.cap_style = CapRound; | ||
| 111 | gc_values.join_style = JoinRound; | ||
| 112 | line_xor_gc = XCreateGC (dpy, window, | ||
| 113 | GCForeground | GCBackground | GCLineStyle | ||
| 114 | | GCJoinStyle | GCCapStyle | GCLineWidth, | ||
| 115 | &gc_values); | ||
| 116 | XSetDashes (dpy, line_xor_gc, 0, dash_list, dashes); | ||
| 117 | |||
| 118 | line_xor_inv_gc = XCreateGC (dpy, window, | ||
| 119 | GCForeground | GCBackground | GCLineWidth, | ||
| 120 | &gc_values); | ||
| 121 | |||
| 122 | depth = DefaultDepthOfScreen (ScreenOfDisplay (dpy, DefaultScreen (dpy))); | ||
| 123 | pix = XCreateBitmapFromData (dpy, window, page_glyf_bits, | ||
| 124 | page_glyf_width, page_glyf_height); | ||
| 125 | |||
| 126 | XMapWindow (dpy, window); | ||
| 127 | XFlush (dpy); | ||
| 128 | |||
| 129 | while (1) | ||
| 130 | { | ||
| 131 | XNextEvent (dpy, &event); | ||
| 132 | switch (event.type) | ||
| 133 | { | ||
| 134 | case ButtonPress: | ||
| 135 | switch (event.xbutton.button) | ||
| 136 | { | ||
| 137 | case Button1: | ||
| 138 | XDrawLine (dpy, window, line_xor_gc, 25, 75, 300, 75); | ||
| 139 | break; | ||
| 140 | |||
| 141 | case Button2: | ||
| 142 | XDrawLine (dpy, window, line_xor_inv_gc, 25, 25, 300, 25); | ||
| 143 | break; | ||
| 144 | |||
| 145 | case Button3: | ||
| 146 | XDrawLine (dpy, window, line_xor_gc, 25, 25, 25, 125); | ||
| 147 | break; | ||
| 148 | } | ||
| 149 | break; | ||
| 150 | |||
| 151 | case KeyPress: | ||
| 152 | { | ||
| 153 | char buf[20]; | ||
| 154 | int n; | ||
| 155 | XComposeStatus status; | ||
| 156 | KeySym keysym; | ||
| 157 | |||
| 158 | n = XLookupString (&event, buf, 20, &keysym, | ||
| 159 | (XComposeStatus *) &status); | ||
| 160 | |||
| 161 | if (n == 1 && buf[0] == 'q') | ||
| 162 | quit (dpy); | ||
| 163 | } | ||
| 164 | break; | ||
| 165 | |||
| 166 | case EnterNotify: | ||
| 167 | XCopyPlane (dpy, pix, window, fill_gc, 0, 0, | ||
| 168 | page_glyf_width, page_glyf_height, 100, 100, 1L); | ||
| 169 | XFillRectangle (dpy, window, fill_gc, 50, 50, 50, 50); | ||
| 170 | break; | ||
| 171 | |||
| 172 | case LeaveNotify: | ||
| 173 | XClearWindow (dpy, window); | ||
| 174 | break; | ||
| 175 | } | ||
| 176 | |||
| 177 | XFlush (dpy); | ||
| 178 | } | ||
| 179 | } | ||
diff --git a/src/XTests.h b/src/XTests.h deleted file mode 100644 index e91445af7ef..00000000000 --- a/src/XTests.h +++ /dev/null | |||
| @@ -1,7 +0,0 @@ | |||
| 1 | #define page_glyf_width 30 | ||
| 2 | #define page_glyf_height 10 | ||
| 3 | static char page_glyf_bits[] = { | ||
| 4 | 0xf0, 0xff, 0xff, 0x03, 0x08, 0x00, 0x00, 0x04, 0xc4, 0x19, 0xf3, 0x08, | ||
| 5 | 0x42, 0xa5, 0x14, 0x10, 0xc1, 0xa5, 0x70, 0x20, 0x41, 0xbc, 0x16, 0x20, | ||
| 6 | 0x42, 0xa4, 0x14, 0x10, 0x44, 0x24, 0xf3, 0x08, 0x08, 0x00, 0x00, 0x04, | ||
| 7 | 0xf0, 0xff, 0xff, 0x03}; | ||
diff --git a/src/convexos.h b/src/convexos.h deleted file mode 100644 index 94cdbf68346..00000000000 --- a/src/convexos.h +++ /dev/null | |||
| @@ -1,10 +0,0 @@ | |||
| 1 | /* Definitions file for GNU Emacs running on ConvexOS. */ | ||
| 2 | |||
| 3 | #include "bsd4-3.h" | ||
| 4 | |||
| 5 | /* First pty name is /dev/pty?0. We have to search for it. */ | ||
| 6 | #undef FIRST_PTY_LETTER | ||
| 7 | #define FIRST_PTY_LETTER first_pty_letter | ||
| 8 | |||
| 9 | /* getpgrp requires no arguments. */ | ||
| 10 | #define GETPGRP_NO_ARG | ||
diff --git a/src/environ.c b/src/environ.c deleted file mode 100644 index 863f40ccd2a..00000000000 --- a/src/environ.c +++ /dev/null | |||
| @@ -1,316 +0,0 @@ | |||
| 1 | /* Environment-hacking for GNU Emacs subprocess | ||
| 2 | Copyright (C) 1986 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 1, or (at your option) | ||
| 9 | any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
| 19 | |||
| 20 | |||
| 21 | #include "config.h" | ||
| 22 | #include "lisp.h" | ||
| 23 | |||
| 24 | #ifdef MAINTAIN_ENVIRONMENT | ||
| 25 | |||
| 26 | #ifdef VMS | ||
| 27 | you lose -- this is un*x-only | ||
| 28 | #endif | ||
| 29 | |||
| 30 | /* alist of (name-string . value-string) */ | ||
| 31 | Lisp_Object Venvironment_alist; | ||
| 32 | extern char **environ; | ||
| 33 | |||
| 34 | void | ||
| 35 | set_environment_alist (str, val) | ||
| 36 | register Lisp_Object str, val; | ||
| 37 | { | ||
| 38 | register Lisp_Object tem; | ||
| 39 | |||
| 40 | tem = Fassoc (str, Venvironment_alist); | ||
| 41 | if (NULL (tem)) | ||
| 42 | if (NULL (val)) | ||
| 43 | ; | ||
| 44 | else | ||
| 45 | Venvironment_alist = Fcons (Fcons (str, val), Venvironment_alist); | ||
| 46 | else | ||
| 47 | if (NULL (val)) | ||
| 48 | Venvironment_alist = Fdelq (tem, Venvironment_alist); | ||
| 49 | else | ||
| 50 | XCONS (tem)->cdr = val; | ||
| 51 | } | ||
| 52 | |||
| 53 | |||
| 54 | |||
| 55 | static void | ||
| 56 | initialize_environment_alist () | ||
| 57 | { | ||
| 58 | register unsigned char **e, *s; | ||
| 59 | extern char *index (); | ||
| 60 | |||
| 61 | for (e = (unsigned char **) environ; *e; e++) | ||
| 62 | { | ||
| 63 | s = (unsigned char *) index (*e, '='); | ||
| 64 | if (s) | ||
| 65 | set_environment_alist (make_string (*e, s - *e), | ||
| 66 | build_string (s + 1)); | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | |||
| 71 | unsigned char * | ||
| 72 | getenv_1 (str, ephemeral) | ||
| 73 | register unsigned char *str; | ||
| 74 | int ephemeral; /* if ephmeral, don't need to gc-proof */ | ||
| 75 | { | ||
| 76 | register Lisp_Object env; | ||
| 77 | int len = strlen (str); | ||
| 78 | |||
| 79 | for (env = Venvironment_alist; CONSP (env); env = XCONS (env)->cdr) | ||
| 80 | { | ||
| 81 | register Lisp_Object car = XCONS (env)->car; | ||
| 82 | register Lisp_Object tem = XCONS (car)->car; | ||
| 83 | |||
| 84 | if ((len == XSTRING (tem)->size) && | ||
| 85 | (!bcmp (str, XSTRING (tem)->data, len))) | ||
| 86 | { | ||
| 87 | /* Found it in the lisp environment */ | ||
| 88 | tem = XCONS (car)->cdr; | ||
| 89 | if (ephemeral) | ||
| 90 | /* Caller promises that gc won't make him lose */ | ||
| 91 | return XSTRING (tem)->data; | ||
| 92 | else | ||
| 93 | { | ||
| 94 | register unsigned char **e; | ||
| 95 | unsigned char *s; | ||
| 96 | int ll = XSTRING (tem)->size; | ||
| 97 | |||
| 98 | /* Look for element in the original unix environment */ | ||
| 99 | for (e = (unsigned char **) environ; *e; e++) | ||
| 100 | if (!bcmp (str, *e, len) && *(*e + len) == '=') | ||
| 101 | { | ||
| 102 | s = *e + len + 1; | ||
| 103 | if (strlen (s) >= ll) | ||
| 104 | /* User hasn't either hasn't munged it or has set it | ||
| 105 | to something shorter -- we don't have to cons */ | ||
| 106 | goto copy; | ||
| 107 | else | ||
| 108 | goto cons; | ||
| 109 | }; | ||
| 110 | cons: | ||
| 111 | /* User has setenv'ed it to a diferent value, and our caller | ||
| 112 | isn't guaranteeing that he won't stash it away somewhere. | ||
| 113 | We can't just return a pointer to the lisp string, as that | ||
| 114 | will be corrupted when gc happens. So, we cons (in such | ||
| 115 | a way that it can't be freed -- though this isn't such a | ||
| 116 | problem since the only callers of getenv (as opposed to | ||
| 117 | those of egetenv) are very early, before the user -could- | ||
| 118 | have frobbed the environment. */ | ||
| 119 | s = (unsigned char *) xmalloc (ll + 1); | ||
| 120 | copy: | ||
| 121 | bcopy (XSTRING (tem)->data, s, ll + 1); | ||
| 122 | return (s); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | } | ||
| 126 | return ((unsigned char *) 0); | ||
| 127 | } | ||
| 128 | |||
| 129 | /* unsigned -- stupid delcaration in lisp.h */ char * | ||
| 130 | getenv (str) | ||
| 131 | register unsigned char *str; | ||
| 132 | { | ||
| 133 | return ((char *) getenv_1 (str, 0)); | ||
| 134 | } | ||
| 135 | |||
| 136 | unsigned char * | ||
| 137 | egetenv (str) | ||
| 138 | register unsigned char *str; | ||
| 139 | { | ||
| 140 | return (getenv_1 (str, 1)); | ||
| 141 | } | ||
| 142 | |||
| 143 | |||
| 144 | #if (1 == 1) /* use caller-alloca versions, rather than callee-malloc */ | ||
| 145 | int | ||
| 146 | size_of_current_environ () | ||
| 147 | { | ||
| 148 | register int size; | ||
| 149 | Lisp_Object tem; | ||
| 150 | |||
| 151 | tem = Flength (Venvironment_alist); | ||
| 152 | |||
| 153 | size = (XINT (tem) + 1) * sizeof (unsigned char *); | ||
| 154 | /* + 1 for environment-terminating 0 */ | ||
| 155 | |||
| 156 | for (tem = Venvironment_alist; !NULL (tem); tem = XCONS (tem)->cdr) | ||
| 157 | { | ||
| 158 | register Lisp_Object str, val; | ||
| 159 | |||
| 160 | str = XCONS (XCONS (tem)->car)->car; | ||
| 161 | val = XCONS (XCONS (tem)->car)->cdr; | ||
| 162 | |||
| 163 | size += (XSTRING (str)->size + | ||
| 164 | XSTRING (val)->size + | ||
| 165 | 2); /* 1 for '=', 1 for '\000' */ | ||
| 166 | } | ||
| 167 | return size; | ||
| 168 | } | ||
| 169 | |||
| 170 | void | ||
| 171 | get_current_environ (memory_block) | ||
| 172 | unsigned char **memory_block; | ||
| 173 | { | ||
| 174 | register unsigned char **e, *s; | ||
| 175 | register int len; | ||
| 176 | register Lisp_Object tem; | ||
| 177 | |||
| 178 | e = memory_block; | ||
| 179 | |||
| 180 | tem = Flength (Venvironment_alist); | ||
| 181 | |||
| 182 | s = (unsigned char *) memory_block | ||
| 183 | + (XINT (tem) + 1) * sizeof (unsigned char *); | ||
| 184 | |||
| 185 | for (tem = Venvironment_alist; !NULL (tem); tem = XCONS (tem)->cdr) | ||
| 186 | { | ||
| 187 | register Lisp_Object str, val; | ||
| 188 | |||
| 189 | str = XCONS (XCONS (tem)->car)->car; | ||
| 190 | val = XCONS (XCONS (tem)->car)->cdr; | ||
| 191 | |||
| 192 | *e++ = s; | ||
| 193 | len = XSTRING (str)->size; | ||
| 194 | bcopy (XSTRING (str)->data, s, len); | ||
| 195 | s += len; | ||
| 196 | *s++ = '='; | ||
| 197 | len = XSTRING (val)->size; | ||
| 198 | bcopy (XSTRING (val)->data, s, len); | ||
| 199 | s += len; | ||
| 200 | *s++ = '\000'; | ||
| 201 | } | ||
| 202 | *e = 0; | ||
| 203 | } | ||
| 204 | |||
| 205 | #else | ||
| 206 | /* dead code (this function mallocs, caller frees) superseded by above (which allows caller to use alloca) */ | ||
| 207 | unsigned char ** | ||
| 208 | current_environ () | ||
| 209 | { | ||
| 210 | unsigned char **env; | ||
| 211 | register unsigned char **e, *s; | ||
| 212 | register int len, env_len; | ||
| 213 | Lisp_Object tem; | ||
| 214 | Lisp_Object str, val; | ||
| 215 | |||
| 216 | tem = Flength (Venvironment_alist); | ||
| 217 | |||
| 218 | env_len = (XINT (tem) + 1) * sizeof (char *); | ||
| 219 | /* + 1 for terminating 0 */ | ||
| 220 | |||
| 221 | len = 0; | ||
| 222 | for (tem = Venvironment_alist; !NULL (tem); tem = XCONS (tem)->cdr) | ||
| 223 | { | ||
| 224 | str = XCONS (XCONS (tem)->car)->car; | ||
| 225 | val = XCONS (XCONS (tem)->car)->cdr; | ||
| 226 | |||
| 227 | len += (XSTRING (str)->size + | ||
| 228 | XSTRING (val)->size + | ||
| 229 | 2); | ||
| 230 | } | ||
| 231 | |||
| 232 | e = env = (unsigned char **) xmalloc (env_len + len); | ||
| 233 | s = (unsigned char *) env + env_len; | ||
| 234 | |||
| 235 | for (tem = Venvironment_alist; !NULL (tem); tem = XCONS (tem)->cdr) | ||
| 236 | { | ||
| 237 | str = XCONS (XCONS (tem)->car)->car; | ||
| 238 | val = XCONS (XCONS (tem)->car)->cdr; | ||
| 239 | |||
| 240 | *e++ = s; | ||
| 241 | len = XSTRING (str)->size; | ||
| 242 | bcopy (XSTRING (str)->data, s, len); | ||
| 243 | s += len; | ||
| 244 | *s++ = '='; | ||
| 245 | len = XSTRING (val)->size; | ||
| 246 | bcopy (XSTRING (val)->data, s, len); | ||
| 247 | s += len; | ||
| 248 | *s++ = '\000'; | ||
| 249 | } | ||
| 250 | *e = 0; | ||
| 251 | |||
| 252 | return env; | ||
| 253 | } | ||
| 254 | |||
| 255 | #endif /* dead code */ | ||
| 256 | |||
| 257 | |||
| 258 | DEFUN ("getenv", Fgetenv, Sgetenv, 1, 2, "sEnvironment variable: \np", | ||
| 259 | "Return the value of environment variable VAR, as a string.\n\ | ||
| 260 | When invoked interactively, print the value in the echo area.\n\ | ||
| 261 | VAR is a string, the name of the variable,\n\ | ||
| 262 | or the symbol t, meaning to return an alist representing the\n\ | ||
| 263 | current environment.") | ||
| 264 | (str, interactivep) | ||
| 265 | Lisp_Object str, interactivep; | ||
| 266 | { | ||
| 267 | Lisp_Object val; | ||
| 268 | |||
| 269 | if (str == Qt) /* If arg is t, return whole environment */ | ||
| 270 | return (Fcopy_alist (Venvironment_alist)); | ||
| 271 | |||
| 272 | CHECK_STRING (str, 0); | ||
| 273 | val = Fcdr (Fassoc (str, Venvironment_alist)); | ||
| 274 | if (!NULL (interactivep)) | ||
| 275 | { | ||
| 276 | if (NULL (val)) | ||
| 277 | message ("%s not defined in environment", XSTRING (str)->data); | ||
| 278 | else | ||
| 279 | message ("\"%s\"", XSTRING (val)->data); | ||
| 280 | } | ||
| 281 | return val; | ||
| 282 | } | ||
| 283 | |||
| 284 | DEFUN ("setenv", Fsetenv, Ssetenv, 1, 2, | ||
| 285 | "sEnvironment variable: \nsSet %s to value: ", | ||
| 286 | "Set the value of environment variable VAR to VALUE.\n\ | ||
| 287 | Both args must be strings. Returns VALUE.") | ||
| 288 | (str, val) | ||
| 289 | Lisp_Object str; | ||
| 290 | Lisp_Object val; | ||
| 291 | { | ||
| 292 | Lisp_Object tem; | ||
| 293 | |||
| 294 | CHECK_STRING (str, 0); | ||
| 295 | if (!NULL (val)) | ||
| 296 | CHECK_STRING (val, 0); | ||
| 297 | |||
| 298 | set_environment_alist (str, val); | ||
| 299 | return val; | ||
| 300 | } | ||
| 301 | |||
| 302 | |||
| 303 | syms_of_environ () | ||
| 304 | { | ||
| 305 | staticpro (&Venvironment_alist); | ||
| 306 | defsubr (&Ssetenv); | ||
| 307 | defsubr (&Sgetenv); | ||
| 308 | } | ||
| 309 | |||
| 310 | init_environ () | ||
| 311 | { | ||
| 312 | Venvironment_alist = Qnil; | ||
| 313 | initialize_environment_alist (); | ||
| 314 | } | ||
| 315 | |||
| 316 | #endif /* MAINTAIN_ENVIRONMENT */ | ||
diff --git a/src/m/dos386.h b/src/m/dos386.h deleted file mode 100644 index 1fb38da656f..00000000000 --- a/src/m/dos386.h +++ /dev/null | |||
| @@ -1,115 +0,0 @@ | |||
| 1 | /* Machine description file for MS-DOS | ||
| 2 | |||
| 3 | Copyright (C) 1993 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | any later version. | ||
| 11 | |||
| 12 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
| 20 | |||
| 21 | /* Note: lots of stuff here was taken from m-dos386.h in demacs. */ | ||
| 22 | |||
| 23 | |||
| 24 | /* The following three symbols give information on | ||
| 25 | the size of various data types. */ | ||
| 26 | |||
| 27 | #define SHORTBITS 16 /* Number of bits in a short */ | ||
| 28 | #define INTBITS 32 /* Number of bits in an int */ | ||
| 29 | #define LONGBITS 32 /* Number of bits in a long */ | ||
| 30 | |||
| 31 | /* Define BIG_ENDIAN iff lowest-numbered byte in a word | ||
| 32 | is the most significant byte. */ | ||
| 33 | |||
| 34 | /* #define BIG_ENDIAN */ | ||
| 35 | |||
| 36 | /* Define NO_ARG_ARRAY if you cannot take the address of the first of a | ||
| 37 | * group of arguments and treat it as an array of the arguments. */ | ||
| 38 | |||
| 39 | /* #define NO_ARG_ARRAY */ | ||
| 40 | |||
| 41 | /* Define WORD_MACHINE if addresses and such have | ||
| 42 | * to be corrected before they can be used as byte counts. */ | ||
| 43 | |||
| 44 | /* #define WORD_MACHINE */ | ||
| 45 | |||
| 46 | /* Define how to take a char and sign-extend into an int. | ||
| 47 | On machines where char is signed, this is a no-op. */ | ||
| 48 | |||
| 49 | #define SIGN_EXTEND_CHAR(c) (c) | ||
| 50 | |||
| 51 | /* Now define a symbol for the cpu type, if your compiler | ||
| 52 | does not define it automatically: | ||
| 53 | Ones defined so far include vax, m68000, ns16000, pyramid, | ||
| 54 | orion, tahoe, APOLLO and many others */ | ||
| 55 | |||
| 56 | #define INTEL386 | ||
| 57 | |||
| 58 | /* Use type int rather than a union, to represent Lisp_Object */ | ||
| 59 | /* This is desirable for most machines. */ | ||
| 60 | |||
| 61 | #define NO_UNION_TYPE | ||
| 62 | |||
| 63 | /* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend | ||
| 64 | the 24-bit bit field into an int. In other words, if bit fields | ||
| 65 | are always unsigned. | ||
| 66 | |||
| 67 | If you use NO_UNION_TYPE, this flag does not matter. */ | ||
| 68 | |||
| 69 | #define EXPLICIT_SIGN_EXTEND | ||
| 70 | |||
| 71 | /* Data type of load average, as read out of kmem. */ | ||
| 72 | |||
| 73 | /* #define LOAD_AVE_TYPE long */ | ||
| 74 | |||
| 75 | /* Convert that into an integer that is 100 for a load average of 1.0 */ | ||
| 76 | |||
| 77 | /* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */ | ||
| 78 | |||
| 79 | /* Define CANNOT_DUMP on machines where unexec does not work. | ||
| 80 | Then the function dump-emacs will not be defined | ||
| 81 | and temacs will do (load "loadup") automatically unless told otherwise. */ | ||
| 82 | |||
| 83 | /* #define CANNOT_DUMP */ | ||
| 84 | |||
| 85 | /* Define VIRT_ADDR_VARIES if the virtual addresses of | ||
| 86 | pure and impure space as loaded can vary, and even their | ||
| 87 | relative order cannot be relied on. | ||
| 88 | |||
| 89 | Otherwise Emacs assumes that text space precedes data space, | ||
| 90 | numerically. */ | ||
| 91 | |||
| 92 | /* #define VIRT_ADDR_VARIES */ | ||
| 93 | |||
| 94 | /* Define C_ALLOCA if this machine does not support a true alloca | ||
| 95 | and the one written in C should be used instead. | ||
| 96 | Define HAVE_ALLOCA to say that the system provides a properly | ||
| 97 | working alloca function and it should be used. | ||
| 98 | Define neither one if an assembler-language alloca | ||
| 99 | in the file alloca.s should be used. */ | ||
| 100 | |||
| 101 | #define HAVE_ALLOCA | ||
| 102 | #define alloca(x) __builtin_alloca(x) | ||
| 103 | |||
| 104 | /* Define NO_REMAP if memory segmentation makes it not work well | ||
| 105 | to change the boundary between the text section and data section | ||
| 106 | when Emacs is dumped. If you define this, the preloaded Lisp | ||
| 107 | code will not be sharable; but that's better than failing completely. */ | ||
| 108 | |||
| 109 | #define NO_REMAP | ||
| 110 | |||
| 111 | /* We need a little extra space, see ../../lisp/loadup.el */ | ||
| 112 | #define PURESIZE 240000 | ||
| 113 | |||
| 114 | /* We have (the code to control) a mouse. */ | ||
| 115 | #define HAVE_MOUSE | ||
diff --git a/src/mach2.h b/src/mach2.h deleted file mode 100644 index c941c5ff2cf..00000000000 --- a/src/mach2.h +++ /dev/null | |||
| @@ -1,48 +0,0 @@ | |||
| 1 | /* Definitions for Emacs running on Mach version 2 (non-kernelized system). | ||
| 2 | Copyright (C) 1990 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2, or (at your option) | ||
| 9 | any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
| 19 | |||
| 20 | #include "bsd4-3.h" | ||
| 21 | |||
| 22 | /* SYSTEM_TYPE should indicate the kind of system you are using. | ||
| 23 | It sets the Lisp variable system-type. We'll need to undo the bsd one. */ | ||
| 24 | |||
| 25 | #undef SYSTEM_TYPE | ||
| 26 | #define SYSTEM_TYPE "next-mach" | ||
| 27 | |||
| 28 | #define LD_SWITCH_SYSTEM -X -noseglinkedit | ||
| 29 | |||
| 30 | /* Don't use -lc on the NeXT. */ | ||
| 31 | #define LIB_STANDARD -lsys_s | ||
| 32 | #define LIB_MATH -lm | ||
| 33 | |||
| 34 | #define environ _environ | ||
| 35 | |||
| 36 | #define START_FILES pre-crt0.o | ||
| 37 | #define UNEXEC unexnext.o | ||
| 38 | |||
| 39 | /* start_of_text isn't actually used, so make it compile without error. */ | ||
| 40 | #define TEXT_START 0 | ||
| 41 | /* This seems to be right for end_of_text, but it may not be used anyway. */ | ||
| 42 | #define TEXT_END get_etext () | ||
| 43 | /* This seems to be right for end_of_data, but it may not be used anyway. */ | ||
| 44 | #define DATA_END get_edata () | ||
| 45 | |||
| 46 | /* Defining KERNEL_FILE causes lossage because sys/file.h | ||
| 47 | stupidly gets confused by it. */ | ||
| 48 | #undef KERNEL_FILE | ||
diff --git a/src/old-ralloc.c b/src/old-ralloc.c deleted file mode 100644 index 28562994e9a..00000000000 --- a/src/old-ralloc.c +++ /dev/null | |||
| @@ -1,1069 +0,0 @@ | |||
| 1 | /* Block-relocating memory allocator. | ||
| 2 | Copyright (C) 1990 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 1, or (at your option) | ||
| 9 | any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
| 19 | |||
| 20 | /* This package works by allocating blocks from a zone of memory | ||
| 21 | above that used by malloc (). When malloc needs more space that | ||
| 22 | would enter our zone, we relocate blocks upward. The bottom of | ||
| 23 | our zone is kept in the variable `virtual_break_value'. The top | ||
| 24 | of our zone is indicated by `real_break_value'. | ||
| 25 | |||
| 26 | As blocks are freed, a free list is maintained and we attempt | ||
| 27 | to satisfy further requests for space using a first-fit policy. | ||
| 28 | If there are holes, but none fit, memory is compacted and a new | ||
| 29 | block is obtained at the top of the zone. | ||
| 30 | |||
| 31 | NOTE that our blocks are always rounded to page boundaries. */ | ||
| 32 | |||
| 33 | /* | ||
| 34 | NOTES: | ||
| 35 | |||
| 36 | Once this is stable, I can speed things up by intially leaving a large | ||
| 37 | gap between real_break_value and true_break_value, or maybe making | ||
| 38 | a large hole before the first block. | ||
| 39 | |||
| 40 | If we also kept track of size_wanted, we could gain some | ||
| 41 | extra space upon compactification. | ||
| 42 | |||
| 43 | Perhaps we should just note a hole when malloc does doing sbrk(-n)? | ||
| 44 | |||
| 45 | Relocating downward upon freeing the first block would simplify | ||
| 46 | other things. | ||
| 47 | |||
| 48 | When r_alloc places a block in a hole, we could easily check if there's | ||
| 49 | much more than required, and leave a hole. | ||
| 50 | */ | ||
| 51 | |||
| 52 | #include "mem_limits.h" | ||
| 53 | |||
| 54 | static POINTER r_alloc_sbrk (); | ||
| 55 | static POINTER sbrk (); | ||
| 56 | static POINTER brk (); | ||
| 57 | |||
| 58 | /* Variable `malloc' uses for the function which gets more space | ||
| 59 | from the system. */ | ||
| 60 | extern POINTER (*__morecore) (); | ||
| 61 | |||
| 62 | /* List of variables which point into the associated data block. */ | ||
| 63 | struct other_pointer | ||
| 64 | { | ||
| 65 | POINTER *location; | ||
| 66 | struct other_pointer *next; | ||
| 67 | }; | ||
| 68 | |||
| 69 | /* List describing all the user's pointers to relocatable blocks. */ | ||
| 70 | typedef struct rel_pointers | ||
| 71 | { | ||
| 72 | struct rel_pointers *next; | ||
| 73 | struct rel_pointers *prev; | ||
| 74 | struct other_pointer *others; /* Other variables which use this block. */ | ||
| 75 | POINTER *location; /* Location of the block's pointer. */ | ||
| 76 | POINTER block; /* Address of the actual data. */ | ||
| 77 | int size; /* The size of the block. */ | ||
| 78 | } relocatable_pointer; | ||
| 79 | |||
| 80 | #define REL_NIL ((struct rel_pointers *) 0) | ||
| 81 | |||
| 82 | static relocatable_pointer *pointer_list; | ||
| 83 | static relocatable_pointer *last_pointer; | ||
| 84 | |||
| 85 | #define MAX_HOLES 2 | ||
| 86 | |||
| 87 | /* Vector of available holes among allocated blocks. This can include | ||
| 88 | a hole at the beginning of the list, but never the end. */ | ||
| 89 | typedef struct | ||
| 90 | { | ||
| 91 | POINTER address; | ||
| 92 | unsigned int size; | ||
| 93 | } hole_descriptor; | ||
| 94 | |||
| 95 | static hole_descriptor r_alloc_holes[MAX_HOLES]; | ||
| 96 | |||
| 97 | /* Number of holes currently available. */ | ||
| 98 | static int holes; | ||
| 99 | |||
| 100 | /* The process break value (i.e., curbrk) */ | ||
| 101 | static POINTER real_break_value; | ||
| 102 | |||
| 103 | /* The REAL (i.e., page aligned) break value. */ | ||
| 104 | static POINTER true_break_value; | ||
| 105 | |||
| 106 | /* Address of start of data space in use by relocatable blocks. | ||
| 107 | This is what `malloc' thinks is the process break value. */ | ||
| 108 | static POINTER virtual_break_value; | ||
| 109 | |||
| 110 | /* Nonzero if we have told `malloc' to start using `r_alloc_sbrk' | ||
| 111 | instead of calling `sbrk' directly. */ | ||
| 112 | int r_alloc_in_use; | ||
| 113 | |||
| 114 | #define PAGE (getpagesize ()) | ||
| 115 | #define ALIGNED(addr) (((unsigned int) (addr) & (PAGE - 1)) == 0) | ||
| 116 | #define ROUNDUP(size) (((unsigned int) (size) + PAGE) & ~(PAGE - 1)) | ||
| 117 | |||
| 118 | /* | ||
| 119 | Level number of warnings already issued. | ||
| 120 | 0 -- no warnings issued. | ||
| 121 | 1 -- 75% warning already issued. | ||
| 122 | 2 -- 85% warning already issued. | ||
| 123 | */ | ||
| 124 | static int warnlevel; | ||
| 125 | |||
| 126 | /* Function to call to issue a warning; | ||
| 127 | 0 means don't issue them. */ | ||
| 128 | static void (*warnfunction) (); | ||
| 129 | |||
| 130 | /* Call this to start things off. It determines the current process | ||
| 131 | break value, as well as the `true' break value--because the system | ||
| 132 | allocates memory in page increments, if the break value is not page | ||
| 133 | aligned it means that space up to the next page boundary is actually | ||
| 134 | available. */ | ||
| 135 | |||
| 136 | void | ||
| 137 | malloc_init (start, warn_func) | ||
| 138 | POINTER start; | ||
| 139 | void (*warn_func) (); | ||
| 140 | { | ||
| 141 | r_alloc_in_use = 1; | ||
| 142 | __morecore = r_alloc_sbrk; | ||
| 143 | |||
| 144 | virtual_break_value = real_break_value = sbrk (0); | ||
| 145 | if (ALIGNED (real_break_value)) | ||
| 146 | true_break_value = real_break_value; | ||
| 147 | else | ||
| 148 | true_break_value = (POINTER) ROUNDUP (real_break_value); | ||
| 149 | |||
| 150 | if (start) | ||
| 151 | data_space_start = start; | ||
| 152 | lim_data = 0; | ||
| 153 | warnlevel = 0; | ||
| 154 | warnfunction = warn_func; | ||
| 155 | |||
| 156 | get_lim_data (); | ||
| 157 | } | ||
| 158 | |||
| 159 | /* Get more space for us to use. Return a pointer to SIZE more | ||
| 160 | bytes of space. SIZE is internally rounded up to a page boundary, | ||
| 161 | and requests for integral pages prefetch an extra page. */ | ||
| 162 | |||
| 163 | static POINTER | ||
| 164 | get_more_space (size) | ||
| 165 | unsigned int size; | ||
| 166 | { | ||
| 167 | unsigned int margin = true_break_value - real_break_value; | ||
| 168 | unsigned int get; | ||
| 169 | POINTER old_break = real_break_value; | ||
| 170 | |||
| 171 | if (size == 0) | ||
| 172 | return real_break_value; | ||
| 173 | |||
| 174 | if (size <= margin) | ||
| 175 | { | ||
| 176 | real_break_value += size; | ||
| 177 | return old_break; | ||
| 178 | } | ||
| 179 | |||
| 180 | get = ROUNDUP (size - margin); | ||
| 181 | if (sbrk (get) < (POINTER) 0) | ||
| 182 | return NULL; | ||
| 183 | |||
| 184 | true_break_value += get; | ||
| 185 | real_break_value = (old_break + size); | ||
| 186 | |||
| 187 | return old_break; | ||
| 188 | } | ||
| 189 | |||
| 190 | /* Relinquish size bytes of space to the system. Space is only returned | ||
| 191 | in page increments. If successful, return real_break_value. */ | ||
| 192 | |||
| 193 | static POINTER | ||
| 194 | return_space (size) | ||
| 195 | unsigned int size; | ||
| 196 | { | ||
| 197 | unsigned int margin = (true_break_value - real_break_value) + size; | ||
| 198 | unsigned int to_return = (margin / PAGE) * PAGE; | ||
| 199 | unsigned new_margin = margin % PAGE; | ||
| 200 | |||
| 201 | true_break_value -= to_return; | ||
| 202 | if (! brk (true_break_value)) | ||
| 203 | return NULL; | ||
| 204 | |||
| 205 | real_break_value = true_break_value - new_margin; | ||
| 206 | return real_break_value; | ||
| 207 | } | ||
| 208 | |||
| 209 | /* Record a new hole in memory beginning at ADDRESS of size SIZE. | ||
| 210 | Holes are ordered by location. Adjacent holes are merged. | ||
| 211 | Holes are zero filled before being noted. */ | ||
| 212 | |||
| 213 | static void | ||
| 214 | note_hole (address, size) | ||
| 215 | POINTER address; | ||
| 216 | int size; | ||
| 217 | { | ||
| 218 | register int this_hole = holes - 1; /* Start at the last hole. */ | ||
| 219 | register POINTER end = address + size; /* End of the hole. */ | ||
| 220 | register int i; | ||
| 221 | |||
| 222 | if (holes) | ||
| 223 | { | ||
| 224 | /* Find the hole which should precede this new one. */ | ||
| 225 | while (this_hole >= 0 && r_alloc_holes[this_hole].address > address) | ||
| 226 | this_hole--; | ||
| 227 | |||
| 228 | /* Can we merge with preceding? */ | ||
| 229 | if (this_hole >= 0 | ||
| 230 | && r_alloc_holes[this_hole].address + r_alloc_holes[this_hole].size | ||
| 231 | == address) | ||
| 232 | { | ||
| 233 | r_alloc_holes[this_hole].size += size; | ||
| 234 | |||
| 235 | if (this_hole == holes - 1) | ||
| 236 | return; | ||
| 237 | |||
| 238 | /* Can we also merge with following? */ | ||
| 239 | if (end == r_alloc_holes[this_hole + 1].address) | ||
| 240 | { | ||
| 241 | r_alloc_holes[this_hole].size | ||
| 242 | += r_alloc_holes[this_hole + 1].size; | ||
| 243 | |||
| 244 | for (i = this_hole + 1; i < holes - 1; i++) | ||
| 245 | r_alloc_holes[i] = r_alloc_holes[i + 1]; | ||
| 246 | holes--; | ||
| 247 | } | ||
| 248 | |||
| 249 | return; | ||
| 250 | } | ||
| 251 | |||
| 252 | if (this_hole < holes - 1) /* there are following holes */ | ||
| 253 | { | ||
| 254 | register int next_hole = this_hole + 1; | ||
| 255 | |||
| 256 | /* Can we merge with the next hole? */ | ||
| 257 | if (end == r_alloc_holes[next_hole].address) | ||
| 258 | { | ||
| 259 | r_alloc_holes[next_hole].address = address; | ||
| 260 | r_alloc_holes[next_hole].size += size; | ||
| 261 | return; | ||
| 262 | } | ||
| 263 | |||
| 264 | /* Can't merge, so insert. */ | ||
| 265 | for (i = holes; i > next_hole; i--) | ||
| 266 | r_alloc_holes[i] = r_alloc_holes[i - 1]; | ||
| 267 | r_alloc_holes[next_hole].address = address; | ||
| 268 | r_alloc_holes[next_hole].size = size; | ||
| 269 | holes++; | ||
| 270 | |||
| 271 | return; | ||
| 272 | } | ||
| 273 | else /* Simply add this hole at the end. */ | ||
| 274 | { | ||
| 275 | r_alloc_holes[holes].address = address; | ||
| 276 | r_alloc_holes[holes].size = size; | ||
| 277 | holes++; | ||
| 278 | |||
| 279 | return; | ||
| 280 | } | ||
| 281 | |||
| 282 | abort (); | ||
| 283 | } | ||
| 284 | else /* Make the first hole. */ | ||
| 285 | { | ||
| 286 | holes = 1; | ||
| 287 | r_alloc_holes[0].address = address; | ||
| 288 | r_alloc_holes[0].size = size; | ||
| 289 | } | ||
| 290 | } | ||
| 291 | |||
| 292 | /* Mark hole HOLE as no longer available by re-organizing the vector. | ||
| 293 | HOLE is the Nth hole, beginning with 0. This doesn *not* affect memory | ||
| 294 | organization. */ | ||
| 295 | |||
| 296 | static void | ||
| 297 | delete_hole (hole) | ||
| 298 | int hole; | ||
| 299 | { | ||
| 300 | register int i; | ||
| 301 | |||
| 302 | for (i = hole; i < holes - 1; i++) | ||
| 303 | r_alloc_holes[i] = r_alloc_holes[i + 1]; | ||
| 304 | |||
| 305 | holes--; | ||
| 306 | } | ||
| 307 | |||
| 308 | /* Insert a newly allocated pointer, NEW_PTR, at the appropriate | ||
| 309 | place in our list. */ | ||
| 310 | |||
| 311 | static void | ||
| 312 | insert (new_ptr) | ||
| 313 | register relocatable_pointer *new_ptr; | ||
| 314 | { | ||
| 315 | register relocatable_pointer *this_ptr = pointer_list; | ||
| 316 | |||
| 317 | while (this_ptr != REL_NIL && this_ptr->block < new_ptr->block) | ||
| 318 | this_ptr = this_ptr->next; | ||
| 319 | |||
| 320 | if (this_ptr == REL_NIL) | ||
| 321 | abort (); /* Use `attach' for appending. */ | ||
| 322 | |||
| 323 | new_ptr->next = this_ptr; | ||
| 324 | new_ptr->prev = this_ptr->prev; | ||
| 325 | this_ptr->prev = new_ptr; | ||
| 326 | |||
| 327 | if (this_ptr == pointer_list) | ||
| 328 | pointer_list = new_ptr; | ||
| 329 | else | ||
| 330 | new_ptr->prev->next = new_ptr; | ||
| 331 | } | ||
| 332 | |||
| 333 | /* Attach a newly allocated pointer, NEW_PTR, to the end of our list. */ | ||
| 334 | |||
| 335 | static void | ||
| 336 | attach (new_ptr) | ||
| 337 | relocatable_pointer *new_ptr; | ||
| 338 | { | ||
| 339 | if (pointer_list == REL_NIL) | ||
| 340 | { | ||
| 341 | pointer_list = new_ptr; | ||
| 342 | last_pointer = new_ptr; | ||
| 343 | new_ptr->next = new_ptr->prev = REL_NIL; | ||
| 344 | } | ||
| 345 | else | ||
| 346 | { | ||
| 347 | new_ptr->next = REL_NIL; | ||
| 348 | last_pointer->next = new_ptr; | ||
| 349 | new_ptr->prev = last_pointer; | ||
| 350 | last_pointer = new_ptr; | ||
| 351 | } | ||
| 352 | } | ||
| 353 | |||
| 354 | static relocatable_pointer * | ||
| 355 | find_block (block) | ||
| 356 | POINTER block; | ||
| 357 | { | ||
| 358 | register relocatable_pointer *this_ptr = pointer_list; | ||
| 359 | |||
| 360 | while (this_ptr != REL_NIL && this_ptr->block != block) | ||
| 361 | this_ptr = this_ptr->next; | ||
| 362 | |||
| 363 | return this_ptr; | ||
| 364 | } | ||
| 365 | |||
| 366 | static relocatable_pointer * | ||
| 367 | find_location (address) | ||
| 368 | POINTER *address; | ||
| 369 | { | ||
| 370 | register relocatable_pointer *this_ptr = pointer_list; | ||
| 371 | |||
| 372 | while (this_ptr != REL_NIL && this_ptr->location != address) | ||
| 373 | { | ||
| 374 | struct other_pointer *op = this_ptr->others; | ||
| 375 | |||
| 376 | while (op != (struct other_pointer *) 0) | ||
| 377 | { | ||
| 378 | if (op->location == address) | ||
| 379 | return this_ptr; | ||
| 380 | |||
| 381 | op = op->next; | ||
| 382 | } | ||
| 383 | |||
| 384 | this_ptr = this_ptr->next; | ||
| 385 | } | ||
| 386 | |||
| 387 | return this_ptr; | ||
| 388 | } | ||
| 389 | |||
| 390 | |||
| 391 | static void compactify (); | ||
| 392 | |||
| 393 | /* Record of last new block allocated. */ | ||
| 394 | static relocatable_pointer *last_record; | ||
| 395 | |||
| 396 | /* Allocate a block of size SIZE and record that PTR points to it. | ||
| 397 | If successful, store the address of the block in *PTR and return | ||
| 398 | it as well. Otherwise return NULL. */ | ||
| 399 | |||
| 400 | POINTER | ||
| 401 | r_alloc (ptr, size) | ||
| 402 | POINTER *ptr; | ||
| 403 | int size; | ||
| 404 | { | ||
| 405 | register relocatable_pointer *record | ||
| 406 | = (relocatable_pointer *) malloc (sizeof (relocatable_pointer)); | ||
| 407 | register POINTER block; | ||
| 408 | |||
| 409 | /* If we can't get space to record this pointer, fail. */ | ||
| 410 | if (record == 0) | ||
| 411 | return NULL; | ||
| 412 | |||
| 413 | last_record = record; | ||
| 414 | |||
| 415 | if (holes) /* Search for a hole the right size. */ | ||
| 416 | { | ||
| 417 | int i; | ||
| 418 | |||
| 419 | for (i = 0; i < holes; i++) | ||
| 420 | if (r_alloc_holes[i].size >= size) | ||
| 421 | { | ||
| 422 | record->location = ptr; | ||
| 423 | record->others = (struct other_pointer *) 0; | ||
| 424 | record->block = *ptr = r_alloc_holes[i].address; | ||
| 425 | if (r_alloc_holes[i].size > ROUNDUP (size)) | ||
| 426 | { | ||
| 427 | record->size = ROUNDUP (size); | ||
| 428 | r_alloc_holes[i].size -= ROUNDUP (size); | ||
| 429 | r_alloc_holes[i].address += ROUNDUP (size); | ||
| 430 | } | ||
| 431 | else | ||
| 432 | { | ||
| 433 | record->size = r_alloc_holes[i].size; | ||
| 434 | delete_hole (i); | ||
| 435 | } | ||
| 436 | insert (record); | ||
| 437 | |||
| 438 | *ptr = record->block; | ||
| 439 | return record->block; | ||
| 440 | } | ||
| 441 | |||
| 442 | /* No holes large enough. Burp. */ | ||
| 443 | compactify (); | ||
| 444 | } | ||
| 445 | |||
| 446 | /* No holes: grow the process. */ | ||
| 447 | block = get_more_space (size); | ||
| 448 | if (block == NULL) | ||
| 449 | { | ||
| 450 | free (record); | ||
| 451 | return NULL; | ||
| 452 | } | ||
| 453 | |||
| 454 | /* Return the address of the block. */ | ||
| 455 | *ptr = block; | ||
| 456 | |||
| 457 | /* Record and append this pointer to our list. */ | ||
| 458 | record->location = ptr; | ||
| 459 | record->others = (struct other_pointer *) 0; | ||
| 460 | record->block = block; | ||
| 461 | record->size = size; | ||
| 462 | attach (record); | ||
| 463 | |||
| 464 | return block; | ||
| 465 | } | ||
| 466 | |||
| 467 | /* Declare VAR to be a pointer which points into the block of r_alloc'd | ||
| 468 | memory at BLOCK. | ||
| 469 | |||
| 470 | If VAR is already delcared for this block, simply return. | ||
| 471 | If VAR currently points to some other block, remove that declaration | ||
| 472 | of it, then install the new one. | ||
| 473 | |||
| 474 | Return 0 if successful, -1 otherwise. */ | ||
| 475 | |||
| 476 | int | ||
| 477 | r_alloc_declare (var, block) | ||
| 478 | POINTER *var; | ||
| 479 | register POINTER block; | ||
| 480 | { | ||
| 481 | register relocatable_pointer *block_ptr = find_block (block); | ||
| 482 | relocatable_pointer *var_ptr = find_location (var); | ||
| 483 | register struct other_pointer *other; | ||
| 484 | |||
| 485 | if (block_ptr == REL_NIL) | ||
| 486 | abort (); | ||
| 487 | |||
| 488 | if (var_ptr != REL_NIL) /* Var already declared somewhere. */ | ||
| 489 | { | ||
| 490 | register struct other_pointer *po; | ||
| 491 | |||
| 492 | if (var_ptr == block_ptr) /* Var already points to this block. */ | ||
| 493 | return 0; | ||
| 494 | |||
| 495 | po = (struct other_pointer *) 0; | ||
| 496 | other = var_ptr->others; | ||
| 497 | while (other && other->location != var) | ||
| 498 | { | ||
| 499 | po = other; | ||
| 500 | other = other->next; | ||
| 501 | } | ||
| 502 | |||
| 503 | if (!other) /* This only happens if the location is */ | ||
| 504 | abort (); /* the main pointer and not an `other' */ | ||
| 505 | |||
| 506 | if (po) /* In the chain */ | ||
| 507 | { | ||
| 508 | po->next = other->next; | ||
| 509 | free (other); | ||
| 510 | } | ||
| 511 | else /* Only element of the chain */ | ||
| 512 | { | ||
| 513 | free (var_ptr->others); | ||
| 514 | var_ptr->others = (struct other_pointer *) 0; | ||
| 515 | } | ||
| 516 | } | ||
| 517 | |||
| 518 | /* Install this variable as an `other' element */ | ||
| 519 | |||
| 520 | other = (struct other_pointer *) malloc (sizeof (struct other_pointer)); | ||
| 521 | |||
| 522 | if (other == 0) | ||
| 523 | return -1; | ||
| 524 | |||
| 525 | /* If the malloc relocated this data block, adjust this variable. */ | ||
| 526 | if (block != block_ptr->block) | ||
| 527 | { | ||
| 528 | int offset = block_ptr->block - block; | ||
| 529 | |||
| 530 | *var += offset; | ||
| 531 | } | ||
| 532 | |||
| 533 | other->location = var; | ||
| 534 | other->next = (struct other_pointer *) 0; | ||
| 535 | |||
| 536 | if (block_ptr->others == (struct other_pointer *) 0) | ||
| 537 | block_ptr->others = other; | ||
| 538 | else | ||
| 539 | { | ||
| 540 | register struct other_pointer *op = block_ptr->others; | ||
| 541 | |||
| 542 | while (op->next != (struct other_pointer *) 0) | ||
| 543 | op = op->next; | ||
| 544 | op->next = other; | ||
| 545 | } | ||
| 546 | |||
| 547 | return 0; | ||
| 548 | } | ||
| 549 | |||
| 550 | /* Recursively free the linked list of `other' pointers to a block. */ | ||
| 551 | |||
| 552 | static void | ||
| 553 | free_others (another) | ||
| 554 | struct other_pointer *another; | ||
| 555 | { | ||
| 556 | if (another == (struct other_pointer *) 0) | ||
| 557 | return; | ||
| 558 | |||
| 559 | free_others (another->next); | ||
| 560 | free (another); | ||
| 561 | } | ||
| 562 | |||
| 563 | /* Remove the element pointed to by PTR from the doubly linked list. | ||
| 564 | Record the newly freed space in `holes', unless it was at the end, | ||
| 565 | in which case return that space to the system. Return 0 if successful, | ||
| 566 | -1 otherwise. */ | ||
| 567 | |||
| 568 | int | ||
| 569 | r_alloc_free (ptr) | ||
| 570 | register POINTER *ptr; | ||
| 571 | { | ||
| 572 | register relocatable_pointer *this_ptr = find_block (*ptr); | ||
| 573 | |||
| 574 | if (this_ptr == REL_NIL) | ||
| 575 | return -1; | ||
| 576 | else | ||
| 577 | { | ||
| 578 | register relocatable_pointer *prev = this_ptr->prev; | ||
| 579 | register relocatable_pointer *next = this_ptr->next; | ||
| 580 | if (next && prev) /* Somewhere in the middle */ | ||
| 581 | { | ||
| 582 | next->prev = prev; | ||
| 583 | prev->next = next; | ||
| 584 | } | ||
| 585 | else if (prev) /* Last block */ | ||
| 586 | { | ||
| 587 | prev->next = REL_NIL; | ||
| 588 | last_pointer = prev; | ||
| 589 | return_space (this_ptr->size); | ||
| 590 | free_others (this_ptr->others); | ||
| 591 | free (this_ptr); | ||
| 592 | |||
| 593 | return 0; | ||
| 594 | } | ||
| 595 | else if (next) /* First block */ | ||
| 596 | { | ||
| 597 | next->prev = REL_NIL; | ||
| 598 | pointer_list = next; | ||
| 599 | } | ||
| 600 | else if (this_ptr = pointer_list) /* ONLY block */ | ||
| 601 | { | ||
| 602 | pointer_list = REL_NIL; | ||
| 603 | last_pointer = REL_NIL; | ||
| 604 | if (holes) /* A hole precedes this block. */ | ||
| 605 | { | ||
| 606 | holes = 0; | ||
| 607 | return_space (real_break_value - virtual_break_value); | ||
| 608 | } | ||
| 609 | else | ||
| 610 | return_space (this_ptr->size); | ||
| 611 | |||
| 612 | if (real_break_value != virtual_break_value) | ||
| 613 | abort (); | ||
| 614 | |||
| 615 | free_others (this_ptr->others); | ||
| 616 | free (this_ptr); | ||
| 617 | /* Turn off r_alloc_in_use? */ | ||
| 618 | |||
| 619 | return 0; | ||
| 620 | } | ||
| 621 | else | ||
| 622 | abort (); /* Weird shit */ | ||
| 623 | |||
| 624 | free_others (this_ptr->others); | ||
| 625 | free (this_ptr); | ||
| 626 | bzero (this_ptr->block, this_ptr->size); | ||
| 627 | note_hole (this_ptr->block, this_ptr->size); | ||
| 628 | |||
| 629 | if (holes == MAX_HOLES) | ||
| 630 | compactify (); | ||
| 631 | } | ||
| 632 | |||
| 633 | return 0; | ||
| 634 | } | ||
| 635 | |||
| 636 | /* Change the size of the block pointed to by the thing in PTR. | ||
| 637 | If neccessary, r_alloc a new block and copy the data there. | ||
| 638 | Return a pointer to the block if successfull, NULL otherwise. | ||
| 639 | |||
| 640 | Note that if the size requested is less than the actual bloc size, | ||
| 641 | nothing is done and the pointer is simply returned. */ | ||
| 642 | |||
| 643 | POINTER | ||
| 644 | r_re_alloc (ptr, size) | ||
| 645 | POINTER *ptr; | ||
| 646 | int size; | ||
| 647 | { | ||
| 648 | register relocatable_pointer *this_ptr = find_block (*ptr); | ||
| 649 | POINTER block; | ||
| 650 | |||
| 651 | if (! this_ptr) | ||
| 652 | return NULL; | ||
| 653 | |||
| 654 | if (this_ptr->size >= size) /* Already have enough space. */ | ||
| 655 | return *ptr; | ||
| 656 | |||
| 657 | /* Here we could try relocating the blocks just above... */ | ||
| 658 | block = r_alloc (ptr, size); | ||
| 659 | if (block) | ||
| 660 | { | ||
| 661 | bcopy (this_ptr->block, block, this_ptr->size); | ||
| 662 | if (this_ptr->others) | ||
| 663 | last_record->others = this_ptr->others; | ||
| 664 | |||
| 665 | if (! r_alloc_free (this_ptr->block)) | ||
| 666 | abort (); | ||
| 667 | |||
| 668 | *ptr = block; | ||
| 669 | return block; | ||
| 670 | } | ||
| 671 | |||
| 672 | return NULL; | ||
| 673 | } | ||
| 674 | |||
| 675 | |||
| 676 | /* Move and relocate all blocks from FIRST_PTR to LAST_PTR, inclusive, | ||
| 677 | downwards to space starting at ADDRESS. */ | ||
| 678 | |||
| 679 | static int | ||
| 680 | move_blocks_downward (first_ptr, last_ptr, address) | ||
| 681 | relocatable_pointer *first_ptr, *last_ptr; | ||
| 682 | POINTER address; | ||
| 683 | { | ||
| 684 | int size = (last_ptr->block + last_ptr->size) - first_ptr->block; | ||
| 685 | register relocatable_pointer *this_ptr = first_ptr; | ||
| 686 | register offset = first_ptr->block - address; | ||
| 687 | register struct other_pointer *op; | ||
| 688 | |||
| 689 | /* Move all the data. */ | ||
| 690 | bcopy (first_ptr->block, address, size); | ||
| 691 | |||
| 692 | /* Now relocate all the pointers to those blocks. */ | ||
| 693 | while (1) | ||
| 694 | { | ||
| 695 | this_ptr->block -= offset; | ||
| 696 | *this_ptr->location = this_ptr->block; | ||
| 697 | |||
| 698 | op = this_ptr->others; | ||
| 699 | while (op != (struct other_pointer *) 0) | ||
| 700 | { | ||
| 701 | *op->location -= offset; | ||
| 702 | op = op->next; | ||
| 703 | } | ||
| 704 | |||
| 705 | if (this_ptr == last_ptr) | ||
| 706 | return; | ||
| 707 | else | ||
| 708 | this_ptr = this_ptr->next; | ||
| 709 | } | ||
| 710 | |||
| 711 | return size; | ||
| 712 | } | ||
| 713 | |||
| 714 | /* Burp our memory zone. */ | ||
| 715 | |||
| 716 | static void | ||
| 717 | compactify () | ||
| 718 | { | ||
| 719 | register relocatable_pointer *this_ptr = pointer_list; | ||
| 720 | relocatable_pointer *first_to_move; | ||
| 721 | register relocatable_pointer *last_to_move; | ||
| 722 | hole_descriptor *this_hole = &r_alloc_holes[0]; | ||
| 723 | register hole_descriptor *next_hole; | ||
| 724 | register POINTER end; /* First address after hole */ | ||
| 725 | unsigned int space_regained = 0; | ||
| 726 | |||
| 727 | while (holes) /* While there are holes */ | ||
| 728 | { | ||
| 729 | /* Find the first block after this hole. */ | ||
| 730 | end = this_hole->address + this_hole->size; | ||
| 731 | while (this_ptr && this_ptr->block != end) | ||
| 732 | this_ptr = this_ptr->next; | ||
| 733 | |||
| 734 | if (! this_ptr) | ||
| 735 | abort (); | ||
| 736 | |||
| 737 | next_hole = this_hole + 1; | ||
| 738 | last_to_move = first_to_move = this_ptr; | ||
| 739 | this_ptr = this_ptr->next; | ||
| 740 | |||
| 741 | /* Note all blocks located before the next hole. */ | ||
| 742 | while (this_ptr && this_ptr->block < next_hole->address) | ||
| 743 | { | ||
| 744 | last_to_move = this_ptr; | ||
| 745 | this_ptr = this_ptr->next; | ||
| 746 | } | ||
| 747 | space_regained += | ||
| 748 | move_blocks_downward (first_to_move, last_to_move, this_hole->address); | ||
| 749 | |||
| 750 | holes--; | ||
| 751 | this_hole = next_hole; | ||
| 752 | } | ||
| 753 | |||
| 754 | return_space (space_regained); | ||
| 755 | } | ||
| 756 | |||
| 757 | /* Relocate the list elements from the beginning of the list up to and | ||
| 758 | including UP_TO_THIS_PTR to the area beginning at FREE_SPACE, which is | ||
| 759 | after all current blocks. | ||
| 760 | |||
| 761 | First copy all the data, then adjust the pointers and reorganize | ||
| 762 | the list. NOTE that this *only* works for contiguous blocks. */ | ||
| 763 | |||
| 764 | static unsigned int | ||
| 765 | relocate_to_end (up_to_this_ptr, free_space) | ||
| 766 | register relocatable_pointer *up_to_this_ptr; | ||
| 767 | POINTER free_space; | ||
| 768 | { | ||
| 769 | register relocatable_pointer *this_ptr; | ||
| 770 | POINTER block_start = pointer_list->block; | ||
| 771 | POINTER block_end = up_to_this_ptr->block + up_to_this_ptr->size; | ||
| 772 | unsigned int total_size = block_end - block_start; | ||
| 773 | unsigned int offset = (int) (free_space - block_start); | ||
| 774 | |||
| 775 | bcopy (block_start, free_space, total_size); | ||
| 776 | for (this_ptr = up_to_this_ptr; this_ptr; this_ptr = this_ptr->prev) | ||
| 777 | { | ||
| 778 | struct other_pointer *op = this_ptr->others; | ||
| 779 | |||
| 780 | *this_ptr->location += offset; | ||
| 781 | this_ptr->block += offset; | ||
| 782 | |||
| 783 | while (op != (struct other_pointer *) 0) | ||
| 784 | { | ||
| 785 | *op->location += offset; | ||
| 786 | op = op->next; | ||
| 787 | } | ||
| 788 | } | ||
| 789 | |||
| 790 | /* Connect the head to the tail. */ | ||
| 791 | last_pointer->next = pointer_list; | ||
| 792 | pointer_list->prev = last_pointer; | ||
| 793 | |||
| 794 | /* Disconnect */ | ||
| 795 | up_to_this_ptr->next->prev = REL_NIL; | ||
| 796 | pointer_list = up_to_this_ptr->next; | ||
| 797 | up_to_this_ptr->next = REL_NIL; | ||
| 798 | last_pointer = up_to_this_ptr; | ||
| 799 | |||
| 800 | return total_size; /* of space relocated. */ | ||
| 801 | } | ||
| 802 | |||
| 803 | /* Relocate the list elements from FROM_THIS_PTR to (and including) | ||
| 804 | the last to the zone beginning at FREE_SPACE, which is located | ||
| 805 | before any blocks. | ||
| 806 | |||
| 807 | First copy all the data, then adjust the pointers and reorganize | ||
| 808 | the list. NOTE that this *only* works for contiguous blocks. */ | ||
| 809 | |||
| 810 | static unsigned int | ||
| 811 | relocate_to_beginning (from_this_ptr, free_space) | ||
| 812 | register relocatable_pointer *from_this_ptr; | ||
| 813 | POINTER free_space; | ||
| 814 | { | ||
| 815 | POINTER block_start = from_this_ptr->block; | ||
| 816 | POINTER block_end = last_pointer->block + last_pointer->size; | ||
| 817 | unsigned int total_size = (int) (block_end - block_start); | ||
| 818 | unsigned int offset = (int) (from_this_ptr->block - free_space); | ||
| 819 | register relocatable_pointer *this_ptr; | ||
| 820 | |||
| 821 | bcopy (block_start, free_space, total_size); | ||
| 822 | for (this_ptr = from_this_ptr; this_ptr; this_ptr = this_ptr->next) | ||
| 823 | { | ||
| 824 | struct other_pointer *op = this_ptr->others; | ||
| 825 | |||
| 826 | *this_ptr->location -= offset; | ||
| 827 | this_ptr->block -= offset; | ||
| 828 | |||
| 829 | while (op != (struct other_pointer *) 0) | ||
| 830 | { | ||
| 831 | *op->location -= offset; | ||
| 832 | op = op->next; | ||
| 833 | } | ||
| 834 | } | ||
| 835 | |||
| 836 | /* Connect the end to the beginning. */ | ||
| 837 | last_pointer->next = pointer_list; | ||
| 838 | pointer_list->prev = last_pointer; | ||
| 839 | |||
| 840 | /* Disconnect and reset first and last. */ | ||
| 841 | from_this_ptr->prev->next = REL_NIL; | ||
| 842 | last_pointer = from_this_ptr->prev; | ||
| 843 | pointer_list = from_this_ptr; | ||
| 844 | pointer_list->prev = REL_NIL; | ||
| 845 | |||
| 846 | return total_size; /* of space moved. */ | ||
| 847 | } | ||
| 848 | |||
| 849 | /* Relocate any blocks neccessary, either upwards or downwards, | ||
| 850 | to obtain a space of SIZE bytes. Assumes we have at least one block. */ | ||
| 851 | |||
| 852 | static unsigned int | ||
| 853 | relocate (size) | ||
| 854 | register int size; | ||
| 855 | { | ||
| 856 | register relocatable_pointer *ptr; | ||
| 857 | register int got = 0; | ||
| 858 | |||
| 859 | if (size > 0) /* Up: Relocate enough blocs to get SIZE. */ | ||
| 860 | { | ||
| 861 | register POINTER new_space; | ||
| 862 | |||
| 863 | for (ptr = pointer_list; got < size && ptr; ptr = ptr->next) | ||
| 864 | got += ptr->size; | ||
| 865 | |||
| 866 | if (ptr == REL_NIL) | ||
| 867 | ptr = last_pointer; | ||
| 868 | |||
| 869 | new_space = get_more_space (size); | ||
| 870 | if (!new_space) | ||
| 871 | return 0; | ||
| 872 | |||
| 873 | return (relocate_to_end (ptr, pointer_list->block + size)); | ||
| 874 | } | ||
| 875 | |||
| 876 | if (size < 0) /* Down: relocate as many blocs as will | ||
| 877 | fit in SIZE bytes of space. */ | ||
| 878 | { | ||
| 879 | register POINTER to_zone; | ||
| 880 | unsigned int moved; | ||
| 881 | |||
| 882 | for (ptr = last_pointer; got >= size && ptr; ptr = ptr->prev) | ||
| 883 | got -= ptr->size; | ||
| 884 | |||
| 885 | if (ptr == REL_NIL) | ||
| 886 | ptr = pointer_list; | ||
| 887 | else | ||
| 888 | { | ||
| 889 | /* Back off one block to be <= size */ | ||
| 890 | got += ptr->size; | ||
| 891 | ptr = ptr->next; | ||
| 892 | } | ||
| 893 | |||
| 894 | if (got >= size) | ||
| 895 | { | ||
| 896 | to_zone = virtual_break_value - size + got; | ||
| 897 | moved = relocate_to_beginning (ptr, to_zone); | ||
| 898 | if (moved) | ||
| 899 | return_space (moved); | ||
| 900 | |||
| 901 | return moved; | ||
| 902 | } | ||
| 903 | |||
| 904 | return 0; | ||
| 905 | } | ||
| 906 | |||
| 907 | abort (); | ||
| 908 | } | ||
| 909 | |||
| 910 | /* This function encapsulates `sbrk' to preserve the relocatable blocks. | ||
| 911 | It is called just like `sbrk'. When relocatable blocks are in use, | ||
| 912 | `malloc' must use this function instead of `sbrk'. */ | ||
| 913 | |||
| 914 | POINTER | ||
| 915 | r_alloc_sbrk (size) | ||
| 916 | unsigned int size; | ||
| 917 | { | ||
| 918 | POINTER new_zone; /* Start of the zone we will return. */ | ||
| 919 | |||
| 920 | #if 0 | ||
| 921 | if (! r_alloc_in_use) | ||
| 922 | return (POINTER) sbrk (size); | ||
| 923 | #endif | ||
| 924 | |||
| 925 | if (size == 0) | ||
| 926 | return virtual_break_value; | ||
| 927 | |||
| 928 | if (size > 0) /* Get more space */ | ||
| 929 | { | ||
| 930 | register unsigned int space; | ||
| 931 | |||
| 932 | if (pointer_list == REL_NIL) | ||
| 933 | { | ||
| 934 | POINTER space = get_more_space (size); | ||
| 935 | |||
| 936 | virtual_break_value = real_break_value; | ||
| 937 | return space; | ||
| 938 | } | ||
| 939 | |||
| 940 | new_zone = virtual_break_value; | ||
| 941 | |||
| 942 | /* Check if there is a hole just before the buffer zone. */ | ||
| 943 | if (holes && r_alloc_holes[0].address == virtual_break_value) | ||
| 944 | { | ||
| 945 | if (r_alloc_holes[0].size > size) | ||
| 946 | { | ||
| 947 | /* Adjust the hole size. */ | ||
| 948 | r_alloc_holes[0].size -= size; | ||
| 949 | r_alloc_holes[0].address += size; | ||
| 950 | virtual_break_value += size; | ||
| 951 | |||
| 952 | return new_zone; | ||
| 953 | } | ||
| 954 | |||
| 955 | if (r_alloc_holes[0].size == size) | ||
| 956 | { | ||
| 957 | virtual_break_value += size; | ||
| 958 | delete_hole (0); | ||
| 959 | |||
| 960 | return new_zone; | ||
| 961 | } | ||
| 962 | |||
| 963 | /* Adjust the size requested by space | ||
| 964 | already available in this hole. */ | ||
| 965 | size -= r_alloc_holes[0].size; | ||
| 966 | virtual_break_value += r_alloc_holes[0].size; | ||
| 967 | delete_hole (0); | ||
| 968 | } | ||
| 969 | |||
| 970 | space = relocate (size); | ||
| 971 | if (!space) | ||
| 972 | return (POINTER) -1; | ||
| 973 | |||
| 974 | #ifdef REL_ALLOC_SAVE_SPACE | ||
| 975 | move_blocks_downward | ||
| 976 | #else | ||
| 977 | bzero (new_zone, space); | ||
| 978 | if (space > size) | ||
| 979 | note_hole (new_zone + size, space - size); | ||
| 980 | #endif /* REL_ALLOC_SAVE_SPACE */ | ||
| 981 | |||
| 982 | virtual_break_value += size; | ||
| 983 | return new_zone; | ||
| 984 | } | ||
| 985 | else /* Return space to system */ | ||
| 986 | { | ||
| 987 | int moved; | ||
| 988 | int left_over; | ||
| 989 | POINTER old_break_value; | ||
| 990 | |||
| 991 | if (pointer_list == REL_NIL) | ||
| 992 | { | ||
| 993 | POINTER space = return_space (-size); | ||
| 994 | virtual_break_value = real_break_value; | ||
| 995 | |||
| 996 | return space; | ||
| 997 | } | ||
| 998 | |||
| 999 | if (holes && r_alloc_holes[0].address == virtual_break_value) | ||
| 1000 | { | ||
| 1001 | size -= r_alloc_holes[0].size; | ||
| 1002 | delete_hole (0); | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | moved = relocate (size); | ||
| 1006 | old_break_value = virtual_break_value; | ||
| 1007 | |||
| 1008 | if (!moved) | ||
| 1009 | return (POINTER) -1; | ||
| 1010 | |||
| 1011 | left_over = moved + size; | ||
| 1012 | virtual_break_value += size; | ||
| 1013 | |||
| 1014 | if (left_over) | ||
| 1015 | { | ||
| 1016 | #ifdef REL_ALLOC_SAVE_SPACE | ||
| 1017 | move_blocks_downward | ||
| 1018 | #else | ||
| 1019 | bzero (virtual_break_value, left_over); | ||
| 1020 | note_hole (virtual_break_value, left_over); | ||
| 1021 | #endif /* not REL_ALLOC_SAVE_SPACE */ | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | return old_break_value; | ||
| 1025 | } | ||
| 1026 | } | ||
| 1027 | |||
| 1028 | /* For debugging */ | ||
| 1029 | |||
| 1030 | #include <stdio.h> | ||
| 1031 | |||
| 1032 | void | ||
| 1033 | memory_trace () | ||
| 1034 | { | ||
| 1035 | relocatable_pointer *ptr; | ||
| 1036 | int i; | ||
| 1037 | |||
| 1038 | fprintf (stderr, "virtual: 0x%x\n real: 0x%x\n true: 0x%x\n\n", | ||
| 1039 | virtual_break_value, real_break_value, true_break_value); | ||
| 1040 | fprintf (stderr, "Blocks:\n"); | ||
| 1041 | for (ptr = pointer_list; ptr; ptr = ptr->next) | ||
| 1042 | { | ||
| 1043 | fprintf (stderr, " address: 0x%x\n", ptr->block); | ||
| 1044 | fprintf (stderr, " size: 0x%x\n", ptr->size); | ||
| 1045 | if (ptr->others) | ||
| 1046 | { | ||
| 1047 | struct other_pointer *op = ptr->others; | ||
| 1048 | fprintf (stderr, " others:", ptr->size); | ||
| 1049 | while (op) | ||
| 1050 | { | ||
| 1051 | fprintf (stderr, " 0x%x", op->location); | ||
| 1052 | op = op->next; | ||
| 1053 | } | ||
| 1054 | fprintf (stderr, "\n"); | ||
| 1055 | } | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | if (holes) | ||
| 1059 | { | ||
| 1060 | fprintf (stderr, "\nHoles:\n"); | ||
| 1061 | for (i = 0; i < holes; i++) | ||
| 1062 | { | ||
| 1063 | fprintf (stderr, " address: 0x%x\n", r_alloc_holes[i].address); | ||
| 1064 | fprintf (stderr, " size: 0x%x\n", r_alloc_holes[i].size); | ||
| 1065 | } | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | fprintf (stderr, "\n\n"); | ||
| 1069 | } | ||
diff --git a/src/sol2-2.h b/src/sol2-2.h deleted file mode 100644 index 016f75e488a..00000000000 --- a/src/sol2-2.h +++ /dev/null | |||
| @@ -1,18 +0,0 @@ | |||
| 1 | /* casper@fwi.uva.nl says this file is not needed | ||
| 2 | and sol2.h should work. */ | ||
| 3 | |||
| 4 | #include "sol2.h" | ||
| 5 | |||
| 6 | /* Take care of libucb.a as well as X Windows. */ | ||
| 7 | #undef LD_SWITCH_SYSTEM | ||
| 8 | #ifndef __GNUC__ | ||
| 9 | #define LD_SWITCH_SYSTEM -R/usr/openwin/lib:/usr/ucblib | ||
| 10 | #else /* GCC */ | ||
| 11 | #define LD_SWITCH_SYSTEM -Xlinker -R/usr/openwin/lib:/usr/ucblib | ||
| 12 | #endif /* GCC */ | ||
| 13 | |||
| 14 | /* Link with libucb.a. */ | ||
| 15 | #ifdef LIB_STANDARD | ||
| 16 | #undef LIB_STANDARD | ||
| 17 | #define LIB_STANDARD -lc -L/usr/ucblib -lucb | ||
| 18 | #endif | ||
diff --git a/src/unexelf1.c b/src/unexelf1.c deleted file mode 100644 index a832755167e..00000000000 --- a/src/unexelf1.c +++ /dev/null | |||
| @@ -1,952 +0,0 @@ | |||
| 1 | /* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992 | ||
| 2 | Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2, or (at your option) | ||
| 9 | any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 18 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 19 | Boston, MA 02111-1307, USA. | ||
| 20 | |||
| 21 | In other words, you are welcome to use, share and improve this program. | ||
| 22 | You are forbidden to forbid anyone else to use, share and improve | ||
| 23 | what you give them. Help stamp out software-hoarding! */ | ||
| 24 | |||
| 25 | |||
| 26 | /* | ||
| 27 | * unexec.c - Convert a running program into an a.out file. | ||
| 28 | * | ||
| 29 | * Author: Spencer W. Thomas | ||
| 30 | * Computer Science Dept. | ||
| 31 | * University of Utah | ||
| 32 | * Date: Tue Mar 2 1982 | ||
| 33 | * Modified heavily since then. | ||
| 34 | * | ||
| 35 | * Synopsis: | ||
| 36 | * unexec (new_name, a_name, data_start, bss_start, entry_address) | ||
| 37 | * char *new_name, *a_name; | ||
| 38 | * unsigned data_start, bss_start, entry_address; | ||
| 39 | * | ||
| 40 | * Takes a snapshot of the program and makes an a.out format file in the | ||
| 41 | * file named by the string argument new_name. | ||
| 42 | * If a_name is non-NULL, the symbol table will be taken from the given file. | ||
| 43 | * On some machines, an existing a_name file is required. | ||
| 44 | * | ||
| 45 | * The boundaries within the a.out file may be adjusted with the data_start | ||
| 46 | * and bss_start arguments. Either or both may be given as 0 for defaults. | ||
| 47 | * | ||
| 48 | * Data_start gives the boundary between the text segment and the data | ||
| 49 | * segment of the program. The text segment can contain shared, read-only | ||
| 50 | * program code and literal data, while the data segment is always unshared | ||
| 51 | * and unprotected. Data_start gives the lowest unprotected address. | ||
| 52 | * The value you specify may be rounded down to a suitable boundary | ||
| 53 | * as required by the machine you are using. | ||
| 54 | * | ||
| 55 | * Specifying zero for data_start means the boundary between text and data | ||
| 56 | * should not be the same as when the program was loaded. | ||
| 57 | * If NO_REMAP is defined, the argument data_start is ignored and the | ||
| 58 | * segment boundaries are never changed. | ||
| 59 | * | ||
| 60 | * Bss_start indicates how much of the data segment is to be saved in the | ||
| 61 | * a.out file and restored when the program is executed. It gives the lowest | ||
| 62 | * unsaved address, and is rounded up to a page boundary. The default when 0 | ||
| 63 | * is given assumes that the entire data segment is to be stored, including | ||
| 64 | * the previous data and bss as well as any additional storage allocated with | ||
| 65 | * break (2). | ||
| 66 | * | ||
| 67 | * The new file is set up to start at entry_address. | ||
| 68 | * | ||
| 69 | * If you make improvements I'd like to get them too. | ||
| 70 | * harpo!utah-cs!thomas, thomas@Utah-20 | ||
| 71 | * | ||
| 72 | */ | ||
| 73 | |||
| 74 | /* Even more heavily modified by james@bigtex.cactus.org of Dell Computer Co. | ||
| 75 | * ELF support added. | ||
| 76 | * | ||
| 77 | * Basic theory: the data space of the running process needs to be | ||
| 78 | * dumped to the output file. Normally we would just enlarge the size | ||
| 79 | * of .data, scooting everything down. But we can't do that in ELF, | ||
| 80 | * because there is often something between the .data space and the | ||
| 81 | * .bss space. | ||
| 82 | * | ||
| 83 | * In the temacs dump below, notice that the Global Offset Table | ||
| 84 | * (.got) and the Dynamic link data (.dynamic) come between .data1 and | ||
| 85 | * .bss. It does not work to overlap .data with these fields. | ||
| 86 | * | ||
| 87 | * The solution is to create a new .data segment. This segment is | ||
| 88 | * filled with data from the current process. Since the contents of | ||
| 89 | * various sections refer to sections by index, the new .data segment | ||
| 90 | * is made the last in the table to avoid changing any existing index. | ||
| 91 | |||
| 92 | * This is an example of how the section headers are changed. "Addr" | ||
| 93 | * is a process virtual address. "Offset" is a file offset. | ||
| 94 | |||
| 95 | raid:/nfs/raid/src/dist-18.56/src> dump -h temacs | ||
| 96 | |||
| 97 | temacs: | ||
| 98 | |||
| 99 | **** SECTION HEADER TABLE **** | ||
| 100 | [No] Type Flags Addr Offset Size Name | ||
| 101 | Link Info Adralgn Entsize | ||
| 102 | |||
| 103 | [1] 1 2 0x80480d4 0xd4 0x13 .interp | ||
| 104 | 0 0 0x1 0 | ||
| 105 | |||
| 106 | [2] 5 2 0x80480e8 0xe8 0x388 .hash | ||
| 107 | 3 0 0x4 0x4 | ||
| 108 | |||
| 109 | [3] 11 2 0x8048470 0x470 0x7f0 .dynsym | ||
| 110 | 4 1 0x4 0x10 | ||
| 111 | |||
| 112 | [4] 3 2 0x8048c60 0xc60 0x3ad .dynstr | ||
| 113 | 0 0 0x1 0 | ||
| 114 | |||
| 115 | [5] 9 2 0x8049010 0x1010 0x338 .rel.plt | ||
| 116 | 3 7 0x4 0x8 | ||
| 117 | |||
| 118 | [6] 1 6 0x8049348 0x1348 0x3 .init | ||
| 119 | 0 0 0x4 0 | ||
| 120 | |||
| 121 | [7] 1 6 0x804934c 0x134c 0x680 .plt | ||
| 122 | 0 0 0x4 0x4 | ||
| 123 | |||
| 124 | [8] 1 6 0x80499cc 0x19cc 0x3c56f .text | ||
| 125 | 0 0 0x4 0 | ||
| 126 | |||
| 127 | [9] 1 6 0x8085f3c 0x3df3c 0x3 .fini | ||
| 128 | 0 0 0x4 0 | ||
| 129 | |||
| 130 | [10] 1 2 0x8085f40 0x3df40 0x69c .rodata | ||
| 131 | 0 0 0x4 0 | ||
| 132 | |||
| 133 | [11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1 | ||
| 134 | 0 0 0x4 0 | ||
| 135 | |||
| 136 | [12] 1 3 0x8088330 0x3f330 0x20afc .data | ||
| 137 | 0 0 0x4 0 | ||
| 138 | |||
| 139 | [13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1 | ||
| 140 | 0 0 0x4 0 | ||
| 141 | |||
| 142 | [14] 1 3 0x80a96cc 0x606cc 0x1a8 .got | ||
| 143 | 0 0 0x4 0x4 | ||
| 144 | |||
| 145 | [15] 6 3 0x80a9874 0x60874 0x80 .dynamic | ||
| 146 | 4 0 0x4 0x8 | ||
| 147 | |||
| 148 | [16] 8 3 0x80a98f4 0x608f4 0x449c .bss | ||
| 149 | 0 0 0x4 0 | ||
| 150 | |||
| 151 | [17] 2 0 0 0x608f4 0x9b90 .symtab | ||
| 152 | 18 371 0x4 0x10 | ||
| 153 | |||
| 154 | [18] 3 0 0 0x6a484 0x8526 .strtab | ||
| 155 | 0 0 0x1 0 | ||
| 156 | |||
| 157 | [19] 3 0 0 0x729aa 0x93 .shstrtab | ||
| 158 | 0 0 0x1 0 | ||
| 159 | |||
| 160 | [20] 1 0 0 0x72a3d 0x68b7 .comment | ||
| 161 | 0 0 0x1 0 | ||
| 162 | |||
| 163 | raid:/nfs/raid/src/dist-18.56/src> dump -h xemacs | ||
| 164 | |||
| 165 | xemacs: | ||
| 166 | |||
| 167 | **** SECTION HEADER TABLE **** | ||
| 168 | [No] Type Flags Addr Offset Size Name | ||
| 169 | Link Info Adralgn Entsize | ||
| 170 | |||
| 171 | [1] 1 2 0x80480d4 0xd4 0x13 .interp | ||
| 172 | 0 0 0x1 0 | ||
| 173 | |||
| 174 | [2] 5 2 0x80480e8 0xe8 0x388 .hash | ||
| 175 | 3 0 0x4 0x4 | ||
| 176 | |||
| 177 | [3] 11 2 0x8048470 0x470 0x7f0 .dynsym | ||
| 178 | 4 1 0x4 0x10 | ||
| 179 | |||
| 180 | [4] 3 2 0x8048c60 0xc60 0x3ad .dynstr | ||
| 181 | 0 0 0x1 0 | ||
| 182 | |||
| 183 | [5] 9 2 0x8049010 0x1010 0x338 .rel.plt | ||
| 184 | 3 7 0x4 0x8 | ||
| 185 | |||
| 186 | [6] 1 6 0x8049348 0x1348 0x3 .init | ||
| 187 | 0 0 0x4 0 | ||
| 188 | |||
| 189 | [7] 1 6 0x804934c 0x134c 0x680 .plt | ||
| 190 | 0 0 0x4 0x4 | ||
| 191 | |||
| 192 | [8] 1 6 0x80499cc 0x19cc 0x3c56f .text | ||
| 193 | 0 0 0x4 0 | ||
| 194 | |||
| 195 | [9] 1 6 0x8085f3c 0x3df3c 0x3 .fini | ||
| 196 | 0 0 0x4 0 | ||
| 197 | |||
| 198 | [10] 1 2 0x8085f40 0x3df40 0x69c .rodata | ||
| 199 | 0 0 0x4 0 | ||
| 200 | |||
| 201 | [11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1 | ||
| 202 | 0 0 0x4 0 | ||
| 203 | |||
| 204 | [12] 1 3 0x8088330 0x3f330 0x20afc .data | ||
| 205 | 0 0 0x4 0 | ||
| 206 | |||
| 207 | [13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1 | ||
| 208 | 0 0 0x4 0 | ||
| 209 | |||
| 210 | [14] 1 3 0x80a96cc 0x606cc 0x1a8 .got | ||
| 211 | 0 0 0x4 0x4 | ||
| 212 | |||
| 213 | [15] 6 3 0x80a9874 0x60874 0x80 .dynamic | ||
| 214 | 4 0 0x4 0x8 | ||
| 215 | |||
| 216 | [16] 8 3 0x80c6800 0x7d800 0 .bss | ||
| 217 | 0 0 0x4 0 | ||
| 218 | |||
| 219 | [17] 2 0 0 0x7d800 0x9b90 .symtab | ||
| 220 | 18 371 0x4 0x10 | ||
| 221 | |||
| 222 | [18] 3 0 0 0x87390 0x8526 .strtab | ||
| 223 | 0 0 0x1 0 | ||
| 224 | |||
| 225 | [19] 3 0 0 0x8f8b6 0x93 .shstrtab | ||
| 226 | 0 0 0x1 0 | ||
| 227 | |||
| 228 | [20] 1 0 0 0x8f949 0x68b7 .comment | ||
| 229 | 0 0 0x1 0 | ||
| 230 | |||
| 231 | [21] 1 3 0x80a98f4 0x608f4 0x1cf0c .data | ||
| 232 | 0 0 0x4 0 | ||
| 233 | |||
| 234 | * This is an example of how the file header is changed. "Shoff" is | ||
| 235 | * the section header offset within the file. Since that table is | ||
| 236 | * after the new .data section, it is moved. "Shnum" is the number of | ||
| 237 | * sections, which we increment. | ||
| 238 | * | ||
| 239 | * "Phoff" is the file offset to the program header. "Phentsize" and | ||
| 240 | * "Shentsz" are the program and section header entries sizes respectively. | ||
| 241 | * These can be larger than the apparent struct sizes. | ||
| 242 | |||
| 243 | raid:/nfs/raid/src/dist-18.56/src> dump -f temacs | ||
| 244 | |||
| 245 | temacs: | ||
| 246 | |||
| 247 | **** ELF HEADER **** | ||
| 248 | Class Data Type Machine Version | ||
| 249 | Entry Phoff Shoff Flags Ehsize | ||
| 250 | Phentsize Phnum Shentsz Shnum Shstrndx | ||
| 251 | |||
| 252 | 1 1 2 3 1 | ||
| 253 | 0x80499cc 0x34 0x792f4 0 0x34 | ||
| 254 | 0x20 5 0x28 21 19 | ||
| 255 | |||
| 256 | raid:/nfs/raid/src/dist-18.56/src> dump -f xemacs | ||
| 257 | |||
| 258 | xemacs: | ||
| 259 | |||
| 260 | **** ELF HEADER **** | ||
| 261 | Class Data Type Machine Version | ||
| 262 | Entry Phoff Shoff Flags Ehsize | ||
| 263 | Phentsize Phnum Shentsz Shnum Shstrndx | ||
| 264 | |||
| 265 | 1 1 2 3 1 | ||
| 266 | 0x80499cc 0x34 0x96200 0 0x34 | ||
| 267 | 0x20 5 0x28 22 19 | ||
| 268 | |||
| 269 | * These are the program headers. "Offset" is the file offset to the | ||
| 270 | * segment. "Vaddr" is the memory load address. "Filesz" is the | ||
| 271 | * segment size as it appears in the file, and "Memsz" is the size in | ||
| 272 | * memory. Below, the third segment is the code and the fourth is the | ||
| 273 | * data: the difference between Filesz and Memsz is .bss | ||
| 274 | |||
| 275 | raid:/nfs/raid/src/dist-18.56/src> dump -o temacs | ||
| 276 | |||
| 277 | temacs: | ||
| 278 | ***** PROGRAM EXECUTION HEADER ***** | ||
| 279 | Type Offset Vaddr Paddr | ||
| 280 | Filesz Memsz Flags Align | ||
| 281 | |||
| 282 | 6 0x34 0x8048034 0 | ||
| 283 | 0xa0 0xa0 5 0 | ||
| 284 | |||
| 285 | 3 0xd4 0 0 | ||
| 286 | 0x13 0 4 0 | ||
| 287 | |||
| 288 | 1 0x34 0x8048034 0 | ||
| 289 | 0x3f2f9 0x3f2f9 5 0x1000 | ||
| 290 | |||
| 291 | 1 0x3f330 0x8088330 0 | ||
| 292 | 0x215c4 0x25a60 7 0x1000 | ||
| 293 | |||
| 294 | 2 0x60874 0x80a9874 0 | ||
| 295 | 0x80 0 7 0 | ||
| 296 | |||
| 297 | raid:/nfs/raid/src/dist-18.56/src> dump -o xemacs | ||
| 298 | |||
| 299 | xemacs: | ||
| 300 | ***** PROGRAM EXECUTION HEADER ***** | ||
| 301 | Type Offset Vaddr Paddr | ||
| 302 | Filesz Memsz Flags Align | ||
| 303 | |||
| 304 | 6 0x34 0x8048034 0 | ||
| 305 | 0xa0 0xa0 5 0 | ||
| 306 | |||
| 307 | 3 0xd4 0 0 | ||
| 308 | 0x13 0 4 0 | ||
| 309 | |||
| 310 | 1 0x34 0x8048034 0 | ||
| 311 | 0x3f2f9 0x3f2f9 5 0x1000 | ||
| 312 | |||
| 313 | 1 0x3f330 0x8088330 0 | ||
| 314 | 0x3e4d0 0x3e4d0 7 0x1000 | ||
| 315 | |||
| 316 | 2 0x60874 0x80a9874 0 | ||
| 317 | 0x80 0 7 0 | ||
| 318 | |||
| 319 | |||
| 320 | */ | ||
| 321 | |||
| 322 | /* Modified by wtien@urbana.mcd.mot.com of Motorola Inc. | ||
| 323 | * | ||
| 324 | * The above mechanism does not work if the unexeced ELF file is being | ||
| 325 | * re-layout by other applications (such as `strip'). All the applications | ||
| 326 | * that re-layout the internal of ELF will layout all sections in ascending | ||
| 327 | * order of their file offsets. After the re-layout, the data2 section will | ||
| 328 | * still be the LAST section in the section header vector, but its file offset | ||
| 329 | * is now being pushed far away down, and causes part of it not to be mapped | ||
| 330 | * in (ie. not covered by the load segment entry in PHDR vector), therefore | ||
| 331 | * causes the new binary to fail. | ||
| 332 | * | ||
| 333 | * The solution is to modify the unexec algorithm to insert the new data2 | ||
| 334 | * section header right before the new bss section header, so their file | ||
| 335 | * offsets will be in the ascending order. Since some of the section's (all | ||
| 336 | * sections AFTER the bss section) indexes are now changed, we also need to | ||
| 337 | * modify some fields to make them point to the right sections. This is done | ||
| 338 | * by macro PATCH_INDEX. All the fields that need to be patched are: | ||
| 339 | * | ||
| 340 | * 1. ELF header e_shstrndx field. | ||
| 341 | * 2. section header sh_link and sh_info field. | ||
| 342 | * 3. symbol table entry st_shndx field. | ||
| 343 | * | ||
| 344 | * The above example now should look like: | ||
| 345 | |||
| 346 | **** SECTION HEADER TABLE **** | ||
| 347 | [No] Type Flags Addr Offset Size Name | ||
| 348 | Link Info Adralgn Entsize | ||
| 349 | |||
| 350 | [1] 1 2 0x80480d4 0xd4 0x13 .interp | ||
| 351 | 0 0 0x1 0 | ||
| 352 | |||
| 353 | [2] 5 2 0x80480e8 0xe8 0x388 .hash | ||
| 354 | 3 0 0x4 0x4 | ||
| 355 | |||
| 356 | [3] 11 2 0x8048470 0x470 0x7f0 .dynsym | ||
| 357 | 4 1 0x4 0x10 | ||
| 358 | |||
| 359 | [4] 3 2 0x8048c60 0xc60 0x3ad .dynstr | ||
| 360 | 0 0 0x1 0 | ||
| 361 | |||
| 362 | [5] 9 2 0x8049010 0x1010 0x338 .rel.plt | ||
| 363 | 3 7 0x4 0x8 | ||
| 364 | |||
| 365 | [6] 1 6 0x8049348 0x1348 0x3 .init | ||
| 366 | 0 0 0x4 0 | ||
| 367 | |||
| 368 | [7] 1 6 0x804934c 0x134c 0x680 .plt | ||
| 369 | 0 0 0x4 0x4 | ||
| 370 | |||
| 371 | [8] 1 6 0x80499cc 0x19cc 0x3c56f .text | ||
| 372 | 0 0 0x4 0 | ||
| 373 | |||
| 374 | [9] 1 6 0x8085f3c 0x3df3c 0x3 .fini | ||
| 375 | 0 0 0x4 0 | ||
| 376 | |||
| 377 | [10] 1 2 0x8085f40 0x3df40 0x69c .rodata | ||
| 378 | 0 0 0x4 0 | ||
| 379 | |||
| 380 | [11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1 | ||
| 381 | 0 0 0x4 0 | ||
| 382 | |||
| 383 | [12] 1 3 0x8088330 0x3f330 0x20afc .data | ||
| 384 | 0 0 0x4 0 | ||
| 385 | |||
| 386 | [13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1 | ||
| 387 | 0 0 0x4 0 | ||
| 388 | |||
| 389 | [14] 1 3 0x80a96cc 0x606cc 0x1a8 .got | ||
| 390 | 0 0 0x4 0x4 | ||
| 391 | |||
| 392 | [15] 6 3 0x80a9874 0x60874 0x80 .dynamic | ||
| 393 | 4 0 0x4 0x8 | ||
| 394 | |||
| 395 | [16] 1 3 0x80a98f4 0x608f4 0x1cf0c .data | ||
| 396 | 0 0 0x4 0 | ||
| 397 | |||
| 398 | [17] 8 3 0x80c6800 0x7d800 0 .bss | ||
| 399 | 0 0 0x4 0 | ||
| 400 | |||
| 401 | [18] 2 0 0 0x7d800 0x9b90 .symtab | ||
| 402 | 19 371 0x4 0x10 | ||
| 403 | |||
| 404 | [19] 3 0 0 0x87390 0x8526 .strtab | ||
| 405 | 0 0 0x1 0 | ||
| 406 | |||
| 407 | [20] 3 0 0 0x8f8b6 0x93 .shstrtab | ||
| 408 | 0 0 0x1 0 | ||
| 409 | |||
| 410 | [21] 1 0 0 0x8f949 0x68b7 .comment | ||
| 411 | 0 0 0x1 0 | ||
| 412 | |||
| 413 | */ | ||
| 414 | |||
| 415 | #include <sys/types.h> | ||
| 416 | #include <stdio.h> | ||
| 417 | #include <sys/stat.h> | ||
| 418 | #include <memory.h> | ||
| 419 | #include <string.h> | ||
| 420 | #include <errno.h> | ||
| 421 | #include <unistd.h> | ||
| 422 | #include <fcntl.h> | ||
| 423 | #include <elf.h> | ||
| 424 | #include <sys/mman.h> | ||
| 425 | |||
| 426 | #ifdef __alpha__ | ||
| 427 | # include <sym.h> /* get COFF debugging symbol table declaration */ | ||
| 428 | #endif | ||
| 429 | |||
| 430 | #if __GNU_LIBRARY__ - 0 >= 6 | ||
| 431 | # include <link.h> /* get ElfW etc */ | ||
| 432 | #endif | ||
| 433 | |||
| 434 | #ifndef ElfW | ||
| 435 | # ifdef __STDC__ | ||
| 436 | # define ElfW(type) Elf32_##type | ||
| 437 | # else | ||
| 438 | # define ElfW(type) Elf32_/**/type | ||
| 439 | # endif | ||
| 440 | #endif | ||
| 441 | |||
| 442 | #ifndef emacs | ||
| 443 | #define fatal(a, b, c) fprintf (stderr, a, b, c), exit (1) | ||
| 444 | #else | ||
| 445 | #include <config.h> | ||
| 446 | extern void fatal (char *, ...); | ||
| 447 | #endif | ||
| 448 | |||
| 449 | #ifndef ELF_BSS_SECTION_NAME | ||
| 450 | #define ELF_BSS_SECTION_NAME ".bss" | ||
| 451 | #endif | ||
| 452 | |||
| 453 | /* Get the address of a particular section or program header entry, | ||
| 454 | * accounting for the size of the entries. | ||
| 455 | */ | ||
| 456 | /* | ||
| 457 | On PPC Reference Platform running Solaris 2.5.1 | ||
| 458 | the plt section is also of type NOBI like the bss section. | ||
| 459 | (not really stored) and therefore sections after the bss | ||
| 460 | section start at the plt offset. The plt section is always | ||
| 461 | the one just before the bss section. | ||
| 462 | Thus, we modify the test from | ||
| 463 | if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset) | ||
| 464 | to | ||
| 465 | if (NEW_SECTION_H (nn).sh_offset >= | ||
| 466 | OLD_SECTION_H (old_bss_index-1).sh_offset) | ||
| 467 | This is just a hack. We should put the new data section | ||
| 468 | before the .plt section. | ||
| 469 | And we should not have this routine at all but use | ||
| 470 | the libelf library to read the old file and create the new | ||
| 471 | file. | ||
| 472 | The changed code is minimal and depends on prep set in m/prep.h | ||
| 473 | Erik Deumens | ||
| 474 | Quantum Theory Project | ||
| 475 | University of Florida | ||
| 476 | deumens@qtp.ufl.edu | ||
| 477 | Apr 23, 1996 | ||
| 478 | */ | ||
| 479 | |||
| 480 | #define OLD_SECTION_H(n) \ | ||
| 481 | (*(ElfW(Shdr) *) ((byte *) old_section_h + old_file_h->e_shentsize * (n))) | ||
| 482 | #define NEW_SECTION_H(n) \ | ||
| 483 | (*(ElfW(Shdr) *) ((byte *) new_section_h + new_file_h->e_shentsize * (n))) | ||
| 484 | #define OLD_PROGRAM_H(n) \ | ||
| 485 | (*(ElfW(Phdr) *) ((byte *) old_program_h + old_file_h->e_phentsize * (n))) | ||
| 486 | #define NEW_PROGRAM_H(n) \ | ||
| 487 | (*(ElfW(Phdr) *) ((byte *) new_program_h + new_file_h->e_phentsize * (n))) | ||
| 488 | |||
| 489 | #define PATCH_INDEX(n) \ | ||
| 490 | do { \ | ||
| 491 | if ((int) (n) >= old_bss_index) \ | ||
| 492 | (n)++; } while (0) | ||
| 493 | typedef unsigned char byte; | ||
| 494 | |||
| 495 | /* Round X up to a multiple of Y. */ | ||
| 496 | |||
| 497 | int | ||
| 498 | round_up (x, y) | ||
| 499 | int x, y; | ||
| 500 | { | ||
| 501 | int rem = x % y; | ||
| 502 | if (rem == 0) | ||
| 503 | return x; | ||
| 504 | return x - rem + y; | ||
| 505 | } | ||
| 506 | |||
| 507 | /* **************************************************************** | ||
| 508 | * unexec | ||
| 509 | * | ||
| 510 | * driving logic. | ||
| 511 | * | ||
| 512 | * In ELF, this works by replacing the old .bss section with a new | ||
| 513 | * .data section, and inserting an empty .bss immediately afterwards. | ||
| 514 | * | ||
| 515 | */ | ||
| 516 | void | ||
| 517 | unexec (new_name, old_name, data_start, bss_start, entry_address) | ||
| 518 | char *new_name, *old_name; | ||
| 519 | unsigned data_start, bss_start, entry_address; | ||
| 520 | { | ||
| 521 | int new_file, old_file, new_file_size; | ||
| 522 | |||
| 523 | /* Pointers to the base of the image of the two files. */ | ||
| 524 | caddr_t old_base, new_base; | ||
| 525 | |||
| 526 | /* Pointers to the file, program and section headers for the old and new | ||
| 527 | * files. | ||
| 528 | */ | ||
| 529 | ElfW(Ehdr) *old_file_h, *new_file_h; | ||
| 530 | ElfW(Phdr) *old_program_h, *new_program_h; | ||
| 531 | ElfW(Shdr) *old_section_h, *new_section_h; | ||
| 532 | |||
| 533 | /* Point to the section name table in the old file */ | ||
| 534 | char *old_section_names; | ||
| 535 | |||
| 536 | ElfW(Addr) old_bss_addr, new_bss_addr; | ||
| 537 | ElfW(Word) old_bss_size, new_data2_size; | ||
| 538 | ElfW(Off) new_data2_offset; | ||
| 539 | ElfW(Addr) new_data2_addr; | ||
| 540 | |||
| 541 | int n, nn, old_bss_index, old_data_index, new_data2_index; | ||
| 542 | struct stat stat_buf; | ||
| 543 | |||
| 544 | /* Open the old file & map it into the address space. */ | ||
| 545 | |||
| 546 | old_file = open (old_name, O_RDONLY); | ||
| 547 | |||
| 548 | if (old_file < 0) | ||
| 549 | fatal ("Can't open %s for reading: errno %d\n", old_name, errno); | ||
| 550 | |||
| 551 | if (fstat (old_file, &stat_buf) == -1) | ||
| 552 | fatal ("Can't fstat (%s): errno %d\n", old_name, errno); | ||
| 553 | |||
| 554 | old_base = mmap (0, stat_buf.st_size, PROT_READ, MAP_SHARED, old_file, 0); | ||
| 555 | |||
| 556 | if (old_base == (caddr_t) -1) | ||
| 557 | fatal ("Can't mmap (%s): errno %d\n", old_name, errno); | ||
| 558 | |||
| 559 | #ifdef DEBUG | ||
| 560 | fprintf (stderr, "mmap (%s, %x) -> %x\n", old_name, stat_buf.st_size, | ||
| 561 | old_base); | ||
| 562 | #endif | ||
| 563 | |||
| 564 | /* Get pointers to headers & section names */ | ||
| 565 | |||
| 566 | old_file_h = (ElfW(Ehdr) *) old_base; | ||
| 567 | old_program_h = (ElfW(Phdr) *) ((byte *) old_base + old_file_h->e_phoff); | ||
| 568 | old_section_h = (ElfW(Shdr) *) ((byte *) old_base + old_file_h->e_shoff); | ||
| 569 | old_section_names = (char *) old_base | ||
| 570 | + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset; | ||
| 571 | |||
| 572 | /* Find the old .bss section. Figure out parameters of the new | ||
| 573 | * data2 and bss sections. | ||
| 574 | */ | ||
| 575 | |||
| 576 | for (old_bss_index = 1; old_bss_index < (int) old_file_h->e_shnum; | ||
| 577 | old_bss_index++) | ||
| 578 | { | ||
| 579 | #ifdef DEBUG | ||
| 580 | fprintf (stderr, "Looking for .bss - found %s\n", | ||
| 581 | old_section_names + OLD_SECTION_H (old_bss_index).sh_name); | ||
| 582 | #endif | ||
| 583 | if (!strcmp (old_section_names + OLD_SECTION_H (old_bss_index).sh_name, | ||
| 584 | ELF_BSS_SECTION_NAME)) | ||
| 585 | break; | ||
| 586 | } | ||
| 587 | if (old_bss_index == old_file_h->e_shnum) | ||
| 588 | fatal ("Can't find .bss in %s.\n", old_name, 0); | ||
| 589 | |||
| 590 | old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; | ||
| 591 | old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; | ||
| 592 | #if defined(emacs) || !defined(DEBUG) | ||
| 593 | new_bss_addr = (ElfW(Addr)) sbrk (0); | ||
| 594 | #else | ||
| 595 | new_bss_addr = old_bss_addr + old_bss_size + 0x1234; | ||
| 596 | #endif | ||
| 597 | new_data2_addr = old_bss_addr; | ||
| 598 | new_data2_size = new_bss_addr - old_bss_addr; | ||
| 599 | new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset; | ||
| 600 | |||
| 601 | #ifdef DEBUG | ||
| 602 | fprintf (stderr, "old_bss_index %d\n", old_bss_index); | ||
| 603 | fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); | ||
| 604 | fprintf (stderr, "old_bss_size %x\n", old_bss_size); | ||
| 605 | fprintf (stderr, "new_bss_addr %x\n", new_bss_addr); | ||
| 606 | fprintf (stderr, "new_data2_addr %x\n", new_data2_addr); | ||
| 607 | fprintf (stderr, "new_data2_size %x\n", new_data2_size); | ||
| 608 | fprintf (stderr, "new_data2_offset %x\n", new_data2_offset); | ||
| 609 | #endif | ||
| 610 | |||
| 611 | if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size) | ||
| 612 | fatal (".bss shrank when undumping???\n", 0, 0); | ||
| 613 | |||
| 614 | /* Set the output file to the right size and mmap it. Set | ||
| 615 | * pointers to various interesting objects. stat_buf still has | ||
| 616 | * old_file data. | ||
| 617 | */ | ||
| 618 | |||
| 619 | new_file = open (new_name, O_RDWR | O_CREAT, 0666); | ||
| 620 | if (new_file < 0) | ||
| 621 | fatal ("Can't creat (%s): errno %d\n", new_name, errno); | ||
| 622 | |||
| 623 | new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size; | ||
| 624 | |||
| 625 | if (ftruncate (new_file, new_file_size)) | ||
| 626 | fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno); | ||
| 627 | |||
| 628 | #ifdef UNEXEC_USE_MAP_PRIVATE | ||
| 629 | new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, | ||
| 630 | new_file, 0); | ||
| 631 | #else | ||
| 632 | new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED, | ||
| 633 | new_file, 0); | ||
| 634 | #endif | ||
| 635 | |||
| 636 | if (new_base == (caddr_t) -1) | ||
| 637 | fatal ("Can't mmap (%s): errno %d\n", new_name, errno); | ||
| 638 | |||
| 639 | new_file_h = (ElfW(Ehdr) *) new_base; | ||
| 640 | new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff); | ||
| 641 | new_section_h = (ElfW(Shdr) *) | ||
| 642 | ((byte *) new_base + old_file_h->e_shoff + new_data2_size); | ||
| 643 | |||
| 644 | /* Make our new file, program and section headers as copies of the | ||
| 645 | * originals. | ||
| 646 | */ | ||
| 647 | |||
| 648 | memcpy (new_file_h, old_file_h, old_file_h->e_ehsize); | ||
| 649 | memcpy (new_program_h, old_program_h, | ||
| 650 | old_file_h->e_phnum * old_file_h->e_phentsize); | ||
| 651 | |||
| 652 | /* Modify the e_shstrndx if necessary. */ | ||
| 653 | PATCH_INDEX (new_file_h->e_shstrndx); | ||
| 654 | |||
| 655 | /* Fix up file header. We'll add one section. Section header is | ||
| 656 | * further away now. | ||
| 657 | */ | ||
| 658 | |||
| 659 | new_file_h->e_shoff += new_data2_size; | ||
| 660 | new_file_h->e_shnum += 1; | ||
| 661 | |||
| 662 | #ifdef DEBUG | ||
| 663 | fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff); | ||
| 664 | fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum); | ||
| 665 | fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff); | ||
| 666 | fprintf (stderr, "New section count %d\n", new_file_h->e_shnum); | ||
| 667 | #endif | ||
| 668 | |||
| 669 | /* Fix up a new program header. Extend the writable data segment so | ||
| 670 | * that the bss area is covered too. Find that segment by looking | ||
| 671 | * for a segment that ends just before the .bss area. Make sure | ||
| 672 | * that no segments are above the new .data2. Put a loop at the end | ||
| 673 | * to adjust the offset and address of any segment that is above | ||
| 674 | * data2, just in case we decide to allow this later. | ||
| 675 | */ | ||
| 676 | |||
| 677 | for (n = new_file_h->e_phnum - 1; n >= 0; n--) | ||
| 678 | { | ||
| 679 | /* Compute maximum of all requirements for alignment of section. */ | ||
| 680 | int alignment = (NEW_PROGRAM_H (n)).p_align; | ||
| 681 | if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) | ||
| 682 | alignment = OLD_SECTION_H (old_bss_index).sh_addralign; | ||
| 683 | |||
| 684 | if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_bss_addr) | ||
| 685 | fatal ("Program segment above .bss in %s\n", old_name, 0); | ||
| 686 | |||
| 687 | if (NEW_PROGRAM_H (n).p_type == PT_LOAD | ||
| 688 | && (round_up ((NEW_PROGRAM_H (n)).p_vaddr | ||
| 689 | + (NEW_PROGRAM_H (n)).p_filesz, | ||
| 690 | alignment) | ||
| 691 | == round_up (old_bss_addr, alignment))) | ||
| 692 | break; | ||
| 693 | } | ||
| 694 | if (n < 0) | ||
| 695 | fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0); | ||
| 696 | |||
| 697 | NEW_PROGRAM_H (n).p_filesz += new_data2_size; | ||
| 698 | NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; | ||
| 699 | |||
| 700 | #if 0 /* Maybe allow section after data2 - does this ever happen? */ | ||
| 701 | for (n = new_file_h->e_phnum - 1; n >= 0; n--) | ||
| 702 | { | ||
| 703 | if (NEW_PROGRAM_H (n).p_vaddr | ||
| 704 | && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr) | ||
| 705 | NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size; | ||
| 706 | |||
| 707 | if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset) | ||
| 708 | NEW_PROGRAM_H (n).p_offset += new_data2_size; | ||
| 709 | } | ||
| 710 | #endif | ||
| 711 | |||
| 712 | /* Fix up section headers based on new .data2 section. Any section | ||
| 713 | * whose offset or virtual address is after the new .data2 section | ||
| 714 | * gets its value adjusted. .bss size becomes zero and new address | ||
| 715 | * is set. data2 section header gets added by copying the existing | ||
| 716 | * .data header and modifying the offset, address and size. | ||
| 717 | */ | ||
| 718 | for (old_data_index = 1; old_data_index < (int) old_file_h->e_shnum; | ||
| 719 | old_data_index++) | ||
| 720 | if (!strcmp (old_section_names + OLD_SECTION_H (old_data_index).sh_name, | ||
| 721 | ".data")) | ||
| 722 | break; | ||
| 723 | if (old_data_index == old_file_h->e_shnum) | ||
| 724 | fatal ("Can't find .data in %s.\n", old_name, 0); | ||
| 725 | |||
| 726 | /* Walk through all section headers, insert the new data2 section right | ||
| 727 | before the new bss section. */ | ||
| 728 | for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++) | ||
| 729 | { | ||
| 730 | caddr_t src; | ||
| 731 | /* If it is bss section, insert the new data2 section before it. */ | ||
| 732 | if (n == old_bss_index) | ||
| 733 | { | ||
| 734 | /* Steal the data section header for this data2 section. */ | ||
| 735 | memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index), | ||
| 736 | new_file_h->e_shentsize); | ||
| 737 | |||
| 738 | NEW_SECTION_H (nn).sh_addr = new_data2_addr; | ||
| 739 | NEW_SECTION_H (nn).sh_offset = new_data2_offset; | ||
| 740 | NEW_SECTION_H (nn).sh_size = new_data2_size; | ||
| 741 | /* Use the bss section's alignment. This will assure that the | ||
| 742 | new data2 section always be placed in the same spot as the old | ||
| 743 | bss section by any other application. */ | ||
| 744 | NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign; | ||
| 745 | |||
| 746 | /* Now copy over what we have in the memory now. */ | ||
| 747 | memcpy (NEW_SECTION_H (nn).sh_offset + new_base, | ||
| 748 | (caddr_t) OLD_SECTION_H (n).sh_addr, | ||
| 749 | new_data2_size); | ||
| 750 | nn++; | ||
| 751 | } | ||
| 752 | |||
| 753 | memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), | ||
| 754 | old_file_h->e_shentsize); | ||
| 755 | |||
| 756 | /* The new bss section's size is zero, and its file offset and virtual | ||
| 757 | address should be off by NEW_DATA2_SIZE. */ | ||
| 758 | if (n == old_bss_index) | ||
| 759 | { | ||
| 760 | /* NN should be `old_bss_index + 1' at this point. */ | ||
| 761 | NEW_SECTION_H (nn).sh_offset += new_data2_size; | ||
| 762 | NEW_SECTION_H (nn).sh_addr += new_data2_size; | ||
| 763 | /* Let the new bss section address alignment be the same as the | ||
| 764 | section address alignment followed the old bss section, so | ||
| 765 | this section will be placed in exactly the same place. */ | ||
| 766 | NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign; | ||
| 767 | NEW_SECTION_H (nn).sh_size = 0; | ||
| 768 | } | ||
| 769 | else | ||
| 770 | { | ||
| 771 | /* Any section that was original placed AFTER the bss | ||
| 772 | section should now be off by NEW_DATA2_SIZE. */ | ||
| 773 | #ifdef SOLARIS_POWERPC | ||
| 774 | /* On PPC Reference Platform running Solaris 2.5.1 | ||
| 775 | the plt section is also of type NOBI like the bss section. | ||
| 776 | (not really stored) and therefore sections after the bss | ||
| 777 | section start at the plt offset. The plt section is always | ||
| 778 | the one just before the bss section. | ||
| 779 | It would be better to put the new data section before | ||
| 780 | the .plt section, or use libelf instead. | ||
| 781 | Erik Deumens, deumens@qtp.ufl.edu. */ | ||
| 782 | if (NEW_SECTION_H (nn).sh_offset | ||
| 783 | >= OLD_SECTION_H (old_bss_index-1).sh_offset) | ||
| 784 | NEW_SECTION_H (nn).sh_offset += new_data2_size; | ||
| 785 | #else | ||
| 786 | if (round_up (NEW_SECTION_H (nn).sh_offset, | ||
| 787 | OLD_SECTION_H (old_bss_index).sh_addralign) | ||
| 788 | >= new_data2_offset) | ||
| 789 | NEW_SECTION_H (nn).sh_offset += new_data2_size; | ||
| 790 | #endif | ||
| 791 | /* Any section that was originally placed after the section | ||
| 792 | header table should now be off by the size of one section | ||
| 793 | header table entry. */ | ||
| 794 | if (NEW_SECTION_H (nn).sh_offset > new_file_h->e_shoff) | ||
| 795 | NEW_SECTION_H (nn).sh_offset += new_file_h->e_shentsize; | ||
| 796 | } | ||
| 797 | |||
| 798 | /* If any section hdr refers to the section after the new .data | ||
| 799 | section, make it refer to next one because we have inserted | ||
| 800 | a new section in between. */ | ||
| 801 | |||
| 802 | PATCH_INDEX (NEW_SECTION_H (nn).sh_link); | ||
| 803 | /* For symbol tables, info is a symbol table index, | ||
| 804 | so don't change it. */ | ||
| 805 | if (NEW_SECTION_H (nn).sh_type != SHT_SYMTAB | ||
| 806 | && NEW_SECTION_H (nn).sh_type != SHT_DYNSYM) | ||
| 807 | PATCH_INDEX (NEW_SECTION_H (nn).sh_info); | ||
| 808 | |||
| 809 | /* Now, start to copy the content of sections. */ | ||
| 810 | if (NEW_SECTION_H (nn).sh_type == SHT_NULL | ||
| 811 | || NEW_SECTION_H (nn).sh_type == SHT_NOBITS) | ||
| 812 | continue; | ||
| 813 | |||
| 814 | /* Write out the sections. .data and .data1 (and data2, called | ||
| 815 | ".data" in the strings table) get copied from the current process | ||
| 816 | instead of the old file. */ | ||
| 817 | if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") | ||
| 818 | || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | ||
| 819 | ".data1")) | ||
| 820 | src = (caddr_t) OLD_SECTION_H (n).sh_addr; | ||
| 821 | else | ||
| 822 | src = old_base + OLD_SECTION_H (n).sh_offset; | ||
| 823 | |||
| 824 | memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src, | ||
| 825 | NEW_SECTION_H (nn).sh_size); | ||
| 826 | |||
| 827 | #ifdef __alpha__ | ||
| 828 | /* Update Alpha COFF symbol table: */ | ||
| 829 | if (strcmp (old_section_names + OLD_SECTION_H (n).sh_name, ".mdebug") | ||
| 830 | == 0) | ||
| 831 | { | ||
| 832 | pHDRR symhdr = (pHDRR) (NEW_SECTION_H (nn).sh_offset + new_base); | ||
| 833 | |||
| 834 | symhdr->cbLineOffset += new_data2_size; | ||
| 835 | symhdr->cbDnOffset += new_data2_size; | ||
| 836 | symhdr->cbPdOffset += new_data2_size; | ||
| 837 | symhdr->cbSymOffset += new_data2_size; | ||
| 838 | symhdr->cbOptOffset += new_data2_size; | ||
| 839 | symhdr->cbAuxOffset += new_data2_size; | ||
| 840 | symhdr->cbSsOffset += new_data2_size; | ||
| 841 | symhdr->cbSsExtOffset += new_data2_size; | ||
| 842 | symhdr->cbFdOffset += new_data2_size; | ||
| 843 | symhdr->cbRfdOffset += new_data2_size; | ||
| 844 | symhdr->cbExtOffset += new_data2_size; | ||
| 845 | } | ||
| 846 | #endif /* __alpha__ */ | ||
| 847 | |||
| 848 | /* If it is the symbol table, its st_shndx field needs to be patched. */ | ||
| 849 | if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB | ||
| 850 | || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) | ||
| 851 | { | ||
| 852 | ElfW(Shdr) *spt = &NEW_SECTION_H (nn); | ||
| 853 | unsigned int num = spt->sh_size / spt->sh_entsize; | ||
| 854 | ElfW(Sym) * sym = (ElfW(Sym) *) (NEW_SECTION_H (nn).sh_offset + | ||
| 855 | new_base); | ||
| 856 | for (; num--; sym++) | ||
| 857 | { | ||
| 858 | if ((sym->st_shndx == SHN_UNDEF) | ||
| 859 | || (sym->st_shndx == SHN_ABS) | ||
| 860 | || (sym->st_shndx == SHN_COMMON)) | ||
| 861 | continue; | ||
| 862 | |||
| 863 | PATCH_INDEX (sym->st_shndx); | ||
| 864 | } | ||
| 865 | } | ||
| 866 | } | ||
| 867 | |||
| 868 | /* Update the symbol values of _edata and _end. */ | ||
| 869 | for (n = new_file_h->e_shnum - 1; n; n--) | ||
| 870 | { | ||
| 871 | byte *symnames; | ||
| 872 | ElfW(Sym) *symp, *symendp; | ||
| 873 | |||
| 874 | if (NEW_SECTION_H (n).sh_type != SHT_DYNSYM | ||
| 875 | && NEW_SECTION_H (n).sh_type != SHT_SYMTAB) | ||
| 876 | continue; | ||
| 877 | |||
| 878 | symnames = ((byte *) new_base | ||
| 879 | + NEW_SECTION_H (NEW_SECTION_H (n).sh_link).sh_offset); | ||
| 880 | symp = (ElfW(Sym) *) (NEW_SECTION_H (n).sh_offset + new_base); | ||
| 881 | symendp = (ElfW(Sym) *) ((byte *)symp + NEW_SECTION_H (n).sh_size); | ||
| 882 | |||
| 883 | for (; symp < symendp; symp ++) | ||
| 884 | if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0 | ||
| 885 | || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0) | ||
| 886 | memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr)); | ||
| 887 | } | ||
| 888 | |||
| 889 | /* This loop seeks out relocation sections for the data section, so | ||
| 890 | that it can undo relocations performed by the runtime linker. */ | ||
| 891 | for (n = new_file_h->e_shnum - 1; n; n--) | ||
| 892 | { | ||
| 893 | ElfW(Shdr) section = NEW_SECTION_H (n); | ||
| 894 | switch (section.sh_type) { | ||
| 895 | default: | ||
| 896 | break; | ||
| 897 | case SHT_REL: | ||
| 898 | case SHT_RELA: | ||
| 899 | /* This code handles two different size structs, but there should | ||
| 900 | be no harm in that provided that r_offset is always the first | ||
| 901 | member. */ | ||
| 902 | nn = section.sh_info; | ||
| 903 | if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data") | ||
| 904 | || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | ||
| 905 | ".data1")) | ||
| 906 | { | ||
| 907 | ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr - | ||
| 908 | NEW_SECTION_H (nn).sh_offset; | ||
| 909 | caddr_t reloc = old_base + section.sh_offset, end; | ||
| 910 | for (end = reloc + section.sh_size; reloc < end; | ||
| 911 | reloc += section.sh_entsize) | ||
| 912 | { | ||
| 913 | ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset; | ||
| 914 | #ifdef __alpha__ | ||
| 915 | /* The Alpha ELF binutils currently have a bug that | ||
| 916 | sometimes results in relocs that contain all | ||
| 917 | zeroes. Work around this for now... */ | ||
| 918 | if (((ElfW(Rel) *) reloc)->r_offset == 0) | ||
| 919 | continue; | ||
| 920 | #endif | ||
| 921 | memcpy (new_base + addr, old_base + addr, sizeof(ElfW(Addr))); | ||
| 922 | } | ||
| 923 | } | ||
| 924 | break; | ||
| 925 | } | ||
| 926 | } | ||
| 927 | |||
| 928 | #ifdef UNEXEC_USE_MAP_PRIVATE | ||
| 929 | if (lseek (new_file, 0, SEEK_SET) == -1) | ||
| 930 | fatal ("Can't rewind (%s): errno %d\n", new_name, errno); | ||
| 931 | |||
| 932 | if (write (new_file, new_base, new_file_size) != new_file_size) | ||
| 933 | fatal ("Can't write (%s): errno %d\n", new_name, errno); | ||
| 934 | #endif | ||
| 935 | |||
| 936 | /* Close the files and make the new file executable. */ | ||
| 937 | |||
| 938 | if (close (old_file)) | ||
| 939 | fatal ("Can't close (%s): errno %d\n", old_name, errno); | ||
| 940 | |||
| 941 | if (close (new_file)) | ||
| 942 | fatal ("Can't close (%s): errno %d\n", new_name, errno); | ||
| 943 | |||
| 944 | if (stat (new_name, &stat_buf) == -1) | ||
| 945 | fatal ("Can't stat (%s): errno %d\n", new_name, errno); | ||
| 946 | |||
| 947 | n = umask (777); | ||
| 948 | umask (n); | ||
| 949 | stat_buf.st_mode |= 0111 & ~n; | ||
| 950 | if (chmod (new_name, stat_buf.st_mode) == -1) | ||
| 951 | fatal ("Can't chmod (%s): errno %d\n", new_name, errno); | ||
| 952 | } | ||
diff --git a/src/unexsgi.c b/src/unexsgi.c deleted file mode 100644 index cd0067f08d9..00000000000 --- a/src/unexsgi.c +++ /dev/null | |||
| @@ -1,900 +0,0 @@ | |||
| 1 | /* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992 | ||
| 2 | Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2, or (at your option) | ||
| 9 | any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 18 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 19 | Boston, MA 02111-1307, USA. | ||
| 20 | |||
| 21 | In other words, you are welcome to use, share and improve this program. | ||
| 22 | You are forbidden to forbid anyone else to use, share and improve | ||
| 23 | what you give them. Help stamp out software-hoarding! */ | ||
| 24 | |||
| 25 | |||
| 26 | /* | ||
| 27 | * unexec.c - Convert a running program into an a.out file. | ||
| 28 | * | ||
| 29 | * Author: Spencer W. Thomas | ||
| 30 | * Computer Science Dept. | ||
| 31 | * University of Utah | ||
| 32 | * Date: Tue Mar 2 1982 | ||
| 33 | * Modified heavily since then. | ||
| 34 | * | ||
| 35 | * Synopsis: | ||
| 36 | * unexec (new_name, a_name, data_start, bss_start, entry_address) | ||
| 37 | * char *new_name, *a_name; | ||
| 38 | * unsigned data_start, bss_start, entry_address; | ||
| 39 | * | ||
| 40 | * Takes a snapshot of the program and makes an a.out format file in the | ||
| 41 | * file named by the string argument new_name. | ||
| 42 | * If a_name is non-NULL, the symbol table will be taken from the given file. | ||
| 43 | * On some machines, an existing a_name file is required. | ||
| 44 | * | ||
| 45 | * The boundaries within the a.out file may be adjusted with the data_start | ||
| 46 | * and bss_start arguments. Either or both may be given as 0 for defaults. | ||
| 47 | * | ||
| 48 | * Data_start gives the boundary between the text segment and the data | ||
| 49 | * segment of the program. The text segment can contain shared, read-only | ||
| 50 | * program code and literal data, while the data segment is always unshared | ||
| 51 | * and unprotected. Data_start gives the lowest unprotected address. | ||
| 52 | * The value you specify may be rounded down to a suitable boundary | ||
| 53 | * as required by the machine you are using. | ||
| 54 | * | ||
| 55 | * Specifying zero for data_start means the boundary between text and data | ||
| 56 | * should not be the same as when the program was loaded. | ||
| 57 | * If NO_REMAP is defined, the argument data_start is ignored and the | ||
| 58 | * segment boundaries are never changed. | ||
| 59 | * | ||
| 60 | * Bss_start indicates how much of the data segment is to be saved in the | ||
| 61 | * a.out file and restored when the program is executed. It gives the lowest | ||
| 62 | * unsaved address, and is rounded up to a page boundary. The default when 0 | ||
| 63 | * is given assumes that the entire data segment is to be stored, including | ||
| 64 | * the previous data and bss as well as any additional storage allocated with | ||
| 65 | * break (2). | ||
| 66 | * | ||
| 67 | * The new file is set up to start at entry_address. | ||
| 68 | * | ||
| 69 | * If you make improvements I'd like to get them too. | ||
| 70 | * harpo!utah-cs!thomas, thomas@Utah-20 | ||
| 71 | * | ||
| 72 | */ | ||
| 73 | |||
| 74 | /* Even more heavily modified by james@bigtex.cactus.org of Dell Computer Co. | ||
| 75 | * ELF support added. | ||
| 76 | * | ||
| 77 | * Basic theory: the data space of the running process needs to be | ||
| 78 | * dumped to the output file. Normally we would just enlarge the size | ||
| 79 | * of .data, scooting everything down. But we can't do that in ELF, | ||
| 80 | * because there is often something between the .data space and the | ||
| 81 | * .bss space. | ||
| 82 | * | ||
| 83 | * In the temacs dump below, notice that the Global Offset Table | ||
| 84 | * (.got) and the Dynamic link data (.dynamic) come between .data1 and | ||
| 85 | * .bss. It does not work to overlap .data with these fields. | ||
| 86 | * | ||
| 87 | * The solution is to create a new .data segment. This segment is | ||
| 88 | * filled with data from the current process. Since the contents of | ||
| 89 | * various sections refer to sections by index, the new .data segment | ||
| 90 | * is made the last in the table to avoid changing any existing index. | ||
| 91 | |||
| 92 | * This is an example of how the section headers are changed. "Addr" | ||
| 93 | * is a process virtual address. "Offset" is a file offset. | ||
| 94 | |||
| 95 | raid:/nfs/raid/src/dist-18.56/src> dump -h temacs | ||
| 96 | |||
| 97 | temacs: | ||
| 98 | |||
| 99 | **** SECTION HEADER TABLE **** | ||
| 100 | [No] Type Flags Addr Offset Size Name | ||
| 101 | Link Info Adralgn Entsize | ||
| 102 | |||
| 103 | [1] 1 2 0x80480d4 0xd4 0x13 .interp | ||
| 104 | 0 0 0x1 0 | ||
| 105 | |||
| 106 | [2] 5 2 0x80480e8 0xe8 0x388 .hash | ||
| 107 | 3 0 0x4 0x4 | ||
| 108 | |||
| 109 | [3] 11 2 0x8048470 0x470 0x7f0 .dynsym | ||
| 110 | 4 1 0x4 0x10 | ||
| 111 | |||
| 112 | [4] 3 2 0x8048c60 0xc60 0x3ad .dynstr | ||
| 113 | 0 0 0x1 0 | ||
| 114 | |||
| 115 | [5] 9 2 0x8049010 0x1010 0x338 .rel.plt | ||
| 116 | 3 7 0x4 0x8 | ||
| 117 | |||
| 118 | [6] 1 6 0x8049348 0x1348 0x3 .init | ||
| 119 | 0 0 0x4 0 | ||
| 120 | |||
| 121 | [7] 1 6 0x804934c 0x134c 0x680 .plt | ||
| 122 | 0 0 0x4 0x4 | ||
| 123 | |||
| 124 | [8] 1 6 0x80499cc 0x19cc 0x3c56f .text | ||
| 125 | 0 0 0x4 0 | ||
| 126 | |||
| 127 | [9] 1 6 0x8085f3c 0x3df3c 0x3 .fini | ||
| 128 | 0 0 0x4 0 | ||
| 129 | |||
| 130 | [10] 1 2 0x8085f40 0x3df40 0x69c .rodata | ||
| 131 | 0 0 0x4 0 | ||
| 132 | |||
| 133 | [11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1 | ||
| 134 | 0 0 0x4 0 | ||
| 135 | |||
| 136 | [12] 1 3 0x8088330 0x3f330 0x20afc .data | ||
| 137 | 0 0 0x4 0 | ||
| 138 | |||
| 139 | [13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1 | ||
| 140 | 0 0 0x4 0 | ||
| 141 | |||
| 142 | [14] 1 3 0x80a96cc 0x606cc 0x1a8 .got | ||
| 143 | 0 0 0x4 0x4 | ||
| 144 | |||
| 145 | [15] 6 3 0x80a9874 0x60874 0x80 .dynamic | ||
| 146 | 4 0 0x4 0x8 | ||
| 147 | |||
| 148 | [16] 8 3 0x80a98f4 0x608f4 0x449c .bss | ||
| 149 | 0 0 0x4 0 | ||
| 150 | |||
| 151 | [17] 2 0 0 0x608f4 0x9b90 .symtab | ||
| 152 | 18 371 0x4 0x10 | ||
| 153 | |||
| 154 | [18] 3 0 0 0x6a484 0x8526 .strtab | ||
| 155 | 0 0 0x1 0 | ||
| 156 | |||
| 157 | [19] 3 0 0 0x729aa 0x93 .shstrtab | ||
| 158 | 0 0 0x1 0 | ||
| 159 | |||
| 160 | [20] 1 0 0 0x72a3d 0x68b7 .comment | ||
| 161 | 0 0 0x1 0 | ||
| 162 | |||
| 163 | raid:/nfs/raid/src/dist-18.56/src> dump -h xemacs | ||
| 164 | |||
| 165 | xemacs: | ||
| 166 | |||
| 167 | **** SECTION HEADER TABLE **** | ||
| 168 | [No] Type Flags Addr Offset Size Name | ||
| 169 | Link Info Adralgn Entsize | ||
| 170 | |||
| 171 | [1] 1 2 0x80480d4 0xd4 0x13 .interp | ||
| 172 | 0 0 0x1 0 | ||
| 173 | |||
| 174 | [2] 5 2 0x80480e8 0xe8 0x388 .hash | ||
| 175 | 3 0 0x4 0x4 | ||
| 176 | |||
| 177 | [3] 11 2 0x8048470 0x470 0x7f0 .dynsym | ||
| 178 | 4 1 0x4 0x10 | ||
| 179 | |||
| 180 | [4] 3 2 0x8048c60 0xc60 0x3ad .dynstr | ||
| 181 | 0 0 0x1 0 | ||
| 182 | |||
| 183 | [5] 9 2 0x8049010 0x1010 0x338 .rel.plt | ||
| 184 | 3 7 0x4 0x8 | ||
| 185 | |||
| 186 | [6] 1 6 0x8049348 0x1348 0x3 .init | ||
| 187 | 0 0 0x4 0 | ||
| 188 | |||
| 189 | [7] 1 6 0x804934c 0x134c 0x680 .plt | ||
| 190 | 0 0 0x4 0x4 | ||
| 191 | |||
| 192 | [8] 1 6 0x80499cc 0x19cc 0x3c56f .text | ||
| 193 | 0 0 0x4 0 | ||
| 194 | |||
| 195 | [9] 1 6 0x8085f3c 0x3df3c 0x3 .fini | ||
| 196 | 0 0 0x4 0 | ||
| 197 | |||
| 198 | [10] 1 2 0x8085f40 0x3df40 0x69c .rodata | ||
| 199 | 0 0 0x4 0 | ||
| 200 | |||
| 201 | [11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1 | ||
| 202 | 0 0 0x4 0 | ||
| 203 | |||
| 204 | [12] 1 3 0x8088330 0x3f330 0x20afc .data | ||
| 205 | 0 0 0x4 0 | ||
| 206 | |||
| 207 | [13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1 | ||
| 208 | 0 0 0x4 0 | ||
| 209 | |||
| 210 | [14] 1 3 0x80a96cc 0x606cc 0x1a8 .got | ||
| 211 | 0 0 0x4 0x4 | ||
| 212 | |||
| 213 | [15] 6 3 0x80a9874 0x60874 0x80 .dynamic | ||
| 214 | 4 0 0x4 0x8 | ||
| 215 | |||
| 216 | [16] 8 3 0x80c6800 0x7d800 0 .bss | ||
| 217 | 0 0 0x4 0 | ||
| 218 | |||
| 219 | [17] 2 0 0 0x7d800 0x9b90 .symtab | ||
| 220 | 18 371 0x4 0x10 | ||
| 221 | |||
| 222 | [18] 3 0 0 0x87390 0x8526 .strtab | ||
| 223 | 0 0 0x1 0 | ||
| 224 | |||
| 225 | [19] 3 0 0 0x8f8b6 0x93 .shstrtab | ||
| 226 | 0 0 0x1 0 | ||
| 227 | |||
| 228 | [20] 1 0 0 0x8f949 0x68b7 .comment | ||
| 229 | 0 0 0x1 0 | ||
| 230 | |||
| 231 | [21] 1 3 0x80a98f4 0x608f4 0x1cf0c .data | ||
| 232 | 0 0 0x4 0 | ||
| 233 | |||
| 234 | * This is an example of how the file header is changed. "Shoff" is | ||
| 235 | * the section header offset within the file. Since that table is | ||
| 236 | * after the new .data section, it is moved. "Shnum" is the number of | ||
| 237 | * sections, which we increment. | ||
| 238 | * | ||
| 239 | * "Phoff" is the file offset to the program header. "Phentsize" and | ||
| 240 | * "Shentsz" are the program and section header entries sizes respectively. | ||
| 241 | * These can be larger than the apparent struct sizes. | ||
| 242 | |||
| 243 | raid:/nfs/raid/src/dist-18.56/src> dump -f temacs | ||
| 244 | |||
| 245 | temacs: | ||
| 246 | |||
| 247 | **** ELF HEADER **** | ||
| 248 | Class Data Type Machine Version | ||
| 249 | Entry Phoff Shoff Flags Ehsize | ||
| 250 | Phentsize Phnum Shentsz Shnum Shstrndx | ||
| 251 | |||
| 252 | 1 1 2 3 1 | ||
| 253 | 0x80499cc 0x34 0x792f4 0 0x34 | ||
| 254 | 0x20 5 0x28 21 19 | ||
| 255 | |||
| 256 | raid:/nfs/raid/src/dist-18.56/src> dump -f xemacs | ||
| 257 | |||
| 258 | xemacs: | ||
| 259 | |||
| 260 | **** ELF HEADER **** | ||
| 261 | Class Data Type Machine Version | ||
| 262 | Entry Phoff Shoff Flags Ehsize | ||
| 263 | Phentsize Phnum Shentsz Shnum Shstrndx | ||
| 264 | |||
| 265 | 1 1 2 3 1 | ||
| 266 | 0x80499cc 0x34 0x96200 0 0x34 | ||
| 267 | 0x20 5 0x28 22 19 | ||
| 268 | |||
| 269 | * These are the program headers. "Offset" is the file offset to the | ||
| 270 | * segment. "Vaddr" is the memory load address. "Filesz" is the | ||
| 271 | * segment size as it appears in the file, and "Memsz" is the size in | ||
| 272 | * memory. Below, the third segment is the code and the fourth is the | ||
| 273 | * data: the difference between Filesz and Memsz is .bss | ||
| 274 | |||
| 275 | raid:/nfs/raid/src/dist-18.56/src> dump -o temacs | ||
| 276 | |||
| 277 | temacs: | ||
| 278 | ***** PROGRAM EXECUTION HEADER ***** | ||
| 279 | Type Offset Vaddr Paddr | ||
| 280 | Filesz Memsz Flags Align | ||
| 281 | |||
| 282 | 6 0x34 0x8048034 0 | ||
| 283 | 0xa0 0xa0 5 0 | ||
| 284 | |||
| 285 | 3 0xd4 0 0 | ||
| 286 | 0x13 0 4 0 | ||
| 287 | |||
| 288 | 1 0x34 0x8048034 0 | ||
| 289 | 0x3f2f9 0x3f2f9 5 0x1000 | ||
| 290 | |||
| 291 | 1 0x3f330 0x8088330 0 | ||
| 292 | 0x215c4 0x25a60 7 0x1000 | ||
| 293 | |||
| 294 | 2 0x60874 0x80a9874 0 | ||
| 295 | 0x80 0 7 0 | ||
| 296 | |||
| 297 | raid:/nfs/raid/src/dist-18.56/src> dump -o xemacs | ||
| 298 | |||
| 299 | xemacs: | ||
| 300 | ***** PROGRAM EXECUTION HEADER ***** | ||
| 301 | Type Offset Vaddr Paddr | ||
| 302 | Filesz Memsz Flags Align | ||
| 303 | |||
| 304 | 6 0x34 0x8048034 0 | ||
| 305 | 0xa0 0xa0 5 0 | ||
| 306 | |||
| 307 | 3 0xd4 0 0 | ||
| 308 | 0x13 0 4 0 | ||
| 309 | |||
| 310 | 1 0x34 0x8048034 0 | ||
| 311 | 0x3f2f9 0x3f2f9 5 0x1000 | ||
| 312 | |||
| 313 | 1 0x3f330 0x8088330 0 | ||
| 314 | 0x3e4d0 0x3e4d0 7 0x1000 | ||
| 315 | |||
| 316 | 2 0x60874 0x80a9874 0 | ||
| 317 | 0x80 0 7 0 | ||
| 318 | |||
| 319 | |||
| 320 | */ | ||
| 321 | |||
| 322 | /* Modified by wtien@urbana.mcd.mot.com of Motorola Inc. | ||
| 323 | * | ||
| 324 | * The above mechanism does not work if the unexeced ELF file is being | ||
| 325 | * re-layout by other applications (such as `strip'). All the applications | ||
| 326 | * that re-layout the internal of ELF will layout all sections in ascending | ||
| 327 | * order of their file offsets. After the re-layout, the data2 section will | ||
| 328 | * still be the LAST section in the section header vector, but its file offset | ||
| 329 | * is now being pushed far away down, and causes part of it not to be mapped | ||
| 330 | * in (ie. not covered by the load segment entry in PHDR vector), therefore | ||
| 331 | * causes the new binary to fail. | ||
| 332 | * | ||
| 333 | * The solution is to modify the unexec algorithm to insert the new data2 | ||
| 334 | * section header right before the new bss section header, so their file | ||
| 335 | * offsets will be in the ascending order. Since some of the section's (all | ||
| 336 | * sections AFTER the bss section) indexes are now changed, we also need to | ||
| 337 | * modify some fields to make them point to the right sections. This is done | ||
| 338 | * by macro PATCH_INDEX. All the fields that need to be patched are: | ||
| 339 | * | ||
| 340 | * 1. ELF header e_shstrndx field. | ||
| 341 | * 2. section header sh_link and sh_info field. | ||
| 342 | * 3. symbol table entry st_shndx field. | ||
| 343 | * | ||
| 344 | * The above example now should look like: | ||
| 345 | |||
| 346 | **** SECTION HEADER TABLE **** | ||
| 347 | [No] Type Flags Addr Offset Size Name | ||
| 348 | Link Info Adralgn Entsize | ||
| 349 | |||
| 350 | [1] 1 2 0x80480d4 0xd4 0x13 .interp | ||
| 351 | 0 0 0x1 0 | ||
| 352 | |||
| 353 | [2] 5 2 0x80480e8 0xe8 0x388 .hash | ||
| 354 | 3 0 0x4 0x4 | ||
| 355 | |||
| 356 | [3] 11 2 0x8048470 0x470 0x7f0 .dynsym | ||
| 357 | 4 1 0x4 0x10 | ||
| 358 | |||
| 359 | [4] 3 2 0x8048c60 0xc60 0x3ad .dynstr | ||
| 360 | 0 0 0x1 0 | ||
| 361 | |||
| 362 | [5] 9 2 0x8049010 0x1010 0x338 .rel.plt | ||
| 363 | 3 7 0x4 0x8 | ||
| 364 | |||
| 365 | [6] 1 6 0x8049348 0x1348 0x3 .init | ||
| 366 | 0 0 0x4 0 | ||
| 367 | |||
| 368 | [7] 1 6 0x804934c 0x134c 0x680 .plt | ||
| 369 | 0 0 0x4 0x4 | ||
| 370 | |||
| 371 | [8] 1 6 0x80499cc 0x19cc 0x3c56f .text | ||
| 372 | 0 0 0x4 0 | ||
| 373 | |||
| 374 | [9] 1 6 0x8085f3c 0x3df3c 0x3 .fini | ||
| 375 | 0 0 0x4 0 | ||
| 376 | |||
| 377 | [10] 1 2 0x8085f40 0x3df40 0x69c .rodata | ||
| 378 | 0 0 0x4 0 | ||
| 379 | |||
| 380 | [11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1 | ||
| 381 | 0 0 0x4 0 | ||
| 382 | |||
| 383 | [12] 1 3 0x8088330 0x3f330 0x20afc .data | ||
| 384 | 0 0 0x4 0 | ||
| 385 | |||
| 386 | [13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1 | ||
| 387 | 0 0 0x4 0 | ||
| 388 | |||
| 389 | [14] 1 3 0x80a96cc 0x606cc 0x1a8 .got | ||
| 390 | 0 0 0x4 0x4 | ||
| 391 | |||
| 392 | [15] 6 3 0x80a9874 0x60874 0x80 .dynamic | ||
| 393 | 4 0 0x4 0x8 | ||
| 394 | |||
| 395 | [16] 1 3 0x80a98f4 0x608f4 0x1cf0c .data | ||
| 396 | 0 0 0x4 0 | ||
| 397 | |||
| 398 | [17] 8 3 0x80c6800 0x7d800 0 .bss | ||
| 399 | 0 0 0x4 0 | ||
| 400 | |||
| 401 | [18] 2 0 0 0x7d800 0x9b90 .symtab | ||
| 402 | 19 371 0x4 0x10 | ||
| 403 | |||
| 404 | [19] 3 0 0 0x87390 0x8526 .strtab | ||
| 405 | 0 0 0x1 0 | ||
| 406 | |||
| 407 | [20] 3 0 0 0x8f8b6 0x93 .shstrtab | ||
| 408 | 0 0 0x1 0 | ||
| 409 | |||
| 410 | [21] 1 0 0 0x8f949 0x68b7 .comment | ||
| 411 | 0 0 0x1 0 | ||
| 412 | |||
| 413 | */ | ||
| 414 | |||
| 415 | #include <config.h> | ||
| 416 | #include <sys/types.h> | ||
| 417 | #include <stdio.h> | ||
| 418 | #include <sys/stat.h> | ||
| 419 | #include <memory.h> | ||
| 420 | #include <string.h> | ||
| 421 | #include <errno.h> | ||
| 422 | #include <unistd.h> | ||
| 423 | #include <fcntl.h> | ||
| 424 | #include <elf.h> | ||
| 425 | #include <syms.h> /* for HDRR declaration */ | ||
| 426 | #include <sys/mman.h> | ||
| 427 | |||
| 428 | #ifndef emacs | ||
| 429 | #define fatal(a, b, c) fprintf(stderr, a, b, c), exit(1) | ||
| 430 | #else | ||
| 431 | extern void fatal(char *, ...); | ||
| 432 | #endif | ||
| 433 | |||
| 434 | /* Get the address of a particular section or program header entry, | ||
| 435 | * accounting for the size of the entries. | ||
| 436 | */ | ||
| 437 | |||
| 438 | #define OLD_SECTION_H(n) \ | ||
| 439 | (*(Elf32_Shdr *) ((byte *) old_section_h + old_file_h->e_shentsize * (n))) | ||
| 440 | #define NEW_SECTION_H(n) \ | ||
| 441 | (*(Elf32_Shdr *) ((byte *) new_section_h + new_file_h->e_shentsize * (n))) | ||
| 442 | #define OLD_PROGRAM_H(n) \ | ||
| 443 | (*(Elf32_Phdr *) ((byte *) old_program_h + old_file_h->e_phentsize * (n))) | ||
| 444 | #define NEW_PROGRAM_H(n) \ | ||
| 445 | (*(Elf32_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n))) | ||
| 446 | |||
| 447 | #define PATCH_INDEX(n) \ | ||
| 448 | do { \ | ||
| 449 | if ((n) >= old_bss_index) \ | ||
| 450 | (n)++; } while (0) | ||
| 451 | typedef unsigned char byte; | ||
| 452 | |||
| 453 | /* Round X up to a multiple of Y. */ | ||
| 454 | |||
| 455 | int | ||
| 456 | round_up (x, y) | ||
| 457 | int x, y; | ||
| 458 | { | ||
| 459 | int rem = x % y; | ||
| 460 | if (rem == 0) | ||
| 461 | return x; | ||
| 462 | return x - rem + y; | ||
| 463 | } | ||
| 464 | |||
| 465 | /* Return the index of the section named NAME. | ||
| 466 | SECTION_NAMES, FILE_NAME and FILE_H give information | ||
| 467 | about the file we are looking in. | ||
| 468 | |||
| 469 | If we don't find the section NAME, that is a fatal error | ||
| 470 | if NOERROR is 0; we return -1 if NOERROR is nonzero. */ | ||
| 471 | |||
| 472 | static int | ||
| 473 | find_section (name, section_names, file_name, old_file_h, old_section_h, noerror) | ||
| 474 | char *name; | ||
| 475 | char *section_names; | ||
| 476 | char *file_name; | ||
| 477 | Elf32_Ehdr *old_file_h; | ||
| 478 | Elf32_Shdr *old_section_h; | ||
| 479 | int noerror; | ||
| 480 | { | ||
| 481 | int idx; | ||
| 482 | |||
| 483 | for (idx = 1; idx < old_file_h->e_shnum; idx++) | ||
| 484 | { | ||
| 485 | #ifdef DEBUG | ||
| 486 | fprintf (stderr, "Looking for %s - found %s\n", name, | ||
| 487 | section_names + OLD_SECTION_H (idx).sh_name); | ||
| 488 | #endif | ||
| 489 | if (!strcmp (section_names + OLD_SECTION_H (idx).sh_name, | ||
| 490 | name)) | ||
| 491 | break; | ||
| 492 | } | ||
| 493 | if (idx == old_file_h->e_shnum) | ||
| 494 | { | ||
| 495 | if (noerror) | ||
| 496 | return -1; | ||
| 497 | else | ||
| 498 | fatal ("Can't find .bss in %s.\n", file_name, 0); | ||
| 499 | } | ||
| 500 | |||
| 501 | return idx; | ||
| 502 | } | ||
| 503 | |||
| 504 | /* **************************************************************** | ||
| 505 | * unexec | ||
| 506 | * | ||
| 507 | * driving logic. | ||
| 508 | * | ||
| 509 | * In ELF, this works by replacing the old .bss section with a new | ||
| 510 | * .data section, and inserting an empty .bss immediately afterwards. | ||
| 511 | * | ||
| 512 | */ | ||
| 513 | void | ||
| 514 | unexec (new_name, old_name, data_start, bss_start, entry_address) | ||
| 515 | char *new_name, *old_name; | ||
| 516 | unsigned data_start, bss_start, entry_address; | ||
| 517 | { | ||
| 518 | extern unsigned int bss_end; | ||
| 519 | int new_file, old_file, new_file_size; | ||
| 520 | |||
| 521 | /* Pointers to the base of the image of the two files. */ | ||
| 522 | caddr_t old_base, new_base; | ||
| 523 | |||
| 524 | /* Pointers to the file, program and section headers for the old and new | ||
| 525 | files. */ | ||
| 526 | Elf32_Ehdr *old_file_h, *new_file_h; | ||
| 527 | Elf32_Phdr *old_program_h, *new_program_h; | ||
| 528 | Elf32_Shdr *old_section_h, *new_section_h; | ||
| 529 | |||
| 530 | /* Point to the section name table in the old file. */ | ||
| 531 | char *old_section_names; | ||
| 532 | |||
| 533 | Elf32_Addr old_bss_addr, new_bss_addr; | ||
| 534 | Elf32_Word old_bss_size, new_data2_size; | ||
| 535 | Elf32_Off new_data2_offset; | ||
| 536 | Elf32_Addr new_data2_addr; | ||
| 537 | Elf32_Addr new_offsets_shift; | ||
| 538 | |||
| 539 | int n, nn, old_bss_index, old_data_index, new_data2_index; | ||
| 540 | int old_mdebug_index; | ||
| 541 | struct stat stat_buf; | ||
| 542 | |||
| 543 | /* Open the old file & map it into the address space. */ | ||
| 544 | |||
| 545 | old_file = open (old_name, O_RDONLY); | ||
| 546 | |||
| 547 | if (old_file < 0) | ||
| 548 | fatal ("Can't open %s for reading: errno %d\n", old_name, errno); | ||
| 549 | |||
| 550 | if (fstat (old_file, &stat_buf) == -1) | ||
| 551 | fatal ("Can't fstat(%s): errno %d\n", old_name, errno); | ||
| 552 | |||
| 553 | old_base = mmap (0, stat_buf.st_size, PROT_READ, MAP_SHARED, old_file, 0); | ||
| 554 | |||
| 555 | if (old_base == (caddr_t) -1) | ||
| 556 | fatal ("Can't mmap(%s): errno %d\n", old_name, errno); | ||
| 557 | |||
| 558 | #ifdef DEBUG | ||
| 559 | fprintf (stderr, "mmap(%s, %x) -> %x\n", old_name, stat_buf.st_size, | ||
| 560 | old_base); | ||
| 561 | #endif | ||
| 562 | |||
| 563 | /* Get pointers to headers & section names. */ | ||
| 564 | |||
| 565 | old_file_h = (Elf32_Ehdr *) old_base; | ||
| 566 | old_program_h = (Elf32_Phdr *) ((byte *) old_base + old_file_h->e_phoff); | ||
| 567 | old_section_h = (Elf32_Shdr *) ((byte *) old_base + old_file_h->e_shoff); | ||
| 568 | old_section_names | ||
| 569 | = (char *) old_base + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset; | ||
| 570 | |||
| 571 | /* Find the mdebug section, if any. */ | ||
| 572 | |||
| 573 | old_mdebug_index = find_section (".mdebug", old_section_names, | ||
| 574 | old_name, old_file_h, old_section_h, 1); | ||
| 575 | |||
| 576 | /* Find the old .bss section. */ | ||
| 577 | |||
| 578 | old_bss_index = find_section (".bss", old_section_names, | ||
| 579 | old_name, old_file_h, old_section_h, 0); | ||
| 580 | |||
| 581 | /* Find the old .data section. Figure out parameters of | ||
| 582 | the new data2 and bss sections. */ | ||
| 583 | |||
| 584 | old_data_index = find_section (".data", old_section_names, | ||
| 585 | old_name, old_file_h, old_section_h, 0); | ||
| 586 | |||
| 587 | old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; | ||
| 588 | old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; | ||
| 589 | #if defined(emacs) || !defined(DEBUG) | ||
| 590 | bss_end = (unsigned int) sbrk (0); | ||
| 591 | new_bss_addr = (Elf32_Addr) bss_end; | ||
| 592 | #else | ||
| 593 | new_bss_addr = old_bss_addr + old_bss_size + 0x1234; | ||
| 594 | #endif | ||
| 595 | new_data2_addr = old_bss_addr; | ||
| 596 | new_data2_size = new_bss_addr - old_bss_addr; | ||
| 597 | new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset + | ||
| 598 | (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr); | ||
| 599 | new_offsets_shift = new_bss_addr - | ||
| 600 | ((old_bss_addr & ~0xfff) + ((old_bss_addr & 0xfff) ? 0x1000 : 0)); | ||
| 601 | |||
| 602 | #ifdef DEBUG | ||
| 603 | fprintf (stderr, "old_bss_index %d\n", old_bss_index); | ||
| 604 | fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); | ||
| 605 | fprintf (stderr, "old_bss_size %x\n", old_bss_size); | ||
| 606 | fprintf (stderr, "new_bss_addr %x\n", new_bss_addr); | ||
| 607 | fprintf (stderr, "new_data2_addr %x\n", new_data2_addr); | ||
| 608 | fprintf (stderr, "new_data2_size %x\n", new_data2_size); | ||
| 609 | fprintf (stderr, "new_data2_offset %x\n", new_data2_offset); | ||
| 610 | fprintf (stderr, "new_offsets_shift %x\n", new_offsets_shift); | ||
| 611 | #endif | ||
| 612 | |||
| 613 | if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size) | ||
| 614 | fatal (".bss shrank when undumping???\n", 0, 0); | ||
| 615 | |||
| 616 | /* Set the output file to the right size and mmap it. Set | ||
| 617 | pointers to various interesting objects. stat_buf still has | ||
| 618 | old_file data. */ | ||
| 619 | |||
| 620 | new_file = open (new_name, O_RDWR | O_CREAT, 0666); | ||
| 621 | if (new_file < 0) | ||
| 622 | fatal ("Can't creat (%s): errno %d\n", new_name, errno); | ||
| 623 | |||
| 624 | new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_offsets_shift; | ||
| 625 | |||
| 626 | if (ftruncate (new_file, new_file_size)) | ||
| 627 | fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno); | ||
| 628 | |||
| 629 | new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED, | ||
| 630 | new_file, 0); | ||
| 631 | |||
| 632 | if (new_base == (caddr_t) -1) | ||
| 633 | fatal ("Can't mmap (%s): errno %d\n", new_name, errno); | ||
| 634 | |||
| 635 | new_file_h = (Elf32_Ehdr *) new_base; | ||
| 636 | new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff); | ||
| 637 | new_section_h | ||
| 638 | = (Elf32_Shdr *) ((byte *) new_base + old_file_h->e_shoff | ||
| 639 | + new_offsets_shift); | ||
| 640 | |||
| 641 | /* Make our new file, program and section headers as copies of the | ||
| 642 | originals. */ | ||
| 643 | |||
| 644 | memcpy (new_file_h, old_file_h, old_file_h->e_ehsize); | ||
| 645 | memcpy (new_program_h, old_program_h, | ||
| 646 | old_file_h->e_phnum * old_file_h->e_phentsize); | ||
| 647 | |||
| 648 | /* Modify the e_shstrndx if necessary. */ | ||
| 649 | PATCH_INDEX (new_file_h->e_shstrndx); | ||
| 650 | |||
| 651 | /* Fix up file header. We'll add one section. Section header is | ||
| 652 | further away now. */ | ||
| 653 | |||
| 654 | new_file_h->e_shoff += new_offsets_shift; | ||
| 655 | new_file_h->e_shnum += 1; | ||
| 656 | |||
| 657 | #ifdef DEBUG | ||
| 658 | fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff); | ||
| 659 | fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum); | ||
| 660 | fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff); | ||
| 661 | fprintf (stderr, "New section count %d\n", new_file_h->e_shnum); | ||
| 662 | #endif | ||
| 663 | |||
| 664 | /* Fix up a new program header. Extend the writable data segment so | ||
| 665 | that the bss area is covered too. Find that segment by looking | ||
| 666 | for a segment that ends just before the .bss area. Make sure | ||
| 667 | that no segments are above the new .data2. Put a loop at the end | ||
| 668 | to adjust the offset and address of any segment that is above | ||
| 669 | data2, just in case we decide to allow this later. */ | ||
| 670 | |||
| 671 | for (n = new_file_h->e_phnum - 1; n >= 0; n--) | ||
| 672 | { | ||
| 673 | /* Compute maximum of all requirements for alignment of section. */ | ||
| 674 | int alignment = (NEW_PROGRAM_H (n)).p_align; | ||
| 675 | if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) | ||
| 676 | alignment = OLD_SECTION_H (old_bss_index).sh_addralign; | ||
| 677 | |||
| 678 | /* Supposedly this condition is okay for the SGI. */ | ||
| 679 | #if 0 | ||
| 680 | if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_bss_addr) | ||
| 681 | fatal ("Program segment above .bss in %s\n", old_name, 0); | ||
| 682 | #endif | ||
| 683 | |||
| 684 | if (NEW_PROGRAM_H (n).p_type == PT_LOAD | ||
| 685 | && (round_up ((NEW_PROGRAM_H (n)).p_vaddr | ||
| 686 | + (NEW_PROGRAM_H (n)).p_filesz, | ||
| 687 | alignment) | ||
| 688 | == round_up (old_bss_addr, alignment))) | ||
| 689 | break; | ||
| 690 | } | ||
| 691 | if (n < 0) | ||
| 692 | fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0); | ||
| 693 | |||
| 694 | NEW_PROGRAM_H (n).p_filesz += new_offsets_shift; | ||
| 695 | NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; | ||
| 696 | |||
| 697 | #if 1 /* Maybe allow section after data2 - does this ever happen? */ | ||
| 698 | for (n = new_file_h->e_phnum - 1; n >= 0; n--) | ||
| 699 | { | ||
| 700 | if (NEW_PROGRAM_H (n).p_vaddr | ||
| 701 | && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr) | ||
| 702 | NEW_PROGRAM_H (n).p_vaddr += new_offsets_shift - old_bss_size; | ||
| 703 | |||
| 704 | if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset) | ||
| 705 | NEW_PROGRAM_H (n).p_offset += new_offsets_shift; | ||
| 706 | } | ||
| 707 | #endif | ||
| 708 | |||
| 709 | /* Fix up section headers based on new .data2 section. Any section | ||
| 710 | whose offset or virtual address is after the new .data2 section | ||
| 711 | gets its value adjusted. .bss size becomes zero and new address | ||
| 712 | is set. data2 section header gets added by copying the existing | ||
| 713 | .data header and modifying the offset, address and size. */ | ||
| 714 | for (old_data_index = 1; old_data_index < old_file_h->e_shnum; | ||
| 715 | old_data_index++) | ||
| 716 | if (!strcmp (old_section_names + OLD_SECTION_H (old_data_index).sh_name, | ||
| 717 | ".data")) | ||
| 718 | break; | ||
| 719 | if (old_data_index == old_file_h->e_shnum) | ||
| 720 | fatal ("Can't find .data in %s.\n", old_name, 0); | ||
| 721 | |||
| 722 | /* Walk through all section headers, insert the new data2 section right | ||
| 723 | before the new bss section. */ | ||
| 724 | for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++) | ||
| 725 | { | ||
| 726 | caddr_t src; | ||
| 727 | |||
| 728 | /* If it is bss section, insert the new data2 section before it. */ | ||
| 729 | if (n == old_bss_index) | ||
| 730 | { | ||
| 731 | /* Steal the data section header for this data2 section. */ | ||
| 732 | memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index), | ||
| 733 | new_file_h->e_shentsize); | ||
| 734 | |||
| 735 | NEW_SECTION_H (nn).sh_addr = new_data2_addr; | ||
| 736 | NEW_SECTION_H (nn).sh_offset = new_data2_offset; | ||
| 737 | NEW_SECTION_H (nn).sh_size = new_data2_size; | ||
| 738 | /* Use the bss section's alignment. This will assure that the | ||
| 739 | new data2 section always be placed in the same spot as the old | ||
| 740 | bss section by any other application. */ | ||
| 741 | NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign; | ||
| 742 | |||
| 743 | /* Now copy over what we have in the memory now. */ | ||
| 744 | memcpy (NEW_SECTION_H (nn).sh_offset + new_base, | ||
| 745 | (caddr_t) OLD_SECTION_H (n).sh_addr, | ||
| 746 | new_data2_size); | ||
| 747 | nn++; | ||
| 748 | memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), | ||
| 749 | old_file_h->e_shentsize); | ||
| 750 | |||
| 751 | /* The new bss section's size is zero, and its file offset and virtual | ||
| 752 | address should be off by NEW_OFFSETS_SHIFT. */ | ||
| 753 | NEW_SECTION_H (nn).sh_offset += new_offsets_shift; | ||
| 754 | NEW_SECTION_H (nn).sh_addr = new_bss_addr; | ||
| 755 | /* Let the new bss section address alignment be the same as the | ||
| 756 | section address alignment followed the old bss section, so | ||
| 757 | this section will be placed in exactly the same place. */ | ||
| 758 | NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign; | ||
| 759 | NEW_SECTION_H (nn).sh_size = 0; | ||
| 760 | } | ||
| 761 | else | ||
| 762 | { | ||
| 763 | memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), | ||
| 764 | old_file_h->e_shentsize); | ||
| 765 | |||
| 766 | /* Any section that was original placed AFTER the bss | ||
| 767 | section must now be adjusted by NEW_OFFSETS_SHIFT. */ | ||
| 768 | |||
| 769 | if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset) | ||
| 770 | NEW_SECTION_H (nn).sh_offset += new_offsets_shift; | ||
| 771 | } | ||
| 772 | |||
| 773 | /* If any section hdr refers to the section after the new .data | ||
| 774 | section, make it refer to next one because we have inserted | ||
| 775 | a new section in between. */ | ||
| 776 | |||
| 777 | PATCH_INDEX (NEW_SECTION_H (nn).sh_link); | ||
| 778 | /* For symbol tables, info is a symbol table index, | ||
| 779 | so don't change it. */ | ||
| 780 | if (NEW_SECTION_H (nn).sh_type != SHT_SYMTAB | ||
| 781 | && NEW_SECTION_H (nn).sh_type != SHT_DYNSYM) | ||
| 782 | PATCH_INDEX (NEW_SECTION_H (nn).sh_info); | ||
| 783 | |||
| 784 | /* Now, start to copy the content of sections. */ | ||
| 785 | if (NEW_SECTION_H (nn).sh_type == SHT_NULL | ||
| 786 | || NEW_SECTION_H (nn).sh_type == SHT_NOBITS) | ||
| 787 | continue; | ||
| 788 | |||
| 789 | /* Write out the sections. .data and .data1 (and data2, called | ||
| 790 | ".data" in the strings table) get copied from the current process | ||
| 791 | instead of the old file. */ | ||
| 792 | if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data") | ||
| 793 | || !strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data1") | ||
| 794 | #ifdef IRIX6_5 | ||
| 795 | /* Under IRIX 6.5 gcc places objects with adresses relative to | ||
| 796 | shared symbols in the section .rodata, which are adjusted at | ||
| 797 | startup time. Unfortunately they aren't adjusted after unexec, | ||
| 798 | so with this configuration we must get .rodata also from memory. | ||
| 799 | Do any other configurations need this, too? | ||
| 800 | <Wolfgang.Glas@hfm.tu-graz.ac.at> 1999-06-08. */ | ||
| 801 | || !strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".rodata") | ||
| 802 | #endif | ||
| 803 | || !strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".got")) | ||
| 804 | src = (caddr_t) OLD_SECTION_H (n).sh_addr; | ||
| 805 | else | ||
| 806 | src = old_base + OLD_SECTION_H (n).sh_offset; | ||
| 807 | |||
| 808 | memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src, | ||
| 809 | NEW_SECTION_H (nn).sh_size); | ||
| 810 | |||
| 811 | /* Adjust the HDRR offsets in .mdebug and copy the | ||
| 812 | line data if it's in its usual 'hole' in the object. | ||
| 813 | Makes the new file debuggable with dbx. | ||
| 814 | patches up two problems: the absolute file offsets | ||
| 815 | in the HDRR record of .mdebug (see /usr/include/syms.h), and | ||
| 816 | the ld bug that gets the line table in a hole in the | ||
| 817 | elf file rather than in the .mdebug section proper. | ||
| 818 | David Anderson. davea@sgi.com Jan 16,1994. */ | ||
| 819 | if (n == old_mdebug_index) | ||
| 820 | { | ||
| 821 | #define MDEBUGADJUST(__ct,__fileaddr) \ | ||
| 822 | if (n_phdrr->__ct > 0) \ | ||
| 823 | { \ | ||
| 824 | n_phdrr->__fileaddr += movement; \ | ||
| 825 | } | ||
| 826 | |||
| 827 | HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset); | ||
| 828 | HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset); | ||
| 829 | unsigned movement = new_offsets_shift; | ||
| 830 | |||
| 831 | MDEBUGADJUST (idnMax, cbDnOffset); | ||
| 832 | MDEBUGADJUST (ipdMax, cbPdOffset); | ||
| 833 | MDEBUGADJUST (isymMax, cbSymOffset); | ||
| 834 | MDEBUGADJUST (ioptMax, cbOptOffset); | ||
| 835 | MDEBUGADJUST (iauxMax, cbAuxOffset); | ||
| 836 | MDEBUGADJUST (issMax, cbSsOffset); | ||
| 837 | MDEBUGADJUST (issExtMax, cbSsExtOffset); | ||
| 838 | MDEBUGADJUST (ifdMax, cbFdOffset); | ||
| 839 | MDEBUGADJUST (crfd, cbRfdOffset); | ||
| 840 | MDEBUGADJUST (iextMax, cbExtOffset); | ||
| 841 | /* The Line Section, being possible off in a hole of the object, | ||
| 842 | requires special handling. */ | ||
| 843 | if (n_phdrr->cbLine > 0) | ||
| 844 | { | ||
| 845 | if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset | ||
| 846 | + OLD_SECTION_H (n).sh_size)) | ||
| 847 | { | ||
| 848 | /* line data is in a hole in elf. do special copy and adjust | ||
| 849 | for this ld mistake. | ||
| 850 | */ | ||
| 851 | n_phdrr->cbLineOffset += movement; | ||
| 852 | |||
| 853 | memcpy (n_phdrr->cbLineOffset + new_base, | ||
| 854 | o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine); | ||
| 855 | } | ||
| 856 | else | ||
| 857 | { | ||
| 858 | /* somehow line data is in .mdebug as it is supposed to be. */ | ||
| 859 | MDEBUGADJUST (cbLine, cbLineOffset); | ||
| 860 | } | ||
| 861 | } | ||
| 862 | } | ||
| 863 | |||
| 864 | /* If it is the symbol table, its st_shndx field needs to be patched. */ | ||
| 865 | if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB | ||
| 866 | || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) | ||
| 867 | { | ||
| 868 | Elf32_Shdr *spt = &NEW_SECTION_H (nn); | ||
| 869 | unsigned int num = spt->sh_size / spt->sh_entsize; | ||
| 870 | Elf32_Sym * sym = (Elf32_Sym *) (NEW_SECTION_H (nn).sh_offset | ||
| 871 | + new_base); | ||
| 872 | for (; num--; sym++) | ||
| 873 | { | ||
| 874 | /* don't patch special section indices. */ | ||
| 875 | if (sym->st_shndx == SHN_UNDEF | ||
| 876 | || sym->st_shndx >= SHN_LORESERVE) | ||
| 877 | continue; | ||
| 878 | |||
| 879 | PATCH_INDEX (sym->st_shndx); | ||
| 880 | } | ||
| 881 | } | ||
| 882 | } | ||
| 883 | |||
| 884 | /* Close the files and make the new file executable. */ | ||
| 885 | |||
| 886 | if (close (old_file)) | ||
| 887 | fatal ("Can't close (%s): errno %d\n", old_name, errno); | ||
| 888 | |||
| 889 | if (close (new_file)) | ||
| 890 | fatal ("Can't close (%s): errno %d\n", new_name, errno); | ||
| 891 | |||
| 892 | if (stat (new_name, &stat_buf) == -1) | ||
| 893 | fatal ("Can't stat (%s): errno %d\n", new_name, errno); | ||
| 894 | |||
| 895 | n = umask (777); | ||
| 896 | umask (n); | ||
| 897 | stat_buf.st_mode |= 0111 & ~n; | ||
| 898 | if (chmod (new_name, stat_buf.st_mode) == -1) | ||
| 899 | fatal ("Can't chmod (%s): errno %d\n", new_name, errno); | ||
| 900 | } | ||
diff --git a/src/x11term.h b/src/x11term.h deleted file mode 100644 index 367eeaacc95..00000000000 --- a/src/x11term.h +++ /dev/null | |||
| @@ -1,24 +0,0 @@ | |||
| 1 | #include <X11/Xlib.h> | ||
| 2 | #include <X11/Xatom.h> | ||
| 3 | #include <X11/keysym.h> | ||
| 4 | #include <X11/cursorfont.h> | ||
| 5 | #include <X11/Xutil.h> | ||
| 6 | #include <X11/X10.h> | ||
| 7 | |||
| 8 | #define XMOUSEBUFSIZE 64 | ||
| 9 | |||
| 10 | #ifndef sigmask | ||
| 11 | #define sigmask(no) (1L << ((no) - 1)) | ||
| 12 | #endif | ||
| 13 | |||
| 14 | #define BLOCK_INPUT_DECLARE() int BLOCK_INPUT_mask | ||
| 15 | #ifdef SIGIO | ||
| 16 | #define BLOCK_INPUT() EMACS_SIGBLOCKX (SIGIO, BLOCK_INPUT_mask) | ||
| 17 | #define UNBLOCK_INPUT() \ | ||
| 18 | do { int _dummy; EMACS_SIGSETMASK (BLOCK_INPUT_mask, _dummy); } while (0) | ||
| 19 | #else /* not SIGIO */ | ||
| 20 | #define BLOCK_INPUT() | ||
| 21 | #define UNBLOCK_INPUT() | ||
| 22 | #endif /* SIGIO */ | ||
| 23 | |||
| 24 | #define CLASS "Emacs" /* class id for GNU Emacs, used in .Xdefaults, etc. */ | ||
diff --git a/src/xscrollbar.h b/src/xscrollbar.h deleted file mode 100644 index e1a3f45d247..00000000000 --- a/src/xscrollbar.h +++ /dev/null | |||
| @@ -1,123 +0,0 @@ | |||
| 1 | /* Bitmaps and things for scrollbars. | ||
| 2 | Copyright (C) 1989 Free Software Foundation. | ||
| 3 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 1, or (at your option) | ||
| 9 | any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
| 19 | |||
| 20 | |||
| 21 | static void install_vertical_scrollbar (); | ||
| 22 | static void install_horizontal_scrollbar (); | ||
| 23 | static void x_set_horizontal_scrollbar (); | ||
| 24 | static void x_set_vertical_scrollbar (); | ||
| 25 | |||
| 26 | /* Prefix-characters for scroll bar commands in Vglobal_mouse_map. | ||
| 27 | Choice of prefix depends on which region of the scroll bar. */ | ||
| 28 | |||
| 29 | enum scroll_bar_prefix | ||
| 30 | { VSCROLL_BAR_PREFIX = 050, VSCROLL_SLIDER_PREFIX /* unused */, | ||
| 31 | VSCROLL_THUMBUP_PREFIX, VSCROLL_THUMBDOWN_PREFIX, | ||
| 32 | HSCROLL_BAR_PREFIX, HSCROLL_SLIDER_PREFIX /* unused */, | ||
| 33 | HSCROLL_THUMBLEFT_PREFIX, HSCROLL_THUMBRIGHT_PREFIX }; | ||
| 34 | |||
| 35 | #define CROSS_WIDTH 16 | ||
| 36 | #define CROSS_HEIGHT 16 | ||
| 37 | |||
| 38 | #define CROSS_MASK_WIDTH 16 | ||
| 39 | #define CROSS_MASK_HEIGHT 16 | ||
| 40 | |||
| 41 | /* Vertical and Horizontal scroll bar widths. */ | ||
| 42 | #define VSCROLL_WIDTH 18 | ||
| 43 | #define HSCROLL_HEIGHT 18 | ||
| 44 | |||
| 45 | #ifdef HAVE_X11 | ||
| 46 | |||
| 47 | /* Arrow cursors for scroll bars. */ | ||
| 48 | |||
| 49 | Cursor up_arrow_cursor, down_arrow_cursor, v_double_arrow_cursor; | ||
| 50 | Cursor left_arrow_cursor, right_arrow_cursor, h_double_arrow_cursor; | ||
| 51 | |||
| 52 | static char cross_bits[] = | ||
| 53 | { | ||
| 54 | 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, | ||
| 55 | 0x80, 0x01, 0xfe, 0x7f, 0xfe, 0x7f, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, | ||
| 56 | 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00 | ||
| 57 | }; | ||
| 58 | |||
| 59 | static char gray_bits[] = | ||
| 60 | { | ||
| 61 | 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, | ||
| 62 | 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, | ||
| 63 | 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, | ||
| 64 | 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa | ||
| 65 | }; | ||
| 66 | |||
| 67 | static char up_arrow_bits[] = | ||
| 68 | { | ||
| 69 | 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf8, 0x1f, | ||
| 70 | 0xfc, 0x3f, 0xfe, 0x7f, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, | ||
| 71 | 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xff, 0xff | ||
| 72 | }; | ||
| 73 | |||
| 74 | static char down_arrow_bits[] = | ||
| 75 | { | ||
| 76 | 0xff, 0xff, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, | ||
| 77 | 0x80, 0x01, 0x80, 0x01, 0xfe, 0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xf0, 0x0f, | ||
| 78 | 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00 | ||
| 79 | }; | ||
| 80 | |||
| 81 | static char left_arrow_bits[] = | ||
| 82 | { | ||
| 83 | 0x00, 0x80, 0x80, 0x80, 0xc0, 0x80, 0xe0, 0x80, 0xf0, 0x80, 0xf8, 0x80, | ||
| 84 | 0xfc, 0x80, 0xfe, 0xff, 0xfe, 0xff, 0xfc, 0x80, 0xf8, 0x80, 0xf0, 0x80, | ||
| 85 | 0xe0, 0x80, 0xc0, 0x80, 0x80, 0x80, 0x00, 0x80 | ||
| 86 | }; | ||
| 87 | |||
| 88 | static char right_arrow_bits[] = | ||
| 89 | { | ||
| 90 | 0x01, 0x00, 0x01, 0x01, 0x01, 0x03, 0x01, 0x07, 0x01, 0x0f, 0x01, 0x1f, | ||
| 91 | 0x01, 0x3f, 0xff, 0x7f, 0xff, 0x7f, 0x01, 0x3f, 0x01, 0x1f, 0x01, 0x0f, | ||
| 92 | 0x01, 0x07, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00 | ||
| 93 | }; | ||
| 94 | |||
| 95 | static char cross_mask_bits[] = | ||
| 96 | { | ||
| 97 | 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, | ||
| 98 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xc0, 0x03, | ||
| 99 | 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03 | ||
| 100 | }; | ||
| 101 | #else /* not HAVE_X11 */ | ||
| 102 | static short cross_bits[] = | ||
| 103 | { | ||
| 104 | 0x0000, 0x0180, 0x0180, 0x0180, | ||
| 105 | 0x0180, 0x0180, 0x0180, 0x7ffe, | ||
| 106 | 0x7ffe, 0x0180, 0x0180, 0x0180, | ||
| 107 | 0x0180, 0x0180, 0x0180, 0x0000, | ||
| 108 | }; | ||
| 109 | |||
| 110 | static short gray_bits[] = { | ||
| 111 | 0xaaaa, 0x5555, 0xaaaa, 0x5555, | ||
| 112 | 0xaaaa, 0x5555, 0xaaaa, 0x5555, | ||
| 113 | 0xaaaa, 0x5555, 0xaaaa, 0x5555, | ||
| 114 | 0xaaaa, 0x5555, 0xaaaa, 0x5555}; | ||
| 115 | |||
| 116 | static short cross_mask_bits[] = | ||
| 117 | { | ||
| 118 | 0x03c0, 0x03c0, 0x03c0, 0x03c0, | ||
| 119 | 0x03c0, 0x03c0, 0xffff, 0xffff, | ||
| 120 | 0xffff, 0xffff, 0x03c0, 0x03c0, | ||
| 121 | 0x03c0, 0x03c0, 0x03c0, 0x03c0, | ||
| 122 | }; | ||
| 123 | #endif /* X10 */ | ||
diff --git a/src/xselect.c.old b/src/xselect.c.old deleted file mode 100644 index 8a3e0443270..00000000000 --- a/src/xselect.c.old +++ /dev/null | |||
| @@ -1,950 +0,0 @@ | |||
| 1 | /* X Selection processing for emacs | ||
| 2 | Copyright (C) 1990, 1992, 1993 Free Software Foundation. | ||
| 3 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2, or (at your option) | ||
| 9 | any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
| 19 | |||
| 20 | #include "config.h" | ||
| 21 | #include "lisp.h" | ||
| 22 | #include "xterm.h" | ||
| 23 | #include "buffer.h" | ||
| 24 | #include "frame.h" | ||
| 25 | |||
| 26 | #ifdef HAVE_X11 | ||
| 27 | |||
| 28 | /* Macros for X Selections */ | ||
| 29 | #define MAX_SELECTION(dpy) (((dpy)->max_request_size << 2) - 100) | ||
| 30 | #define SELECTION_LENGTH(len,format) ((len) * ((format) >> 2)) | ||
| 31 | |||
| 32 | /* The timestamp of the last input event we received from the X server. */ | ||
| 33 | unsigned long last_event_timestamp; | ||
| 34 | |||
| 35 | /* t if a mouse button is depressed. */ | ||
| 36 | extern Lisp_Object Vmouse_grabbed; | ||
| 37 | |||
| 38 | /* When emacs became the PRIMARY selection owner. */ | ||
| 39 | Time x_begin_selection_own; | ||
| 40 | |||
| 41 | /* When emacs became the SECONDARY selection owner. */ | ||
| 42 | Time x_begin_secondary_selection_own; | ||
| 43 | |||
| 44 | /* When emacs became the CLIPBOARD selection owner. */ | ||
| 45 | Time x_begin_clipboard_own; | ||
| 46 | |||
| 47 | /* The value of the current CLIPBOARD selection. */ | ||
| 48 | Lisp_Object Vx_clipboard_value; | ||
| 49 | |||
| 50 | /* The value of the current PRIMARY selection. */ | ||
| 51 | Lisp_Object Vx_selection_value; | ||
| 52 | |||
| 53 | /* The value of the current SECONDARY selection. */ | ||
| 54 | Lisp_Object Vx_secondary_selection_value; | ||
| 55 | |||
| 56 | /* Types of selections we may make. */ | ||
| 57 | Lisp_Object Qprimary, Qsecondary, Qclipboard; | ||
| 58 | |||
| 59 | /* Emacs' selection property identifiers. */ | ||
| 60 | Atom Xatom_emacs_selection; | ||
| 61 | Atom Xatom_emacs_secondary_selection; | ||
| 62 | |||
| 63 | /* Clipboard selection atom. */ | ||
| 64 | Atom Xatom_clipboard_selection; | ||
| 65 | |||
| 66 | /* Clipboard atom. */ | ||
| 67 | Atom Xatom_clipboard; | ||
| 68 | |||
| 69 | /* Atom for indicating incremental selection transfer. */ | ||
| 70 | Atom Xatom_incremental; | ||
| 71 | |||
| 72 | /* Atom for indicating multiple selection request list */ | ||
| 73 | Atom Xatom_multiple; | ||
| 74 | |||
| 75 | /* Atom for what targets emacs handles. */ | ||
| 76 | Atom Xatom_targets; | ||
| 77 | |||
| 78 | /* Atom for indicating timstamp selection request */ | ||
| 79 | Atom Xatom_timestamp; | ||
| 80 | |||
| 81 | /* Atom requesting we delete our selection. */ | ||
| 82 | Atom Xatom_delete; | ||
| 83 | |||
| 84 | /* Selection magic. */ | ||
| 85 | Atom Xatom_insert_selection; | ||
| 86 | |||
| 87 | /* Type of property for INSERT_SELECTION. */ | ||
| 88 | Atom Xatom_pair; | ||
| 89 | |||
| 90 | /* More selection magic. */ | ||
| 91 | Atom Xatom_insert_property; | ||
| 92 | |||
| 93 | /* Atom for indicating property type TEXT */ | ||
| 94 | Atom Xatom_text; | ||
| 95 | |||
| 96 | /* Kinds of protocol things we may receive. */ | ||
| 97 | Atom Xatom_wm_take_focus; | ||
| 98 | Atom Xatom_wm_save_yourself; | ||
| 99 | Atom Xatom_wm_delete_window; | ||
| 100 | |||
| 101 | /* Communication with window managers. */ | ||
| 102 | Atom Xatom_wm_protocols; | ||
| 103 | |||
| 104 | /* These are to handle incremental selection transfer. */ | ||
| 105 | Window incr_requestor; | ||
| 106 | Atom incr_property; | ||
| 107 | int incr_nbytes; | ||
| 108 | unsigned char *incr_value; | ||
| 109 | unsigned char *incr_ptr; | ||
| 110 | |||
| 111 | /* Declarations for handling cut buffers. | ||
| 112 | |||
| 113 | Whenever we set a cut buffer or read a cut buffer's value, we cache | ||
| 114 | it in cut_buffer_value. We look for PropertyNotify events about | ||
| 115 | the CUT_BUFFER properties, and invalidate our cache accordingly. | ||
| 116 | We ignore PropertyNotify events that we suspect were caused by our | ||
| 117 | own changes to the cut buffers, so we can keep the cache valid | ||
| 118 | longer. | ||
| 119 | |||
| 120 | IS ALL THIS HAIR WORTH IT? Well, these functions get called every | ||
| 121 | time an element goes into or is retrieved from the kill ring, and | ||
| 122 | those ought to be quick. It's not fun in time or space to wait for | ||
| 123 | 50k cut buffers to fly back and forth across the net. */ | ||
| 124 | |||
| 125 | /* The number of CUT_BUFFER properties defined under X. */ | ||
| 126 | #define NUM_CUT_BUFFERS (8) | ||
| 127 | |||
| 128 | /* cut_buffer_atom[n] is the atom naming the nth cut buffer. */ | ||
| 129 | static Atom cut_buffer_atom[NUM_CUT_BUFFERS] = { | ||
| 130 | XA_CUT_BUFFER0, XA_CUT_BUFFER1, XA_CUT_BUFFER2, XA_CUT_BUFFER3, | ||
| 131 | XA_CUT_BUFFER4, XA_CUT_BUFFER5, XA_CUT_BUFFER6, XA_CUT_BUFFER7 | ||
| 132 | }; | ||
| 133 | |||
| 134 | /* cut_buffer_value is an eight-element vector; | ||
| 135 | (aref cut_buffer_value n) is the cached value of cut buffer n, or | ||
| 136 | Qnil if cut buffer n is unset. */ | ||
| 137 | static Lisp_Object cut_buffer_value; | ||
| 138 | |||
| 139 | /* Bit N of cut_buffer_cached is true if (aref cut_buffer_value n) is | ||
| 140 | known to be valid. This is cleared by PropertyNotify events | ||
| 141 | handled by x_invalidate_cut_buffer_cache. It would be wonderful if | ||
| 142 | that routine could just set the appropriate element of | ||
| 143 | cut_buffer_value to some special value meaning "uncached", but that | ||
| 144 | would lose if a GC happened to be in progress. | ||
| 145 | |||
| 146 | Bit N of cut_buffer_just_set is true if cut buffer N has been set since | ||
| 147 | the last PropertyNotify event; since we get an event even when we set | ||
| 148 | the property ourselves, we should ignore one event after setting | ||
| 149 | a cut buffer, so we don't have to throw away our cache. */ | ||
| 150 | #ifdef __STDC__ | ||
| 151 | volatile | ||
| 152 | #endif | ||
| 153 | static cut_buffer_cached, cut_buffer_just_set; | ||
| 154 | |||
| 155 | |||
| 156 | /* Acquiring ownership of a selection. */ | ||
| 157 | |||
| 158 | |||
| 159 | /* Request selection ownership if we do not already have it. */ | ||
| 160 | |||
| 161 | static int | ||
| 162 | own_selection (selection_type, time) | ||
| 163 | Atom selection_type; | ||
| 164 | Time time; | ||
| 165 | { | ||
| 166 | Window owner_window, selecting_window; | ||
| 167 | |||
| 168 | if ((selection_type == XA_PRIMARY | ||
| 169 | && !NILP (Vx_selection_value)) | ||
| 170 | || (selection_type == XA_SECONDARY | ||
| 171 | && !NILP (Vx_secondary_selection_value)) | ||
| 172 | || (selection_type == Xatom_clipboard | ||
| 173 | && !NILP (Vx_clipboard_value))) | ||
| 174 | return 1; | ||
| 175 | |||
| 176 | selecting_window = FRAME_X_WINDOW (selected_frame); | ||
| 177 | XSetSelectionOwner (x_current_display, selection_type, | ||
| 178 | selecting_window, time); | ||
| 179 | owner_window = XGetSelectionOwner (x_current_display, selection_type); | ||
| 180 | |||
| 181 | if (owner_window != selecting_window) | ||
| 182 | return 0; | ||
| 183 | |||
| 184 | return 1; | ||
| 185 | } | ||
| 186 | |||
| 187 | /* Become the selection owner and make our data the selection value. | ||
| 188 | If we are already the owner, merely change data and timestamp values. | ||
| 189 | This avoids generating SelectionClear events for ourselves. */ | ||
| 190 | |||
| 191 | DEFUN ("x-set-selection", Fx_set_selection, Sx_set_selection, | ||
| 192 | 2, 2, "", | ||
| 193 | "Set the value of SELECTION to STRING.\n\ | ||
| 194 | SELECTION may be `primary', `secondary', or `clipboard'.\n\ | ||
| 195 | \n\ | ||
| 196 | Selections are a mechanism for cutting and pasting information between\n\ | ||
| 197 | X Windows clients. Emacs's kill ring commands set the `primary'\n\ | ||
| 198 | selection to the top string of the kill ring, making it available to\n\ | ||
| 199 | other clients, like xterm. Those commands also use the `primary'\n\ | ||
| 200 | selection to retrieve information from other clients.\n\ | ||
| 201 | \n\ | ||
| 202 | According to the Inter-Client Communications Conventions Manual:\n\ | ||
| 203 | \n\ | ||
| 204 | The `primary' selection \"... is used for all commands that take only a\n\ | ||
| 205 | single argument and is the principal means of communication between\n\ | ||
| 206 | clients that use the selection mechanism.\" In Emacs, this means\n\ | ||
| 207 | that the kill ring commands set the primary selection to the text\n\ | ||
| 208 | put in the kill ring.\n\ | ||
| 209 | \n\ | ||
| 210 | The `secondary' selection \"... is used as the second argument to\n\ | ||
| 211 | commands taking two arguments (for example, `exchange primary and\n\ | ||
| 212 | secondary selections'), and as a means of obtaining data when there\n\ | ||
| 213 | is a primary selection and the user does not want to disturb it.\"\n\ | ||
| 214 | I am not sure how Emacs should use the secondary selection; if you\n\ | ||
| 215 | come up with ideas, this function will at least let you get at it.\n\ | ||
| 216 | \n\ | ||
| 217 | The `clipboard' selection \"... is used to hold data that is being\n\ | ||
| 218 | transferred between clients, that is, data that usually is being\n\ | ||
| 219 | cut or copied, and then pasted.\" It seems that the `clipboard'\n\ | ||
| 220 | selection is for the most part equivalent to the `primary'\n\ | ||
| 221 | selection, so Emacs sets them both.\n\ | ||
| 222 | \n\ | ||
| 223 | Also see `x-selection', and the `interprogram-cut-function' variable.") | ||
| 224 | (selection, string) | ||
| 225 | register Lisp_Object selection, string; | ||
| 226 | { | ||
| 227 | Atom selection_type; | ||
| 228 | Lisp_Object val; | ||
| 229 | Time event_time = last_event_timestamp; | ||
| 230 | CHECK_STRING (string, 0); | ||
| 231 | |||
| 232 | val = Qnil; | ||
| 233 | |||
| 234 | if (NILP (selection) || EQ (selection, Qprimary)) | ||
| 235 | { | ||
| 236 | BLOCK_INPUT; | ||
| 237 | if (own_selection (XA_PRIMARY, event_time)) | ||
| 238 | { | ||
| 239 | x_begin_selection_own = event_time; | ||
| 240 | val = Vx_selection_value = string; | ||
| 241 | } | ||
| 242 | UNBLOCK_INPUT; | ||
| 243 | } | ||
| 244 | else if (EQ (selection, Qsecondary)) | ||
| 245 | { | ||
| 246 | BLOCK_INPUT; | ||
| 247 | if (own_selection (XA_SECONDARY, event_time)) | ||
| 248 | { | ||
| 249 | x_begin_secondary_selection_own = event_time; | ||
| 250 | val = Vx_secondary_selection_value = string; | ||
| 251 | } | ||
| 252 | UNBLOCK_INPUT; | ||
| 253 | } | ||
| 254 | else if (EQ (selection, Qclipboard)) | ||
| 255 | { | ||
| 256 | BLOCK_INPUT; | ||
| 257 | if (own_selection (Xatom_clipboard, event_time)) | ||
| 258 | { | ||
| 259 | x_begin_clipboard_own = event_time; | ||
| 260 | val = Vx_clipboard_value = string; | ||
| 261 | } | ||
| 262 | UNBLOCK_INPUT; | ||
| 263 | } | ||
| 264 | else | ||
| 265 | error ("Invalid X selection type"); | ||
| 266 | |||
| 267 | return val; | ||
| 268 | } | ||
| 269 | |||
| 270 | /* Clear our selection ownership data, as some other client has | ||
| 271 | become the owner. */ | ||
| 272 | |||
| 273 | void | ||
| 274 | x_disown_selection (old_owner, selection, changed_owner_time) | ||
| 275 | Window *old_owner; | ||
| 276 | Atom selection; | ||
| 277 | Time changed_owner_time; | ||
| 278 | { | ||
| 279 | struct frame *s = x_window_to_frame (old_owner); | ||
| 280 | |||
| 281 | if (s) /* We are the owner */ | ||
| 282 | { | ||
| 283 | if (selection == XA_PRIMARY) | ||
| 284 | { | ||
| 285 | x_begin_selection_own = 0; | ||
| 286 | Vx_selection_value = Qnil; | ||
| 287 | } | ||
| 288 | else if (selection == XA_SECONDARY) | ||
| 289 | { | ||
| 290 | x_begin_secondary_selection_own = 0; | ||
| 291 | Vx_secondary_selection_value = Qnil; | ||
| 292 | } | ||
| 293 | else if (selection == Xatom_clipboard) | ||
| 294 | { | ||
| 295 | x_begin_clipboard_own = 0; | ||
| 296 | Vx_clipboard_value = Qnil; | ||
| 297 | } | ||
| 298 | else | ||
| 299 | abort (); | ||
| 300 | } | ||
| 301 | else | ||
| 302 | abort (); /* Inconsistent state. */ | ||
| 303 | } | ||
| 304 | |||
| 305 | |||
| 306 | /* Answering selection requests. */ | ||
| 307 | |||
| 308 | int x_selection_alloc_error; | ||
| 309 | int x_converting_selection; | ||
| 310 | |||
| 311 | /* Reply to some client's request for our selection data. | ||
| 312 | Data is placed in a property supplied by the requesting window. | ||
| 313 | |||
| 314 | If the data exceeds the maximum amount the server can send, | ||
| 315 | then prepare to send it incrementally, and reply to the client with | ||
| 316 | the total size of the data. | ||
| 317 | |||
| 318 | But first, check for all the other crufty stuff we could get. */ | ||
| 319 | |||
| 320 | void | ||
| 321 | x_answer_selection_request (event) | ||
| 322 | XSelectionRequestEvent event; | ||
| 323 | { | ||
| 324 | Time emacs_own_time; | ||
| 325 | Lisp_Object selection_value; | ||
| 326 | XSelectionEvent evt; | ||
| 327 | int format = 8; /* We have only byte sized (text) data. */ | ||
| 328 | |||
| 329 | evt.type = SelectionNotify; /* Construct reply event */ | ||
| 330 | evt.display = event.display; | ||
| 331 | evt.requestor = event.requestor; | ||
| 332 | evt.selection = event.selection; | ||
| 333 | evt.time = event.time; | ||
| 334 | evt.target = event.target; | ||
| 335 | |||
| 336 | if (event.selection == XA_PRIMARY) | ||
| 337 | { | ||
| 338 | emacs_own_time = x_begin_selection_own; | ||
| 339 | selection_value = Vx_selection_value; | ||
| 340 | } | ||
| 341 | else if (event.selection == XA_SECONDARY) | ||
| 342 | { | ||
| 343 | emacs_own_time = x_begin_secondary_selection_own; | ||
| 344 | selection_value = Vx_secondary_selection_value; | ||
| 345 | } | ||
| 346 | else if (event.selection == Xatom_clipboard) | ||
| 347 | { | ||
| 348 | emacs_own_time = x_begin_clipboard_own; | ||
| 349 | selection_value = Vx_clipboard_value; | ||
| 350 | } | ||
| 351 | else | ||
| 352 | abort (); | ||
| 353 | |||
| 354 | if (event.time != CurrentTime | ||
| 355 | && event.time < emacs_own_time) | ||
| 356 | evt.property = None; | ||
| 357 | else | ||
| 358 | { | ||
| 359 | if (event.property == None) /* obsolete client */ | ||
| 360 | evt.property = event.target; | ||
| 361 | else | ||
| 362 | evt.property = event.property; | ||
| 363 | } | ||
| 364 | |||
| 365 | if (event.target == Xatom_targets) /* Send List of target atoms */ | ||
| 366 | { | ||
| 367 | } | ||
| 368 | else if (event.target == Xatom_multiple) /* Recvd list: <target, prop> */ | ||
| 369 | { | ||
| 370 | Atom type; | ||
| 371 | int return_format; | ||
| 372 | unsigned long items, bytes_left; | ||
| 373 | unsigned char *data; | ||
| 374 | int result, i; | ||
| 375 | |||
| 376 | if (event.property == 0 /* 0 == NILP */ | ||
| 377 | || event.property == None) | ||
| 378 | return; | ||
| 379 | |||
| 380 | result = XGetWindowProperty (event.display, event.requestor, | ||
| 381 | event.property, 0L, 10000000L, | ||
| 382 | True, Xatom_pair, &type, &return_format, | ||
| 383 | &items, &bytes_left, &data); | ||
| 384 | |||
| 385 | if (result == Success && type == Xatom_pair) | ||
| 386 | for (i = items; i > 0; i--) | ||
| 387 | { | ||
| 388 | /* Convert each element of the list. */ | ||
| 389 | } | ||
| 390 | |||
| 391 | (void) XSendEvent (x_current_display, evt.requestor, False, | ||
| 392 | 0L, (XEvent *) &evt); | ||
| 393 | return; | ||
| 394 | } | ||
| 395 | else if (event.target == Xatom_timestamp) /* Send ownership timestamp */ | ||
| 396 | { | ||
| 397 | if (! emacs_own_time) | ||
| 398 | abort (); | ||
| 399 | |||
| 400 | format = 32; | ||
| 401 | XChangeProperty (evt.display, evt.requestor, evt.property, | ||
| 402 | evt.target, format, PropModeReplace, | ||
| 403 | (unsigned char *) &emacs_own_time, 1); | ||
| 404 | return; | ||
| 405 | } | ||
| 406 | else if (event.target == Xatom_delete) /* Delete our selection. */ | ||
| 407 | { | ||
| 408 | if (EQ (Qnil, selection_value)) | ||
| 409 | abort (); | ||
| 410 | |||
| 411 | x_disown_selection (event.owner, event.selection, event.time); | ||
| 412 | |||
| 413 | /* Now return property of type NILP, length 0. */ | ||
| 414 | XChangeProperty (event.display, event.requestor, event.property, | ||
| 415 | 0, format, PropModeReplace, (unsigned char *) 0, 0); | ||
| 416 | return; | ||
| 417 | } | ||
| 418 | else if (event.target == Xatom_insert_selection) | ||
| 419 | { | ||
| 420 | Atom type; | ||
| 421 | int return_format; | ||
| 422 | unsigned long items, bytes_left; | ||
| 423 | unsigned char *data; | ||
| 424 | int result = XGetWindowProperty (event.display, event.requestor, | ||
| 425 | event.property, 0L, 10000000L, | ||
| 426 | True, Xatom_pair, &type, &return_format, | ||
| 427 | &items, &bytes_left, &data); | ||
| 428 | if (result == Success && type == Xatom_pair) | ||
| 429 | { | ||
| 430 | /* Convert the first atom to (a selection) to the target | ||
| 431 | indicated by the second atom. */ | ||
| 432 | } | ||
| 433 | } | ||
| 434 | else if (event.target == Xatom_insert_property) | ||
| 435 | { | ||
| 436 | Atom type; | ||
| 437 | int return_format; | ||
| 438 | unsigned long items, bytes_left; | ||
| 439 | unsigned char *data; | ||
| 440 | int result = XGetWindowProperty (event.display, event.requestor, | ||
| 441 | event.property, 0L, 10000000L, | ||
| 442 | True, XA_STRING, &type, &return_format, | ||
| 443 | &items, &bytes_left, &data); | ||
| 444 | |||
| 445 | if (result == Success && type == XA_STRING && return_format == 8) | ||
| 446 | { | ||
| 447 | if (event.selection == Xatom_emacs_selection) | ||
| 448 | Vx_selection_value = make_string (data); | ||
| 449 | else if (event.selection == Xatom_emacs_secondary_selection) | ||
| 450 | Vx_secondary_selection_value = make_string (data); | ||
| 451 | else if (event.selection == Xatom_clipboard_selection) | ||
| 452 | Vx_clipboard_value = make_string (data); | ||
| 453 | else | ||
| 454 | abort (); | ||
| 455 | } | ||
| 456 | |||
| 457 | return; | ||
| 458 | } | ||
| 459 | else if ((event.target == Xatom_text | ||
| 460 | || event.target == XA_STRING)) | ||
| 461 | { | ||
| 462 | int size = XSTRING (selection_value)->size; | ||
| 463 | unsigned char *data = XSTRING (selection_value)->data; | ||
| 464 | |||
| 465 | if (EQ (Qnil, selection_value)) | ||
| 466 | abort (); | ||
| 467 | |||
| 468 | /* Place data on requestor window's property. */ | ||
| 469 | if (SELECTION_LENGTH (size, format) | ||
| 470 | <= MAX_SELECTION (x_current_display)) | ||
| 471 | { | ||
| 472 | x_converting_selection = 1; | ||
| 473 | XChangeProperty (evt.display, evt.requestor, evt.property, | ||
| 474 | evt.target, format, PropModeReplace, | ||
| 475 | data, size); | ||
| 476 | if (x_selection_alloc_error) | ||
| 477 | { | ||
| 478 | x_selection_alloc_error = 0; | ||
| 479 | abort (); | ||
| 480 | } | ||
| 481 | x_converting_selection = 0; | ||
| 482 | } | ||
| 483 | else /* Send incrementally */ | ||
| 484 | { | ||
| 485 | evt.target = Xatom_incremental; | ||
| 486 | incr_requestor = evt.requestor; | ||
| 487 | incr_property = evt.property; | ||
| 488 | x_converting_selection = 1; | ||
| 489 | |||
| 490 | /* Need to handle Alloc errors on these requests. */ | ||
| 491 | XChangeProperty (evt.display, incr_requestor, incr_property, | ||
| 492 | Xatom_incremental, 32, | ||
| 493 | PropModeReplace, | ||
| 494 | (unsigned char *) &size, 1); | ||
| 495 | if (x_selection_alloc_error) | ||
| 496 | { | ||
| 497 | x_selection_alloc_error = 0; | ||
| 498 | x_converting_selection = 0; | ||
| 499 | abort (); | ||
| 500 | /* Now abort the send. */ | ||
| 501 | } | ||
| 502 | |||
| 503 | incr_nbytes = size; | ||
| 504 | incr_value = data; | ||
| 505 | incr_ptr = data; | ||
| 506 | |||
| 507 | /* Ask for notification when requestor deletes property. */ | ||
| 508 | XSelectInput (x_current_display, incr_requestor, PropertyChangeMask); | ||
| 509 | |||
| 510 | /* If we're sending incrementally, perhaps block here | ||
| 511 | until all sent? */ | ||
| 512 | } | ||
| 513 | } | ||
| 514 | else | ||
| 515 | evt.property = None; | ||
| 516 | |||
| 517 | /* Don't do this if there was an Alloc error: abort the transfer | ||
| 518 | by sending None. */ | ||
| 519 | (void) XSendEvent (x_current_display, evt.requestor, False, | ||
| 520 | 0L, (XEvent *) &evt); | ||
| 521 | } | ||
| 522 | |||
| 523 | /* Send an increment of selection data in response to a PropertyNotify event. | ||
| 524 | The increment is placed in a property on the requestor's window. | ||
| 525 | When the requestor has processed the increment, it deletes the property, | ||
| 526 | which sends us another PropertyNotify event. | ||
| 527 | |||
| 528 | When there is no more data to send, we send a zero-length increment. */ | ||
| 529 | |||
| 530 | void | ||
| 531 | x_send_incremental (event) | ||
| 532 | XPropertyEvent event; | ||
| 533 | { | ||
| 534 | if (incr_requestor | ||
| 535 | && incr_requestor == event.window | ||
| 536 | && incr_property == event.atom | ||
| 537 | && event.state == PropertyDelete) | ||
| 538 | { | ||
| 539 | int format = 8; | ||
| 540 | int length = MAX_SELECTION (x_current_display); | ||
| 541 | int bytes_left = (incr_nbytes - (incr_ptr - incr_value)); | ||
| 542 | |||
| 543 | if (length > bytes_left) /* Also sends 0 len when finished. */ | ||
| 544 | length = bytes_left; | ||
| 545 | XChangeProperty (x_current_display, incr_requestor, | ||
| 546 | incr_property, XA_STRING, format, | ||
| 547 | PropModeAppend, incr_ptr, length); | ||
| 548 | if (x_selection_alloc_error) | ||
| 549 | { | ||
| 550 | x_selection_alloc_error = 0; | ||
| 551 | x_converting_selection = 0; | ||
| 552 | /* Abandon the transmission. */ | ||
| 553 | abort (); | ||
| 554 | } | ||
| 555 | if (length > 0) | ||
| 556 | incr_ptr += length; | ||
| 557 | else | ||
| 558 | { /* Everything's sent */ | ||
| 559 | XSelectInput (x_current_display, incr_requestor, 0L); | ||
| 560 | incr_requestor = (Window) 0; | ||
| 561 | incr_property = (Atom) 0; | ||
| 562 | incr_nbytes = 0; | ||
| 563 | incr_value = (unsigned char *) 0; | ||
| 564 | incr_ptr = (unsigned char *) 0; | ||
| 565 | x_converting_selection = 0; | ||
| 566 | } | ||
| 567 | } | ||
| 568 | } | ||
| 569 | |||
| 570 | |||
| 571 | /* Requesting the value of a selection. */ | ||
| 572 | |||
| 573 | static Lisp_Object x_selection_arrival (); | ||
| 574 | |||
| 575 | /* Predicate function used to match a requested event. */ | ||
| 576 | |||
| 577 | Bool | ||
| 578 | XCheckSelectionEvent (dpy, event, window) | ||
| 579 | Display *dpy; | ||
| 580 | XEvent *event; | ||
| 581 | char *window; | ||
| 582 | { | ||
| 583 | if (event->type == SelectionNotify) | ||
| 584 | if (event->xselection.requestor == (Window) window) | ||
| 585 | return True; | ||
| 586 | |||
| 587 | return False; | ||
| 588 | } | ||
| 589 | |||
| 590 | /* Request a selection value from its owner. This will block until | ||
| 591 | all the data is arrived. */ | ||
| 592 | |||
| 593 | static Lisp_Object | ||
| 594 | get_selection_value (type) | ||
| 595 | Atom type; | ||
| 596 | { | ||
| 597 | XEvent event; | ||
| 598 | Lisp_Object val; | ||
| 599 | Time requestor_time; /* Timestamp of selection request. */ | ||
| 600 | Window requestor_window; | ||
| 601 | |||
| 602 | BLOCK_INPUT; | ||
| 603 | requestor_time = last_event_timestamp; | ||
| 604 | requestor_window = FRAME_X_WINDOW (selected_frame); | ||
| 605 | XConvertSelection (x_current_display, type, XA_STRING, | ||
| 606 | Xatom_emacs_selection, requestor_window, requestor_time); | ||
| 607 | XIfEvent (x_current_display, | ||
| 608 | &event, | ||
| 609 | XCheckSelectionEvent, | ||
| 610 | (char *) requestor_window); | ||
| 611 | val = x_selection_arrival (&event, requestor_window, requestor_time); | ||
| 612 | UNBLOCK_INPUT; | ||
| 613 | |||
| 614 | return val; | ||
| 615 | } | ||
| 616 | |||
| 617 | /* Request a selection value from the owner. If we are the owner, | ||
| 618 | simply return our selection value. If we are not the owner, this | ||
| 619 | will block until all of the data has arrived. */ | ||
| 620 | |||
| 621 | DEFUN ("x-selection", Fx_selection, Sx_selection, | ||
| 622 | 1, 1, "", | ||
| 623 | "Return the value of SELECTION.\n\ | ||
| 624 | SELECTION is one of `primary', `secondary', or `clipboard'.\n\ | ||
| 625 | \n\ | ||
| 626 | Selections are a mechanism for cutting and pasting information between\n\ | ||
| 627 | X Windows clients. When the user selects text in an X application,\n\ | ||
| 628 | the application should set the primary selection to that text; Emacs's\n\ | ||
| 629 | kill ring commands will then check the value of the `primary'\n\ | ||
| 630 | selection, and return it as the most recent kill.\n\ | ||
| 631 | The documentation for `x-set-selection' gives more information on how\n\ | ||
| 632 | the different selection types are intended to be used.\n\ | ||
| 633 | Also see the `interprogram-paste-function' variable.") | ||
| 634 | (selection) | ||
| 635 | register Lisp_Object selection; | ||
| 636 | { | ||
| 637 | Atom selection_type; | ||
| 638 | |||
| 639 | if (NILP (selection) || EQ (selection, Qprimary)) | ||
| 640 | { | ||
| 641 | if (!NILP (Vx_selection_value)) | ||
| 642 | return Vx_selection_value; | ||
| 643 | |||
| 644 | return get_selection_value (XA_PRIMARY); | ||
| 645 | } | ||
| 646 | else if (EQ (selection, Qsecondary)) | ||
| 647 | { | ||
| 648 | if (!NILP (Vx_secondary_selection_value)) | ||
| 649 | return Vx_secondary_selection_value; | ||
| 650 | |||
| 651 | return get_selection_value (XA_SECONDARY); | ||
| 652 | } | ||
| 653 | else if (EQ (selection, Qclipboard)) | ||
| 654 | { | ||
| 655 | if (!NILP (Vx_clipboard_value)) | ||
| 656 | return Vx_clipboard_value; | ||
| 657 | |||
| 658 | return get_selection_value (Xatom_clipboard); | ||
| 659 | } | ||
| 660 | else | ||
| 661 | error ("Invalid X selection type"); | ||
| 662 | } | ||
| 663 | |||
| 664 | static Lisp_Object | ||
| 665 | x_selection_arrival (event, requestor_window, requestor_time) | ||
| 666 | register XSelectionEvent *event; | ||
| 667 | Window requestor_window; | ||
| 668 | Time requestor_time; | ||
| 669 | { | ||
| 670 | int result; | ||
| 671 | Atom type, selection; | ||
| 672 | int format; | ||
| 673 | unsigned long items; | ||
| 674 | unsigned long bytes_left; | ||
| 675 | unsigned char *data = 0; | ||
| 676 | int offset = 0; | ||
| 677 | |||
| 678 | if (event->selection == XA_PRIMARY) | ||
| 679 | selection = Xatom_emacs_selection; | ||
| 680 | else if (event->selection == XA_SECONDARY) | ||
| 681 | selection = Xatom_emacs_secondary_selection; | ||
| 682 | else if (event->selection == Xatom_clipboard) | ||
| 683 | selection = Xatom_clipboard_selection; | ||
| 684 | else | ||
| 685 | abort (); | ||
| 686 | |||
| 687 | if (event->requestor == requestor_window | ||
| 688 | && event->time == requestor_time | ||
| 689 | && event->property != None) | ||
| 690 | if (event->target != Xatom_incremental) | ||
| 691 | { | ||
| 692 | unsigned char *return_string = | ||
| 693 | (unsigned char *) alloca (MAX_SELECTION (x_current_display)); | ||
| 694 | |||
| 695 | do | ||
| 696 | { | ||
| 697 | result = XGetWindowProperty (x_current_display, requestor_window, | ||
| 698 | event->property, 0L, | ||
| 699 | 10000000L, True, XA_STRING, | ||
| 700 | &type, &format, &items, | ||
| 701 | &bytes_left, &data); | ||
| 702 | if (result == Success && type == XA_STRING && format == 8 | ||
| 703 | && offset < MAX_SELECTION (x_current_display)) | ||
| 704 | { | ||
| 705 | bcopy (data, return_string + offset, items); | ||
| 706 | offset += items; | ||
| 707 | } | ||
| 708 | XFree ((char *) data); | ||
| 709 | } | ||
| 710 | while (bytes_left); | ||
| 711 | |||
| 712 | return make_string (return_string, offset); | ||
| 713 | } | ||
| 714 | else /* Prepare incremental transfer. */ | ||
| 715 | { | ||
| 716 | unsigned char *increment_value; | ||
| 717 | unsigned char *increment_ptr; | ||
| 718 | int total_size; | ||
| 719 | int *increment_nbytes = 0; | ||
| 720 | |||
| 721 | result = XGetWindowProperty (x_current_display, requestor_window, | ||
| 722 | selection, 0L, 10000000L, False, | ||
| 723 | event->property, &type, &format, | ||
| 724 | &items, &bytes_left, | ||
| 725 | (unsigned char **) &increment_nbytes); | ||
| 726 | if (result == Success) | ||
| 727 | { | ||
| 728 | XPropertyEvent property_event; | ||
| 729 | |||
| 730 | total_size = *increment_nbytes; | ||
| 731 | increment_value = (unsigned char *) alloca (total_size); | ||
| 732 | increment_ptr = increment_value; | ||
| 733 | |||
| 734 | XDeleteProperty (x_current_display, event->requestor, | ||
| 735 | event->property); | ||
| 736 | XFlush (x_current_display); | ||
| 737 | XFree ((char *) increment_nbytes); | ||
| 738 | |||
| 739 | do | ||
| 740 | { /* NOTE: this blocks. */ | ||
| 741 | XWindowEvent (x_current_display, requestor_window, | ||
| 742 | PropertyChangeMask, | ||
| 743 | (XEvent *) &property_event); | ||
| 744 | |||
| 745 | if (property_event.atom == selection | ||
| 746 | && property_event.state == PropertyNewValue) | ||
| 747 | do | ||
| 748 | { | ||
| 749 | result = XGetWindowProperty (x_current_display, | ||
| 750 | requestor_window, | ||
| 751 | selection, 0L, | ||
| 752 | 10000000L, True, | ||
| 753 | AnyPropertyType, | ||
| 754 | &type, &format, | ||
| 755 | &items, &bytes_left, | ||
| 756 | &data); | ||
| 757 | if (result == Success && type == XA_STRING | ||
| 758 | && format == 8) | ||
| 759 | { | ||
| 760 | bcopy (data, increment_ptr, items); | ||
| 761 | increment_ptr += items; | ||
| 762 | } | ||
| 763 | } | ||
| 764 | while (bytes_left); | ||
| 765 | |||
| 766 | } | ||
| 767 | while (increment_ptr < (increment_value + total_size)); | ||
| 768 | |||
| 769 | return make_string (increment_value, | ||
| 770 | (increment_ptr - increment_value)); | ||
| 771 | } | ||
| 772 | } | ||
| 773 | |||
| 774 | return Qnil; | ||
| 775 | } | ||
| 776 | |||
| 777 | |||
| 778 | /* Cut buffer management. */ | ||
| 779 | |||
| 780 | DEFUN ("x-get-cut-buffer", Fx_get_cut_buffer, Sx_get_cut_buffer, 0, 1, "", | ||
| 781 | "Return the value of cut buffer N, or nil if it is unset.\n\ | ||
| 782 | If N is omitted, it defaults to zero.\n\ | ||
| 783 | Note that cut buffers have some problems that selections don't; try to\n\ | ||
| 784 | write your code to use cut buffers only for backward compatibility,\n\ | ||
| 785 | and use selections for the serious work.") | ||
| 786 | (n) | ||
| 787 | Lisp_Object n; | ||
| 788 | { | ||
| 789 | int buf_num; | ||
| 790 | |||
| 791 | if (NILP (n)) | ||
| 792 | buf_num = 0; | ||
| 793 | else | ||
| 794 | { | ||
| 795 | CHECK_NUMBER (n, 0); | ||
| 796 | buf_num = XINT (n); | ||
| 797 | } | ||
| 798 | |||
| 799 | if (buf_num < 0 || buf_num >= NUM_CUT_BUFFERS) | ||
| 800 | error ("cut buffer numbers must be from zero to seven"); | ||
| 801 | |||
| 802 | { | ||
| 803 | Lisp_Object value; | ||
| 804 | |||
| 805 | /* Note that no PropertyNotify events will be processed while | ||
| 806 | input is blocked. */ | ||
| 807 | BLOCK_INPUT; | ||
| 808 | |||
| 809 | if (cut_buffer_cached & (1 << buf_num)) | ||
| 810 | value = XVECTOR (cut_buffer_value)->contents[buf_num]; | ||
| 811 | else | ||
| 812 | { | ||
| 813 | /* Our cache is invalid; retrieve the property's value from | ||
| 814 | the server. */ | ||
| 815 | int buf_len; | ||
| 816 | char *buf = XFetchBuffer (x_current_display, &buf_len, buf_num); | ||
| 817 | |||
| 818 | if (buf_len == 0) | ||
| 819 | value = Qnil; | ||
| 820 | else | ||
| 821 | value = make_string (buf, buf_len); | ||
| 822 | |||
| 823 | XVECTOR (cut_buffer_value)->contents[buf_num] = value; | ||
| 824 | cut_buffer_cached |= (1 << buf_num); | ||
| 825 | |||
| 826 | XFree (buf); | ||
| 827 | } | ||
| 828 | |||
| 829 | UNBLOCK_INPUT; | ||
| 830 | |||
| 831 | return value; | ||
| 832 | } | ||
| 833 | } | ||
| 834 | |||
| 835 | DEFUN ("x-set-cut-buffer", Fx_set_cut_buffer, Sx_set_cut_buffer, 2, 2, "", | ||
| 836 | "Set the value of cut buffer N to STRING.\n\ | ||
| 837 | Note that cut buffers have some problems that selections don't; try to\n\ | ||
| 838 | write your code to use cut buffers only for backward compatibility,\n\ | ||
| 839 | and use selections for the serious work.") | ||
| 840 | (n, string) | ||
| 841 | Lisp_Object n, string; | ||
| 842 | { | ||
| 843 | int buf_num; | ||
| 844 | |||
| 845 | CHECK_NUMBER (n, 0); | ||
| 846 | CHECK_STRING (string, 1); | ||
| 847 | |||
| 848 | buf_num = XINT (n); | ||
| 849 | |||
| 850 | if (buf_num < 0 || buf_num >= NUM_CUT_BUFFERS) | ||
| 851 | error ("cut buffer numbers must be from zero to seven"); | ||
| 852 | |||
| 853 | BLOCK_INPUT; | ||
| 854 | |||
| 855 | /* DECwindows and some other servers don't seem to like setting | ||
| 856 | properties to values larger than about 20k. For very large | ||
| 857 | values, they signal an error, but for intermediate values they | ||
| 858 | just seem to hang. | ||
| 859 | |||
| 860 | We could just truncate the request, but it's better to let the | ||
| 861 | user know that the strategy he/she's using isn't going to work | ||
| 862 | than to have it work partially, but incorrectly. */ | ||
| 863 | |||
| 864 | if (XSTRING (string)->size == 0 | ||
| 865 | || XSTRING (string)->size > MAX_SELECTION (x_current_display)) | ||
| 866 | { | ||
| 867 | XStoreBuffer (x_current_display, (char *) 0, 0, buf_num); | ||
| 868 | string = Qnil; | ||
| 869 | } | ||
| 870 | else | ||
| 871 | { | ||
| 872 | XStoreBuffer (x_current_display, | ||
| 873 | (char *) XSTRING (string)->data, XSTRING (string)->size, | ||
| 874 | buf_num); | ||
| 875 | } | ||
| 876 | |||
| 877 | XVECTOR (cut_buffer_value)->contents[buf_num] = string; | ||
| 878 | cut_buffer_cached |= (1 << buf_num); | ||
| 879 | cut_buffer_just_set |= (1 << buf_num); | ||
| 880 | |||
| 881 | UNBLOCK_INPUT; | ||
| 882 | |||
| 883 | return string; | ||
| 884 | } | ||
| 885 | |||
| 886 | /* Ask the server to send us an event if any cut buffer is modified. */ | ||
| 887 | |||
| 888 | void | ||
| 889 | x_watch_cut_buffer_cache () | ||
| 890 | { | ||
| 891 | XSelectInput (x_current_display, ROOT_WINDOW, PropertyChangeMask); | ||
| 892 | } | ||
| 893 | |||
| 894 | /* The server has told us that a cut buffer has been modified; deal with that. | ||
| 895 | Note that this function is called at interrupt level. */ | ||
| 896 | void | ||
| 897 | x_invalidate_cut_buffer_cache (XPropertyEvent *event) | ||
| 898 | { | ||
| 899 | int i; | ||
| 900 | |||
| 901 | /* See which cut buffer this is about, if any. */ | ||
| 902 | for (i = 0; i < NUM_CUT_BUFFERS; i++) | ||
| 903 | if (event->atom == cut_buffer_atom[i]) | ||
| 904 | { | ||
| 905 | int mask = (1 << i); | ||
| 906 | |||
| 907 | if (cut_buffer_just_set & mask) | ||
| 908 | cut_buffer_just_set &= ~mask; | ||
| 909 | else | ||
| 910 | cut_buffer_cached &= ~mask; | ||
| 911 | |||
| 912 | break; | ||
| 913 | } | ||
| 914 | } | ||
| 915 | |||
| 916 | |||
| 917 | /* Bureaucracy. */ | ||
| 918 | |||
| 919 | void | ||
| 920 | syms_of_xselect () | ||
| 921 | { | ||
| 922 | DEFVAR_LISP ("x-selection-value", &Vx_selection_value, | ||
| 923 | "The value of emacs' last cut-string."); | ||
| 924 | Vx_selection_value = Qnil; | ||
| 925 | |||
| 926 | DEFVAR_LISP ("x-secondary-selection-value", &Vx_secondary_selection_value, | ||
| 927 | "The value of emacs' last secondary cut-string."); | ||
| 928 | Vx_secondary_selection_value = Qnil; | ||
| 929 | |||
| 930 | DEFVAR_LISP ("x-clipboard-value", &Vx_clipboard_value, | ||
| 931 | "The string emacs last sent to the clipboard."); | ||
| 932 | Vx_clipboard_value = Qnil; | ||
| 933 | |||
| 934 | Qprimary = intern ("primary"); | ||
| 935 | staticpro (&Qprimary); | ||
| 936 | Qsecondary = intern ("secondary"); | ||
| 937 | staticpro (&Qsecondary); | ||
| 938 | Qclipboard = intern ("clipboard"); | ||
| 939 | staticpro (&Qclipboard); | ||
| 940 | |||
| 941 | defsubr (&Sx_set_selection); | ||
| 942 | defsubr (&Sx_selection); | ||
| 943 | |||
| 944 | cut_buffer_value = Fmake_vector (make_number (NUM_CUT_BUFFERS), Qnil); | ||
| 945 | staticpro (&cut_buffer_value); | ||
| 946 | |||
| 947 | defsubr (&Sx_get_cut_buffer); | ||
| 948 | defsubr (&Sx_set_cut_buffer); | ||
| 949 | } | ||
| 950 | #endif /* X11 */ | ||