[comp.sys.atari.st] MJC, fixes to lib.c

egisin@watmath.waterloo.edu (Eric Gisin) (02/23/88)

Here is some information I got in response to my recent article
on bugs in MJC version 1.2.

Version 2.0 is supposed to be released in a few months.
Most of the bugs I mentioned will be fixed, and it will have floating point.
Someone mentioned version 1.4, which suggests version 1.3 is available.
Since Mark Johnson can't post to Usenet, could someone with access
to Compuserve or Genie watch for new versions and post them to Usenet?

Mark Johnson's home address has changed since 1.2 was released,
here is the new address:
#   Mark A. Johnson 
#   5315 Holmes Place 
#   Boulder, CO 80303 

-----

I looked at the changes I've made to lib.c, they are numerous.
So I am posting two sets of context diffs,
the first including the more important changes,
the second including all changes.

Here is the first set.  The only change are fixes to stdio.
The original only implemented binary mode for files opened with
stdio, and text more is much more useful.
So I changed things to use text mode, but the old behaviour
can be restored by undefining TEXT_MODE.

I don't know if Mark has implemented these modes
with the "b" and "t" options in the mode argument of fopen --
they are very important in MS-DOS enviroments (ANSI C adopts it).

*** lib.c_1.2	Thu Aug  6 10:17:55 1987
--- lib.c	Mon Feb 22 18:49:08 1988
***************
*** 1,5 ****
--- 1,16 ----
  /* C library - startup, stdio, strings, TOS */
  
+ /*
+  * changes to MJC 1.2 lib.c by Eric Gisin.
+  * fixes to stdio when stdin or stdout redirected by shell.
+  * stdio now does text mode mapping ("\n" <--> "\r\n") by default.
+  * the original used binary mode except on stdin/stdout.
+  * the "proper" way to fix this is with "t" and "b" in the fopen mode.
+  * recognizes ^D on stdin.
+  */
+ 
+ #define	TEXT_MODE	/* text mode mapping, undef for binary mode */
+ 
  /* max number of args in argv[] */
  
  #define MAXARG	50
***************
*** 92,102 ****
  	/* init stdio */
  	for (i = 0; i < MAXIO; i++) {
  		_iobuf[i].mode = FREE;
! 		_iobuf[i].fd = _iobuf[i].idx = _iobuf[i].len = 0;
  	}
! 	stdin = &_iobuf[0];
! 	stdout = &_iobuf[1];
! 	stderr = &_iobuf[2];
  	stdin->mode = stdout->mode = stderr->mode = RDWR;
  	if (in) {
  		stdin->fd = i = trap(1, OPEN, in, 0);
--- 103,113 ----
  	/* init stdio */
  	for (i = 0; i < MAXIO; i++) {
  		_iobuf[i].mode = FREE;
! 		_iobuf[i].idx = _iobuf[i].len = 0;
  	}
! 	stdin = &_iobuf[0];	stdin->fd = 0;
! 	stdout = &_iobuf[1];	stdout->fd = 1;
! 	stderr = &_iobuf[2];	stderr->fd = -1;
  	stdin->mode = stdout->mode = stderr->mode = RDWR;
  	if (in) {
  		stdin->fd = i = trap(1, OPEN, in, 0);
***************
*** 322,329 ****
  	}
  	else	return EOF;
  	c = s->buf[i] & 255;
! 	if (s->fd == 0 && c == '\r')
! 		putc(c = '\n', s);
  	return c;
  }
  
--- 333,351 ----
  	}
  	else	return EOF;
  	c = s->buf[i] & 255;
! 	if (s->fd == 0) {		/* tty input */
! 		if (c == '\r') {
! 			l = trap(1, WRITE, s->fd, (long) 1, "\n");
! 			c = '\n';
! 		} else
! 		if (c == 0x04)
! 			c = EOF;
! 		return c;
! 	}
! #ifdef TEXT_MODE
! 	if (c == '\r')			/* we could do better */
! 		c = getc(s);
! #endif
  	return c;
  }
  
***************
*** 337,345 ****
  }
  
  putc(c, s) int c; FILE *s; {
! 	int i, r;
  	if (s == NULL) return EOF;
! 	r = 0;
  	if (s->mode == RDWR) {
  		s->buf[0] = c;
  		r = trap(1, WRITE, s->fd, (long) 1, s->buf);
--- 359,373 ----
  }
  
  putc(c, s) int c; FILE *s; {
! 	int i, r = 0;
! 
  	if (s == NULL) return EOF;
! #ifdef TEXT_MODE
! 	if (c == '\n')
! #else
! 	if (c == '\n' && (s == stdout || s == stderr))
! #endif
! 		r = putc('\r', s);
  	if (s->mode == RDWR) {
  		s->buf[0] = c;
  		r = trap(1, WRITE, s->fd, (long) 1, s->buf);
***************
*** 350,356 ****
  		s->idx = s->idx + 1;
  	}
  	else 	return EOF;
- 	if (s->fd == 0 && c == '\n') r = putc('\r', s);
  	return r <= 0 ? EOF : r;
  }
  
--- 378,383 ----

-----

Here is the second set of complete diffs.
Changing MAXBUF (the buffer size for stdio) from 512 to 1024 improves IO speed.

*** lib.c_1.2	Thu Aug  6 10:17:55 1987
--- lib.c	Sun Feb 21 15:06:43 1988
***************
*** 1,12 ****
  /* C library - startup, stdio, strings, TOS */
  
! /* max number of args in argv[] */
  
! #define MAXARG	50
  
  /* header file for stdio implementation */
  
! #define MAXBUF	512
  #define MAXIO	6
  
  struct file {
--- 1,20 ----
  /* C library - startup, stdio, strings, TOS */
  
! /*
!  * changes by Eric Gisin <egisin@Waterloo.EDU>
!  * bug fixes to _cttp when fd 0 or 1 redirected by shell.
!  * added environ, getenv(), removed env from exec().
!  * added atoi(). still needs binary/text mode for stdio.
!  * made text mode default for stdio, fixed things up.
!  */
  
! #define	TEXT_MODE		/* stdio always maps \r\n <-> \n */
  
+ #define MAXARG	50		/* max number of args in argv[] */
+ 
  /* header file for stdio implementation */
  
! #define MAXBUF	1024
  #define MAXIO	6
  
  struct file {
***************
*** 61,68 ****
  	extern char *argv[MAXARG];
  	extern FILE *stdin, *stdout, *stderr;
  	extern FILE _iobuf[1];
  
! 	char *b, *w, *in, *out, *arge;
  	int i;
  	long x, *lp;
  
--- 69,77 ----
  	extern char *argv[MAXARG];
  	extern FILE *stdin, *stdout, *stderr;
  	extern FILE _iobuf[1];
+ 	extern char *environ;
  
! 	char *b, *w, *in, *out;
  	int i;
  	long x, *lp;
  
***************
*** 75,81 ****
  	/* parse the command line */
  	argc = 1;
  	argv[0] = "yc";
! 	arge = (char *) lp[11];
  	b = tpa + 0x81;
  	in = out = NULL;
  	while (*b) {
--- 84,90 ----
  	/* parse the command line */
  	argc = 1;
  	argv[0] = "yc";
! 	environ = (char *) lp[11];
  	b = tpa + 0x81;
  	in = out = NULL;
  	while (*b) {
***************
*** 92,102 ****
  	/* init stdio */
  	for (i = 0; i < MAXIO; i++) {
  		_iobuf[i].mode = FREE;
! 		_iobuf[i].fd = _iobuf[i].idx = _iobuf[i].len = 0;
  	}
! 	stdin = &_iobuf[0];
! 	stdout = &_iobuf[1];
! 	stderr = &_iobuf[2];
  	stdin->mode = stdout->mode = stderr->mode = RDWR;
  	if (in) {
  		stdin->fd = i = trap(1, OPEN, in, 0);
--- 101,111 ----
  	/* init stdio */
  	for (i = 0; i < MAXIO; i++) {
  		_iobuf[i].mode = FREE;
! 		_iobuf[i].idx = _iobuf[i].len = 0;
  	}
! 	stdin = &_iobuf[0];	stdin->fd = 0;
! 	stdout = &_iobuf[1];	stdout->fd = 1;
! 	stderr = &_iobuf[2];	stderr->fd = -1;
  	stdin->mode = stdout->mode = stderr->mode = RDWR;
  	if (in) {
  		stdin->fd = i = trap(1, OPEN, in, 0);
***************
*** 116,122 ****
  	}
  	
  	/* run the program */
! 	i = main(argc, argv, arge);
  
  	/* close up shop */
  	if (in) fclose(stdin);
--- 125,131 ----
  	}
  	
  	/* run the program */
! 	i = main(argc, argv, environ);
  
  	/* close up shop */
  	if (in) fclose(stdin);
***************
*** 143,148 ****
--- 152,158 ----
  
  int 	argc;
  char 	*argv[MAXARG];
+ char	*environ;
  
  FILE	_iobuf[MAXIO], *stdin, 	*stdout, *stderr;
  
***************
*** 235,240 ****
--- 245,258 ----
  	return b;
  }
  
+ /* BUG: not general */
+ FILE *
+ freopen(name, mode, fp) char *name, *mode; FILE *fp; {
+ 	FILE *fopen();
+ 	fclose(fp);
+ 	return fopen(name, mode);
+ }
+ 
  /* open a stream */
  
  FILE *
***************
*** 322,329 ****
  	}
  	else	return EOF;
  	c = s->buf[i] & 255;
! 	if (s->fd == 0 && c == '\r')
! 		putc(c = '\n', s);
  	return c;
  }
  
--- 340,358 ----
  	}
  	else	return EOF;
  	c = s->buf[i] & 255;
! 	if (s->fd == 0) {		/* tty input */
! 		if (c == '\r') {
! 			l = trap(1, WRITE, s->fd, (long) 1, "\n");
! 			c = '\n';
! 		} else
! 		if (c == 0x04)
! 			c = EOF;
! 		return c;
! 	}
! #ifdef TEXT_MODE
! 	if (c == '\r')			/* we could do better */
! 		c = getc(s);
! #endif
  	return c;
  }
  
***************
*** 337,345 ****
  }
  
  putc(c, s) int c; FILE *s; {
! 	int i, r;
  	if (s == NULL) return EOF;
! 	r = 0;
  	if (s->mode == RDWR) {
  		s->buf[0] = c;
  		r = trap(1, WRITE, s->fd, (long) 1, s->buf);
--- 366,380 ----
  }
  
  putc(c, s) int c; FILE *s; {
! 	int i, r = 0;
! 
  	if (s == NULL) return EOF;
! #ifdef TEXT_MODE
! 	if (c == '\n')
! #else
! 	if (c == '\n' && (s == stdout || s == stderr))
! #endif
! 		r = putc('\r', s);
  	if (s->mode == RDWR) {
  		s->buf[0] = c;
  		r = trap(1, WRITE, s->fd, (long) 1, s->buf);
***************
*** 350,356 ****
  		s->idx = s->idx + 1;
  	}
  	else 	return EOF;
- 	if (s->fd == 0 && c == '\n') r = putc('\r', s);
  	return r <= 0 ? EOF : r;
  }
  
--- 385,390 ----
***************
*** 362,373 ****
  
  dup(fd) { return trap(1, 0x45, fd); }
  
  /*  execute a program: mode=0 -> load and go; mode=3 -> load and return  */
  
! exec(file, args, env, mode) char *file, *args, *env; int mode; {
! 	return trap(1, 0x4B, mode, file, args, env);
  }
  
  /* get current directory: drive=0 -> current drive, drive=1 -> A:, etc */
  
  getdir(buf, drive) char *buf; {
--- 396,427 ----
  
  dup(fd) { return trap(1, 0x45, fd); }
  
+ dup2(fold, fnew) { return trap(1, 0x46, fold, fnew); }
+ 
  /*  execute a program: mode=0 -> load and go; mode=3 -> load and return  */
  
! exec(file, args, mode) char *file, *args; int mode; {
! 	return trap(1, 0x4B, mode, file, args, environ);
  }
  
+ /* get enviroment variable */
+ 
+ char * getenv(name)
+ 	char * name;
+ {
+ 	register char *p, *q;
+ 
+ 	for (p = environ; *p != '\0'; ) {
+ 		for (q = name; *p++ == *q++; )
+ 			;
+ 		if (p[-1] == '=' && q[-1] == '\0')
+ 			return p;
+ 		while (*p++ != '\0')
+ 			;
+ 	}
+ 	return 0;
+ }
+ 
  /* get current directory: drive=0 -> current drive, drive=1 -> A:, etc */
  
  getdir(buf, drive) char *buf; {
***************
*** 1101,1106 ****
--- 1155,1166 ----
  	while (n = *s++) {
  		m[n >> 5] |= 1L << (n & 31);
  	}
+ }
+ 
+ int
+ atoi(s) char *s; {
+ 	long	strtol();
+ 	return strtol(s, (char**)NULL, 10);
  }
  
  long