Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!cs.utexas.edu!uunet!zephyr.ens.tek.com!tekgen!tekred!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v08i042: NetHack3 - display oriented dungeons & dragons (Ver. 3.0), Patch4f
Message-ID: <4632@tekred.CNA.TEK.COM>
Date: 29 Sep 89 21:11:47 GMT
Sender: nobody@tekred.CNA.TEK.COM
Lines: 2018
Approved: billr@saab.CNA.TEK.COM
Submitted-by: Izchak Miller
Posting-number: Volume 8, Issue 42
Archive-name: NetHack3/Patch4f
Patch-To: NetHack3: Volume 7, Issue 56-93
#! /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 'patches04f' <<'END_OF_FILE'
X*** /dev/null Wed Sep 27 12:46:46 1989
X--- vms/Install.vms Tue Sep 26 22:10:07 1989
X***************
X*** 0 ****
X--- 1,44 ----
X+ Instructions for installing NetHack 3.0 on a VMS system
X+ =======================================================
X+
X+ First, consider reading Install.unix. While many of the details will differ,
X+ it should give you an idea of how the NetHack files are set up, and what a
X+ full installation process is like.
X+
X+ You should not have to move any files from their default positions, but you
X+ will want to edit config.h and vmsconf.h. Then run vms_build.com and
X+ spec_lev.com. These will create all the necessary files, but not install
X+ them anywhere in particular. That is left as an exercise for the installer.
X+
X+
X+ Some additional notes:
X+
X+ VMS Nethack uses the termcap routines supplied with GNU Emacs. These have
X+ been supplied for those who do not already have GNU Emacs, but they are not
X+ properly a part of the NetHack distribution. Since these files (vmstermcap.c
X+ and vmstparam.c) bear the usual GNU license, any executable made with these
X+ files is also under the GNU license, which among other things means you must
X+ be prepared to distribute all the source that went into the executable if you
X+ distribute the executable. See the GNU license in the files for further
X+ details.
X+
X+ No termcap file is supplied. One should be snarfable from any Unix system.
X+ If you do not have GNU Emacs installed, you will need to define the logical
X+ TERMCAP to point to the termcap file.
X+
X+ There is code which attempts to make Nethack secure in case it is installed
X+ with privileges (to allow the playground to be protected against world write).
X+ THIS HAS NOT BEEN TESTED. Install Nethack with privileges at your own risk.
X+ If you do so, however, we would love to hear of your experiences, good or bad.
X+
X+ VMS Nethack uses SMG$READ_KEYSTROKE to read characters from the keyboard.
X+ This means that arrow keys work! It also means that using escape to abort
X+ commands doesn't! If you want to abort a command use ^Z. Just about any
X+ non-arrow function key should also work. Note that under Unix ^Z is the
X+ suspend command. This is of little use on VMS so our use is harmless.
X+
X+ Nethack does not run in PASTHRU or PASSALL mode. This is to allow ^C
X+ interrupts. An unpleasant (albeit minor) side-effect of this is that some
X+ wizard commands don't work (^G, ^O, ^X). Another side-effect is that ^Y and
X+ ^C echo the stupid, inverse-video "CANCEL" and "INTERRUPT" banners. Is there
X+ no other way to turn these off???
X*** /dev/null Wed Sep 27 12:46:56 1989
X--- vms/spec_lev.com Tue Sep 26 20:00:12 1989
X***************
X*** 0 ****
X--- 1,25 ----
X+ $! yacc := bison/def ! .CLD version of bison
X+ $! yacc := $bison$dir:bison -y -d ! non-CLD version of bison
X+ $ yacc := $shell$exe:yacc -d ! yacc from DEC/Shell
X+ $! lex := $flex$dir:flex ! flex
X+ $ lex := $shell$exe:lex ! lex from DEC/Shell
X+ $ cc = "CC/NOLIST/OPT=NOINLINE/DEB/INCL=[-.INCLUDE]/DEFI=(""WIZARD=""""GENTZEL"""""")"
X+ $ link := link/nomap
X+ $
X+ $ yacc lev_comp.y
X+ $ rename y_tab.c lev_comp.c
X+ $ rename y_tab.h [-.include]lev_comp.h
X+ $ lex lev_comp.l
X+ $ rename lex_yy.c lev_lex.c
X+ $ cc lev_comp.c
X+ $ cc lev_lex.c
X+ $ cc lev_main.c
X+ $ link lev_comp.obj,lev_lex.obj,lev_main.obj,alloc.obj,monst.obj,objects.obj,panic.obj,vmsmisc.obj,sys$input:/opt
X+ sys$share:vaxcrtl/share
X+ $
X+ $ old_dir = f$environment("DEFAULT")
X+ $ set default [-.auxil]
X+ $ mcr sys$disk:[-.src]lev_comp castle.des
X+ $ mcr sys$disk:[-.src]lev_comp endgame.des
X+ $ mcr sys$disk:[-.src]lev_comp tower.des
X+ $ set default 'old_dir
X*** /dev/null Wed Sep 27 12:47:07 1989
X--- vms/vmsbuild.com Wed Sep 27 09:36:05 1989
X***************
X*** 0 ****
X--- 1,201 ----
X+ $ makedefs := $sys$disk:[]makedefs
X+ $ cc = "CC/NOLIST/OPT=NOINLINE/DEB/INCL=[-.INCLUDE]/DEFI=(""WIZARD=""""GENTZEL"""""")"
X+ $ link := link/nomap
X+ $ if p1 .eqs. "LINK" then goto link
X+ $ cc alloc.c
X+ $ cc makedefs.c
X+ $ cc monst.c
X+ $ cc objects.c
X+ $ cc panic.c
X+ $ cc [-.vms]vmsmisc
X+ $ link makedefs.obj,monst.obj,objects.obj,panic.obj,vmsmisc.obj,sys$input:/opt
X+ sys$share:vaxcrtl/share
X+ $ makedefs -p
X+ $ makedefs -o
X+ $ makedefs -t
X+ $ cc allmain.c
X+ $ cc apply.c
X+ $ cc artifact.c
X+ $ cc attrib.c
X+ $ cc bones.c
X+ $ cc cmd.c
X+ $ cc dbridge.c
X+ $ cc decl.c
X+ $ cc demon.c
X+ $ cc do.c
X+ $ cc do_name.c
X+ $ cc do_wear.c
X+ $ cc dog.c
X+ $ cc dogmove.c
X+ $ cc dokick.c
X+ $ cc dothrow.c
X+ $ cc eat.c
X+ $ cc end.c
X+ $ cc engrave.c
X+ $ cc exper.c
X+ $ cc extralev.c
X+ $ cc fountain.c
X+ $ cc getline.c
X+ $ cc hack.c
X+ $ cc invent.c
X+ $ cc lock.c
X+ $ cc mail.c
X+ $ cc [-.vms]vmsmain.c/obj=main.obj
X+ $ cc makemon.c
X+ $ cc mcastu.c
X+ $ cc mhitm.c
X+ $ cc mhitu.c
X+ $ cc mklev.c
X+ $ cc mkmaze.c
X+ $ cc mkobj.c
X+ $ cc mkroom.c
X+ $ cc mon.c
X+ $ cc mondata.c
X+ $ cc monmove.c
X+ $ cc mthrowu.c
X+ $ cc music.c
X+ $ cc o_init.c
X+ $ cc objnam.c
X+ $ cc options.c
X+ $ cc pager.c
X+ $ cc pickup.c
X+ $ cc polyself.c
X+ $ cc potion.c
X+ $ cc pray.c
X+ $ cc pri.c
X+ $ cc priest.c
X+ $ cc prisym.c
X+ $ cc read.c
X+ $ cc restore.c
X+ $ cc rip.c
X+ $ cc rnd.c
X+ $ cc rumors.c
X+ $ cc save.c
X+ $ cc search.c
X+ $ cc shk.c
X+ $ cc shknam.c
X+ $ cc sit.c
X+ $ cc sounds.c
X+ $ cc sp_lev.c
X+ $ cc spell.c
X+ $ cc steal.c
X+ $ cc termcap.c
X+ $ cc timeout.c
X+ $ cc topl.c
X+ $ cc topten.c
X+ $ cc track.c
X+ $ cc trap.c
X+ $ cc [-.vms]vmstty.c/obj=tty.obj
X+ $ cc u_init.c
X+ $ cc uhitm.c
X+ $ cc [-.vms]vmsunix.c/obj=unix.obj
X+ $ cc vault.c
X+ $ makedefs -v
X+ $ cc version.c
X+ $ cc weapon.c
X+ $ cc were.c
X+ $ cc wield.c
X+ $ cc wizard.c
X+ $ cc worm.c
X+ $ cc worn.c
X+ $ cc write.c
X+ $ cc zap.c
X+ $ cc [-.others]random.c
X+ $ cc/def="bcopy(s1,s2,sz)=memcpy(s2,s1,sz)" [-.vms]vmstermcap.c
X+ $ cc [-.vms]vmstparam.c
X+ $link:
X+ $ link/exe=nethack sys$input:/opt
X+ allmain.obj,-
X+ alloc.obj,-
X+ apply.obj,-
X+ artifact.obj,-
X+ attrib.obj,-
X+ bones.obj,-
X+ cmd.obj,-
X+ dbridge.obj,-
X+ decl.obj,-
X+ demon.obj,-
X+ do.obj,-
X+ do_name.obj,-
X+ do_wear.obj,-
X+ dog.obj,-
X+ dogmove.obj,-
X+ dokick.obj,-
X+ dothrow.obj,-
X+ eat.obj,-
X+ end.obj,-
X+ engrave.obj,-
X+ exper.obj,-
X+ extralev.obj,-
X+ fountain.obj,-
X+ getline.obj,-
X+ hack.obj,-
X+ invent.obj,-
X+ lock.obj,-
X+ mail.obj,-
X+ main.obj,-
X+ makemon.obj,-
X+ mcastu.obj,-
X+ mhitm.obj,-
X+ mhitu.obj,-
X+ mklev.obj,-
X+ mkmaze.obj,-
X+ mkobj.obj,-
X+ mkroom.obj,-
X+ mon.obj,-
X+ mondata.obj,-
X+ monmove.obj,-
X+ monst.obj,-
X+ mthrowu.obj,-
X+ music.obj,-
X+ o_init.obj,-
X+ objects.obj,-
X+ objnam.obj,-
X+ options.obj,-
X+ pager.obj,-
X+ pickup.obj,-
X+ polyself.obj,-
X+ potion.obj,-
X+ pray.obj,-
X+ pri.obj,-
X+ priest.obj,-
X+ prisym.obj,-
X+ read.obj,-
X+ restore.obj,-
X+ rip.obj,-
X+ rnd.obj,-
X+ rumors.obj,-
X+ save.obj,-
X+ search.obj,-
X+ shk.obj,-
X+ shknam.obj,-
X+ sit.obj,-
X+ sounds.obj,-
X+ sp_lev.obj,-
X+ spell.obj,-
X+ steal.obj,-
X+ termcap.obj,-
X+ timeout.obj,-
X+ topl.obj,-
X+ topten.obj,-
X+ track.obj,-
X+ trap.obj,-
X+ tty.obj,-
X+ u_init.obj,-
X+ uhitm.obj,-
X+ unix.obj,-
X+ vault.obj,-
X+ version.obj,-
X+ weapon.obj,-
X+ were.obj,-
X+ wield.obj,-
X+ wizard.obj,-
X+ worm.obj,-
X+ worn.obj,-
X+ write.obj,-
X+ zap.obj,-
X+ random.obj,-
X+ vmsmisc.obj,-
X+ vmstermcap.obj,-
X+ vmstparam.obj
X+ sys$library:vaxcrtl/library
X*** /dev/null Wed Sep 27 12:47:15 1989
X--- vms/vmsmain.c Tue Sep 26 18:45:52 1989
X***************
X*** 0 ****
X--- 1,378 ----
X+ /* SCCS Id: @(#)vmsmain.c 3.0 89/01/13
X+ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X+ /* NetHack may be freely redistributed. See license for details. */
X+ /* main.c - VMS NetHack */
X+
X+ #include
X+
X+ #include "hack.h"
X+
X+ char SAVEF[PL_NSIZ + 20]; /* [.save]player;1 */
X+
X+ char *hname = 0; /* name of the game (argv[0] of call) */
X+ char obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */
X+ int hackpid = 0; /* current pid */
X+ int locknum = 0; /* max num of players */
X+
X+ static void whoami();
X+ static void byebye();
X+
X+ int
X+ main(argc,argv)
X+ int argc;
X+ char *argv[];
X+ {
X+ extern int x_maze_max, y_maze_max;
X+ register int fd;
X+ #ifdef CHDIR
X+ register char *dir;
X+ #endif
X+
X+ atexit(byebye);
X+ hname = argv[0];
X+ hackpid = getpid();
X+ (void) umask(0);
X+
X+ /*
X+ * Remember tty modes, to be restored on exit.
X+ *
X+ * gettty() must be called before startup()
X+ * due to ordering of LI/CO settings
X+ * startup() must be called before initoptions()
X+ * due to ordering of graphics settings
X+ */
X+ gettty();
X+ setbuf(stdout,obuf);
X+ startup();
X+ initoptions();
X+ whoami();
X+
X+ #ifdef CHDIR /* otherwise no chdir() */
X+ /*
X+ * See if we must change directory to the playground.
X+ * (Perhaps hack is installed with privs and playground is
X+ * inaccessible for the player.)
X+ * The logical name HACKDIR is overridden by a
X+ * -d command line option (must be the first option given)
X+ */
X+ dir = getenv("HACKDIR");
X+ #endif
X+ if(argc > 1) {
X+ #ifdef CHDIR
X+ if (!strncmp(argv[1], "-d", 2)) {
X+ argc--;
X+ argv++;
X+ dir = argv[0]+2;
X+ if(*dir == '=' || *dir == ':') dir++;
X+ if(!*dir && argc > 1) {
X+ argc--;
X+ argv++;
X+ dir = argv[0];
X+ }
X+ if(!*dir)
X+ error("Flag -d must be followed by a directory name.");
X+ } else
X+ #endif /* CHDIR /**/
X+
X+ /*
X+ * Now we know the directory containing 'record' and
X+ * may do a prscore().
X+ */
X+ if (!strncmp(argv[1], "-s", 2)) {
X+ #ifdef CHDIR
X+ chdirx(dir,0);
X+ #endif
X+ prscore(argc, argv);
X+ getret();
X+ settty(NULL);
X+ exit(0);
X+ }
X+ }
X+
X+ /*
X+ * It seems you really want to play.
X+ */
X+ setrandom();
X+ cls();
X+ u.uhp = 1; /* prevent RIP on early quits */
X+ u.ux = FAR; /* prevent nscr() */
X+ (void) signal(SIGHUP, (SIG_RET_TYPE) hangup);
X+
X+ /*
X+ * Find the creation date of this game,
X+ * so as to avoid restoring outdated savefiles.
X+ */
X+ gethdate(hname);
X+
X+ /*
X+ * We cannot do chdir earlier, otherwise gethdate will fail.
X+ */
X+ #ifdef CHDIR
X+ chdirx(dir,1);
X+ #endif
X+
X+ /*
X+ * Process options.
X+ */
X+ while(argc > 1 && argv[1][0] == '-'){
X+ argv++;
X+ argc--;
X+ switch(argv[0][1]){
X+ #if defined(WIZARD) || defined(EXPLORE_MODE)
X+ # ifndef EXPLORE_MODE
X+ case 'X':
X+ case 'x':
X+ # endif
X+ case 'D':
X+ # ifdef WIZARD
X+ if(!strcmp(getenv("USER"), WIZARD))
X+ wizard = TRUE;
X+ break;
X+ }
X+ /* otherwise fall thru to discover */
X+ # endif
X+ # ifdef EXPLORE_MODE
X+ case 'X':
X+ case 'x':
X+ discover = TRUE;
X+ # endif
X+ break;
X+ #endif
X+ #ifdef NEWS
X+ case 'n':
X+ flags.nonews = TRUE;
X+ break;
X+ #endif
X+ case 'u':
X+ if(argv[0][2])
X+ (void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
X+ else if(argc > 1) {
X+ argc--;
X+ argv++;
X+ (void) strncpy(plname, argv[0], sizeof(plname)-1);
X+ } else
X+ Printf("Player name expected after -u\n");
X+ break;
X+ default:
X+ /* allow -T for Tourist, etc. */
X+ (void) strncpy(pl_character, argv[0]+1,
X+ sizeof(pl_character)-1);
X+
X+ /* Printf("Unknown option: %s\n", *argv); */
X+ }
X+ }
X+
X+ if(argc > 1)
X+ locknum = atoi(argv[1]);
X+ #ifdef MAX_NR_OF_PLAYERS
X+ if(!locknum || locknum > MAX_NR_OF_PLAYERS)
X+ locknum = MAX_NR_OF_PLAYERS;
X+ #endif
X+ #ifdef WIZARD
X+ if (wizard)
X+ Strcpy(plname, "wizard");
X+ else
X+ #endif
X+ if(!*plname || !strncmp(plname, "games", 4))
X+ askname();
X+ plnamesuffix(); /* strip suffix from name; calls askname() */
X+ /* again if suffix was whole name */
X+ /* accepts any suffix */
X+ #ifdef WIZARD
X+ if(!wizard) {
X+ #endif
X+ /*
X+ * check for multiple games under the same name
X+ * (if !locknum) or check max nr of players (otherwise)
X+ */
X+ (void) signal(SIGQUIT,SIG_IGN);
X+ (void) signal(SIGINT,SIG_IGN);
X+ if(!locknum)
X+ Sprintf(lock, "%d%s", getuid(), plname);
X+ getlock(); /* sets lock if locknum != 0 */
X+ #ifdef WIZARD
X+ } else
X+ Sprintf(lock, "%d%s", getuid(), plname);
X+ #endif /* WIZARD /**/
X+ setftty();
X+
X+ /*
X+ * Initialisation of the boundaries of the mazes
X+ * Both boundaries have to be even.
X+ */
X+
X+ x_maze_max = COLNO-1;
X+ if (x_maze_max % 2)
X+ x_maze_max--;
X+ y_maze_max = ROWNO-1;
X+ if (y_maze_max % 2)
X+ y_maze_max--;
X+
X+ /* initialize static monster strength array */
X+ init_monstr();
X+
X+ Sprintf(SAVEF, "[.save]%d%s", getuid(), plname);
X+ regularize(SAVEF+7); /* avoid bogus chars in name */
X+ if((fd = open(SAVEF,0)) >= 0 &&
X+ (uptodate(fd) || unlink(SAVEF) >= 0)) {
X+ #ifdef WIZARD
X+ /* Since wizard is actually flags.debug, restoring might
X+ * overwrite it.
X+ */
X+ boolean remember_wiz_mode = wizard;
X+ #endif
X+ (void) signal(SIGINT, (SIG_RET_TYPE) done1);
X+ pline("Restoring old save file...");
X+ (void) fflush(stdout);
X+ if(!dorecover(fd))
X+ goto not_recovered;
X+ #ifdef WIZARD
X+ if(!wizard && remember_wiz_mode) wizard = TRUE;
X+ #endif
X+ pline("Hello %s, welcome to NetHack!", plname);
X+ /* get shopkeeper set properly if restore is in shop */
X+ (void) inshop();
X+ #ifdef EXPLORE_MODE
X+ if (discover)
X+ You("are in non-scoring discovery mode.");
X+ #endif
X+ #if defined(EXPLORE_MODE) || defined(WIZARD)
X+ if (discover || wizard) {
X+ pline("Do you want to keep the save file? ");
X+ if(yn() == 'n')
X+ (void) unlink(SAVEF);
X+ }
X+ #endif
X+ flags.move = 0;
X+ } else {
X+ not_recovered:
X+ newgame();
X+ /* give welcome message before pickup messages */
X+ pline("Hello %s, welcome to NetHack!", plname);
X+ #ifdef EXPLORE_MODE
X+ if (discover)
X+ You("are in non-scoring discovery mode.");
X+ #endif
X+ flags.move = 0;
X+ set_wear();
X+ pickup(1);
X+ read_engr_at(u.ux,u.uy);
X+ }
X+
X+ flags.moonphase = phase_of_the_moon();
X+ if(flags.moonphase == FULL_MOON) {
X+ You("are lucky! Full moon tonight.");
X+ if(!u.uluck) change_luck(1);
X+ } else if(flags.moonphase == NEW_MOON) {
X+ pline("Be careful! New moon tonight.");
X+ }
X+
X+ initrack();
X+
X+ moveloop();
X+ return(0);
X+ }
X+
X+ void
X+ glo(foo)
X+ register int foo;
X+ {
X+ /* construct the string xlock.n */
X+ register char *tf;
X+
X+ tf = lock;
X+ while(*tf && *tf != '.') tf++;
X+ Sprintf(tf, ".%d;1", foo);
X+ }
X+
X+ /*
X+ * plname is filled either by an option (-u Player or -uPlayer) or
X+ * explicitly (by being the wizard) or by askname.
X+ * It may still contain a suffix denoting pl_character.
X+ */
X+ void
X+ askname() {
X+ register int c, ct;
X+
X+ Printf("\nWho are you? ");
X+ (void) fflush(stdout);
X+ ct = 0;
X+ while((c = getchar()) != '\n') {
X+ if(c == EOF) error("End of input\n");
X+ if(c != '-')
X+ if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_';
X+ if(ct < sizeof(plname)-1)
X+ plname[ct++] = c;
X+ }
X+ plname[ct] = 0;
X+ if(ct == 0) askname();
X+ }
X+
X+ #ifdef CHDIR
X+ void
X+ chdirx(dir, wr)
X+ char *dir;
X+ boolean wr;
X+ {
X+ static char *defdir = HACKDIR;
X+
X+ # ifdef HACKDIR
X+ if(dir == NULL)
X+ dir = defdir;
X+ else if (wr)
X+ /* If we're playing anywhere other than HACKDIR, turn off any
X+ privs we may have been installed with. */
X+ privoff();
X+ # endif
X+
X+ if(dir && chdir(dir) < 0) {
X+ perror(dir);
X+ error("Cannot chdir to %s.", dir);
X+ }
X+
X+ /* warn the player if we can't write the record file */
X+ if(wr) {
X+ register int fd;
X+
X+ if(dir == NULL)
X+ dir = "";
X+ if((fd = open(RECORD, 2)) < 0) {
X+ Printf("Warning: cannot write %s%s", dir, RECORD);
X+ getret();
X+ } else
X+ (void) close(fd);
X+ }
X+ defdir = dir;
X+ }
X+ #endif /* CHDIR /**/
X+
X+ static void
X+ whoami() {
X+ /*
X+ * Who am i? Algorithm: 1. Use name as specified in NETHACKOPTIONS
X+ * 2. Use $USER (if 1. fails)
X+ * The resulting name is overridden by command line options.
X+ * If everything fails, or if the resulting name is some generic
X+ * account like "games" then eventually we'll ask him.
X+ * Note that we trust him here; it is possible to play under
X+ * somebody else's name.
X+ */
X+ register char *s;
X+
X+ if(!*plname && (s = getenv("USER")))
X+ (void) strncpy(plname, s, sizeof(plname)-1);
X+ }
X+
X+ static void
X+ byebye()
X+ {
X+ void (*hup)();
X+ extern unsigned int dosh_pid;
X+
X+ /* SIGHUP doesn't seem to do anything on VMS, so we fudge it here... */
X+ hup = signal(SIGHUP, SIG_IGN);
X+ if (hup != SIG_DFL && hup != SIG_IGN)
X+ (*hup)();
X+ if (dosh_pid)
X+ SYS$DELPRC(&dosh_pid, 0);
X+ }
X*** /dev/null Wed Sep 27 12:47:25 1989
X--- vms/vmsmisc.c Sat Sep 16 12:25:25 1989
X***************
X*** 0 ****
X--- 1,14 ----
X+ #include
X+
X+ void
X+ vms_exit(status)
X+ int status;
X+ {
X+ exit(status ? SS$_ABORT : SS$_NORMAL);
X+ }
X+
X+ void
X+ vms_abort()
X+ {
X+ (void) LIB$SIGNAL(SS$_DEBUG);
X+ }
X*** /dev/null Wed Sep 27 12:47:33 1989
X--- vms/vmstermcap.c Sat Sep 16 12:24:04 1989
X***************
X*** 0 ****
X--- 1,742 ----
X+ /* Work-alike for termcap, plus extra features.
X+ Copyright (C) 1985, 1986 Free Software Foundation, Inc.
X+
X+ NO WARRANTY
X+
X+ BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
X+ NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
X+ WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
X+ RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
X+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
X+ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
X+ FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
X+ AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
X+ DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
X+ CORRECTION.
X+
X+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
X+ STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
X+ WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
X+ LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
X+ OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
X+ USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
X+ DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
X+ A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
X+ PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
X+ DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
X+
X+ GENERAL PUBLIC LICENSE TO COPY
X+
X+ 1. You may copy and distribute verbatim copies of this source file
X+ as you receive it, in any medium, provided that you conspicuously and
X+ appropriately publish on each copy a valid copyright notice "Copyright
X+ (C) 1986 Free Software Foundation, Inc."; and include following the
X+ copyright notice a verbatim copy of the above disclaimer of warranty
X+ and of this License. You may charge a distribution fee for the
X+ physical act of transferring a copy.
X+
X+ 2. You may modify your copy or copies of this source file or
X+ any portion of it, and copy and distribute such modifications under
X+ the terms of Paragraph 1 above, provided that you also do the following:
X+
X+ a) cause the modified files to carry prominent notices stating
X+ that you changed the files and the date of any change; and
X+
X+ b) cause the whole of any work that you distribute or publish,
X+ that in whole or in part contains or is a derivative of this
X+ program or any part thereof, to be licensed at no charge to all
X+ third parties on terms identical to those contained in this
X+ License Agreement (except that you may choose to grant more extensive
X+ warranty protection to some or all third parties, at your option).
X+
X+ c) You may charge a distribution fee for the physical act of
X+ transferring a copy, and you may at your option offer warranty
X+ protection in exchange for a fee.
X+
X+ Mere aggregation of another unrelated program with this program (or its
X+ derivative) on a volume of a storage or distribution medium does not bring
X+ the other program under the scope of these terms.
X+
X+ 3. You may copy and distribute this program (or a portion or derivative
X+ of it, under Paragraph 2) in object code or executable form under the terms
X+ of Paragraphs 1 and 2 above provided that you also do one of the following:
X+
X+ a) accompany it with the complete corresponding machine-readable
X+ source code, which must be distributed under the terms of
X+ Paragraphs 1 and 2 above; or,
X+
X+ b) accompany it with a written offer, valid for at least three
X+ years, to give any third party free (except for a nominal
X+ shipping charge) a complete machine-readable copy of the
X+ corresponding source code, to be distributed under the terms of
X+ Paragraphs 1 and 2 above; or,
X+
X+ c) accompany it with the information you received as to where the
X+ corresponding source code may be obtained. (This alternative is
X+ allowed only for noncommercial distribution and only if you
X+ received the program in object code or executable form alone.)
X+
X+ For an executable file, complete source code means all the source code for
X+ all modules it contains; but, as a special exception, it need not include
X+ source code for modules which are standard libraries that accompany the
X+ operating system on which the executable file runs.
X+
X+ 4. You may not copy, sublicense, distribute or transfer this program
X+ except as expressly provided under this License Agreement. Any attempt
X+ otherwise to copy, sublicense, distribute or transfer this program is void and
X+ your rights to use the program under this License agreement shall be
X+ automatically terminated. However, parties who have received computer
X+ software programs from you with this License Agreement will not have
X+ their licenses terminated so long as such parties remain in full compliance.
X+
X+ 5. If you wish to incorporate parts of this program into other free
X+ programs whose distribution conditions are different, write to the Free
X+ Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet
X+ worked out a simple rule that can be stated here, but we will often permit
X+ this. We will be guided by the two goals of preserving the free status of
X+ all derivatives of our free software and of promoting the sharing and reuse of
X+ software.
X+
X+
X+ In other words, you are welcome to use, share and improve this program.
X+ You are forbidden to forbid anyone else to use, share and improve
X+ what you give them. Help stamp out software-hoarding! */
X+
X+
X+
X+ /* BUFSIZE is the initial size allocated for the buffer
X+ for reading the termcap file.
X+ It is not a limit.
X+ Make it large normally for speed.
X+ Make it variable when debugging, so can exercise
X+ increasing the space dynamically. */
X+
X+ #ifdef emacs
X+ #include "config.h"
X+ #endif
X+
X+ #ifndef BUFSIZE
X+ #ifdef DEBUG
X+ #define BUFSIZE bufsize
X+
X+ int bufsize = 128;
X+ #else
X+ #define BUFSIZE 2048
X+ #endif
X+ #endif
X+
X+ #ifndef emacs
X+ static
X+ memory_out ()
X+ {
X+ write (2, "Virtual memory exhausted\n", 25);
X+ exit (1);
X+ }
X+
X+ static int
X+ xmalloc (size)
X+ int size;
X+ {
X+ register tem = malloc (size);
X+ if (!tem)
X+ memory_out ();
X+ return tem;
X+ }
X+
X+ static int
X+ xrealloc (ptr, size)
X+ int ptr;
X+ int size;
X+ {
X+ register tem = realloc (ptr, size);
X+ if (!tem)
X+ memory_out ();
X+ return tem;
X+ }
X+ #endif /* not emacs */
X+
X+ /* Looking up capabilities in the entry already found */
X+
X+ /* The pointer to the data made by tgetent is left here
X+ for tgetnum, tgetflag and tgetstr to find. */
X+
X+ static char *term_entry;
X+
X+ static char *tgetst1 ();
X+
X+ /* This is the main subroutine that is used to search
X+ an entry for a particular capability */
X+
X+ static char *
X+ find_capability (bp, cap)
X+ register char *bp, *cap;
X+ {
X+ for (; *bp; bp++)
X+ if (bp[0] == ':'
X+ && bp[1] == cap[0]
X+ && bp[2] == cap[1])
X+ return &bp[4];
X+ return 0;
X+ }
X+
X+ int
X+ tgetnum (cap)
X+ char *cap;
X+ {
X+ register char *ptr = find_capability (term_entry, cap);
X+ if (!ptr || ptr[-1] != '#')
X+ return -1;
X+ return atoi (ptr);
X+ }
X+
X+ int
X+ tgetflag (cap)
X+ char *cap;
X+ {
X+ register char *ptr = find_capability (term_entry, cap);
X+ return 0 != ptr && ptr[-1] == ':';
X+ }
X+
X+ /* Look up a string-valued capability `cap'.
X+ If `area' is nonzero, it points to a pointer to a block in which
X+ to store the string. That pointer is advanced over the space used.
X+ If `area' is zero, space is allocated with `malloc'. */
X+
X+ char *
X+ tgetstr (cap, area)
X+ char *cap;
X+ char **area;
X+ {
X+ register char *ptr = find_capability (term_entry, cap);
X+ if (!ptr || (ptr[-1] != '=' && ptr[-1] != '~'))
X+ return 0;
X+ return tgetst1 (ptr, area);
X+ }
X+
X+ /* Table, indexed by a character in range 0100 to 0140 with 0100 subtracted,
X+ gives meaning of character following \, or a space if no special meaning.
X+ Eight characters per line within the string. */
X+
X+ static char esctab[]
X+ = " \007\010 \033\014 \
X+ \012 \
X+ \015 \011 \013 \
X+ ";
X+
X+ /* Given a pointer to a string value inside a termcap entry (`ptr'),
X+ copy the value and process \ and ^ abbreviations.
X+ Copy into block that *area points to,
X+ or to newly allocated storage if area is 0. */
X+
X+ static char *
X+ tgetst1 (ptr, area)
X+ char *ptr;
X+ char **area;
X+ {
X+ register char *p, *r;
X+ register int c;
X+ register int size;
X+ char *ret;
X+ register int c1;
X+
X+ if (!ptr)
X+ return 0;
X+
X+ /* `ret' gets address of where to store the string */
X+ if (!area)
X+ {
X+ /* Compute size of block needed (may overestimate) */
X+ p = ptr;
X+ while ((c = *p++) && c != ':' && c != '\n');
X+ ret = (char *) xmalloc (p - ptr + 1);
X+ }
X+ else
X+ ret = *area;
X+
X+ /* Copy the string value, stopping at null or colon. */
X+ /* Also process ^ and \ abbreviations. */
X+ p = ptr;
X+ r = ret;
X+ while ((c = *p++) && c != ':' && c != '\n')
X+ {
X+ if (c == '^')
X+ c = *p++ & 037;
X+ else if (c == '\\')
X+ {
X+ c = *p++;
X+ if (c >= '0' && c <= '7')
X+ {
X+ c -= '0';
X+ size = 0;
X+
X+ while (++size < 3 && (c1 = *p) >= '0' && c1 <= '7')
X+ {
X+ c *= 8;
X+ c += c1 - '0';
X+ p++;
X+ }
X+ }
X+ else if (c >= 0100 && c < 0200)
X+ {
X+ c1 = esctab[(c & ~040) - 0100];
X+ if (c1 != ' ')
X+ c = c1;
X+ }
X+ }
X+ *r++ = c;
X+ }
X+ *r = 0;
X+ /* Update *area */
X+ if (area)
X+ *area = r + 1;
X+ return ret;
X+ }
X+
X+ /* Outputting a string with padding */
X+
X+ short ospeed;
X+ char PC;
X+
X+ /* Actual baud rate if positive;
X+ - baud rate / 100 if negative. */
X+
X+ static short speeds[] =
X+ {
X+ #ifdef VMS
X+ 0, 50, 75, 110, 134, 150, -3, -6, -12, -18,
X+ -20, -24, -36, -48, -72, -96, -192
X+ #else /* not VMS */
X+ 0, 50, 75, 110, 135, 150, -2, -3, -6, -12,
X+ -18, -24, -48, -96, -192, -384
X+ #endif /* not VMS */
X+ };
X+
X+ tputs (string, nlines, outfun)
X+ register char *string;
X+ int nlines;
X+ register int (*outfun) ();
X+ {
X+ register int padcount = 0;
X+
X+ if (string == (char *) 0)
X+ return;
X+ while (*string >= '0' && *string <= '9')
X+ {
X+ padcount += *string++ - '0';
X+ padcount *= 10;
X+ }
X+ if (*string == '.')
X+ {
X+ string++;
X+ padcount += *string++ - '0';
X+ }
X+ if (*string == '*')
X+ {
X+ string++;
X+ padcount *= nlines;
X+ }
X+ while (*string)
X+ (*outfun) (*string++);
X+
X+ /* padcount is now in units of tenths of msec. */
X+ padcount *= speeds[ospeed];
X+ padcount += 500;
X+ padcount /= 1000;
X+ if (speeds[ospeed] < 0)
X+ padcount = -padcount;
X+ else
X+ {
X+ padcount += 50;
X+ padcount /= 100;
X+ }
X+
X+ while (padcount-- > 0)
X+ (*outfun) (PC);
X+ }
X+
X+ /* Finding the termcap entry in the termcap data base */
X+
X+ struct buffer
X+ {
X+ char *beg;
X+ int size;
X+ char *ptr;
X+ int ateof;
X+ int full;
X+ };
X+
X+ /* Forward declarations of static functions */
X+
X+ static int scan_file ();
X+ static char *gobble_line ();
X+ static int compare_contin ();
X+ static int name_match ();
X+
X+ #ifdef VMS
X+
X+ #include
X+ #include
X+ #include
X+
X+ static int
X+ legal_filename_p (fn)
X+ char *fn;
X+ {
X+ struct FAB fab = cc$rms_fab;
X+ struct NAM nam = cc$rms_nam;
X+ char esa[NAM$C_MAXRSS];
X+
X+ fab.fab$l_fna = fn;
X+ fab.fab$b_fns = strlen(fn);
X+ fab.fab$l_nam = &nam;
X+ fab.fab$l_fop = FAB$M_NAM;
X+
X+ nam.nam$l_esa = esa;
X+ nam.nam$b_ess = sizeof esa;
X+
X+ return SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL;
X+ }
X+
X+ #endif /* VMS */
X+
X+ /* Find the termcap entry data for terminal type `name'
X+ and store it in the block that `bp' points to.
X+ Record its address for future use.
X+
X+ If `bp' is zero, space is dynamically allocated. */
X+
X+ int
X+ tgetent (bp, name)
X+ char *bp, *name;
X+ {
X+ register char *tem;
X+ register int fd;
X+ struct buffer buf;
X+ register char *bp1;
X+ char *bp2;
X+ char *term;
X+ int malloc_size = 0;
X+ register int c;
X+ char *tcenv; /* TERMCAP value, if it contais :tc=. */
X+ char *indirect = 0; /* Terminal type in :tc= in TERMCAP value. */
X+ int filep;
X+
X+ tem = (char *) getenv ("TERMCAP");
X+ if (tem && *tem == 0) tem = 0;
X+
X+ #ifdef VMS
X+ filep = tem && legal_filename_p (tem);
X+ #else
X+ filep = tem && (*tem == '/');
X+ #endif /* VMS */
X+
X+ /* If tem is non-null and starts with / (in the un*x case, that is),
X+ it is a file name to use instead of /etc/termcap.
X+ If it is non-null and does not start with /,
X+ it is the entry itself, but only if
X+ the name the caller requested matches the TERM variable. */
X+
X+ if (tem && !filep && !strcmp (name, getenv ("TERM")))
X+ {
X+ indirect = tgetst1 (find_capability (tem, "tc"), 0);
X+ if (!indirect)
X+ {
X+ if (!bp)
X+ bp = tem;
X+ else
X+ strcpy (bp, tem);
X+ goto ret;
X+ }
X+ else
X+ { /* we will need to read /etc/termcap */
X+ tcenv = tem;
X+ tem = 0;
X+ }
X+ }
X+ else
X+ indirect = (char *) 0;
X+
X+ if (!tem)
X+ #ifdef VMS
X+ tem = "emacs_library:[etc]termcap.dat";
X+ #else
X+ tem = "/etc/termcap";
X+ #endif
X+
X+ /* Here we know we must search a file and tem has its name. */
X+
X+ fd = open (tem, 0, 0);
X+ if (fd < 0)
X+ return -1;
X+
X+ buf.size = BUFSIZE;
X+ buf.beg = (char *) xmalloc (buf.size);
X+ term = indirect ? indirect : name;
X+
X+ if (!bp)
X+ {
X+ malloc_size = indirect ? strlen (tcenv) + 1 : buf.size;
X+ bp = (char *) xmalloc (malloc_size);
X+ }
X+ bp1 = bp;
X+
X+ if (indirect) /* copy the data from the environment variable */
X+ {
X+ strcpy (bp, tcenv);
X+ bp1 += strlen (tcenv);
X+ }
X+
X+ while (term)
X+ {
X+ /* Scan file, reading it via buf, till find start of main entry */
X+ if (scan_file (term, fd, &buf) == 0)
X+ return 0;
X+
X+ /* Free old `term' if appropriate. */
X+ if (term != name)
X+ free (term);
X+
X+ /* If `bp' is malloc'd by us, make sure it is big enough. */
X+ if (malloc_size)
X+ {
X+ malloc_size = bp1 - bp + buf.size;
X+ tem = (char *) xrealloc (bp, malloc_size);
X+ bp1 += tem - bp;
X+ bp = tem;
X+ }
X+
X+ bp2 = bp1;
X+
X+ /* Copy the line of the entry from buf into bp. */
X+ tem = buf.ptr;
X+ while ((*bp1++ = c = *tem++) && c != '\n')
X+ /* Drop out any \ newline sequence. */
X+ if (c == '\\' && *tem == '\n')
X+ {
X+ bp1--;
X+ tem++;
X+ }
X+ *bp1 = 0;
X+
X+ /* Does this entry refer to another terminal type's entry? */
X+ /* If something is found, copy it into heap and null-terminate it */
X+ term = tgetst1 (find_capability (bp2, "tc"), 0);
X+ }
X+
X+ close (fd);
X+ free (buf.beg);
X+
X+ if (malloc_size)
X+ {
X+ bp = (char *) xrealloc (bp, bp1 - bp + 1);
X+ }
X+
X+ ret:
X+ term_entry = bp;
X+ if (malloc_size)
X+ return (int) bp;
X+ return 1;
X+ }
X+
X+ /* Given file open on `fd' and buffer `bufp',
X+ scan the file from the beginning until a line is found
X+ that starts the entry for terminal type `string'.
X+ Returns 1 if successful, with that line in `bufp',
X+ or returns 0 if no entry found in the file. */
X+
X+ static int
X+ scan_file (string, fd, bufp)
X+ char *string;
X+ int fd;
X+ register struct buffer *bufp;
X+ {
X+ register char *tem;
X+ register char *end;
X+
X+ bufp->ptr = bufp->beg;
X+ bufp->full = 0;
X+ bufp->ateof = 0;
X+ *bufp->ptr = 0;
X+
X+ lseek (fd, 0L, 0);
X+
X+ while (!bufp->ateof)
X+ {
X+ /* Read a line into the buffer */
X+ end = 0;
X+ do
X+ {
X+ /* if it is continued, append another line to it,
X+ until a non-continued line ends */
X+ end = gobble_line (fd, bufp, end);
X+ }
X+ while (!bufp->ateof && end[-2] == '\\');
X+
X+ if (*bufp->ptr != '#'
X+ && name_match (bufp->ptr, string))
X+ return 1;
X+
X+ /* Discard the line just processed */
X+ bufp->ptr = end;
X+ }
X+ return 0;
X+ }
X+
X+ /* Return nonzero if NAME is one of the names specified
X+ by termcap entry LINE. */
X+
X+ static int
X+ name_match (line, name)
X+ char *line, *name;
X+ {
X+ register char *tem;
X+
X+ if (!compare_contin (line, name))
X+ return 1;
X+ /* This line starts an entry. Is it the right one? */
X+ for (tem = line; *tem && *tem != '\n' && *tem != ':'; tem++)
X+ if (*tem == '|' && !compare_contin (tem + 1, name))
X+ return 1;
X+
X+ return 0;
X+ }
X+
X+ static int
X+ compare_contin (str1, str2)
X+ register char *str1, *str2;
X+ {
X+ register int c1, c2;
X+ while (1)
X+ {
X+ c1 = *str1++;
X+ c2 = *str2++;
X+ while (c1 == '\\' && *str1 == '\n')
X+ {
X+ str1++;
X+ while ((c1 = *str1++) == ' ' || c1 == '\t');
X+ }
X+ if (c2 == '\0') /* end of type being looked up */
X+ {
X+ if (c1 == '|' || c1 == ':') /* If end of name in data base, */
X+ return 0; /* we win. */
X+ else
X+ return 1;
X+ }
X+ else if (c1 != c2)
X+ return 1;
X+ }
X+ }
X+
X+ /* Make sure that the buffer <- `bufp' contains a full line
X+ of the file open on `fd', starting at the place `bufp->ptr'
X+ points to. Can read more of the file, discard stuff before
X+ `bufp->ptr', or make the buffer bigger.
X+
X+ Returns the pointer to after the newline ending the line,
X+ or to the end of the file, if there is no newline to end it.
X+
X+ Can also merge on continuation lines. If `append_end' is
X+ nonzero, it points past the newline of a line that is
X+ continued; we add another line onto it and regard the whole
X+ thing as one line. The caller decides when a line is continued. */
X+
X+ static char *
X+ gobble_line (fd, bufp, append_end)
X+ int fd;
X+ register struct buffer *bufp;
X+ char *append_end;
X+ {
X+ register char *end;
X+ register int nread;
X+ register char *buf = bufp->beg;
X+ register char *tem;
X+
X+ if (append_end == 0)
X+ append_end = bufp->ptr;
X+
X+ while (1)
X+ {
X+ end = append_end;
X+ while (*end && *end != '\n') end++;
X+ if (*end)
X+ break;
X+ if (bufp->ateof)
X+ return buf + bufp->full;
X+ if (bufp->ptr == buf)
X+ {
X+ if (bufp->full == bufp->size)
X+ {
X+ bufp->size *= 2;
X+ tem = (char *) xrealloc (buf, bufp->size);
X+ bufp->ptr += tem - buf;
X+ append_end += tem - buf;
X+ bufp->beg = buf = tem;
X+ }
X+ }
X+ else
X+ {
X+ append_end -= bufp->ptr - buf;
X+ bcopy (bufp->ptr, buf, bufp->full -= bufp->ptr - buf);
X+ bufp->ptr = buf;
X+ }
X+ if (!(nread = read (fd, buf + bufp->full, bufp->size - bufp->full)))
X+ bufp->ateof = 1;
X+ bufp->full += nread;
X+ if (bufp->full != bufp->size)
X+ buf[bufp->full] = 0;
X+ }
X+ return end + 1;
X+ }
X+
X+ #ifdef TEST
X+
X+ #include
X+
X+ main (argc, argv)
X+ int argc;
X+ char **argv;
X+ {
X+ char *term;
X+ char *buf;
X+
X+ term = argv[1];
X+ printf ("TERM: %s\n", term);
X+
X+ buf = (char *) tgetent (0, term);
X+ if ((int) buf <= 0)
X+ {
X+ printf ("No entry.\n");
X+ return 0;
X+ }
X+
X+ printf ("Entry: %s\n", buf);
X+
X+ tprint ("cm");
X+ tprint ("AL");
X+
X+ printf ("co: %d\n", tgetnum ("co"));
X+ printf ("am: %d\n", tgetflag ("am"));
X+ }
X+
X+ tprint (cap)
X+ char *cap;
X+ {
X+ char *x = tgetstr (cap, 0);
X+ register char *y;
X+
X+ printf ("%s: ", cap);
X+ if (x)
X+ {
X+ for (y = x; *y; y++)
X+ if (*y <= ' ' || *y == 0177)
X+ printf ("\\%0o", *y);
X+ else
X+ putchar (*y);
X+ free (x);
X+ }
X+ else
X+ printf ("none");
X+ putchar ('\n');
X+ }
X+
X+ #endif /* TEST */
X*** /dev/null Wed Sep 27 12:47:48 1989
X--- vms/vmstparam.c Sat Sep 16 12:24:46 1989
X***************
X*** 0 ****
X--- 1,360 ----
X+ /* Merge parameters into a termcap entry string.
X+ Copyright (C) 1985, 1987 Free Software Foundation, Inc.
X+
X+
X+ NO WARRANTY
X+
X+ BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
X+ NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
X+ WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
X+ RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
X+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
X+ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
X+ FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
X+ AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
X+ DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
X+ CORRECTION.
X+
X+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
X+ STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
X+ WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
X+ LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
X+ OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
X+ USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
X+ DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
X+ A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
X+ PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
X+ DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
X+
X+ GENERAL PUBLIC LICENSE TO COPY
X+
X+ 1. You may copy and distribute verbatim copies of this source file
X+ as you receive it, in any medium, provided that you conspicuously and
X+ appropriately publish on each copy a valid copyright notice "Copyright
X+ (C) 1986 Free Software Foundation, Inc."; and include following the
X+ copyright notice a verbatim copy of the above disclaimer of warranty
X+ and of this License. You may charge a distribution fee for the
X+ physical act of transferring a copy.
X+
X+ 2. You may modify your copy or copies of this source file or
X+ any portion of it, and copy and distribute such modifications under
X+ the terms of Paragraph 1 above, provided that you also do the following:
X+
X+ a) cause the modified files to carry prominent notices stating
X+ that you changed the files and the date of any change; and
X+
X+ b) cause the whole of any work that you distribute or publish,
X+ that in whole or in part contains or is a derivative of this
X+ program or any part thereof, to be licensed at no charge to all
X+ third parties on terms identical to those contained in this
X+ License Agreement (except that you may choose to grant more extensive
X+ warranty protection to some or all third parties, at your option).
X+
X+ c) You may charge a distribution fee for the physical act of
X+ transferring a copy, and you may at your option offer warranty
X+ protection in exchange for a fee.
X+
X+ Mere aggregation of another unrelated program with this program (or its
X+ derivative) on a volume of a storage or distribution medium does not bring
X+ the other program under the scope of these terms.
X+
X+ 3. You may copy and distribute this program (or a portion or derivative
X+ of it, under Paragraph 2) in object code or executable form under the terms
X+ of Paragraphs 1 and 2 above provided that you also do one of the following:
X+
X+ a) accompany it with the complete corresponding machine-readable
X+ source code, which must be distributed under the terms of
X+ Paragraphs 1 and 2 above; or,
X+
X+ b) accompany it with a written offer, valid for at least three
X+ years, to give any third party free (except for a nominal
X+ shipping charge) a complete machine-readable copy of the
X+ corresponding source code, to be distributed under the terms of
X+ Paragraphs 1 and 2 above; or,
X+
X+ c) accompany it with the information you received as to where the
X+ corresponding source code may be obtained. (This alternative is
X+ allowed only for noncommercial distribution and only if you
X+ received the program in object code or executable form alone.)
X+
X+ For an executable file, complete source code means all the source code for
X+ all modules it contains; but, as a special exception, it need not include
X+ source code for modules which are standard libraries that accompany the
X+ operating system on which the executable file runs.
X+
X+ 4. You may not copy, sublicense, distribute or transfer this program
X+ except as expressly provided under this License Agreement. Any attempt
X+ otherwise to copy, sublicense, distribute or transfer this program is void and
X+ your rights to use the program under this License agreement shall be
X+ automatically terminated. However, parties who have received computer
X+ software programs from you with this License Agreement will not have
X+ their licenses terminated so long as such parties remain in full compliance.
X+
X+ 5. If you wish to incorporate parts of this program into other free
X+ programs whose distribution conditions are different, write to the Free
X+ Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet
X+ worked out a simple rule that can be stated here, but we will often permit
X+ this. We will be guided by the two goals of preserving the free status of
X+ all derivatives of our free software and of promoting the sharing and reuse of
X+ software.
X+
X+
X+ In other words, you are welcome to use, share and improve this program.
X+ You are forbidden to forbid anyone else to use, share and improve
X+ what you give them. Help stamp out software-hoarding! */
X+
X+
X+ /* config.h may rename various library functions such as malloc. */
X+ #ifdef emacs
X+ #include "config.h"
X+ #endif
X+
X+ /* Assuming STRING is the value of a termcap string entry
X+ containing `%' constructs to expand parameters,
X+ merge in parameter values and store result in block OUTSTRING points to.
X+ LEN is the length of OUTSTRING. If more space is needed,
X+ a block is allocated with `malloc'.
X+
X+ The value returned is the address of the resulting string.
X+ This may be OUTSTRING or may be the address of a block got with `malloc'.
X+ In the latter case, the caller must free the block.
X+
X+ The fourth and following args to tparam serve as the parameter values. */
X+
X+ static char *tparam1 ();
X+
X+ /* VARARGS 2 */
X+ char *
X+ tparam (string, outstring, len, arg0, arg1, arg2, arg3)
X+ char *string;
X+ char *outstring;
X+ int len;
X+ int arg0, arg1, arg2, arg3;
X+ {
X+ #ifdef NO_ARG_ARRAY
X+ int arg[4];
X+ arg[0] = arg0;
X+ arg[1] = arg1;
X+ arg[2] = arg2;
X+ arg[3] = arg3;
X+ return tparam1 (string, outstring, len, 0, 0, arg);
X+ #else
X+ return tparam1 (string, outstring, len, 0, 0, &arg0);
X+ #endif
X+ }
X+
X+ char *BC;
X+ char *UP;
X+
X+ static char tgoto_buf[50];
X+
X+ char *
X+ tgoto (cm, hpos, vpos)
X+ char *cm;
X+ int hpos, vpos;
X+ {
X+ int args[2];
X+ if (!cm)
X+ return 0;
X+ args[0] = vpos;
X+ args[1] = hpos;
X+ return tparam1 (cm, tgoto_buf, 50, UP, BC, args);
X+ }
X+
X+ static char *
X+ tparam1 (string, outstring, len, up, left, argp)
X+ char *string;
X+ char *outstring;
X+ int len;
X+ char *up, *left;
X+ register int *argp;
X+ {
X+ register int c;
X+ register char *p = string;
X+ register char *op = outstring;
X+ char *outend;
X+ int outlen = 0;
X+
X+ register int tem;
X+ int *oargp = argp;
X+ int doleft = 0;
X+ int doup = 0;
X+
X+ outend = outstring + len;
X+
X+ while (1)
X+ {
X+ /* If the buffer might be too short, make it bigger. */
X+ if (op + 5 >= outend)
X+ {
X+ register char *new;
X+ if (outlen == 0)
X+ {
X+ new = (char *) malloc (outlen = 40 + len);
X+ outend += 40;
X+ }
X+ else
X+ {
X+ outend += outlen;
X+ new = (char *) realloc (outstring, outlen *= 2);
X+ }
X+ op += new - outstring;
X+ outend += new - outstring;
X+ outstring = new;
X+ }
X+ if (!(c = *p++))
X+ break;
X+ if (c == '%')
X+ {
X+ c = *p++;
X+ tem = *argp;
X+ switch (c)
X+ {
X+ case 'd': /* %d means output in decimal */
X+ if (tem < 10)
X+ goto onedigit;
X+ if (tem < 100)
X+ goto twodigit;
X+ case '3': /* %3 means output in decimal, 3 digits. */
X+ if (tem > 999)
X+ {
X+ *op++ = tem / 1000 + '0';
X+ tem %= 1000;
X+ }
X+ *op++ = tem / 100 + '0';
X+ case '2': /* %2 means output in decimal, 2 digits. */
X+ twodigit:
X+ tem %= 100;
X+ *op++ = tem / 10 + '0';
X+ onedigit:
X+ *op++ = tem % 10 + '0';
X+ argp++;
X+ break;
X+
X+ case 'C':
X+ /* For c-100: print quotient of value by 96, if nonzero,
X+ then do like %+ */
X+ if (tem >= 96)
X+ {
X+ *op++ = tem / 96;
X+ tem %= 96;
X+ }
X+ case '+': /* %+x means add character code of char x */
X+ tem += *p++;
X+ case '.': /* %. means output as character */
X+ if (left)
X+ {
X+ /* If want to forbid output of 0 and \n and \t,
X+ and this is one of them, increment it. */
X+ while (tem == 0 || tem == '\n' || tem == '\t')
X+ {
X+ tem++;
X+ if (argp == oargp)
X+ doleft++, outend -= strlen (left);
X+ else
X+ doup++, outend -= strlen (up);
X+ }
X+ }
X+ *op++ = tem | 0200;
X+ case 'f': /* %f means discard next arg */
X+ argp++;
X+ break;
X+
X+ case 'b': /* %b means back up one arg (and re-use it) */
X+ argp--;
X+ break;
X+
X+ case 'r': /* %r means interchange following two args */
X+ argp[0] = argp[1];
X+ argp[1] = tem;
X+ oargp++;
X+ break;
X+
X+ case '>': /* %>xy means if arg is > char code of x, */
X+ if (argp[0] > *p++) /* then add char code of y to the arg, */
X+ argp[0] += *p; /* and in any case don't output. */
X+ p++; /* Leave the arg to be output later. */
X+ break;
X+
X+ case 'a': /* %a means arithmetic */
X+ /* Next character says what operation.
X+ Add or subtract either a constant or some other arg */
X+ /* First following character is + to add or - to subtract
X+ or = to assign. */
X+ /* Next following char is 'p' and an arg spec
X+ (0100 plus position of that arg relative to this one)
X+ or 'c' and a constant stored in a character */
X+ tem = p[2] & 0177;
X+ if (p[1] == 'p')
X+ tem = argp[tem - 0100];
X+ if (p[0] == '-')
X+ argp[0] -= tem;
X+ else if (p[0] == '+')
X+ argp[0] += tem;
X+ else if (p[0] == '*')
X+ argp[0] *= tem;
X+ else if (p[0] == '/')
X+ argp[0] /= tem;
X+ else
X+ argp[0] = tem;
X+
X+ p += 3;
X+ break;
X+
X+ case 'i': /* %i means add one to arg, */
X+ argp[0] ++; /* and leave it to be output later. */
X+ argp[1] ++; /* Increment the following arg, too! */
X+ break;
X+
X+ case '%': /* %% means output %; no arg. */
X+ goto ordinary;
X+
X+ case 'n': /* %n means xor each of next two args with 140 */
X+ argp[0] ^= 0140;
X+ argp[1] ^= 0140;
X+ break;
X+
X+ case 'm': /* %m means xor each of next two args with 177 */
X+ argp[0] ^= 0177;
X+ argp[1] ^= 0177;
X+ break;
X+
X+ case 'B': /* %B means express arg as BCD char code. */
X+ argp[0] += 6 * (tem / 10);
X+ break;
X+
X+ case 'D': /* %D means weird Delta Data transformation */
X+ argp[0] -= 2 * (tem % 16);
X+ break;
X+ }
X+ }
X+ else
X+ /* Ordinary character in the argument string. */
X+ ordinary:
X+ *op++ = c;
X+ }
X+ *op = 0;
X+ while (doleft-- > 0)
X+ strcpy (op, left);
X+ while (doup-- > 0)
X+ strcpy (op, up);
X+ return outstring;
X+ }
X+
X+ #ifdef DEBUG
X+
X+ main (argc, argv)
X+ int argc;
X+ char **argv;
X+ {
X+ char buf[50];
X+ int args[3];
X+ args[0] = atoi (argv[2]);
X+ args[1] = atoi (argv[3]);
X+ args[2] = atoi (argv[4]);
X+ tparam1 (argv[1], buf, "LEFT", "UP", args);
X+ printf ("%s\n", buf);
X+ return 0;
X+ }
X+
X+ #endif /* DEBUG */
X*** /dev/null Wed Sep 27 12:48:01 1989
X--- vms/vmstty.c Wed Sep 27 09:29:57 1989
X***************
X*** 0 ****
X--- 1,170 ----
X+ /* SCCS Id: @(#)vmstty.c 3.0 88/05/03
X+ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X+ /* NetHack may be freely redistributed. See license for details. */
X+ /* tty.c - (VMS) version */
X+
X+ #define NEED_VARARGS
X+ #include "hack.h"
X+
X+ #include
X+ #include
X+ #include
X+
X+ #define LIB$M_CLI_CTRLT 0x100000
X+ #define LIB$M_CLI_CTRLY 0x2000000
X+
X+ extern short ospeed;
X+ char erase_char, intr_char, kill_char;
X+ static boolean settty_needed = FALSE;
X+ static unsigned int kb = 0;
X+
X+ int
X+ vms_getchar()
X+ {
X+ short key;
X+
X+ if (kb)
X+ {
X+ SMG$READ_KEYSTROKE(&kb, &key);
X+ switch (key)
X+ {
X+ case SMG$K_TRM_UP:
X+ key = 'k';
X+ break;
X+ case SMG$K_TRM_DOWN:
X+ key = 'j';
X+ break;
X+ case SMG$K_TRM_LEFT:
X+ key = 'h';
X+ break;
X+ case SMG$K_TRM_RIGHT:
X+ key = 'l';
X+ break;
X+ case '\r':
X+ key = '\n';
X+ break;
X+ default:
X+ if (key == '\007' || key == '\032' || key > 255)
X+ key = '\033';
X+ break;
X+ }
X+ }
X+ else
X+ key = getchar();
X+ return key;
X+ }
X+
X+ static struct sensemode {
X+ short status;
X+ unsigned char xmit_baud;
X+ unsigned char rcv_baud;
X+ unsigned char crfill;
X+ unsigned char lffill;
X+ unsigned char parity;
X+ unsigned char unused;
X+ char class;
X+ char type;
X+ short scr_wid;
X+ unsigned long tt_char: 24, scr_len: 8;
X+ unsigned long tt2_char;
X+ } sg;
X+ unsigned int ctrl_mask;
X+
X+ static void
X+ setctty(){
X+ }
X+
X+ /*
X+ * Get initial state of terminal, set ospeed (for termcap routines)
X+ * and switch off tab expansion if necessary.
X+ * Called by startup() in termcap.c and after returning from ! or ^Z
X+ */
X+ void
X+ gettty(){
X+ int status;
X+ int input_chan;
X+ $DESCRIPTOR (input_dsc, "TT");
X+ unsigned int zero = 0;
X+
X+ if (!(SYS$ASSIGN (&input_dsc, &input_chan, 0, 0) & 1))
X+ perror("NetHack (gettty)");
X+ status = SYS$QIOW(0, input_chan, IO$_SENSEMODE, &sg, 0, 0, &sg.class, 12,
X+ 0, 0, 0, 0);
X+ SYS$DASSGN (input_chan);
X+ if (!(status & 1))
X+ perror("NetHack (gettty)");
X+ ospeed = sg.xmit_baud;
X+ erase_char = '\177';
X+ kill_char = '\025';
X+ intr_char = '\003';
X+ (void) LIB$ENABLE_CTRL(&zero, &ctrl_mask);
X+ /* Use the systems's values for lines and columns if it has any idea. */
X+ if (sg.scr_len)
X+ LI = sg.scr_len;
X+ if (sg.scr_wid)
X+ CO = sg.scr_wid;
X+ settty_needed = TRUE;
X+ }
X+
X+ #ifdef MAIL
X+ unsigned long pasteboard_id = 0;
X+ #endif
X+
X+ /* reset terminal to original state */
X+ void
X+ settty(s)
X+ char *s;
X+ {
X+ clear_screen();
X+ end_screen();
X+ if(s) Printf(s);
X+ (void) fflush(stdout);
X+ SMG$DELETE_VIRTUAL_KEYBOARD(&kb);
X+ #ifdef MAIL
X+ SMG$DELETE_PASTEBOARD(&pasteboard_id);
X+ #endif
X+ if (ctrl_mask)
X+ (void) LIB$ENABLE_CTRL(&ctrl_mask, 0);
X+ flags.echo = ON;
X+ flags.cbreak = OFF;
X+ }
X+
X+ #ifdef MAIL
X+ static void
X+ broadcast_ast(dummy)
X+ {
X+ extern int broadcasts;
X+
X+ broadcasts++;
X+ }
X+ #endif
X+
X+ void
X+ setftty(){
X+ unsigned int mask = LIB$M_CLI_CTRLT | LIB$M_CLI_CTRLY;
X+
X+ flags.cbreak = ON;
X+ flags.echo = OFF;
X+ (void) LIB$DISABLE_CTRL(&mask, 0);
X+ SMG$CREATE_VIRTUAL_KEYBOARD(&kb);
X+ #ifdef MAIL
X+ SMG$CREATE_PASTEBOARD(&pasteboard_id, 0, 0, 0, 0);
X+ SMG$SET_BROADCAST_TRAPPING(&pasteboard_id, broadcast_ast, 0);
X+ #endif
X+ start_screen();
X+ }
X+
X+
X+ /* fatal error */
X+ /*VARARGS1*/
X+ void
X+ error VA_DECL(char *,s)
X+ VA_START(s);
X+ VA_INIT(char *,s);
X+ if(settty_needed)
X+ settty(NULL);
X+ Vprintf(s,VA_ARGS);
X+ (void) putchar('\n');
X+ VA_END();
X+ exit(1);
X+ }
X
END_OF_FILE
if test 52494 -ne `wc -c <'patches04f'`; then
echo shar: \"'patches04f'\" unpacked with wrong size!
fi
# end of 'patches04f'
fi
echo shar: End of archive 6 \(of 11\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 11 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0