ftp.nice.ch/pub/next/developer/languages/lisp/AKCL.1.599.s.tar.gz#/akcl-1-599/c/dguxsave.c

This is dguxsave.c in view mode; [Download] [Up]

/*
(C) Copyright Taiichi Yuasa and Masami Hagiya, 1984.  All rights reserved.
*/

#include "include.h"

struct nsection {
	unsigned int logical_start;
	unsigned int logical_length;
	unsigned int file_start;
	unsigned int file_length;
	unsigned int file_reloc;
	unsigned int file_reloc_length;
	unsigned int attributes;
	};

struct prformat {
	unsigned short magic_number;       /*  magic                 */
	unsigned short format_rev_number;  /*  format rev. number    */
	unsigned short num_non_exec_sect;  /*  # of non-exec.  sects */
	unsigned short num_exec_sect;      /*  # of executable sects */
	struct nsection syshead;        /*  system header */
	struct nsection symbolt;        /*  symbol table  */
	struct nsection ds;             /*                */
	struct nsection dl;             /*                */
	struct nsection lt;             /*                */
	struct nsection exec[2];        /*  two executable sections */
	};

struct system_header {
	unsigned int	start_pc;
	unsigned int	stacks;
	unsigned int	unlabeled;
	unsigned int	time_stamp;
	unsigned int	user_rev_number;
	unsigned short	flags;
	unsigned short	ntasks;
	unsigned short	nchannels;
	};

struct stack_register {
	unsigned int fp;
	unsigned int sp;
	unsigned int sl;
	unsigned int sb;
};

#define NUM_ENVIRON 6

/*
	saved_init copies arg and environment variables from top of data
	segment to stack area and shrink the memory.

	When execed by system, arg and environment variables are as follows;

	break value --> |                    |
		        +--------------------+
			| environ array ptr  |--------+
			+--------------------+        |
			| argument array ptr |----+   |
			+--------------------+    |   |
	AC2 ---------->	| argument count     |    |   |
			+--------------------+    |   |
			|                    |    |   |
	+============>	|    environment     |    |   |
	!		|                    |    |   |
	!		+--------------------+    |   |
	!		|                    |    |   |
	!	+====>	|     arguments      |    |   |
	!	!	|                    |    |   |
	!	!	+--------------------+    |   |
	+====== ! =====	| environment array  |<-- | --+
		!	+--------------------+    |
		+======	|   argument array   |<---+
			+--------------------+
			|                    |

*/


void
saved_init()
{
	char	*break_value;
	char	*new_break_value;
	char	*sbrk();
	char	*old_start;	/* old data area start byte address */
	char	*new_start;	/* new data area start byte address */
	int	size;		/* data size */
	int	*sp;		/* wide stack pointer */
	int	i;

	int	argc;
	char	**argv;
	char	**envp;

	break_value = sbrk(0);

	argc = *((unsigned int *)break_value - 3);	/* arg count */
	argv =
	 (char **)(*((unsigned int *)break_value - 2));	/* arg array ptr */
	envp =
	 (char **)(*((unsigned int *)break_value - 1));	/* env array ptr */

	/*
	old_start will be new break value after initialization.
	*/
	new_break_value = old_start = (char *)&argv[0];

	/*
	calc total space required. size is byte size and is multiple of 4
	becase both break_value and argv[0] are double word boundary.
	*/
	size = break_value - old_start;

	/* allocate space from stack. */
	sp = getsp();				/* current stack pointer */
	setsp(sp + size / 4);			/* extent stack */

	new_start = (char *)(sp + 1);

	blockmove(new_start, old_start, size);

	/*
	set up new argv and new envp
	*/
	argv = ((unsigned int)argv - (old_start - new_start) / 2);
	envp = ((unsigned int)envp - (old_start - new_start) / 2);

	for (i = 0; i < argc; i++)
		argv[i] -= (old_start - new_start);

	for (i = 0; i < NUM_ENVIRON; i++)
		envp[i] -= (old_start - new_start);

	new_break_value =
	(((unsigned int)new_break_value + PAGESIZE -1 ) / PAGESIZE) * PAGESIZE;

	brk(new_break_value);			/* shrink memory */

	main(argc, argv, envp);			/* call main routine */

	exit(0);
}

filecpy(to, from, n)
FILE *to, *from;
int n;
{
	char	buffer[BUFSIZ];

	for (;;)
		if (n > BUFSIZ) {
			fread(buffer, BUFSIZ, 1, from);
			fwrite(buffer, BUFSIZ, 1, to);
			n -= BUFSIZ;
		} else if (n > 0) {
			fread(buffer, n, 1, from);
			fwrite(buffer, n, 1, to);
			break;
		} else
			break;
}

memory_save(original_file, save_file)
char *original_file, *save_file;
{
	int	s, n;
	char	*data_start;
	int	data_size;
	int	orig_e0_start, orig_e0_len, orig_e1_start, orig_e1_len;
	char	*p, *sbrk();
	void	SVINIT();		/* special initializer */
	FILE	*in, *out;
	struct	prformat head;
	struct	system_header system;
	struct	stack_register sregs;
	char	buffer0[BUFSIZ], buffer1[BUFSIZ];
	char	buffer[BUFSIZ];

	out = fopen(save_file, "w+");
	if (out == NULL) FEerror("Can't open output file.", 0);
	setbuf(out, buffer0);

	in = fopen(original_file, "r");
	if (in == NULL) FEerror("Can't open original KCl.", 0);
	setbuf(in, buffer1);

	/*
		First, we must build file header. File header is built
		by modifying the origial program's file header.
	*/
	fread((char *)&head, sizeof(struct prformat), 1, in);

	orig_e0_start = head.exec[0].file_start;
	orig_e0_len = head.exec[0].file_length;
	orig_e1_start = head.exec[1].file_start;
	orig_e1_len = head.exec[1].file_length;

	data_size = sbrk(0) - (char *)034000000000;
	head.exec[1].file_start = (orig_e0_start + data_size + 02000) & ~01777;
	s = head.exec[1].file_start - orig_e1_start;
	head.symbolt.file_start += s;
	head.ds.file_start += s;
	head.dl.file_start += s;
	head.lt.file_start += s;
	head.exec[0].logical_length += (s / 2);
	head.exec[0].file_length = data_size;

	fwrite((char *)&head, sizeof(struct prformat), 1, out);	/* header */

	/*
		Start_pc should be changed to special initializer for 
		a saved program.
	*/
	fread((char *)&system, sizeof(system), 1, in);
	system.start_pc = &SVINIT;
	system.stacks = *(unsigned int *)016000000024 -
				*(unsigned int *)016000000026;
	fwrite((char *)&system, sizeof(system), 1, out);

	/*
		gap
	*/
	filecpy(out, in, orig_e0_start - sizeof(struct prformat)
		- sizeof(struct system_header));

	/*
		data segment
	*/
	for (p = (char *)034000000000, n = data_size;
	     ;p += BUFSIZ, n -= BUFSIZ)
		if (n > BUFSIZ)
			fwrite(p, BUFSIZ, 1, out);
		else if (n > 0) {
			fwrite(p, n, 1, out);
			break;
		} else
			break;

	/*
		gap
	*/
	zero(buffer, BUFSIZ);
	fwrite(buffer,
	  head.exec[1].file_start - (head.exec[0].file_start + data_size),
	  1,
	  out);

	/*
		text segment
	*/
	fseek(in, orig_e1_start, 0);
	filecpy(out, in, head.exec[1].file_length);

	/*
		others
	*/
	filecpy(out, in, head.symbolt.file_length);
	filecpy(out, in, head.ds.file_length);
	filecpy(out, in, head.dl.file_length);
	filecpy(out, in, head.lt.file_length);

	fclose(out);
	fclose(in);

	chmod(save_file, 0777);		/* change file mode */
}

Lsave()
{
	char	filename[256];

	check_arg(1);
	check_type_or_pathname_string_symbol_stream(&vs_base[0]);
	coerce_to_filename(vs_base[0], filename);
	memory_save(kcl_self, filename);
	exit(0);
}

init_dguxsave()
{
	make_function("SAVE", Lsave);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.