guy%gorodish@Sun.COM (Guy Harris) (08/05/87)
> What library did you sysV users use for terminal capabilities? I used > curses (not my idea) and the output was all garbled. I would have to redraw > the screen every once in a while to figure out where I was. I tried bringing it up on a Sun here in the S5 environment with the S5R3.1 version of "curses" (and bunches of other stuff not in SunOS 3.x, but that's neither here nor there). Once I fixed a couple of bugs in that version of "curses" (including one @##!$%@! null-pointer bug), I didn't see any such problem when I tried it briefly. One of those bugs would have prevented it from running at all (a routine wasn't null-terminating a string, so it would think the (simulated) "bs" capability was false); the other might conceivably have broken things on machines that do allow dereferencing of null pointers, especially if said dereferencing yields a non-null string. Perhaps bugs in the "termcap" emulation in various versions of the S5 "curses" were causing the problems? Oh yes, I *did* notice some problems with the code itself: 1) The Makefile, for some inexplicable reason, links "hack" by using full-frontal "ld" rather than using "cc". This makes some rather dubious assumptions about the arguments that "cc" passes to "ld", and as such is a rather bad practice. (Somebody had problems linking "logo" a while ago, and they were doing it with "ld" rather than "cc", which was causing at least some of their problems; if the Makefile for "logo" was using "ld", and the "ld" command it was using was the bogus one the person was having problems with, the Makefile's should be strung up.) It also passes the "-X" flag. In V7-flavored versions of UNIX (including [24]BSD), this flag tells "ld" to remove some symbols from the symbol table. In S5R3, at least, it is not a valid flag to "ld". In either case, the Makefile has no business [fm]ucking with this flag in the general case; if it is needed by some benighted implementation, this should be mentioned in the comments in the Makefile or something and MADE OPTIONAL. 2) "install" doesn't depend on what it's installing. It is not required to do so, but it is considered uncool if it doesn't. 3) In "cmd.c", a "char" is compared against 0377. If "char"s are signed on your machine, and it properly implements the C conversion rules, this comparison will always indicate that the "char" is unequal to 0377, since the "char" with the value '\377' yields the value -1 when coerced to "int". Yes, kids, there *will* be compilers that implement those rules properly; the little warning our compiler issues in this case about the conversion being done incorrectly now for bug compatibility, but being done correctly in 4.0, should be taken very seriously indeed. 4) In "config.h", it claims that "Some include files are in a different place under SYSV". This is certainly true, except that one of the include files is not in a "different place" under System V, it doesn't exist at all! This include file is <sys/wait.h>. This include file defines a structure which probably seemed like a good idea to the Berkloids at the time, but which really wasn't; the return value of "wait" is defined by every other UNIX variant as an "int" with certain bits meaning certain things, not as a "struct" containing bitfields. In fact, the definition as a "struct" is *machine-dependent*, because the order of bitfields in a structure is machine-dependent; our <sys/wait.h> has #ifdefs to fix this. The only place in the entire program where this structure is used is in one "wait" call in "pager.c"; this "wait" call only uses it to cast 0 to an appropriate pointer type. Since in most versions of UNIX the appropriate pointer type is "(int *)0" - in fact, the *really* appropriate pointer type in *all* versions of UNIX is "(int *)0", except that the Berkloids decided to promote this new structure and put it in the documentation and the "lint" library - it is better not to waste time with <sys/wait.h> and just to use "(int *)0". This also eliminates the need for the NOWAITINCLUDE #define constant in "config.h". Here are a bunch of context diffs to fix the aforementioned problems: Makefile.unix: *** Makefile.unix.orig Wed Aug 5 01:19:11 1987 --- Makefile.unix Wed Aug 5 01:20:21 1987 *************** *** 19,25 **** SHELLDIR = /usr/games MANDIR = /usr/man/man6 CFLAGS = -O ! LFLAGS = -X HACKCSRC = alloc.c apply.c bones.c cmd.c decl.c do.c do_name.c do_wear.c\ dog.c dogmove.c dothrow.c eat.c end.c engrave.c fight.c fountain.c\ --- 19,25 ---- SHELLDIR = /usr/games MANDIR = /usr/man/man6 CFLAGS = -O ! LFLAGS = HACKCSRC = alloc.c apply.c bones.c cmd.c decl.c do.c do_name.c do_wear.c\ dog.c dogmove.c dothrow.c eat.c end.c engrave.c fight.c fountain.c\ *************** *** 57,63 **** $(GAME): specifics $(HOBJ) Makefile @echo "Loading ..." ! @ld $(LFLAGS) -o $(GAME) /lib/crt0.o $(HOBJ) $(TERMLIB) -lc all: $(GAME) lint @echo "Done." --- 57,63 ---- $(GAME): specifics $(HOBJ) Makefile @echo "Loading ..." ! @$(CC) $(LFLAGS) -g -o $(GAME) $(HOBJ) /argonsrc/5lib/libcurses/screen/obj/termcap.o $(TERMLIB) all: $(GAME) lint @echo "Done." *************** *** 131,137 **** chmod 666 $(GAMEDIR)/* chmod 777 $(GAMEDIR) $(GAMEDIR)/save ! install: $(VARAUX) -rm -f $(GAMEDIR)/$(GAME) -rm -f $(GAMEDIR)/bones* -rm -f $(GAMEDIR)/save/* --- 131,137 ---- chmod 666 $(GAMEDIR)/* chmod 777 $(GAMEDIR) $(GAMEDIR)/save ! install: $(VARAUX) $(GAME) -rm -f $(GAMEDIR)/$(GAME) -rm -f $(GAMEDIR)/bones* -rm -f $(GAMEDIR)/save/* cmd.c: *** cmd.c.orig Tue Aug 4 23:40:10 1987 --- cmd.c Tue Aug 4 23:55:18 1987 *************** *** 244,252 **** } /* Special case of *cmd == ' ' handled better below */ ! if(!*cmd || *cmd == 0377) { #else ! if(!*cmd || *cmd == 0377 || (flags.no_rest_on_space && *cmd == ' ')){ #endif bell(); flags.move = 0; --- 244,252 ---- } /* Special case of *cmd == ' ' handled better below */ ! if(!*cmd || *cmd == '\377') { #else ! if(!*cmd || *cmd == '\377' || (flags.no_rest_on_space && *cmd == ' ')){ #endif bell(); flags.move = 0; config.h: *** config.h.orig Tue Aug 4 23:40:33 1987 --- config.h Wed Aug 5 01:42:03 1987 *************** *** 11,17 **** * Some include files are in a different place under SYSV * BSD SYSV * <strings.h> <string.h> - * <sys/wait.h> <wait.h> * <sys/time.h> <time.h> * <sgtty.h> <termio.h> * Some routines are called differently --- 11,16 ---- *************** *** 32,41 **** /* #define APOLLO /* same for the Apollo */ /* #define STUPID /* avoid some complicated expressions if your C compiler chokes on them */ - /* #define NOWAITINCLUDE /* neither <wait.h> nor <sys/wait.h> exists */ - #ifdef MSDOS - #define NOWAITINCLUDE - #endif #define WIZARD "mike" /* the person allowed to use the -D option */ #define RECORD "record"/* the file containing the list of topscorers */ --- 31,36 ---- pager.c: *** pager.c.orig Tue Aug 4 23:40:28 1987 --- pager.c Wed Aug 5 00:11:29 1987 *************** *** 382,406 **** } #endif /* SHELL /**/ - #ifdef NOWAITINCLUDE - union wait { /* used only for the cast (union wait *) 0 */ - int w_status; - struct { - unsigned short w_Termsig:7; - unsigned short w_Coredump:1; - unsigned short w_Retcode:8; - } w_T; - }; - - #else - - #ifdef BSD - #include <sys/wait.h> - #else - #include <wait.h> - #endif - #endif /* NOWAITINCLUDE /**/ - child(wt) { register int f = fork(); if(f == 0){ /* child */ --- 382,387 ---- *************** *** 419,425 **** /* fork succeeded; wait for child to exit */ (void) signal(SIGINT,SIG_IGN); (void) signal(SIGQUIT,SIG_IGN); ! (void) wait((union wait *) 0); gettty(); setftty(); (void) signal(SIGINT,done1); --- 400,406 ---- /* fork succeeded; wait for child to exit */ (void) signal(SIGINT,SIG_IGN); (void) signal(SIGQUIT,SIG_IGN); ! (void) wait((int *) 0); gettty(); setftty(); (void) signal(SIGINT,done1); Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.com