[comp.sources.atari.st] v02i075: gcclib2 -- Patches to GCC library part04/07

koreth%panarthea.ebay@sun.com (Steven Grimm) (08/20/89)

Submitted-by: uunet.UU.NET!unido!sbsvax!roeder (Edgar Roeder)
Posting-number: Volume 2, Issue 75
Archive-name: gcclib2/part04



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 4 (of 7)."
# Contents:  memory.c.cdiff pexecv.c signal.c stat.c system.c timer.c
# Wrapped by roeder@sbsvax on Wed Aug 16 22:03:02 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'memory.c.cdiff' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'memory.c.cdiff'\"
else
echo shar: Extracting \"'memory.c.cdiff'\" \(4440 characters\)
sed "s/^X//" >'memory.c.cdiff' <<'END_OF_FILE'
X*** terminator/memory.c	Fri Aug 11 18:52:40 1989
X--- new-lib/memory.c	Thu Aug  3 22:37:44 1989
X***************
X*** 1 ****
X--- 1,14 ----
X+ /* Added malloc_init and warnfunction for emacs support
X+  * This will only work if you set _stksize = -1. Otherwise we have no
X+  * correct lim_data and data_bytes_unused
X+  * [[ i have a solution for this, but i included this stuff for emacs only ]]
X+  * er (Edgar Roeder)
X+  */
X+ /* Changed 89/02/06, AD (Atze Dijkstra ) 
X+    System request made dependant of _heapbase, init in crt0.s.
X+    If != NULL, mem will not be requested via Malloc,
X+    but heap and stack are contiguous and consume almost
X+    all the free mem.
X+    Corrected 23-Jun-1989 by Piet van Oostrum
X+  */
X  
X***************
X*** 3,4 ****
X--- 16,25 ----
X  
X+ extern	char *		_heapbase ; 	/*AD, PvO*/
X+ extern	char *		_stksize ; 	/*AD, PvO*/
X+ 
X+ static long	malloc_bytes_in_free_list = 0;
X+ 
X+ long	malloc_sbrk_used = 0;
X+ long	malloc_sbrk_unused = 1024000;	/* only dummy initializer */
X+ 
X  /* minimum chunk to ask OS for */
X***************
X*** 6,9 ****
X  
X- #include <osbind.h>
X- 
X  #define NULL 0
X--- 27,28 ----
X***************
X*** 20,21 ****
X--- 39,91 ----
X  
X+ /* Number of bytes of writable memory we can expect to be able to get */
X+ static long lim_data = 0;
X+ 
X+ /* Level number of warnings already issued.
X+   0 -- no warnings issued.
X+   1 -- 75% warning already issued.
X+   2 -- 85% warning already issued.
X+ */
X+ static int warnlevel;
X+ 
X+ /* Function to call to issue a warning;
X+    0 means don't issue them.  */
X+ static void (*warnfunction) ();
X+ 
X+ /* Cause reinitialization based on job parameters;
X+   also declare where the end of pure storage is. */
X+ void
X+ malloc_init (start, warnfun)	/* ignore start - it's for emacs to get happy */
X+      char *start;
X+      void (*warnfun) ();
X+ {
X+   malloc_sbrk_unused = lim_data = 0;
X+   warnlevel = 0;
X+   if (warnfun != (void (*)) -1)
X+     warnfunction = warnfun;
X+ }
X+ 
X+ static char * HeapAlloc( sz )			/*AD, PvO*/
X+   unsigned long sz ;				/*AD*/
X+ {						/*AD*/
X+   
X+   char slush [64];				/*PvO*/
X+   register char* sp ;				/*AD, PvO*/
X+   int	available;
X+ 						/*AD*/
X+   sp = slush;					/*AD, PvO*/
X+   available = (int) (sp - _heapbase + sz);
X+   if (!lim_data) lim_data = available;
X+   if ( available < 0 )				/*AD, PvO, er*/
X+   {						/*AD*/
X+     return( NULL ) ;				/*AD*/
X+   }						/*AD*/
X+   malloc_sbrk_unused = available + malloc_bytes_in_free_list;
X+   malloc_bytes_in_free_list += sz;
X+   sp = _heapbase ;				/*AD*/
X+   _heapbase += sz ;				/*AD*/
X+   _stksize -= sz ;				/*AD*/
X+ 						/*AD*/
X+   return( sp ) ;				/*AD*/
X+ }						/*AD*/
X+ 
X  char * malloc(n)
X***************
X*** 62,65 ****
X  */
X! /*	q = (struct mem_chunk * )trap_1_wlww(0x48, sz);	*/
X! 	q = (struct mem_chunk * )Malloc(sz);
X  /*
X--- 132,137 ----
X  */
X! 	if ( _heapbase )					/*AD*/
X! 		q = (struct mem_chunk * )HeapAlloc( sz ) ;	/*AD*/
X! 	else							/*AD*/
X! 		q = (struct mem_chunk * )trap_1_wlww(0x48, sz);
X  /*
X***************
X*** 68,69 ****
X--- 140,162 ----
X  */
X+ 	if(warnfunction)
X+ 	switch (warnlevel) {
X+ 		case 0: 
X+ 		if (malloc_sbrk_used > (lim_data / 4) * 3) {
X+ 			warnlevel++;
X+ 			(*warnfunction) ("Warning: past 75% of memory limit\n");
X+ 		}
X+ 		break;
X+ 		case 1: 
X+ 		if (malloc_sbrk_used > (lim_data / 20) * 17) {
X+ 			warnlevel++;
X+ 			(*warnfunction) ("Warning: past 85% of memory limit\n");
X+ 		}
X+ 		break;
X+ 		case 2: 
X+ 		if (malloc_sbrk_used > (lim_data / 20) * 19) {
X+ 			warnlevel++;
X+ 		(*warnfunction) ("Warning: past 95% of memory limit\n");
X+ 		}
X+ 		break;
X+ 	}
X  	if (((long)q) <= 0) 		/* can't alloc any more? */
X***************
X*** 94,95 ****
X--- 187,191 ----
X  */
X+   malloc_sbrk_used += q->size;
X+   malloc_sbrk_unused -= q->size;
X+   malloc_bytes_in_free_list -= q->size;
X    return((char * )++q);
X***************
X*** 102,103 ****
X--- 198,200 ----
X  
X+   if (!r) return;
X  /* move back to uncover the mem_chunk */
X***************
X*** 104,105 ****
X--- 201,205 ----
X    r--;			/* there it is! */
X+   malloc_sbrk_used -= r->size;
X+   malloc_sbrk_unused += r->size;
X+   malloc_bytes_in_free_list += r->size;
X  /*
X***************
X*** 158,160 ****
X  	{			/* block too small, get new one */
X! 	dst = q = (struct mem_chunk * )malloc(n);
X  	if (q != NULL)
X--- 258,260 ----
X  	{			/* block too small, get new one */
X! 	dst = (long *) q = (struct mem_chunk * )malloc(n);
X  	if (q != NULL)
X***************
X*** 190,191 ****
X  }
X- 
X--- 290 ----
END_OF_FILE
if test 4440 -ne `wc -c <'memory.c.cdiff'`; then
    echo shar: \"'memory.c.cdiff'\" unpacked with wrong size!
fi
# end of 'memory.c.cdiff'
fi
if test -f 'pexecv.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'pexecv.c'\"
else
echo shar: Extracting \"'pexecv.c'\" \(3861 characters\)
sed "s/^X//" >'pexecv.c' <<'END_OF_FILE'
X#ifdef test
X#define testmain
X#include <stdio.h>
X#endif
X#include <osbind.h>
X#include <ctype.h>
X#include <time.h>
X
X#define alloca	__builtin_alloca
X
Xclock_t	_child_runtime;
Xchar	*xarg_pattern = "xArg=00000000";
Xchar	*pbp_pattern = "PBP=%ld";
X
Xint
XPexecv(int mode, const char *command, char *argv[], char *env[])
X{
X	extern char	**environ;
X	register char	*new_env;
X	register int	env_len = 0;
X	register int	arg_len = 30;	/* "PBP=%ld\0ARGV=" + 10 bytes slack */
X	register char	*cp;
X	register char	**ap, **ep;
X	register int	i;
X	int	old_parameter_passing;
X	char	*tail;
X	char	cmd[strlen(command)+1];
X	int	old_input, old_output, in, out;
X	clock_t	start_time;
X	short	argc;
X	struct {
X		long	magic;
X		short	argc;
X		char	**argv;
X		char	*iovector;
X		long	parent;
X	} xarg_vector;
X	extern long	_base;
X
X	strcpy(cmd, command);
X	unix_to_tos(cmd);
X	if(!env) env = environ;
X#ifdef test
X	printf("Pexecv(%d,%s,%06lx,%06lx)\n",mode,cmd,argv,env);
X	printf("calculating environment length ..."); fflush(stdout);
X#endif
X	ep = env;
X	if(ep) while(*ep) env_len += 1 + strlen(*ep++);
X#ifdef test
X	printf(" done (%d)\n", env_len);
X	printf("calculating argument length ..."); fflush(stdout);
X#endif
X	ap = argv;
X	argc = 0;
X	if(ap) while(*ap) {
X		arg_len += 1 + strlen(*ap++);
X		argc++;
X	}
X#ifdef test
X	printf(" done (%d, %d args)\n", arg_len, argc);
X	printf("copying environment ...\n");
X#endif
X	cp = new_env = alloca(env_len+arg_len+1);
X	ep = env;
X	if(ep) while(*ep && strncmp("ARGV=",*ep,5)) {
X		/* don't pass our own arguments */
X#ifdef test
X		printf("copy '%s'", *ep);
X#endif
X		if(strncmp(xarg_pattern,*ep,5) && strncmp(pbp_pattern,*ep,4)) {
X			strcpy(cp,*ep++);
X			cp += strlen(cp) + 1;
X#ifdef test
X			printf("\n");
X#endif
X		} else {
X			ep++;
X#ifdef test
X			printf(" skipped\n");
X#endif
X		}
X	}
X#ifdef test
X	printf("copying environment ... done\n");
X#endif
X	in = out = old_input = old_output = -10;
X	if(old_parameter_passing = isupper(argv[0][0])) {
X		/* This is for old compiler passes not recognizing xArg */
X		strcpy(cp,"ARGV=CCC?");
X		cp += 10;
X	}
X	tail = alloca(arg_len);
X	*tail = '\0';
X	ap = argv;
X	if(ap) while(1) {
X		strcpy(cp,*ap++);
X		if((*cp == '<' || *cp == '>') && !cp[1] && *ap) {
X			if(*cp == '>') {
X				old_output = Fdup(1);
X				Fforce(1, out = creat(*ap++, 0664));
X			} else {
X				old_input = Fdup(0);
X				Fforce(0, in = open(*ap++, 0));
X			}
X		} else if(old_parameter_passing) cp += strlen(cp) + 1;
X		if(!*ap) break;
X		strcat(tail," ");
X		strcat(tail,*ap);
X	}
X	*cp = '\0';
X	i = strlen(tail);
X	if(i > 126) i = 126;
X	*tail = i - 1;
X	tail[i] = '\0';
X	strcat(tail+1,"\r");
X	if(!old_parameter_passing) {
X		long	tmp;
X#ifdef test
X		char	*savepos;
X#endif
X
X		xarg_vector.magic = 0x78417267;
X		xarg_vector.iovector = (char *) 0;
X		xarg_vector.parent = _base;
X		xarg_vector.argv = argv;
X		xarg_vector.argc = argc;
X		strcpy(cp,xarg_pattern);
X#ifdef test
X		savepos = cp;
X#endif
X		cp += 13;
X		tmp = (long) &xarg_vector;
X		while(tmp) {
X			*--cp = "0123456789ABCDEF"[tmp & 0x0F];
X			tmp >>= 4;
X		}
X#ifdef test
X		printf("xArg Parameters\n");
X		printf("Environment variable = '%s'\n",savepos);
X		printf("\t   magic = '%4s'\n",&(xarg_vector.magic));
X		printf("\tiovector = %08lx\n",xarg_vector.iovector);
X		printf("\t  parent = %08lx\n",xarg_vector.parent);
X		printf("\t    argc = %d\n",xarg_vector.argc);
X		printf("\t    argv = %08lx\n",xarg_vector.argv);
X#endif
X	}
X	start_time = clock();
X	i = (Pexec(mode, cmd, tail, new_env));
X	_child_runtime += clock() - start_time;
X#ifdef test
X	printf("Pexec() returns %X = %d\n", i, i);
X#endif
X	if(old_output != -10) Fforce(1, old_output);
X	Fclose(old_output);
X	close(out);
X	if(old_input != -10) Fforce(0, old_input);
X	Fclose(old_input);
X	close(in);
X#ifdef test
X	fprintf(stderr, "Pexec() returns %X = %d\n", i, i);
X#endif
X	return(i);
X}
X
X#ifdef testmain
Xmain(int argc, char *argv[])
X{
X	printf("argc = %d\n", argc);
X	Pexecv(0, "a.out", argv, 0L);
X}
X#endif
END_OF_FILE
if test 3861 -ne `wc -c <'pexecv.c'`; then
    echo shar: \"'pexecv.c'\" unpacked with wrong size!
fi
# end of 'pexecv.c'
fi
if test -f 'signal.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'signal.c'\"
else
echo shar: Extracting \"'signal.c'\" \(5591 characters\)
sed "s/^X//" >'signal.c' <<'END_OF_FILE'
X/*
X *		Cross Development System for Atari ST 
X *     Copyright (c) 1988, Memorial University of Newfoundland
X *
X * Use a signal stack when serving signals arrived in super mode (er) 14.8.89
X *
X * Added execute_in_user_mode and changed sig_array type, added some new
X * signals (SIGUSR, SIGHUP) (er)
X *
X * Adapted to ANSI-C (_do_signal renamed to raise) (er)
X * added return value and error checking to raise (er)
X *
X *   Signal routine - the signals are actually done by calling the _do_signal
X * routine - similiar to kill() I guess.
X *
X * $Header: signal.c,v 1.1 88/02/03 22:58:53 m68k Exp $
X *
X * $Log:	signal.c,v $
X * Revision 1.1  88/02/03  22:58:53  m68k
X * Initial revision
X * 
X */
X#include	<signal.h>
X#include	<errno.h>
X#include	<osbind.h>
X#include	<stdlib.h>
X
Xstatic void	stop(int);
Xextern void	_exit(int);
X
X/* ANSI C says that signal handlers have type (void (*)(int)) but even gcc */
X/* assumes that it's (int (*)(int)) */
X
X#define my_exit	((sig_handler_t *) exit)
X#define my_quit	((sig_handler_t *) _exit)
X#define my_stop	((sig_handler_t *) stop)
X
Xstatic struct sigarray_str {
X	sig_handler_t	*s_func;	/* actual handler */
X	sig_handler_t	*d_func;	/* default handler */
X} sig_array[NSIG] = {
X	{ SIG_DFL, SIG_IGN },	/* SIGNULL */
X	{ SIG_DFL, SIG_IGN },	/* SIGALRM */
X	{ SIG_DFL, my_exit },	/* SIGSEGV */
X	{ SIG_DFL, my_exit },	/* SIGODD */
X	{ SIG_DFL, my_exit },	/* SIGILL */
X	{ SIG_DFL, SIG_IGN },	/* SIGZDIV */
X	{ SIG_DFL, my_exit },	/* SIGCHK */
X	{ SIG_DFL, my_exit },	/* SIGTRAP */
X	{ SIG_DFL, my_exit },	/* SIGPRIV */
X	{ SIG_DFL, SIG_IGN },	/* SIGTRACE */
X	{ SIG_DFL, my_exit },	/* SIGINT */
X	{ SIG_DFL, my_exit },	/* SIGQUIT */
X	{ SIG_DFL, my_stop },	/* SIGTSTP */
X	{ SIG_DFL, SIG_IGN },	/* SIGFPE */
X	{ SIG_IGN, my_exit },	/* SIGHUP */
X	{ SIG_DFL, my_quit },	/* SIGABRT */
X	{ SIG_DFL, my_exit },	/* SIGTERM */
X	{ SIG_DFL, SIG_IGN },	/* SIGUSR1 */
X	{ SIG_DFL, SIG_IGN },	/* SIGUSR2 */
X};
X
X#undef my_exit
X#undef my_quit
X#undef my_stop
X
Xsig_handler_t *
Xsignal(int sig, sig_handler_t *func)
X{
X	sig_handler_t	*oldfunc;
X
X	if (sig >= 0 && sig < NSIG) {
X		oldfunc = sig_array[sig].s_func;
X		sig_array[sig].s_func = func;
X	} else {
X		errno = EINVAL;
X		oldfunc = SIG_ERR;
X	}
X	return oldfunc;
X}
X
Xvolatile char	_sig_done;	/* needed for pause.c */
Xstatic long	_signal_stack[256];
Xstatic long	*const signal_stack = _signal_stack+256;
X
X/* We can't just switch the stack pointers to execute in usermode since	*/
X/* there are some programs which use their userstack as supervisorstack */
X/* too. We use a special signal stack which is reset to it's start if a */
X/* signal is received in supervisor mode. This is safe because the only */
X/* way to get back to the supervisor mode if you are in user mode would */
X/* use a call to the operating system (and so to the standard library), */
X/* which leeds to undefined behavior according to ANSI C. If we get the */
X/* signal in usermode we need not to worry about the stack.             */
Xstatic /* no inline */ void
Xexecute_in_usermode(sig_handler_t *func, int param)
X{
X	auto int	super_mode;	/* Avoid any problems with func by */
X	auto long	super_stack;	/* putting these important vars on */
X	auto long	user_stack;	/* the stack and not in registers. */
X
X	if (super_mode = Super(1)) {
X		asm ("movel sp, %0" : "=g" (super_stack));
X		asm ("movel usp, %0" : "=a" (user_stack));
X		asm ("andiw #0xDFFF, sr");	/* switch to the user mode */
X		asm ("movel %0, sp" :: "g" (signal_stack));
X	}
X	(void) (*func)(param);	/* this is executed in user mode */
X	/* In the following cases we would never return to here: */
X	/*	- func terminates with exit or abort		 */
X	/*	- func terminates with a longjmp		 */
X	/* In both of the cases we don't need to know where the  */
X	/* userstack pointer was before the supervisormode was   */
X	/* entered since we don't want to get back there either. */
X	if (super_mode) {
X		Super(super_stack - 6);		/* this uses the user stack! */
X		/* Don't worry about deferred popping of param above when we */
X		/* have optimized this code with gcc -O. Just set the usp to */
X		/* the old value recorded at the start of this function. Any */
X		/* wrong setting of the ssp due to incorrect implementations */
X		/* of Super will be corrected by the following "unlk a6".    */
X		asm ("movel %0, usp" :: "a" (user_stack));
X	}
X}
X
Xstatic void
Xstop(int sig)
X{
X	Fwrite(2,23,"\r\nProgram stopped !!!\r\n");
X	system("-i");		/* interactively call the shell at *_shell_p */
X	Fwrite(1,2,"\33e");	/* some shells switch the cursor off on exit */
X}
X
Xint
Xraise(int sig)
X{
X	sig_handler_t	*func;
X
X	if (sig >= 0 && sig < NSIG) {
X		/* we have to make sure that we call the signal-handler */
X		/* in user mode, to avoid problems on super stack later */
X		func = sig_array[sig].s_func;
X		if (func == SIG_DFL) func = sig_array[sig].d_func;
X		if (func != SIG_IGN) {
X			/* ANSI C requires either signal(sig,SIG_DFL) or an  */
X			/* "implementation defined blocking of the signal".  */
X			/* This blocking can be done by setting a flag which */
X			/* is cleared here after the call or in longjmp. But */
X			/* what about this scenario: signal(sig,abort) and   */
X			/* signal(SIGABRT,func) and func doing a longjmp ?   */
X			if(sig != SIGILL) sig_array[sig].s_func = SIG_DFL;
X			execute_in_usermode(func,sig);
X			_sig_done = 1;
X		}
X		/* else ignore it */
X		return(0);
X	}
X	/* invalid request for non existant signal */
X	errno = EINVAL;
X	return(-1);
X}
X
Xvoid
Xkill(int sig, int pid)
X{
X	extern const long	_base;
X
X	if(pid == _base) raise(sig);	/* we can't process kill requests */
X					/* for other programs cause we do */
X					/* not know their signal-handlers */
X}
END_OF_FILE
if test 5591 -ne `wc -c <'signal.c'`; then
    echo shar: \"'signal.c'\" unpacked with wrong size!
fi
# end of 'signal.c'
fi
if test -f 'stat.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stat.c'\"
else
echo shar: Extracting \"'stat.c'\" \(4534 characters\)
sed "s/^X//" >'stat.c' <<'END_OF_FILE'
X/*
X *		Cross Development System for Atari ST 
X *     Copyright (c) 1988, Memorial University of Newfoundland
X *
X * er: coupled this code with opendir/readdir/closedir, added fstat
X *
X * er: added inode stuff, file attributes (including executable), /dev/null
X *
X *  The only thing that doesn't get filled in at all is st_ino - it really
X * should be a unique number for each file - any ideas?
X *
X * $Header: stat.c,v 1.2 88/01/29 17:31:52 m68k Exp $
X *
X * $Log:	stat.c,v $
X *
X * added fstat, inode numbers, more info about file modes and conversion of
X * unix names to tos syntax (er)
X *
X * 1.2 jrd
X *
X * Revision 1.1  88/01/29  17:31:52  m68k
X * Initial revision
X * 
X */
X#include	<types.h>
X#include	<stat.h>
X#include	<ctype.h>
X#include	<errno.h>
X#include	<osbind.h>
X#include	<string.h>
X#include	<param.h>
X#include	<file.h>
X#include	<dir.h>
X
Xstatic ino_t	inode = 2;	/* FIX_ME: inodes are different in readdir */
XDIR	*_current_open_directory = (DIR *) 0;
X
Xint
Xfstat(int fd, struct stat *st)
X{
X	if((fd >= 0) && (fd < N_HANDLES) && __handle_to_name[fd]) {
X		return(stat(__handle_to_name[fd], st));
X	} else {
X		errno = EBADF;
X		return -1;
X	}
X}
X
Xint
Xstat(p, st)
X	char		*p;
X	struct stat	*st;
X{
X	char		path[strlen(p)+1];
X	int		rval;
X	struct _dta	dtabuf;
X	extern long	_time();
X	int		fd;
X	short		magic;
X	short		dots;
X	int		len;
X
X	strcpy(path,p);
X	if(!strcmp(p,"/dev/null")) {
X		st->st_mode = S_IFBLK | 0666;
X		st->st_attr = FA_LABEL;
X		st->st_ino = 1;
X		goto specials;
X	}
X	unix_to_tos(path);
X	len = strlen(path);
X	if (path[len-1] == '\\' || len == 2 && path[1] == ':') {
X		if (len > 3 || len > 1 && path[1] != ':') {
X			path[--len] = 0;
X		} else {	/* root directory */
Xroot_dir:
X			st->st_mode = S_IFDIR | 0755;
X			st->st_attr = FA_DIR;
X			st->st_ino = 2;	/* In root dir '.' and '..' have the */
X					/* same inode number; we should also */
X					/* differentiate between the drives. */
Xspecials:
X			st->st_mtime = st->st_ctime = st->st_atime = 0;
X			goto fill_in;
X		}
X	}
X	if (!path) {
X		errno = EFAULT;
X		return -1;
X	}
X	if (index(path, '*') || index(path, '?')) {
X		errno = EPATH;
X		return -1;
X	}
X	if ((rval = Fsetdta(&dtabuf)) < 0) {
X		errno = -rval;
X		return -1;
X	}
X	dots = 0;
X	if (*path == '.') {
X		dots++;
X		if (len > 1) {
X			if (len == 2 && path[1] == '.') dots++;
X			else dots = 0;
X		}
X	}
X	if (dots) {
X		char	actual_path[MAXPATHLEN];
X
X		Dgetpath(actual_path,0);
X		if (!*actual_path) goto root_dir;
X		if ((rval = Fsfirst("*.*", FA_DIR)) < 0) {
X			errno = -rval;
X			return -1;
X		}
X		if (dots == 2 && (rval = Fsnext()) < 0) {
X			errno = -rval;
X			return -1;
X		}
X		if (strcmp(path, dtabuf.dta_name)) {
X			errno = ENOENT;
X			return -1;
X		}
X	} else {
X		/* Optimization: if the file is already found in an open dir */
X		/*      use information collected there instead of Fsfirst() */
X		char	*cp;
X		char	buf[MAXPATHLEN+1];
X		DIR	*dp;
X		struct _dircontents	*dc;
X
X		strcpy(buf, path);
X		cp = rindex(buf, '\\');
X		if(cp) *cp++ = '\0';
X		else {
X			/* we are searching in '.' */
X			cp = path;
X			Dgetpath(buf, 0);
X		}
X		/* now we have the directory component in buf */
X		for(dp = _current_open_directory; dp; dp = dp->dd_next) {
X		  if(!strcmp(dp->dd_name, buf)) {	/* WOW!, we got it */
X			for(dc = dp->dd_contents;dc;dc = dc->_d_next) {
X				if(!strcmp(cp,dc->_d_entry)) {
X					dtabuf.dta_attribute = dc->_d_attr;
X					dtabuf.dta_date = dc->_d_date;
X					dtabuf.dta_time = dc->_d_time;
X					dtabuf.dta_size = dc->_d_size;
X					goto got_dta;;
X				}
X			}
X		  }
X		}
X		if ((rval = Fsfirst(path, FA_SYSTEM|FA_HIDDEN|FA_DIR)) < 0) {
X			errno = -rval;
X			return -1;
X		}
X	}
Xgot_dta:
X	st->st_ino = ++inode;	/* should be able to do better then this */
X	st->st_mode = 0644 | (dtabuf.dta_attribute & FA_DIR ?
X			      S_IFDIR | 0111 : S_IFREG);
X	if(dtabuf.dta_attribute & FA_RDONLY) st->st_mode &= ~0222;
X	if(dtabuf.dta_attribute & FA_HIDDEN) st->st_mode &= ~0444;
X	st->st_mtime = st->st_ctime = st->st_atime =
X		_time(0L, (dtabuf.dta_date << 16) | dtabuf.dta_time);
X	st->st_attr = dtabuf.dta_attribute;
X	if (st->st_mode & S_IFREG) {
X		if ((fd = Fopen(path,0)) < 0) {
X			errno = -rval;
X			return -1;
X		}
X		Fread(fd,2,&magic);
X		Fclose(fd);
X		if (magic == 0x601A) st->st_mode |= 0111;
X		st->st_size = dtabuf.dta_size;
X		st->st_blocks = (dtabuf.dta_size + 1023) / 1024;
X	} else {
Xfill_in:
X		st->st_size = 1024;
X		st->st_blocks = 1;
X	}
X	if (*path && path[1] == ':')
X		st->st_dev = islower(*path) ? *path - 'a' : *path - 'A';
X	else
X		st->st_dev = Dgetdrv();
X	st->st_rdev = 0;
X	st->st_nlink = 1;
X	st->st_uid = 0;
X	st->st_gid = 0;
X	st->st_blksize = 1024;
X	return 0;
X}
END_OF_FILE
if test 4534 -ne `wc -c <'stat.c'`; then
    echo shar: \"'stat.c'\" unpacked with wrong size!
fi
# end of 'stat.c'
fi
if test -f 'system.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'system.c'\"
else
echo shar: Extracting \"'system.c'\" \(3327 characters\)
sed "s/^X//" >'system.c' <<'END_OF_FILE'
X/* 9.8.1989 (er)	changed return values of m_getenv() and g_getline(), to
X *			minimize program size (this file is contained in every
X *			program because of signal(SIGTSTP))
X *			registers d1-a5 are now saved before a system call (not
X *			necessary in m_getenv since Master will do this)
X */
X#include <osbind.h>
X#include <time.h>
X
Xstatic	long	(*shell_p)();
Xextern	int	errno;
Xclock_t	_sys_runtime;
Xchar	_shell_is_running = 0;
X
Xstatic void
Xread_shell(void)
X{
X	long	*_shell_p = (long *) 0x4F6L;
X
X	shell_p = (long (*)())(*_shell_p);
X}
X
X/* This reads the _shell_p vector and tries to determine what kind */
X/* of shell we have running - !!! PLEASE ADD NEW MAGIC NUMBERS !!! */
Xstatic int
Xinit_system(void)
X{
X	int	ret;
X
X	Supexec(read_shell);
X	if(!(long)shell_p) return(0);
X	ret = 1;
X	if((*((long *)(((long) shell_p)-10)) == 0x00420135L))
X		ret = 2; /* Gulam */
X	if((*((long *)(((long) shell_p)-4)) == 0xCDCEC5D2L) || /* Master 5.0 */
X	   (*((long *)(((long) shell_p)-8)) == 0x4D415354L))   /* Master 5.4 */
X		ret = 3; /* Master */
X	return(ret);
X}
X
X/* this function executes the given command cmd by the shell at _shell_p   */
X/* if cmd == NULL only the presence of a shell (and it's type) is reported */
X/* when we want an interactive shell (cmd == "-i") then substitute this to */
X/* "" if the shell is Gulam - we could also Pexec("$SHELL") if there is no */
X/* shell at _shell_p */
Xint
Xsystem(const char *cmd)
X{
X	int	ret;
X	clock_t	start_time;
X
X	switch(ret = init_system()) {
X		case 0 : return(0);
X		case 2 : if (!strcmp(cmd,"-i")) cmd = "ue";
X		default: if (cmd) {
X				start_time = clock();
X				_shell_is_running = 1;
X				asm("moveml d1-a5, sp@-");
X				asm("movel %0, sp@-" :: "g" (cmd));
X				(void) (shell_p[0])();
X				asm("addql #4, sp");
X				asm("moveml sp@+, d1-a5");
X				asm volatile ("movel d0, %0" : "=g" (ret));
X				_shell_is_running = 0;
X				_sys_runtime += clock() - start_time;
X				if(ret < 0) errno = -ret;
X			 }
X			 return(ret);
X	}
X	/*NOTREACHED*/
X}
X
X/* special system call if the shell is Master 5.x */
X/* we ask for the expansion of the shell variable var, if Master is not     */
X/* running we return with the expansion as environment var - we could also  */
X/* get shell vars from other shells with output redirection like this one:  */
X/* system("echo $var > var.tmp") and then read this file if we got no error */
Xchar *
Xm_getenv(const char *var)
X{
X	extern long	getenv();
X	char	*result;
X
X	if(init_system() == 3) {
X		_shell_is_running = 1;
X		result = (char *) (shell_p[4])(1L,var);
X		_shell_is_running = 0;
X	} else result = "";			/* getenv(var); */
X	return(result);
X}
X
X/* special system call if the shell is Gulam */
X/* we ask for a line of input provided by the shell (with all usual   */
X/* editing), if Gulam is not running we simply read a line from stdin */
X/* we could also use system("ask \"\" tmpvar") and then get the value */
X/* of $tmpvar with m_getenv("tmpvar") if the shell is Master */
Xvoid
Xg_getline(char *line)
X{
X	void	(*func)(void);
X
X	if(!line) return;
X	if(init_system() != 2) *line = '\0';	/* read(0,line,256); */
X	else {
X		_shell_is_running = 1;
X		func = (void (*)(void))&(shell_p[-6]);
X		asm("moveml d1-a5, sp@-");
X		asm("movel %0, sp@-" :: "g" (line));
X		(*func)();	/* the argument is already on the stack */
X		asm("addql #4, sp");
X		asm("moveml sp@+, d1-a5");
X		_shell_is_running = 0;
X	}
X}
END_OF_FILE
if test 3327 -ne `wc -c <'system.c'`; then
    echo shar: \"'system.c'\" unpacked with wrong size!
fi
# end of 'system.c'
fi
if test -f 'timer.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'timer.c'\"
else
echo shar: Extracting \"'timer.c'\" \(3923 characters\)
sed "s/^X//" >'timer.c' <<'END_OF_FILE'
X/*
X *		Cross Development System for Atari ST 
X *     Copyright (c) 1988, Memorial University of Newfoundland
X *
X *   This routine uses the vertical blank interrupt queue to get it's timing
X * done.  This means that it probably depends on the resolution of the screen.
X *   If there is no room in the vbl queue then -1 is returned.  Note that
X * before the program terminates, this routine must be taken out of the
X * queue - to do this, _unalarm() is called from exit().  If alarm() is
X * not used in the program, the _unalarm() routine is a null one.
X *   This routine works by messing with the return pc (and sr) on the stack
X * when it gets called from the vbl interupt routine.  Also, the routine
X * checks to make sure a trap is not in progress by checking the __in_trap
X * variable (which *must* be set to one before a trap is done, and cleared
X * afer by the programmer - this is normally handled by the __*bios routines).
X * All this weirdness is done to ensure that the os is not disturbed while
X * it is doing stuff - therefor it is safe to do a longjmp() inside a signal
X * handling routine.
X *
X * $Header: alarm.c,v 1.1 88/02/03 22:37:51 m68k Exp $
X *
X * added SIGHUP, _init_timer and _exit_timer (called from crt0.s) (er)
X * renamed to timer.c and included clock()-function (er)
X *
X * $Log:	alarm.c,v $
X * Revision 1.1  88/02/03  22:37:51  m68k
X * Initial revision
X * 
X */
X#include	<osbind.h>
X#include	<sysvars.h>
X#include	<signal.h>
X#include	<time.h>
X
X#define	HZ		(70)		/* how often we get called a second */
X#define	CLK_VEC		0x100		/* the clock vector */
X
Xtypedef long	*long_ptr;
X
Xextern volatile int	_received_signal;	/* in alrm_nasty.s */
Xextern char		_shell_is_running;	/* in system.c */
Xextern const long	_base;
Xextern const long_ptr	_act_pd;
X
Xstatic int	alarm_timer();
Xextern int	_exit_timer();
Xextern int	_init_timer();
Xstatic int	remove_timer();
Xstatic int	install_timer();
X
Xclock_t	_start_time = 0L;
X
Xstatic int
X_clock(void)
X{
X	return *((clock_t *)_hz_200);
X}
X
Xclock_t
Xclock(void)
X{
X	return (Supexec(_clock) - _start_time);
X}
X
Xstatic int	carrier_was_on = 0;
Xstatic long	alarmtime = 0;
Xstatic clock_t	trigger = (clock_t) 0;
X
Xint
Xalarm(int n)
X{
X	long		oldticks;
X
X	trigger = (clock_t) 0;				/* block alarms now */
X	oldticks = alarmtime;
X	alarmtime = n;					/* that's the new one */
X	if(n) trigger = Supexec(_clock) + n * CLK_TCK;	/* and go */
X	return oldticks;
X}
X
Xint
X_init_timer(void)
X{
X	return Supexec(install_timer);
X}
X
Xint
X_exit_timer(void)
X{
X	return Supexec(remove_timer);
X}
X
X/*
X * This routine should be as small as possible as it is called lots of times
X * (There isn't really an argument - it's just there so we can get the
X * address of the stack)
X * If we just received another signal don't do anything - just wait until it's
X * being processed. (er)
X */
Xasm(".ascii	\"XBRAGNUC\"");	/* protocoll */
Xasm(".long	0");		/* old vector == no vector */
X
Xstatic int
Xalarm_timer(int arg)
X{
X	if(_shell_is_running || *_act_pd != _base || _received_signal)
X		return 0;	/* too dangerous to process signals */
X	if (trigger && *((clock_t *)_hz_200) > trigger) {
X		/* rrriiinnnngggggggg! */
X		alarmtime = trigger = 0;
X		_received_signal = SIGALRM;
X		_alrm_nasty(&arg);
X	} else {
X		int carrier_is_off = (*(char *) 0x00FFFA01L) & 2;
X
X		if (carrier_was_on && carrier_is_off) {
X			carrier_was_on = 0;
X			_received_signal = SIGHUP;
X			_alrm_nasty(&arg);
X		} else carrier_was_on = !carrier_is_off;
X	}
X	return 0;
X}
X
X/* These routines must be called in super mode */
Xstatic	int
Xremove_timer(void)
X{
X	char	**func;
X	int	i;
X
X	trigger = (clock_t) 0;	/* no more alarms now */
X	func = *_vblqueue;
X	i = *nvblq;
X	while (i--)
X		if (*func == (char *) alarm_timer) {
X			*func = (char *) 0;
X			return 0;
X		} else func++;
X	return 1;
X}
X
Xstatic	int
Xinstall_timer(void)
X{
X	char	**func;
X	int	i;
X
X	func = *_vblqueue;
X	i = *nvblq;
X	while (i--)
X		if (!*func) {
X			*func = (char *) alarm_timer;
X			return 0;
X		} else func++;
X	return 1;
X}
END_OF_FILE
if test 3923 -ne `wc -c <'timer.c'`; then
    echo shar: \"'timer.c'\" unpacked with wrong size!
fi
# end of 'timer.c'
fi
echo shar: End of archive 4 \(of 7\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 7 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 7 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0