home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
emacs-19.28-src.tgz
/
tar.out
/
fsf
/
emacs
/
src
/
amiga_dump.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
36KB
|
1,530 lines
#include <exec/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <assert.h>
#include <proto/dos.h>
#include <setjmp.h>
#include <internal/messages.h>
#include "config.h"
#include "lisp.h"
#include "buffer.h"
#include "regex.h"
#include "amiga.h"
#include "dispextern.h"
#include "termchar.h"
#include "paths.h"
#include "frame.h"
#ifdef USE_PROTOS
#include "protos.h"
#endif
#define RANGE(ptr, s, e) ((char *)ptr >= (char *)s && (char *)ptr < (char *)e)
#define HUNK_POS (VALBITS - 3)
#define HUNK_MASK (7 << HUNK_POS)
#define HUNK_CODE (0 << HUNK_POS)
#define HUNK_DATA (1 << HUNK_POS)
#define HUNK_BSS (2 << HUNK_POS)
#define HUNK_MALLOC (3 << HUNK_POS)
#define HUNK_PURE (4 << HUNK_POS)
#define ARRAY_MARK_FLAG ((MARKBIT >> 1) & ~MARKBIT)
void *far first_fn = first_function, *far last_fn = last_function;
/* alloc.c */
extern int *pure, puresize;
extern struct gcpro *gcprolist;
extern Lisp_Object *staticvec[];
extern int staticidx;
extern struct cons_block *cons_block;
extern struct Lisp_Cons *cons_free_list;
extern struct Lisp_Vector *all_vectors;
extern struct symbol_block *symbol_block;
extern struct Lisp_Symbol *symbol_free_list;
extern struct marker_block *marker_block;
extern struct Lisp_Marker *marker_free_list;
extern struct interval_block *interval_block;
extern INTERVAL interval_free_list;
struct string_block_head
{
struct string_block_head *next, *prev;
int pos;
};
struct string_block
{
struct string_block *next, *prev;
#if 0 /* not needed */
int pos;
char chars[STRING_BLOCK_SIZE];
#endif
};
extern struct string_block *current_string_block;
extern struct string_block *first_string_block;
extern struct string_block *large_string_blocks;
#ifdef LISP_FLOAT_TYPE
extern struct float_block *float_block;
extern struct Lisp_Float *float_free_list;
#endif /* LISP_FLOAT_TYPE */
struct backtrace /* see eval.c or alloc.c */
{
struct backtrace *next;
Lisp_Object *function;
Lisp_Object *args; /* Points to vector of args. */
int nargs; /* Length of vector.
If nargs is UNEVALLED, args points to slot holding
list of unevalled args */
char evalargs;
/* Nonzero means call value of debugger when done with this operation. */
char debug_on_exit;
};
extern struct backtrace *backtrace_list;
struct catchtag
{
Lisp_Object tag;
Lisp_Object val;
struct catchtag *next;
struct gcpro *gcpro;
jmp_buf jmp;
struct backtrace *backlist;
struct handler *handlerlist;
int lisp_eval_depth;
int pdlcount;
int poll_suppress_count;
};
extern struct catchtag *catchlist;
extern char *stack_copy;
extern int *kbd_macro_buffer;
extern char *read_buffer, *chars_wasted, *copybuf;
#if 0
extern struct minibuf_save_data *minibuf_save_vector;
#endif
extern struct re_pattern_buffer searchbuf;
#if 0 /* CHFIXME */
extern int *ILcost, *DLcost, *ILncost, *DLncost;
#endif
#if 0
extern Lisp_Object MouseMap, global_map, Vglobal_map, Vesc_map, Vctl_x_map;
#else
extern Lisp_Object global_map, meta_map, control_x_map;
#endif
extern Lisp_Object selected_window;
extern char *callint_argfuns[];
/* lread.c/init_obarray variables */
extern Lisp_Object Qvariable_documentation, Vpurify_flag;
/* eval.c/init_eval_once variables */
/* specpdl */
/* syntax.c/init_syntax_once */
/* */
/* window.c variables */
/* */
/* buffer.c */
/* -> buffer.h */
/* dired.c */
extern Lisp_Object Qdirectory_files, Qfile_name_completion,
Qfile_name_all_completions, Qfile_attributes;
/* fileio.c */
extern Lisp_Object Qset_visited_file_modtime;
/* process.c */
/* extern Lisp_Object stream_process; CHFIXME activate HAVE_SOCKETS ?*/
/* editfns.c */
extern char *message_text;
/* regex variables */
typedef unsigned char *fail_stack_elt_t;
typedef struct
{
fail_stack_elt_t *stack;
unsigned size;
unsigned avail; /* Offset of next open position. */
} fail_stack_type;
typedef short register_info_type;
extern fail_stack_type fail_stack;
extern const char ** regstart, ** regend;
extern const char ** old_regstart, ** old_regend;
extern const char **best_regstart, **best_regend;
extern register_info_type *reg_info;
extern const char **reg_dummy;
extern void *reg_info_dummy;
/* keyboard.c/variables CHFIXME: need to be checked on version change */
#define HEAD_TABLE_SIZE 3
#define SCROLL_BAR_PARTS_SIZE 3
struct event_head {
Lisp_Object *var;
char *name;
Lisp_Object *kind;
};
extern struct event_head head_table[];
extern Lisp_Object *scroll_bar_parts[];
extern struct input_event *kbd_fetch_ptr;
extern struct input_event volatile *kbd_store_ptr;
/* search.c */
extern struct re_registers search_regs;
#if 0
#define DBUG /* dump debug */
#endif
static char *dump_error_example[] =
{
"dump-error-example-1",
"dump-error-example-2"
};
static void cpr() {} /* CHFIXME */
static void *dump_malloc(int size)
{
void *new = malloc(size);
if (!new) no_memory();
return new;
}
static void bailout(char *fn)
{
if (fn) _message("%s isn't a dump file for this version of Emacs, aborting", fn);
else _message("Dump file isn't for this version of Emacs, aborting");
/* We are in deep trouble, as all our variables are potentially corrupt */
/* Therefore, no cleanup is possible */
/* Remove cleanup routines */
onexit(0);
/* However, the library & the memory allocation should be ok, so
we can exit reasonably */
_fail("Some system resources may have been lost");
}
void print_ranges()
{
#if 0
_message("HUNK_CODE : %08lx .. %08lx (%08lx)",
first_fn, last_fn, (char *) last_fn - (char *) first_fn);
_message("HUNK_DATA : %08lx .. %08lx (%08lx)",
&first_data, &last_data, (char *) &last_data - (char *) &first_data);
_message("HUNK_BSS : %08lx .. %08lx (%08lx)",
&first_bss, &last_bss, (char *) &last_bss - (char *) &first_bss);
_message("HUNK_PURE : %08lx .. %08lx (%08lx)"
, pure, (char *)pure + puresize, puresize);
_message("HUNK_MALLOC: %08lx .. %08lx (%08lx)",
malloc_hunk, malloc_hunk + malloc_hunk_size, malloc_hunk_size);
#endif
}
/*
* ignore:
* stack_bottom, IconBase, last_marked (array), interval_block_index (int)
* gcprolist (currently?),
* pending (list), returned (list)
*/
int
check_ignore(void *x)
{
#ifndef USE_PROTOS
extern int IconBase, IFFParseBase, interval_block_index, instream, cliphook;
#else
extern int interval_block_index;
#endif
int ign = 0;
if((x == (void *) &IconBase)
|| (x == (void *) &stack_bottom)
/* || (x == (void *) &interval_block_index) */
|| (x == (void *) &pure)
|| (x == (void *) &gcprolist)
|| (x == (void *) &malloc_hunk)
|| (x == (void *) &IFFParseBase)
|| (x == (void *) &instream)
|| (x == (void *) &cbuffer_pos)
|| (x == (void *) &cliphook)
|| (x == (void *) ((int *)&cliphook+1))
|| (x == (void *) ((int *)&cliphook+2))
|| (x == (void *) &specpdl_ptr)
|| (x == (void *) &handlerlist) /* CHFIXME: ok? */
|| (x == (void *) &catchlist) /* CHFIXME: ok? */
|| (x == (void *) &backtrace_list) /* CHFIXME: ok? */
)
ign = 1;
return ign;
}
/*
* test for candidates which may need extra handling on dump
*/
void
check_cand(char *s, void *start, void *end)
{
unsigned int *ip, *starthit = NULL, *lasthit = NULL;
unsigned short int *is;
int range = 0;
int de = ((unsigned)dump_error_example[0] >> 24);
#define FIRST ((char*) &first_data) /* first symbol in data hunk */
for(is = start; (char *)is < (char *)end; is++)
{
ip = (unsigned int *) is;
if((((*ip >> 24) == 0x08)
|| (*ip >> 24) == de)
&& ! check_ignore(ip))
{
if(lasthit+1 == ip)
{
lasthit++;
range = 1;
}
else
{
if(range)
{
fprintf(stderr,"%s: 0x%08lx .. 0x%08lx (0x%08lx)\n",
s,
(char *)starthit-FIRST,
(char *)lasthit-FIRST,
(char*)lasthit-(char*)starthit);
range = 0;
}
else
{
starthit = lasthit = ip;
}
}
}
else
{
if((unsigned short *) lasthit+1 != is)
{
if(range)
{
fprintf(stderr,"%s: 0x%08lx .. 0x%08lx (0x%08lx)\n",
s,
(char *)starthit-FIRST,
(char *)lasthit-FIRST,
(char*)lasthit-(char*)starthit);
}
else if(lasthit)
{
fprintf(stderr,"%s: 0x%08lx (0x%08lx)\n", s, (char *)lasthit-FIRST, *lasthit);
}
range = 0;
lasthit = NULL;
}
}
}
if(range)
{
fprintf(stderr,"%s: 0x%08lx .. 0x%08lx (0x%08lx)\n",
s,
(char *)starthit-FIRST,
(char *)lasthit-FIRST,
(char*)lasthit-(char*)starthit);
}
else if(lasthit)
{
fprintf(stderr,"%s: 0x%08lx\n (0x%08ls)", s, (char *)lasthit-FIRST, *lasthit);
}
}
void
check_cands(void)
{
fprintf(stderr,"Possible candidates for FAR or amiga_dump\n");
check_cand("DATA", &first_data, &last_data);
check_cand("BSS ", &first_bss, &last_bss);
}
#ifdef DBUG
static int mcol = 0;
static int mrow = 0;
static FILE *mfile;
static char spaces[] = " ";
static mtresh = 0;
void MInit(char *s)
{
mcol = 0;
mrow = 0;
mtresh = 0;
mfile = fopen(s,"a");
fprintf(mfile,"\n***START***\n");
}
void MClean()
{
fprintf(mfile,"\n**END**\n");
fclose(mfile);
}
#define P(x)
void MEnter(char *s)
{
if(mtresh > 100) return;
#if 0
fwrite(spaces, mcol, 1, mfile);
#endif
fprintf(mfile, "(%d) %s\n", mcol, s);
mcol += 1;
}
void M(char *s)
{
if(mtresh > 100) return;
mtresh++;
#if 0
if(mcol)
fwrite(spaces, mcol, 1, mfile);
#endif
fprintf(mfile, "(%d) %s\n", mcol, s);
}
void MLeave(char *s)
{
if(mtresh > 100) return;
mcol -= 1;
#if 0
if(mcol)
fwrite(spaces, mcol, 1, mfile);
#endif
fprintf(mfile, "(%d) %s\n", mcol, s);
}
#else
#define MInit(x)
#define MClean()
#define MEnter(x)
#define M(x)
#define P(x)
#define MLeave(x)
#endif
static void *hunk_pointer(void *ptr)
{
if (!ptr)
{
P("P0");
return ptr;
}
#if 1 /* CHFIXME */
if(RANGE(ptr, first_fn, last_fn) && ((char *)ptr - (char *)first_fn) == 0x21c)
cpr();
#endif
if (RANGE(ptr, first_fn, last_fn))
{
P("PC");
return (void *)(HUNK_CODE | (char *)ptr - (char *)first_fn);
}
else if (RANGE(ptr, &first_data, &last_data))
{
P("PD");
return (void *)(HUNK_DATA | (char *)ptr - (char *)&first_data);
}
else if (RANGE(ptr, &first_bss, &last_bss))
{
P("PB");
return (void *)(HUNK_BSS | (char *)ptr - (char *)&first_bss);
}
else if (RANGE(ptr, malloc_hunk, malloc_hunk + malloc_hunk_size))
{
P("PM");
return (void *)(HUNK_MALLOC | (char *)ptr - malloc_hunk);
}
else if (RANGE(ptr, pure, (char *)pure + puresize))
{
P("PP");
return (void *)(HUNK_PURE | (char *)ptr - (char *)pure);
}
else
{
_message("hunk_pointer: cannot locate pointer 0x%08lx", ptr);
print_ranges();
bailout(0);
}
}
static Lisp_Object hunk_lispptr(Lisp_Object *objptr, Lisp_Object val)
{
int type = val & ~VALMASK;
void *ptr = (void *)XPNTR(val);
#if 1 /* CHFIXME */
if(RANGE(ptr, first_fn, last_fn) && ((char *)ptr - (char *)first_fn) == 0x21c)
cpr();
#endif
if (RANGE(ptr, first_fn, last_fn))
{
M("LC");
return type | HUNK_CODE | (char *)ptr - (char *)first_fn;
}
else if (RANGE(ptr, &first_data, &last_data))
{
M("LD");
return type | HUNK_DATA | (char *)ptr - (char *)&first_data;
}
else if (RANGE(ptr, &first_bss, &last_bss))
{
M("LB");
return type | HUNK_BSS | (char *)ptr - (char *)&first_bss;
}
else if (RANGE(ptr, pure, (char *)pure + puresize))
{
M("LP");
return type | HUNK_PURE | (char *)ptr - (char *)pure;
}
else if (RANGE(ptr, malloc_hunk, malloc_hunk + malloc_hunk_size))
{
M("LM");
return type | HUNK_MALLOC | (char *)ptr - malloc_hunk;
}
else
{
_message("hunk_pointer: cannot locate pointer 0x%08lx", ptr);
print_ranges();
bailout(0);
}
}
static void patch_pointers ();
static void patch_buffer (buf)
Lisp_Object buf;
{
Lisp_Object tem;
register struct buffer *buffer = XBUFFER (buf);
register Lisp_Object *ptr;
buffer->text.beg = hunk_pointer (buffer->text.beg);
patch_pointers (&buffer->markers);
/* This is the buffer's markbit */
patch_pointers (&buffer->name);
assert(!XMARKBIT(&buffer->name)); /* CHFIXME */
XMARK (buffer->name);
for (ptr = &buffer->name + 1;
(char *)ptr < (char *)buffer + sizeof (struct buffer);
ptr++)
patch_pointers (ptr);
}
static void patch_pointers (objptr)
Lisp_Object *objptr;
{
register Lisp_Object obj;
MEnter("O+");
loop:
obj = *objptr;
loop2:
XUNMARK (obj);
switch (XGCTYPE (obj))
{
case Lisp_String:
M("O1");
/* CHIXME */
{
register struct Lisp_String *ptr = XSTRING (obj);
if (ptr->size & MARKBIT)
/* A large string. */
_message("Lisp_String case: large_string found!");
}
*objptr = hunk_lispptr(objptr, *objptr);
break;
case Lisp_Vector:
case Lisp_Window:
case Lisp_Process:
case Lisp_Window_Configuration:
M("O2");
*objptr = hunk_lispptr(objptr, *objptr);
{
register struct Lisp_Vector *ptr = XVECTOR (obj);
register int size = ptr->size;
struct Lisp_Vector *volatile ptr1 = ptr; /* CHFIXME */
register int i;
if (size & ARRAY_MARK_FLAG) break; /* Already marked */
ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */
for (i = 0; i < size; i++) /* and then mark its elements */
patch_pointers (&ptr1->contents[i]);
}
break;
case Lisp_Compiled: /* similar to vector but avoid some recursion */
M("O3");
*objptr = hunk_lispptr(objptr, *objptr);
{
register struct Lisp_Vector *ptr = XVECTOR (obj);
register int size = ptr->size;
struct Lisp_Vector *volatile ptr1 = ptr; /* CHFIXME */
register int i;
if (size & ARRAY_MARK_FLAG) break; /* Already marked */
ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */
for (i = 0; i < size; i++) /* and then mark its elements */
if (i != COMPILED_CONSTANTS)
patch_pointers (&ptr1->contents[i]);
objptr = &ptr1->contents[COMPILED_CONSTANTS];
goto loop;
}
break;
case Lisp_Symbol:
M("O4");
*objptr = hunk_lispptr(objptr, *objptr);
{
register struct Lisp_Symbol * volatile ptr = XSYMBOL (obj);
struct Lisp_Symbol *ptrx;
if (XMARKBIT (ptr->plist)) break;
XMARK (ptr->plist);
patch_pointers ((Lisp_Object *) &ptr->value);
patch_pointers (&ptr->function);
patch_pointers (&ptr->plist);
XSETTYPE (*(Lisp_Object *) &ptr->name, Lisp_String);
patch_pointers ((Lisp_Object *) &ptr->name);
objptr = (Lisp_Object *)&ptr->next;
ptr = ptr->next;
if (ptr)
{
ptrx = ptr; /* Use pf ptrx avoids compiler bug on Sun */
XSETSYMBOL (obj, ptrx);
/* We can't goto loop here because *objptr doesn't contain an
actual Lisp_Object with valid datatype field. */
goto loop2;
}
}
break;
case Lisp_Marker:
M("O5");
{
struct Lisp_Marker *ptr = XMARKER (obj);
*objptr = hunk_lispptr(objptr, *objptr);
if (XMARKBIT (ptr->chain)) break;
XMARK (ptr->chain);
ptr->buffer = hunk_pointer (ptr->buffer);
patch_pointers (&ptr->chain);
break;
}
case Lisp_Cons:
case Lisp_Buffer_Local_Value:
case Lisp_Some_Buffer_Local_Value:
M("O6");
*objptr = hunk_lispptr(objptr, *objptr);
{
register struct Lisp_Cons *ptr = XCONS (obj);
if (XMARKBIT (ptr->car)) break;
XMARK (ptr->car);
patch_pointers (&ptr->car);
objptr = &XCONS (obj)->cdr;
goto loop;
}
case Lisp_Buffer:
M("O7");
*objptr = hunk_lispptr(objptr, *objptr);
if (!XMARKBIT (XBUFFER (obj)->name))
patch_buffer (obj);
break;
case Lisp_Subr:
M("O8");
{
struct Lisp_Subr *subr = XSUBR(obj);
*objptr = hunk_lispptr(objptr, *objptr);
if (subr->min_args & 0x8000) break;
subr->min_args |= 0x8000;
subr->function = hunk_pointer(subr->function);
subr->symbol_name = hunk_pointer(subr->symbol_name);
subr->prompt = hunk_pointer(subr->prompt);
if ((long)subr->doc >= 0) /* Make sure that not a doc offset */
subr->doc = hunk_pointer(subr->doc);
break;
}
case Lisp_Int:
case Lisp_Void:
case Lisp_Buffer_Objfwd: break;
case Lisp_Intfwd:
case Lisp_Boolfwd:
case Lisp_Objfwd:
case Lisp_Internal_Stream:
M("O9");
*objptr = hunk_lispptr(objptr, *objptr);
/* Don't bother with Lisp_Buffer_Objfwd,
since all markable slots in current buffer marked anyway. */
/* Don't need to do Lisp_Objfwd, since the places they point
are protected with staticpro. */
break;
#ifdef LISP_FLOAT_TYPE
case Lisp_Float:
M("OA");
*objptr = hunk_lispptr(objptr, *objptr);
XMARK (XFLOAT (obj)->type);
break;
#endif /* LISP_FLOAT_TYPE */
default:
_message("patch_pointers: unknown XGCTYPE (obj): %ld", XGCTYPE (obj));
abort ();
}
MLeave("O-");
}
static void patch_chain(void **ptr, int offset)
{
while (*ptr)
{
void **next = (void **)((char *)*ptr + offset);
*ptr = hunk_pointer(*ptr);
ptr = next;
}
}
#define HUNK_LISPPTR(a) a = hunk_lispptr(&a,a)
#define HUNK_PTR(a) a = hunk_pointer(a)
static void patch(void)
{
Lisp_Object LO;
int i;
struct string_block *sptr;
struct buffer *bptr;
struct mem_header *mem;
struct backtrace *backlist;
struct catchtag *catch;
MInit("MLOG.patch");
print_ranges(); /* CHFIXME */
#ifdef DBUG
i = 0;
#else
for (i = 0; i < staticidx; i++)
#endif
{
if (!XMARKBIT(*staticvec[i]))
{
patch_pointers(staticvec[i]);
XMARK(*staticvec[i]);
}
staticvec[i] = hunk_pointer(staticvec[i]);
}
#ifndef DBUG
/* Patch all the pointers normally used before a dump ! */
patch_chain((void **)&cons_block, 0);
patch_chain((void **)&cons_free_list, 0);
patch_chain((void **)&all_vectors, 4);
patch_chain((void **)&symbol_block, 0);
patch_chain((void **)&symbol_free_list, 4);
patch_chain((void **)&marker_block, 0);
patch_chain((void **)&marker_free_list, 4);
patch_chain((void **)&interval_block, 0);
patch_chain((void **)&interval_free_list, 4*sizeof(long));
/* Strings are lots of fun */
patch_chain((void **)&large_string_blocks, 0);
sptr = first_string_block;
while (sptr)
{
struct string_block *next = sptr->next;
if (sptr->next) HUNK_PTR(sptr->next);
if (sptr->prev) HUNK_PTR(sptr->prev);
sptr = next;
}
HUNK_PTR(first_string_block);
HUNK_PTR(current_string_block);
/* More fun with buffers */
bptr = all_buffers;
if (bptr)
{
while (bptr->next)
{
struct buffer *next = bptr->next;
HUNK_PTR(bptr->next);
bptr = next;
}
}
HUNK_PTR(all_buffers);
HUNK_PTR(current_buffer);
#ifdef LISP_FLOAT_TYPE
patch_chain((void **) &float_block, 0);
patch_chain((void **) &float_free_list, 0);
#endif /* LISP_FLOAT_TYPE */
#if 0 /* CHFIXME needed ? */
/* even more fun with 19.28 backtrace */
for (backlist = backtrace_list; backlist; )
{
struct backtrace *next = backlist->next;
if (!XMARKBIT (*backlist->function))
{
patch_pointers(backlist->function);
XMARK (*backlist->function);
}
if (backlist->nargs == UNEVALLED || backlist->nargs == MANY)
i = 0;
else
i = backlist->nargs - 1;
for (; i >= 0; i--)
if (!XMARKBIT (backlist->args[i]))
{
patch_pointers(&backlist->args[i]);
XMARK (backlist->args[i]);
}
if(backlist->next) HUNK_PTR(backlist->next);
backlist = next;
}
HUNK_PTR(backtrace_list);
for (catch = catchlist; catch;)
{
struct catchtag *next = catch->next;
patch_pointers (&catch->tag);
patch_pointers (&catch->val);
HUNK_PTR(catch->backlist);
HUNK_PTR(catch->handlerlist);
if(catch->next) HUNK_PTR(catch->next);
catch = next;
}
HUNK_PTR(catchlist);
#endif
/* HUNK_PTR(gcprolist); CHFIXME*/
HUNK_PTR(stack_copy);
HUNK_PTR(kbd_macro_buffer);
#if 0
HUNK_PTR(minibuf_save_vector);
#endif
HUNK_PTR(searchbuf.buffer);
HUNK_PTR(searchbuf.fastmap);
HUNK_PTR(specpdl);
HUNK_PTR(read_buffer);
#if 0 /* CHFIXME */
MouseMap = hunk_lispptr(&MouseMap, MouseMap);
#endif
HUNK_LISPPTR( current_global_map );
HUNK_LISPPTR( global_map );
HUNK_LISPPTR( meta_map );
HUNK_LISPPTR( control_x_map );
HUNK_LISPPTR( selected_window );
HUNK_LISPPTR( Qvariable_documentation );
#ifndef MULTI_FRAME
/* CHFIXME: use makro */
HUNK_LISPPTR( the_only_frame.root_window );
#else
you lose;
#endif
mem = free_list;
HUNK_PTR( free_list );
while (mem)
{
struct mem_header *next = mem->next;
HUNK_PTR( mem->prev );
HUNK_PTR( mem->next );
mem = next;
}
for (i = 0; i <= 4; i++)
HUNK_PTR( callint_argfuns[i] );
HUNK_PTR( fail_stack.stack );
HUNK_PTR( regstart );
HUNK_PTR( regend );
HUNK_PTR( old_regstart );
HUNK_PTR( old_regend );
HUNK_PTR( best_regstart );
HUNK_PTR( best_regend );
HUNK_PTR( reg_info );
HUNK_PTR( reg_dummy );
HUNK_PTR( reg_info_dummy );
for(i = 0; i < HEAD_TABLE_SIZE; i++)
{
HUNK_PTR( head_table[i].var );
HUNK_PTR( head_table[i].name );
HUNK_PTR( head_table[i].kind );
}
for(i = 0; i < SCROLL_BAR_PARTS_SIZE; i++)
{
HUNK_PTR( scroll_bar_parts[i] );
}
HUNK_PTR(kbd_fetch_ptr);
HUNK_PTR(kbd_store_ptr);
XSET(LO, Lisp_Buffer, &buffer_local_types);
patch_buffer(LO);
HUNK_LISPPTR(Qdirectory_files);
HUNK_LISPPTR(Qfile_name_completion);
HUNK_LISPPTR(Qfile_name_all_completions);
HUNK_LISPPTR(Qfile_attributes);
HUNK_LISPPTR(Qset_visited_file_modtime);
/* HUNK_LISPPTR(stream_process);*/
HUNK_PTR(message_text);
/* search.c */
HUNK_PTR(search_regs.start);
HUNK_PTR(search_regs.end);
#endif
MClean();
check_cands();
}
static dump(char *fn)
{
BPTR fd;
long size;
fd = Open(fn, MODE_NEWFILE);
if (!fd)
{
static void unpatch(void);
unpatch();
_fail("emacs hasn't been dumped (%s missing)", fn);
}
Write(fd, (char *)&puresize, sizeof puresize);
Write(fd, (char *)&malloc_hunk_size, sizeof malloc_hunk_size);
Write(fd, (char *)&first_data, (char *)&last_data - (char *)&first_data);
Write(fd, (char *)&first_bss, (char *)&last_bss - (char *)&first_bss);
Write(fd, (char *)pure, puresize);
Write(fd, (char *)malloc_hunk, malloc_hunk_size);
Write(fd, (char *)&staticidx, sizeof staticidx);
Write(fd, (char *)staticvec, staticidx * sizeof(Lisp_Object *));
size = (char *)last_fn - (char *)first_fn;
Write(fd, (char *)&size, sizeof size);
Close(fd);
}
static void *make_pointer(void *ptr)
{
int hunk = (long)ptr & HUNK_MASK;
int offset = (long)ptr & (VALMASK & ~HUNK_MASK);
if (!ptr)
{
P("P0");
return 0;
}
if (hunk == HUNK_CODE)
{
P("PC");
return (char *)first_fn + offset;
}
if (hunk == HUNK_DATA)
{
P("PD");
return (char *)&first_data + offset;
}
if (hunk == HUNK_BSS)
{
P("PB");
return (char *)&first_bss + offset;
}
if (hunk == HUNK_PURE)
{
P("PP");
return (char *)pure + offset;
}
if (hunk == HUNK_MALLOC)
{
P("PM");
return malloc_hunk + offset;
}
assert(0);
}
static Lisp_Object make_lispptr(Lisp_Object *objptr, Lisp_Object obj)
{
long val = XUINT(obj);
int hunk = val & HUNK_MASK;
int offset = val & ~HUNK_MASK;
char *ptr;
assert(obj); /* CHFIXME */
if (hunk == HUNK_CODE)
{
M("LC");
ptr = (char *)first_fn + offset;
}
else if (hunk == HUNK_DATA)
{
M("LD");
ptr = (char *)&first_data + offset;
}
else if (hunk == HUNK_BSS)
{
M("LB");
ptr = (char *)&first_bss + offset;
}
else if (hunk == HUNK_PURE)
{
M("LP");
ptr = (char *)pure + offset;
}
else if (hunk == HUNK_MALLOC)
{
M("LM");
ptr = malloc_hunk + offset;
}
else assert(0);
assert((int) ptr > 0); /* CHFIXME */
OXSETPNTR(obj, (long)ptr); /* CHFIXME */
return obj;
}
static void unpatch_pointers ();
static void unpatch_buffer (buf)
Lisp_Object buf;
{
Lisp_Object tem;
register struct buffer *buffer = XBUFFER (buf);
register Lisp_Object *ptr;
buffer->text.beg = make_pointer (buffer->text.beg);
unpatch_pointers (&buffer->markers);
/* This is the buffer's markbit */
XUNMARK (buffer->name);
unpatch_pointers (&buffer->name);
for (ptr = &buffer->name + 1;
(char *)ptr < (char *)buffer + sizeof (struct buffer);
ptr++)
unpatch_pointers (ptr);
}
static void unpatch_pointers (objptr)
Lisp_Object *objptr;
{
register Lisp_Object obj;
Lisp_Object obj2;
MEnter("O+");
loop:
obj = *objptr;
loop2:
XUNMARK (obj);
switch (XGCTYPE (obj))
{
case Lisp_String:
M("O1");
*objptr = make_lispptr(objptr, *objptr);
break;
case Lisp_Vector:
case Lisp_Window:
case Lisp_Process:
case Lisp_Window_Configuration:
M("O2");
obj = *objptr = make_lispptr(objptr, *objptr);
{
register struct Lisp_Vector *ptr = XVECTOR (obj);
register int size;
struct Lisp_Vector *volatile ptr1 = ptr; /* CHFIXME */
register int i;
if (!(ptr->size & ARRAY_MARK_FLAG)) break; /* Already unmarked */
size = ptr->size &= ~ARRAY_MARK_FLAG; /* Else unmark it */
for (i = 0; i < size; i++) /* and then unmark its elements */
unpatch_pointers (&ptr1->contents[i]);
}
break;
case Lisp_Compiled: /* similar to vector but avoid some recursion */
M("O3");
obj = *objptr = make_lispptr(objptr, *objptr);
{
register struct Lisp_Vector *ptr = XVECTOR (obj);
register int size = ptr->size;
struct Lisp_Vector *volatile ptr1 = ptr; /* CHFIXME */
register int i;
if (!(size & ARRAY_MARK_FLAG)) break; /* Already unmarked */
size = ptr->size &= ~ARRAY_MARK_FLAG; /* Else unmark it */
for (i = 0; i < size; i++) /* and then mark its elements */
if (i != COMPILED_CONSTANTS)
unpatch_pointers (&ptr1->contents[i]);
objptr = (Lisp_Object *) &ptr1->contents[COMPILED_CONSTANTS];
goto loop;
}
break;
case Lisp_Symbol:
M("O4");
/* due to goto below objptr may not point to object containing
SYMBOL type information so let obj care for symbol type */
obj2 = *objptr = make_lispptr(objptr, *objptr);
{
register struct Lisp_Symbol * volatile ptr = XSYMBOL (obj2);
struct Lisp_Symbol *ptrx;
if (!XMARKBIT (ptr->plist)) break;
XUNMARK (ptr->plist);
unpatch_pointers ((Lisp_Object *) &ptr->value);
unpatch_pointers (&ptr->function);
unpatch_pointers (&ptr->plist);
unpatch_pointers ((Lisp_Object *) &ptr->name);
ptr->name = XSTRING (*(Lisp_Object *)&ptr->name);
objptr = (Lisp_Object *)&ptr->next;
ptr = ptr->next;
if (ptr)
{
ptrx = ptr; /* Use pf ptrx avoids compiler bug on Sun */
XSETSYMBOL (obj, ptrx);
/* We can't goto loop here because *objptr doesn't contain an
actual Lisp_Object with valid datatype field. */
goto loop2;
}
}
break;
case Lisp_Marker:
M("O5");
obj = *objptr = make_lispptr(objptr, *objptr);
{
struct Lisp_Marker *ptr = XMARKER (obj);
if (!XMARKBIT (ptr->chain)) break;
XUNMARK (ptr->chain);
ptr->buffer = make_pointer (ptr->buffer);
unpatch_pointers (&ptr->chain);
}
break;
case Lisp_Cons:
case Lisp_Buffer_Local_Value:
case Lisp_Some_Buffer_Local_Value:
M("O6");
obj = *objptr = make_lispptr(objptr, *objptr);
{
register struct Lisp_Cons *ptr = XCONS (obj);
if (!XMARKBIT (ptr->car)) break;
XUNMARK (ptr->car);
unpatch_pointers (&ptr->car);
objptr = &ptr->cdr;
goto loop;
}
case Lisp_Buffer:
M("O7");
obj = *objptr = make_lispptr(objptr, *objptr);
if (XMARKBIT (XBUFFER (obj)->name))
unpatch_buffer (obj);
break;
case Lisp_Subr:
M("O8");
obj = *objptr = make_lispptr(objptr, *objptr);
{
struct Lisp_Subr *subr = XSUBR(obj);
if (!(subr->min_args & 0x8000)) break;
subr->min_args &= ~0x8000;
subr->function = make_pointer(subr->function);
subr->symbol_name = make_pointer(subr->symbol_name);
subr->prompt = make_pointer(subr->prompt);
if ((long)subr->doc >= 0) /* Make sure that not a doc offset */
subr->doc = make_pointer(subr->doc);
break;
}
case Lisp_Int:
case Lisp_Void:
case Lisp_Buffer_Objfwd: break;
case Lisp_Intfwd:
case Lisp_Boolfwd:
case Lisp_Objfwd:
case Lisp_Internal_Stream:
M("O9");
*objptr = make_lispptr(objptr, *objptr);
/* Don't bother with Lisp_Buffer_Objfwd,
since all markable slots in current buffer marked anyway. */
/* Don't need to do Lisp_Objfwd, since the places they point
are protected with staticpro. */
break;
#ifdef LISP_FLOAT_TYPE
case Lisp_Float:
M("OA");
obj = *objptr = make_lispptr(objptr, *objptr);
XUNMARK (XFLOAT (obj)->type);
break;
#endif /* LISP_FLOAT_TYPE */
default:
abort ();
}
MLeave("O-");
}
static void unpatch_chain(void **ptr, int offset)
{
while (*ptr)
{
*ptr = make_pointer(*ptr);
ptr = (void **)((char *)*ptr + offset);
}
}
/* CHFIXME: for all! */
#define MAKE_LISPPTR(a) a = make_lispptr(&a,a)
#define MAKE_PTR(a) a = make_pointer(a)
/* Reconstructs the addresses that were patched */
static void unpatch(void)
{
Lisp_Object LO;
int fd, i;
struct string_block *sptr;
struct buffer *bptr;
struct mem_header *mem;
struct backtrace *backlist;
struct catchtag *catch;
print_ranges(); /* CHFIXME */
MInit("MLOG.unpatch");
#ifdef DBUG
i = 0;
#else
for (i = 0; i < staticidx; i++)
#endif
{
staticvec[i] = make_pointer(staticvec[i]);
if (XMARKBIT(*staticvec[i]))
{
XUNMARK(*staticvec[i]);
unpatch_pointers(staticvec[i]);
}
}
#ifndef DBUG
/* Unpatch all the pointers normally used before a dump ! */
unpatch_chain((void **)&cons_block, 0);
unpatch_chain((void **)&cons_free_list, 0);
unpatch_chain((void **)&all_vectors, 4);
unpatch_chain((void **)&symbol_block, 0);
unpatch_chain((void **)&symbol_free_list, 4);
unpatch_chain((void **)&marker_block, 0);
unpatch_chain((void **)&marker_free_list, 4);
unpatch_chain((void **)&interval_block, 0);
unpatch_chain((void **)&interval_free_list, 4*sizeof(long));
/* Strings are lots of fun */
unpatch_chain((void **)&large_string_blocks, 0);
sptr = MAKE_PTR(first_string_block);
MAKE_PTR(current_string_block);
while (sptr)
{
if (sptr->next) MAKE_PTR(sptr->next);
if (sptr->prev) MAKE_PTR(sptr->prev);
sptr = sptr->next;
}
/* More fun with buffers */
bptr = MAKE_PTR(all_buffers);
if (bptr)
{
while (bptr->next)
{
MAKE_PTR(bptr->next);
bptr = bptr->next;
}
}
MAKE_PTR(current_buffer);
#ifdef LISP_FLOAT_TYPE
unpatch_chain((void **) &float_block, 0);
unpatch_chain((void **) &float_free_list, 0);
#endif /* LISP_FLOAT_TYPE */
#if 0 /* CHFIXME needed ? */
/* even more fun with 19.28 backtrace */
MAKE_PTR(backtrace_list);
for (backlist = backtrace_list; backlist; backlist = backlist->next)
{
if(backlist->next) MAKE_PTR(backlist->next);
if (XMARKBIT (*backlist->function))
{
XUNMARK (*backlist->function);
unpatch_pointers(backlist->function);
}
if (backlist->nargs == UNEVALLED || backlist->nargs == MANY)
i = 0;
else
i = backlist->nargs - 1;
for (; i >= 0; i--)
if (XMARKBIT (backlist->args[i]))
{
XUNMARK (backlist->args[i]);
unpatch_pointers(&backlist->args[i]);
}
}
MAKE_PTR(catchlist);
for (catch = catchlist; catch; catch = catch->next)
{
if(catch->next) MAKE_PTR(catch->next);
unpatch_pointers (&catch->tag);
unpatch_pointers (&catch->val);
MAKE_PTR(catch->backlist);
MAKE_PTR(catch->handlerlist);
}
#endif
/* MAKE_PTR(gcprolist); CHFIXME */
MAKE_PTR(stack_copy);
MAKE_PTR(kbd_macro_buffer);
#if 0
MAKE_PTR(minibuf_save_vector);
#endif
MAKE_PTR(searchbuf.buffer);
MAKE_PTR(searchbuf.fastmap);
MAKE_PTR(specpdl);
MAKE_PTR(read_buffer);
#if 0 /* CHFIXME */
MouseMap = make_lispptr(&MouseMap, MouseMap);
#endif
MAKE_LISPPTR(current_global_map);
MAKE_LISPPTR(global_map);
MAKE_LISPPTR(meta_map);
MAKE_LISPPTR(control_x_map);
MAKE_LISPPTR(selected_window);
MAKE_LISPPTR(Qvariable_documentation);
#ifndef MULTI_FRAME
/* CHFIXME: use makro */
MAKE_LISPPTR(the_only_frame.root_window);
#else
you lose;
#endif
MAKE_PTR(free_list);
mem = free_list;
while (mem)
{
MAKE_PTR(mem->prev);
MAKE_PTR(mem->next);
mem = mem->next;
}
for (i = 0; i <= 4; i++)
MAKE_PTR(callint_argfuns[i]);
MAKE_PTR(fail_stack.stack);
MAKE_PTR(regstart);
MAKE_PTR(regend);
MAKE_PTR(old_regstart);
MAKE_PTR(old_regend);
MAKE_PTR(best_regstart);
MAKE_PTR(best_regend);
MAKE_PTR(reg_info);
MAKE_PTR(reg_dummy);
MAKE_PTR(reg_info_dummy);
for(i = 0; i < HEAD_TABLE_SIZE; i++)
{
MAKE_PTR(head_table[i].var);
MAKE_PTR(head_table[i].name);
MAKE_PTR(head_table[i].kind);
}
for(i = 0; i < SCROLL_BAR_PARTS_SIZE; i++)
MAKE_PTR(scroll_bar_parts[i]);
MAKE_PTR(kbd_fetch_ptr);
MAKE_PTR(kbd_store_ptr);
XSET(LO, Lisp_Buffer, &buffer_local_types);
unpatch_buffer(LO);
MAKE_LISPPTR(Qdirectory_files);
MAKE_LISPPTR(Qfile_name_completion);
MAKE_LISPPTR(Qfile_name_all_completions);
MAKE_LISPPTR(Qfile_attributes);
MAKE_LISPPTR(Qset_visited_file_modtime);
/* MAKE_LISPPTR(stream_process);*/
MAKE_PTR(message_text);
/* search.c */
MAKE_PTR(search_regs.start);
MAKE_PTR(search_regs.end);
#endif
MClean();
}
static undump(char *fn)
{
BPTR fd;
long code_size;
char *_malloc_hunk;
int *_pure;
/*extern struct Library *FifoBase;
struct Library *_FifoBase = FifoBase;*/
fd = Open(fn, MODE_OLDFILE);
if (!fd) return 0;
Read(fd, (char *)&puresize, sizeof puresize);
Read(fd, (char *)&malloc_hunk_size, sizeof malloc_hunk_size);
_pure = dump_malloc(puresize);
_malloc_hunk = dump_malloc(malloc_hunk_size + pre_alloc);
Read(fd, (char *)&first_data, (char *)&last_data - (char *)&first_data);
Read(fd, (char *)&first_bss, (char *)&last_bss - (char *)&first_bss);
Read(fd, (char *)_pure, puresize);
Read(fd, (char *)_malloc_hunk, malloc_hunk_size);
Read(fd, (char *)&staticidx, sizeof staticidx);
Read(fd, (char *)staticvec, staticidx * sizeof(Lisp_Object *));
/*FifoBase = _FifoBase;*/
if (Read(fd, (char *)&code_size, sizeof code_size) != sizeof code_size ||
code_size != (char *)last_fn - (char *)first_fn)
{
Close(fd);
bailout(fn);
}
Close(fd);
malloc_hunk = _malloc_hunk;
pure = _pure;
return 1;
}
void map_out_data(char *fn)
{
if (amiga_initialized) error("You can only dump once !");
Fgarbage_collect();
#if 0 /* CHFIXME */
dump("EMACS-DATA.pre");
#endif
patch();
dump(fn);
unpatch();
#if 0
dump("EMACS-DATA.post");
#endif
amiga_initialized = 1;
}
#ifndef MULTI_FRAME
static struct x_display A_Display;
#else
you lose */
#endif
void map_in_data(int load)
{
if (load && undump(NAME_DATA))
{
unpatch();
#if 0 /*CHFIXME */
current_screen = new_screen = temp_screen = 0;
message_buf = 0;
#endif
chars_wasted = 0;
copybuf = 0;
initialized = amiga_initialized = 1;
/* CHFIXME: force errors if used but not patched */
handlerlist = (void *) -1;
catchlist = (void *)-1;
backtrace_list = (void *)-1;
#if 0
FRAME_EXTERNAL_MENU_BAR(selected_frame) = 1; /* CHFIXME where to put? */
#endif
}
else
{
malloc_hunk = dump_malloc(malloc_hunk_size + pre_alloc);
pure = dump_malloc(puresize);
}
#ifndef MULTI_FRAME
FRAME_DISPLAY(selected_frame) = &A_Display;
#else
you lose again.
#endif
amiga_undump_reinit();
}
void
early_init_amiga_dump()
{
#ifndef MULTI_FRAME
FRAME_DISPLAY(selected_frame) = &A_Display;
#else
you lose again.
#endif
}