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