aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRodney W. Grimes <rgrimes@FreeBSD.org>1993-06-12 14:49:13 +0000
committerRodney W. Grimes <rgrimes@FreeBSD.org>1993-06-12 14:49:13 +0000
commit9002c02abc587664acb357c6879d8ca08664dd0b (patch)
tree515fc124b039c993c5762b23524842c4aebcaa06
downloadsrc-9002c02abc5.tar.gz
src-9002c02abc5.zip
Initial import, 0.1 + pk 0.2.4-B1
Notes
Notes: svn path=/cvs2svn/branches/tcpdump/; revision=2
-rw-r--r--gnu/games/chess/DOCUMENTATION/ARTICLE66
-rw-r--r--gnu/games/chess/DOCUMENTATION/ARTICLE.2123
-rw-r--r--gnu/games/chess/DOCUMENTATION/CHANGES362
-rw-r--r--gnu/games/chess/DOCUMENTATION/COPYING123
-rw-r--r--gnu/games/chess/DOCUMENTATION/GENERAL34
-rw-r--r--gnu/games/chess/DOCUMENTATION/HEURISTICS122
-rw-r--r--gnu/games/chess/DOCUMENTATION/MAN-PAGE161
-rw-r--r--gnu/games/chess/Makefile15
-rw-r--r--gnu/games/chess/Xchess/COPYING124
-rw-r--r--gnu/games/chess/Xchess/Makefile136
-rw-r--r--gnu/games/chess/Xchess/ScrollText34
-rw-r--r--gnu/games/chess/Xchess/XCircle.c162
-rw-r--r--gnu/games/chess/Xchess/bishop.bitmap71
-rw-r--r--gnu/games/chess/Xchess/bishop_mask.bitmap71
-rw-r--r--gnu/games/chess/Xchess/bishop_outline.bitmap71
-rw-r--r--gnu/games/chess/Xchess/bishop_small.bitmap15
-rw-r--r--gnu/games/chess/Xchess/bishop_small_outline.bitmap15
-rw-r--r--gnu/games/chess/Xchess/board.c179
-rw-r--r--gnu/games/chess/Xchess/button.c337
-rw-r--r--gnu/games/chess/Xchess/clock.c291
-rw-r--r--gnu/games/chess/Xchess/control.c515
-rw-r--r--gnu/games/chess/Xchess/jail.c327
-rw-r--r--gnu/games/chess/Xchess/king.bitmap71
-rw-r--r--gnu/games/chess/Xchess/king_mask.bitmap71
-rw-r--r--gnu/games/chess/Xchess/king_outline.bitmap71
-rw-r--r--gnu/games/chess/Xchess/king_small.bitmap15
-rw-r--r--gnu/games/chess/Xchess/king_small_outline.bitmap15
-rw-r--r--gnu/games/chess/Xchess/knight.bitmap71
-rw-r--r--gnu/games/chess/Xchess/knight_mask.bitmap71
-rw-r--r--gnu/games/chess/Xchess/knight_outline.bitmap71
-rw-r--r--gnu/games/chess/Xchess/knight_small.bitmap15
-rw-r--r--gnu/games/chess/Xchess/knight_small_outline.bitmap15
-rw-r--r--gnu/games/chess/Xchess/message.c101
-rw-r--r--gnu/games/chess/Xchess/parse.c386
-rw-r--r--gnu/games/chess/Xchess/pawn.bitmap71
-rw-r--r--gnu/games/chess/Xchess/pawn_mask.bitmap71
-rw-r--r--gnu/games/chess/Xchess/pawn_outline.bitmap71
-rw-r--r--gnu/games/chess/Xchess/pawn_small.bitmap15
-rw-r--r--gnu/games/chess/Xchess/pawn_small_outline.bitmap15
-rw-r--r--gnu/games/chess/Xchess/popup.c112
-rw-r--r--gnu/games/chess/Xchess/program.c200
-rw-r--r--gnu/games/chess/Xchess/queen.bitmap71
-rw-r--r--gnu/games/chess/Xchess/queen_mask.bitmap71
-rw-r--r--gnu/games/chess/Xchess/queen_outline.bitmap71
-rw-r--r--gnu/games/chess/Xchess/queen_small.bitmap15
-rw-r--r--gnu/games/chess/Xchess/queen_small_outline.bitmap15
-rw-r--r--gnu/games/chess/Xchess/record.c315
-rw-r--r--gnu/games/chess/Xchess/rook.bitmap71
-rw-r--r--gnu/games/chess/Xchess/rook_mask.bitmap71
-rw-r--r--gnu/games/chess/Xchess/rook_outline.bitmap71
-rw-r--r--gnu/games/chess/Xchess/rook_small.bitmap15
-rw-r--r--gnu/games/chess/Xchess/rook_small_outline.bitmap15
-rw-r--r--gnu/games/chess/Xchess/scrollText.c1858
-rw-r--r--gnu/games/chess/Xchess/scrollText.h32
-rw-r--r--gnu/games/chess/Xchess/scrollText/scrollText.c1858
-rw-r--r--gnu/games/chess/Xchess/scrollText/scrollText.h32
-rw-r--r--gnu/games/chess/Xchess/shade.bitmap71
-rw-r--r--gnu/games/chess/Xchess/std.c425
-rw-r--r--gnu/games/chess/Xchess/std.h105
-rw-r--r--gnu/games/chess/Xchess/valid.c264
-rw-r--r--gnu/games/chess/Xchess/window.c952
-rw-r--r--gnu/games/chess/Xchess/window.c.bm928
-rw-r--r--gnu/games/chess/Xchess/xchess.1217
-rw-r--r--gnu/games/chess/Xchess/xchess.c205
-rw-r--r--gnu/games/chess/Xchess/xchess.c.150197
-rw-r--r--gnu/games/chess/Xchess/xchess.cur9
-rw-r--r--gnu/games/chess/Xchess/xchess.game8
-rw-r--r--gnu/games/chess/Xchess/xchess.h301
-rw-r--r--gnu/games/chess/Xchess/xchess.icon28
-rw-r--r--gnu/games/chess/Xchess/xchess_mask.cur7
-rw-r--r--gnu/games/chess/gnuchess.book3878
-rw-r--r--gnu/games/chess/gnuchess.c2307
-rw-r--r--gnu/games/chess/gnuchess.h97
-rw-r--r--gnu/games/chess/move.c357
-rw-r--r--gnu/games/chess/move.h81
-rw-r--r--gnu/games/chess/nondsp.c791
-rw-r--r--gnu/games/chess/pathnames.h36
-rw-r--r--gnu/games/chess/uxdsp.c933
-rw-r--r--share/man/man4/man4.i386/Makefile7
-rw-r--r--share/man/man4/man4.i386/mem.482
-rw-r--r--share/man/man4/man4.i386/spkr.4117
-rw-r--r--share/man/man4/mem.482
-rw-r--r--share/man/man4/spkr.4117
-rw-r--r--usr.bin/symorder/Makefile5
-rw-r--r--usr.bin/symorder/symorder.181
-rw-r--r--usr.bin/symorder/symorder.c281
-rw-r--r--usr.sbin/dbsym/Makefile4
-rw-r--r--usr.sbin/dbsym/dbsym.c192
-rw-r--r--usr.sbin/tcpdump/Makefile5
-rw-r--r--usr.sbin/tcpdump/Makefile.inc3
-rw-r--r--usr.sbin/tcpdump/tcpdump/Makefile24
-rw-r--r--usr.sbin/tcpdump/tcpdump/VERSION1
-rw-r--r--usr.sbin/tcpdump/tcpdump/addrtoname.c478
-rw-r--r--usr.sbin/tcpdump/tcpdump/addrtoname.h36
-rw-r--r--usr.sbin/tcpdump/tcpdump/appletalk.h156
-rw-r--r--usr.sbin/tcpdump/tcpdump/bootp.h103
-rw-r--r--usr.sbin/tcpdump/tcpdump/bpf_dump.c61
-rw-r--r--usr.sbin/tcpdump/tcpdump/bpf_image.c282
-rw-r--r--usr.sbin/tcpdump/tcpdump/etherent.c144
-rw-r--r--usr.sbin/tcpdump/tcpdump/etherent.h34
-rw-r--r--usr.sbin/tcpdump/tcpdump/etherproto.h70
-rw-r--r--usr.sbin/tcpdump/tcpdump/extract.h49
-rw-r--r--usr.sbin/tcpdump/tcpdump/gencode.c1384
-rw-r--r--usr.sbin/tcpdump/tcpdump/gencode.h156
-rw-r--r--usr.sbin/tcpdump/tcpdump/inet.c172
-rw-r--r--usr.sbin/tcpdump/tcpdump/interface.h111
-rw-r--r--usr.sbin/tcpdump/tcpdump/md.c35
-rw-r--r--usr.sbin/tcpdump/tcpdump/md.h40
-rw-r--r--usr.sbin/tcpdump/tcpdump/mib.h1256
-rw-r--r--usr.sbin/tcpdump/tcpdump/nametoaddr.c258
-rw-r--r--usr.sbin/tcpdump/tcpdump/nametoaddr.h43
-rw-r--r--usr.sbin/tcpdump/tcpdump/ntp.h117
-rw-r--r--usr.sbin/tcpdump/tcpdump/optimize.c1871
-rw-r--r--usr.sbin/tcpdump/tcpdump/os.c26
-rw-r--r--usr.sbin/tcpdump/tcpdump/os.h85
-rw-r--r--usr.sbin/tcpdump/tcpdump/ospf.h223
-rw-r--r--usr.sbin/tcpdump/tcpdump/pcap.c209
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-arp.c100
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-atalk.c478
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-bootp.c263
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-domain.c287
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-egp.c347
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-ether.c123
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-fddi.c236
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-icmp.c207
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-ip.c313
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-nfs.c466
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-ntp.c277
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-null.c117
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-ospf.c586
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-ppp.c102
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-rip.c116
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-sl.c246
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-snmp.c1043
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-sunrpc.c136
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-tcp.c287
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-tftp.c149
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-udp.c141
-rw-r--r--usr.sbin/tcpdump/tcpdump/savefile.c303
-rw-r--r--usr.sbin/tcpdump/tcpdump/savefile.h75
-rw-r--r--usr.sbin/tcpdump/tcpdump/tcpdump.11067
-rw-r--r--usr.sbin/tcpdump/tcpdump/tcpdump.c347
-rw-r--r--usr.sbin/tcpdump/tcpdump/tcpgram.y232
-rw-r--r--usr.sbin/tcpdump/tcpdump/tcplex.l146
-rw-r--r--usr.sbin/tcpdump/tcpdump/util.c278
-rw-r--r--usr.sbin/tcpdump/tcpslice/Makefile18
-rw-r--r--usr.sbin/tcpdump/tcpslice/gwtm2secs.c75
-rw-r--r--usr.sbin/tcpdump/tcpslice/search.c563
-rw-r--r--usr.sbin/tcpdump/tcpslice/tcpslice.1260
-rw-r--r--usr.sbin/tcpdump/tcpslice/tcpslice.c645
150 files changed, 40089 insertions, 0 deletions
diff --git a/gnu/games/chess/DOCUMENTATION/ARTICLE b/gnu/games/chess/DOCUMENTATION/ARTICLE
new file mode 100644
index 000000000000..b2ab331d21d5
--- /dev/null
+++ b/gnu/games/chess/DOCUMENTATION/ARTICLE
@@ -0,0 +1,66 @@
+[This article was reproduced from a GNU Bulletin.]
+
+ GNU Chess
+ by Stuart Cracraft
+ copyright 1987 Stuart Cracraft
+
+
+ GNU Chess is a communal chess program. Contributors donate their
+time and effort in order to make it a stronger, better, sleeker program.
+Contributions take many forms: interfaces to high-resolution displays,
+opening book treatises, speedups of the underlying algorithms, additions
+of extra heuristics. These contributions are then distributed to the
+large user-base so that all may enjoy the fruits of our labor. The
+original and continuing purpose of this project is to permanently end
+the rampant hoarding of computer chess software that has been the
+case for the past 20 years.
+
+ Many people have contributed to GNU Chess. Their contributions have
+improved the program from being a patzer (weak program) to being a
+grandpatzer (decently strong program). In its growth since initial
+release, GNU Chess has gone from approximately class D to expert
+strength. It beats the Fidelity Excel commercial unit rather handily.
+
+ GNU Chess's structure is a hybrid of the Shannon Type-A and
+Type-B methods. It conducts a full-width search to a fixed-depth
+and then continues with a quiescence search for many more ply.
+This quiescence search helps the program find positions which
+can be safely evaluated and which are not too turbulent. If
+a terminal position is too turbulent, the evaluation will be
+highly inaccurate. Additional searching by investigating series
+of captures, checks, and other potentially imbalance-producing
+moves is quite helpful.
+
+ GNU Chess will sacrifice pieces in order to reach known winning
+endings. Also, it uses a trade-down bonus to encourage the stronger
+side to trade off certain types of pieces thus reaching a more
+simplified and therefore ostensibly "clearer" position.
+
+ GNU Chess has certain types of knowledge regarding easier endgames.
+This allows it to play these endings somewhat better than might be
+expected.
+
+ GNU Chess has time heuristics that it uses to improve its handling
+of time-controls and hasten its making of "obvious" moves.
+
+ GNU Chess is interfaced to the SUN Windows and X Windows
+display protocols and can display its pieces in elaborate format,
+similar to chess diagrams.
+
+ GNU Chess has an opening book which consists of many variations
+from MCO (Modern Chess Openings).
+
+ For comparison purposes, GNU Chess running on a VAX 8650 is
+stronger than the famous Chess 4.5 running on a CDC 6400.
+
+ We wish to acknowledge the contributions of the following
+individuals: (in alphabetical order) Jim Aspnes, Wayne Christopher,
+Steve Dougherty, David Goldberg, Richard Greenblatt, David Kittinger,
+Richard Stallman, John Stanback, and Ken Thompson.
+
+ Contact information: The author may be reached by a variety of
+methods. Via U.S. mail: Stuart Cracraft, 5 Via Amistosa, Suite G,
+Rancho Santa Margarita, Ca. 92688 USA.
+ By Internet: 'cracraft at wheaties.ai.mit.edu'
+The author may also be contacted via the Free Software Foundation, Inc.
+675 Massachusetts Ave.,Cambridge MA 02139.
diff --git a/gnu/games/chess/DOCUMENTATION/ARTICLE.2 b/gnu/games/chess/DOCUMENTATION/ARTICLE.2
new file mode 100644
index 000000000000..031ae18f9e4b
--- /dev/null
+++ b/gnu/games/chess/DOCUMENTATION/ARTICLE.2
@@ -0,0 +1,123 @@
+
+
+ GNU Chess: Experiences Learned
+ with Communal Sharing
+ by Stuart Cracraft
+ (and contributors to the GNU Project)
+
+
+Limited sharing has characterized the computer chess community
+for the past two decades. Occasional research articles give hints
+and suggestions for useful features, but rarely reveal the real
+details of the critically important advances. We will here
+describe an effort underway (titled "GNU Chess") to create a more
+open and friendly environment of sharing.
+
+GNU Chess is part of Project GNU, a large-scale effort in which
+the philosophical goals are far-reaching. We will not go into any
+great depth about these goals as they relate to the larger pro-
+ject, because these are described elsewhere [1]. However, we will
+mention the basic issues and the changes we hope to encourage.
+
+The start of the GNU Chess project was a natural result of the
+experiences gleaned in writing a chess program. While the author
+was at a progressive academic location [2], he was able to con-
+ceive the idea of a communal chess program only after much heart-
+ache. During the period of writing the initial version (which
+has since undergone many improvements and whole revisions), it
+became clear that the best features and most useful hints, the
+very best of the heuristics, were hidden and difficult to find in
+the literature.
+
+Sprinkled across many books, research papers, magazine articles,
+accumulated in the community, during the past 25 years, there was
+literally a void of true, empirical programs. Locating usable
+programs was difficult. Many programs were the result of academic
+work in "ivory towers", and hence were inaccessible to the common
+man. Other programs were sequestered in research think-tanks. Na-
+turally, developers of commercial programs carefully guarded
+their source in order to protect their investment. On the other
+hand, a few chess program source listings had actually been pub-
+lished, but these were not really very strong, often written in a
+non-general language, and frequently more pedantic than practi-
+cal.
+
+The idea of a reasonably strong communal program solidified.
+When we refer to a communal program, we do not regard this as
+public-domain software. Rather, we refer to a program which is
+under the shared authority of a number of individuals, the prin-
+cipal contributors. These individuals have experienced and real-
+ized the positive results of a sharing community and the rapid
+improvements that come through contributing in such a community.
+Further, these individuals devote time and energy to coordinating
+the contributions of other individuals. While they exercise a
+certain editorial right, this is usually not exercised arbitrari-
+ly; instead, a discussion is often undertaken.
+
+Eventually, a working C program that played chess was available.
+The coordinating institution for Project GNU [3], accepted our
+suggestion of inclusion of a chess program in the GNU distribu-
+tion. Initial distribution of GNU Chess commenced in October of
+1986. Interest in the project increased rapidly.
+
+Contributions came in from many places and people. Interfaces to
+X-windows and SUN-windows were donated, thus allowing very fancy
+chess fonts on bit-mapped screens. Also, contributions involving
+large portions of opening books such as MCO and collections of
+master games were added to the distribution. Additionally,
+tree-search modifications and heuristics were provided, and occa-
+sionally even entire rewrites.
+
+The program advanced in strength by several USCF class intervals
+during a period of less than one year. During this time, many
+unusual features and enhancements were added to the program, usu-
+ally under the coordination of two or more people, with one work-
+ing in a distant-advisory capacity to the other. Frequently, gra-
+duate students would give up significant time from their thesis
+work to devote energy to contributing. Their corporate counter-
+parts would often give up project time to make their donation.
+
+Contributors would often enter the project in a very forceful way
+and then having made their contribution, learn the viability of
+communal sharing once others had stepped in and contributed to
+them, thus providing considerable reinforcement. Frequently, con-
+tributors would then go into "hibernation" for a long period of
+time, but most of them remained open to contributing and were
+helpful when asked to reprogram their particular contribution in
+a more recent version.
+
+GNU Chess has made great strides in relatively little time. It
+has run on many different hardware architectures and has been
+compiled by a number of C compilers [4]. A sampling of the com-
+puters on which the program has run is: National 32032, Vax
+11/750, 8550, 8600, 8650, Motorola 68020, CCI 5/32, CCI 6/32
+(tahoe), Cray XMP.
+
+It is our belief that GNU Chess will stimulate graduate research
+in computer chess theory and practice. When students are able to
+easily obtain a state-of-the-art program in order to test out
+their ideas, they will no longer need to reinvent the wheel. The
+students will be able to investigate their research areas much
+more thoroughly, because they will spend more time on the specif-
+ic research areas they are concerned about. Basically, GNU Chess
+"frees up" time in order to get on to more fundamental issues.
+
+We also feel that as other researchers gain trust in the GNU
+Chess project, they will be more likely to release their results
+directly and rapidly, through journal articles, or directly to
+the GNU project, and in fact become contributors and join the
+present list [5]. At the very least, a communal, ever-growing
+program will encourage the few "closeted" researchers to be some-
+what more open in their approach to disseminating advances.
+
+In whatever form it takes, the progress toward elaboration of
+machine chess is ongoing, and we hope that GNU chess will be
+helpful to the community. Copies of GNU Chess source and "book",
+as well as additional experimental code are available from the
+Free Software Foundation [3] or the author [6].
+
+
+[1] The GNU Manifesto, Richard Stallman, Free Software Foundation, Inc.
+
+[2] University of Southern California, Information Sciences Institute.
+
diff --git a/gnu/games/chess/DOCUMENTATION/CHANGES b/gnu/games/chess/DOCUMENTATION/CHANGES
new file mode 100644
index 000000000000..9866075ab8a8
--- /dev/null
+++ b/gnu/games/chess/DOCUMENTATION/CHANGES
@@ -0,0 +1,362 @@
+ GNU CHESS HISTORY
+ (#include "../version.h")
+
+August 1, 1989 -- Jay Scott
+He proofread the opening book and made
+corrections.
+
+June 21, 1989 -- Hes @log-se.sv
+He contributed new move generation routines (move.c move.h) to speedup
+move generation and the overall program, by about 15-30%
+
+June 9, 1989 -- Tim Radzy (unet!nplab4!radz@ames.arc.nasa.gov)
+He fixed a bug in xchess/board.c. In a post-game new-game situation,
+castling wouldn't be permitted under circumstances. Tim made
+it possible to castle again.
+
+May 12, 1989 -- Joe Garbarini (garbarini%kegger@circus.llnl.gov)
+Recommended changes to documentation vis a vis chesstool usage.
+
+May 5, 1989 -- Jouko Holopainen (jhol@tolsun.oulu.fi)
+Wrote code to support underpromotion.
+Changed interface to accept ECO/Informator style moves.
+
+April 30, 1989 -- Various GNU contributors
+setlinebuf() modification for xchess/chesstool.
+check for zero division in time printout.
+
+January 17, 1989 -- Anders Thulin
+Provided extensive addition to the opening book for his
+favorite opening the Vienna Game. This was drawn from ECO.
+
+November 23, 1988 -- Stuart Cracraft
+Installed new version of Xchess that is better debugged, works on
+the next version of X. Thanks to Wayne Christopher and Arturo Perez.
+
+August 28, 1988 -- Stuart Cracraft
+Removed a sacrifice line from the Giuoco Piano entry in the opening
+book; the program didn't seem to like the positions it got from this line.
+
+December 30, 1987 -- John Stanback
+Wrote a short blurb on the heuristics contained in GNU Chess. It resides
+in the subdirectory DOCUMENTATION as the file HEURISTICS.
+
+December 17, 1987 -- John Stanback
+Modified criteria for positional evaluation in quiescence search
+to include positions in which the estimated score lies within
+the alpha-beta window; fixed a bug in the king proximity to pawns heuristic;
+fixed a bug involving passed pawn heuristics;
+
+December 16, 1987 -- Stuart Cracraft
+Added automatic 'list' upon exit (both in display, non-display, and
+chesstool mode); command-line setting of tournament time controls
+bug fixed.
+
+December 14, 1987 -- John Stanback
+GNU defeated the commercial product 'Fidelity Excellence' 5.5-4.5 in
+a 10-game match. It was running at about 500 nodes per second (typical
+of its speed on a VAX 8650) and this would indicate its strength
+would be about USCF 1875-1900.
+
+December 4, 1987 -- John Stanback
+Man page added. Command line arguments now specify regular clock
+settings if so desired (useful for SUN players). Thinking
+on opponent's time is now disabled by default. Estimated
+rating is 1850 at 500 nodes per second.
+
+October 20, 1987 -- Stuart Cracraft
+Fixed GNU/SUN interaction. Chesstool and its features now
+seem to fully work.
+
+October 5, 1987 -- Ken Thompson
+GNU beat Belle (actually drew due to a bug, but
+Ken kept GNU playing through to the win) while
+running on a Cray XMP-48. In this 3-1 time handicap game
+Belle outsearched Cray GNU by 10-1 (even with the handicap).
+
+September 26, 1987 -- John Stanback at HP
+Hash table functioning. Thinking on opponent's
+time functioning.
+
+August 20, 1987 -- Mike Meyer at Berkeley
+Mike ran GNU Chess on a Cray 1 supercomputer.
+The system was very heavily loaded, so the
+program was not as speedy as with the Cray below.
+
+August 16, 1987 -- David Goldberg at SUN
+He added "chesstool" support so that this
+version of GNU Chess can run under the
+display manager "chesstool".
+
+August 15, 1987 -- John Stanback at HP
+Hash tables, more heuristics, a modified
+search which is more efficient. He also
+discovered a bug in the piece-exchanger. This
+would cause the program to exchange pieces suboptimally.
+With this fix, the program should play much
+more strongly.
+
+August 13, 1987 -- Ken Thompson at Bell Labs
+Ken ran GNU Chess on a Cray XMP supercomputer
+ (among other processors). The program got
+ about 3000-4000 chess positions per second
+ which is comprable to today's fastest bit-slice
+ commercial machines. Also, he had GNU Chess
+ play two games against Belle.
+
+July 19, 1987 -- Jay Scott & John Stanback
+ Many positional heuristics have been added.
+
+July 18, 1987 -- Stuart Cracraft
+ Improvements have been made to the opening
+ book. It is mostly an MCO book, containing
+ major variations from many of the major openings
+ and particularly in-depth on Sicilian.
+
+May 11, 1987 -- John Stanback at HP
+ He donated his chess program, a fairly mature
+ and strong program.
+
+May 1, 1987 -- Stuart Cracraft
+ He added several bug fixes various people
+ had reported. He also changed makemove() so that
+ the calling syntax is makemove(movelist,index,board)
+ rather than makemove(move,board). Having the latter
+ tickled a bug in at least one manufacturer's C-compiler,
+ so rather than write fancy code, we simplified it.
+
+April 25, 1987-- Jim Aspnes at MIT
+He added all sorts of useful capabilities,
+including positional evaluation in the tree
+search using a table-driven algorithm,
+modifying transposition table code in order
+to work properly, though it doesn't improve
+speed too much, checkmates/stalemates detected
+in the search, en passant captures allowed,
+detect repeated positions, iterative deepening,
+quicker quiescence search, tournament time controls,
+sqattacked sped up by a factor of 4, compile-time
+debugging options.
+
+January 2, 1987 -- Stuart Cracraft
+ He added a few more Tal games to the collection.
+
+January 2, 1987 -- Jim Aspnes at MIT
+ He contributed MCO variations for the Catalan,
+ Queen's Indian, and Reti openings.
+
+December 29, 1986 -- Jim Aspnes at MIT
+ He contributed all MCO variations of the Najdorf
+ to the opening book. He also contributed a LISP
+ macro (written in GNU Emacs Lisp) to convert
+ xchess game formats to GNU Chess opening book
+ format.
+
+December 14, 1986 -- Ken Thompson at Bell Labs
+ He contributed almost 200 games by Tal to
+ our collection of Tal-games, bringing the
+ total number of Tal positions in the book
+ to 10,692. Total book positions now 13,207.
+ These reside in bookin, bookin.bdg, bookin.tal.
+ Note that presently, only bookin and bookin.tal
+ can be used. The new Tal positions came in a
+ slightly different format, which we have chosen
+ to adopt as our standard format. All book
+ games in bookin and bookin.bdg will gradually
+ change into the new standard format.
+
+December 11, 1986 -- Stuart Cracraft
+ Added "averages" for node-count per move,
+ cpu per move, rate per move to list_history
+ and write_history.
+ New version of Xchess installed.
+ Started typing in Tal games into "bookin.tal".
+ Added "total book positions" printout to "book"
+ and "enter" statistics printout.
+
+December 10, 1986 -- Stuart Cracraft
+ Implemented aspiration search in normal
+ alpha-beta search. Speedups of 3% to 40%
+ have been noticed in most positions.
+ Occasionally a slower search will result,
+ but it is thought these are worth the
+ usual speedups.
+
+December 9, 1986 -- Stuart Cracraft
+ Fixed minor bug in write_history()
+ Added another Tal game, 2nd game of 1st world
+ championship match with Botvinnik, a Benoni.
+
+December 9, 1986 -- Stuart Cracraft
+ Enhanced parallelism. All parallel processors
+ now communicate via a shared data file and
+ are kept running (in idle loops watching the
+ shared data file). This saves us a few seconds
+ on each move since the 'rsh' need not be invoked
+ more than once (at the beginning). Since the
+ shared data file is now implemented, we will
+ next work towards a "parallel anarchy" in which
+ any processor can use any other processor in
+ order to reduce its search. The current scheme
+ with the program being only as fast as its slowest
+ processor, is quite inefficient.
+
+December 1, 1986 -- Jim Aspnes at MIT
+ Added a couple of Master games from
+ Modern Chess Openings 12 (a Fischer game,
+ and a Matanovic game).
+
+November 30, 1986 -- Stuart Cracraft
+ Added parallelism. Can now handle multiple
+ processors (sharing same disk). Later we will
+ add the capability to use processors not sharing
+ the same disk. Modified README and MAN-PAGE.
+
+November 26, 1986 -- Stuart Cracraft
+ Fixed a few bugs in book-mailing mechanism.
+ Fixed a bug regarding situations where only
+ one move is available.
+ Fixed a bug in read_history() that caused
+ Black queenside castles to be mishandled.
+
+November 25, 1986 -- Stuart Cracraft
+ Added two pawn heuristics. Reward pawns moving into
+ a phalanx of pawns. A phalanx is two or more
+ horizontally-connected pawns. Likewise, penalize
+ pawns leaving a phalanx of pawns. The penalty for
+ leaving is a little more than the reward for
+ entering.
+
+November 24, 1986 -- Stuart Cracraft
+ A user reported an unbelievable bug. Investigation
+ of this bug led to the discovery that GNU Chess was
+ not picking the move judged best by the tree search
+ in all cases. This resulted in the bug showing
+ itself which further showed that the program was
+ selecting an inferior move. This may result in an
+ improvement to the program's play.
+
+November 24, 1986 -- Stuart Cracraft
+ Added two heuristics. Penalize king moves if
+ the king hasn't castled yet. Also, penalize pawn
+ moves which produce doubled pawns. Should
+ probably have something for isolated pawns
+ too.
+
+November 23, 1986 -- Wayne Christopher at Berkeley
+ New version of X chess display front-end.
+ Fixed bugs include multiple pieces, runs
+ on SUNS & Bobcats, loads saved games.
+
+November 23, 1986 -- Stuart Cracraft
+ Cleaned up some minor bugs regarding history.
+ Added "Illegal command" error message at Wayne's
+ request.
+
+November 22, 1986 -- David Goldberg at SUN Microsystems
+ He complained that GNU Chess was memory-hungry.
+ A few minor modifications to hash.c reduced
+ uninitialized data space 87% and text space
+ 12%. This should make it easier for GNU Chess
+ to run on small computers.
+
+November 22, 1986 -- Stuart Cracraft
+ "read" command was working, but needed
+ additional tweaking so that history
+ array would be printed by list_history().
+
+November 19, 1986 -- Stuart Cracraft
+ Added "read" command which reads a history
+ file (game listing) and restores the board
+ to as if the person was still playing that.
+ particular game. Generally cleaned up
+ history mechanism, made it more orthogonal.
+ Revised README. Added doc to MAN-PAGE.
+
+November 16, 1986 -- Stuart Cracraft
+ More opening book bugs found and fixed.
+ Added capability to accept abbreviated-algebraic notation
+ for entering "book" games from files.
+ Added approximately 2500 new positions to
+ opening book from games involving the
+ opening called Blackmar-Diemer Gambit,
+ a hoary line developed by Diemer in
+ Germany years ago.
+
+November 15, 1986 -- Wayne Christopher at Berkeley
+ He modified the move generator, resulting in
+ a 28% speedup.
+
+November 14, 1986 -- Stuart Cracraft
+ He documented a lot of the GNU Chess modules
+ with brief comments for each function. More
+ extensive internal documentation may go in
+ later.
+
+November 14, 1986 -- Wayne Christopher at Berkeley
+ He created the Xchess interface for
+ GNU Chess to have windowing with X windows.
+
+November 14, 1986 -- Stuart Cracraft
+ He added a "randomization" feature to
+ the opening book. This will cause the
+ program to select randomly from alternate
+ variations whenever -DBEST is removed
+ from Makefile's CFLAGS. If this is not
+ removed, the opening play selects the
+ first move found in the book as it appears
+ "in order" in the human-readable book.
+
+November 14, 1986 -- David Goldberg at SUN Microsystems
+ He responded to a query about dbm(3) which
+ eventually resulted in the fixing of a subtle
+ bug in the book code which was causing the
+ program to sometimes hash to the incorrect
+ address and thereby produce a book move which
+ didn't even exist in the book. Thanks David!
+
+November 14, 1986 -- Stuart Cracraft
+ He added the "oboard" routine in util.c. This
+ is the reverse of the already extant "iboard"
+ (same module). These two routines translate
+ between GNU Chess internal format and
+ Forsythe notation.
+
+November 10, 1986 -- Stuart Cracraft
+ He added the "enter" command. This causes
+ the current game to be entered in the book.
+ Then, GNU Chess tries to mail this new entry
+ to the book maintainers (for inclusion in
+ the master copy of the book).
+
+November 9, 1986 -- Stuart Cracraft
+He added code for an opening book. MAN-PAGE
+and README were modified accordingly.
+
+November 8, 1986 -- Stuart Cracraft
+Checks and mates are now noticed at ply-1.
+This is a more complete fix to the Oct 31 fix.
+
+October 31, 1986 -- Stuart Cracraft
+First attempt at fix to bug which causes
+program to check human's king when program
+itself is in check.
+
+October 31, 1986 -- Mly at MIT
+Reported a bug which caused program to crash
+when an illegal human move was played. Fixed.
+Also, program was unable to play as White. Fixed.
+
+October 22, 1986 -- Stuart Cracraft
+Pps now rewards moves which liberate bishops.
+
+October 19, 1986 -- Stuart Cracraft
+Added bitmapper routines to distribution.
+Added version notice.
+
+October 19, 1986 -- David Goldberg at SUN Microsystems
+Interfaced GNU Chess with SUN's chesstool.
+
+October 18, 1986 -- Initial release date.
+
+
diff --git a/gnu/games/chess/DOCUMENTATION/COPYING b/gnu/games/chess/DOCUMENTATION/COPYING
new file mode 100644
index 000000000000..17847b71307f
--- /dev/null
+++ b/gnu/games/chess/DOCUMENTATION/COPYING
@@ -0,0 +1,123 @@
+ GNU CHESS GENERAL PUBLIC LICENSE
+
+ Copyright (C) 1986,1987 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license, but changing it is not allowed.
+
+ The license agreements of most software companies keep you at the
+mercy of those companies. By contrast, our general public license is
+intended to give everyone the right to share GNU Chess. To make
+sure that you get the rights we want you to have, we need to make
+restrictions that forbid anyone to deny you these rights or to ask you
+to surrender the rights. Hence this license agreement.
+
+ Specifically, we want to make sure that you have the right to give
+away copies of GNU Chess, that you receive source code or else can get it
+if you want it, that you can change GNU Chess or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To make sure that everyone has such rights, we have to forbid you to
+deprive anyone else of these rights. For example, if you distribute
+copies of GNU Chess, you must give the recipients all the rights that you
+have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ Also, for our own protection, we must make certain that everyone
+finds out that there is no warranty for GNU Chess. If GNU Chess is
+modified by someone else and passed on, we want its recipients to know
+that what they have is not what we distributed, so that any problems
+introduced by others will not reflect on our reputation.
+
+ Therefore the Free Software Foundation, Inc. makes the following
+terms which say what you must do to be allowed to distribute or change
+GNU Chess.
+
+ COPYING POLICIES
+
+ 1. You may copy and distribute verbatim copies of GNU Chess source
+code as you receive it, in any medium, provided that you conspicuously
+and appropriately publish on each file a valid copyright notice
+"Copyright (C) 1986,1987 Free Software Foundation, Inc.", containing the
+year of last change for the file in question; keep intact the notices
+on all files that refer to this License Agreement and to the absence
+of any warranty; and give any other recipients of the GNU Chess
+program a copy of this License Agreement along with the program.
+
+ 2. You may modify your copy or copies of GNU Chess source code or
+any portion of it, and copy and distribute such modifications under
+the terms of Paragraph 1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating
+ who last changed such files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish,
+ that in whole or in part contains or is a derivative of GNU Chess
+ or any part thereof, to be freely distributed
+ and licensed to all third parties on terms identical to those
+ contained in this License Agreement (except that you may choose
+ to grant more extensive warranty protection to third parties,
+ at your option).
+
+ c) if the modified program serves as a text editor, cause it
+ when started running in the simplest and usual way, to print
+ an announcement including a valid copyright notice ("Copyright
+ (C)", the year of authorship, and all copyright owners' names),
+ saying that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of
+ this License Agreement.
+
+ 3. You may copy and distribute GNU Chess or any portion of it in
+compiled, executable or object code form under the terms of Paragraphs
+1 and 2 above provided that you do the following:
+
+ a) cause each such copy of GNU Chess to be accompanied by the
+ corresponding machine-readable source code; or
+
+ b) cause each such copy of GNU Chess to be accompanied by a
+ written offer, with no time limit, to give any third party
+ free (except for a nominal shipping charge) machine readable
+ copy of the corresponding source code; or
+
+ c) in the case of a recipient of GNU Chess in compiled, executable
+ or object code form (without the corresponding source code) you
+ shall cause copies you distribute to be accompanied by a copy
+ of the written offer of source code which you received along
+ with the copy of GNU Chess.
+
+ 4. You may not copy, sublicense, distribute or transfer GNU Chess
+except as expressly provided under this License Agreement. Any attempt
+otherwise to copy, sublicense, distribute or transfer GNU Chess is void and
+your rights to use GNU Chess under this License agreement shall be
+automatically terminated. However, parties who have received computer
+software programs from you with this License Agreement will not have
+their licenses terminated so long as such parties remain in full compliance.
+
+Your comments and suggestions about our licensing policies and our
+software are welcome! Please contact the Free Software Foundation, Inc.,
+1000 Mass Ave, Cambridge, MA 02138, or call (617) 876-3296.
+
+ NO WARRANTY
+
+ BECAUSE GNU CHESS IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
+NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
+WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
+AND/OR OTHER PARTIES PROVIDE GNU CHESS "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE GNU CHESS PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL FREE SOFTWARE
+FOUNDATION, INC., AND/OR ANY OTHER PARTY WHO MAY MODIFY AND
+REDISTRIBUTE GNU CHESS AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
+DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL,
+INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
+BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
+FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
+FREE SOFTWARE FOUNDATION, INC.) THE PROGRAM, EVEN IF YOU HAVE BEEN
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY
+OTHER PARTY.
+======================================================================
diff --git a/gnu/games/chess/DOCUMENTATION/GENERAL b/gnu/games/chess/DOCUMENTATION/GENERAL
new file mode 100644
index 000000000000..aafb7ed335e3
--- /dev/null
+++ b/gnu/games/chess/DOCUMENTATION/GENERAL
@@ -0,0 +1,34 @@
+ GNU Chess
+
+Copyright (C) 1987 Stuart Cracraft
+ (Copying permission notice at the end.)
+
+GNU Chess is your program (as long as you follow the copyright and
+licensing rules listed in the file COPYING). Your contributioinspire current and future software
+developers.
+
+This document
+-------------
+This document is not meant to be a an introduction to computer chess.
+The following books are excellent introductions and treatises.
+They are listed in order of difficulty:
+
+ Computer Chess (2nd edition), by David Welsh and Boris Bazcynski
+ The Joy of Computer Chess, by David Levy
+ Chess Skill in Man and Machine (2nd edition), by Peter Frey
+
+
+Current Distribution
+--------------------
+The most recent distribution of GNU Chess contains the following
+main-level files and directories:
+
+ Filename Purpose
+ ------------------------------------------------------
+ README Pointer to main README below.
+ gnuchess.c Most recent version of GNU Chess
+ nondsp.c Non-display interface, and chesstool/xchess interface
+ uxdsp.c Unix (curses) display interface
+ ansidsp.c ANSI display interface
+ gnuchess.book Most recent version of opening book
+
diff --git a/gnu/games/chess/DOCUMENTATION/HEURISTICS b/gnu/games/chess/DOCUMENTATION/HEURISTICS
new file mode 100644
index 000000000000..254b34472abe
--- /dev/null
+++ b/gnu/games/chess/DOCUMENTATION/HEURISTICS
@@ -0,0 +1,122 @@
+This file contains a description of GNU's heuristics.
+ Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+
+This file is part of CHESS.
+
+CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+CHESS, but only under the conditions described in the
+CHESS General Public License. A copy of this license is
+supposed to have been given to you along with CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+ -- requested by main author
+Heuristic descriptions for CHESS.
+
+Revision: 12-16-87
+
+Copyright (c) 1987 by John Stanback
+
+ Here is a brief description of the heuristics used in the positional
+ evaluator of the GNU Chess program. Many heuristics are functions of the
+ stage of the game which is based on the total non-pawn material remaining
+ for both sides.
+
+
+PAWNS
+ The material value of a pawn is 100 points. Isolated pawns get a
+ penalty depending on which file they occupy:
+ (12,14,16,20,20,16,14,12) for files (a..h).
+ Doubled pawns (which are not also isolated) get a penalty of 12
+ points. Backward pawns (defined simply as not being defended by a
+ pawn with the square in front also not defended by a a pawn) are
+ penalized 6 points. A 4 point penalty is also invoked for each attack
+ by the opponent to a backward pawn and for a backward pawn on a
+ half-open file. Pawn Advancement in the centre is given a bonus of
+ about 4 points per rank in the opening increasing to about 8 points
+ per rank in the ending. Advancement on the edges is given a lower
+ bonus. Pawns on the e and d files and on the 2nd rank are given a 10
+ point penalty. An additional penalty of 15 points is invoked if these
+ pawns are also blocked. Pawns within 2 squares of the king are given
+ a 10 point bonus. Passed pawns are given a bonus for increasing rank
+ which is a function of stage of the game and of whether the opponent
+ blocks or attacks one or more squares in front of the pawn or if the
+ opponents king is in the square of the pawn. This bonus ranges from
+ about 15 points for a pawn on the second rank up to about 300 points
+ for a passed pawn on the 7th rank which can't be stopped from
+ queening.
+
+
+KNIGHTS
+ The material value of a knight is 330 points. The main heuristic for
+ knights is a bonus for proximity to the centre. This varies from 0
+ points in the corners to 30 points in the centre. Knights are also
+ given a bonus for being within 2 squares of each enemy piece. This
+ bonus is a function of the stage of the game, equalling 4 points in
+ the end game. A penalty of 1 point per square is given for distance
+ from either king. A bonus of up to 8 points (depends on stage) is
+ given for knights which can't be driven away by enemy pawns.
+
+
+BISHOPS
+ The material value of a bishop is 330 points. Bishops are given a
+ bonus as material falls off the board equalling 10 points in the end
+ game. Bishops get a bonus for mobility and Xray mobility thru pieces
+ but not pawns. This bonus ranges from -4 points for a totally blocked
+ bishop up to 18 points for a bishop attacking 12 or more squares.
+ Xray attacks on an enemy R,Q,K or any undefended piece are given an 8
+ point bonus. Bishops are given a bonus of 14 points if they lie on
+ the edge of the board up to 22 points if the lie in the centre. A
+ bishop is given a bonus of up to 5 points for each attack to a square
+ adjacent to the enemy king.
+
+
+ROOKS
+ The material value of a rook is 520 points. Rook mobility is handled
+ similiarly to bishops with a bonus of 0 points if blocked up to 20
+ points if attacking 12 squares or more. A bonus of 8 points for Xray
+ attacks is handled as it is for bishops. Rooks are given a bonus of
+ 10 points for occupying a file with no friendly pawns and a bonus of
+ 4 points if no enemy pawns lie on that file. After the opening Rooks
+ are penalized slightly depending on "taxicab" distance to the enemy
+ king.
+
+
+QUEENS
+ The material value of a queen is 980 points. The only heuristic for a
+ queen is that after the opening it is penalized slightly for
+ "taxicab" distance to the enemy king.
+
+
+KINGS
+ Kings are given a penalty for proximity to the centre in the opening
+ and a bonus for proximity to the centre in the endgame. The penalty
+ is about 24 points for being in the centre in the opening with a
+ bonus of about 36 points for being in the centre in the endgame.
+ Kings are penalized for lying on an open or half-open file or if the
+ adjacent file closest to the corner is open or half-open. This
+ penalty is up to 23 points in the opening and goes to zero in the end
+ game. The King is penalized up to 8 points if there are no pawns
+ immediately adjacent. A penalty is invoked depending on the number of
+ "safe" checks available by the opponent. This penalty ranges from 6
+ points for one such check to 50 points for 4 or more. Depending on
+ game stage, Kings are given up to 10 points for castling and a
+ penalty of up to 40 points for moving before castling.
+
+
+SPECIAL
+ If more than one piece is "hung" (attacked and not defended or
+ attacked by an enemy piece of lower value) an extra penalty of 10
+ points is invoked for that side and the search may be extended one
+ ply. Pinned or trapped pieces are treated similarly. A special mating
+ routine is used if one side has only a king and the other has mating
+ material.
+
diff --git a/gnu/games/chess/DOCUMENTATION/MAN-PAGE b/gnu/games/chess/DOCUMENTATION/MAN-PAGE
new file mode 100644
index 000000000000..bbf0aa4abf98
--- /dev/null
+++ b/gnu/games/chess/DOCUMENTATION/MAN-PAGE
@@ -0,0 +1,161 @@
+.TH Chess GNU
+.SH NAME
+Chess \- GNU Chess
+.SH SYNOPSIS
+.B Chess
+[
+.B arg1 arg2
+]
+.SH DESCRIPTION
+.I Chess
+plays a game of chess against the user or it plays against itself.
+.PP
+.I Chess
+has a simple alpha-numeric board display or it can be compiled for
+use with the CHESSTOOL program on a SUN workstation.
+The program gets its opening moves from the file gnuchess.book which
+should be located in the same directory as gnuchess.
+To invoke the prgram, type 'gnuchess' or type 'chesstool gnuchess'
+on a SUN workstation where 'CHESSTOOL' is installed.
+The 'gnuchess' command can be followed by up to 2 command line arguments.
+If one argument is given it determines the programs search time in
+seconds. If two arguments are given, they will be used to set tournament
+time controls with the first argument being the number of moves and the second
+being the total clock time in minutes. Thus, entering 'chess 60 5' will set
+the clocks for 5 minutes (300 seconds) for the first 60 moves.
+If no argument is given the program will prompt the user for level of
+play.
+For use with CHESSTOOL, see the documentation on that program.
+.PP
+Once
+.I Chess
+is invoked, the program will display the board and prompt the user
+for a move. To enter a move, use the notation 'e2e4' where the first
+letter-number pair indicates the origination square
+and the second letter-number pair indicates the destination square.
+An alternative is to use the notation 'nf3' where
+the first letter indicates the piece type (p,n,b,r,q,k).
+To castle, type the origin and destination squares
+of the king just as you would do for a regular move, or type
+"o-o" for kingside castling and "o-o-o" for queenside.
+.SH COMMANDS
+.PP
+In addition to legal moves, the following commands are available as responses.
+.PP
+.I beep
+-- causes the program to beep after each move.
+.PP
+.I bd
+-- updates the current board position on the display.
+.PP
+.I book
+-- turns off use of the opening library.
+.PP
+.I both
+-- causes the computer to play both sides of a chess game.
+.PP
+.I black
+-- causes the computer to take the black pieces with the move
+and begin searching.
+.PP
+.I level
+-- allows the user to set time controls such as
+60 moves in 5 minutes etc. In tournament mode, the program will
+vary the time it takes for each
+move depending on the situation. If easy mode is disabled (using
+the 'easy' command), the program
+will often respond with its move immediately, saving time on
+its clock for use later on.
+.PP
+.I depth
+-- allows the user to change the
+search depth of the program. The maximum depth is 29 ply.
+Normally the depth is set to 29 and the computer terminates
+its search based on elapsed time rather than depth.
+Using the depth command allows setting depth to say
+4 ply and setting response time to a large number such as
+9999 seconds. The program will then search until all moves
+have been examined to a depth of 4 ply (with extensions up
+to 11 additional ply for sequences of checks and captures).
+.PP
+.I easy
+-- toggles easy mode (thinking on opponents time)
+on and off. The default is easy mode ON. If easy mode is disabled,
+the user must enter a 'break' or '^C' to get the programs
+attention before entering each move.
+.PP
+.I edit
+-- allows the user to set up a board position.
+In this mode, the '#' command will clear the board, the 'c'
+command will toggle piece color, and the '.' command will exit
+setup mode. Pieces are entered by typing a letter (p,n,b,r,q,k) for
+the piece followed by the coordinate. For example "pb3" would
+place a pawn on square b3.
+.PP
+.I force
+-- allows the user to enter moves for both
+sides. To get the program to play after a sequence of moves
+has been entered use the 'white' or 'black' commands.
+.PP
+.I get
+-- retrieves a game from disk. The program will
+prompt the user for a file name.
+.PP
+.I help
+-- displays a short description of the commands.
+.PP
+.I hint
+-- causes the program to supply the user with
+its predicted move.
+.PP
+.I list
+-- writes the game moves and some statistics
+on search depth, nodes, and time to the file 'chess.lst'.
+.PP
+.I new
+-- starts a new game.
+.PP
+.I post
+-- causes the program to display the principle
+variation and the score during the search. A score of
+100 is equivalent to a 1 pawn advantage for the computer.
+.PP
+.I random
+-- causes the program to randomize its move
+selection slightly.
+.PP
+.I reverse
+-- causes the board display to be reversed. That
+is, the white pieces will now appear at the top of the board.
+.PP
+.I quit
+-- exits the game.
+.PP
+.I save
+-- saves a game to disk. The program will prompt
+the user for a file name.
+.PP
+.I switch
+-- causes the program to switch places with
+the opponent and begin searching.
+.PP
+.I undo
+-- undoes the last move whether it was the computer's
+or the human's. You may also type "remove". This is equivalent
+to two "undo's" (e.g. retract one move for each side).
+.PP
+.I white
+-- causes the computer to take the white pieces
+with the move and begin searching.
+.SH BUGS
+.PP
+Pawn promotion to pieces other than a queen is not allowed.
+En-Passant does not work properly with CHESSTOOOL.
+The transposition table may not work properly in some
+positions so the default is to turn this off.
+.fi
+.SH SEE ALSO
+.nf
+chesstool(6)
+.fi
+
diff --git a/gnu/games/chess/Makefile b/gnu/games/chess/Makefile
new file mode 100644
index 000000000000..d5fa6f48f53c
--- /dev/null
+++ b/gnu/games/chess/Makefile
@@ -0,0 +1,15 @@
+# @(#)Makefile 5.4 (Berkeley) 5/11/90
+
+PROG= chess
+SRCS= gnuchess.c uxdsp.c move.c
+CFLAGS+=-DNEWMOVE=12
+MAN6= chess.0
+DPADD= ${LIBCURSES} ${LIBTERM}
+LDADD= -lcurses -ltermlib
+HIDEGAME=hidegame
+
+beforeinstall:
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/gnuchess.book \
+ ${DESTDIR}/usr/share/games
+
+.include <bsd.prog.mk>
diff --git a/gnu/games/chess/Xchess/COPYING b/gnu/games/chess/Xchess/COPYING
new file mode 100644
index 000000000000..5905c3292de1
--- /dev/null
+++ b/gnu/games/chess/Xchess/COPYING
@@ -0,0 +1,124 @@
+
+ GNU X-CHESS GENERAL PUBLIC LICENSE
+
+ Copyright (C) 1986 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license, but changing it is not allowed.
+
+ The license agreements of most software companies keep you at the
+mercy of those companies. By contrast, our general public license is
+intended to give everyone the right to share GNU X-Chess. To make
+sure that you get the rights we want you to have, we need to make
+restrictions that forbid anyone to deny you these rights or to ask you
+to surrender the rights. Hence this license agreement.
+
+ Specifically, we want to make sure that you have the right to give
+away copies of GNU X-Chess, that you receive source code or else can get it
+if you want it, that you can change GNU X-Chess or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To make sure that everyone has such rights, we have to forbid you to
+deprive anyone else of these rights. For example, if you distribute
+copies of GNU X-Chess, you must give the recipients all the rights that you
+have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ Also, for our own protection, we must make certain that everyone
+finds out that there is no warranty for GNU X-Chess. If GNU X-Chess is
+modified by someone else and passed on, we want its recipients to know
+that what they have is not what we distributed, so that any problems
+introduced by others will not reflect on our reputation.
+
+ Therefore the Free Software Foundation, Inc. makes the following
+terms which say what you must do to be allowed to distribute or change
+GNU X-Chess.
+
+ COPYING POLICIES
+
+ 1. You may copy and distribute verbatim copies of GNU X-Chess source
+code as you receive it, in any medium, provided that you conspicuously
+and appropriately publish on each file a valid copyright notice
+"Copyright (C) 1986 Free Software Foundation, Inc.", containing the
+year of last change for the file in question; keep intact the notices
+on all files that refer to this License Agreement and to the absence
+of any warranty; and give any other recipients of the GNU X-Chess
+program a copy of this License Agreement along with the program.
+
+ 2. You may modify your copy or copies of GNU X-Chess source code or
+any portion of it, and copy and distribute such modifications under
+the terms of Paragraph 1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating
+ who last changed such files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish,
+ that in whole or in part contains or is a derivative of GNU X-Chess
+ or any part thereof, to be freely distributed
+ and licensed to all third parties on terms identical to those
+ contained in this License Agreement (except that you may choose
+ to grant more extensive warranty protection to third parties,
+ at your option).
+
+ c) if the modified program serves as a text editor, cause it
+ when started running in the simplest and usual way, to print
+ an announcement including a valid copyright notice ("Copyright
+ (C)", the year of authorship, and all copyright owners' names),
+ saying that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of
+ this License Agreement.
+
+ 3. You may copy and distribute GNU X-Chess or any portion of it in
+compiled, executable or object code form under the terms of Paragraphs
+1 and 2 above provided that you do the following:
+
+ a) cause each such copy of GNU X-Chess to be accompanied by the
+ corresponding machine-readable source code; or
+
+ b) cause each such copy of GNU X-Chess to be accompanied by a
+ written offer, with no time limit, to give any third party
+ free (except for a nominal shipping charge) machine readable
+ copy of the corresponding source code; or
+
+ c) in the case of a recipient of GNU X-Chess in compiled, executable
+ or object code form (without the corresponding source code) you
+ shall cause copies you distribute to be accompanied by a copy
+ of the written offer of source code which you received along
+ with the copy of GNU X-Chess.
+
+ 4. You may not copy, sublicense, distribute or transfer GNU X-Chess
+except as expressly provided under this License Agreement. Any attempt
+otherwise to copy, sublicense, distribute or transfer GNU X-Chess is void and
+your rights to use GNU X-Chess under this License agreement shall be
+automatically terminated. However, parties who have received computer
+software programs from you with this License Agreement will not have
+their licenses terminated so long as such parties remain in full compliance.
+
+Your comments and suggestions about our licensing policies and our
+software are welcome! Please contact the Free Software Foundation, Inc.,
+1000 Mass Ave, Cambridge, MA 02138, or call (617) 876-3296.
+
+ NO WARRANTY
+
+ BECAUSE GNU X-CHESS IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
+NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
+WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
+AND/OR OTHER PARTIES PROVIDE GNU X-CHESS "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE GNU X-CHESS PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL FREE SOFTWARE
+FOUNDATION, INC., AND/OR ANY OTHER PARTY WHO MAY MODIFY AND
+REDISTRIBUTE GNU X-CHESS AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
+DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL,
+INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
+BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
+FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
+FREE SOFTWARE FOUNDATION, INC.) THE PROGRAM, EVEN IF YOU HAVE BEEN
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY
+OTHER PARTY.
+======================================================================
diff --git a/gnu/games/chess/Xchess/Makefile b/gnu/games/chess/Xchess/Makefile
new file mode 100644
index 000000000000..c6afd8ffb3f2
--- /dev/null
+++ b/gnu/games/chess/Xchess/Makefile
@@ -0,0 +1,136 @@
+# RCS Info: $Revision: 1.5 $ on $Date: 86/11/26 12:09:19 $
+# $Source: /users/faustus/xchess/RCS/Makefile,v $
+# Copyright (c) 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
+#
+# Makefile for xchess.
+
+#CC = cc -O -m68010 -L/pub.MC68010/lib -L/usr.MC68010/lib
+CC = cc -O
+
+CFILES =\
+ board.c\
+ button.c\
+ clock.c\
+ control.c\
+ jail.c\
+ message.c\
+ parse.c\
+ popup.c\
+ program.c\
+ record.c\
+ std.c\
+ valid.c\
+ window.c\
+ XCircle.c
+
+COBJS =\
+ board.o\
+ button.o\
+ clock.o\
+ control.o\
+ jail.o\
+ message.o\
+ parse.o\
+ popup.o\
+ program.o\
+ record.o\
+ std.o\
+ valid.o\
+ window.o\
+ XCircle.o
+
+HFILES =\
+ std.h\
+ xchess.h
+
+SOURCE = $(CFILES)
+
+ALLFILES = $(SOURCE) $(HFILES)
+
+INCLUDE = -I.
+
+DEFINES = -DDEF_PROGRAM=\"gnuchess\"
+
+CFLAGS = $(DEFINES) $(INCLUDE)
+LINTFLAGS = -u -z -lc -DLINT $(DEFINES) $(INCLUDE)
+LINTLIB = ../lib/llib-lX.ln
+#LDFLAGS = -L/usr2/X/lib -z -lX -lm
+LDFLAGS = -loldX -lX11 -z -lX -lm
+GPLDFLAGS = -z -loldX -lX11 -lXMenu_p -lX -lm_p -g -pg
+
+.c.o: $*.c
+ $(CC) $(CFLAGS) -c $*.c
+.s.o: $*.s
+ $(CC) $(CFLAGS) -c $*.s
+
+all: xchess scrollText.o
+ @echo "All done."
+
+everything: all tags depend lint wc
+ @echo "All done."
+
+xchess: xchess.o $(COBJS) scrollText.o
+ $(CC) -o xchess xchess.o $(COBJS) scrollText.o \
+ $(LDFLAGS)
+
+scrollText.o: scrollText.h scrollText.c
+
+gpxchess: xchess.o $(COBJS)
+ $(CC) -o gpxchess xchess.o $(COBJS) scrollText/libScroll.a \
+ $(GPLDFLAGS)
+
+lint: $(SOURCE)
+ lint $(LINTFLAGS) $(SOURCE) $(LINTLIB) | \
+ grep -v "multiply declared"
+
+qgrind: $(ALLFILES)
+ qgrind -lc $(ALLFILES)
+
+vgrind: $(ALLFILES)
+ vgrind -lc $(ALLFILES)
+
+opt: all
+
+reopt: all
+
+install: all
+
+source: $(SOURCE)
+
+tags: $(ALLFILES)
+ ctags -w -t *.c *.h > /dev/null 2>&1
+
+wc: $(ALLFILES)
+ @wc $(ALLFILES)
+
+print: $(ALLFILES)
+ @pr $(ALLFILES)
+
+clean:
+ rm -f *.o *.a *.out xchess tags foo tmp
+
+tar:
+ tar -cf xchess.tar Makefile *.h *.c *.bitmap *.icon *.cur *.1\
+ scrollText/Makefile scrollText/*.h scrollText/*.c scrollText/*.1\
+ scrollText/*.3
+
+$(ALLFILES):
+ co $@
+
+depend: $(SOURCE)
+ cc -M $(CFLAGS) $(CFILES) > makedep
+ echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
+ echo '$$r makedep' >>eddep
+ echo 'w' >>eddep
+ ed - Makefile < eddep
+ rm eddep makedep
+ echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile
+ echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile
+ echo '# see make depend above' >> Makefile
+
+#-----------------------------------------------------------------
+# DO NOT DELETE THIS LINE -- make depend uses it
+# DEPENDENCIES MUST END AT END OF FILE
+
+xchess.o $(COBJS): $(HFILES)
+
diff --git a/gnu/games/chess/Xchess/ScrollText b/gnu/games/chess/Xchess/ScrollText
new file mode 100644
index 000000000000..782a54f48548
--- /dev/null
+++ b/gnu/games/chess/Xchess/ScrollText
@@ -0,0 +1,34 @@
+Subject: File: scrollText.h
+
+/*
+ * Scrollable Text Window Header File
+ *
+ * David Harrison
+ * University of California, Berkeley
+ * 1986
+ *
+ * This file contains definitions for a scrollable text window
+ * with scroll bar support.
+ */
+
+int TxtGrab();
+ /* Take hold of a previously created window */
+
+#define TXT_NO_COLOR -1
+
+int TxtAddFont();
+ /* Loads a new font for use later */
+int TxtWinP();
+ /* Returns non-zero value if the window is text window */
+int TxtClear();
+ /* Clears text window and resets text buffer */
+
+int TxtWriteStr();
+ /* Writes a string to window with immediate update */
+int TxtJamStr();
+ /* Write a string without causing update to screen */
+
+int TxtRepaint();
+ /* Repaints entire scrollable text window */
+int TxtFilter();
+ /* Handles events related to text window */
diff --git a/gnu/games/chess/Xchess/XCircle.c b/gnu/games/chess/Xchess/XCircle.c
new file mode 100644
index 000000000000..d2144bcab849
--- /dev/null
+++ b/gnu/games/chess/Xchess/XCircle.c
@@ -0,0 +1,162 @@
+
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.2 $ on $Date: 86/11/23 17:17:04 $
+ * $Source: /users/faustus/xchess/RCS/XCircle.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ *
+ */
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/X10.h>
+#include <math.h>
+
+#define PI 3.1415926535897932384
+
+#define MAXVERTS 1000
+
+void
+XCircle(win, x, y, rad, start, end, width, height, pixel, func, planes)
+ Window win;
+ int x, y, rad;
+ double start, end;
+ int pixel;
+ int width, height;
+ int func, planes;
+{
+ Vertex verts[MAXVERTS];
+ double xp, yp, ang;
+ int lx, ly, xpt, ypt, i;
+ double gradincr = 2 / (double) rad;
+ int bk = 0;
+
+ while (end >= PI * 2)
+ end -= PI * 2;
+ while (start >= PI * 2)
+ start -= PI * 2;
+ while (end < 0)
+ end += PI * 2;
+ while (start < 0)
+ start += PI * 2;
+ if (end == start) {
+ if (end < gradincr)
+ end = end + PI * 2 - gradincr / 2;
+ else
+ end -= gradincr / 2;
+ }
+ for (ang = start, i = 0; i < MAXVERTS; ) {
+
+ xp = x + rad * cos(ang);
+ yp = y + rad * sin(ang);
+
+ xpt = xp;
+ ypt = yp;
+
+ if (!i || (lx != xpt) || (ly != ypt)) {
+ verts[i].x = xpt;
+ verts[i].y = ypt;
+ verts[i].flags = 0;
+ i++;
+ }
+ lx = xpt;
+ ly = ypt;
+ if (bk)
+ break;
+ if (((ang < end) && (ang + gradincr > end)) || ((end < start)
+ && (ang + gradincr > 2 * PI)
+ && (ang + gradincr - 2 * PI > end))) {
+ ang = end;
+ bk = 1;
+ } else if (ang == end) {
+ break;
+ } else {
+ ang += gradincr;
+ }
+ if (ang >= PI * 2)
+ ang -= PI * 2;
+ }
+
+ /* Now draw the thing.. */
+ XDraw(win, verts, i, width, height, pixel, func, planes);
+
+ return;
+}
+
+#ifdef notdef VertexCurved is screwed up
+
+void
+XCircle(win, x, y, rad, start, end, width, height, pixel, func, planes)
+ Window win;
+ int x, y, rad;
+ double start, end;
+ int pixel;
+ int width, height;
+ int func, planes;
+{
+ Vertex verts[7];
+ int i, j, sv, ev;
+ int dp = 0;
+
+ for (i = j = 0 ; i < 4; i++) {
+ verts[j].x = x + rad * cos((double) (PI * i / 2));
+ verts[j].y = y + rad * sin((double) (PI * i / 2));
+ verts[j].flags = VertexCurved;
+ if ((start >= PI * i / 2) && (start < PI * (i + 1) / 2) &&
+ (start != end)) {
+ j++;
+ verts[j].x = x + rad * cos(start);
+ verts[j].y = y + rad * sin(start);
+ verts[j].flags = VertexCurved;
+ sv = j;
+ } else if ((end >= PI * i / 2) && (end < PI * (i + 1) / 2)
+ && (start != end)) {
+ j++;
+ verts[j].x = x + rad * cos(end);
+ verts[j].y = y + rad * sin(end);
+ verts[j].flags = VertexCurved;
+ ev = j;
+ }
+ j++;
+ }
+ verts[0].flags |= VertexStartClosed;
+ verts[j].x = verts[0].x;
+ verts[j].y = verts[0].y;
+ verts[j].flags = (verts[0].flags & ~VertexStartClosed) |
+ VertexEndClosed;
+ for (i = 0; i < 15; i++) {
+ if (dp)
+ verts[i % 7].flags |= VertexDontDraw;
+ if (i % 7 == ev)
+ dp = 1;
+ else if (i % 7 == sv)
+ dp = 0;
+ }
+ XDraw(win, verts, j + 1, width, height, pixel, func, planes);
+
+ return;
+}
+
+#endif notdef
+
diff --git a/gnu/games/chess/Xchess/bishop.bitmap b/gnu/games/chess/Xchess/bishop.bitmap
new file mode 100644
index 000000000000..dc068ddf1cfa
--- /dev/null
+++ b/gnu/games/chess/Xchess/bishop.bitmap
@@ -0,0 +1,71 @@
+
+#define bishop_width 80
+#define bishop_height 80
+static char bishop_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x8f,
+ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x8f, 0x0f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x8f, 0x0f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x0f, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x9f,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xf8, 0xff, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfc, 0xff, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
+ 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x23, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x67, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0xff, 0xf8, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x1f, 0xc0, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0xc0,
+ 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0xc0, 0x5f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xf8, 0x7f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0xff, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xe0, 0xff, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+ 0xff, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xf8,
+ 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xf8, 0x7f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xf8, 0xff, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xf0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff,
+ 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x3f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
+ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfe, 0xfd, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0xf8,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x70, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x70, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfa, 0xf8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfe, 0xfd, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xc0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f,
+ 0xfc, 0xfd, 0xc1, 0xff, 0x01, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xfd,
+ 0xff, 0xff, 0x07, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff,
+ 0x3f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0xc0, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x80,
+ 0x0f, 0xf0, 0x0f, 0xc0, 0x7f, 0x00, 0x1f, 0x00, 0x00, 0xc0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/bishop_mask.bitmap b/gnu/games/chess/Xchess/bishop_mask.bitmap
new file mode 100644
index 000000000000..ca17bb3dae0d
--- /dev/null
+++ b/gnu/games/chess/Xchess/bishop_mask.bitmap
@@ -0,0 +1,71 @@
+
+#define bishop_mask_width 80
+#define bishop_mask_height 80
+static char bishop_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x8f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0xdf, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xdf,
+ 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xdf, 0x1f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xdf, 0x1f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0xdf, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x8f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff,
+ 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x3f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x3f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfe, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xf0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xfc, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff,
+ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x7f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xe0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+ 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff,
+ 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x1f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
+ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x1f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xe0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+ 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfc, 0x3f, 0xfc, 0xff, 0xe3, 0xff, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x01, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0x01,
+ 0x00, 0xf8, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0x01, 0x00, 0xe0,
+ 0xff, 0xff, 0x7f, 0xf8, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf0, 0x1f, 0xf8,
+ 0x1f, 0xe0, 0xff, 0x80, 0xff, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/bishop_outline.bitmap b/gnu/games/chess/Xchess/bishop_outline.bitmap
new file mode 100644
index 000000000000..9772328c2984
--- /dev/null
+++ b/gnu/games/chess/Xchess/bishop_outline.bitmap
@@ -0,0 +1,71 @@
+
+#define bishop_outline_width 80
+#define bishop_outline_height 80
+static char bishop_outline_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x8d,
+ 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x88, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x8d, 0x0d, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x0f, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x98,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x70, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x40, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0xc0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x08, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x80, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80,
+ 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x22, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x66, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x01, 0x05, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0xe0, 0x3d, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x20,
+ 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe0, 0x3d, 0x50, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x05, 0x70, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x05, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x05, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x05, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x05,
+ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x05, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xc0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x07,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x8d, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x8d, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x02, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xc0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f,
+ 0x0c, 0x85, 0xc1, 0xff, 0x01, 0x00, 0x00, 0x00, 0x0e, 0xf0, 0x87, 0x0d,
+ 0x7f, 0x00, 0x07, 0x00, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x08, 0x00, 0x00,
+ 0x3c, 0x00, 0x00, 0x70, 0x00, 0x00, 0xe0, 0x18, 0x00, 0x00, 0xe0, 0x00,
+ 0x00, 0xc0, 0xf8, 0x1f, 0x38, 0x70, 0xc0, 0xff, 0x31, 0x00, 0x00, 0x80,
+ 0x0f, 0xf0, 0x0f, 0xc0, 0x7f, 0x00, 0x1f, 0x00, 0x00, 0xc0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/bishop_small.bitmap b/gnu/games/chess/Xchess/bishop_small.bitmap
new file mode 100644
index 000000000000..5525ecd03c2d
--- /dev/null
+++ b/gnu/games/chess/Xchess/bishop_small.bitmap
@@ -0,0 +1,15 @@
+
+#define bishop_small_width 32
+#define bishop_small_height 32
+static char bishop_small_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x00, 0x70, 0x1c, 0x00,
+ 0x00, 0x70, 0x1c, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x60, 0x16, 0x00,
+ 0x00, 0x60, 0x22, 0x00, 0x00, 0xf0, 0x23, 0x00, 0x00, 0xf0, 0x21, 0x00,
+ 0x00, 0xf8, 0x21, 0x00, 0x00, 0xf8, 0x23, 0x00, 0x00, 0xf8, 0x23, 0x00,
+ 0x00, 0xf8, 0x27, 0x00, 0x00, 0x38, 0x27, 0x00, 0x00, 0x3c, 0x2f, 0x00,
+ 0x00, 0x0c, 0x2c, 0x00, 0x00, 0x0e, 0x3c, 0x00, 0x00, 0x3e, 0x3f, 0x00,
+ 0x00, 0x3e, 0x3f, 0x00, 0x00, 0x3e, 0x3f, 0x00, 0x00, 0x3e, 0x3f, 0x00,
+ 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xfe, 0x7f, 0x00,
+ 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xfe, 0x7f, 0x00,
+ 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0xe0, 0xff, 0xff, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/bishop_small_outline.bitmap b/gnu/games/chess/Xchess/bishop_small_outline.bitmap
new file mode 100644
index 000000000000..8d29a812e29e
--- /dev/null
+++ b/gnu/games/chess/Xchess/bishop_small_outline.bitmap
@@ -0,0 +1,15 @@
+
+#define bishop_small_outline_width 32
+#define bishop_small_outline_height 32
+static char bishop_small_outline_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x00, 0x50, 0x14, 0x00,
+ 0x00, 0x70, 0x1c, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x60, 0x16, 0x00,
+ 0x00, 0x60, 0x22, 0x00, 0x00, 0xf0, 0x23, 0x00, 0x00, 0x10, 0x21, 0x00,
+ 0x00, 0x18, 0x21, 0x00, 0x00, 0x08, 0x23, 0x00, 0x00, 0x08, 0x22, 0x00,
+ 0x00, 0x08, 0x26, 0x00, 0x00, 0x08, 0x24, 0x00, 0x00, 0xcc, 0x2c, 0x00,
+ 0x00, 0xc4, 0x28, 0x00, 0x00, 0xf6, 0x3b, 0x00, 0x00, 0xf2, 0x23, 0x00,
+ 0x00, 0xc2, 0x20, 0x00, 0x00, 0xc2, 0x20, 0x00, 0x00, 0xc2, 0x20, 0x00,
+ 0x00, 0xc2, 0x60, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00,
+ 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00,
+ 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0xe0, 0xff, 0xff, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/board.c b/gnu/games/chess/Xchess/board.c
new file mode 100644
index 000000000000..4c5b9347d8e6
--- /dev/null
+++ b/gnu/games/chess/Xchess/board.c
@@ -0,0 +1,179 @@
+
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/23 17:17:15 $
+ * $Source: /users/faustus/xchess/RCS/board.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ *
+ * Stuff to deal with the board.
+ */
+
+#include "xchess.h"
+
+board *chessboard;
+
+void
+board_setup()
+{
+ chessboard = alloc(board);
+ board_init(chessboard);
+ return;
+}
+
+void
+board_init(b)
+ board *b;
+{
+ int i, j;
+
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < SIZE; j++)
+ b->square[i][j].color = BLACK;
+ for (i = 2; i < 6; i++)
+ for (j = 0; j < SIZE; j++)
+ b->square[i][j].color = NONE;
+ for (i = 6; i < 8; i++)
+ for (j = 0; j < SIZE; j++)
+ b->square[i][j].color = WHITE;
+ for (i = 0; i < SIZE; i++)
+ b->square[1][i].type = b->square[6][i].type =
+ PAWN;
+ b->square[0][0].type = b->square[7][0].type = ROOK;
+ b->square[0][1].type = b->square[7][1].type = KNIGHT;
+ b->square[0][2].type = b->square[7][2].type = BISHOP;
+ b->square[0][3].type = b->square[7][3].type = QUEEN;
+ b->square[0][4].type = b->square[7][4].type = KING;
+ b->square[0][5].type = b->square[7][5].type = BISHOP;
+ b->square[0][6].type = b->square[7][6].type = KNIGHT;
+ b->square[0][7].type = b->square[7][7].type = ROOK;
+ b->black_cant_castle_k = false;
+ b->black_cant_castle_q = false;
+ b->white_cant_castle_k = false;
+ b->white_cant_castle_q = false;
+
+ return;
+}
+
+void
+board_drawall()
+{
+ int i, j;
+
+ for (i = 0; i < SIZE; i++)
+ for (j = 0; j < SIZE; j++)
+ if (chessboard->square[i][j].color != NONE) {
+ win_drawpiece(&chessboard->square[i][j], i,
+ j, WHITE);
+ if (!oneboard)
+ win_drawpiece(&chessboard->square[i][j],
+ i, j, BLACK);
+ }
+ return;
+}
+
+void
+board_move(b, m)
+ board *b;
+ move *m;
+{
+ switch (m->type) {
+
+ case MOVE:
+ case CAPTURE:
+ b->square[m->fromy][m->fromx].color = NONE;
+ b->square[m->toy][m->tox].color = m->piece.color;
+ b->square[m->toy][m->tox].type = m->piece.type;
+ if ((m->piece.type == PAWN) && (((m->piece.color == BLACK) &&
+ (m->toy == 7)) || ((m->piece.color == WHITE) &&
+ (m->toy == 0))))
+ b->square[m->toy][m->tox].type = QUEEN;
+ if (m->enpassant)
+ b->square[m->toy + ((m->piece.color == WHITE) ? 1 :
+ -1)][m->tox].color = NONE;
+ break;
+
+ case KCASTLE:
+ if (m->piece.color == WHITE) {
+ b->square[7][5].color = m->piece.color;
+ b->square[7][5].type = ROOK;
+ b->square[7][6].color = m->piece.color;
+ b->square[7][6].type = KING;
+ b->square[7][4].color = NONE;
+ b->square[7][7].color = NONE;
+ } else {
+ b->square[0][5].color = m->piece.color;
+ b->square[0][5].type = ROOK;
+ b->square[0][6].color = m->piece.color;
+ b->square[0][6].type = KING;
+ b->square[0][4].color = NONE;
+ b->square[0][7].color = NONE;
+ }
+ break;
+
+ case QCASTLE:
+ if (m->piece.color == WHITE) {
+ b->square[7][3].color = m->piece.color;
+ b->square[7][3].type = ROOK;
+ b->square[7][2].color = m->piece.color;
+ b->square[7][2].type = KING;
+ b->square[7][4].color = NONE;
+ b->square[7][0].color = NONE;
+ } else {
+ b->square[0][3].color = m->piece.color;
+ b->square[0][3].type = ROOK;
+ b->square[0][2].color = m->piece.color;
+ b->square[0][2].type = KING;
+ b->square[0][4].color = NONE;
+ b->square[0][0].color = NONE;
+ }
+ break;
+
+ default:
+ fprintf(stderr, "Bad move type %d\n", m->type);
+ }
+
+ if (m->piece.type == KING) {
+ if (m->piece.color == WHITE)
+ b->white_cant_castle_q =
+ b->white_cant_castle_k= true;
+ else
+ b->black_cant_castle_q =
+ b->black_cant_castle_k= true;
+ } else if (m->piece.type == ROOK) {
+ if (m->piece.color == WHITE) {
+ if (m->fromx == 0)
+ b->white_cant_castle_q = true;
+ else if (m->fromx == 7)
+ b->white_cant_castle_k = true;
+ } else {
+ if (m->fromx == 0)
+ b->black_cant_castle_q = true;
+ else if (m->fromx == 7)
+ b->black_cant_castle_k = true;
+ }
+ }
+
+ return;
+}
+
diff --git a/gnu/games/chess/Xchess/button.c b/gnu/games/chess/Xchess/button.c
new file mode 100644
index 000000000000..67bf3c86942f
--- /dev/null
+++ b/gnu/games/chess/Xchess/button.c
@@ -0,0 +1,337 @@
+
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/26 12:09:41 $
+ * $Source: /users/faustus/xchess/RCS/button.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ *
+ * Do stuff with the buttons.
+ * The configuration we're using is: Draw Back Pause
+ * Resign Fwd Flip
+ * Reset Save Easy (Switch)
+ */
+
+#include "xchess.h"
+
+typedef enum choice { NOCHOICE, DRAW, RESIGN, REPLAY, SWITCH, FORE, SAVE,
+ STOP, FLIP, RESTART, EASY } choice;
+
+static struct but {
+ char *label;
+ int x, y;
+ int width, height;
+ choice which;
+} buts[] = {
+ { "Draw", 0, 20, 108, 29, DRAW } ,
+ { "Back", 109, 20, 108, 29, REPLAY } ,
+ { "Pause", 219, 20, 108, 29, STOP } ,
+ { "Resign", 0, 50, 108, 29, RESIGN } ,
+ { "Fwd", 109, 50, 108, 29, FORE } ,
+ { "Flip", 219, 50, 108, 29, FLIP } ,
+ { "Reset", 0, 80, 108, 29, RESTART } ,
+ { "Save", 109, 80, 108, 29, SAVE } ,
+#define EASY_OFFSET 8
+ { "Switch", 219, 80, 108, 29, SWITCH }
+/* { "NoEasy", 219, 80, 108, 29, EASY }*/
+} ;
+static int easy = 1;
+
+void
+button_draw(win)
+ windata *win;
+{
+ int i, x, numbuts = sizeof (buts) / sizeof (struct but);
+
+ XSetState(win->display, DefaultGC(win->display, 0),
+ win->border.pixel, WhitePixel(win->display, 0),
+ GXcopy, AllPlanes);
+ XSetLineAttributes(win->display, DefaultGC(win->display, 0),
+ BORDER_WIDTH, LineSolid, CapButt,
+ JoinMiter);
+
+ XDrawLine(win->display, win->buttonwin,
+ DefaultGC(win->display, 0),
+ 0, 29, BUTTON_WIDTH, 29);
+ XDrawLine(win->display, win->buttonwin,
+ DefaultGC(win->display, 0),
+ 0, 60, BUTTON_WIDTH, 60);
+ XDrawLine(win->display, win->buttonwin,
+ DefaultGC(win->display, 0),
+ 108, 0, 108, BUTTON_HEIGHT);
+ XDrawLine(win->display, win->buttonwin,
+ DefaultGC(win->display, 0),
+ 219, 0, 219, BUTTON_HEIGHT);
+
+ XSetFont(win->display, DefaultGC(win->display, 0), win->large->fid);
+ XSetForeground(win->display, DefaultGC(win->display, 0),
+ win->textcolor.pixel);
+ XSetBackground(win->display, DefaultGC(win->display, 0),
+ win->textback.pixel);
+
+ for (i = 0; i < numbuts; i++) {
+ x = (buts[i].width -
+ XTextWidth(win->large, buts[i].label,
+ strlen(buts[i].label))) / 2;
+
+ XDrawImageString(win->display, win->buttonwin,
+ DefaultGC(win->display, 0),
+ buts[i].x + x, buts[i].y, buts[i].label,
+ strlen(buts[i].label));
+ }
+ return;
+}
+
+void
+button_service(win, event)
+ windata *win;
+ XEvent *event;
+{
+ XKeyEvent *ev = &event->xkey;
+ choice c;
+ int i, numbuts = sizeof (buts) / sizeof (struct but);
+ char *s;
+
+ ev->y += 15;
+ for (i = 0; i < numbuts; i++)
+ if ((ev->x >= buts[i].x) && (ev->x <= buts[i].x +
+ buts[i].width) && (ev->y >= buts[i].y) &&
+ (ev->y <= buts[i].y + buts[i].height)) {
+ c = buts[i].which;
+ break;
+ }
+ if ((i == numbuts) || (c == NOCHOICE)) {
+ message_add(win, "Bad choice.\n", true);
+ return;
+ }
+
+ if (loading_flag && (c != STOP)) {
+ message_add(win, "You can only use PAUSE now\n", true);
+ return;
+ }
+
+ switch (c) {
+ case DRAW:
+ if (!oneboard) {
+ message_add(win, "Just a sec...\n", false);
+ if (!pop_question(((win == win1) ? win2 : win1),
+"The other player wants\nto call the game a draw.\nDo you agree?\n")) {
+ message_add(win,
+ "The other player declines the draw\n", false);
+ return;
+ }
+ }
+ message_add(win1, "Draw agreed.\n", false);
+ if (!oneboard)
+ message_add(win2, "Draw agreed.\n", false);
+ cleanup("Draw agreed.");
+ break;
+
+ case RESIGN:
+ if (!pop_question(win, "Are you sure\nyou want to resign?"))
+ return;
+ if ((oneboard && !progflag) || (nexttomove == win->color)) {
+ if (nexttomove == WHITE)
+ s = "White resigns.";
+ else
+ s = "Black resigns.";
+ if (oneboard) {
+ message_add(win, s, false);
+ message_add(win, "\n", false);
+ } else {
+ message_add(win1, s, false);
+ message_add(win, "\n", false);
+ message_add(win2, s, false);
+ message_add(win, "\n", false);
+ }
+ sleep(5);
+ cleanup(s);
+ } else {
+ message_add(win, "It's not your turn.\n", true);
+ }
+ break;
+
+ case REPLAY:
+ if (!oneboard) {
+ message_add(win, "Just a sec...\n", false);
+ if (!pop_question(((win == win1) ? win2 : win1),
+"The other player wants\nto take back his last move.\nDo you let him?\n")) {
+ message_add(win,
+ "The other player refuses...\n", false);
+ return;
+ }
+ }
+ if (!moves) {
+ message_add(win, "Can't back up...\n", true);
+ break;
+ }
+ message_add(win1, "Replaying...\n", false);
+ if (!oneboard)
+ message_add(win2, "Replaying...\n", false);
+ replay();
+ if (progflag)
+ replay();
+ break;
+
+ case FORE:
+ if (!oneboard) {
+ message_add(win, "Just a sec...\n", false);
+ if (!pop_question(((win == win1) ? win2 : win1),
+"The other player wants\nto do a 'fore'.\nIs that ok with you?\n")) {
+ message_add(win,
+ "The other player refuses...\n", false);
+ return;
+ }
+ }
+ if (!foremoves) {
+ message_add(win, "Can't go forward...\n", true);
+ break;
+ }
+ message_add(win1, "Moving forward...\n", false);
+ if (!oneboard)
+ message_add(win2, "Moving forward...\n", false);
+ forward();
+ break;
+
+ case SWITCH:
+ message_add(win, "You can't switch yet.\n", false);
+ break;
+
+ case SAVE:
+ if (saveflag) {
+ message_add(win,
+ "Game is already being logged in file '", true);
+ message_add(win, record_file, true);
+ message_add(win, "'.\n", true);
+ } else {
+ message_add(win, "Saving game to file '", false);
+ message_add(win, record_file, false);
+ message_add(win, "'.\n", false);
+ record_save();
+ }
+ break;
+
+ case STOP:
+ if (loading_flag) {
+ loading_paused = (loading_paused ? false : true);
+ message_add(win, loading_paused ?
+ "Stopped.\nHit 'Pause' again to restart.\n" :
+ "Restarted.\n", false);
+ } else if (clock_started) {
+ if (!oneboard) {
+ message_add(win, "Just a sec...\n", false);
+ if (!pop_question(((win == win1) ? win2 : win1),
+"The other player wants\nto stop the clock.\nDo you let him?\n")) {
+ message_add(win,
+ "The other player refuses to pause.\n",
+ false);
+ return;
+ }
+ }
+ message_add(win1,
+ "Clock stopped.\nHit 'Pause' again to restart.\n",
+ false);
+ if (!oneboard)
+ message_add(win2,
+ "Clock stopped.\nHit 'Pause' again to restart.\n",
+ false);
+ clock_started = false;
+ } else {
+ if (!oneboard) {
+ message_add(win, "Just a sec...\n", false);
+ if (!pop_question(((win == win1) ? win2 : win1),
+"The other player wants\nto start the clock again.\nIs that ok?\n")) {
+ message_add(win,
+ "The other player refuses to resume.\n",
+ false);
+ return;
+ }
+ }
+ message_add(win1, "Clock restarted.\n", false);
+ if (!oneboard)
+ message_add(win2, "Clock restarted.\n", false);
+ clock_started = true;
+ }
+ break;
+
+ case FLIP:
+ message_add(win, "Flipping window...\n", false);
+ win->flipped = win->flipped ? false : true;
+ win_redraw(win, (XEvent *) NULL);
+ break;
+
+ case RESTART:
+ if (!oneboard) {
+ message_add(win, "Just a sec...\n", false);
+ if (!pop_question(((win == win1) ? win2 : win1),
+"The other player wants\nto restart the game.\nDo you agree?\n")) {
+ message_add(win,
+ "The other player refuses to reset\n", false);
+ return;
+ }
+ }
+ message_add(win, "Restarting game.\n", false);
+ restart();
+ break;
+ case EASY:
+ if (oneboard) {
+ int x;
+ if (easy)
+ easy = 0;
+ else
+ easy = 1;
+
+ if (easy)
+ buts[EASY_OFFSET].label = " Easy ";
+ else
+ buts[EASY_OFFSET].label = "NoEasy";
+
+ program_easy(easy);
+
+ x = (buts[EASY_OFFSET].width -
+ XTextWidth(win->large,
+ buts[EASY_OFFSET].label,
+ strlen(buts[EASY_OFFSET].label))) / 2;
+
+ XSetFont(win->display, DefaultGC(win->display,
+ 0), win->large->fid);
+ XSetForeground(win->display,
+ DefaultGC(win->display, 0),
+ win->textcolor.pixel);
+ XSetBackground(win->display,
+ DefaultGC(win->display, 0),
+ win->textback.pixel);
+
+ XDrawImageString(win->display,
+ win->buttonwin,
+ DefaultGC(win->display, 0),
+ buts[EASY_OFFSET].x + x,
+ buts[EASY_OFFSET].y,
+ buts[EASY_OFFSET].label,
+ strlen(buts[EASY_OFFSET].label));
+ }
+ break;
+ }
+ return;
+}
+
diff --git a/gnu/games/chess/Xchess/clock.c b/gnu/games/chess/Xchess/clock.c
new file mode 100644
index 000000000000..a7b3c3264e3c
--- /dev/null
+++ b/gnu/games/chess/Xchess/clock.c
@@ -0,0 +1,291 @@
+
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/26 12:09:47 $
+ * $Source: /users/faustus/xchess/RCS/clock.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ *
+ * Do stuff with the clocks. The way things work is as follows. We call
+ * clock_init to draw the clocks initially, but they don't actually start
+ * running until we call clock_switch for the first time.
+ */
+
+#include "xchess.h"
+
+int movesperunit = 0;
+int timeunit = 0;
+bool clock_started = false;
+int whiteseconds, blackseconds;
+
+static bool white_running = true;
+static long lastwhite, lastblack;
+static bool firstmove = true;
+
+extern void dohands(), hilight();
+
+#define PI 3.1415926535897932384
+
+void
+clock_draw(win, col)
+ windata *win;
+ color col;
+{
+ int i;
+ char buf[BSIZE];
+ int x = CLOCK_WIDTH / 2, y = CLOCK_WIDTH / 2;
+ int xp, yp;
+ int rad = CLOCK_WIDTH / 2 - 10;
+ Window w = ((col == WHITE) ? win->wclockwin : win->bclockwin);
+
+ /* Draw a clock face and the hands. */
+ XCircle(w, x, y, rad, 0.0, 0.0, 1, 1, win->textcolor.pixel, GXcopy,
+ AllPlanes);
+ rad -= 8;
+
+ XSetFont(win->display, DefaultGC(win->display, 0),
+ win->small->fid);
+ XSetForeground(win->display, DefaultGC(win->display, 0),
+ win->textcolor.pixel);
+ XSetBackground(win->display, DefaultGC(win->display, 0),
+ win->textback.pixel);
+ for (i = 1; i <= 12; i++) {
+ xp = x + rad * cos(PI * 3 / 2 + i * PI / 6) - 4;
+ yp = y + rad * sin(PI * 3 / 2 + i * PI / 6) - 5;
+ sprintf(buf, "%d", i);
+ XDrawString(win->display, w, DefaultGC(win->display, 0),
+ xp, yp, buf, strlen(buf));
+ }
+
+ dohands(win, col);
+
+ if (white_running) {
+ hilight(win, WHITE, true);
+ hilight(win, BLACK, false);
+ } else {
+ hilight(win, WHITE, false);
+ hilight(win, BLACK, true);
+ }
+ return;
+}
+
+void
+clock_init(win, col)
+ windata *win;
+ color col;
+{
+ whiteseconds = blackseconds = 0;
+ clock_started = false;
+ firstmove = true;
+ clock_draw(win, col);
+
+ return;
+}
+
+void
+clock_update()
+{
+ int now = time((long *) NULL);
+ int i;
+
+ if (!clock_started) {
+ lastwhite = lastblack = now;
+ return;
+ }
+
+ if (white_running) {
+ whiteseconds += now - lastwhite;
+ lastwhite = now;
+ dohands(win1, WHITE);
+ if (!oneboard)
+ dohands(win2, WHITE);
+ if (timeunit) {
+ i = whiteseconds / timeunit;
+ if ((i > 0) && (whiteseconds > i * timeunit) &&
+ (whiteseconds < i * timeunit + 10) &&
+ (movesperunit * i > movenum)) {
+ message_add(win1,
+ "White has exceeded his time limit\n",
+ true);
+ if (!oneboard) {
+ message_add(win2,
+ "White has exceeded his time limit\n",
+ true);
+ }
+ timeunit = 0;
+ }
+ }
+ } else {
+ blackseconds += now - lastblack;
+ lastblack = now;
+ dohands(win1, BLACK);
+ if (!oneboard)
+ dohands(win2, BLACK);
+ if (timeunit) {
+ i = blackseconds / timeunit;
+ if ((i > 0) && (blackseconds > i * timeunit) &&
+ (blackseconds < i * timeunit + 10) &&
+ (movesperunit * i > movenum)) {
+ message_add(win1,
+ "Black has exceeded his time limit\n",
+ true);
+ if (!oneboard) {
+ message_add(win2,
+ "Black has exceeded his time limit\n",
+ true);
+ }
+ timeunit = 0;
+ }
+ }
+ }
+ return;
+}
+
+void
+clock_switch()
+{
+ if (firstmove) {
+ clock_started = true;
+ firstmove = false;
+ lastwhite = lastblack = time((long *) NULL);
+ }
+ if (white_running) {
+ white_running = false;
+ lastblack = time((long *) NULL);
+ hilight(win1, WHITE, false);
+ hilight(win1, BLACK, true);
+ if (!oneboard) {
+ hilight(win2, WHITE, false);
+ hilight(win2, BLACK, true);
+ }
+ } else {
+ white_running = true;
+ lastwhite = time((long *) NULL);
+ hilight(win1, WHITE, true);
+ hilight(win1, BLACK, false);
+ if (!oneboard) {
+ hilight(win2, WHITE, true);
+ hilight(win2, BLACK, false);
+ }
+ }
+ return;
+}
+
+static void
+dohands(win, col)
+ windata *win;
+ color col;
+{
+ int cx = CLOCK_WIDTH / 2, cy = CLOCK_WIDTH / 2;
+ double *h = (col == WHITE) ? win->whitehands : win->blackhands;
+ Window w = (col == WHITE) ? win->wclockwin : win->bclockwin;
+ long secs = (col == WHITE) ? whiteseconds : blackseconds;
+ int rad, x, y, i;
+
+ /* First erase the old hands. */
+ XSetState(win->display, DefaultGC(win->display, 0),
+ win->textback.pixel, win->textback.pixel,
+ GXcopy, AllPlanes);
+
+ rad = CLOCK_WIDTH / 2 - 30;
+ for (i = 0; i < 3; i++) {
+ x = cx + rad * sin(PI - h[i]);
+ y = cy + rad * cos(PI - h[i]);
+ XSetLineAttributes(win->display,
+ DefaultGC(win->display, 0),
+ i, LineSolid, 0, 0);
+ XDrawLine(win->display, w, DefaultGC(win->display, 0),
+ cx, cy, x, y);
+ rad -= 8;
+ }
+
+ h[0] = (secs % 60) * 2 * PI / 60;
+ h[1] = ((secs / 60) % 60) * 2 * PI / 60;
+ h[2] = ((secs / 3600) % 12) * 2 * PI / 12;
+
+ /* Now draw the new ones. */
+
+ XSetState(win->display, DefaultGC(win->display, 0),
+ win->textcolor.pixel, win->textback.pixel,
+ GXcopy, AllPlanes);
+
+ rad = CLOCK_WIDTH / 2 - 30;
+ for (i = 0; i < 3; i++) {
+ x = cx + rad * sin(PI - h[i]);
+ y = cy + rad * cos(PI - h[i]);
+ XSetLineAttributes(win->display,
+ DefaultGC(win->display, 0),
+ i, LineSolid, 0, 0);
+ XDrawLine(win->display, w, DefaultGC(win->display, 0),
+ cx, cy, x, y);
+ rad -= 8;
+ }
+ XFlush(win->display);
+ return;
+}
+
+static void
+hilight(win, col, on)
+ windata *win;
+ color col;
+ bool on;
+{
+ Window w = (col == WHITE) ? win->wclockwin : win->bclockwin;
+ char *s = (col == WHITE) ? " WHITE " : " BLACK ";
+ int x;
+
+
+ x = XTextWidth(win->large, s, strlen(s));
+ if (on)
+ XSetState(win->display, DefaultGC(win->display, 0),
+ win->textback.pixel,
+ win->textcolor.pixel,
+ GXcopy,
+ AllPlanes);
+ else
+ XSetState(win->display, DefaultGC(win->display, 0),
+ win->textcolor.pixel,
+ win->textback.pixel,
+ GXcopy, AllPlanes);
+
+ XSetLineAttributes(win->display, DefaultGC(win->display, 0),
+ BORDER_WIDTH, LineSolid, CapButt, JoinMiter);
+ XSetFont(win->display, DefaultGC(win->display, 0),
+ win->large->fid);
+
+ XDrawLine(win->display, w, DefaultGC(win->display, 0),
+ 0, CLOCK_HEIGHT - 26,
+ CLOCK_WIDTH, CLOCK_HEIGHT - 26);
+
+ XDrawImageString(win->display, w, DefaultGC(win->display, 0),
+ (CLOCK_WIDTH - x) / 2, CLOCK_HEIGHT,
+ s, strlen(s));
+
+ if (on)
+ XSetState(win->display, DefaultGC(win->display, 0),
+ win->textcolor.pixel,
+ win->textback.pixel,
+ GXcopy, AllPlanes);
+ return;
+}
+
diff --git a/gnu/games/chess/Xchess/control.c b/gnu/games/chess/Xchess/control.c
new file mode 100644
index 000000000000..ad2e1d7994fd
--- /dev/null
+++ b/gnu/games/chess/Xchess/control.c
@@ -0,0 +1,515 @@
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/23 17:17:32 $
+ * $Source: /users/faustus/xchess/RCS/control.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ *
+ * Deal with input from the user.
+ */
+
+#include "xchess.h"
+
+move *moves;
+move *foremoves;
+color nexttomove = WHITE;
+bool noisyflag = false;
+
+move *lastmove;
+static move *thismove;
+
+static void screen_move();
+
+void
+button_pressed(event, win)
+ XEvent *event;
+ windata *win;
+{
+ int x, y;
+ XKeyEvent *ev = (XKeyEvent *) event;
+
+ if (!oneboard && (win->color != nexttomove)) {
+ message_add(win, "Wrong player!\n", true);
+ return;
+ }
+ if (progflag && (nexttomove == (blackflag ? WHITE : BLACK))) {
+ message_add(win, "Wait for the computer...\n", true);
+ return;
+ }
+ if (loading_flag) {
+ message_add(win, "You'd better not do that now...\n", true);
+ return;
+ }
+
+ /* Figure out what piece he is pointing at. */
+ x = ev->x / (SQUARE_WIDTH + BORDER_WIDTH);
+ y = ev->y / (SQUARE_HEIGHT + BORDER_WIDTH);
+
+ if (win->flipped) {
+ y = SIZE - y - 1;
+ x = SIZE - x - 1;
+ }
+
+ if ((x < 0) || (x >= SIZE) || (y < 0) || (y >= SIZE)) {
+ fprintf(stderr, "Bad coords (%d, %d)\n", x, y);
+ return;
+ }
+
+ if (oneboard && (chessboard->square[y][x].color != nexttomove)) {
+ message_add(win, "Wrong player!\n", true);
+ return;
+ } else if (!oneboard && (chessboard->square[y][x].color !=
+ win->color)) {
+ message_add(win, "Can't move that\n", true);
+ return;
+ }
+
+ thismove = alloc(move);
+ thismove->fromx = x;
+ thismove->fromy = y;
+ thismove->piece.color = chessboard->square[y][x].color;
+ thismove->piece.type = chessboard->square[y][x].type;
+
+ if (debug)
+ fprintf(stderr, "%s selected his %s at (%d, %d)...\n",
+ colornames[(int) thismove->piece.color],
+ piecenames[(int) thismove->piece.type],
+ thismove->fromy, thismove->fromx);
+ return;
+}
+
+void
+button_released(event, win)
+ XEvent *event;
+ windata *win;
+{
+ int x, y;
+ XKeyEvent *ev = (XKeyEvent *) event;
+
+ if (!thismove) {
+ /* fprintf(stderr, "Error: button hasn't been pressed\n"); */
+ return;
+ }
+ if (loading_flag)
+ return;
+
+ /* Figure out what piece he is pointing at. */
+ x = ev->x / (SQUARE_WIDTH + BORDER_WIDTH);
+ y = ev->y / (SQUARE_HEIGHT + BORDER_WIDTH);
+
+ if (win->flipped) {
+ y = SIZE - y - 1;
+ x = SIZE - x - 1;
+ }
+
+ if ((x < 0) || (x >= SIZE) || (y < 0) || (y >= SIZE)) {
+ fprintf(stderr, "Bad coords (%d, %d)\n", x, y);
+ return;
+ }
+
+ if ((thismove->fromx == x) && (thismove->fromy == y)) {
+ message_add(win, "Hey, you touch it, you move it, buddy.\n",
+ true);
+ return;
+ }
+ if (chessboard->square[y][x].color == thismove->piece.color) {
+ message_add(win, "Can't put one piece on top of another\n",
+ true);
+ return;
+ }
+
+ thismove->tox = x;
+ thismove->toy = y;
+ thismove->taken.color = chessboard->square[y][x].color;
+ thismove->taken.type = chessboard->square[y][x].type;
+ if (thismove->taken.color != NONE)
+ thismove->type = CAPTURE;
+ else if ((thismove->piece.type == KING) && (thismove->fromx == 4) &&
+ (thismove->tox == 6) &&
+ (thismove->toy == thismove->fromy))
+ thismove->type = KCASTLE;
+ else if ((thismove->piece.type == KING) && (thismove->tox == 2) &&
+ (thismove->fromx == 4) &&
+ (thismove->toy == thismove->fromy))
+ thismove->type = QCASTLE;
+ else
+ thismove->type = MOVE;
+
+ /* Now check the en-passant case... */
+ if ((thismove->type == MOVE) && ((thismove->tox == thismove->fromx + 1)
+ || (thismove->tox == thismove->fromx - 1)) &&
+ (thismove->piece.type == PAWN) && lastmove &&
+ (lastmove->tox == lastmove->fromx) && (lastmove->fromx
+ == thismove->tox) && ((lastmove->fromy + lastmove->toy)
+ / 2 == thismove->toy)) {
+ thismove->type = CAPTURE;
+ thismove->enpassant = true;
+ thismove->taken = lastmove->piece;
+ }
+
+ if (!valid_move(thismove, chessboard)) {
+ message_add(win, "Invalid move.\n", true);
+ return;
+ }
+
+ if (debug)
+ fprintf(stderr, "\t... and moved it to (%d, %d), type %s\n",
+ thismove->toy, thismove->tox,
+ movetypenames[(int) thismove->type]);
+ move_piece(thismove);
+
+ if (thismove->check) {
+ message_add(win1, "Check.\n", true);
+ if (!oneboard) {
+ message_add(win2, "Check.\n", true);
+ }
+ }
+
+ if (!moves)
+ moves = lastmove = thismove;
+ else
+ lastmove = lastmove->next = thismove;
+
+ if (progflag)
+ program_send(thismove);
+
+ thismove = NULL;
+ nexttomove = ((nexttomove == WHITE) ? BLACK : WHITE);
+ clock_switch();
+
+ return;
+}
+
+void
+prog_move(m)
+ move *m;
+{
+ if (debug)
+ fprintf(stderr, "program moves from (%d, %d) to (%d, %d)\n",
+ m->fromy, m->fromx, m->toy, m->tox);
+ move_piece(m);
+
+ if (!moves)
+ moves = lastmove = m;
+ else
+ lastmove = lastmove->next = m;
+
+ nexttomove = ((nexttomove == WHITE) ? BLACK : WHITE);
+ clock_switch();
+
+ return;
+}
+
+void
+move_piece(m)
+ move *m;
+{
+ /* Update the screen... */
+ screen_move(m);
+
+ /* Move the piece on the board... */
+ board_move(chessboard, m);
+
+ /* And record it... */
+ record_move(m);
+
+ if (noisyflag) {
+ XBell(win1->display, 50);
+ XBell(win2->display, 50);
+ }
+ return;
+}
+
+static void
+screen_move(m)
+ move *m;
+{
+ piece pp;
+
+ switch (m->type) {
+ case CAPTURE:
+ jail_add(&m->taken);
+ /* FALLTHRU */
+
+ case MOVE:
+ win_erasepiece(m->fromy, m->fromx, WHITE);
+ if (win_flashmove)
+ win_flash(m, WHITE);
+ win_drawpiece(&m->piece, m->toy, m->tox, WHITE);
+ if (m->enpassant)
+ win_erasepiece(m->toy + ((m->piece.color == WHITE) ?
+ 1 : -1), m->tox, WHITE);
+ if (!oneboard) {
+ win_erasepiece(m->fromy, m->fromx, BLACK);
+ if (win_flashmove)
+ win_flash(m, BLACK);
+ win_drawpiece(&m->piece, m->toy, m->tox, BLACK);
+ if (m->enpassant)
+ win_erasepiece(m->toy + ((m->piece.color ==
+ WHITE) ? 1 : -1), m->tox, WHITE);
+ }
+ if ((m->piece.type == PAWN) && (((m->piece.color == BLACK) &&
+ (m->toy == 7)) || ((m->piece.color == WHITE) &&
+ (m->toy == 0)))) {
+ pp.color = m->piece.color;
+ pp.type = QUEEN;
+ win_drawpiece(&pp, m->toy, m->tox, WHITE);
+ if (!oneboard)
+ win_drawpiece(&m->piece, m->toy, m->tox, BLACK);
+ }
+ break;
+
+ case KCASTLE:
+ if (m->piece.color == WHITE) {
+ win_erasepiece(7, 4, WHITE);
+ win_erasepiece(7, 7, WHITE);
+ if (win_flashmove)
+ win_flash(m, WHITE);
+ win_drawpiece(&m->piece, 7, 6, WHITE);
+ win_drawpiece(&chessboard->square[7][7], 7, 5, WHITE);
+ if (!oneboard) {
+ win_erasepiece(7, 4, BLACK);
+ win_erasepiece(7, 7, BLACK);
+ if (win_flashmove)
+ win_flash(m, BLACK);
+ win_drawpiece(&m->piece, 7, 6, BLACK);
+ win_drawpiece(&chessboard->square[7][7], 7, 5,
+ BLACK);
+ }
+ } else {
+ win_erasepiece(0, 4, WHITE);
+ win_erasepiece(0, 7, WHITE);
+ if (win_flashmove)
+ win_flash(m, WHITE);
+ win_drawpiece(&m->piece, 0, 6, WHITE);
+ win_drawpiece(&chessboard->square[0][7], 0, 5, WHITE);
+ if (!oneboard) {
+ win_erasepiece(0, 4, BLACK);
+ win_erasepiece(0, 7, BLACK);
+ if (win_flashmove)
+ win_flash(m, BLACK);
+ win_drawpiece(&m->piece, 0, 6, BLACK);
+ win_drawpiece(&chessboard->square[0][7], 0, 5,
+ BLACK);
+ }
+ }
+ break;
+
+ case QCASTLE:
+ if (m->piece.color == WHITE) {
+ win_erasepiece(7, 4, WHITE);
+ win_erasepiece(7, 0, WHITE);
+ if (win_flashmove)
+ win_flash(m, WHITE);
+ win_drawpiece(&m->piece, 7, 2, WHITE);
+ win_drawpiece(&chessboard->square[7][0], 7, 3, WHITE);
+ if (!oneboard) {
+ win_erasepiece(7, 4, BLACK);
+ win_erasepiece(7, 0, BLACK);
+ if (win_flashmove)
+ win_flash(m, BLACK);
+ win_drawpiece(&m->piece, 7, 2, BLACK);
+ win_drawpiece(&chessboard->square[7][7], 7, 3,
+ BLACK);
+ }
+ } else {
+ win_erasepiece(0, 4, WHITE);
+ win_erasepiece(0, 0, WHITE);
+ if (win_flashmove)
+ win_flash(m, WHITE);
+ win_drawpiece(&m->piece, 0, 2, WHITE);
+ win_drawpiece(&chessboard->square[0][0], 0, 3, WHITE);
+ if (!oneboard) {
+ win_erasepiece(0, 4, BLACK);
+ win_erasepiece(0, 0, BLACK);
+ if (win_flashmove)
+ win_flash(m, BLACK);
+ win_drawpiece(&m->piece, 0, 2, BLACK);
+ win_drawpiece(&chessboard->square[0][7], 0, 3,
+ BLACK);
+ }
+ }
+ break;
+
+ default:
+ fprintf(stderr, "Bad move type %d\n", m->type);
+ }
+ return;
+}
+
+/* Retract the last move made... */
+
+void
+replay()
+{
+ move *m = lastmove, bm;
+
+ memset(&bm, 0, sizeof(bm));
+ switch (m->type) {
+ case MOVE:
+ bm.type = MOVE;
+ bm.piece = m->piece;
+ bm.fromx = m->tox;
+ bm.fromy = m->toy;
+ bm.tox = m->fromx;
+ bm.toy = m->fromy;
+ board_move(chessboard, &bm);
+ screen_move(&bm);
+ break;
+
+ case CAPTURE:
+ bm.type = MOVE;
+ bm.piece = m->piece;
+ bm.fromx = m->tox;
+ bm.fromy = m->toy;
+ bm.tox = m->fromx;
+ bm.toy = m->fromy;
+ board_move(chessboard, &bm);
+ screen_move(&bm);
+ chessboard->square[m->toy][m->tox] = m->taken;
+ bm.piece = m->taken;
+ bm.fromx = bm.tox = m->tox;
+ bm.fromy = bm.toy = m->toy;
+ screen_move(&bm);
+ jail_remove(&m->taken);
+ break;
+
+ case KCASTLE:
+ bm.type = MOVE;
+ bm.piece.type = KING;
+ bm.piece.color = m->piece.color;
+ bm.fromx = 6;
+ bm.tox = 4;
+ bm.fromy = bm.toy = (m->piece.color == WHITE) ? 7 : 0;
+ board_move(chessboard, &bm);
+ screen_move(&bm);
+ bm.type = MOVE;
+ bm.piece.type = ROOK;
+ bm.piece.color = m->piece.color;
+ bm.fromx = 5;
+ bm.tox = 7;
+ bm.fromy = bm.toy = (m->piece.color == WHITE) ? 7 : 0;
+ board_move(chessboard, &bm);
+ screen_move(&bm);
+ if (m->piece.color == WHITE)
+ chessboard->white_cant_castle_k = false;
+ else
+ chessboard->black_cant_castle_k = false;
+ break;
+
+ case QCASTLE:
+ bm.type = MOVE;
+ bm.piece.type = KING;
+ bm.piece.color = m->piece.color;
+ bm.fromx = 2;
+ bm.tox = 4;
+ bm.fromy = bm.toy = (m->piece.color == WHITE) ? 7 : 0;
+ board_move(chessboard, &bm);
+ screen_move(&bm);
+ bm.type = MOVE;
+ bm.piece.type = ROOK;
+ bm.piece.color = m->piece.color;
+ bm.fromx = 3;
+ bm.tox = 0;
+ bm.fromy = bm.toy = (m->piece.color == WHITE) ? 7 : 0;
+ board_move(chessboard, &bm);
+ screen_move(&bm);
+ if (m->piece.color == WHITE)
+ chessboard->white_cant_castle_q = false;
+ else
+ chessboard->black_cant_castle_q = false;
+ break;
+ }
+ record_back();
+
+ nexttomove = ((nexttomove == WHITE) ? BLACK : WHITE);
+ clock_switch();
+
+ if (!moves->next) {
+ moves->next = foremoves;
+ foremoves = moves;
+ moves = lastmove = NULL;
+ } else {
+ for (m = moves; m->next; m = m->next)
+ lastmove = m;
+ lastmove->next->next = foremoves;
+ foremoves = lastmove->next;
+ lastmove->next = NULL;
+ }
+
+ if (progflag)
+ program_undo();
+
+ return;
+}
+
+/* Put back the last move undone. */
+
+void
+forward()
+{
+ prog_move(foremoves);
+ foremoves = foremoves->next;
+ return;
+}
+
+/* End the game. */
+
+void
+cleanup(s)
+ char *s;
+{
+ if (progflag)
+ program_end();
+ record_end(s);
+ XSync(win1->display, 0);
+ if (!oneboard) {
+ XSync(win2->display, 0);
+ }
+ exit(0);
+}
+
+void
+restart()
+{
+ moves = lastmove = thismove = NULL;
+ nexttomove = WHITE;
+
+ clock_init(win1, WHITE);
+ clock_init(win1, BLACK);
+ jail_init(win1);
+ if (!oneboard) {
+ clock_init(win2, WHITE);
+ clock_init(win2, BLACK);
+ jail_init(win2);
+ }
+ board_init(chessboard);
+ win_restart();
+ record_reset();
+ if (progflag) {
+ program_end();
+ program_init(progname);
+ }
+ return;
+}
+
diff --git a/gnu/games/chess/Xchess/jail.c b/gnu/games/chess/Xchess/jail.c
new file mode 100644
index 000000000000..e5e60642430a
--- /dev/null
+++ b/gnu/games/chess/Xchess/jail.c
@@ -0,0 +1,327 @@
+
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.3 $ on $Date: 86/11/26 12:09:54 $
+ * $Source: /users/faustus/xchess/RCS/jail.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ *
+ */
+
+#include "xchess.h"
+
+#include "pawn_small.bitmap"
+#include "rook_small.bitmap"
+#include "knight_small.bitmap"
+#include "bishop_small.bitmap"
+#include "queen_small.bitmap"
+#include "king_small.bitmap"
+
+#include "pawn_small_outline.bitmap"
+#include "rook_small_outline.bitmap"
+#include "knight_small_outline.bitmap"
+#include "bishop_small_outline.bitmap"
+#include "queen_small_outline.bitmap"
+#include "king_small_outline.bitmap"
+
+static bool pos[32];
+
+static piecetype pcs[] = { KING, QUEEN, ROOK, ROOK, BISHOP, BISHOP, KNIGHT,
+ KNIGHT, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN } ;
+
+extern int piecepos();
+extern char *bitsget();
+
+void
+jail_init(win)
+ windata *win;
+{
+ int i;
+
+ for (i = 0; i < 32; i++)
+ pos[i] = false;
+ jail_draw(win);
+ return;
+}
+
+#define JAIL_HEADER "Captured Pieces"
+
+void
+jail_draw(win)
+ windata *win;
+{
+ int i;
+ char *bits;
+ Pixmap tmpPM;
+ piece p;
+
+ i = XTextWidth(win->large, JAIL_HEADER, strlen(JAIL_HEADER));
+ XSetFont(win->display, DefaultGC(win->display, 0),
+ win->large->fid);
+ XSetForeground(win->display, DefaultGC(win->display, 0),
+ win->textcolor.pixel);
+ XSetBackground(win->display, DefaultGC(win->display, 0),
+ win->textback.pixel);
+
+ XDrawImageString(win->display, win->jailwin,
+ DefaultGC(win->display, 0),
+ (JAIL_WIDTH - i) / 2, 20, JAIL_HEADER,
+ strlen(JAIL_HEADER));
+
+ XSetForeground(win->display, DefaultGC(win->display, 0),
+ win->blackpiece.pixel);
+ XSetBackground(win->display, DefaultGC(win->display, 0),
+ win->textback.pixel);
+ XSetFillStyle(win->display, DefaultGC(win->display, 0),
+ FillSolid);
+ XSetFunction(win->display, DefaultGC(win->display, 0),
+ GXcopy);
+
+ for (i = 0; i < 16; i++)
+ if (pos[i]) {
+ p.color = WHITE;
+ p.type = pcs[i];
+ bits = bitsget(&p);
+ tmpPM = XCreateBitmapFromData(win->display,
+ win->jailwin, bits,
+ 32, 32);
+
+ XCopyPlane(win->display, tmpPM, win->jailwin,
+ DefaultGC(win->display, 0),
+ 0, 0, 32, 32,
+ 5 + (i % 8) * 32, 25 + (i / 8) * 32,
+ 1);
+ XFreePixmap(win->display, tmpPM);
+ } else {
+ XFillRectangle(win->display, win->jailwin,
+ DefaultGC(win->display, 0),
+ 5 + (i % 8) * 32,
+ 25 + (i / 8) * 32,
+ 32, 32);
+ }
+ for (i = 0; i < 16; i++)
+ if (pos[i + 16]) {
+ p.color = BLACK;
+ p.type = pcs[i];
+ bits = bitsget(&p);
+ tmpPM = XCreateBitmapFromData(win->display,
+ win->jailwin, bits,
+ 32, 32);
+
+ XCopyPlane(win->display, tmpPM, win->jailwin,
+ DefaultGC(win->display, 0),
+ 0, 0, 32, 32,
+ 5 + (i % 8) * 32, 94 + (i / 8) * 32,
+ 1);
+ XFreePixmap(win->display, tmpPM);
+ } else {
+ XFillRectangle(win->display, win->jailwin,
+ DefaultGC(win->display, 0),
+ 5 + (i % 8) * 32, 94 + (i / 8) * 32,
+ 32, 32);
+ }
+
+ return;
+}
+
+void
+jail_add(p)
+ piece *p;
+{
+ int i = piecepos(p, false);
+ char *bits;
+ Pixmap tmpPM;
+
+ pos[i] = true;
+
+ bits = bitsget(p);
+
+ XSetState(win1->display, DefaultGC(win1->display, 0),
+ win1->blackpiece.pixel,
+ win1->textback.pixel,
+ GXcopy,
+ AllPlanes);
+
+ tmpPM = XCreateBitmapFromData(win1->display,
+ win1->jailwin, bits,
+ 32, 32);
+
+ XCopyPlane(win1->display, tmpPM, win1->jailwin,
+ DefaultGC(win1->display, 0),
+ 0, 0, 32, 32,
+ 5 + (i % 8) * 32, ((i >= 16) ? 30 : 25) + (i / 8) * 32,
+ 1);
+ XFreePixmap(win1->display, tmpPM);
+
+ if (!oneboard) {
+ XSetState(win2->display, DefaultGC(win2->display, 0),
+ win2->blackpiece.pixel,
+ win2->textback.pixel,
+ GXcopy,
+ AllPlanes);
+
+
+ tmpPM = XCreateBitmapFromData(win2->display,
+ win2->jailwin, bits,
+ 32, 32);
+
+ XCopyPlane(win2->display, tmpPM, win2->jailwin,
+ DefaultGC(win2->display, 0),
+ 0, 0, 32, 32,
+ 5 + (i % 8) * 32, ((i >= 16) ? 30 : 25) + (i / 8) * 32,
+ 1);
+ XFreePixmap(win2->display, tmpPM);
+ }
+
+ return;
+}
+
+void
+jail_remove(p)
+ piece *p;
+{
+ int i = piecepos(p, true);
+
+ pos[i] = false;
+
+
+ XSetForeground(win1->display,
+ DefaultGC(win1->display, 0),
+ win1->blackpiece.pixel);
+ XSetBackground(win1->display,
+ DefaultGC(win1->display, 0),
+ win1->textback.pixel);
+ XSetFillStyle(win1->display,
+ DefaultGC(win1->display, 0),
+ FillSolid);
+
+ XFillRectangle(win1->display, win1->jailwin,
+ DefaultGC(win1->display, 0),
+ 5 + (i % 8) * 32,
+ ((i >= 16) ? 30 : 25) + (i / 8) * 32,
+ 32, 32);
+
+ if (!oneboard) {
+ XSetForeground(win2->display,
+ DefaultGC(win2->display, 0),
+ win2->blackpiece.pixel);
+ XSetBackground(win2->display,
+ DefaultGC(win2->display, 0),
+ win2->textback.pixel);
+ XSetFillStyle(win2->display,
+ DefaultGC(win2->display, 0),
+ FillSolid);
+
+ XFillRectangle(win2->display, win2->jailwin,
+ DefaultGC(win2->display, 0),
+ 5 + (i % 8) * 32,
+ ((i >= 16) ? 30 : 25) + (i / 8) * 32,
+ 32, 32);
+ }
+
+ return;
+}
+
+static char *bitsget(p)
+ piece *p;
+{
+ char *bits;
+
+ switch (p->type) {
+ case PAWN:
+ bits = (p->color == WHITE) ? pawn_small_outline_bits :
+ pawn_small_bits;
+ break;
+
+ case ROOK:
+ bits = (p->color == WHITE) ? rook_small_outline_bits :
+ rook_small_bits;
+ break;
+
+ case KNIGHT:
+ bits = (p->color == WHITE) ? knight_small_outline_bits :
+ knight_small_bits;
+ break;
+
+ case BISHOP:
+ bits = (p->color == WHITE) ? bishop_small_outline_bits :
+ bishop_small_bits;
+ break;
+
+ case QUEEN:
+ bits = (p->color == WHITE) ? queen_small_outline_bits :
+ queen_small_bits;
+ break;
+
+ case KING:
+ bits = (p->color == WHITE) ? king_small_outline_bits :
+ king_small_bits;
+ break;
+ }
+ return (bits);
+}
+
+static int
+piecepos(p, there)
+ piece *p;
+ bool there;
+{
+ int i, base = (p->color == WHITE) ? 0 : 16;
+
+ switch (p->type) {
+ case PAWN:
+ for (i = base + 8; (i < base + 15) && pos[i]; i++)
+ ;
+ if (there && !pos[i])
+ i--;
+ break;
+
+ case KING:
+ /* Hmm... */
+ i = base;
+ break;
+
+ case QUEEN:
+ i = base + 1;
+ break;
+
+ case ROOK:
+ i = base + 2;
+ if ((there && pos[i + 1]) || (!there && pos[i]))
+ i++;
+ break;
+
+ case BISHOP:
+ i = base + 4;
+ if ((there && pos[i + 1]) || (!there && pos[i]))
+ i++;
+ break;
+
+ case KNIGHT:
+ i = base + 6;
+ if ((there && pos[i + 1]) || (!there && pos[i]))
+ i++;
+ break;
+ }
+ return (i);
+}
diff --git a/gnu/games/chess/Xchess/king.bitmap b/gnu/games/chess/Xchess/king.bitmap
new file mode 100644
index 000000000000..dd9178a2ed9e
--- /dev/null
+++ b/gnu/games/chess/Xchess/king.bitmap
@@ -0,0 +1,71 @@
+
+#define king_width 80
+#define king_height 80
+static char king_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x30, 0x18, 0x00, 0xfc, 0x1f, 0x00,
+ 0x00, 0xfe, 0x7f, 0x00, 0xb8, 0x3b, 0x00, 0xff, 0x7f, 0x00, 0x00, 0xff,
+ 0xff, 0x00, 0xb8, 0x3b, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x03,
+ 0xb8, 0x3b, 0xe0, 0xff, 0xff, 0x01, 0xc0, 0xff, 0xff, 0x0f, 0xb8, 0x3b,
+ 0xf0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x1f, 0xb8, 0x3b, 0xf8, 0xff,
+ 0xf8, 0x07, 0xe0, 0x1f, 0xc0, 0x3f, 0xb8, 0x3b, 0xfc, 0x07, 0xe2, 0x07,
+ 0xf0, 0xcf, 0x9f, 0x7f, 0x30, 0x18, 0xfe, 0xf3, 0xcf, 0x0f, 0xf0, 0xe7,
+ 0x3f, 0xfe, 0xf0, 0x1f, 0x7e, 0xfc, 0xdf, 0x0f, 0xf0, 0xf3, 0xff, 0xfc,
+ 0xf1, 0x1f, 0x3f, 0xff, 0x9f, 0x0f, 0xf8, 0xfb, 0xff, 0xfd, 0xf3, 0x9f,
+ 0xbf, 0xff, 0xbf, 0x1f, 0xf8, 0xf9, 0xff, 0xf9, 0xe3, 0x8f, 0xdf, 0xff,
+ 0x3f, 0x1f, 0xf8, 0xfd, 0xff, 0xf3, 0xef, 0xcf, 0xcf, 0xff, 0x7f, 0x1f,
+ 0xf8, 0xfd, 0xff, 0xe7, 0xef, 0xef, 0xef, 0xff, 0x7f, 0x1f, 0xfc, 0xfd,
+ 0xff, 0xcf, 0xff, 0xff, 0xe7, 0x3f, 0x7c, 0x3f, 0xfc, 0x3c, 0xfc, 0xdf,
+ 0xff, 0xfe, 0xf3, 0x3d, 0x7c, 0x3f, 0xfc, 0x3e, 0xfc, 0x9e, 0x7f, 0xfc,
+ 0xf9, 0x39, 0x7c, 0x3f, 0xfc, 0x3e, 0x7c, 0xbe, 0x3f, 0xf8, 0xf9, 0x3b,
+ 0x7c, 0x3f, 0xfc, 0x3e, 0x78, 0x3f, 0x7f, 0xfc, 0xfc, 0x3b, 0x7f, 0x3f,
+ 0xfc, 0xfe, 0x7b, 0x7f, 0xff, 0xfe, 0xfe, 0x9b, 0x7f, 0x3f, 0xf8, 0xfe,
+ 0xbb, 0x7f, 0xfe, 0x7f, 0xfe, 0xdb, 0x79, 0x1f, 0xf8, 0xfe, 0xb3, 0xff,
+ 0xfe, 0x7f, 0xff, 0xcb, 0x7c, 0x1f, 0xf8, 0x9e, 0xb7, 0xff, 0xfe, 0x7f,
+ 0xff, 0x2b, 0x3e, 0x1f, 0xf8, 0x3e, 0xa6, 0xff, 0xfc, 0x7f, 0xff, 0xa3,
+ 0xbf, 0x1f, 0xf8, 0xfe, 0xa8, 0xff, 0xfd, 0x3e, 0xff, 0xd3, 0xbf, 0x1f,
+ 0xf8, 0xfd, 0x83, 0xff, 0x7d, 0xbc, 0xff, 0xc3, 0xbf, 0x1f, 0xf0, 0xfd,
+ 0x8f, 0xff, 0x39, 0xb8, 0xff, 0xe3, 0xbf, 0x1f, 0xf0, 0xfd, 0x9f, 0xff,
+ 0x7b, 0xbc, 0xff, 0xf1, 0x9f, 0x0f, 0xf0, 0xf9, 0xbf, 0xff, 0xfb, 0xbe,
+ 0xff, 0xfd, 0xdf, 0x0f, 0xf0, 0xfb, 0x3f, 0xff, 0xf3, 0x9f, 0xff, 0xfd,
+ 0xdf, 0x0f, 0xf0, 0xf3, 0x7f, 0xff, 0xf7, 0xdf, 0xff, 0xfc, 0xdf, 0x0f,
+ 0xe0, 0xf7, 0x7f, 0xfe, 0xf7, 0xdf, 0xff, 0xfe, 0xdf, 0x07, 0xe0, 0xf7,
+ 0xff, 0xfe, 0xf7, 0xdf, 0x7f, 0xfe, 0xcf, 0x07, 0xe0, 0xe7, 0xff, 0xfe,
+ 0xf7, 0xdf, 0x7f, 0xff, 0xef, 0x07, 0xc0, 0xef, 0xff, 0xfc, 0xef, 0xee,
+ 0x7f, 0xff, 0xe7, 0x03, 0xc0, 0xcf, 0xff, 0xfd, 0x6f, 0xec, 0x3f, 0xff,
+ 0xf7, 0x03, 0x80, 0xdf, 0xff, 0xf9, 0xef, 0xee, 0xbf, 0xff, 0xf3, 0x01,
+ 0x80, 0x9f, 0xff, 0xfb, 0xef, 0xef, 0x9f, 0xff, 0xfb, 0x01, 0x00, 0xbf,
+ 0xff, 0xfb, 0xef, 0xef, 0xdf, 0xff, 0xf9, 0x00, 0x00, 0x7e, 0xff, 0xf3,
+ 0xef, 0xef, 0xdf, 0xff, 0x7e, 0x00, 0x00, 0x7e, 0xfe, 0xff, 0xef, 0xef,
+ 0xff, 0x7f, 0x7e, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xef, 0xef, 0xff, 0x7f,
+ 0x3f, 0x00, 0x00, 0xfc, 0xf9, 0xff, 0xef, 0xef, 0xff, 0x3f, 0x1f, 0x00,
+ 0x00, 0xf8, 0xfb, 0x03, 0xe0, 0x0f, 0x00, 0x9f, 0x1f, 0x00, 0x00, 0xf0,
+ 0x03, 0xf8, 0xff, 0xff, 0x7f, 0xc0, 0x0f, 0x00, 0x00, 0xe0, 0xff, 0xbf,
+ 0xf7, 0xde, 0xfb, 0xff, 0x07, 0x00, 0x00, 0xc0, 0xff, 0x1d, 0x63, 0x8c,
+ 0x71, 0xff, 0x03, 0x00, 0x00, 0x80, 0xef, 0xb8, 0xf7, 0xde, 0x3b, 0xee,
+ 0x01, 0x00, 0x00, 0x00, 0xc7, 0xfd, 0xff, 0xff, 0x7f, 0xc7, 0x00, 0x00,
+ 0x00, 0x00, 0xee, 0xff, 0x00, 0x00, 0xfc, 0x6f, 0x00, 0x00, 0x00, 0x00,
+ 0xfe, 0x03, 0xfe, 0xff, 0x01, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x06, 0xf8,
+ 0x7f, 0xfc, 0x7f, 0x60, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x1f, 0xf0,
+ 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xff, 0x07, 0xc0, 0xff, 0x63,
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0xff, 0x1f, 0xf0, 0xff, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0xfc, 0x7f, 0xfc, 0x3f, 0x60, 0x00, 0x00, 0x00, 0x00,
+ 0x06, 0xff, 0xff, 0xff, 0xff, 0x60, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xff,
+ 0x00, 0x00, 0xfc, 0x63, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0xfe, 0xff,
+ 0x01, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x06, 0xf8, 0xff, 0xff, 0x7f, 0x60,
+ 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00,
+ 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/king_mask.bitmap b/gnu/games/chess/Xchess/king_mask.bitmap
new file mode 100644
index 000000000000..e1bb523cad10
--- /dev/null
+++ b/gnu/games/chess/Xchess/king_mask.bitmap
@@ -0,0 +1,71 @@
+
+#define king_mask_width 80
+#define king_mask_height 80
+static char king_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3f, 0x00, 0xf8, 0x3f, 0x00, 0xfe,
+ 0x3f, 0x00, 0x00, 0xff, 0xff, 0x00, 0xfc, 0x3f, 0x80, 0xff, 0x7f, 0x00,
+ 0x80, 0xff, 0xff, 0x01, 0xfc, 0x7f, 0xc0, 0xff, 0xff, 0x00, 0xc0, 0xff,
+ 0xff, 0x07, 0xfc, 0x7f, 0xe0, 0xff, 0xff, 0x01, 0xe0, 0xff, 0xff, 0x1f,
+ 0xfc, 0x7f, 0xf8, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x3f, 0xfc, 0x7f,
+ 0xfc, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x7f, 0xfc, 0x7f, 0xfe, 0xff,
+ 0xff, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0x1f,
+ 0xf8, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf8, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+ 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x1f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f,
+ 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x0f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x07, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07,
+ 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x7f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00,
+ 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xfc,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xf8, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x07, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x03, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00,
+ 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/king_outline.bitmap b/gnu/games/chess/Xchess/king_outline.bitmap
new file mode 100644
index 000000000000..173651c28efa
--- /dev/null
+++ b/gnu/games/chess/Xchess/king_outline.bitmap
@@ -0,0 +1,71 @@
+
+#define king_outline_width 80
+#define king_outline_height 80
+static char king_outline_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x1c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x0c, 0x60, 0x00, 0xfc, 0x1f, 0x00,
+ 0x00, 0x0e, 0x70, 0x00, 0x84, 0x43, 0x00, 0x07, 0x70, 0x00, 0x00, 0x03,
+ 0xc0, 0x00, 0xc4, 0x46, 0x80, 0x01, 0xc0, 0x00, 0x80, 0x01, 0x80, 0x03,
+ 0x44, 0x44, 0xe0, 0x00, 0x80, 0x01, 0xc0, 0x00, 0x00, 0x0e, 0x44, 0x44,
+ 0x30, 0x00, 0x00, 0x03, 0x60, 0x00, 0x00, 0x18, 0x44, 0x44, 0x18, 0x00,
+ 0x07, 0x06, 0x20, 0xe0, 0x3f, 0x30, 0xc4, 0x46, 0x0c, 0xf8, 0x1d, 0x04,
+ 0x30, 0x30, 0x60, 0x60, 0x8c, 0x63, 0x06, 0x0c, 0x30, 0x0c, 0x10, 0x18,
+ 0xc0, 0xc1, 0x08, 0x20, 0x82, 0x03, 0x20, 0x0c, 0x10, 0x0c, 0x00, 0x83,
+ 0x09, 0x20, 0xc3, 0x00, 0x60, 0x08, 0x18, 0x04, 0x00, 0x02, 0x8b, 0xa3,
+ 0x41, 0x00, 0x40, 0x18, 0x08, 0x06, 0x00, 0x06, 0x7a, 0xb6, 0x20, 0x00,
+ 0xc0, 0x10, 0x08, 0x02, 0x00, 0x0c, 0x3e, 0x7c, 0x30, 0x00, 0x80, 0x10,
+ 0x08, 0x02, 0x00, 0x18, 0x18, 0x18, 0x10, 0x00, 0x80, 0x10, 0x0c, 0x02,
+ 0x00, 0x30, 0x00, 0x00, 0x18, 0xc0, 0x83, 0x30, 0x04, 0xc3, 0x03, 0x20,
+ 0x00, 0x01, 0x0c, 0xc2, 0x83, 0x20, 0x04, 0xc1, 0x03, 0x61, 0x80, 0x03,
+ 0x06, 0xc6, 0x83, 0x20, 0x04, 0xc1, 0x83, 0x41, 0xc0, 0x07, 0x06, 0xc4,
+ 0x83, 0x20, 0x04, 0xc1, 0x87, 0xc0, 0x80, 0x03, 0x03, 0xc4, 0x80, 0x20,
+ 0x0c, 0x01, 0x84, 0x80, 0x00, 0x01, 0x01, 0x64, 0x80, 0x30, 0x08, 0x01,
+ 0x44, 0x80, 0x01, 0x80, 0x01, 0x24, 0x86, 0x10, 0x08, 0x01, 0x4c, 0x00,
+ 0x01, 0x80, 0x00, 0x34, 0x83, 0x10, 0x08, 0x61, 0x48, 0x00, 0x01, 0x80,
+ 0x00, 0xd4, 0xc1, 0x10, 0x08, 0xc1, 0x59, 0x00, 0x03, 0x80, 0x00, 0x5c,
+ 0x40, 0x10, 0x08, 0x01, 0x57, 0x00, 0x02, 0xc1, 0x00, 0x2c, 0x40, 0x10,
+ 0x18, 0x02, 0x7c, 0x00, 0x82, 0x43, 0x00, 0x3c, 0x40, 0x18, 0x10, 0x02,
+ 0x70, 0x00, 0xc6, 0x47, 0x00, 0x1c, 0x40, 0x18, 0x10, 0x02, 0x60, 0x00,
+ 0x84, 0x43, 0x00, 0x0e, 0x60, 0x08, 0x10, 0x06, 0x40, 0x00, 0x04, 0x41,
+ 0x00, 0x02, 0x20, 0x08, 0x10, 0x04, 0xc0, 0x00, 0x0c, 0x60, 0x00, 0x02,
+ 0x20, 0x0c, 0x30, 0x0c, 0x80, 0x00, 0x08, 0x20, 0x00, 0x03, 0x20, 0x0c,
+ 0x20, 0x08, 0x80, 0x01, 0x08, 0x20, 0x00, 0x01, 0x20, 0x04, 0x20, 0x08,
+ 0x00, 0x01, 0x08, 0x20, 0x80, 0x01, 0x30, 0x04, 0x60, 0x18, 0x00, 0x01,
+ 0x08, 0x20, 0x80, 0x00, 0x10, 0x06, 0x40, 0x10, 0x00, 0x03, 0x10, 0x11,
+ 0x80, 0x00, 0x18, 0x02, 0xc0, 0x30, 0x00, 0x02, 0x90, 0x13, 0xc0, 0x00,
+ 0x08, 0x03, 0x80, 0x20, 0x00, 0x06, 0x10, 0x11, 0x40, 0x00, 0x04, 0x01,
+ 0x80, 0x61, 0x00, 0x04, 0x10, 0x10, 0x60, 0x00, 0x84, 0x01, 0x00, 0x41,
+ 0x00, 0x04, 0x10, 0x10, 0x20, 0x00, 0xc6, 0x00, 0x00, 0x83, 0x00, 0x0c,
+ 0x10, 0x10, 0x20, 0x00, 0x41, 0x00, 0x00, 0x82, 0x01, 0x00, 0x10, 0x10,
+ 0x00, 0x80, 0x61, 0x00, 0x00, 0x06, 0x01, 0x00, 0x10, 0x10, 0x00, 0x80,
+ 0x30, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x10, 0x10, 0x00, 0xc0, 0x10, 0x00,
+ 0x00, 0x18, 0x02, 0xff, 0x1f, 0xf0, 0xff, 0x60, 0x18, 0x00, 0x00, 0x30,
+ 0xfe, 0x01, 0x00, 0x00, 0x80, 0x3f, 0x0c, 0x00, 0x00, 0x20, 0x00, 0x40,
+ 0x08, 0x21, 0x04, 0x00, 0x06, 0x00, 0x00, 0xc0, 0x00, 0xe2, 0x9c, 0x73,
+ 0x8e, 0x00, 0x03, 0x00, 0x00, 0x80, 0x11, 0x47, 0x08, 0x21, 0xc4, 0x11,
+ 0x01, 0x00, 0x00, 0x00, 0x3b, 0x02, 0x00, 0x00, 0x80, 0xb8, 0x00, 0x00,
+ 0x00, 0x00, 0x12, 0x00, 0xff, 0xff, 0x03, 0x90, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0xfc, 0x01, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x07,
+ 0x80, 0x03, 0x80, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xe0, 0x0f,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, 0xf8, 0x3f, 0x00, 0x5c,
+ 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0xe0, 0x0f, 0x00, 0x5f, 0x00, 0x00,
+ 0x00, 0x00, 0xfa, 0x03, 0x80, 0x03, 0xc0, 0x5f, 0x00, 0x00, 0x00, 0x00,
+ 0xfa, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00,
+ 0xff, 0xff, 0x03, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfc, 0x01, 0x00,
+ 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x07, 0x00, 0x00, 0x80, 0x5f,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/king_small.bitmap b/gnu/games/chess/Xchess/king_small.bitmap
new file mode 100644
index 000000000000..38bb2b7e88b8
--- /dev/null
+++ b/gnu/games/chess/Xchess/king_small.bitmap
@@ -0,0 +1,15 @@
+
+#define king_small_width 32
+#define king_small_height 32
+static char king_small_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xe0, 0x00, 0x00, 0x80, 0x9f, 0x00, 0x00, 0x70, 0x20, 0x00,
+ 0x00, 0x0c, 0x40, 0x00, 0x00, 0x02, 0x80, 0x01, 0x80, 0x01, 0x00, 0x03,
+ 0x40, 0x00, 0x00, 0x06, 0x40, 0x60, 0x30, 0x08, 0x20, 0x60, 0x30, 0x10,
+ 0x20, 0x00, 0x00, 0x60, 0x20, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x80,
+ 0x10, 0x00, 0x02, 0x80, 0x10, 0x00, 0x01, 0x80, 0x10, 0x01, 0x01, 0x80,
+ 0x10, 0x03, 0x1f, 0x84, 0x10, 0x02, 0x00, 0x84, 0x10, 0x06, 0x00, 0x86,
+ 0x20, 0x1c, 0x00, 0x42, 0x20, 0xf0, 0xff, 0x43, 0x20, 0x00, 0x00, 0x40,
+ 0x40, 0x00, 0x00, 0x20, 0x40, 0x00, 0x00, 0x20, 0x80, 0x01, 0x00, 0x18,
+ 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/king_small_outline.bitmap b/gnu/games/chess/Xchess/king_small_outline.bitmap
new file mode 100644
index 000000000000..18d569e9d7b9
--- /dev/null
+++ b/gnu/games/chess/Xchess/king_small_outline.bitmap
@@ -0,0 +1,15 @@
+
+#define king_small_outline_width 32
+#define king_small_outline_height 32
+static char king_small_outline_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x90, 0x00, 0x06, 0x10, 0xb1, 0x00,
+ 0x22, 0x12, 0xe1, 0x00, 0x24, 0x92, 0x9f, 0x00, 0x40, 0x72, 0xa0, 0x50,
+ 0x04, 0x0e, 0x40, 0x50, 0x40, 0x02, 0x80, 0x71, 0xc8, 0x01, 0x00, 0x73,
+ 0xd8, 0x00, 0x00, 0x46, 0xd8, 0x60, 0x30, 0x08, 0xa0, 0x60, 0x30, 0x10,
+ 0x20, 0x00, 0x00, 0x60, 0x20, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x80,
+ 0x10, 0x00, 0x02, 0x80, 0x10, 0x00, 0x01, 0x80, 0x10, 0x01, 0x01, 0x80,
+ 0x10, 0x03, 0x1f, 0x84, 0x10, 0x02, 0x00, 0x84, 0x10, 0x06, 0x00, 0x86,
+ 0x20, 0x1c, 0x00, 0x42, 0x20, 0xf0, 0xff, 0x43, 0x20, 0x00, 0x00, 0x40,
+ 0x40, 0x00, 0x00, 0x20, 0x40, 0x00, 0x00, 0x20, 0x80, 0x01, 0x00, 0x18,
+ 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/knight.bitmap b/gnu/games/chess/Xchess/knight.bitmap
new file mode 100644
index 000000000000..c5b1de1997f4
--- /dev/null
+++ b/gnu/games/chess/Xchess/knight.bitmap
@@ -0,0 +1,71 @@
+
+#define knight_width 80
+#define knight_height 80
+static char knight_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xe0, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xbf, 0xff,
+ 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0xfe, 0x0f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xf8, 0xff, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0xe0, 0x0f, 0xfc, 0xe3, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf0, 0xe1, 0xf3, 0xcf, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xfd,
+ 0xff, 0x1f, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3f, 0xfe, 0x7f,
+ 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xfe, 0xff, 0xfc, 0x07,
+ 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x7f, 0x00, 0x00,
+ 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xe7, 0x1f, 0x00, 0x00, 0x00, 0xe0,
+ 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0x03, 0x00, 0x00, 0xf0, 0xff, 0xff,
+ 0xff, 0xff, 0x9f, 0x3f, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff,
+ 0x3f, 0xff, 0x07, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe,
+ 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfc, 0x07, 0x00,
+ 0x00, 0xfe, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xfd, 0x01, 0x00, 0x00, 0xff,
+ 0xff, 0xff, 0xff, 0x3f, 0xff, 0xfb, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xbf, 0xff, 0xf3, 0x03, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x9f,
+ 0xff, 0xf7, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xef,
+ 0x07, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x7f, 0xf3, 0xff, 0xcf, 0x7f, 0x00,
+ 0xe0, 0xff, 0xff, 0xff, 0x1f, 0xfd, 0xff, 0xdf, 0x07, 0x00, 0xe0, 0xff,
+ 0xff, 0xff, 0x83, 0xff, 0xf3, 0x9f, 0xff, 0x00, 0xf0, 0xff, 0xff, 0x7f,
+ 0x80, 0xff, 0xf9, 0xbf, 0x0f, 0x00, 0xf0, 0xff, 0xff, 0x00, 0x80, 0x7f,
+ 0xfc, 0x7f, 0xff, 0x01, 0xf8, 0x3f, 0x7f, 0x00, 0x80, 0x81, 0xff, 0x7f,
+ 0x1e, 0x00, 0x18, 0x9f, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0x7f, 0xfe, 0x07,
+ 0x98, 0x8f, 0x1f, 0x00, 0xc0, 0xff, 0xcf, 0x7f, 0x3e, 0x00, 0xf8, 0x87,
+ 0x0f, 0x00, 0xe0, 0xff, 0xe3, 0xff, 0xfe, 0x07, 0xf0, 0xc3, 0x07, 0x00,
+ 0xf0, 0x1f, 0xfc, 0xff, 0x3c, 0x00, 0xf0, 0xe1, 0x03, 0x00, 0xf0, 0xc0,
+ 0xff, 0xff, 0xfc, 0x0f, 0x60, 0xe0, 0x01, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0x7c, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0x0f,
+ 0x00, 0x70, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x7c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xf9, 0x0f, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
+ 0xff, 0xff, 0xf9, 0x0f, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff,
+ 0xf9, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x1f,
+ 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x01, 0x00, 0x00,
+ 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x3f, 0x00, 0x00, 0x00, 0xf0,
+ 0xff, 0xff, 0xff, 0xff, 0xf3, 0x01, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
+ 0xff, 0xff, 0xf3, 0x3f, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff,
+ 0xf3, 0x01, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x3f,
+ 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x01, 0x00, 0x00,
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x3f, 0x00, 0x00, 0x00, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xf3, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xf3, 0x3f, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf3, 0x01, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x3f,
+ 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x01, 0x00, 0x00,
+ 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x3f, 0x00, 0x00, 0xe0, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xf3, 0x01, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xf3, 0x3f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf3, 0x01, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x3f,
+ 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x01, 0x00, 0x00,
+ 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x3f, 0x00, 0x00, 0xfc, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xf3, 0x01, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xf3, 0x3f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf3, 0x01, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/knight_mask.bitmap b/gnu/games/chess/Xchess/knight_mask.bitmap
new file mode 100644
index 000000000000..97d288c60554
--- /dev/null
+++ b/gnu/games/chess/Xchess/knight_mask.bitmap
@@ -0,0 +1,71 @@
+
+#define knight_mask_width 80
+#define knight_mask_height 80
+static char knight_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xf0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
+ 0xfc, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
+ 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00,
+ 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xf8,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xfc, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x0f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00,
+ 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x7f, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x7f, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, 0xff, 0xff,
+ 0xc7, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfc, 0xff, 0xff, 0xff, 0xc1, 0xff,
+ 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0x01, 0xc0, 0xff, 0xff, 0xff,
+ 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x0f,
+ 0xfc, 0xff, 0x7f, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xfc, 0xdf,
+ 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xfc, 0xef, 0x1f, 0x00,
+ 0xf8, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf8, 0xf7, 0x0f, 0x00, 0xfc, 0xff,
+ 0xff, 0xff, 0xff, 0x1f, 0xf8, 0xfb, 0x07, 0x00, 0xfc, 0xff, 0xff, 0xff,
+ 0xff, 0x1f, 0xf0, 0xf9, 0x03, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x1f,
+ 0x00, 0xf8, 0x01, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0xf8,
+ 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x80,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x1f, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f,
+ 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00,
+ 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0xfc,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00,
+ 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xc0, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x7f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00,
+ 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf8, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x7f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+ 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/knight_outline.bitmap b/gnu/games/chess/Xchess/knight_outline.bitmap
new file mode 100644
index 000000000000..a1ab938b773f
--- /dev/null
+++ b/gnu/games/chess/Xchess/knight_outline.bitmap
@@ -0,0 +1,71 @@
+
+#define knight_outline_width 80
+#define knight_outline_height 80
+static char knight_outline_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf9, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x0f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x80,
+ 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0xe0, 0xf0, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x30, 0x58, 0x07, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x18, 0x4c,
+ 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x78, 0x07, 0x00,
+ 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x23, 0xe0, 0x01, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00,
+ 0x00, 0xc0, 0x08, 0x00, 0x00, 0x40, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60,
+ 0x04, 0x00, 0x00, 0x40, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x30, 0x02, 0x00,
+ 0x00, 0x60, 0x00, 0x20, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x20,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x80,
+ 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x20, 0x00, 0x80, 0x07, 0x00,
+ 0x00, 0x26, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x13,
+ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x1f, 0x00, 0x00, 0x09, 0x40, 0x00,
+ 0x00, 0x18, 0x08, 0x00, 0x02, 0x00, 0x80, 0x05, 0xc0, 0x00, 0x00, 0x0c,
+ 0x0c, 0x00, 0x3e, 0x00, 0x80, 0x00, 0x80, 0x00, 0xc0, 0x03, 0x06, 0x00,
+ 0x04, 0x00, 0xc0, 0x00, 0x80, 0x01, 0x70, 0x01, 0xc3, 0x00, 0x7c, 0x00,
+ 0x60, 0x00, 0x00, 0x03, 0x1e, 0x81, 0x41, 0x00, 0x04, 0x00, 0x20, 0x00,
+ 0x00, 0xce, 0x83, 0x61, 0x60, 0x00, 0xfc, 0x00, 0x30, 0x00, 0x80, 0x7f,
+ 0x80, 0x1c, 0x30, 0x00, 0x08, 0x00, 0x10, 0xe0, 0xc1, 0x00, 0x80, 0x07,
+ 0x10, 0x00, 0xf8, 0x01, 0x18, 0x30, 0x61, 0x00, 0x80, 0x00, 0x08, 0x00,
+ 0x10, 0x00, 0x08, 0x98, 0x31, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xf0, 0x07,
+ 0x08, 0x8c, 0x18, 0x00, 0x40, 0x00, 0x03, 0x00, 0x20, 0x00, 0x18, 0x86,
+ 0x0c, 0x00, 0x60, 0xc0, 0x01, 0x00, 0xe0, 0x07, 0x10, 0xc3, 0x06, 0x00,
+ 0x30, 0x30, 0x00, 0x00, 0x20, 0x00, 0xf0, 0x61, 0x02, 0x00, 0x10, 0x1e,
+ 0x00, 0x00, 0xe0, 0x0f, 0x60, 0x30, 0x02, 0x00, 0x98, 0x03, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x02, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xc0, 0x0f,
+ 0x00, 0xb0, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xc0,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+ 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+ 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/knight_small.bitmap b/gnu/games/chess/Xchess/knight_small.bitmap
new file mode 100644
index 000000000000..77c74517f0f6
--- /dev/null
+++ b/gnu/games/chess/Xchess/knight_small.bitmap
@@ -0,0 +1,15 @@
+
+#define knight_small_width 32
+#define knight_small_height 32
+static char knight_small_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x00, 0x00, 0xee, 0x7f, 0x02,
+ 0x00, 0xfe, 0x7f, 0x01, 0x00, 0xff, 0xff, 0x04, 0x00, 0xff, 0xff, 0x02,
+ 0x80, 0xff, 0xff, 0x09, 0xc0, 0xfc, 0xff, 0x07, 0xe0, 0xfc, 0xff, 0x11,
+ 0xe0, 0xff, 0xff, 0x0d, 0xe0, 0xff, 0xff, 0x03, 0xf0, 0xff, 0xff, 0x3f,
+ 0xf0, 0xff, 0xff, 0x03, 0xf0, 0xff, 0xff, 0x7f, 0xf8, 0xff, 0xff, 0x07,
+ 0xfc, 0xc7, 0xff, 0x7f, 0xfe, 0xc1, 0xff, 0x07, 0xfa, 0xc1, 0xff, 0x7f,
+ 0xce, 0xc0, 0xff, 0x07, 0x6c, 0xc0, 0xff, 0x7f, 0x28, 0xe0, 0xff, 0x07,
+ 0x00, 0xe0, 0xff, 0x7f, 0x00, 0xe0, 0xff, 0x0f, 0x00, 0xf0, 0xff, 0x7f,
+ 0x00, 0xf0, 0xff, 0x0f, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0xf8, 0xff, 0x0f,
+ 0x00, 0xf8, 0xff, 0x7f, 0x00, 0xfc, 0xff, 0x0f, 0x00, 0xff, 0xff, 0x7f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/knight_small_outline.bitmap b/gnu/games/chess/Xchess/knight_small_outline.bitmap
new file mode 100644
index 000000000000..c0e738c6db4c
--- /dev/null
+++ b/gnu/games/chess/Xchess/knight_small_outline.bitmap
@@ -0,0 +1,15 @@
+
+#define knight_small_outline_width 32
+#define knight_small_outline_height 32
+static char knight_small_outline_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x00, 0x00, 0xee, 0x7f, 0x02,
+ 0x00, 0x3a, 0x40, 0x01, 0x00, 0x03, 0xc0, 0x04, 0x00, 0x01, 0x80, 0x02,
+ 0x80, 0x01, 0x80, 0x09, 0xc0, 0x0c, 0x00, 0x07, 0x60, 0x0c, 0x00, 0x11,
+ 0x20, 0x00, 0x00, 0x0d, 0x20, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00, 0x3e,
+ 0x10, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x7e, 0x18, 0x7c, 0x00, 0x04,
+ 0x0c, 0x47, 0x00, 0x7c, 0x06, 0x41, 0x00, 0x04, 0xf2, 0x41, 0x00, 0x7c,
+ 0xde, 0x40, 0x00, 0x04, 0x6c, 0x40, 0x00, 0x7c, 0x28, 0x60, 0x00, 0x04,
+ 0x00, 0x20, 0x00, 0x7c, 0x00, 0x20, 0x00, 0x08, 0x00, 0x30, 0x00, 0x78,
+ 0x00, 0x10, 0x00, 0x08, 0x00, 0x10, 0x00, 0x78, 0x00, 0x18, 0x00, 0x08,
+ 0x00, 0x08, 0x00, 0x78, 0x00, 0x0c, 0x00, 0x08, 0x00, 0xff, 0xff, 0x7f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/message.c b/gnu/games/chess/Xchess/message.c
new file mode 100644
index 000000000000..8b85e9c77f83
--- /dev/null
+++ b/gnu/games/chess/Xchess/message.c
@@ -0,0 +1,101 @@
+
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/26 12:10:22 $
+ * $Source: /users/faustus/xchess/RCS/message.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ *
+ * Do stuff with the message window. Font 0 is the normal font, font 1
+ * is large, and font 2 is normal red.
+ */
+
+#include "xchess.h"
+
+#define MESSAGE_HEADER "\n1 XChess Messages0\n"
+
+void
+message_init(win)
+ windata *win;
+{
+ TxtGrab(win->display, win->messagewin, "xchess", win->medium,
+ win->textback.pixel, win->textcolor.pixel,
+ win->cursorcolor.pixel);
+ TxtAddFont(win->display, win->messagewin, 1, win->large, win->textcolor.pixel);
+ TxtAddFont(win->display, win->messagewin, 2, win->medium, win->errortext.pixel);
+ TxtAddFont(win->display, win->messagewin, 3, win->medium, win->playertext.pixel);
+
+ TxtWriteStr(win->display, win->messagewin, MESSAGE_HEADER);
+ return;
+}
+
+void
+message_add(win, string, err)
+ windata *win;
+ char *string;
+ bool err;
+{
+ if (err) {
+ TxtWriteStr(win->display, win->messagewin, "2");
+ TxtWriteStr(win->display, win->messagewin, string);
+ TxtWriteStr(win->display, win->messagewin, "0");
+ XBell(win->display, 50);
+ } else
+ TxtWriteStr(win->display, win->messagewin, string);
+
+ XSync(win->display, 0);
+ return;
+}
+
+void
+message_send(win, event)
+ windata *win;
+ XEvent *event;
+{
+ XKeyEvent *ev = &event->xkey;
+ KeySym keysym;
+ windata *ow = (win == win1) ? win2 : win1;
+ char buf[BSIZE], *s;
+ int i;
+
+ i = XLookupString(ev, buf, sizeof(buf) - 1, &keysym, &s);
+ buf[i] = '\0';
+ for (s = buf; *s; s++)
+ if (*s == '\r')
+ *s = '\n';
+ else if (*s == '\177')
+ *s = '';
+
+ TxtWriteStr(win->display, win->messagewin, "3");
+ TxtWriteStr(win->display, win->messagewin, buf);
+ TxtWriteStr(win->display, win->messagewin, "0");
+ XSync(win->display, 0);
+ if (ow) {
+ TxtWriteStr(ow->display, ow->messagewin, "3");
+ TxtWriteStr(ow->display, ow->messagewin, buf);
+ TxtWriteStr(ow->display, ow->messagewin, "0");
+ XSync(ow->display, 0);
+ }
+ return;
+}
+
diff --git a/gnu/games/chess/Xchess/parse.c b/gnu/games/chess/Xchess/parse.c
new file mode 100644
index 000000000000..c66cc38bdbfe
--- /dev/null
+++ b/gnu/games/chess/Xchess/parse.c
@@ -0,0 +1,386 @@
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.2 $ on $Date: 86/11/23 17:17:59 $
+ * $Source: /users/faustus/xchess/RCS/parse.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ *
+ * Parse a sequence of chess moves...
+ */
+
+#include "xchess.h"
+
+bool loading_flag = false;
+bool loading_paused = false;
+
+static char *line;
+
+/* Load a record file in. This returns a number of things -- the board, the
+ * list of moves, and whose turn it is.
+ */
+
+void
+load_game(file)
+ char *file;
+{
+ FILE *fp;
+ char buf[BSIZE];
+ bool eflag;
+ move *m;
+ board *tmpboard = alloc(board);
+
+ if (eq(file, "xchess.game") && saveflag) {
+ message_add(win1,
+ "Oops, I just overwrote the\nfile xchess.game...\n",
+ true);
+ message_add(win1, "I hope you had another copy.\n", true);
+ return;
+ }
+ if (!(fp = fopen(file, "r"))) {
+ perror(file);
+ return;
+ }
+
+ /* Get a few lines... */
+ fgets(buf, BSIZE, fp);
+ message_add(win1, buf, false);
+ if (!oneboard)
+ message_add(win2, buf, false);
+
+ fgets(buf, BSIZE, fp);
+ message_add(win1, buf, false);
+ if (!oneboard)
+ message_add(win2, buf, false);
+
+ fgets(buf, BSIZE, fp);
+ if (eq(buf, "\tenglish\n"))
+ eflag = true;
+ else if (eq(buf, "\talgebraic\n"))
+ eflag = false;
+ else {
+ fprintf(stderr, "Can't decide whether this is english...\n");
+ return;
+ }
+
+ board_init(tmpboard);
+ line = NULL;
+ m = parse_file(fp, tmpboard, eflag);
+ tfree(tmpboard);
+
+ /* Now apply these moves to the board we were given... */
+ loading_flag = true;
+ while (m) {
+ if (!quickflag)
+ XSync(win1->display, 0);
+ win_process(true);
+ if (!quickflag)
+ sleep(1);
+ if (!loading_paused) {
+ prog_move(m);
+ m = m->next;
+ }
+ }
+ loading_flag = false;
+ if (line)
+ message_add(win1, line, false);
+
+ while (fgets(buf, BSIZE, fp))
+ message_add(win1, buf, false);
+
+ fclose(fp);
+
+ return;
+}
+
+/* Given a starting position (usually the beginning board configuration),
+ * read in a file of moves.
+ */
+
+move *
+parse_file(fp, b, english)
+ FILE *fp;
+ board *b;
+ bool english;
+{
+ move *mvs = NULL, *end = NULL;
+ char buf[BSIZE], *s, *t;
+
+ while (fgets(buf, BSIZE, fp)) {
+ if (*buf == '#')
+ continue;
+ s = buf;
+
+ /* The move number... */
+ if (!(t = gettok(&s)))
+ break;
+ if (!isdigit(*t)) {
+ line = copy(buf);
+ break;
+ }
+
+ if (!(t = gettok(&s)))
+ break;
+ if (end)
+ end = end->next = (english ? parse_move(b, t, WHITE) :
+ parse_imove(b, t, WHITE));
+ else
+ mvs = end = (english ? parse_move(b, t, WHITE) :
+ parse_imove(b, t, WHITE));
+ if (!end) {
+ fprintf(stderr, "Can't parse %s\n", buf);
+ return (NULL);
+ }
+ board_move(b, end);
+
+ if (!(t = gettok(&s)))
+ break;
+ if (end)
+ end = end->next = (english ? parse_move(b, t, BLACK) :
+ parse_imove(b, t, BLACK));
+ else
+ mvs = end = (english ? parse_move(b, t, BLACK) :
+ parse_imove(b, t, BLACK));
+ if (!end) {
+ fprintf(stderr, "Can't parse %s\n", buf);
+ return (NULL);
+ }
+ board_move(b, end);
+ }
+
+ return (mvs);
+}
+
+/* Parse a move. The move format accepted is as follows -
+ * move: spec-spec
+ * capture: specxspec
+ * kcastle: 2 o's
+ * qcastle: 3 o's
+ * A spec is either piece/pos, piece, or just pos. A pos consists of a column
+ * name followed by a row number. If the column name is kr, kn, kb, k, q,
+ * qb, qn, or qr, then the row number is according to the english system,
+ * or if it is a-h then it is according to the international system.
+ *
+ *** As of now the spec must include the position.
+ */
+
+move *
+parse_move(b, str, w)
+ board *b;
+ char *str;
+ color w;
+{
+ move *m = alloc(move);
+ char *s;
+ char spec1[16], spec2[16];
+ int i, j;
+
+if (debug) fprintf(stderr, "parsing %s\n", str);
+
+ /* Check for castles. */
+ for (s = str, i = 0; *s; s++)
+ if ((*s == 'o') || (*s == 'O'))
+ i++;
+ if (i == 2) {
+ m->type = KCASTLE;
+ m->piece.type = KING;
+ m->piece.color = w;
+ return (m);
+ } else if (i == 3) {
+ m->type = QCASTLE;
+ m->piece.type = KING;
+ m->piece.color = w;
+ return (m);
+ }
+ if (index(str, '-'))
+ m->type = MOVE;
+ else if (index(str, 'x'))
+ m->type = CAPTURE;
+ else
+ return (NULL);
+ for (i = 0; str[i]; i++)
+ if ((str[i] == 'x') || (str[i] == '-'))
+ break;
+ else
+ spec1[i] = str[i];
+ spec1[i] = '\0';
+ for (i++, j = 0; str[i]; i++, j++)
+ if ((str[i] == 'x') || (str[i] == '-'))
+ break;
+ else
+ spec2[j] = str[i];
+ spec2[j] = '\0';
+
+ /* Now decode the specifications. */
+ s = spec1;
+ switch (*s) {
+ case 'p': case 'P':
+ m->piece.type = PAWN; break;
+ case 'r': case 'R':
+ m->piece.type = ROOK; break;
+ case 'n': case 'N':
+ m->piece.type = KNIGHT; break;
+ case 'b': case 'B':
+ m->piece.type = BISHOP; break;
+ case 'q': case 'Q':
+ m->piece.type = QUEEN; break;
+ case 'k': case 'K':
+ m->piece.type = KING; break;
+ default:
+ return (NULL);
+ }
+ m->piece.color = w;
+ s += 2;
+
+ /* Now get the {q,k}{,b,n,r}n string... */
+ if ((s[0] == 'q') && (s[1] == 'r'))
+ m->fromx = 0, s += 2;
+ else if ((s[0] == 'q') && (s[1] == 'n'))
+ m->fromx = 1, s += 2;
+ else if ((s[0] == 'q') && (s[1] == 'b'))
+ m->fromx = 2, s += 2;
+ else if ((s[0] == 'q') && isdigit(s[1]))
+ m->fromx = 3, s += 1;
+ else if ((s[0] == 'k') && isdigit(s[1]))
+ m->fromx = 4, s += 1;
+ else if ((s[0] == 'k') && (s[1] == 'b'))
+ m->fromx = 5, s += 2;
+ else if ((s[0] == 'k') && (s[1] == 'n'))
+ m->fromx = 6, s += 2;
+ else if ((s[0] == 'k') && (s[1] == 'r'))
+ m->fromx = 7, s += 2;
+ m->fromy = ((w == WHITE) ? (SIZE - atoi(s)) : (atoi(s) - 1));
+
+ if ((b->square[m->fromy][m->fromx].color != w) ||
+ (b->square[m->fromy][m->fromx].type != m->piece.type)) {
+ fprintf(stderr, "Error: bad stuff\n");
+ return (NULL);
+ }
+
+ s = spec2;
+ if (m->type == CAPTURE) {
+ switch (*s) {
+ case 'p': case 'P':
+ m->taken.type = PAWN; break;
+ case 'r': case 'R':
+ m->taken.type = ROOK; break;
+ case 'n': case 'N':
+ m->taken.type = KNIGHT; break;
+ case 'b': case 'B':
+ m->taken.type = BISHOP; break;
+ case 'q': case 'Q':
+ m->taken.type = QUEEN; break;
+ case 'k': case 'K':
+ m->taken.type = KING; break;
+ default:
+ return (NULL);
+ }
+ m->taken.color = ((w == WHITE) ? BLACK : WHITE);
+ s += 2;
+ }
+
+ /* Now get the {q,k}{,b,n,r}n string... */
+ if ((s[0] == 'q') && (s[1] == 'r'))
+ m->tox = 0, s += 2;
+ else if ((s[0] == 'q') && (s[1] == 'n'))
+ m->tox = 1, s += 2;
+ else if ((s[0] == 'q') && (s[1] == 'b'))
+ m->tox = 2, s += 2;
+ else if ((s[0] == 'q') && isdigit(s[1]))
+ m->tox = 3, s += 1;
+ else if ((s[0] == 'k') && isdigit(s[1]))
+ m->tox = 4, s += 1;
+ else if ((s[0] == 'k') && (s[1] == 'b'))
+ m->tox = 5, s += 2;
+ else if ((s[0] == 'k') && (s[1] == 'n'))
+ m->tox = 6, s += 2;
+ else if ((s[0] == 'k') && (s[1] == 'r'))
+ m->tox = 7, s += 2;
+ m->toy = ((w == WHITE) ? (SIZE - atoi(s)) : (atoi(s) - 1));
+
+ if ((m->type == CAPTURE) && ((b->square[m->toy][m->tox].color !=
+ m->taken.color) || (b->square[m->toy][m->tox].type !=
+ m->taken.type))) {
+ fprintf(stderr, "Error: bad stuff\n");
+ return (NULL);
+ }
+
+ return (m);
+}
+
+/* Parse an algebraic notation move. This is a lot easier... */
+
+move *
+parse_imove(b, buf, w)
+ board *b;
+ char *buf;
+ color w;
+{
+ char *s;
+ move *m = alloc(move);
+ int n;
+
+if (debug) fprintf(stderr, "(alg) parsing %s\n", buf);
+
+ for (s = buf, n = 0; *s; s++)
+ if ((*s == 'o') || (*s == 'O'))
+ n++;
+ s = buf;
+
+ if (n == 2)
+ m->type = KCASTLE;
+ else if (n == 3)
+ m->type = QCASTLE;
+ else {
+ m->fromx = *s++ - 'a';
+ m->fromy = SIZE - (*s++ - '0');
+ m->tox = *s++ - 'a';
+ m->toy = SIZE - (*s++ - '0');
+ m->piece = b->square[m->fromy][m->fromx];
+ m->taken = b->square[m->toy][m->tox];
+ if (m->taken.color == NONE)
+ m->type = MOVE;
+ else
+ m->type = CAPTURE;
+ /* for pawns we must account for en passant */
+ if (m->piece.type == PAWN) {
+ if (m->type == MOVE && m->fromx != m->tox) {
+ m->enpassant = 1;
+ m->type = CAPTURE;
+ }
+ }
+ }
+
+ if (m->piece.color != w) {
+ fprintf(stderr, "Error: parse_imove: piece of wrong color!\n");
+ return (NULL);
+ }
+ if ((m->piece.type == KING) && (m->fromy == m->toy) && (m->fromx == 4)
+ && (m->tox == 6))
+ m->type = KCASTLE;
+ else if ((m->piece.type == KING) && (m->fromy == m->toy) &&
+ (m->fromx == 4) && (m->tox == 2))
+ m->type = QCASTLE;
+
+ return (m);
+}
+
diff --git a/gnu/games/chess/Xchess/pawn.bitmap b/gnu/games/chess/Xchess/pawn.bitmap
new file mode 100644
index 000000000000..5c3ff76dbf68
--- /dev/null
+++ b/gnu/games/chess/Xchess/pawn.bitmap
@@ -0,0 +1,71 @@
+
+#define pawn_width 80
+#define pawn_height 80
+static char pawn_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf8, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x07, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
+ 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff,
+ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xf8, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
+ 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xf0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff,
+ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xc0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+ 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
+ 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x03, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00,
+ 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00,
+ 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xfe, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x1f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/pawn_mask.bitmap b/gnu/games/chess/Xchess/pawn_mask.bitmap
new file mode 100644
index 000000000000..724875c59972
--- /dev/null
+++ b/gnu/games/chess/Xchess/pawn_mask.bitmap
@@ -0,0 +1,71 @@
+
+#define pawn_mask_width 80
+#define pawn_mask_height 80
+static char pawn_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff,
+ 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
+ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+ 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff,
+ 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xf0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
+ 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff,
+ 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
+ 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xf0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x7f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff,
+ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x0f,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xf0, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x0f, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
+ 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x80, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x3f, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x3f, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+ 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/pawn_outline.bitmap b/gnu/games/chess/Xchess/pawn_outline.bitmap
new file mode 100644
index 000000000000..0c4a3a13229a
--- /dev/null
+++ b/gnu/games/chess/Xchess/pawn_outline.bitmap
@@ -0,0 +1,71 @@
+
+#define pawn_outline_width 80
+#define pawn_outline_height 80
+static char pawn_outline_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x70,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xc0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x80, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x30, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xe0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xe0, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x80, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+ 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x30, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0xff, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x78, 0xc0, 0x81, 0x07, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0xc0, 0x7f, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/pawn_small.bitmap b/gnu/games/chess/Xchess/pawn_small.bitmap
new file mode 100644
index 000000000000..88ff7bbcd16f
--- /dev/null
+++ b/gnu/games/chess/Xchess/pawn_small.bitmap
@@ -0,0 +1,15 @@
+
+#define pawn_small_width 32
+#define pawn_small_height 32
+static char pawn_small_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xf0, 0x0f, 0x00,
+ 0x00, 0xf8, 0x1f, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0xf8, 0x1f, 0x00,
+ 0x00, 0xf8, 0x1f, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0xf0, 0x0f, 0x00,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x80, 0xff, 0xff, 0x01,
+ 0x80, 0xff, 0xff, 0x01, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
+ 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0xfc, 0x3f, 0x00,
+ 0x00, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0x0f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/pawn_small_outline.bitmap b/gnu/games/chess/Xchess/pawn_small_outline.bitmap
new file mode 100644
index 000000000000..e860f43f3d50
--- /dev/null
+++ b/gnu/games/chess/Xchess/pawn_small_outline.bitmap
@@ -0,0 +1,15 @@
+
+#define pawn_small_outline_width 32
+#define pawn_small_outline_height 32
+static char pawn_small_outline_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x30, 0x0c, 0x00,
+ 0x00, 0x18, 0x18, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08, 0x10, 0x00,
+ 0x00, 0x08, 0x10, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x30, 0x0c, 0x00,
+ 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00, 0x80, 0x3f, 0xfc, 0x01,
+ 0x80, 0x3f, 0xfc, 0x01, 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00,
+ 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00,
+ 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00,
+ 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00,
+ 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x0c, 0x30, 0x00,
+ 0x00, 0x07, 0xe0, 0x00, 0xe0, 0x01, 0x80, 0x07, 0xf0, 0xff, 0xff, 0x0f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/popup.c b/gnu/games/chess/Xchess/popup.c
new file mode 100644
index 000000000000..2e19ee5b4c35
--- /dev/null
+++ b/gnu/games/chess/Xchess/popup.c
@@ -0,0 +1,112 @@
+
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.2 $ on $Date: 86/11/26 12:10:38 $
+ * $Source: /users/faustus/xchess/RCS/popup.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * faustus@cad.berkeley.edu, ucbvax!faustus
+ * Permission is granted to modify and re-distribute this code in any manner
+ * as long as this notice is preserved. All standard disclaimers apply.
+ *
+ * A simple pop-up menu system.
+ */
+
+#include "xchess.h"
+
+/* Open a small window with some text in it and two buttons -- yes and no.
+ * Use black and white pixel, and the medium font.
+ */
+
+bool
+pop_question(win, text)
+ windata *win;
+ char *text;
+{
+ char *s, *t;
+ int nlines = 1, ncols = 0, i = 0, j;
+ int x, y;
+ Window w;
+ bool ch;
+ XEvent ev;
+
+ for (s = text; *s; s++) {
+ if ((*s == '\n') && s[1])
+ nlines++;
+ if ((*s == '\n') || !s[1]) {
+ if (i > ncols)
+ ncols = i;
+ i = 0;
+ } else
+ i++;
+ }
+
+ if (ncols < 12)
+ ncols = 12;
+ nlines += 4;
+ ncols += 4;
+
+ x = (BASE_WIDTH - ncols * win->medium->max_bounds.width) / 2;
+ y = (BASE_HEIGHT - nlines * win->medium->max_bounds.ascent) / 2;
+
+ w = XCreateSimpleWindow(win->display, win->basewin,
+ x, y, ncols * win->medium->max_bounds.width,
+ nlines * win->medium->ascent,
+ BORDER_WIDTH, win->border.pixel,
+ win->textback.pixel);
+ XMapRaised(win->display, w);
+ XSetFont(win->display, DefaultGC(win->display, 0),
+ win->medium->fid);
+
+ for (i = 0, s = text; i < nlines - 4; i++) {
+ for (t = s, j = 0; *t && (*t != '\n'); t++, j++)
+ ;
+ XDrawString(win->display, w, DefaultGC(win->display, 0),
+ (ncols - j) / 2 * win->medium->max_bounds.width,
+ (i + 1) * win->medium->ascent,
+ s, j);
+ s = t + 1;
+ }
+ XDrawString(win->display, w, DefaultGC(win->display, 0),
+ (ncols - 8) * win->medium->max_bounds.width / 4,
+ (nlines - 2) * win->medium->ascent,
+ "YES", 3);
+ XDrawString(win->display, w, DefaultGC(win->display, 0),
+ (ncols - 4) * win->medium->max_bounds.width * 3 / 4,
+ (nlines - 2) * win->medium->ascent,
+ "NO", 2);
+
+ XSync(win->display, 0);
+ XSelectInput(win->display, w, ButtonPressMask);
+ XWindowEvent(win->display, w, ButtonPressMask, &ev);
+ x = ev.xkey.x;
+ y = ev.xkey.y;
+
+ if (x > ncols * win->medium->max_bounds.width / 2)
+ ch = false;
+ else
+ ch = true;
+
+ XDestroyWindow(win->display, w);
+ XSync(win->display, 0);
+ return (ch);
+}
+
diff --git a/gnu/games/chess/Xchess/program.c b/gnu/games/chess/Xchess/program.c
new file mode 100644
index 000000000000..876f29cb466c
--- /dev/null
+++ b/gnu/games/chess/Xchess/program.c
@@ -0,0 +1,200 @@
+
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.2 $ on $Date: 86/11/23 17:18:10 $
+ * $Source: /users/faustus/xchess/RCS/program.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ *
+ * The interface to whichever chess playing program we are using...
+ */
+
+#include "xchess.h"
+#include <signal.h>
+#include <sys/time.h>
+
+static int pid;
+static FILE *from;
+static FILE *to;
+static bool easy = 1;
+
+bool
+program_init(name)
+ char *name;
+{
+ int toprog[2], fromprog[2];
+ char buf[BSIZE];
+ char time[10];
+ char moves[10];
+
+ pipe(toprog);
+ pipe(fromprog);
+
+ if (!(pid = fork())) {
+ /* Start up the program. */
+ dup2(toprog[0], 0);
+ dup2(fromprog[1], 1);
+ close(toprog[0]);
+ close(toprog[1]);
+ close(fromprog[0]);
+ close(fromprog[1]);
+ sprintf (time, "%d", timeunit/60);
+ sprintf (moves, "%d", movesperunit);
+ if (proghost)
+ execl("/usr/ucb/rsh", "rsh", proghost, name,
+ moves, time,
+ (char *) NULL);
+ else
+ execl(name, name, moves, time, (char *) NULL);
+ perror(name);
+ exit(1);
+ }
+
+ close(toprog[0]);
+ close(fromprog[1]);
+
+ from = fdopen(fromprog[0], "r");
+ setbuf(from, NULL);
+ to = fdopen(toprog[1], "w");
+ setbuf(to, NULL);
+
+ /* Get the first line... */
+ fgets(buf, BSIZE, from);
+ if (debug)
+ fprintf(stderr, "program says %s", buf);
+ if (blackflag) {
+ fputs("switch\n", to);
+ fflush(to);
+ fgets(buf, BSIZE, from);
+ if (debug)
+ fprintf(stderr, "program says %s", buf);
+ message_add(win1, "GNU Chess playing white\n", false);
+ } else
+ message_add(win1, "GNU Chess playing black\n", false);
+
+ return (true);
+}
+
+void
+program_end()
+{
+ fclose(from);
+ fclose(to);
+ kill(pid, SIGTERM);
+ return;
+}
+
+void
+program_send(m)
+ move *m;
+{
+ char buf[BSIZE];
+
+ if ((m->type == MOVE) || (m->type == CAPTURE))
+ sprintf(buf, "%c%d%c%d\n", 'a' + m->fromx, SIZE - m->fromy,
+ 'a' + m->tox, SIZE - m->toy);
+ else if (m->type == KCASTLE)
+ strcpy(buf, (m->piece.color == WHITE) ? "e1g1\n" : "e8g8\n");
+ else if (m->type == QCASTLE)
+ strcpy(buf, (m->piece.color == WHITE) ? "e1c1\n" : "e8c8\n");
+
+ if (debug)
+ fprintf(stderr, "sending program %s", buf);
+ if (!easy)
+ kill (pid, SIGINT);
+
+ fputs(buf, to);
+ fflush(to);
+
+ /* One junk line... */
+ fgets(buf, BSIZE, from);
+ if (debug)
+ fprintf(stderr, "program says %s", buf);
+ return;
+}
+
+move *
+program_get()
+{
+ int rfd = (1 << fileno(from)), wfd = 0, xfd = 0;
+ static struct timeval notime = { 0, 0 };
+ char buf[BSIZE], *s;
+ move *m;
+ int i;
+
+ /* Do a poll... */
+
+ if (!(i = select(32, &rfd, &wfd, &xfd, &notime)) &&
+ !from->_cnt) { /* Bad stuff... */
+ if (debug)
+ fprintf(stderr, "poll: nothing\n");
+ return (NULL);
+ }
+ if (i == -1) {
+ perror("select");
+ return (NULL);
+ }
+
+ fgets(buf, BSIZE, from);
+ if (*buf == '\n' || *buf == '\0') {
+ message_add(win1, "program died", false);
+ return (NULL);
+ }
+
+ if (debug)
+ fprintf(stderr, "got from program %s", buf);
+
+ for (s = buf; !isalpha(*s); s++)
+ ;
+ m = parse_imove(chessboard, s, nexttomove);
+ if (m == NULL)
+ return (NULL);
+
+ if (!valid_move(m, chessboard)) {
+ fprintf(stderr, "Error: move %s is invalid!!\n", buf);
+ return (NULL);
+ }
+
+ /*
+ fgets(buf, BSIZE, from);
+ if (debug)
+ fprintf(stderr, "program says %s", buf);
+ */
+ message_add(win1, buf, false);
+ return (m);
+}
+
+void
+program_undo()
+{
+ fputs("undo\n", to);
+ return;
+}
+void
+program_easy (mode)
+ bool mode;
+
+{
+ fputs("easy\n", to);
+ easy = mode;
+}
diff --git a/gnu/games/chess/Xchess/queen.bitmap b/gnu/games/chess/Xchess/queen.bitmap
new file mode 100644
index 000000000000..ab3817a123a9
--- /dev/null
+++ b/gnu/games/chess/Xchess/queen.bitmap
@@ -0,0 +1,71 @@
+
+#define queen_width 80
+#define queen_height 80
+static char queen_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x80, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x80, 0x01, 0x00, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x80, 0x01, 0x80, 0x0f, 0x00, 0x00,
+ 0x00, 0x00, 0xf0, 0x01, 0xc0, 0x03, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0x00, 0xc0, 0x03, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0xc0, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0xc0, 0x03,
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0xc0, 0x03, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0xc0, 0x03, 0x00, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x03, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0x01, 0xc0, 0x03, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01,
+ 0xe0, 0x07, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0xe0, 0x07,
+ 0xc0, 0x03, 0x00, 0x00, 0x1c, 0x00, 0xc0, 0x03, 0xe0, 0x07, 0xc0, 0x03,
+ 0x00, 0x00, 0x3e, 0x00, 0xc0, 0x03, 0xe0, 0x07, 0xc0, 0x03, 0x00, 0x0e,
+ 0x3e, 0x00, 0xc0, 0x07, 0xe0, 0x07, 0xe0, 0x03, 0x00, 0x1f, 0x3e, 0x00,
+ 0xc0, 0x07, 0xe0, 0x07, 0xe0, 0x03, 0x00, 0x1f, 0x3c, 0x00, 0xc0, 0x07,
+ 0xe0, 0x07, 0xe0, 0x03, 0x00, 0x1f, 0x70, 0x00, 0xc0, 0x0f, 0xe0, 0x07,
+ 0xf0, 0x03, 0x00, 0x0e, 0x60, 0x00, 0xc0, 0x0f, 0xe0, 0x07, 0xf0, 0x03,
+ 0x00, 0x03, 0xe0, 0x00, 0xc0, 0x0f, 0xf0, 0x0f, 0xf0, 0x03, 0x80, 0x03,
+ 0xc0, 0x01, 0xc0, 0x1f, 0xf0, 0x0f, 0xf8, 0x03, 0x80, 0x01, 0xc0, 0x01,
+ 0xc0, 0x1f, 0xf0, 0x0f, 0xf8, 0x03, 0xc0, 0x01, 0xc0, 0x03, 0xc0, 0x1f,
+ 0xf0, 0x0f, 0xf8, 0x03, 0xe0, 0x01, 0xc0, 0x07, 0xc0, 0x1f, 0xf0, 0x0f,
+ 0xf8, 0x03, 0xe0, 0x01, 0xc0, 0x07, 0xc0, 0x3f, 0xf0, 0x0f, 0xfc, 0x03,
+ 0xf0, 0x01, 0xc0, 0x0f, 0xc0, 0x3f, 0xf0, 0x0f, 0xfc, 0x03, 0xf8, 0x01,
+ 0x80, 0x1f, 0xc0, 0x3f, 0xf0, 0x0f, 0xfc, 0x03, 0xf8, 0x01, 0x80, 0x1f,
+ 0xc0, 0x7f, 0xf0, 0x0f, 0xfe, 0x03, 0xfc, 0x01, 0x80, 0x3f, 0xc0, 0x7f,
+ 0xf8, 0x1f, 0xfe, 0x03, 0xfc, 0x00, 0x80, 0x3f, 0xc0, 0x7f, 0xf8, 0x1f,
+ 0xfe, 0x03, 0xfe, 0x00, 0x80, 0x7f, 0xc0, 0xff, 0xf8, 0x1f, 0xff, 0x03,
+ 0xff, 0x00, 0x80, 0xff, 0xc0, 0xff, 0xf8, 0x1f, 0xff, 0x03, 0xff, 0x00,
+ 0x00, 0xff, 0xc0, 0xff, 0xf8, 0x1f, 0xff, 0x83, 0xff, 0x00, 0x00, 0xff,
+ 0xc1, 0xff, 0xf9, 0x9f, 0xff, 0x83, 0xff, 0x00, 0x00, 0xff, 0xc3, 0xff,
+ 0xf9, 0x9f, 0xff, 0xc3, 0xff, 0x00, 0x00, 0xff, 0xc3, 0xff, 0xf9, 0x9f,
+ 0xff, 0xe3, 0x7f, 0x00, 0x00, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xe3,
+ 0x7f, 0x00, 0x00, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x7f, 0x00,
+ 0x00, 0xfe, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x7f, 0x00, 0x00, 0xfe,
+ 0xdf, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x7f, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+ 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xfc,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xfc, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x01, 0x80,
+ 0xff, 0xff, 0x3f, 0x00, 0x00, 0xf8, 0xff, 0x03, 0xfc, 0x3f, 0xc0, 0xff,
+ 0x1f, 0x00, 0x00, 0xf0, 0x01, 0xf8, 0x7f, 0xfe, 0x1f, 0x80, 0x1f, 0x00,
+ 0x00, 0x30, 0xfc, 0xff, 0x1f, 0xf8, 0xff, 0x3f, 0x0c, 0x00, 0x00, 0xe0,
+ 0xe7, 0xff, 0x07, 0xe0, 0xff, 0xe7, 0x07, 0x00, 0x00, 0xc0, 0x81, 0xff,
+ 0x1f, 0xf8, 0xff, 0x81, 0x03, 0x00, 0x00, 0x80, 0x00, 0xfe, 0x7f, 0xfe,
+ 0x7f, 0x00, 0x03, 0x00, 0x00, 0x80, 0x81, 0xff, 0xff, 0xff, 0xff, 0x81,
+ 0x01, 0x00, 0x00, 0x00, 0xe7, 0xff, 0x01, 0x80, 0xff, 0xe7, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0x03, 0xfc, 0x3f, 0xc0, 0xff, 0x00, 0x00, 0x00, 0x80,
+ 0x01, 0xf8, 0xff, 0xff, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0xfc, 0xff,
+ 0xff, 0xff, 0xff, 0x3f, 0x01, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x01, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x03, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00,
+ 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xe0, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/queen_mask.bitmap b/gnu/games/chess/Xchess/queen_mask.bitmap
new file mode 100644
index 000000000000..76a5904e8340
--- /dev/null
+++ b/gnu/games/chess/Xchess/queen_mask.bitmap
@@ -0,0 +1,71 @@
+
+#define queen_mask_width 80
+#define queen_mask_height 80
+static char queen_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01,
+ 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0xc0, 0x03,
+ 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0xc0, 0x03, 0xc0, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0xe0, 0x07, 0xc0, 0x1f, 0x00, 0x00,
+ 0x00, 0x00, 0xf8, 0x03, 0xe0, 0x07, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00,
+ 0xf8, 0x01, 0xe0, 0x07, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01,
+ 0xe0, 0x07, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xe0, 0x07,
+ 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xe0, 0x07, 0x80, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0xe0, 0x07, 0x80, 0x07, 0x00, 0x00,
+ 0x00, 0x00, 0xe0, 0x03, 0xf0, 0x0f, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0x07, 0xf0, 0x0f, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07,
+ 0xf0, 0x0f, 0xc0, 0x07, 0x00, 0x00, 0x7e, 0x00, 0xe0, 0x07, 0xf0, 0x0f,
+ 0xe0, 0x07, 0x00, 0x00, 0x7f, 0x00, 0xe0, 0x0f, 0xf0, 0x0f, 0xe0, 0x07,
+ 0x00, 0x1f, 0x7f, 0x00, 0xe0, 0x0f, 0xf0, 0x0f, 0xe0, 0x07, 0x80, 0x3f,
+ 0x7f, 0x00, 0xe0, 0x0f, 0xf0, 0x0f, 0xf0, 0x07, 0x80, 0x3f, 0x7f, 0x00,
+ 0xe0, 0x0f, 0xf0, 0x0f, 0xf0, 0x07, 0x80, 0x3f, 0xff, 0x00, 0xe0, 0x1f,
+ 0xf0, 0x0f, 0xf0, 0x07, 0x80, 0x3f, 0xfe, 0x00, 0xe0, 0x1f, 0xf0, 0x0f,
+ 0xf8, 0x07, 0x80, 0x1f, 0xfc, 0x01, 0xe0, 0x1f, 0xf8, 0x1f, 0xf8, 0x07,
+ 0x80, 0x1f, 0xf0, 0x03, 0xe0, 0x3f, 0xf8, 0x1f, 0xf8, 0x07, 0xc0, 0x0f,
+ 0xf0, 0x07, 0xe0, 0x3f, 0xf8, 0x1f, 0xfc, 0x07, 0xe0, 0x03, 0xe0, 0x07,
+ 0xe0, 0x3f, 0xf8, 0x1f, 0xfc, 0x07, 0xf0, 0x03, 0xe0, 0x0f, 0xe0, 0x7f,
+ 0xf8, 0x1f, 0xfc, 0x07, 0xf0, 0x03, 0xe0, 0x1f, 0xe0, 0x7f, 0xf8, 0x1f,
+ 0xfc, 0x07, 0xf8, 0x03, 0xe0, 0x1f, 0xe0, 0x7f, 0xf8, 0x1f, 0xfe, 0x07,
+ 0xf8, 0x03, 0xe0, 0x3f, 0xe0, 0x7f, 0xf8, 0x1f, 0xfe, 0x07, 0xfc, 0x03,
+ 0xe0, 0x3f, 0xe0, 0xff, 0xf8, 0x1f, 0xfe, 0x07, 0xfe, 0x03, 0xc0, 0x7f,
+ 0xe0, 0xff, 0xfc, 0x3f, 0xff, 0x07, 0xfe, 0x03, 0xc0, 0xff, 0xe0, 0xff,
+ 0xfd, 0x3f, 0xff, 0x07, 0xff, 0x03, 0xc0, 0xff, 0xe1, 0xff, 0xfd, 0xff,
+ 0xff, 0x87, 0xff, 0x03, 0xc0, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0x87,
+ 0xff, 0x01, 0xc0, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0x01,
+ 0xc0, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0x01, 0x80, 0xff,
+ 0xef, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x01, 0x80, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xe7, 0xff, 0x01, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xf7, 0xff, 0x01, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00,
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xfe,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x7f, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+ 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xf8,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xf0, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x07, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x07, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00,
+ 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xc0,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xc0, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x07, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00,
+ 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xf0,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xf0, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/queen_outline.bitmap b/gnu/games/chess/Xchess/queen_outline.bitmap
new file mode 100644
index 000000000000..2527216b3966
--- /dev/null
+++ b/gnu/games/chess/Xchess/queen_outline.bitmap
@@ -0,0 +1,71 @@
+
+#define queen_outline_width 80
+#define queen_outline_height 80
+static char queen_outline_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x80, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x01, 0x80, 0x01, 0x00, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x80, 0x01, 0x80, 0x0d, 0x00, 0x00,
+ 0x00, 0x00, 0xb0, 0x01, 0xc0, 0x03, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0x00, 0x40, 0x02, 0x80, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0x40, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x40, 0x02,
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x40, 0x02, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x40, 0x02, 0x00, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0x01, 0x40, 0x02, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x01, 0x40, 0x02, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01,
+ 0x60, 0x06, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x03, 0x20, 0x04,
+ 0xc0, 0x02, 0x00, 0x00, 0x1c, 0x00, 0x40, 0x02, 0x20, 0x04, 0x40, 0x02,
+ 0x00, 0x00, 0x36, 0x00, 0x40, 0x02, 0x20, 0x04, 0x40, 0x02, 0x00, 0x0e,
+ 0x22, 0x00, 0x40, 0x06, 0x20, 0x04, 0x60, 0x02, 0x00, 0x1b, 0x36, 0x00,
+ 0x40, 0x04, 0x20, 0x04, 0x20, 0x02, 0x00, 0x11, 0x3c, 0x00, 0x40, 0x04,
+ 0x20, 0x04, 0x20, 0x02, 0x00, 0x1b, 0x70, 0x00, 0x40, 0x0c, 0x20, 0x04,
+ 0x30, 0x02, 0x00, 0x0e, 0x60, 0x00, 0x40, 0x08, 0x20, 0x04, 0x10, 0x02,
+ 0x00, 0x03, 0xe0, 0x00, 0x40, 0x08, 0x30, 0x0c, 0x10, 0x02, 0x80, 0x03,
+ 0xc0, 0x01, 0x40, 0x18, 0x10, 0x08, 0x18, 0x02, 0x80, 0x01, 0x40, 0x01,
+ 0x40, 0x10, 0x10, 0x08, 0x08, 0x02, 0xc0, 0x01, 0x40, 0x03, 0x40, 0x10,
+ 0x10, 0x08, 0x08, 0x02, 0x60, 0x01, 0x40, 0x06, 0x40, 0x10, 0x10, 0x08,
+ 0x08, 0x02, 0x20, 0x01, 0x40, 0x04, 0x40, 0x30, 0x10, 0x08, 0x0c, 0x02,
+ 0x30, 0x01, 0xc0, 0x0c, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x18, 0x01,
+ 0x80, 0x18, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x08, 0x01, 0x80, 0x10,
+ 0x40, 0x60, 0x10, 0x08, 0x06, 0x02, 0x8c, 0x01, 0x80, 0x30, 0x40, 0x40,
+ 0x18, 0x18, 0x02, 0x02, 0x84, 0x00, 0x80, 0x20, 0x40, 0x40, 0x08, 0x10,
+ 0x02, 0x02, 0x86, 0x00, 0x80, 0x60, 0x40, 0xc0, 0x08, 0x10, 0x03, 0x02,
+ 0x83, 0x00, 0x80, 0xc1, 0x40, 0x80, 0x08, 0x10, 0x01, 0x02, 0x81, 0x00,
+ 0x00, 0x81, 0x40, 0x80, 0x08, 0x10, 0x01, 0x82, 0x81, 0x00, 0x00, 0x81,
+ 0x41, 0x80, 0x09, 0x90, 0x01, 0x82, 0x80, 0x00, 0x00, 0x01, 0x43, 0x00,
+ 0x09, 0x90, 0x00, 0xc2, 0xc0, 0x00, 0x00, 0x01, 0x42, 0x00, 0x09, 0x90,
+ 0x00, 0x62, 0x40, 0x00, 0x00, 0x01, 0x46, 0x00, 0x0f, 0xf0, 0x00, 0x22,
+ 0x40, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x32, 0x40, 0x00,
+ 0x00, 0x02, 0x48, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x40, 0x00, 0x00, 0x02,
+ 0x58, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x40, 0x00, 0x00, 0x02, 0x70, 0x00,
+ 0x00, 0x00, 0x00, 0x0e, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xfe, 0x7f,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, 0xfc, 0x03, 0xc0, 0x3f, 0x00,
+ 0x10, 0x00, 0x00, 0x10, 0xfe, 0x07, 0x80, 0x01, 0xe0, 0x7f, 0x18, 0x00,
+ 0x00, 0x30, 0x03, 0x00, 0xe0, 0x07, 0x00, 0xc0, 0x0c, 0x00, 0x00, 0x60,
+ 0x18, 0x00, 0xf8, 0x1f, 0x00, 0x18, 0x06, 0x00, 0x00, 0x40, 0x7e, 0x00,
+ 0xe0, 0x07, 0x00, 0x7e, 0x02, 0x00, 0x00, 0x40, 0xff, 0x01, 0x80, 0x01,
+ 0x80, 0xff, 0x02, 0x00, 0x00, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x7e,
+ 0x02, 0x00, 0x00, 0xc0, 0x18, 0x00, 0xfe, 0x7f, 0x00, 0x18, 0x03, 0x00,
+ 0x00, 0x80, 0x00, 0xfc, 0x03, 0xc0, 0x3f, 0x00, 0x01, 0x00, 0x00, 0x80,
+ 0xfe, 0x07, 0x00, 0x00, 0xe0, 0x7f, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x60,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0xe0, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/queen_small.bitmap b/gnu/games/chess/Xchess/queen_small.bitmap
new file mode 100644
index 000000000000..d7ee50e9b820
--- /dev/null
+++ b/gnu/games/chess/Xchess/queen_small.bitmap
@@ -0,0 +1,15 @@
+
+#define queen_small_width 32
+#define queen_small_height 32
+static char queen_small_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00,
+ 0x80, 0x81, 0xc0, 0x00, 0x80, 0x81, 0xc0, 0x00, 0x00, 0xc1, 0x41, 0x00,
+ 0x00, 0xc1, 0x41, 0x00, 0x02, 0xc3, 0x61, 0x20, 0x06, 0xc3, 0x61, 0x30,
+ 0x04, 0xc3, 0x61, 0x10, 0x0c, 0xc3, 0x61, 0x18, 0x08, 0xc7, 0x71, 0x08,
+ 0x18, 0xc6, 0x31, 0x0c, 0x38, 0xc6, 0x31, 0x0e, 0x30, 0xce, 0x39, 0x06,
+ 0x70, 0xce, 0x39, 0x07, 0x60, 0xee, 0x3b, 0x03, 0xe0, 0xee, 0xbb, 0x03,
+ 0xe0, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x01, 0xc0, 0xff, 0xff, 0x01,
+ 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00, 0xff, 0x7f, 0x00,
+ 0x80, 0xff, 0xff, 0x00, 0xf0, 0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/queen_small_outline.bitmap b/gnu/games/chess/Xchess/queen_small_outline.bitmap
new file mode 100644
index 000000000000..0b624b9587bc
--- /dev/null
+++ b/gnu/games/chess/Xchess/queen_small_outline.bitmap
@@ -0,0 +1,15 @@
+
+#define queen_small_outline_width 32
+#define queen_small_outline_height 32
+static char queen_small_outline_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00,
+ 0x80, 0x81, 0xc0, 0x00, 0x80, 0x81, 0xc0, 0x00, 0x00, 0xc1, 0x41, 0x00,
+ 0x00, 0x41, 0x41, 0x00, 0x02, 0x43, 0x61, 0x20, 0x06, 0x43, 0x61, 0x30,
+ 0x04, 0x43, 0x61, 0x10, 0x0c, 0x43, 0x61, 0x18, 0x08, 0x47, 0x71, 0x08,
+ 0x18, 0x46, 0x31, 0x0c, 0x38, 0x46, 0x31, 0x0e, 0x30, 0x4e, 0x39, 0x06,
+ 0x70, 0x4e, 0x29, 0x07, 0x60, 0x6a, 0x2b, 0x03, 0xe0, 0x2a, 0xab, 0x03,
+ 0xe0, 0x3b, 0xee, 0x03, 0x40, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x80, 0x01,
+ 0x80, 0xfc, 0x9f, 0x00, 0x80, 0x01, 0xc0, 0x00, 0x00, 0x01, 0x40, 0x00,
+ 0x80, 0xfd, 0xdf, 0x00, 0xf0, 0x00, 0x80, 0x07, 0xf0, 0xff, 0xff, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/record.c b/gnu/games/chess/Xchess/record.c
new file mode 100644
index 000000000000..d9459b3a64f0
--- /dev/null
+++ b/gnu/games/chess/Xchess/record.c
@@ -0,0 +1,315 @@
+
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/23 17:18:20 $
+ * $Source: /users/faustus/xchess/RCS/record.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ *
+ * Deal with recording moves.
+ */
+
+#include "xchess.h"
+
+#undef smartass
+
+bool record_english = true;
+char *record_file = DEF_RECORD_FILE;
+int movenum = 0;
+bool saveflag = false;
+
+static char *colnames[] = { "qr", "qn", "qb", "q", "k", "kb", "kn", "kr" } ;
+static char *pcnames[] = { "P", "R", "N", "B", "Q", "K" } ;
+
+static char *movestring();
+static char *tstring();
+static FILE *backup;
+
+#define RECORD_HEADER "\n1 XChess Game Record0\n"
+
+void
+record_init(win)
+ windata *win;
+{
+ int i;
+
+ i = XTextWidth(win->medium, RECORD_HEADER,
+ sizeof(RECORD_HEADER) - 1);
+ i = (40 * win->small->max_bounds.width - i *
+ win->medium->max_bounds.width) /
+ win->medium->max_bounds.width / 2;
+ TxtGrab(win->display, win->recwin, "xchess", win->small, win->textback.pixel,
+ win->textcolor.pixel, win->cursorcolor.pixel);
+ TxtAddFont(win->display, win->recwin, 1, win->medium, win->textcolor.pixel);
+ for (; i > 0; i++)
+ TxtWriteStr(win->display, win->recwin, " ");
+ TxtWriteStr(win->display, win->recwin, RECORD_HEADER);
+
+ if (saveflag) {
+ if (!(backup = fopen(record_file, "w"))) {
+ perror(record_file);
+ saveflag = false;
+ } else {
+ fprintf(backup, "X Chess -- %s\n", datestring());
+ if (dispname2)
+ fprintf(backup, "\tWhite on %s, black on %s\n",
+ dispname1, dispname2);
+ else
+ fprintf(backup, "\tGame played on %s\n",
+ dispname1);
+ fprintf(backup, "\t%s\n", record_english ? "english" :
+ "algebraic");
+ fflush(backup);
+ }
+ }
+
+ movenum = 0;
+ return;
+}
+
+void
+record_reset()
+{
+ TxtWriteStr(win1->display, win1->recwin, "\n\n1 New Game0\n\n");
+ if (!oneboard) {
+ TxtWriteStr(win2->display, win2->recwin, "\n\n1 New Game0\n\n");
+ }
+ movenum = 0;
+ if (saveflag) {
+ fprintf(backup, "\n\nNew Game\n\n");
+ fflush(backup);
+ }
+ return;
+}
+
+void
+record_end(s)
+ char *s;
+{
+ char buf[BSIZE];
+
+ sprintf(buf, "\n%s\n", s);
+ TxtWriteStr(win1->display, win1->recwin, s);
+ if (!oneboard) {
+ TxtWriteStr(win2->display, win2->recwin, s);
+ }
+ if (saveflag) {
+ fprintf(backup, "\n%s\n", s);
+ fprintf(backup, "Time: white: %s, ", tstring(whiteseconds));
+ fprintf(backup, "black: %s\n", tstring(blackseconds));
+ fclose(backup);
+ }
+ return;
+}
+
+void
+record_save()
+{
+ move *m;
+ FILE *fp;
+ int i;
+ char *s;
+
+ if (!(fp = fopen(record_file, "w"))) {
+ perror(record_file);
+ return;
+ }
+ fprintf(fp, "X Chess -- %s\n", datestring());
+ if (dispname2)
+ fprintf(fp, "\tWhite on %s, black on %s\n",
+ dispname1, dispname2);
+ else
+ fprintf(fp, "\tGame played on %s\n", dispname1);
+ fprintf(fp, "\t%s\n", record_english ? "english" : "algebraic");
+
+ for (m = moves, i = 1; m; i++) {
+ s = movestring(m);
+ fprintf(fp, "%2d. %-16s ", i, s);
+ m = m->next;
+ if (m)
+ s = movestring(m);
+ else
+ s = "";
+ fprintf(fp, "%s\n", s);
+ if (m)
+ m = m->next;
+ }
+ fclose(fp);
+ return;
+}
+
+void
+record_move(m)
+ move *m;
+{
+ char *s, buf[BSIZE];
+
+ s = movestring(m);
+
+ if (m->piece.color == WHITE) {
+ movenum++;
+ sprintf(buf, "%2d. %-16s ", movenum, s);
+ } else {
+ sprintf(buf, "%s\n", s);
+ }
+ TxtWriteStr(win1->display, win1->recwin, buf);
+ if (!oneboard) {
+ TxtWriteStr(win2->display, win2->recwin, buf);
+ }
+ if (saveflag) {
+ fprintf(backup, "%s", buf);
+ fflush(backup);
+ }
+
+ return;
+}
+
+void
+record_back()
+{
+ extern move *lastmove;
+ move *m = lastmove;
+ char *s = movestring(m);
+ char buf[BSIZE];
+ long i;
+
+ if (m->piece.color == WHITE) {
+ sprintf(buf, "%2d. %-16s ", movenum, s);
+ } else {
+ sprintf(buf, "%s\n", s);
+ }
+ s = buf;
+ for (i = 0; *s != '\0'; i++)
+ *s++ = ''; /* control H, backspace */
+
+ TxtWriteStr(win1->display, win1->recwin, buf);
+ if (!oneboard) {
+ TxtWriteStr(win2->display, win2->recwin, buf);
+ }
+
+ if (nexttomove == BLACK)
+ movenum--;
+ if (saveflag) {
+ fseek(backup, -i, 1);
+ fflush(backup);
+ }
+
+ return;
+}
+
+static char *
+movestring(m)
+ move *m;
+{
+ int fy, ty;
+ static char buf[BSIZE];
+
+ if (!record_english || (m->piece.color == WHITE)) {
+ fy = SIZE - m->fromy;
+ ty = SIZE - m->toy;
+ } else {
+ fy = m->fromy + 1;
+ ty = m->toy + 1;
+ }
+
+ switch (m->type) {
+ case MOVE:
+ if (record_english)
+ sprintf(buf, "%s/%s%d-%s%d%s", pcnames[(int) m->piece.
+ type], colnames[m->fromx], fy,
+ colnames[m->tox], ty, m->check ? "+" :
+ "");
+ else
+ sprintf(buf, "%c%d%c%d", 'a' + m->fromx, fy, 'a' +
+ m->tox, ty);
+ break;
+ case CAPTURE:
+ if (record_english)
+ sprintf(buf, "%s/%s%dx%s/%s%d%s%s",
+ pcnames[(int) m->piece.type],
+ colnames[m->fromx], fy,
+ pcnames[(int) m->taken.type],
+ colnames[m->tox], ty,
+ m->enpassant ? "e.p." : "",
+ m->check ? "+" : "");
+ else
+ sprintf(buf, "%c%d%c%d", 'a' + m->fromx, fy, 'a' +
+ m->tox, ty);
+ break;
+
+ case KCASTLE:
+ if (record_english)
+ sprintf(buf, "O-O%s", m->check ? "ch" : "");
+ else if (m->piece.color == WHITE)
+ strcpy(buf, "e1g1");
+ else
+ strcpy(buf, "e8g8");
+ break;
+
+ case QCASTLE:
+ if (record_english)
+ sprintf(buf, "O-O-O%s", m->check ? "ch" : "");
+ else if (m->piece.color == WHITE)
+ strcpy(buf, "e1c1");
+ else
+ strcpy(buf, "e8c8");
+ break;
+
+ default:
+ sprintf(buf, "something strange");
+ break;
+ }
+ if ((m->piece.type == PAWN) && (((m->piece.color == BLACK) &&
+ (m->toy == 7)) || ((m->piece.color == WHITE) &&
+ (m->toy == 0))))
+ strcat(buf, "(Q)");
+
+#ifdef smartass
+ if (!(random() % 50))
+ strcat(buf, "?");
+ else if (!(random() % 50))
+ strcat(buf, "!");
+ else if (!(random() % 500))
+ strcat(buf, "???");
+ else if (!(random() % 500))
+ strcat(buf, "!!!");
+#endif smartass
+
+ return (buf);
+}
+
+static char *
+tstring(s)
+ int s;
+{
+ static char buf[64];
+
+ if (s > 3600)
+ sprintf(buf, "%dh %dm %ds", s / 3600, (s % 3600) / 60, s % 60);
+ else if (s > 60)
+ sprintf(buf, "%dm %ds", (s % 3600) / 60, s % 60);
+ else
+ sprintf(buf, "%ds", s);
+ return (buf);
+}
+
diff --git a/gnu/games/chess/Xchess/rook.bitmap b/gnu/games/chess/Xchess/rook.bitmap
new file mode 100644
index 000000000000..f274614eb9cb
--- /dev/null
+++ b/gnu/games/chess/Xchess/rook.bitmap
@@ -0,0 +1,71 @@
+
+#define rook_width 80
+#define rook_height 80
+static char rook_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xf8, 0xff, 0x00, 0x3c,
+ 0x00, 0x00, 0x00, 0x80, 0xff, 0x01, 0xf8, 0xff, 0x00, 0xfc, 0x0f, 0x00,
+ 0x00, 0xc0, 0xff, 0x01, 0xf8, 0xff, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xc0,
+ 0xff, 0x01, 0xf8, 0xff, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xc0, 0xff, 0x01,
+ 0xf8, 0xff, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xc0, 0xff, 0x01, 0xff, 0xff,
+ 0x07, 0xfc, 0x1f, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0x01, 0x00, 0xfc, 0xfd,
+ 0x1f, 0x00, 0x00, 0xc0, 0xff, 0x07, 0xfc, 0xff, 0x01, 0xff, 0x1f, 0x00,
+ 0x00, 0xc0, 0x1f, 0xf0, 0xff, 0xff, 0x7f, 0xc0, 0x1f, 0x00, 0x00, 0x40,
+ 0xc0, 0xff, 0x07, 0x00, 0xff, 0x1f, 0x10, 0x00, 0x00, 0xc0, 0xff, 0x1f,
+ 0xf0, 0x7f, 0xc0, 0xff, 0x1f, 0x00, 0x00, 0xc0, 0x7f, 0xc0, 0xfd, 0xff,
+ 0x1d, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff,
+ 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff,
+ 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0x7f, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0xff, 0xfe, 0x07, 0x10, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfe,
+ 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfe, 0xff, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfe, 0xff, 0x1f, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0xff, 0xff, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff,
+ 0xff, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfe,
+ 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfe, 0xff, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfe, 0xff, 0x1f, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0xff, 0xff, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff,
+ 0x0f, 0x80, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0xe0, 0x3f,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff,
+ 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff,
+ 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff,
+ 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfd, 0xff, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfd, 0xff, 0x1f, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfd, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0xff, 0xff, 0xfd, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff,
+ 0xff, 0xfd, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfd,
+ 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfd, 0xff, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfd, 0xff, 0x1f, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfd, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0xff, 0xff, 0xfd, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff,
+ 0xff, 0xfd, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfd,
+ 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x07, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
+ 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x60,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x3f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/rook_mask.bitmap b/gnu/games/chess/Xchess/rook_mask.bitmap
new file mode 100644
index 000000000000..c04441655879
--- /dev/null
+++ b/gnu/games/chess/Xchess/rook_mask.bitmap
@@ -0,0 +1,71 @@
+
+#define rook_mask_width 80
+#define rook_mask_height 80
+static char rook_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0xfc, 0xff,
+ 0x01, 0x7e, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x03, 0xfc, 0xff, 0x01, 0xfe,
+ 0x1f, 0x00, 0x00, 0xe0, 0xff, 0x03, 0xfc, 0xff, 0x01, 0xfe, 0x3f, 0x00,
+ 0x00, 0xe0, 0xff, 0x03, 0xfc, 0xff, 0x01, 0xfe, 0x3f, 0x00, 0x00, 0xe0,
+ 0xff, 0x03, 0xfc, 0xff, 0x1f, 0xfe, 0x3f, 0x00, 0x00, 0xe0, 0xff, 0x83,
+ 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x3f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x3f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+ 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xe0,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xe0, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x3f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x3f, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00,
+ 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
+ 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff,
+ 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00,
+ 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
+ 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff,
+ 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00,
+ 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
+ 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff,
+ 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00,
+ 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
+ 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff,
+ 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00,
+ 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
+ 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff,
+ 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00,
+ 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
+ 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff,
+ 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00,
+ 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
+ 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff,
+ 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00,
+ 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
+ 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff,
+ 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00,
+ 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x0f, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x1f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+ 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf0,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf0, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x7f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00,
+ 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/rook_outline.bitmap b/gnu/games/chess/Xchess/rook_outline.bitmap
new file mode 100644
index 000000000000..f30107a3f277
--- /dev/null
+++ b/gnu/games/chess/Xchess/rook_outline.bitmap
@@ -0,0 +1,71 @@
+
+#define rook_outline_width 80
+#define rook_outline_height 80
+static char rook_outline_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x08, 0x80, 0x00, 0x3c,
+ 0x00, 0x00, 0x00, 0x80, 0x3f, 0x01, 0x08, 0x80, 0x00, 0xe4, 0x0f, 0x00,
+ 0x00, 0xc0, 0x00, 0x01, 0x08, 0x80, 0x00, 0x04, 0x18, 0x00, 0x00, 0x40,
+ 0x00, 0x01, 0x08, 0x80, 0x00, 0x04, 0x10, 0x00, 0x00, 0x40, 0x00, 0x01,
+ 0x08, 0x80, 0x00, 0x04, 0x10, 0x00, 0x00, 0x40, 0x00, 0x01, 0x0f, 0x80,
+ 0x07, 0x04, 0x10, 0x00, 0x00, 0x40, 0x00, 0xfd, 0x01, 0x00, 0xfc, 0x05,
+ 0x10, 0x00, 0x00, 0x40, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40,
+ 0x00, 0xf0, 0x07, 0x00, 0x7f, 0x00, 0x10, 0x00, 0x00, 0x40, 0xc0, 0x1f,
+ 0x00, 0x00, 0xc0, 0x1f, 0x10, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x02, 0x00,
+ 0x02, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00,
+ 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x80, 0xff, 0xff, 0x0f, 0x10, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff,
+ 0x00, 0x01, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0xf0, 0x7f, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x1f, 0xc0,
+ 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00,
+ 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
+ 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x07, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
+ 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x60,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x3f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/rook_small.bitmap b/gnu/games/chess/Xchess/rook_small.bitmap
new file mode 100644
index 000000000000..ddee75660d4b
--- /dev/null
+++ b/gnu/games/chess/Xchess/rook_small.bitmap
@@ -0,0 +1,15 @@
+
+#define rook_small_width 32
+#define rook_small_height 32
+static char rook_small_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0x73, 0xce, 0x03, 0xc0, 0x73, 0xce, 0x03, 0xc0, 0x73, 0xce, 0x03,
+ 0xc0, 0x73, 0xce, 0x03, 0xc0, 0xff, 0xff, 0x03, 0x00, 0xff, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
+ 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/rook_small_outline.bitmap b/gnu/games/chess/Xchess/rook_small_outline.bitmap
new file mode 100644
index 000000000000..523521b963b7
--- /dev/null
+++ b/gnu/games/chess/Xchess/rook_small_outline.bitmap
@@ -0,0 +1,15 @@
+
+#define rook_small_outline_width 32
+#define rook_small_outline_height 32
+static char rook_small_outline_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0x73, 0xce, 0x03, 0x40, 0x52, 0x4a, 0x02, 0x40, 0x52, 0x4a, 0x02,
+ 0x40, 0x52, 0x4a, 0x02, 0xc0, 0xff, 0xff, 0x03, 0x00, 0x01, 0x80, 0x00,
+ 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00,
+ 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00,
+ 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00,
+ 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00,
+ 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00,
+ 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00,
+ 0xe0, 0xff, 0xff, 0x07, 0x20, 0x00, 0x00, 0x04, 0xe0, 0xff, 0xff, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/scrollText.c b/gnu/games/chess/Xchess/scrollText.c
new file mode 100644
index 000000000000..432071086d15
--- /dev/null
+++ b/gnu/games/chess/Xchess/scrollText.c
@@ -0,0 +1,1858 @@
+/*
+ * A Scrollable Text Output Window
+ *
+ * David Harrison
+ * University of California, Berkeley
+ * 1986
+ *
+ * The following is an implementation for a scrollable text output
+ * system. It handles exposure events only (other interactions are
+ * under user control). For scrolling, a always present scroll bar
+ * is implemented. It detects size changes and compensates accordingly.
+ */
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/X10.h>
+#include <sys/types.h>
+#include "scrollText.h"
+
+extern char *malloc();
+extern char *realloc();
+#define alloc(type) (type *) malloc(sizeof(type))
+#define numalloc(type, num) (type *) malloc((unsigned) (num * sizeof(type)))
+#define MAXINT 2147483647
+
+extern XAssocTable *XCreateAssocTable();
+extern caddr_t XLookUpAssoc();
+
+static XAssocTable *textWindows = (XAssocTable *) 0;
+
+#define NOOPTION -1 /* Option hasn't been set yet */
+#define NORMSCROLL 0 /* Smooth scroll on LineToTop and TopToHere */
+#define JUMPSCROLL 1 /* Jump scrolling on LineToTop and TopToHere */
+
+static int ScrollOption = NOOPTION;
+
+typedef char *Generic;
+
+#define DEFAULT_GC textInfo->fontGC[textInfo->curFont]
+
+#define BARSIZE 15
+#define BARBORDER 1
+#define MAXFONTS 8
+#define INITBUFSIZE 1024
+#define INITLINES 50
+#define INITEXPARY 50
+#define XPADDING 2
+#define YPADDING 2
+#define INTERLINE 5
+#define INTERSPACE 1
+#define CURSORWIDTH 2
+#define EXPANDPERCENT 40
+#define BUFSIZE 1024
+#define CUROFFSET 1
+#define MAXFOREIGN 250
+#define NOINDEX -1
+
+/* The wrap line indicator */
+#define WRAPINDSIZE 7
+#define STEMOFFSET 5
+#define arrow_width 7
+#define arrow_height 5
+static char arrow_bits[] = {
+ 0x24, 0x26, 0x3f, 0x06, 0x04};
+
+#define NEWLINE '\n'
+#define BACKSPACE '\010'
+#define NEWFONT '\006'
+#define LOWCHAR '\040'
+#define HIGHCHAR '\176'
+
+#define CHARMASK 0x00ff /* Character mask */
+#define FONTMASK 0x0700 /* Character font */
+#define FONTSHIFT 8 /* Shift amount */
+
+#define WRAPFLAG 0x01 /* Line wrap flag */
+
+/*
+ * Lines are represented by a pointer into the overall array of
+ * 16-bit characters. The lower eight bits is used to indicate the character
+ * (in ASCII), and the next two bits are used to indicate the font
+ * the character should be drawn in.
+ */
+
+typedef struct txtLine {
+ int lineLength; /* Current line length */
+ int lineHeight; /* Full height of line in pixels */
+ int lineBaseLine; /* Current baseline of the line */
+ int lineWidth; /* Drawing position at end of line */
+ int lineText; /* Offset into master buffer */
+ int lineFlags; /* Line wrap flag is here */
+};
+
+
+/*
+ * For ExposeCopy events, we queue up the redraw requests collapsing
+ * them into line redraw requests until the CopyExpose event arrives.
+ * The queue is represented as a dynamic array of the following
+ * structure:
+ */
+
+typedef struct expEvent {
+ int lineIndex; /* Index of line to redraw */
+ int ypos; /* Drawing position of line */
+};
+
+
+/*
+ * The text buffer is represented using a dynamic counted array
+ * of 16-bit quantities. This array expands as needed.
+ * For the screen representation, a dynamic counted array
+ * of line structures is used. This array points into the
+ * text buffer to denote the start of each line and its parameters.
+ * The windows are configured as one overall window which contains
+ * the scroll bar as a sub-window along its right edge. Thus,
+ * the text drawing space is actually w-BARSIZE.
+ */
+
+#define NOTATBOTTOM 0x01 /* Need to scroll to bottom before appending */
+#define FONTNUMWAIT 0x02 /* Waiting for font number */
+#define COPYEXPOSE 0x04 /* Need to process a copy expose event */
+#define SCREENWRONG 0x08 /* TxtJamStr has invalidated screen contents */
+
+typedef struct txtWin {
+ /* Basic text buffer */
+ int bufAlloc; /* Allocated size of buffer */
+ int bufSpot; /* Current writing position in buffer */
+ short *mainBuffer; /* Main buffer of text */
+
+ /* Line information */
+ int numLines; /* Number of display lines in buffer */
+ int allocLines; /* Number of lines allocated */
+ struct txtLine **txtBuffer; /* Dynamic array of lines */
+
+ /* Current Window display information */
+ Window mainWindow; /* Text display window */
+ Window scrollBar; /* Subwindow for scroll bar */
+ Pixmap arrowMap; /* line wrap indicator */
+ int bgPix, fgPix; /* Background and cursor */
+ GC CursorGC; /* gc for the cursor */
+ GC bgGC; /* gc for erasing things */
+ GC fontGC[MAXFONTS]; /* gc for doing fonts */
+ XFontStruct theFonts[MAXFONTS];/* Display fonts */
+ int theColors[MAXFONTS]; /* foregrounds of the fonts */
+ int curFont; /* current font for tracking */
+ int w, h; /* Current size */
+ int startLine; /* Top line in display */
+ int endLine; /* Bottom line in display */
+ int bottomSpace; /* Space at bottom of screen */
+ int flagWord; /* If non-zero, not at end */
+
+ /* For handling ExposeCopy events */
+ int exposeSize; /* Current size of array */
+ int exposeAlloc; /* Allocated size */
+ struct expEvent **exposeAry;/* Array of line indices */
+
+ /* Drawing position information */
+ int curLine; /* Current line in buffer */
+ int curX; /* Current horizontal positi */
+ int curY; /* Current vertical drawing */
+};
+
+/* Flags for the various basic character handling functions */
+
+#define DODISP 0x01 /* Update the display */
+#define NONEWLINE 0x02 /* Dont append newline */
+
+
+
+static int InitLine(newLine)
+struct txtLine *newLine; /* Newly created line structure */
+/*
+ * This routine initializes a newly created line structure.
+ */
+{
+ newLine->lineLength = 0;
+ newLine->lineHeight = 0;
+ newLine->lineBaseLine = 0;
+ newLine->lineWidth = XPADDING;
+ newLine->lineText = NOINDEX;
+ newLine->lineFlags = 0;
+ return 1;
+}
+
+
+
+
+int TxtGrab(display, txtWin, program, mainFont, bg, fg, cur)
+Display *display; /* display window is on */
+Window txtWin; /* Window to take over as scrollable text */
+char *program; /* Program name for Xdefaults */
+XFontStruct *mainFont; /* Primary text font */
+int bg, fg, cur; /* Background, foreground, and cursor colors */
+/*
+ * This routine takes control of 'txtWin' and makes it into a scrollable
+ * text output window. It will create a sub-window for the scroll bar
+ * with a background of 'bg' and an bar with color 'fg'. Both fixed width
+ * and variable width fonts are supported. Additional fonts can be loaded
+ * using 'TxtAddFont'. Returns 0 if there were problems, non-zero if
+ * everything went ok.
+ */
+{
+ struct txtWin *newWin; /* Text package specific information */
+ XWindowAttributes winInfo; /* Window information */
+ int index;
+ XGCValues gc_val;
+
+ if (textWindows == (XAssocTable *) 0) {
+ textWindows = XCreateAssocTable(32);
+ if (textWindows == (XAssocTable *) 0) return(0);
+ }
+ if (XGetWindowAttributes(display, txtWin, &winInfo) == 0) return 0;
+
+ if (ScrollOption == NOOPTION) {
+ /* Read to see if the user wants jump scrolling or not */
+ if (XGetDefault(display, program, "JumpScroll")) {
+ ScrollOption = JUMPSCROLL;
+ } else {
+ ScrollOption = NORMSCROLL;
+ }
+ }
+
+ /* Initialize local structure */
+ newWin = alloc(struct txtWin);
+
+ /* Initialize arrow pixmap */
+ newWin->arrowMap = XCreatePixmapFromBitmapData(display, txtWin,
+ arrow_bits,
+ arrow_width, arrow_height,
+ cur, bg,
+ DisplayPlanes(display, 0));
+
+ newWin->bufAlloc = INITBUFSIZE;
+ newWin->bufSpot = 0;
+ newWin->mainBuffer = numalloc(short, INITBUFSIZE);
+
+ newWin->numLines = 1;
+ newWin->allocLines = INITLINES;
+ newWin->txtBuffer = numalloc(struct txtLine *, INITLINES);
+ for (index = 0; index < INITLINES; index++) {
+ newWin->txtBuffer[index] = alloc(struct txtLine);
+ InitLine(newWin->txtBuffer[index]);
+ }
+
+ /* Window display information */
+ newWin->mainWindow = txtWin;
+ newWin->w = winInfo.width;
+ newWin->h = winInfo.height;
+ newWin->startLine = 0;
+ newWin->endLine = 0;
+ newWin->bottomSpace = winInfo.height
+ - YPADDING - mainFont->ascent - mainFont->descent - INTERLINE;
+ newWin->flagWord = 0;
+ newWin->bgPix = bg;
+ newWin->fgPix = fg;
+
+ /* Scroll Bar Creation */
+ newWin->scrollBar = XCreateSimpleWindow(display, txtWin,
+ winInfo.width - BARSIZE,
+ 0, BARSIZE - (2*BARBORDER),
+ winInfo.height - (2*BARBORDER),
+ BARBORDER,
+ fg, bg);
+ XSelectInput(display, newWin->scrollBar, ExposureMask|ButtonReleaseMask);
+ XMapRaised(display, newWin->scrollBar);
+
+ /* Font and Color Initialization */
+ newWin->theFonts[0] = *mainFont;
+ newWin->theColors[0] = fg;
+ gc_val.function = GXcopy;
+ gc_val.plane_mask = AllPlanes;
+ gc_val.foreground = fg;
+ gc_val.background = bg;
+ gc_val.graphics_exposures = 1;
+ gc_val.font = mainFont->fid;
+ gc_val.line_width = 1;
+ gc_val.line_style = LineSolid;
+
+ newWin->fontGC[0] = XCreateGC(display, txtWin,
+ GCFunction | GCPlaneMask |
+ GCForeground | GCBackground |
+ GCGraphicsExposures | GCFont,
+ &gc_val);
+
+ gc_val.foreground = cur;
+ newWin->CursorGC = XCreateGC(display, txtWin,
+ GCFunction | GCPlaneMask |
+ GCForeground | GCBackground |
+ GCLineStyle | GCLineWidth,
+ &gc_val);
+
+ gc_val.foreground = bg;
+ newWin->bgGC = XCreateGC(display, txtWin,
+ GCFunction | GCPlaneMask |
+ GCForeground | GCBackground |
+ GCGraphicsExposures | GCFont,
+ &gc_val);
+
+
+ for (index = 1; index < MAXFONTS; index++) {
+ newWin->theFonts[index].fid = 0;
+ newWin->fontGC[index] = 0;
+ }
+
+
+ /* Initialize size of first line */
+ newWin->txtBuffer[0]->lineHeight = newWin->theFonts[0].ascent +
+ newWin->theFonts[0].descent;
+ newWin->txtBuffer[0]->lineText = 0;
+
+ /* ExposeCopy array initialization */
+ newWin->exposeSize = 0;
+ newWin->exposeAlloc = INITEXPARY;
+ newWin->exposeAry = numalloc(struct expEvent *, INITEXPARY);
+ for (index = 0; index < newWin->exposeAlloc; index++)
+ newWin->exposeAry[index] = alloc(struct expEvent);
+ /* Put plus infinity in last slot for sorting purposes */
+ newWin->exposeAry[0]->lineIndex = MAXINT;
+
+ /* Drawing Position Information */
+ newWin->curLine = 0;
+ newWin->curX = 0;
+ newWin->curY = YPADDING + mainFont->ascent + mainFont->descent;
+
+ /* Attach it to both windows */
+ XMakeAssoc(display, textWindows, (XID) txtWin, (caddr_t) newWin);
+ XMakeAssoc(display, textWindows, (XID) newWin->scrollBar, (caddr_t) newWin);
+ return 1;
+}
+
+
+int TxtRelease(display, w)
+Display *display;
+Window w; /* Window to release */
+/*
+ * This routine releases all resources associated with the
+ * specified window which are consumed by the text
+ * window package. This includes the entire text buffer, line start
+ * array, and the scroll bar window. However, the window
+ * itself is NOT destroyed. The routine will return zero if
+ * the window is not owned by the text window package.
+ */
+{
+ struct txtWin *textInfo;
+ int index;
+
+ if ((textInfo = (struct txtWin *) XLookUpAssoc(display,
+ textWindows, (XID) w)) == 0)
+ return 0;
+
+ for (index = 0; index < MAXFONTS; index++)
+ if (textInfo->fontGC[index] != 0)
+ XFreeGC(display, textInfo->fontGC[index]);
+
+ free((Generic) textInfo->mainBuffer);
+ for (index = 0; index < textInfo->numLines; index++) {
+ free((Generic) textInfo->txtBuffer[index]);
+ }
+ free((Generic) textInfo->txtBuffer);
+ XDestroyWindow(display, textInfo->scrollBar);
+ for (index = 0; index < textInfo->exposeSize; index++) {
+ free((Generic) textInfo->exposeAry[index]);
+ }
+ free((Generic) textInfo->exposeAry);
+ XDeleteAssoc(display, textWindows, (XID) w);
+ free((Generic) textInfo);
+ return 1;
+}
+
+
+
+static int RecompBuffer(textInfo)
+struct txtWin *textInfo; /* Text window information */
+/*
+ * This routine recomputes all line breaks in a buffer after
+ * a change in window size or font. This is done by throwing
+ * away the old line start array and recomputing it. Although
+ * a lot of this work is also done elsewhere, it has been included
+ * inline here for efficiency.
+ */
+{
+ int startPos, endSize, linenum;
+ register int index, chsize, curfont;
+ register short *bufptr;
+ register XFontStruct *fontptr;
+ register struct txtLine *lineptr;
+ char theChar;
+
+ /* Record the old position so we can come back to it */
+ for (startPos = textInfo->txtBuffer[textInfo->startLine]->lineText;
+ (startPos > 0) && (textInfo->mainBuffer[startPos] != '\n');
+ startPos--)
+ /* null loop body */;
+
+ /* Clear out the old line start array */
+ for (index = 0; index < textInfo->numLines; index++) {
+ InitLine(textInfo->txtBuffer[index]);
+ }
+
+ /* Initialize first line */
+ textInfo->txtBuffer[0]->lineHeight =
+ textInfo->theFonts[0].ascent + textInfo->theFonts[0].descent;
+ textInfo->txtBuffer[0]->lineText = 0;
+
+ /* Process the text back into lines */
+ endSize = textInfo->w - BARSIZE - WRAPINDSIZE;
+ bufptr = textInfo->mainBuffer;
+ lineptr = textInfo->txtBuffer[0];
+ linenum = 0;
+ fontptr = &(textInfo->theFonts[0]);
+ curfont = 0;
+ for (index = 0; index < textInfo->bufSpot; index++) {
+ theChar = bufptr[index] & CHARMASK;
+
+ if ((bufptr[index] & FONTMASK) != curfont) {
+ int newFontNum, heightDiff;
+
+ /* Switch fonts */
+ newFontNum = (bufptr[index] & FONTMASK) >> FONTSHIFT;
+ if (textInfo->theFonts[newFontNum].fid != 0) {
+ /* Valid font */
+ curfont = bufptr[index] & FONTMASK;
+ fontptr = &(textInfo->theFonts[newFontNum]);
+ heightDiff = (fontptr->ascent + fontptr->descent) -
+ lineptr->lineHeight;
+ if (heightDiff < 0) heightDiff = 0;
+ lineptr->lineHeight += heightDiff;
+ }
+ }
+ if (theChar == '\n') {
+ /* Handle new line */
+ if (linenum >= textInfo->allocLines-1)
+ /* Expand number of lines */
+ ExpandLines(textInfo);
+ linenum++;
+ lineptr = textInfo->txtBuffer[linenum];
+ /* Initialize next line */
+ lineptr->lineHeight = fontptr->ascent + fontptr->descent;
+ lineptr->lineText = index+1;
+ /* Check to see if its the starting line */
+ if (index == startPos) textInfo->startLine = linenum;
+ } else {
+ /* Handle normal character */
+ chsize = CharSize(textInfo, linenum, index);
+ if (lineptr->lineWidth + chsize > endSize) {
+ /* Handle line wrap */
+ lineptr->lineFlags |= WRAPFLAG;
+ if (linenum >= textInfo->allocLines-1)
+ /* Expand number of lines */
+ ExpandLines(textInfo);
+ linenum++;
+ lineptr = textInfo->txtBuffer[linenum];
+ /* Initialize next line */
+ lineptr->lineHeight = fontptr->ascent + fontptr->descent;
+ lineptr->lineText = index;
+ lineptr->lineLength = 1;
+ lineptr->lineWidth += chsize;
+ } else {
+ /* Handle normal addition of character */
+ lineptr->lineLength += 1;
+ lineptr->lineWidth += chsize;
+ }
+ }
+ }
+ /* We now have a valid line array. Let's clean up some other fields. */
+ textInfo->numLines = linenum+1;
+ if (startPos == 0) {
+ textInfo->startLine = 0;
+ }
+ textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace));
+ textInfo->curLine = linenum;
+ /* Check to see if we are at the bottom */
+ if (textInfo->endLine >= textInfo->numLines-1) {
+ textInfo->curY = textInfo->h - textInfo->bottomSpace -
+ lineptr->lineHeight;
+ textInfo->flagWord &= (~NOTATBOTTOM);
+ } else {
+ textInfo->flagWord |= NOTATBOTTOM;
+ }
+ return 1;
+}
+
+
+
+
+int TxtAddFont(display, textWin, fontNumber, newFont, newColor)
+Display *display;
+Window textWin; /* Scrollable text window */
+int fontNumber; /* Place to add font (0-7) */
+XFontStruct *newFont; /* Font to add */
+int newColor; /* Color of font */
+/*
+ * This routine loads a new font so that it can be used in a previously
+ * created text window. There are eight font slots numbered 0 through 7.
+ * If there is already a font in the specified slot, it will be replaced
+ * and an automatic redraw of the window will take place. See TxtWriteStr
+ * for details on using alternate fonts. The color specifies the foreground
+ * color of the text. The default foreground color is used if this
+ * parameter is TXT_NO_COLOR. Returns a non-zero value if
+ * everything went well.
+ */
+{
+ struct txtWin *textInfo;
+ int redrawFlag;
+ XGCValues gc_val;
+
+ if ((fontNumber < 0) || (fontNumber >= MAXFONTS)) return 0;
+ if ((textInfo = (struct txtWin *)
+ XLookUpAssoc(display, textWindows, (XID) textWin)) == 0)
+ return 0;
+ if (newColor == TXT_NO_COLOR) {
+ newColor = textInfo->fgPix;
+ }
+
+ gc_val.font = newFont->fid;
+ gc_val.foreground = newColor;
+ gc_val.background = textInfo->bgPix;
+ gc_val.plane_mask = AllPlanes;
+ gc_val.graphics_exposures = 1;
+ gc_val.function = GXcopy;
+
+ if (textInfo->fontGC[fontNumber] != 0)
+ {
+ XChangeGC(display, textInfo->fontGC[fontNumber],
+ GCFont | GCForeground, &gc_val);
+ }
+ else
+ textInfo->fontGC[fontNumber] = XCreateGC(display, textWin,
+ GCFont |
+ GCForeground |
+ GCBackground |
+ GCFunction |
+ GCPlaneMask |
+ GCGraphicsExposures,
+ &gc_val);
+
+
+ redrawFlag = (textInfo->theFonts[fontNumber].fid != 0) &&
+ (((newFont) && (newFont->fid != textInfo->theFonts[fontNumber].fid)) ||
+ (newColor != textInfo->theColors[fontNumber]));
+ if (newFont) {
+ textInfo->theFonts[fontNumber] = *newFont;
+ }
+ textInfo->theColors[fontNumber] = newColor;
+
+ if (redrawFlag) {
+ RecompBuffer(textInfo);
+ XClearWindow(display, textWin);
+ TxtRepaint(display, textWin);
+ }
+ return 1;
+}
+
+
+
+int TxtWinP(display, w)
+Display *display;
+Window w;
+/*
+ * Returns a non-zero value if the window has been previously grabbed
+ * using TxtGrab and 0 if it has not.
+ */
+{
+ if (XLookUpAssoc(display, textWindows, (XID) w))
+ return(1);
+ else return(0);
+}
+
+
+
+static int FindEndLine(textInfo, botSpace)
+struct txtWin *textInfo;
+int *botSpace;
+/*
+ * Given the starting line in 'textInfo->startLine', this routine
+ * determines the index of the last line that can be drawn given the
+ * current size of the screen. If there are not enough lines to
+ * fill the screen, the index of the last line will be returned.
+ * The amount of empty bottom space is returned in 'botSpace'.
+ */
+{
+ int index, height, lineHeight;
+
+ height = YPADDING;
+ index = textInfo->startLine;
+ while (index < textInfo->numLines) {
+ lineHeight = textInfo->txtBuffer[index]->lineHeight + INTERLINE;
+ if (height + lineHeight > textInfo->h) break;
+ height += lineHeight;
+ index++;
+ }
+ if (botSpace) {
+ *botSpace = textInfo->h - height;
+ }
+ return index - 1;
+}
+
+
+
+static int UpdateScroll(display, textInfo)
+Display *display;
+struct txtWin *textInfo; /* Text window information */
+/*
+ * This routine computes the current extent of the scroll bar
+ * indicator and repaints the bar with the correct information.
+ */
+{
+ int top, bottom;
+
+ if (textInfo->numLines > 1) {
+ top = textInfo->startLine * (textInfo->h - 2*BARBORDER) /
+ (textInfo->numLines - 1);
+ bottom = textInfo->endLine * (textInfo->h - 2*BARBORDER) /
+ (textInfo->numLines - 1);
+ } else {
+ top = 0;
+ bottom = textInfo->h - (2*BARBORDER);
+ }
+
+ /* Draw it - make sure there is a little padding */
+ if (top == 0) top++;
+ if (bottom == textInfo->h-(2*BARBORDER)) bottom--;
+
+ XFillRectangle(display, textInfo->scrollBar,
+ textInfo->bgGC,
+ 0, 0, BARSIZE, top-1);
+ XFillRectangle(display, textInfo->scrollBar,
+ DEFAULT_GC, top, BARSIZE - (2*BARBORDER) - 2,
+ bottom - top);
+ XFillRectangle(display, textInfo->scrollBar, DEFAULT_GC,
+ 0, bottom+1, BARSIZE,
+ textInfo->h - (2 * BARBORDER) - bottom);
+
+ return 1;
+}
+
+
+
+
+int TxtClear(display, w)
+Display *display;
+Window w;
+/*
+ * This routine clears a scrollable text window. It resets the current
+ * writing position to the upper left hand corner of the screen.
+ * NOTE: THIS ALSO CLEARS THE CONTENTS OF THE TEXT WINDOW BUFFER AND
+ * RESETS THE SCROLL BAR. Returns 0 if the window is not a text window.
+ * This should be used *instead* of XClear.
+ */
+{
+ struct txtWin *textInfo;
+ int index;
+
+ if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w)) == 0)
+ return 0;
+
+ /* Zero out the arrays */
+ textInfo->bufSpot = 0;
+ for (index = 0; index < textInfo->numLines; index++) {
+ InitLine(textInfo->txtBuffer[index]);
+ }
+ textInfo->txtBuffer[0]->lineHeight =
+ textInfo->theFonts[textInfo->curFont].ascent +
+ textInfo->theFonts[textInfo->curFont].descent;
+
+ textInfo->numLines = 1;
+ textInfo->startLine = 0;
+ textInfo->endLine = 0;
+ textInfo->curLine = 0;
+ textInfo->curX = 0;
+ textInfo->curY = YPADDING + textInfo->theFonts[textInfo->curFont].ascent
+ + textInfo->theFonts[textInfo->curFont].descent;
+
+ textInfo->bottomSpace = textInfo->h - YPADDING -
+ textInfo->theFonts[textInfo->curFont].ascent - INTERLINE -
+ textInfo->theFonts[textInfo->curFont].descent;
+ /* Actually clear the window */
+ XClearWindow(display, w);
+
+ /* Draw the current cursor */
+ XFillRectangle(display, w, textInfo->CursorGC,
+ XPADDING + CUROFFSET, textInfo->curY,
+ CURSORWIDTH,
+ textInfo->theFonts[textInfo->curFont].ascent +
+ textInfo->theFonts[textInfo->curFont].descent);
+
+ /* Update the scroll bar */
+ UpdateScroll(display, textInfo);
+ return 1;
+}
+
+
+static int WarpToBottom(display, textInfo)
+Display *display;
+struct txtWin *textInfo; /* Text Information */
+/*
+ * This routine causes the specified text window to display its
+ * last screen of information. It updates the scroll bar
+ * to the appropriate spot. The implementation scans backward
+ * through the buffer to find an appropriate starting spot for
+ * the window.
+ */
+{
+ int index, height, lineHeight;
+
+ index = textInfo->numLines-1;
+ height = 0;
+ while (index >= 0) {
+ lineHeight = textInfo->txtBuffer[index]->lineHeight + INTERLINE;
+ if (height + lineHeight > textInfo->h) break;
+ height += lineHeight;
+ index--;
+ }
+ textInfo->startLine = index + 1;
+ textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace));
+ textInfo->curY = textInfo->h - textInfo->bottomSpace -
+ textInfo->txtBuffer[textInfo->endLine]->lineHeight;
+ XClearWindow(display, textInfo->mainWindow);
+ TxtRepaint(display, textInfo->mainWindow);
+ return 1;
+}
+
+
+
+static int UpdateExposures(display, textInfo)
+Display *display;
+struct txtWin *textInfo; /* Text window information */
+/*
+ * Before a new scrolling action occurs, the text window package
+ * must handle all COPYEXPOSE events generated by the last scrolling
+ * action. This routine is called to do this. Foreign events (those
+ * not handled by TxtFilter) are queued up and replaced on the queue
+ * after the processing of the exposure events is complete.
+ */
+{
+#if 0
+ XEvent foreignQueue[MAXFOREIGN];
+ int index, lastItem = 0;
+
+ while (textInfo->flagWord & COPYEXPOSE) {
+ XNextEvent(display, &(foreignQueue[lastItem]));
+ if (!TxtFilter(display, &(foreignQueue[lastItem])))
+ lastItem++;
+ if (lastItem >= MAXFOREIGN) {
+ printf("Too many foreign events to queue!\n");
+ textInfo->flagWord &= (~COPYEXPOSE);
+ }
+ }
+ for (index = 0; index < lastItem; index++) {
+ XPutBackEvent(display, &(foreignQueue[index]));
+ }
+#endif
+ return 1;
+}
+
+
+static int ScrollDown(display,textInfo)
+Display *display;
+struct txtWin *textInfo; /* Text window information */
+/*
+ * This routine scrolls the indicated text window down by one
+ * line. The line below the current line must exist. The window
+ * is scrolled so that the line below the last line is fully
+ * displayed. This may cause many lines to scroll off the top.
+ * Scrolling is done using XCopyArea. The exposure events should
+ * be caught using ExposeCopy.
+ */
+{
+ int lineSum, index, targetSpace, freeSpace, updateFlag;
+
+ lineSum = 0;
+ if (textInfo->endLine + 1 >= textInfo->numLines) return 0;
+ targetSpace = textInfo->txtBuffer[textInfo->endLine+1]->lineHeight +
+ INTERLINE;
+ if (textInfo->bottomSpace < targetSpace) {
+ index = textInfo->startLine;
+ while (index < textInfo->endLine) {
+ lineSum += (textInfo->txtBuffer[index]->lineHeight + INTERLINE);
+ if (textInfo->bottomSpace + lineSum >= targetSpace) break;
+ index++;
+ }
+
+ /* Must move upward by 'lineSum' pixels */
+ XCopyArea(display, textInfo->mainWindow, textInfo->mainWindow,
+ DEFAULT_GC, 0, lineSum,
+ textInfo->w - BARSIZE, textInfo->h,
+ 0, 0);
+
+ textInfo->flagWord |= COPYEXPOSE;
+ /* Repair the damage to the structures */
+ textInfo->startLine = index + 1;
+ updateFlag = 1;
+ } else {
+ updateFlag = 0;
+ }
+ /* More lines might be able to fit. Let's check. */
+ freeSpace = textInfo->bottomSpace + lineSum - targetSpace;
+ index = textInfo->endLine + 1;
+ while (index < textInfo->numLines-1) {
+ if (freeSpace - textInfo->txtBuffer[index+1]->lineHeight - INTERLINE < 0)
+ break;
+ freeSpace -= (textInfo->txtBuffer[index+1]->lineHeight + INTERLINE);
+ index++;
+ }
+ textInfo->endLine = index;
+ textInfo->bottomSpace = freeSpace;
+ if (updateFlag) {
+ UpdateExposures(display, textInfo);
+ }
+ UpdateScroll(display, textInfo);
+ return 1;
+}
+
+
+
+
+static int ExpandLines(textInfo)
+struct txtWin *textInfo; /* Text Information */
+/*
+ * This routine allocates and initializes additional space in
+ * the line start array (txtBuffer). The new space
+ * is allocated using realloc. The expansion factor is a percentage
+ * given by EXPANDPERCENT.
+ */
+{
+ int newSize, index;
+
+ newSize = textInfo->allocLines;
+ newSize += (newSize * EXPANDPERCENT) / 100;
+
+ textInfo->txtBuffer = (struct txtLine **)
+ realloc((char *) textInfo->txtBuffer,
+ (unsigned) (newSize * sizeof(struct txtLine *)));
+ for (index = textInfo->allocLines; index < newSize; index++) {
+ textInfo->txtBuffer[index] = alloc(struct txtLine);
+ InitLine(textInfo->txtBuffer[index]);
+ }
+ textInfo->allocLines = newSize;
+ return 1;
+}
+
+static int ExpandBuffer(textInfo)
+struct txtWin *textInfo; /* Text information */
+/*
+ * Expands the basic character buffer using realloc. The expansion
+ * factor is a percentage given by EXPANDPERCENT.
+ */
+{
+ int newSize;
+
+ newSize = textInfo->bufAlloc + (textInfo->bufAlloc * EXPANDPERCENT) / 100;
+ textInfo->mainBuffer = (short *)
+ realloc((char *) textInfo->mainBuffer, (unsigned) newSize * sizeof(short));
+ textInfo->bufAlloc = newSize;
+ return 1;
+}
+
+
+
+static int HandleNewLine(display, textInfo, flagWord)
+Display *display;
+struct txtWin *textInfo; /* Text Information */
+int flagWord; /* DODISP or NONEWLINE or both */
+/*
+ * This routine initializes the next line for drawing by setting
+ * its height to the current font height, scrolls the screen down
+ * one line, and updates the current drawing position to the
+ * left edge of the newly cleared line. If DODISP is specified,
+ * the screen will be updated (otherwise not). If NONEWLINE is
+ * specified, no newline character will be added to the text buffer
+ * (this is for line wrap).
+ */
+{
+ struct txtLine *curLine, *nextLine;
+
+ /* Check to see if a new line must be allocated */
+ if (textInfo->curLine >= textInfo->allocLines-1)
+ /* Expand the number of lines */
+ ExpandLines(textInfo);
+ textInfo->numLines += 1;
+
+ /* Then we initialize the next line */
+ nextLine = textInfo->txtBuffer[textInfo->numLines-1];
+ nextLine->lineHeight =
+ textInfo->theFonts[textInfo->curFont].ascent +
+ textInfo->theFonts[textInfo->curFont].descent;
+
+ curLine = textInfo->txtBuffer[textInfo->curLine];
+ if (flagWord & DODISP) {
+ /* Scroll down a line if required */
+ if ((textInfo->curY + curLine->lineHeight +
+ nextLine->lineHeight + (INTERLINE * 2)) > textInfo->h)
+ {
+ ScrollDown(display, textInfo);
+ }
+ else
+ {
+ /* Update the bottom space appropriately */
+ textInfo->bottomSpace -= (nextLine->lineHeight + INTERLINE);
+ textInfo->endLine += 1;
+ }
+ /* Update drawing position */
+ textInfo->curY = textInfo->h -
+ (textInfo->bottomSpace + nextLine->lineHeight);
+ }
+
+ /* Move down a line */
+ textInfo->curLine += 1;
+ if (!(flagWord & NONEWLINE)) {
+ /* Append end-of-line to text buffer */
+ if (textInfo->bufSpot >= textInfo->bufAlloc) {
+ /* Allocate more space in main text buffer */
+ ExpandBuffer(textInfo);
+ }
+ textInfo->mainBuffer[(textInfo->bufSpot)++] =
+ (textInfo->curFont << FONTSHIFT) | '\n';
+ }
+ nextLine->lineText = textInfo->bufSpot;
+ textInfo->curX = 0;
+ return 1;
+}
+
+
+
+static int CharSize(textInfo, lineNum, charNum)
+struct txtWin *textInfo; /* Current Text Information */
+int lineNum; /* Line in buffer */
+int charNum; /* Character in line */
+/*
+ * This routine determines the size of the specified character.
+ * It takes in account the font of the character and whether its
+ * fixed or variable. The size includes INTERSPACE spacing between
+ * the characters.
+ */
+{
+ register XFontStruct *charFont;
+ register short *theLine;
+ register short theChar;
+
+ theLine = &(textInfo->mainBuffer[textInfo->txtBuffer[lineNum]->lineText]);
+ theChar = theLine[charNum] & CHARMASK;
+ charFont = &(textInfo->theFonts[(theChar & FONTMASK) >> FONTSHIFT]);
+ if (theChar <= charFont->min_char_or_byte2 ||
+ theChar >= charFont->max_char_or_byte2 ||
+ charFont->per_char == 0)
+ return charFont->max_bounds.width + 1;
+ else
+ return charFont->per_char[theChar].width + 1;
+}
+
+
+
+
+
+static int HandleBackspace(display, textInfo, flagWord)
+Display *display;
+struct txtWin *textInfo; /* Text Information */
+int flagWord; /* DODISP or nothing */
+/*
+ * This routine handles a backspace found in the input stream. The
+ * character before the current writing position will be erased and
+ * the drawing position will move back one character. If the writing
+ * position is at the left margin, the drawing position will move
+ * up to the previous line. If it is a line that has been wrapped,
+ * the character at the end of the previous line will be erased.
+ */
+{
+ struct txtLine *thisLine, *prevLine;
+ int chSize;
+
+ thisLine = textInfo->txtBuffer[textInfo->curLine];
+ /* First, determine whether we need to go back a line */
+ if (thisLine->lineLength == 0) {
+ /* Bleep if at top of buffer */
+ if (textInfo->curLine == 0) {
+ XBell(display, 50);
+ return 0;
+ }
+
+ /* See if we have to scroll in the other direction */
+ if ((flagWord & DODISP) && (textInfo->curY <= YPADDING)) {
+ /* This will display the last lines of the buffer */
+ WarpToBottom(display, textInfo);
+ }
+
+ /* Set drawing position at end of previous line */
+ textInfo->curLine -= 1;
+ prevLine = textInfo->txtBuffer[textInfo->curLine];
+ textInfo->numLines -= 1;
+ if (flagWord & DODISP) {
+ textInfo->curY -= (prevLine->lineHeight + INTERLINE);
+ textInfo->bottomSpace += (thisLine->lineHeight + INTERLINE);
+ textInfo->endLine -= 1;
+ }
+
+ /* We are unlinewrapping if the previous line has flag set */
+ if (prevLine->lineFlags & WRAPFLAG) {
+ /* Get rid of line wrap indicator */
+ if (flagWord & DODISP) {
+ XFillRectangle(display, textInfo->mainWindow,
+ textInfo->bgGC,
+ textInfo->w - BARSIZE - WRAPINDSIZE,
+ textInfo->curY, WRAPINDSIZE,
+ prevLine->lineHeight);
+ }
+ prevLine->lineFlags &= (~WRAPFLAG);
+ /* Call recursively to wipe out the ending character */
+ HandleBackspace(display, textInfo, flagWord);
+ } else {
+ /* Delete the end-of-line in the primary buffer */
+ textInfo->bufSpot -= 1;
+ }
+ } else {
+ /* Normal deletion of character */
+ chSize =
+ CharSize(textInfo, textInfo->curLine,
+ textInfo->txtBuffer[textInfo->curLine]->lineLength - 1);
+ /* Move back appropriate amount and wipe it out */
+ thisLine->lineWidth -= chSize;
+ if (flagWord & DODISP) {
+ XFillRectangle(display, textInfo->mainWindow,
+ textInfo->bgGC,
+ thisLine->lineWidth, textInfo->curY,
+ chSize, thisLine->lineHeight);
+ }
+ /* Delete from buffer */
+ textInfo->txtBuffer[textInfo->curLine]->lineLength -= 1;
+ textInfo->bufSpot -= 1;
+ }
+ return 1;
+}
+
+
+
+static int DrawLineWrap(display, win, x, y, h, col)
+Display *display;
+Window win; /* What window to draw it in */
+int x, y; /* Position of upper left corner */
+int h; /* Height of indicator */
+int col; /* Color of indicator */
+/*
+ * This routine draws a line wrap indicator at the end of a line.
+ * Visually, it is an arrow of the specified height directly against
+ * the scroll bar border. The bitmap used for the arrow is stored
+ * in 'arrowMap' with size 'arrow_width' and 'arrow_height'.
+ */
+{
+ struct txtWin *textInfo;
+
+ textInfo = (struct txtWin *)XLookUpAssoc(display, textWindows,
+ (XID) win);
+
+ /* First, draw the arrow */
+ XCopyArea(display, textInfo->arrowMap, textInfo->mainWindow,
+ textInfo->CursorGC,
+ 0, 0, arrow_width, arrow_height,
+ x, y + h - arrow_height, 1);
+
+ /* Then draw the stem */
+ XDrawLine(display, textInfo->mainWindow, textInfo->CursorGC,
+ x + STEMOFFSET, y,
+ x + STEMOFFSET, y + h - arrow_height);
+ return 1;
+}
+
+
+
+
+static int DrawLine(display, textInfo, lineIndex, ypos)
+Display *display;
+struct txtWin *textInfo; /* Text window information */
+int lineIndex; /* Index of line to draw */
+int ypos; /* Y position for line */
+/*
+ * This routine destructively draws the indicated line in the
+ * indicated window at the indicated position. It does not
+ * clear to end of line however. It draws a line wrap indicator
+ * if needed but does not draw a cursor.
+ */
+{
+ int index, startPos, curFont, theColor, curX, saveX, fontIndex;
+ struct txtLine *someLine;
+ char lineBuffer[BUFSIZE], *glyph;
+ short *linePointer;
+ XFontStruct *theFont;
+ XGCValues gc;
+
+ /* First, we draw the text */
+ index = 0;
+ curX = XPADDING;
+ someLine = textInfo->txtBuffer[lineIndex];
+ linePointer = &(textInfo->mainBuffer[someLine->lineText]);
+ while (index < someLine->lineLength) {
+ startPos = index;
+ saveX = curX;
+ curFont = linePointer[index] & FONTMASK;
+ fontIndex = curFont >> FONTSHIFT;
+ theFont = &(textInfo->theFonts[fontIndex]);
+ theColor = textInfo->theColors[fontIndex];
+ glyph = &(lineBuffer[0]);
+ while ((index < someLine->lineLength) &&
+ ((linePointer[index] & FONTMASK) == curFont))
+ {
+ *glyph = linePointer[index] & CHARMASK;
+ index++;
+ curX += CharSize(textInfo, lineIndex, index);
+ glyph++;
+ }
+
+ /* Flush out the glyphs */
+ XFillRectangle(display, textInfo->mainWindow,
+ textInfo->bgGC,
+ saveX, ypos,
+ textInfo->w - BARSIZE,
+ someLine->lineHeight + YPADDING + INTERLINE);
+
+ XDrawString(display, textInfo->mainWindow,
+ textInfo->fontGC[fontIndex],
+ saveX, ypos,
+ lineBuffer, someLine->lineLength);
+ }
+ /* Then the line wrap indicator (if needed) */
+ if (someLine->lineFlags & WRAPFLAG) {
+ DrawLineWrap(display, textInfo->mainWindow,
+ textInfo->w - BARSIZE - WRAPINDSIZE,
+ ypos, someLine->lineHeight,
+ textInfo->fgPix);
+ }
+ return 1;
+}
+
+
+
+
+static int HandleNewFont(display, fontNum, textInfo, flagWord)
+Display *display;
+int fontNum; /* Font number */
+struct txtWin *textInfo; /* Text information */
+int flagWord; /* DODISP or nothing */
+/*
+ * This routine handles a new font request. These requests take
+ * the form "^F<digit>". The parsing is done in TxtWriteStr.
+ * This routine is called only if the form is valid. It may return
+ * a failure (0 status) if the requested font is not loaded.
+ * If the new font is larger than any of the current
+ * fonts on the line, it will change the line height and redisplay
+ * the line.
+ */
+{
+ struct txtLine *thisLine;
+ int heightDiff, baseDiff, redrawFlag;
+
+ if (textInfo->theFonts[fontNum].fid == 0) {
+ return 0;
+ } else {
+ thisLine = textInfo->txtBuffer[textInfo->curLine];
+ textInfo->curFont = fontNum;
+ redrawFlag = 0;
+ heightDiff = textInfo->theFonts[fontNum].ascent +
+ textInfo->theFonts[fontNum].descent -
+ thisLine->lineHeight;
+
+ if (heightDiff > 0) {
+ redrawFlag = 1;
+ } else {
+ heightDiff = 0;
+ }
+
+ if (redrawFlag) {
+ if (flagWord & DODISP) {
+ /* Clear current line */
+ XFillRectangle(display, textInfo->mainWindow,
+ textInfo->bgGC,
+ 0, textInfo->curY, textInfo->w,
+ thisLine->lineHeight);
+
+ /* Check to see if it requires scrolling */
+ if ((textInfo->curY + thisLine->lineHeight + heightDiff +
+ INTERLINE) > textInfo->h)
+ {
+ /*
+ * General approach: "unscroll" the last line up
+ * and then call ScrollDown to do the right thing.
+ */
+ textInfo->endLine -= 1;
+ textInfo->bottomSpace += thisLine->lineHeight +
+ INTERLINE;
+
+ XFillRectangle(display, textInfo->mainWindow,
+ textInfo->bgGC,
+ 0, textInfo->h - textInfo->bottomSpace,
+ textInfo->w, textInfo->bottomSpace);
+
+ thisLine->lineHeight += heightDiff;
+ ScrollDown(display, textInfo);
+ textInfo->curY = textInfo->h -
+ (textInfo->bottomSpace + INTERLINE +
+ thisLine->lineHeight);
+ }
+ else
+ {
+ /* Just update bottom space */
+ textInfo->bottomSpace -= heightDiff;
+ thisLine->lineHeight += heightDiff;
+ }
+ /* Redraw the current line */
+ DrawLine(display, textInfo, textInfo->curLine, textInfo->curY);
+ } else {
+ /* Just update line height */
+ thisLine->lineHeight += heightDiff;
+ }
+ }
+ return 1;
+ }
+}
+
+
+
+int TxtWriteStr(display, w, str)
+Display *display;
+Window w; /* Text window */
+register char *str; /* 0 terminated string */
+/*
+ * This routine writes a string to the specified text window.
+ * The following notes apply:
+ * - Text is always appended to the end of the text buffer.
+ * - If the scroll bar is positioned such that the end of the
+ * text is not visible, an automatic scroll to the bottom
+ * will be done before the appending of text.
+ * - Non-printable ASCII characters are not displayed.
+ * - The '\n' character causes the current text position to
+ * advance one line and start at the left.
+ * - Tabs are not supported.
+ * - Lines too long for the screen will be wrapped and a line wrap
+ * indication will be drawn.
+ * - Backspace clears the previous character. It will do the right
+ * thing if asked to backspace past a wrapped line.
+ * - A new font can be chosen using the sequence '^F<digit>' where
+ * <digit> is 0-7. The directive will be ignored if
+ * there is no font in the specified slot.
+ * Returns 0 if something went wrong.
+ */
+{
+ register int fontIndex;
+ register struct txtWin *textInfo;
+ register struct txtLine *thisLine;
+
+ if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w)) == 0)
+ return 0;
+
+ /* See if screen needs to be updated */
+ if (textInfo->flagWord & SCREENWRONG) {
+ TxtRepaint(display, textInfo->mainWindow);
+ }
+
+ /* See if we have to scroll down to the bottom */
+ if (textInfo->flagWord & NOTATBOTTOM) {
+ WarpToBottom(display, textInfo);
+ textInfo->flagWord &= (~NOTATBOTTOM);
+ }
+
+ /* Undraw the current cursor */
+ thisLine = textInfo->txtBuffer[textInfo->curLine];
+
+ XFillRectangle(display, w, textInfo->bgGC,
+ thisLine->lineWidth + CUROFFSET,
+ textInfo->curY,
+ CURSORWIDTH,
+ thisLine->lineHeight);
+
+ for ( /* str is ok */ ; (*str != 0) ; str++) {
+ /* Check to see if we are waiting on a font */
+ if (textInfo->flagWord & FONTNUMWAIT) {
+ textInfo->flagWord &= (~FONTNUMWAIT);
+ fontIndex = *str - '0';
+ if ((fontIndex >= 0) && (fontIndex < MAXFONTS)) {
+ /* Handle font -- go get next character */
+ if (HandleNewFont(display, fontIndex, textInfo, DODISP))
+ continue;
+ }
+ }
+
+ /* Inline code for handling normal character case */
+ if ((*str >= LOWCHAR) && (*str <= HIGHCHAR)) {
+ register XFontStruct *thisFont;
+ register struct txtLine *thisLine;
+ register int charWidth;
+ int thisColor;
+
+ /* Determine size of character */
+ thisFont = &(textInfo->theFonts[textInfo->curFont]);
+ thisColor = textInfo->theColors[textInfo->curFont];
+ if (*str <= thisFont->min_char_or_byte2 ||
+ *str >= thisFont->max_char_or_byte2 ||
+ thisFont->per_char == 0)
+ charWidth = thisFont->max_bounds.width + 1;
+ else
+ charWidth = thisFont->per_char[*str].width + 1;
+
+ /* Check to see if line wrap is required */
+ thisLine = textInfo->txtBuffer[textInfo->curLine];
+ if (thisLine->lineWidth + charWidth >
+ (textInfo->w-BARSIZE-WRAPINDSIZE))
+ {
+ DrawLineWrap(display, textInfo->mainWindow,
+ textInfo->w-BARSIZE-WRAPINDSIZE,
+ textInfo->curY, thisLine->lineHeight,
+ textInfo->fgPix);
+ thisLine->lineFlags |= WRAPFLAG;
+ /* Handle the spacing problem the same way as a newline */
+ HandleNewLine(display, textInfo, DODISP | NONEWLINE);
+ thisLine = textInfo->txtBuffer[textInfo->curLine];
+ }
+
+ /* Ready to draw character */
+ XDrawString(display, textInfo->mainWindow,
+ DEFAULT_GC,
+ textInfo->curX += charWidth,
+ textInfo->curY + thisLine->lineHeight,
+ str, 1);
+
+ /* Append character onto main buffer */
+ if (textInfo->bufSpot >= textInfo->bufAlloc)
+ /* Make room for more characters */
+ ExpandBuffer(textInfo);
+ textInfo->mainBuffer[(textInfo->bufSpot)++] =
+ (textInfo->curFont << FONTSHIFT) | (*str);
+
+ /* Update the line start array */
+ thisLine->lineLength += 1;
+ thisLine->lineWidth += charWidth;
+ } else if (*str == NEWLINE) {
+ HandleNewLine(display, textInfo, DODISP);
+ } else if (*str == NEWFONT) {
+ /* Go into waiting for font number mode */
+ textInfo->flagWord |= FONTNUMWAIT;
+ } else if (*str == BACKSPACE) {
+ HandleBackspace(display, textInfo, DODISP);
+ } else {
+ /* Ignore all others */
+ }
+ }
+ /* Draw the cursor in its new position */
+ thisLine = textInfo->txtBuffer[textInfo->curLine];
+
+ XFillRectangle(display, w, textInfo->CursorGC,
+ thisLine->lineWidth + CUROFFSET,
+ textInfo->curY /* + thisLine->lineHeight */,
+ CURSORWIDTH, thisLine->lineHeight);
+
+ return 1;
+}
+
+
+
+int TxtJamStr(display, w, str)
+Display *display;
+Window w; /* Text window */
+register char *str; /* NULL terminated string */
+/*
+ * This is the same as TxtWriteStr except the screen is NOT updated.
+ * After a call to this routine, TxtRepaint should be called to
+ * update the screen. This routine is meant to be used to load
+ * a text buffer with information and then allow the user to
+ * scroll through it at will.
+ */
+{
+ register int fontIndex;
+ register struct txtWin *textInfo;
+
+ if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w)
+ ) == 0)
+ return 0;
+
+ for ( /* str is ok */ ; (*str != 0) ; str++) {
+ /* Check to see if we are waiting on a font */
+ if (textInfo->flagWord & FONTNUMWAIT) {
+ textInfo->flagWord &= (~FONTNUMWAIT);
+ fontIndex = *str - '0';
+ if ((fontIndex >= 0) && (fontIndex < MAXFONTS)) {
+ if (HandleNewFont(display, fontIndex, textInfo, 0)) {
+ /* Handled font -- go get next character */
+ continue;
+ }
+ }
+ }
+ /* Inline code for handling normal character case */
+ if ((*str >= LOWCHAR) && (*str <= HIGHCHAR)) {
+ register XFontStruct *thisFont;
+ register struct txtLine *thisLine;
+ register int charWidth;
+
+ /* Determine size of character */
+ thisFont = &(textInfo->theFonts[textInfo->curFont]);
+
+ if (*str <= thisFont->min_char_or_byte2 ||
+ *str >= thisFont->max_char_or_byte2 ||
+ thisFont->per_char == 0)
+ charWidth = thisFont->max_bounds.width + 1;
+ else
+ charWidth = thisFont->per_char[*str].width + 1;
+
+ /* Check to see if line wrap is required */
+ thisLine = textInfo->txtBuffer[textInfo->curLine];
+ if (thisLine->lineWidth + charWidth >
+ (textInfo->w-BARSIZE-WRAPINDSIZE))
+ {
+ thisLine->lineFlags |= WRAPFLAG;
+ /* Handle the spacing problem the same way as a newline */
+ HandleNewLine(display, textInfo, NONEWLINE);
+ thisLine = textInfo->txtBuffer[textInfo->curLine];
+ }
+ /* Append character onto main buffer */
+ if (textInfo->bufSpot >= textInfo->bufAlloc)
+ /* Make room for more characters */
+ ExpandBuffer(textInfo);
+ textInfo->mainBuffer[(textInfo->bufSpot)++] =
+ (textInfo->curFont << FONTSHIFT) | (*str);
+
+ /* Update the line start array */
+ thisLine->lineLength += 1;
+ thisLine->lineWidth += charWidth;
+ } else if (*str == NEWLINE) {
+ HandleNewLine(display, textInfo, 0);
+ } else if (*str == NEWFONT) {
+ /* Go into waiting for font number mode */
+ textInfo->flagWord |= FONTNUMWAIT;
+ } else if (*str == BACKSPACE) {
+ HandleBackspace(display, textInfo, 0);
+ } else {
+ /* Ignore all others */
+ }
+ }
+ textInfo->flagWord |= SCREENWRONG;
+ return 1;
+}
+
+
+
+int TxtRepaint(display,w)
+Display *display;
+Window w;
+/*
+ * Repaints the given scrollable text window. The routine repaints
+ * the entire window. For handling exposure events, the TxtFilter
+ * routine should be used.
+ */
+{
+ struct txtWin *textInfo;
+ int index, ypos;
+
+ if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w)
+ ) == 0)
+ return 0;
+
+ /* Check to see if the screen is up to date */
+ if (textInfo->flagWord & SCREENWRONG) {
+ textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace));
+ textInfo->flagWord &= (~SCREENWRONG);
+ }
+
+ ypos = YPADDING;
+ index = textInfo->startLine;
+ for (;;) {
+ DrawLine(display, textInfo, index, ypos);
+ if (index >= textInfo->endLine) break;
+ ypos += (textInfo->txtBuffer[index]->lineHeight + INTERLINE);
+ index++;
+ }
+ /* Draw the cursor (if on screen) */
+ if (textInfo->endLine == textInfo->curLine) {
+ XFillRectangle(display, w, textInfo->CursorGC,
+ textInfo->txtBuffer[index]->lineWidth + CUROFFSET,
+ ypos /* + textInfo->txtBuffer[index]->lineHeight */,
+ CURSORWIDTH, textInfo->txtBuffer[index]->lineHeight);
+
+ }
+ /* Update the scroll bar */
+ UpdateScroll(display, textInfo);
+ return 1;
+}
+
+
+
+static int InsertIndex(textInfo, thisIndex, ypos)
+struct txtWin *textInfo; /* Text Window Information */
+int thisIndex; /* Line index of exposed line */
+int ypos; /* Drawing position of line */
+/*
+ * This routine inserts the supplied line index into the copy
+ * exposure array for 'textInfo'. The array is kept sorted
+ * from lowest to highest using insertion sort. The array
+ * is dynamically expanded if needed.
+ */
+{
+ struct expEvent *newItem;
+ int newSize, index, downIndex;
+
+ /* Check to see if we need to expand it */
+ if ((textInfo->exposeSize + 3) >= textInfo->exposeAlloc) {
+ newSize = textInfo->exposeAlloc +
+ (textInfo->exposeAlloc * EXPANDPERCENT / 100);
+ textInfo->exposeAry = (struct expEvent **)
+ realloc((char *) textInfo->exposeAry,
+ (unsigned) (newSize * sizeof(struct expEvent *)));
+ for (index = textInfo->exposeAlloc; index < newSize; index++)
+ textInfo->exposeAry[index] = alloc(struct expEvent);
+ textInfo->exposeAlloc = newSize;
+ }
+ /* Find spot for insertion. NOTE: last spot has big number */
+ for (index = 0; index <= textInfo->exposeSize; index++) {
+ if (textInfo->exposeAry[index]->lineIndex >= thisIndex) {
+ if (textInfo->exposeAry[index]->lineIndex > thisIndex) {
+ /* Insert before this entry */
+ newItem = textInfo->exposeAry[textInfo->exposeSize+1];
+ for (downIndex = textInfo->exposeSize;
+ downIndex >= index;
+ downIndex--)
+ {
+ textInfo->exposeAry[downIndex+1] =
+ textInfo->exposeAry[downIndex];
+ }
+ /* Put a free structure at this spot */
+ textInfo->exposeAry[index] = newItem;
+ /* Fill it in */
+ textInfo->exposeAry[index]->lineIndex = thisIndex;
+ textInfo->exposeAry[index]->ypos = ypos;
+ /* Break out of loop */
+ textInfo->exposeSize += 1;
+ }
+ break;
+ }
+ }
+ return 1;
+}
+
+
+
+static int ScrollUp(display, textInfo)
+Display *display;
+struct txtWin *textInfo; /* Text window information */
+/*
+ * This routine scrolls the indicated text window up by one
+ * line. The line above the current line must exist. The
+ * window is scrolled so that the line above the start line
+ * is displayed at the top of the screen. This may cause
+ * many lines to scroll off the bottom. The scrolling is
+ * done using XCopyArea. The exposure events should be caught
+ * by ExposeCopy.
+ */
+{
+ int targetSpace;
+
+ /* Make sure all exposures have been handled by now */
+ if (textInfo->startLine == 0) return 0;
+ targetSpace = textInfo->txtBuffer[textInfo->startLine-1]->lineHeight +
+ INTERLINE;
+ /* Move the area downward by the target amount */
+ XCopyArea(display, textInfo->mainWindow, textInfo->mainWindow,
+ DEFAULT_GC,
+ 0, YPADDING, textInfo->w - BARSIZE,
+ textInfo->h, 0, targetSpace);
+
+ textInfo->flagWord |= COPYEXPOSE;
+ /* Update the text window parameters */
+ textInfo->startLine -= 1;
+ textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace));
+
+ /* Clear out bottom space region */
+ XClearArea(display, textInfo->mainWindow,
+ 0, textInfo->h - textInfo->bottomSpace,
+ textInfo->w, textInfo->bottomSpace);
+
+ UpdateExposures(display, textInfo);
+ UpdateScroll(display, textInfo);
+
+ return 1;
+}
+
+
+static int ScrollToSpot(display, textInfo, ySpot)
+Display *display;
+struct txtWin *textInfo; /* Text window information */
+int ySpot; /* Button position in scroll window */
+/*
+ * This routine scrolls the specified text window relative to the
+ * position of the mouse in the scroll bar. The center of the screen
+ * will be positioned to correspond to the mouse position.
+ */
+{
+ int targetLine, aboveLines;
+
+ targetLine = textInfo->numLines * ySpot / textInfo->h;
+ textInfo->startLine = targetLine;
+ textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace));
+ aboveLines = 0;
+ /* Make the target line the *center* of the window */
+ while ((textInfo->startLine > 0) &&
+ (aboveLines < textInfo->endLine - targetLine))
+ {
+ textInfo->startLine -= 1;
+ textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace));
+ aboveLines++;
+ }
+ if (textInfo->endLine == textInfo->numLines-1) {
+ WarpToBottom(display, textInfo);
+ } else {
+ XClearWindow(display, textInfo->mainWindow);
+ TxtRepaint(display, textInfo->mainWindow);
+ }
+ return 1;
+}
+
+
+
+static int LineToTop(display, textInfo, pos)
+Display *display;
+struct txtWin *textInfo; /* Text window information */
+int pos; /* Y position of mouse */
+/*
+ * This routine scrolls the screen down until the line at the
+ * mouse position is at the top of the screen. It stops
+ * if it can't scroll the buffer down that far. If the
+ * global 'ScrollOption' is NORMSCROLL, a smooth scroll
+ * is used. Otherwise, it jumps to the right position
+ * and repaints the screen.
+ */
+{
+ int index, sum;
+
+ /* First, we find the current line */
+ sum = 0;
+ for (index = textInfo->startLine; index <= textInfo->endLine; index++) {
+ if (sum + textInfo->txtBuffer[index]->lineHeight + INTERLINE> pos) break;
+ sum += textInfo->txtBuffer[index]->lineHeight + INTERLINE;
+ }
+ /* We always want to scroll down at least one line */
+ if (index == textInfo->startLine) index++;
+ if (ScrollOption == NORMSCROLL) {
+ /* Scroll down until 'index' is the starting line */
+ while ((textInfo->startLine < index) && ScrollDown(display, textInfo))
+ {
+ /* Empty Loop Body */
+ }
+ } else {
+ /* Immediately jump to correct spot */
+ textInfo->startLine = index;
+ textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace));
+ if (textInfo->endLine == textInfo->numLines-1) {
+ WarpToBottom(display, textInfo);
+ } else {
+ XClearWindow(display, textInfo->mainWindow);
+ TxtRepaint(display, textInfo->mainWindow);
+ }
+ }
+ /* Check to see if at end of buffer */
+ if (textInfo->endLine >= textInfo->numLines-1) {
+ textInfo->flagWord &= (~NOTATBOTTOM);
+ }
+ return 1;
+}
+
+
+
+static int TopToHere(display, textInfo, pos)
+Display *display;
+struct txtWin *textInfo; /* Text window information */
+int pos; /* Y position of mouse */
+/*
+ * This routine scrolls the screen up until the top line of
+ * the screen is at the current Y position of the mouse. Again,
+ * it will stop if it can't scroll that far. If the global
+ * 'ScrollOption' is NORMSCROLL, a smooth scroll is used.
+ * If it's not, it will simply redraw the screen at the
+ * correct spot.
+ */
+{
+ int sum, target, linesup, index;
+
+ target = pos - textInfo->txtBuffer[textInfo->startLine]->lineHeight;
+ /* We always want to scroll up at least one line */
+ if (target <= 0) target = 1;
+ sum = 0;
+ linesup = 0;
+ /* Check to see if we are at the top anyway */
+ if (textInfo->startLine == 0) return 0;
+ if (ScrollOption == NORMSCROLL) {
+ /* Scroll up until sum of new top lines greater than target */
+ while ((sum < target) && ScrollUp(display, textInfo)) {
+ sum += textInfo->txtBuffer[textInfo->startLine]->lineHeight;
+ linesup++;
+ }
+ } else {
+ /* Search backward to find index */
+ index = textInfo->startLine - 1;
+ while ((index > 0) && (sum < target)) {
+ sum += textInfo->txtBuffer[index]->lineHeight;
+ linesup++;
+ index--;
+ }
+ /* Go directly to the index */
+ textInfo->startLine = index;
+ textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace));
+ XClearWindow(display, textInfo->mainWindow);
+ TxtRepaint(display, textInfo->mainWindow);
+ }
+ /* If we scrolled, assert we are not at bottom of buffer */
+ if (linesup > 0) {
+ textInfo->flagWord |= NOTATBOTTOM;
+ }
+ return 1;
+}
+
+
+
+int TxtFilter(display, evt)
+Display *display;
+XEvent *evt;
+/*
+ * This routine handles events associated with scrollable text windows.
+ * It will handle all exposure events and any button released events
+ * in the scroll bar of a text window. It does NOT handle any other
+ * events. If it cannot handle the event, it will return 0.
+ */
+{
+ XExposeEvent *expose = &evt->xexpose;
+ XButtonEvent *btEvt = &evt->xbutton;
+ XGraphicsExposeEvent *gexpose = &evt->xgraphicsexpose;
+ XNoExposeEvent *noexpose = &evt->xnoexpose;
+ struct txtWin *textInfo;
+ int index, ypos;
+ Window w, sw;
+
+ if (textWindows == (XAssocTable *) 0) {
+ textWindows = XCreateAssocTable(32);
+ if (textWindows == (XAssocTable *) 0) return(0);
+ }
+ if (evt->type == Expose) {
+ w = expose->window;
+ sw = 0;
+ }
+ else if (evt->type == GraphicsExpose) {
+ w = gexpose->drawable;
+ sw = 0;
+ }
+ else if (evt->type == NoExpose) {
+ w = noexpose->drawable;
+ sw = 0;
+ }
+ else if (evt->type == ButtonRelease) {
+ w = btEvt->window;
+ sw = btEvt->subwindow;
+ }
+ else
+ return 0;
+
+ if ((textInfo = (struct txtWin *)
+ XLookUpAssoc(display, textWindows, (XID) w)) == 0)
+ return 0;
+
+ /* Determine whether it's main window or not */
+ if ((w == textInfo->mainWindow) && (sw == 0)) {
+ /* Main Window - handle exposures */
+ switch (evt->type) {
+ case Expose:
+ ypos = 0 /*YPADDING*/;
+ for (index = textInfo->startLine;
+ index <= textInfo->endLine;
+ index++)
+ {
+ int lh = textInfo->txtBuffer[index]->lineHeight;
+
+ if (((ypos + lh) >= expose->y) &&
+ (ypos <= (expose->y + expose->height)))
+ {
+ /* Intersection region */
+ /* Draw line immediately */
+ DrawLine(display, textInfo, index, ypos);
+ /* And possibly draw cursor */
+ if (textInfo->curLine == index) {
+ XFillRectangle(display, w, textInfo->CursorGC,
+ textInfo->txtBuffer[index]->lineWidth +
+ CUROFFSET,
+ ypos,
+ CURSORWIDTH,
+ lh);
+ }
+ }
+ ypos += lh + INTERLINE;
+ }
+ break;
+ case GraphicsExpose:
+ ypos = 0 /*YPADDING*/;
+ for (index = textInfo->startLine;
+ index <= textInfo->endLine;
+ index++)
+ {
+ int lh = textInfo->txtBuffer[index]->lineHeight;
+
+ if (((ypos + lh) >= gexpose->y) &&
+ (ypos <= (gexpose->y + gexpose->height)))
+ {
+ /* Intersection region */
+ /* Draw line immediately */
+ DrawLine(display, textInfo, index, ypos);
+ /* And possibly draw cursor */
+ if (textInfo->curLine == index) {
+ XFillRectangle(display, w, textInfo->CursorGC,
+ textInfo->txtBuffer[index]->lineWidth +
+ CUROFFSET,
+ ypos,
+ CURSORWIDTH,
+ lh);
+ }
+ }
+ ypos += lh + INTERLINE;
+ }
+ break;
+ case NoExpose:
+ break;
+ default:
+ /* Not one of our events */
+ return 0;
+ }
+ } else {
+ switch (evt->type) {
+ case Expose:
+ UpdateScroll(display, textInfo);
+ break;
+ case ButtonRelease:
+ /* Find out which button */
+ switch (btEvt->button) {
+ case Button1:
+ /* Scroll up until top line is at mouse position */
+ TopToHere(display, textInfo, btEvt->y);
+ break;
+ case Button2:
+ /* Scroll to spot relative to position */
+ ScrollToSpot(display, textInfo, btEvt->y);
+ if (textInfo->endLine >= textInfo->numLines-1) {
+ textInfo->flagWord &= (~NOTATBOTTOM);
+ } else {
+ textInfo->flagWord |= NOTATBOTTOM;
+ }
+ break;
+ case Button3:
+ /* Scroll down until pointed line is at top */
+ LineToTop(display, textInfo, btEvt->y);
+ break;
+ }
+ break;
+ default:
+ /* Not one of our events */
+ return 0;
+ }
+ }
+ return 1;
+}
diff --git a/gnu/games/chess/Xchess/scrollText.h b/gnu/games/chess/Xchess/scrollText.h
new file mode 100644
index 000000000000..d9d05b08dc0b
--- /dev/null
+++ b/gnu/games/chess/Xchess/scrollText.h
@@ -0,0 +1,32 @@
+/*
+ * Scrollable Text Window Header File
+ *
+ * David Harrison
+ * University of California, Berkeley
+ * 1986
+ *
+ * This file contains definitions for a scrollable text window
+ * with scroll bar support.
+ */
+
+int TxtGrab();
+ /* Take hold of a previously created window */
+
+#define TXT_NO_COLOR -1
+
+int TxtAddFont();
+ /* Loads a new font for use later */
+int TxtWinP();
+ /* Returns non-zero value if the window is text window */
+int TxtClear();
+ /* Clears text window and resets text buffer */
+
+int TxtWriteStr();
+ /* Writes a string to window with immediate update */
+int TxtJamStr();
+ /* Write a string without causing update to screen */
+
+int TxtRepaint();
+ /* Repaints entire scrollable text window */
+int TxtFilter();
+ /* Handles events related to text window */
diff --git a/gnu/games/chess/Xchess/scrollText/scrollText.c b/gnu/games/chess/Xchess/scrollText/scrollText.c
new file mode 100644
index 000000000000..432071086d15
--- /dev/null
+++ b/gnu/games/chess/Xchess/scrollText/scrollText.c
@@ -0,0 +1,1858 @@
+/*
+ * A Scrollable Text Output Window
+ *
+ * David Harrison
+ * University of California, Berkeley
+ * 1986
+ *
+ * The following is an implementation for a scrollable text output
+ * system. It handles exposure events only (other interactions are
+ * under user control). For scrolling, a always present scroll bar
+ * is implemented. It detects size changes and compensates accordingly.
+ */
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/X10.h>
+#include <sys/types.h>
+#include "scrollText.h"
+
+extern char *malloc();
+extern char *realloc();
+#define alloc(type) (type *) malloc(sizeof(type))
+#define numalloc(type, num) (type *) malloc((unsigned) (num * sizeof(type)))
+#define MAXINT 2147483647
+
+extern XAssocTable *XCreateAssocTable();
+extern caddr_t XLookUpAssoc();
+
+static XAssocTable *textWindows = (XAssocTable *) 0;
+
+#define NOOPTION -1 /* Option hasn't been set yet */
+#define NORMSCROLL 0 /* Smooth scroll on LineToTop and TopToHere */
+#define JUMPSCROLL 1 /* Jump scrolling on LineToTop and TopToHere */
+
+static int ScrollOption = NOOPTION;
+
+typedef char *Generic;
+
+#define DEFAULT_GC textInfo->fontGC[textInfo->curFont]
+
+#define BARSIZE 15
+#define BARBORDER 1
+#define MAXFONTS 8
+#define INITBUFSIZE 1024
+#define INITLINES 50
+#define INITEXPARY 50
+#define XPADDING 2
+#define YPADDING 2
+#define INTERLINE 5
+#define INTERSPACE 1
+#define CURSORWIDTH 2
+#define EXPANDPERCENT 40
+#define BUFSIZE 1024
+#define CUROFFSET 1
+#define MAXFOREIGN 250
+#define NOINDEX -1
+
+/* The wrap line indicator */
+#define WRAPINDSIZE 7
+#define STEMOFFSET 5
+#define arrow_width 7
+#define arrow_height 5
+static char arrow_bits[] = {
+ 0x24, 0x26, 0x3f, 0x06, 0x04};
+
+#define NEWLINE '\n'
+#define BACKSPACE '\010'
+#define NEWFONT '\006'
+#define LOWCHAR '\040'
+#define HIGHCHAR '\176'
+
+#define CHARMASK 0x00ff /* Character mask */
+#define FONTMASK 0x0700 /* Character font */
+#define FONTSHIFT 8 /* Shift amount */
+
+#define WRAPFLAG 0x01 /* Line wrap flag */
+
+/*
+ * Lines are represented by a pointer into the overall array of
+ * 16-bit characters. The lower eight bits is used to indicate the character
+ * (in ASCII), and the next two bits are used to indicate the font
+ * the character should be drawn in.
+ */
+
+typedef struct txtLine {
+ int lineLength; /* Current line length */
+ int lineHeight; /* Full height of line in pixels */
+ int lineBaseLine; /* Current baseline of the line */
+ int lineWidth; /* Drawing position at end of line */
+ int lineText; /* Offset into master buffer */
+ int lineFlags; /* Line wrap flag is here */
+};
+
+
+/*
+ * For ExposeCopy events, we queue up the redraw requests collapsing
+ * them into line redraw requests until the CopyExpose event arrives.
+ * The queue is represented as a dynamic array of the following
+ * structure:
+ */
+
+typedef struct expEvent {
+ int lineIndex; /* Index of line to redraw */
+ int ypos; /* Drawing position of line */
+};
+
+
+/*
+ * The text buffer is represented using a dynamic counted array
+ * of 16-bit quantities. This array expands as needed.
+ * For the screen representation, a dynamic counted array
+ * of line structures is used. This array points into the
+ * text buffer to denote the start of each line and its parameters.
+ * The windows are configured as one overall window which contains
+ * the scroll bar as a sub-window along its right edge. Thus,
+ * the text drawing space is actually w-BARSIZE.
+ */
+
+#define NOTATBOTTOM 0x01 /* Need to scroll to bottom before appending */
+#define FONTNUMWAIT 0x02 /* Waiting for font number */
+#define COPYEXPOSE 0x04 /* Need to process a copy expose event */
+#define SCREENWRONG 0x08 /* TxtJamStr has invalidated screen contents */
+
+typedef struct txtWin {
+ /* Basic text buffer */
+ int bufAlloc; /* Allocated size of buffer */
+ int bufSpot; /* Current writing position in buffer */
+ short *mainBuffer; /* Main buffer of text */
+
+ /* Line information */
+ int numLines; /* Number of display lines in buffer */
+ int allocLines; /* Number of lines allocated */
+ struct txtLine **txtBuffer; /* Dynamic array of lines */
+
+ /* Current Window display information */
+ Window mainWindow; /* Text display window */
+ Window scrollBar; /* Subwindow for scroll bar */
+ Pixmap arrowMap; /* line wrap indicator */
+ int bgPix, fgPix; /* Background and cursor */
+ GC CursorGC; /* gc for the cursor */
+ GC bgGC; /* gc for erasing things */
+ GC fontGC[MAXFONTS]; /* gc for doing fonts */
+ XFontStruct theFonts[MAXFONTS];/* Display fonts */
+ int theColors[MAXFONTS]; /* foregrounds of the fonts */
+ int curFont; /* current font for tracking */
+ int w, h; /* Current size */
+ int startLine; /* Top line in display */
+ int endLine; /* Bottom line in display */
+ int bottomSpace; /* Space at bottom of screen */
+ int flagWord; /* If non-zero, not at end */
+
+ /* For handling ExposeCopy events */
+ int exposeSize; /* Current size of array */
+ int exposeAlloc; /* Allocated size */
+ struct expEvent **exposeAry;/* Array of line indices */
+
+ /* Drawing position information */
+ int curLine; /* Current line in buffer */
+ int curX; /* Current horizontal positi */
+ int curY; /* Current vertical drawing */
+};
+
+/* Flags for the various basic character handling functions */
+
+#define DODISP 0x01 /* Update the display */
+#define NONEWLINE 0x02 /* Dont append newline */
+
+
+
+static int InitLine(newLine)
+struct txtLine *newLine; /* Newly created line structure */
+/*
+ * This routine initializes a newly created line structure.
+ */
+{
+ newLine->lineLength = 0;
+ newLine->lineHeight = 0;
+ newLine->lineBaseLine = 0;
+ newLine->lineWidth = XPADDING;
+ newLine->lineText = NOINDEX;
+ newLine->lineFlags = 0;
+ return 1;
+}
+
+
+
+
+int TxtGrab(display, txtWin, program, mainFont, bg, fg, cur)
+Display *display; /* display window is on */
+Window txtWin; /* Window to take over as scrollable text */
+char *program; /* Program name for Xdefaults */
+XFontStruct *mainFont; /* Primary text font */
+int bg, fg, cur; /* Background, foreground, and cursor colors */
+/*
+ * This routine takes control of 'txtWin' and makes it into a scrollable
+ * text output window. It will create a sub-window for the scroll bar
+ * with a background of 'bg' and an bar with color 'fg'. Both fixed width
+ * and variable width fonts are supported. Additional fonts can be loaded
+ * using 'TxtAddFont'. Returns 0 if there were problems, non-zero if
+ * everything went ok.
+ */
+{
+ struct txtWin *newWin; /* Text package specific information */
+ XWindowAttributes winInfo; /* Window information */
+ int index;
+ XGCValues gc_val;
+
+ if (textWindows == (XAssocTable *) 0) {
+ textWindows = XCreateAssocTable(32);
+ if (textWindows == (XAssocTable *) 0) return(0);
+ }
+ if (XGetWindowAttributes(display, txtWin, &winInfo) == 0) return 0;
+
+ if (ScrollOption == NOOPTION) {
+ /* Read to see if the user wants jump scrolling or not */
+ if (XGetDefault(display, program, "JumpScroll")) {
+ ScrollOption = JUMPSCROLL;
+ } else {
+ ScrollOption = NORMSCROLL;
+ }
+ }
+
+ /* Initialize local structure */
+ newWin = alloc(struct txtWin);
+
+ /* Initialize arrow pixmap */
+ newWin->arrowMap = XCreatePixmapFromBitmapData(display, txtWin,
+ arrow_bits,
+ arrow_width, arrow_height,
+ cur, bg,
+ DisplayPlanes(display, 0));
+
+ newWin->bufAlloc = INITBUFSIZE;
+ newWin->bufSpot = 0;
+ newWin->mainBuffer = numalloc(short, INITBUFSIZE);
+
+ newWin->numLines = 1;
+ newWin->allocLines = INITLINES;
+ newWin->txtBuffer = numalloc(struct txtLine *, INITLINES);
+ for (index = 0; index < INITLINES; index++) {
+ newWin->txtBuffer[index] = alloc(struct txtLine);
+ InitLine(newWin->txtBuffer[index]);
+ }
+
+ /* Window display information */
+ newWin->mainWindow = txtWin;
+ newWin->w = winInfo.width;
+ newWin->h = winInfo.height;
+ newWin->startLine = 0;
+ newWin->endLine = 0;
+ newWin->bottomSpace = winInfo.height
+ - YPADDING - mainFont->ascent - mainFont->descent - INTERLINE;
+ newWin->flagWord = 0;
+ newWin->bgPix = bg;
+ newWin->fgPix = fg;
+
+ /* Scroll Bar Creation */
+ newWin->scrollBar = XCreateSimpleWindow(display, txtWin,
+ winInfo.width - BARSIZE,
+ 0, BARSIZE - (2*BARBORDER),
+ winInfo.height - (2*BARBORDER),
+ BARBORDER,
+ fg, bg);
+ XSelectInput(display, newWin->scrollBar, ExposureMask|ButtonReleaseMask);
+ XMapRaised(display, newWin->scrollBar);
+
+ /* Font and Color Initialization */
+ newWin->theFonts[0] = *mainFont;
+ newWin->theColors[0] = fg;
+ gc_val.function = GXcopy;
+ gc_val.plane_mask = AllPlanes;
+ gc_val.foreground = fg;
+ gc_val.background = bg;
+ gc_val.graphics_exposures = 1;
+ gc_val.font = mainFont->fid;
+ gc_val.line_width = 1;
+ gc_val.line_style = LineSolid;
+
+ newWin->fontGC[0] = XCreateGC(display, txtWin,
+ GCFunction | GCPlaneMask |
+ GCForeground | GCBackground |
+ GCGraphicsExposures | GCFont,
+ &gc_val);
+
+ gc_val.foreground = cur;
+ newWin->CursorGC = XCreateGC(display, txtWin,
+ GCFunction | GCPlaneMask |
+ GCForeground | GCBackground |
+ GCLineStyle | GCLineWidth,
+ &gc_val);
+
+ gc_val.foreground = bg;
+ newWin->bgGC = XCreateGC(display, txtWin,
+ GCFunction | GCPlaneMask |
+ GCForeground | GCBackground |
+ GCGraphicsExposures | GCFont,
+ &gc_val);
+
+
+ for (index = 1; index < MAXFONTS; index++) {
+ newWin->theFonts[index].fid = 0;
+ newWin->fontGC[index] = 0;
+ }
+
+
+ /* Initialize size of first line */
+ newWin->txtBuffer[0]->lineHeight = newWin->theFonts[0].ascent +
+ newWin->theFonts[0].descent;
+ newWin->txtBuffer[0]->lineText = 0;
+
+ /* ExposeCopy array initialization */
+ newWin->exposeSize = 0;
+ newWin->exposeAlloc = INITEXPARY;
+ newWin->exposeAry = numalloc(struct expEvent *, INITEXPARY);
+ for (index = 0; index < newWin->exposeAlloc; index++)
+ newWin->exposeAry[index] = alloc(struct expEvent);
+ /* Put plus infinity in last slot for sorting purposes */
+ newWin->exposeAry[0]->lineIndex = MAXINT;
+
+ /* Drawing Position Information */
+ newWin->curLine = 0;
+ newWin->curX = 0;
+ newWin->curY = YPADDING + mainFont->ascent + mainFont->descent;
+
+ /* Attach it to both windows */
+ XMakeAssoc(display, textWindows, (XID) txtWin, (caddr_t) newWin);
+ XMakeAssoc(display, textWindows, (XID) newWin->scrollBar, (caddr_t) newWin);
+ return 1;
+}
+
+
+int TxtRelease(display, w)
+Display *display;
+Window w; /* Window to release */
+/*
+ * This routine releases all resources associated with the
+ * specified window which are consumed by the text
+ * window package. This includes the entire text buffer, line start
+ * array, and the scroll bar window. However, the window
+ * itself is NOT destroyed. The routine will return zero if
+ * the window is not owned by the text window package.
+ */
+{
+ struct txtWin *textInfo;
+ int index;
+
+ if ((textInfo = (struct txtWin *) XLookUpAssoc(display,
+ textWindows, (XID) w)) == 0)
+ return 0;
+
+ for (index = 0; index < MAXFONTS; index++)
+ if (textInfo->fontGC[index] != 0)
+ XFreeGC(display, textInfo->fontGC[index]);
+
+ free((Generic) textInfo->mainBuffer);
+ for (index = 0; index < textInfo->numLines; index++) {
+ free((Generic) textInfo->txtBuffer[index]);
+ }
+ free((Generic) textInfo->txtBuffer);
+ XDestroyWindow(display, textInfo->scrollBar);
+ for (index = 0; index < textInfo->exposeSize; index++) {
+ free((Generic) textInfo->exposeAry[index]);
+ }
+ free((Generic) textInfo->exposeAry);
+ XDeleteAssoc(display, textWindows, (XID) w);
+ free((Generic) textInfo);
+ return 1;
+}
+
+
+
+static int RecompBuffer(textInfo)
+struct txtWin *textInfo; /* Text window information */
+/*
+ * This routine recomputes all line breaks in a buffer after
+ * a change in window size or font. This is done by throwing
+ * away the old line start array and recomputing it. Although
+ * a lot of this work is also done elsewhere, it has been included
+ * inline here for efficiency.
+ */
+{
+ int startPos, endSize, linenum;
+ register int index, chsize, curfont;
+ register short *bufptr;
+ register XFontStruct *fontptr;
+ register struct txtLine *lineptr;
+ char theChar;
+
+ /* Record the old position so we can come back to it */
+ for (startPos = textInfo->txtBuffer[textInfo->startLine]->lineText;
+ (startPos > 0) && (textInfo->mainBuffer[startPos] != '\n');
+ startPos--)
+ /* null loop body */;
+
+ /* Clear out the old line start array */
+ for (index = 0; index < textInfo->numLines; index++) {
+ InitLine(textInfo->txtBuffer[index]);
+ }
+
+ /* Initialize first line */
+ textInfo->txtBuffer[0]->lineHeight =
+ textInfo->theFonts[0].ascent + textInfo->theFonts[0].descent;
+ textInfo->txtBuffer[0]->lineText = 0;
+
+ /* Process the text back into lines */
+ endSize = textInfo->w - BARSIZE - WRAPINDSIZE;
+ bufptr = textInfo->mainBuffer;
+ lineptr = textInfo->txtBuffer[0];
+ linenum = 0;
+ fontptr = &(textInfo->theFonts[0]);
+ curfont = 0;
+ for (index = 0; index < textInfo->bufSpot; index++) {
+ theChar = bufptr[index] & CHARMASK;
+
+ if ((bufptr[index] & FONTMASK) != curfont) {
+ int newFontNum, heightDiff;
+
+ /* Switch fonts */
+ newFontNum = (bufptr[index] & FONTMASK) >> FONTSHIFT;
+ if (textInfo->theFonts[newFontNum].fid != 0) {
+ /* Valid font */
+ curfont = bufptr[index] & FONTMASK;
+ fontptr = &(textInfo->theFonts[newFontNum]);
+ heightDiff = (fontptr->ascent + fontptr->descent) -
+ lineptr->lineHeight;
+ if (heightDiff < 0) heightDiff = 0;
+ lineptr->lineHeight += heightDiff;
+ }
+ }
+ if (theChar == '\n') {
+ /* Handle new line */
+ if (linenum >= textInfo->allocLines-1)
+ /* Expand number of lines */
+ ExpandLines(textInfo);
+ linenum++;
+ lineptr = textInfo->txtBuffer[linenum];
+ /* Initialize next line */
+ lineptr->lineHeight = fontptr->ascent + fontptr->descent;
+ lineptr->lineText = index+1;
+ /* Check to see if its the starting line */
+ if (index == startPos) textInfo->startLine = linenum;
+ } else {
+ /* Handle normal character */
+ chsize = CharSize(textInfo, linenum, index);
+ if (lineptr->lineWidth + chsize > endSize) {
+ /* Handle line wrap */
+ lineptr->lineFlags |= WRAPFLAG;
+ if (linenum >= textInfo->allocLines-1)
+ /* Expand number of lines */
+ ExpandLines(textInfo);
+ linenum++;
+ lineptr = textInfo->txtBuffer[linenum];
+ /* Initialize next line */
+ lineptr->lineHeight = fontptr->ascent + fontptr->descent;
+ lineptr->lineText = index;
+ lineptr->lineLength = 1;
+ lineptr->lineWidth += chsize;
+ } else {
+ /* Handle normal addition of character */
+ lineptr->lineLength += 1;
+ lineptr->lineWidth += chsize;
+ }
+ }
+ }
+ /* We now have a valid line array. Let's clean up some other fields. */
+ textInfo->numLines = linenum+1;
+ if (startPos == 0) {
+ textInfo->startLine = 0;
+ }
+ textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace));
+ textInfo->curLine = linenum;
+ /* Check to see if we are at the bottom */
+ if (textInfo->endLine >= textInfo->numLines-1) {
+ textInfo->curY = textInfo->h - textInfo->bottomSpace -
+ lineptr->lineHeight;
+ textInfo->flagWord &= (~NOTATBOTTOM);
+ } else {
+ textInfo->flagWord |= NOTATBOTTOM;
+ }
+ return 1;
+}
+
+
+
+
+int TxtAddFont(display, textWin, fontNumber, newFont, newColor)
+Display *display;
+Window textWin; /* Scrollable text window */
+int fontNumber; /* Place to add font (0-7) */
+XFontStruct *newFont; /* Font to add */
+int newColor; /* Color of font */
+/*
+ * This routine loads a new font so that it can be used in a previously
+ * created text window. There are eight font slots numbered 0 through 7.
+ * If there is already a font in the specified slot, it will be replaced
+ * and an automatic redraw of the window will take place. See TxtWriteStr
+ * for details on using alternate fonts. The color specifies the foreground
+ * color of the text. The default foreground color is used if this
+ * parameter is TXT_NO_COLOR. Returns a non-zero value if
+ * everything went well.
+ */
+{
+ struct txtWin *textInfo;
+ int redrawFlag;
+ XGCValues gc_val;
+
+ if ((fontNumber < 0) || (fontNumber >= MAXFONTS)) return 0;
+ if ((textInfo = (struct txtWin *)
+ XLookUpAssoc(display, textWindows, (XID) textWin)) == 0)
+ return 0;
+ if (newColor == TXT_NO_COLOR) {
+ newColor = textInfo->fgPix;
+ }
+
+ gc_val.font = newFont->fid;
+ gc_val.foreground = newColor;
+ gc_val.background = textInfo->bgPix;
+ gc_val.plane_mask = AllPlanes;
+ gc_val.graphics_exposures = 1;
+ gc_val.function = GXcopy;
+
+ if (textInfo->fontGC[fontNumber] != 0)
+ {
+ XChangeGC(display, textInfo->fontGC[fontNumber],
+ GCFont | GCForeground, &gc_val);
+ }
+ else
+ textInfo->fontGC[fontNumber] = XCreateGC(display, textWin,
+ GCFont |
+ GCForeground |
+ GCBackground |
+ GCFunction |
+ GCPlaneMask |
+ GCGraphicsExposures,
+ &gc_val);
+
+
+ redrawFlag = (textInfo->theFonts[fontNumber].fid != 0) &&
+ (((newFont) && (newFont->fid != textInfo->theFonts[fontNumber].fid)) ||
+ (newColor != textInfo->theColors[fontNumber]));
+ if (newFont) {
+ textInfo->theFonts[fontNumber] = *newFont;
+ }
+ textInfo->theColors[fontNumber] = newColor;
+
+ if (redrawFlag) {
+ RecompBuffer(textInfo);
+ XClearWindow(display, textWin);
+ TxtRepaint(display, textWin);
+ }
+ return 1;
+}
+
+
+
+int TxtWinP(display, w)
+Display *display;
+Window w;
+/*
+ * Returns a non-zero value if the window has been previously grabbed
+ * using TxtGrab and 0 if it has not.
+ */
+{
+ if (XLookUpAssoc(display, textWindows, (XID) w))
+ return(1);
+ else return(0);
+}
+
+
+
+static int FindEndLine(textInfo, botSpace)
+struct txtWin *textInfo;
+int *botSpace;
+/*
+ * Given the starting line in 'textInfo->startLine', this routine
+ * determines the index of the last line that can be drawn given the
+ * current size of the screen. If there are not enough lines to
+ * fill the screen, the index of the last line will be returned.
+ * The amount of empty bottom space is returned in 'botSpace'.
+ */
+{
+ int index, height, lineHeight;
+
+ height = YPADDING;
+ index = textInfo->startLine;
+ while (index < textInfo->numLines) {
+ lineHeight = textInfo->txtBuffer[index]->lineHeight + INTERLINE;
+ if (height + lineHeight > textInfo->h) break;
+ height += lineHeight;
+ index++;
+ }
+ if (botSpace) {
+ *botSpace = textInfo->h - height;
+ }
+ return index - 1;
+}
+
+
+
+static int UpdateScroll(display, textInfo)
+Display *display;
+struct txtWin *textInfo; /* Text window information */
+/*
+ * This routine computes the current extent of the scroll bar
+ * indicator and repaints the bar with the correct information.
+ */
+{
+ int top, bottom;
+
+ if (textInfo->numLines > 1) {
+ top = textInfo->startLine * (textInfo->h - 2*BARBORDER) /
+ (textInfo->numLines - 1);
+ bottom = textInfo->endLine * (textInfo->h - 2*BARBORDER) /
+ (textInfo->numLines - 1);
+ } else {
+ top = 0;
+ bottom = textInfo->h - (2*BARBORDER);
+ }
+
+ /* Draw it - make sure there is a little padding */
+ if (top == 0) top++;
+ if (bottom == textInfo->h-(2*BARBORDER)) bottom--;
+
+ XFillRectangle(display, textInfo->scrollBar,
+ textInfo->bgGC,
+ 0, 0, BARSIZE, top-1);
+ XFillRectangle(display, textInfo->scrollBar,
+ DEFAULT_GC, top, BARSIZE - (2*BARBORDER) - 2,
+ bottom - top);
+ XFillRectangle(display, textInfo->scrollBar, DEFAULT_GC,
+ 0, bottom+1, BARSIZE,
+ textInfo->h - (2 * BARBORDER) - bottom);
+
+ return 1;
+}
+
+
+
+
+int TxtClear(display, w)
+Display *display;
+Window w;
+/*
+ * This routine clears a scrollable text window. It resets the current
+ * writing position to the upper left hand corner of the screen.
+ * NOTE: THIS ALSO CLEARS THE CONTENTS OF THE TEXT WINDOW BUFFER AND
+ * RESETS THE SCROLL BAR. Returns 0 if the window is not a text window.
+ * This should be used *instead* of XClear.
+ */
+{
+ struct txtWin *textInfo;
+ int index;
+
+ if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w)) == 0)
+ return 0;
+
+ /* Zero out the arrays */
+ textInfo->bufSpot = 0;
+ for (index = 0; index < textInfo->numLines; index++) {
+ InitLine(textInfo->txtBuffer[index]);
+ }
+ textInfo->txtBuffer[0]->lineHeight =
+ textInfo->theFonts[textInfo->curFont].ascent +
+ textInfo->theFonts[textInfo->curFont].descent;
+
+ textInfo->numLines = 1;
+ textInfo->startLine = 0;
+ textInfo->endLine = 0;
+ textInfo->curLine = 0;
+ textInfo->curX = 0;
+ textInfo->curY = YPADDING + textInfo->theFonts[textInfo->curFont].ascent
+ + textInfo->theFonts[textInfo->curFont].descent;
+
+ textInfo->bottomSpace = textInfo->h - YPADDING -
+ textInfo->theFonts[textInfo->curFont].ascent - INTERLINE -
+ textInfo->theFonts[textInfo->curFont].descent;
+ /* Actually clear the window */
+ XClearWindow(display, w);
+
+ /* Draw the current cursor */
+ XFillRectangle(display, w, textInfo->CursorGC,
+ XPADDING + CUROFFSET, textInfo->curY,
+ CURSORWIDTH,
+ textInfo->theFonts[textInfo->curFont].ascent +
+ textInfo->theFonts[textInfo->curFont].descent);
+
+ /* Update the scroll bar */
+ UpdateScroll(display, textInfo);
+ return 1;
+}
+
+
+static int WarpToBottom(display, textInfo)
+Display *display;
+struct txtWin *textInfo; /* Text Information */
+/*
+ * This routine causes the specified text window to display its
+ * last screen of information. It updates the scroll bar
+ * to the appropriate spot. The implementation scans backward
+ * through the buffer to find an appropriate starting spot for
+ * the window.
+ */
+{
+ int index, height, lineHeight;
+
+ index = textInfo->numLines-1;
+ height = 0;
+ while (index >= 0) {
+ lineHeight = textInfo->txtBuffer[index]->lineHeight + INTERLINE;
+ if (height + lineHeight > textInfo->h) break;
+ height += lineHeight;
+ index--;
+ }
+ textInfo->startLine = index + 1;
+ textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace));
+ textInfo->curY = textInfo->h - textInfo->bottomSpace -
+ textInfo->txtBuffer[textInfo->endLine]->lineHeight;
+ XClearWindow(display, textInfo->mainWindow);
+ TxtRepaint(display, textInfo->mainWindow);
+ return 1;
+}
+
+
+
+static int UpdateExposures(display, textInfo)
+Display *display;
+struct txtWin *textInfo; /* Text window information */
+/*
+ * Before a new scrolling action occurs, the text window package
+ * must handle all COPYEXPOSE events generated by the last scrolling
+ * action. This routine is called to do this. Foreign events (those
+ * not handled by TxtFilter) are queued up and replaced on the queue
+ * after the processing of the exposure events is complete.
+ */
+{
+#if 0
+ XEvent foreignQueue[MAXFOREIGN];
+ int index, lastItem = 0;
+
+ while (textInfo->flagWord & COPYEXPOSE) {
+ XNextEvent(display, &(foreignQueue[lastItem]));
+ if (!TxtFilter(display, &(foreignQueue[lastItem])))
+ lastItem++;
+ if (lastItem >= MAXFOREIGN) {
+ printf("Too many foreign events to queue!\n");
+ textInfo->flagWord &= (~COPYEXPOSE);
+ }
+ }
+ for (index = 0; index < lastItem; index++) {
+ XPutBackEvent(display, &(foreignQueue[index]));
+ }
+#endif
+ return 1;
+}
+
+
+static int ScrollDown(display,textInfo)
+Display *display;
+struct txtWin *textInfo; /* Text window information */
+/*
+ * This routine scrolls the indicated text window down by one
+ * line. The line below the current line must exist. The window
+ * is scrolled so that the line below the last line is fully
+ * displayed. This may cause many lines to scroll off the top.
+ * Scrolling is done using XCopyArea. The exposure events should
+ * be caught using ExposeCopy.
+ */
+{
+ int lineSum, index, targetSpace, freeSpace, updateFlag;
+
+ lineSum = 0;
+ if (textInfo->endLine + 1 >= textInfo->numLines) return 0;
+ targetSpace = textInfo->txtBuffer[textInfo->endLine+1]->lineHeight +
+ INTERLINE;
+ if (textInfo->bottomSpace < targetSpace) {
+ index = textInfo->startLine;
+ while (index < textInfo->endLine) {
+ lineSum += (textInfo->txtBuffer[index]->lineHeight + INTERLINE);
+ if (textInfo->bottomSpace + lineSum >= targetSpace) break;
+ index++;
+ }
+
+ /* Must move upward by 'lineSum' pixels */
+ XCopyArea(display, textInfo->mainWindow, textInfo->mainWindow,
+ DEFAULT_GC, 0, lineSum,
+ textInfo->w - BARSIZE, textInfo->h,
+ 0, 0);
+
+ textInfo->flagWord |= COPYEXPOSE;
+ /* Repair the damage to the structures */
+ textInfo->startLine = index + 1;
+ updateFlag = 1;
+ } else {
+ updateFlag = 0;
+ }
+ /* More lines might be able to fit. Let's check. */
+ freeSpace = textInfo->bottomSpace + lineSum - targetSpace;
+ index = textInfo->endLine + 1;
+ while (index < textInfo->numLines-1) {
+ if (freeSpace - textInfo->txtBuffer[index+1]->lineHeight - INTERLINE < 0)
+ break;
+ freeSpace -= (textInfo->txtBuffer[index+1]->lineHeight + INTERLINE);
+ index++;
+ }
+ textInfo->endLine = index;
+ textInfo->bottomSpace = freeSpace;
+ if (updateFlag) {
+ UpdateExposures(display, textInfo);
+ }
+ UpdateScroll(display, textInfo);
+ return 1;
+}
+
+
+
+
+static int ExpandLines(textInfo)
+struct txtWin *textInfo; /* Text Information */
+/*
+ * This routine allocates and initializes additional space in
+ * the line start array (txtBuffer). The new space
+ * is allocated using realloc. The expansion factor is a percentage
+ * given by EXPANDPERCENT.
+ */
+{
+ int newSize, index;
+
+ newSize = textInfo->allocLines;
+ newSize += (newSize * EXPANDPERCENT) / 100;
+
+ textInfo->txtBuffer = (struct txtLine **)
+ realloc((char *) textInfo->txtBuffer,
+ (unsigned) (newSize * sizeof(struct txtLine *)));
+ for (index = textInfo->allocLines; index < newSize; index++) {
+ textInfo->txtBuffer[index] = alloc(struct txtLine);
+ InitLine(textInfo->txtBuffer[index]);
+ }
+ textInfo->allocLines = newSize;
+ return 1;
+}
+
+static int ExpandBuffer(textInfo)
+struct txtWin *textInfo; /* Text information */
+/*
+ * Expands the basic character buffer using realloc. The expansion
+ * factor is a percentage given by EXPANDPERCENT.
+ */
+{
+ int newSize;
+
+ newSize = textInfo->bufAlloc + (textInfo->bufAlloc * EXPANDPERCENT) / 100;
+ textInfo->mainBuffer = (short *)
+ realloc((char *) textInfo->mainBuffer, (unsigned) newSize * sizeof(short));
+ textInfo->bufAlloc = newSize;
+ return 1;
+}
+
+
+
+static int HandleNewLine(display, textInfo, flagWord)
+Display *display;
+struct txtWin *textInfo; /* Text Information */
+int flagWord; /* DODISP or NONEWLINE or both */
+/*
+ * This routine initializes the next line for drawing by setting
+ * its height to the current font height, scrolls the screen down
+ * one line, and updates the current drawing position to the
+ * left edge of the newly cleared line. If DODISP is specified,
+ * the screen will be updated (otherwise not). If NONEWLINE is
+ * specified, no newline character will be added to the text buffer
+ * (this is for line wrap).
+ */
+{
+ struct txtLine *curLine, *nextLine;
+
+ /* Check to see if a new line must be allocated */
+ if (textInfo->curLine >= textInfo->allocLines-1)
+ /* Expand the number of lines */
+ ExpandLines(textInfo);
+ textInfo->numLines += 1;
+
+ /* Then we initialize the next line */
+ nextLine = textInfo->txtBuffer[textInfo->numLines-1];
+ nextLine->lineHeight =
+ textInfo->theFonts[textInfo->curFont].ascent +
+ textInfo->theFonts[textInfo->curFont].descent;
+
+ curLine = textInfo->txtBuffer[textInfo->curLine];
+ if (flagWord & DODISP) {
+ /* Scroll down a line if required */
+ if ((textInfo->curY + curLine->lineHeight +
+ nextLine->lineHeight + (INTERLINE * 2)) > textInfo->h)
+ {
+ ScrollDown(display, textInfo);
+ }
+ else
+ {
+ /* Update the bottom space appropriately */
+ textInfo->bottomSpace -= (nextLine->lineHeight + INTERLINE);
+ textInfo->endLine += 1;
+ }
+ /* Update drawing position */
+ textInfo->curY = textInfo->h -
+ (textInfo->bottomSpace + nextLine->lineHeight);
+ }
+
+ /* Move down a line */
+ textInfo->curLine += 1;
+ if (!(flagWord & NONEWLINE)) {
+ /* Append end-of-line to text buffer */
+ if (textInfo->bufSpot >= textInfo->bufAlloc) {
+ /* Allocate more space in main text buffer */
+ ExpandBuffer(textInfo);
+ }
+ textInfo->mainBuffer[(textInfo->bufSpot)++] =
+ (textInfo->curFont << FONTSHIFT) | '\n';
+ }
+ nextLine->lineText = textInfo->bufSpot;
+ textInfo->curX = 0;
+ return 1;
+}
+
+
+
+static int CharSize(textInfo, lineNum, charNum)
+struct txtWin *textInfo; /* Current Text Information */
+int lineNum; /* Line in buffer */
+int charNum; /* Character in line */
+/*
+ * This routine determines the size of the specified character.
+ * It takes in account the font of the character and whether its
+ * fixed or variable. The size includes INTERSPACE spacing between
+ * the characters.
+ */
+{
+ register XFontStruct *charFont;
+ register short *theLine;
+ register short theChar;
+
+ theLine = &(textInfo->mainBuffer[textInfo->txtBuffer[lineNum]->lineText]);
+ theChar = theLine[charNum] & CHARMASK;
+ charFont = &(textInfo->theFonts[(theChar & FONTMASK) >> FONTSHIFT]);
+ if (theChar <= charFont->min_char_or_byte2 ||
+ theChar >= charFont->max_char_or_byte2 ||
+ charFont->per_char == 0)
+ return charFont->max_bounds.width + 1;
+ else
+ return charFont->per_char[theChar].width + 1;
+}
+
+
+
+
+
+static int HandleBackspace(display, textInfo, flagWord)
+Display *display;
+struct txtWin *textInfo; /* Text Information */
+int flagWord; /* DODISP or nothing */
+/*
+ * This routine handles a backspace found in the input stream. The
+ * character before the current writing position will be erased and
+ * the drawing position will move back one character. If the writing
+ * position is at the left margin, the drawing position will move
+ * up to the previous line. If it is a line that has been wrapped,
+ * the character at the end of the previous line will be erased.
+ */
+{
+ struct txtLine *thisLine, *prevLine;
+ int chSize;
+
+ thisLine = textInfo->txtBuffer[textInfo->curLine];
+ /* First, determine whether we need to go back a line */
+ if (thisLine->lineLength == 0) {
+ /* Bleep if at top of buffer */
+ if (textInfo->curLine == 0) {
+ XBell(display, 50);
+ return 0;
+ }
+
+ /* See if we have to scroll in the other direction */
+ if ((flagWord & DODISP) && (textInfo->curY <= YPADDING)) {
+ /* This will display the last lines of the buffer */
+ WarpToBottom(display, textInfo);
+ }
+
+ /* Set drawing position at end of previous line */
+ textInfo->curLine -= 1;
+ prevLine = textInfo->txtBuffer[textInfo->curLine];
+ textInfo->numLines -= 1;
+ if (flagWord & DODISP) {
+ textInfo->curY -= (prevLine->lineHeight + INTERLINE);
+ textInfo->bottomSpace += (thisLine->lineHeight + INTERLINE);
+ textInfo->endLine -= 1;
+ }
+
+ /* We are unlinewrapping if the previous line has flag set */
+ if (prevLine->lineFlags & WRAPFLAG) {
+ /* Get rid of line wrap indicator */
+ if (flagWord & DODISP) {
+ XFillRectangle(display, textInfo->mainWindow,
+ textInfo->bgGC,
+ textInfo->w - BARSIZE - WRAPINDSIZE,
+ textInfo->curY, WRAPINDSIZE,
+ prevLine->lineHeight);
+ }
+ prevLine->lineFlags &= (~WRAPFLAG);
+ /* Call recursively to wipe out the ending character */
+ HandleBackspace(display, textInfo, flagWord);
+ } else {
+ /* Delete the end-of-line in the primary buffer */
+ textInfo->bufSpot -= 1;
+ }
+ } else {
+ /* Normal deletion of character */
+ chSize =
+ CharSize(textInfo, textInfo->curLine,
+ textInfo->txtBuffer[textInfo->curLine]->lineLength - 1);
+ /* Move back appropriate amount and wipe it out */
+ thisLine->lineWidth -= chSize;
+ if (flagWord & DODISP) {
+ XFillRectangle(display, textInfo->mainWindow,
+ textInfo->bgGC,
+ thisLine->lineWidth, textInfo->curY,
+ chSize, thisLine->lineHeight);
+ }
+ /* Delete from buffer */
+ textInfo->txtBuffer[textInfo->curLine]->lineLength -= 1;
+ textInfo->bufSpot -= 1;
+ }
+ return 1;
+}
+
+
+
+static int DrawLineWrap(display, win, x, y, h, col)
+Display *display;
+Window win; /* What window to draw it in */
+int x, y; /* Position of upper left corner */
+int h; /* Height of indicator */
+int col; /* Color of indicator */
+/*
+ * This routine draws a line wrap indicator at the end of a line.
+ * Visually, it is an arrow of the specified height directly against
+ * the scroll bar border. The bitmap used for the arrow is stored
+ * in 'arrowMap' with size 'arrow_width' and 'arrow_height'.
+ */
+{
+ struct txtWin *textInfo;
+
+ textInfo = (struct txtWin *)XLookUpAssoc(display, textWindows,
+ (XID) win);
+
+ /* First, draw the arrow */
+ XCopyArea(display, textInfo->arrowMap, textInfo->mainWindow,
+ textInfo->CursorGC,
+ 0, 0, arrow_width, arrow_height,
+ x, y + h - arrow_height, 1);
+
+ /* Then draw the stem */
+ XDrawLine(display, textInfo->mainWindow, textInfo->CursorGC,
+ x + STEMOFFSET, y,
+ x + STEMOFFSET, y + h - arrow_height);
+ return 1;
+}
+
+
+
+
+static int DrawLine(display, textInfo, lineIndex, ypos)
+Display *display;
+struct txtWin *textInfo; /* Text window information */
+int lineIndex; /* Index of line to draw */
+int ypos; /* Y position for line */
+/*
+ * This routine destructively draws the indicated line in the
+ * indicated window at the indicated position. It does not
+ * clear to end of line however. It draws a line wrap indicator
+ * if needed but does not draw a cursor.
+ */
+{
+ int index, startPos, curFont, theColor, curX, saveX, fontIndex;
+ struct txtLine *someLine;
+ char lineBuffer[BUFSIZE], *glyph;
+ short *linePointer;
+ XFontStruct *theFont;
+ XGCValues gc;
+
+ /* First, we draw the text */
+ index = 0;
+ curX = XPADDING;
+ someLine = textInfo->txtBuffer[lineIndex];
+ linePointer = &(textInfo->mainBuffer[someLine->lineText]);
+ while (index < someLine->lineLength) {
+ startPos = index;
+ saveX = curX;
+ curFont = linePointer[index] & FONTMASK;
+ fontIndex = curFont >> FONTSHIFT;
+ theFont = &(textInfo->theFonts[fontIndex]);
+ theColor = textInfo->theColors[fontIndex];
+ glyph = &(lineBuffer[0]);
+ while ((index < someLine->lineLength) &&
+ ((linePointer[index] & FONTMASK) == curFont))
+ {
+ *glyph = linePointer[index] & CHARMASK;
+ index++;
+ curX += CharSize(textInfo, lineIndex, index);
+ glyph++;
+ }
+
+ /* Flush out the glyphs */
+ XFillRectangle(display, textInfo->mainWindow,
+ textInfo->bgGC,
+ saveX, ypos,
+ textInfo->w - BARSIZE,
+ someLine->lineHeight + YPADDING + INTERLINE);
+
+ XDrawString(display, textInfo->mainWindow,
+ textInfo->fontGC[fontIndex],
+ saveX, ypos,
+ lineBuffer, someLine->lineLength);
+ }
+ /* Then the line wrap indicator (if needed) */
+ if (someLine->lineFlags & WRAPFLAG) {
+ DrawLineWrap(display, textInfo->mainWindow,
+ textInfo->w - BARSIZE - WRAPINDSIZE,
+ ypos, someLine->lineHeight,
+ textInfo->fgPix);
+ }
+ return 1;
+}
+
+
+
+
+static int HandleNewFont(display, fontNum, textInfo, flagWord)
+Display *display;
+int fontNum; /* Font number */
+struct txtWin *textInfo; /* Text information */
+int flagWord; /* DODISP or nothing */
+/*
+ * This routine handles a new font request. These requests take
+ * the form "^F<digit>". The parsing is done in TxtWriteStr.
+ * This routine is called only if the form is valid. It may return
+ * a failure (0 status) if the requested font is not loaded.
+ * If the new font is larger than any of the current
+ * fonts on the line, it will change the line height and redisplay
+ * the line.
+ */
+{
+ struct txtLine *thisLine;
+ int heightDiff, baseDiff, redrawFlag;
+
+ if (textInfo->theFonts[fontNum].fid == 0) {
+ return 0;
+ } else {
+ thisLine = textInfo->txtBuffer[textInfo->curLine];
+ textInfo->curFont = fontNum;
+ redrawFlag = 0;
+ heightDiff = textInfo->theFonts[fontNum].ascent +
+ textInfo->theFonts[fontNum].descent -
+ thisLine->lineHeight;
+
+ if (heightDiff > 0) {
+ redrawFlag = 1;
+ } else {
+ heightDiff = 0;
+ }
+
+ if (redrawFlag) {
+ if (flagWord & DODISP) {
+ /* Clear current line */
+ XFillRectangle(display, textInfo->mainWindow,
+ textInfo->bgGC,
+ 0, textInfo->curY, textInfo->w,
+ thisLine->lineHeight);
+
+ /* Check to see if it requires scrolling */
+ if ((textInfo->curY + thisLine->lineHeight + heightDiff +
+ INTERLINE) > textInfo->h)
+ {
+ /*
+ * General approach: "unscroll" the last line up
+ * and then call ScrollDown to do the right thing.
+ */
+ textInfo->endLine -= 1;
+ textInfo->bottomSpace += thisLine->lineHeight +
+ INTERLINE;
+
+ XFillRectangle(display, textInfo->mainWindow,
+ textInfo->bgGC,
+ 0, textInfo->h - textInfo->bottomSpace,
+ textInfo->w, textInfo->bottomSpace);
+
+ thisLine->lineHeight += heightDiff;
+ ScrollDown(display, textInfo);
+ textInfo->curY = textInfo->h -
+ (textInfo->bottomSpace + INTERLINE +
+ thisLine->lineHeight);
+ }
+ else
+ {
+ /* Just update bottom space */
+ textInfo->bottomSpace -= heightDiff;
+ thisLine->lineHeight += heightDiff;
+ }
+ /* Redraw the current line */
+ DrawLine(display, textInfo, textInfo->curLine, textInfo->curY);
+ } else {
+ /* Just update line height */
+ thisLine->lineHeight += heightDiff;
+ }
+ }
+ return 1;
+ }
+}
+
+
+
+int TxtWriteStr(display, w, str)
+Display *display;
+Window w; /* Text window */
+register char *str; /* 0 terminated string */
+/*
+ * This routine writes a string to the specified text window.
+ * The following notes apply:
+ * - Text is always appended to the end of the text buffer.
+ * - If the scroll bar is positioned such that the end of the
+ * text is not visible, an automatic scroll to the bottom
+ * will be done before the appending of text.
+ * - Non-printable ASCII characters are not displayed.
+ * - The '\n' character causes the current text position to
+ * advance one line and start at the left.
+ * - Tabs are not supported.
+ * - Lines too long for the screen will be wrapped and a line wrap
+ * indication will be drawn.
+ * - Backspace clears the previous character. It will do the right
+ * thing if asked to backspace past a wrapped line.
+ * - A new font can be chosen using the sequence '^F<digit>' where
+ * <digit> is 0-7. The directive will be ignored if
+ * there is no font in the specified slot.
+ * Returns 0 if something went wrong.
+ */
+{
+ register int fontIndex;
+ register struct txtWin *textInfo;
+ register struct txtLine *thisLine;
+
+ if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w)) == 0)
+ return 0;
+
+ /* See if screen needs to be updated */
+ if (textInfo->flagWord & SCREENWRONG) {
+ TxtRepaint(display, textInfo->mainWindow);
+ }
+
+ /* See if we have to scroll down to the bottom */
+ if (textInfo->flagWord & NOTATBOTTOM) {
+ WarpToBottom(display, textInfo);
+ textInfo->flagWord &= (~NOTATBOTTOM);
+ }
+
+ /* Undraw the current cursor */
+ thisLine = textInfo->txtBuffer[textInfo->curLine];
+
+ XFillRectangle(display, w, textInfo->bgGC,
+ thisLine->lineWidth + CUROFFSET,
+ textInfo->curY,
+ CURSORWIDTH,
+ thisLine->lineHeight);
+
+ for ( /* str is ok */ ; (*str != 0) ; str++) {
+ /* Check to see if we are waiting on a font */
+ if (textInfo->flagWord & FONTNUMWAIT) {
+ textInfo->flagWord &= (~FONTNUMWAIT);
+ fontIndex = *str - '0';
+ if ((fontIndex >= 0) && (fontIndex < MAXFONTS)) {
+ /* Handle font -- go get next character */
+ if (HandleNewFont(display, fontIndex, textInfo, DODISP))
+ continue;
+ }
+ }
+
+ /* Inline code for handling normal character case */
+ if ((*str >= LOWCHAR) && (*str <= HIGHCHAR)) {
+ register XFontStruct *thisFont;
+ register struct txtLine *thisLine;
+ register int charWidth;
+ int thisColor;
+
+ /* Determine size of character */
+ thisFont = &(textInfo->theFonts[textInfo->curFont]);
+ thisColor = textInfo->theColors[textInfo->curFont];
+ if (*str <= thisFont->min_char_or_byte2 ||
+ *str >= thisFont->max_char_or_byte2 ||
+ thisFont->per_char == 0)
+ charWidth = thisFont->max_bounds.width + 1;
+ else
+ charWidth = thisFont->per_char[*str].width + 1;
+
+ /* Check to see if line wrap is required */
+ thisLine = textInfo->txtBuffer[textInfo->curLine];
+ if (thisLine->lineWidth + charWidth >
+ (textInfo->w-BARSIZE-WRAPINDSIZE))
+ {
+ DrawLineWrap(display, textInfo->mainWindow,
+ textInfo->w-BARSIZE-WRAPINDSIZE,
+ textInfo->curY, thisLine->lineHeight,
+ textInfo->fgPix);
+ thisLine->lineFlags |= WRAPFLAG;
+ /* Handle the spacing problem the same way as a newline */
+ HandleNewLine(display, textInfo, DODISP | NONEWLINE);
+ thisLine = textInfo->txtBuffer[textInfo->curLine];
+ }
+
+ /* Ready to draw character */
+ XDrawString(display, textInfo->mainWindow,
+ DEFAULT_GC,
+ textInfo->curX += charWidth,
+ textInfo->curY + thisLine->lineHeight,
+ str, 1);
+
+ /* Append character onto main buffer */
+ if (textInfo->bufSpot >= textInfo->bufAlloc)
+ /* Make room for more characters */
+ ExpandBuffer(textInfo);
+ textInfo->mainBuffer[(textInfo->bufSpot)++] =
+ (textInfo->curFont << FONTSHIFT) | (*str);
+
+ /* Update the line start array */
+ thisLine->lineLength += 1;
+ thisLine->lineWidth += charWidth;
+ } else if (*str == NEWLINE) {
+ HandleNewLine(display, textInfo, DODISP);
+ } else if (*str == NEWFONT) {
+ /* Go into waiting for font number mode */
+ textInfo->flagWord |= FONTNUMWAIT;
+ } else if (*str == BACKSPACE) {
+ HandleBackspace(display, textInfo, DODISP);
+ } else {
+ /* Ignore all others */
+ }
+ }
+ /* Draw the cursor in its new position */
+ thisLine = textInfo->txtBuffer[textInfo->curLine];
+
+ XFillRectangle(display, w, textInfo->CursorGC,
+ thisLine->lineWidth + CUROFFSET,
+ textInfo->curY /* + thisLine->lineHeight */,
+ CURSORWIDTH, thisLine->lineHeight);
+
+ return 1;
+}
+
+
+
+int TxtJamStr(display, w, str)
+Display *display;
+Window w; /* Text window */
+register char *str; /* NULL terminated string */
+/*
+ * This is the same as TxtWriteStr except the screen is NOT updated.
+ * After a call to this routine, TxtRepaint should be called to
+ * update the screen. This routine is meant to be used to load
+ * a text buffer with information and then allow the user to
+ * scroll through it at will.
+ */
+{
+ register int fontIndex;
+ register struct txtWin *textInfo;
+
+ if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w)
+ ) == 0)
+ return 0;
+
+ for ( /* str is ok */ ; (*str != 0) ; str++) {
+ /* Check to see if we are waiting on a font */
+ if (textInfo->flagWord & FONTNUMWAIT) {
+ textInfo->flagWord &= (~FONTNUMWAIT);
+ fontIndex = *str - '0';
+ if ((fontIndex >= 0) && (fontIndex < MAXFONTS)) {
+ if (HandleNewFont(display, fontIndex, textInfo, 0)) {
+ /* Handled font -- go get next character */
+ continue;
+ }
+ }
+ }
+ /* Inline code for handling normal character case */
+ if ((*str >= LOWCHAR) && (*str <= HIGHCHAR)) {
+ register XFontStruct *thisFont;
+ register struct txtLine *thisLine;
+ register int charWidth;
+
+ /* Determine size of character */
+ thisFont = &(textInfo->theFonts[textInfo->curFont]);
+
+ if (*str <= thisFont->min_char_or_byte2 ||
+ *str >= thisFont->max_char_or_byte2 ||
+ thisFont->per_char == 0)
+ charWidth = thisFont->max_bounds.width + 1;
+ else
+ charWidth = thisFont->per_char[*str].width + 1;
+
+ /* Check to see if line wrap is required */
+ thisLine = textInfo->txtBuffer[textInfo->curLine];
+ if (thisLine->lineWidth + charWidth >
+ (textInfo->w-BARSIZE-WRAPINDSIZE))
+ {
+ thisLine->lineFlags |= WRAPFLAG;
+ /* Handle the spacing problem the same way as a newline */
+ HandleNewLine(display, textInfo, NONEWLINE);
+ thisLine = textInfo->txtBuffer[textInfo->curLine];
+ }
+ /* Append character onto main buffer */
+ if (textInfo->bufSpot >= textInfo->bufAlloc)
+ /* Make room for more characters */
+ ExpandBuffer(textInfo);
+ textInfo->mainBuffer[(textInfo->bufSpot)++] =
+ (textInfo->curFont << FONTSHIFT) | (*str);
+
+ /* Update the line start array */
+ thisLine->lineLength += 1;
+ thisLine->lineWidth += charWidth;
+ } else if (*str == NEWLINE) {
+ HandleNewLine(display, textInfo, 0);
+ } else if (*str == NEWFONT) {
+ /* Go into waiting for font number mode */
+ textInfo->flagWord |= FONTNUMWAIT;
+ } else if (*str == BACKSPACE) {
+ HandleBackspace(display, textInfo, 0);
+ } else {
+ /* Ignore all others */
+ }
+ }
+ textInfo->flagWord |= SCREENWRONG;
+ return 1;
+}
+
+
+
+int TxtRepaint(display,w)
+Display *display;
+Window w;
+/*
+ * Repaints the given scrollable text window. The routine repaints
+ * the entire window. For handling exposure events, the TxtFilter
+ * routine should be used.
+ */
+{
+ struct txtWin *textInfo;
+ int index, ypos;
+
+ if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w)
+ ) == 0)
+ return 0;
+
+ /* Check to see if the screen is up to date */
+ if (textInfo->flagWord & SCREENWRONG) {
+ textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace));
+ textInfo->flagWord &= (~SCREENWRONG);
+ }
+
+ ypos = YPADDING;
+ index = textInfo->startLine;
+ for (;;) {
+ DrawLine(display, textInfo, index, ypos);
+ if (index >= textInfo->endLine) break;
+ ypos += (textInfo->txtBuffer[index]->lineHeight + INTERLINE);
+ index++;
+ }
+ /* Draw the cursor (if on screen) */
+ if (textInfo->endLine == textInfo->curLine) {
+ XFillRectangle(display, w, textInfo->CursorGC,
+ textInfo->txtBuffer[index]->lineWidth + CUROFFSET,
+ ypos /* + textInfo->txtBuffer[index]->lineHeight */,
+ CURSORWIDTH, textInfo->txtBuffer[index]->lineHeight);
+
+ }
+ /* Update the scroll bar */
+ UpdateScroll(display, textInfo);
+ return 1;
+}
+
+
+
+static int InsertIndex(textInfo, thisIndex, ypos)
+struct txtWin *textInfo; /* Text Window Information */
+int thisIndex; /* Line index of exposed line */
+int ypos; /* Drawing position of line */
+/*
+ * This routine inserts the supplied line index into the copy
+ * exposure array for 'textInfo'. The array is kept sorted
+ * from lowest to highest using insertion sort. The array
+ * is dynamically expanded if needed.
+ */
+{
+ struct expEvent *newItem;
+ int newSize, index, downIndex;
+
+ /* Check to see if we need to expand it */
+ if ((textInfo->exposeSize + 3) >= textInfo->exposeAlloc) {
+ newSize = textInfo->exposeAlloc +
+ (textInfo->exposeAlloc * EXPANDPERCENT / 100);
+ textInfo->exposeAry = (struct expEvent **)
+ realloc((char *) textInfo->exposeAry,
+ (unsigned) (newSize * sizeof(struct expEvent *)));
+ for (index = textInfo->exposeAlloc; index < newSize; index++)
+ textInfo->exposeAry[index] = alloc(struct expEvent);
+ textInfo->exposeAlloc = newSize;
+ }
+ /* Find spot for insertion. NOTE: last spot has big number */
+ for (index = 0; index <= textInfo->exposeSize; index++) {
+ if (textInfo->exposeAry[index]->lineIndex >= thisIndex) {
+ if (textInfo->exposeAry[index]->lineIndex > thisIndex) {
+ /* Insert before this entry */
+ newItem = textInfo->exposeAry[textInfo->exposeSize+1];
+ for (downIndex = textInfo->exposeSize;
+ downIndex >= index;
+ downIndex--)
+ {
+ textInfo->exposeAry[downIndex+1] =
+ textInfo->exposeAry[downIndex];
+ }
+ /* Put a free structure at this spot */
+ textInfo->exposeAry[index] = newItem;
+ /* Fill it in */
+ textInfo->exposeAry[index]->lineIndex = thisIndex;
+ textInfo->exposeAry[index]->ypos = ypos;
+ /* Break out of loop */
+ textInfo->exposeSize += 1;
+ }
+ break;
+ }
+ }
+ return 1;
+}
+
+
+
+static int ScrollUp(display, textInfo)
+Display *display;
+struct txtWin *textInfo; /* Text window information */
+/*
+ * This routine scrolls the indicated text window up by one
+ * line. The line above the current line must exist. The
+ * window is scrolled so that the line above the start line
+ * is displayed at the top of the screen. This may cause
+ * many lines to scroll off the bottom. The scrolling is
+ * done using XCopyArea. The exposure events should be caught
+ * by ExposeCopy.
+ */
+{
+ int targetSpace;
+
+ /* Make sure all exposures have been handled by now */
+ if (textInfo->startLine == 0) return 0;
+ targetSpace = textInfo->txtBuffer[textInfo->startLine-1]->lineHeight +
+ INTERLINE;
+ /* Move the area downward by the target amount */
+ XCopyArea(display, textInfo->mainWindow, textInfo->mainWindow,
+ DEFAULT_GC,
+ 0, YPADDING, textInfo->w - BARSIZE,
+ textInfo->h, 0, targetSpace);
+
+ textInfo->flagWord |= COPYEXPOSE;
+ /* Update the text window parameters */
+ textInfo->startLine -= 1;
+ textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace));
+
+ /* Clear out bottom space region */
+ XClearArea(display, textInfo->mainWindow,
+ 0, textInfo->h - textInfo->bottomSpace,
+ textInfo->w, textInfo->bottomSpace);
+
+ UpdateExposures(display, textInfo);
+ UpdateScroll(display, textInfo);
+
+ return 1;
+}
+
+
+static int ScrollToSpot(display, textInfo, ySpot)
+Display *display;
+struct txtWin *textInfo; /* Text window information */
+int ySpot; /* Button position in scroll window */
+/*
+ * This routine scrolls the specified text window relative to the
+ * position of the mouse in the scroll bar. The center of the screen
+ * will be positioned to correspond to the mouse position.
+ */
+{
+ int targetLine, aboveLines;
+
+ targetLine = textInfo->numLines * ySpot / textInfo->h;
+ textInfo->startLine = targetLine;
+ textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace));
+ aboveLines = 0;
+ /* Make the target line the *center* of the window */
+ while ((textInfo->startLine > 0) &&
+ (aboveLines < textInfo->endLine - targetLine))
+ {
+ textInfo->startLine -= 1;
+ textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace));
+ aboveLines++;
+ }
+ if (textInfo->endLine == textInfo->numLines-1) {
+ WarpToBottom(display, textInfo);
+ } else {
+ XClearWindow(display, textInfo->mainWindow);
+ TxtRepaint(display, textInfo->mainWindow);
+ }
+ return 1;
+}
+
+
+
+static int LineToTop(display, textInfo, pos)
+Display *display;
+struct txtWin *textInfo; /* Text window information */
+int pos; /* Y position of mouse */
+/*
+ * This routine scrolls the screen down until the line at the
+ * mouse position is at the top of the screen. It stops
+ * if it can't scroll the buffer down that far. If the
+ * global 'ScrollOption' is NORMSCROLL, a smooth scroll
+ * is used. Otherwise, it jumps to the right position
+ * and repaints the screen.
+ */
+{
+ int index, sum;
+
+ /* First, we find the current line */
+ sum = 0;
+ for (index = textInfo->startLine; index <= textInfo->endLine; index++) {
+ if (sum + textInfo->txtBuffer[index]->lineHeight + INTERLINE> pos) break;
+ sum += textInfo->txtBuffer[index]->lineHeight + INTERLINE;
+ }
+ /* We always want to scroll down at least one line */
+ if (index == textInfo->startLine) index++;
+ if (ScrollOption == NORMSCROLL) {
+ /* Scroll down until 'index' is the starting line */
+ while ((textInfo->startLine < index) && ScrollDown(display, textInfo))
+ {
+ /* Empty Loop Body */
+ }
+ } else {
+ /* Immediately jump to correct spot */
+ textInfo->startLine = index;
+ textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace));
+ if (textInfo->endLine == textInfo->numLines-1) {
+ WarpToBottom(display, textInfo);
+ } else {
+ XClearWindow(display, textInfo->mainWindow);
+ TxtRepaint(display, textInfo->mainWindow);
+ }
+ }
+ /* Check to see if at end of buffer */
+ if (textInfo->endLine >= textInfo->numLines-1) {
+ textInfo->flagWord &= (~NOTATBOTTOM);
+ }
+ return 1;
+}
+
+
+
+static int TopToHere(display, textInfo, pos)
+Display *display;
+struct txtWin *textInfo; /* Text window information */
+int pos; /* Y position of mouse */
+/*
+ * This routine scrolls the screen up until the top line of
+ * the screen is at the current Y position of the mouse. Again,
+ * it will stop if it can't scroll that far. If the global
+ * 'ScrollOption' is NORMSCROLL, a smooth scroll is used.
+ * If it's not, it will simply redraw the screen at the
+ * correct spot.
+ */
+{
+ int sum, target, linesup, index;
+
+ target = pos - textInfo->txtBuffer[textInfo->startLine]->lineHeight;
+ /* We always want to scroll up at least one line */
+ if (target <= 0) target = 1;
+ sum = 0;
+ linesup = 0;
+ /* Check to see if we are at the top anyway */
+ if (textInfo->startLine == 0) return 0;
+ if (ScrollOption == NORMSCROLL) {
+ /* Scroll up until sum of new top lines greater than target */
+ while ((sum < target) && ScrollUp(display, textInfo)) {
+ sum += textInfo->txtBuffer[textInfo->startLine]->lineHeight;
+ linesup++;
+ }
+ } else {
+ /* Search backward to find index */
+ index = textInfo->startLine - 1;
+ while ((index > 0) && (sum < target)) {
+ sum += textInfo->txtBuffer[index]->lineHeight;
+ linesup++;
+ index--;
+ }
+ /* Go directly to the index */
+ textInfo->startLine = index;
+ textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace));
+ XClearWindow(display, textInfo->mainWindow);
+ TxtRepaint(display, textInfo->mainWindow);
+ }
+ /* If we scrolled, assert we are not at bottom of buffer */
+ if (linesup > 0) {
+ textInfo->flagWord |= NOTATBOTTOM;
+ }
+ return 1;
+}
+
+
+
+int TxtFilter(display, evt)
+Display *display;
+XEvent *evt;
+/*
+ * This routine handles events associated with scrollable text windows.
+ * It will handle all exposure events and any button released events
+ * in the scroll bar of a text window. It does NOT handle any other
+ * events. If it cannot handle the event, it will return 0.
+ */
+{
+ XExposeEvent *expose = &evt->xexpose;
+ XButtonEvent *btEvt = &evt->xbutton;
+ XGraphicsExposeEvent *gexpose = &evt->xgraphicsexpose;
+ XNoExposeEvent *noexpose = &evt->xnoexpose;
+ struct txtWin *textInfo;
+ int index, ypos;
+ Window w, sw;
+
+ if (textWindows == (XAssocTable *) 0) {
+ textWindows = XCreateAssocTable(32);
+ if (textWindows == (XAssocTable *) 0) return(0);
+ }
+ if (evt->type == Expose) {
+ w = expose->window;
+ sw = 0;
+ }
+ else if (evt->type == GraphicsExpose) {
+ w = gexpose->drawable;
+ sw = 0;
+ }
+ else if (evt->type == NoExpose) {
+ w = noexpose->drawable;
+ sw = 0;
+ }
+ else if (evt->type == ButtonRelease) {
+ w = btEvt->window;
+ sw = btEvt->subwindow;
+ }
+ else
+ return 0;
+
+ if ((textInfo = (struct txtWin *)
+ XLookUpAssoc(display, textWindows, (XID) w)) == 0)
+ return 0;
+
+ /* Determine whether it's main window or not */
+ if ((w == textInfo->mainWindow) && (sw == 0)) {
+ /* Main Window - handle exposures */
+ switch (evt->type) {
+ case Expose:
+ ypos = 0 /*YPADDING*/;
+ for (index = textInfo->startLine;
+ index <= textInfo->endLine;
+ index++)
+ {
+ int lh = textInfo->txtBuffer[index]->lineHeight;
+
+ if (((ypos + lh) >= expose->y) &&
+ (ypos <= (expose->y + expose->height)))
+ {
+ /* Intersection region */
+ /* Draw line immediately */
+ DrawLine(display, textInfo, index, ypos);
+ /* And possibly draw cursor */
+ if (textInfo->curLine == index) {
+ XFillRectangle(display, w, textInfo->CursorGC,
+ textInfo->txtBuffer[index]->lineWidth +
+ CUROFFSET,
+ ypos,
+ CURSORWIDTH,
+ lh);
+ }
+ }
+ ypos += lh + INTERLINE;
+ }
+ break;
+ case GraphicsExpose:
+ ypos = 0 /*YPADDING*/;
+ for (index = textInfo->startLine;
+ index <= textInfo->endLine;
+ index++)
+ {
+ int lh = textInfo->txtBuffer[index]->lineHeight;
+
+ if (((ypos + lh) >= gexpose->y) &&
+ (ypos <= (gexpose->y + gexpose->height)))
+ {
+ /* Intersection region */
+ /* Draw line immediately */
+ DrawLine(display, textInfo, index, ypos);
+ /* And possibly draw cursor */
+ if (textInfo->curLine == index) {
+ XFillRectangle(display, w, textInfo->CursorGC,
+ textInfo->txtBuffer[index]->lineWidth +
+ CUROFFSET,
+ ypos,
+ CURSORWIDTH,
+ lh);
+ }
+ }
+ ypos += lh + INTERLINE;
+ }
+ break;
+ case NoExpose:
+ break;
+ default:
+ /* Not one of our events */
+ return 0;
+ }
+ } else {
+ switch (evt->type) {
+ case Expose:
+ UpdateScroll(display, textInfo);
+ break;
+ case ButtonRelease:
+ /* Find out which button */
+ switch (btEvt->button) {
+ case Button1:
+ /* Scroll up until top line is at mouse position */
+ TopToHere(display, textInfo, btEvt->y);
+ break;
+ case Button2:
+ /* Scroll to spot relative to position */
+ ScrollToSpot(display, textInfo, btEvt->y);
+ if (textInfo->endLine >= textInfo->numLines-1) {
+ textInfo->flagWord &= (~NOTATBOTTOM);
+ } else {
+ textInfo->flagWord |= NOTATBOTTOM;
+ }
+ break;
+ case Button3:
+ /* Scroll down until pointed line is at top */
+ LineToTop(display, textInfo, btEvt->y);
+ break;
+ }
+ break;
+ default:
+ /* Not one of our events */
+ return 0;
+ }
+ }
+ return 1;
+}
diff --git a/gnu/games/chess/Xchess/scrollText/scrollText.h b/gnu/games/chess/Xchess/scrollText/scrollText.h
new file mode 100644
index 000000000000..d9d05b08dc0b
--- /dev/null
+++ b/gnu/games/chess/Xchess/scrollText/scrollText.h
@@ -0,0 +1,32 @@
+/*
+ * Scrollable Text Window Header File
+ *
+ * David Harrison
+ * University of California, Berkeley
+ * 1986
+ *
+ * This file contains definitions for a scrollable text window
+ * with scroll bar support.
+ */
+
+int TxtGrab();
+ /* Take hold of a previously created window */
+
+#define TXT_NO_COLOR -1
+
+int TxtAddFont();
+ /* Loads a new font for use later */
+int TxtWinP();
+ /* Returns non-zero value if the window is text window */
+int TxtClear();
+ /* Clears text window and resets text buffer */
+
+int TxtWriteStr();
+ /* Writes a string to window with immediate update */
+int TxtJamStr();
+ /* Write a string without causing update to screen */
+
+int TxtRepaint();
+ /* Repaints entire scrollable text window */
+int TxtFilter();
+ /* Handles events related to text window */
diff --git a/gnu/games/chess/Xchess/shade.bitmap b/gnu/games/chess/Xchess/shade.bitmap
new file mode 100644
index 000000000000..a32ac80611ce
--- /dev/null
+++ b/gnu/games/chess/Xchess/shade.bitmap
@@ -0,0 +1,71 @@
+
+#define shade_width 80
+#define shade_height 80
+static char shade_bits[] = {
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88};
diff --git a/gnu/games/chess/Xchess/std.c b/gnu/games/chess/Xchess/std.c
new file mode 100644
index 000000000000..c839b912314a
--- /dev/null
+++ b/gnu/games/chess/Xchess/std.c
@@ -0,0 +1,425 @@
+
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.1 $ on $Date: 86/11/01 17:08:40 $
+ * $Source: /users/faustus/xchess/RCS/std.c,v $
+ * Copyright (c) 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
+ *
+ * Utility routines.
+ */
+
+#include "std.h"
+
+#ifndef IBMPC
+#include <sys/types.h>
+#endif not IBMPC
+#ifdef UNIX
+#include <signal.h>
+#include <pwd.h>
+#endif UNIX
+#ifdef BSD
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif BSD
+
+extern char **environ;
+
+bool
+prefix(p, s)
+ register char *p, *s;
+{
+ while (*p && (*p == *s))
+ p++, s++;
+ if (!*p)
+ return (true);
+ else
+ return (false);
+}
+
+/* Create a copy of a string. */
+
+char *
+copy(str)
+ char *str;
+{
+ char *p, *tmalloc();
+
+ p = tmalloc(strlen(str) + 1);
+ strcpy(p, str);
+ return(p);
+}
+
+/* Determine whether sub is a substring of str. */
+
+bool
+substring(sub, str)
+ register char *str, *sub;
+{
+ register char *s;
+
+ while(*str) {
+ if(*str == *sub) {
+ for(s = sub; *s; s++)
+ if(*s != *str++)
+ break;
+ if(*s == '\0')
+ return (true);
+ }
+ str++;
+ }
+ return (false);
+}
+
+/* Malloc num bytes and initialize to zero. Fatal error if the space can't
+ * be malloc'd.
+ */
+
+char *
+tmalloc(num)
+ register int num;
+{
+ register char *s;
+ char *malloc();
+
+ s = malloc((unsigned) num);
+ if (!s) {
+ fatal("malloc: can't allocate %d bytes", num);
+ }
+ bzero(s, num);
+ return(s);
+}
+
+char *
+trealloc(ptr, num)
+ char *ptr;
+ int num;
+{
+ register char *s;
+ char *realloc();
+
+ s = realloc(ptr, (unsigned) num);
+ if (!s) {
+ fatal("realloc: can't allocate %d bytes", num);
+ }
+ /* Well, this won't be zeroed... Too bad... */
+ return(s);
+}
+
+/* Append one character to a string. Don't check for overflow. */
+
+void
+appendc(s, c)
+ char *s, c;
+{
+ while (*s)
+ s++;
+ *s++ = c;
+ *s = '\0';
+ return;
+}
+
+int
+scannum(str)
+ char *str;
+{
+ int i = 0;
+
+ while(isdigit(*str))
+ i = i * 10 + *(str++) - '0';
+ return(i);
+}
+
+/* Case insensitive prefix. */
+
+bool
+ciprefix(p, s)
+ register char *p, *s;
+{
+ while (*p) {
+ if ((isupper(*p) ? tolower(*p) : *p) !=
+ (isupper(*s) ? tolower(*s) : *s))
+ return(false);
+ p++;
+ s++;
+ }
+ return (true);
+}
+
+/* Case insensitive strcmp... */
+
+bool
+cieq(p, s)
+ register char *p, *s;
+{
+ while (*p) {
+ if ((isupper(*p) ? tolower(*p) : *p) !=
+ (isupper(*s) ? tolower(*s) : *s))
+ return(false);
+ p++;
+ s++;
+ }
+ return (!*s);
+}
+
+#ifdef BSD
+
+/* Return the date. Return value is static data. */
+
+char *
+datestring()
+{
+ register char *tzn;
+ struct tm *tp;
+ static char tbuf[40];
+ char *ap;
+ struct timeval tv;
+ struct timezone tz;
+ char *timezone(), *asctime();
+ int i;
+ struct tm *localtime();
+
+ (void) gettimeofday(&tv, &tz);
+ tp = localtime((time_t *) &tv.tv_sec);
+ ap = asctime(tp);
+ tzn = timezone(tz.tz_minuteswest, tp->tm_isdst);
+ sprintf(tbuf, "%.20s", ap);
+ if (tzn)
+ strcat(tbuf, tzn);
+ strcat(tbuf, ap + 19);
+ i = strlen(tbuf);
+ tbuf[i - 1] = '\0';
+ return (tbuf);
+}
+
+#else BSD
+
+/* Give it a try... */
+
+char *
+datestring()
+{
+ long i;
+ static char buf[64];
+
+ i = time(0);
+ strcpy(buf, ctime(&i));
+ buf[strlen(buf) - 1] = '\0'; /* Kill the nl. */
+ return (buf);
+}
+
+#endif
+
+/* How many seconds have elapsed in running time. */
+
+int
+seconds()
+{
+#ifdef BSD
+ struct rusage ruse;
+
+ getrusage(RUSAGE_SELF, &ruse);
+ return (ruse.ru_utime.tv_sec);
+#else BSD
+#endif BSD
+}
+
+/* A few things that may not exist on non-unix systems. */
+
+#ifndef BSD
+
+#ifndef index
+
+char *
+index(s, c)
+ register char *s;
+ register char c;
+{
+ while ((*s != c) && (*s != '\0'))
+ s++;
+ if (*s == '\0')
+ return ((char *) 0);
+ else
+ return (s);
+}
+
+#endif not index
+
+#ifndef rindex
+
+char *
+rindex(s, c)
+ register char *s;
+ register char c;
+{
+ register char *t;
+
+ for (t = s; *t != '\0'; t++);
+ while ((*t != c) && (t != s))
+ t--;
+ if (t == s)
+ return ((char *) 0);
+ else
+ return (t);
+}
+
+#endif not rindex
+
+#ifndef bcopy
+
+void
+bcopy(from, to, num)
+ register char *from, *to;
+ register int num;
+{
+ while (num-- > 0)
+ *to++ = *from++;
+ return;
+}
+
+#endif not bcopy
+
+#ifndef bzero
+
+void
+bzero(ptr, num)
+ register char *ptr;
+ register int num;
+{
+ while (num-- > 0)
+ *ptr++ = '\0';
+ return;
+}
+
+#endif not bzero
+
+/* This might not be around... If not then forget about sorting... */
+
+void qsort() {}
+
+#endif BSD
+
+char *
+gettok(s)
+ char **s;
+{
+ char buf[BSIZE];
+ int i = 0;
+
+ while (isspace(**s))
+ (*s)++;
+ if (!**s)
+ return (NULL);
+ while (**s && !isspace(**s))
+ buf[i++] = *(*s)++;
+ buf[i] = '\0';
+ while (isspace(**s))
+ (*s)++;
+ return (copy(buf));
+}
+
+/* Die horribly. */
+
+/* VARARGS1 */
+void
+fatal(s, args)
+ char *s;
+{
+ fputs("Internal Error: ", stderr);
+ _doprnt(s, &args, stderr);
+ putc('\n', stderr);
+
+ kill(getpid(), SIGIOT);
+ /* NOTREACHED */
+}
+
+void
+setenv(name, value)
+ char *name, *value;
+{
+ int i;
+ char **xx, *s;
+
+ s = tmalloc(strlen(name) + 2);
+ sprintf(s, "%s=", name);
+
+ /* Copy the old environment... */
+ for (i = 0; environ[i]; i++)
+ if (prefix(s, environ[i]))
+ break;
+ if (!environ[i]) {
+ xx = (char **) tmalloc((i + 2) * sizeof (char *));
+ for (i = 0; environ[i]; i++)
+ xx[i] = environ[i];
+ xx[i + 1] = NULL;
+ environ = xx;
+ } else
+ xx = environ;
+
+ xx[i] = tmalloc(strlen(name) + strlen(value) + 2);
+ sprintf(xx[i], "%s=%s", name, value);
+ return;
+}
+
+char *
+getusername()
+{
+ int i = getuid();
+ struct passwd *pw = getpwuid(i);
+
+ return (pw ? pw->pw_name : NULL);
+}
+
+char *
+gethome()
+{
+ int i = getuid();
+ struct passwd *pw = getpwuid(i);
+
+ return (pw ? pw->pw_dir : "/strange");
+}
+
+char *
+tildexpand(s)
+ char *s;
+{
+ struct passwd *pw;
+ char *n, buf[64];
+ int i;
+
+ if (*s != '~')
+ return (copy(s));
+
+ for (s++, i = 0; *s != '/'; s++, i++)
+ buf[i] = *s;
+ buf[i] = '\0';
+ if (!i)
+ pw = getpwuid(getuid());
+ else
+ pw = getpwnam(buf);
+ if (!pw)
+ return (s);
+ n = tmalloc(strlen(s) + strlen(pw->pw_dir) + 1);
+ strcpy(n, pw->pw_dir);
+ strcat(n, s);
+ return (n);
+}
+
diff --git a/gnu/games/chess/Xchess/std.h b/gnu/games/chess/Xchess/std.h
new file mode 100644
index 000000000000..fc8fa6460dcb
--- /dev/null
+++ b/gnu/games/chess/Xchess/std.h
@@ -0,0 +1,105 @@
+
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.2 $ on $Date: 86/11/23 17:18:32 $
+ * $Source: /users/faustus/xchess/RCS/std.h,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ *
+ * Standard definitions.
+ */
+
+#define UNIX
+#define BSD
+
+#ifndef FILE
+#include <stdio.h>
+#endif
+#ifndef isalpha
+#include <ctype.h>
+#endif
+#ifndef HUGE
+#include <math.h>
+#endif
+#include <strings.h>
+
+typedef int bool;
+
+#define false 0
+#define true 1
+
+/* Externs defined in std.c */
+
+extern char *tmalloc();
+extern char *trealloc();
+extern char *copy();
+extern char *datestring();
+extern char *getusername();
+extern char *gethome();
+extern char *gettok();
+extern char *tildexpand();
+extern void fatal();
+extern void setenv();
+extern void appendc();
+extern int scannum();
+extern int seconds();
+extern bool prefix();
+extern bool ciprefix();
+extern bool cieq();
+extern bool substring();
+
+/* Externs from libc */
+
+extern char *getenv();
+extern int errno;
+extern char *sys_errlist[];
+
+/* Should use BSIZE instead of BUFSIZ... */
+
+#define BSIZE 512
+
+/* Some standard macros. */
+
+#define eq(a,b) (!strcmp((a), (b)))
+#define isalphanum(c) (isalpha(c) || isdigit(c))
+#define alloc(strname) ((struct strname *) tmalloc(sizeof(struct strname)))
+#define tfree(ptr) { if (ptr) free((char *) ptr); ptr = 0; }
+#define hexnum(c) ((((c) >= '0') && ((c) <= '9')) ? ((c) - '0') : ((((c) >= \
+ 'a') && ((c) <= 'f')) ? ((c) - 'a' + 10) : ((((c) >= 'A') && \
+ ((c) <= 'F')) ? ((c) - 'A' + 10) : 0)))
+
+#ifndef BSD
+#define random rand
+#define srandom srand
+#endif BSD
+
+#ifdef VMS
+
+#define EXIT_NORMAL 1
+#define EXIT_BAD 0
+
+#else VMS
+
+#define EXIT_NORMAL 0
+#define EXIT_BAD 1
+
+#endif VMS
+
diff --git a/gnu/games/chess/Xchess/valid.c b/gnu/games/chess/Xchess/valid.c
new file mode 100644
index 000000000000..3dcdb004d320
--- /dev/null
+++ b/gnu/games/chess/Xchess/valid.c
@@ -0,0 +1,264 @@
+
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.3 $ on $Date: 86/11/23 17:18:35 $
+ * $Source: /users/faustus/xchess/RCS/valid.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ *
+ * Validate a move.
+ */
+
+#include "xchess.h"
+
+extern bool ischeck(), couldmove();
+
+bool
+valid_move(m, b)
+ move *m;
+ board *b;
+{
+ board tb;
+
+ /* First check that the piece can make the move at all... */
+ if (!couldmove(m, b))
+ return (false);
+
+ /* Now see if the king is in check now. */
+ bcopy((char *) b, (char *) &tb, sizeof (board));
+ board_move(&tb, m);
+ if (ischeck(&tb, m->piece.color))
+ return (false);
+
+ if (ischeck(&tb, ((m->piece.color == WHITE) ? BLACK : WHITE)))
+ m->check = true;
+
+ return (true);
+}
+
+static bool
+couldmove(m, b)
+ move *m;
+ board *b;
+{
+ int x, y;
+
+ switch (m->type) {
+ case KCASTLE:
+ if ((m->piece.color == WHITE) && (b->white_cant_castle_k) ||
+ (m->piece.color == BLACK) &&
+ (b->black_cant_castle_k))
+ return (false);
+ if ((b->square[m->fromy][5].color != NONE) ||
+ (b->square[m->fromy][6].color != NONE))
+ return (false);
+ if (ischeck(b, m->piece.color))
+ return (false);
+ break;
+
+ case QCASTLE:
+ if ((m->piece.color == WHITE) && (b->white_cant_castle_q) ||
+ (m->piece.color == BLACK) &&
+ (b->black_cant_castle_q))
+ return (false);
+ if ((b->square[m->fromy][1].color != NONE) ||
+ (b->square[m->fromy][2].color != NONE) ||
+ (b->square[m->fromy][3].color != NONE))
+ return (false);
+ if (ischeck(b, m->piece.color))
+ return (false);
+ break;
+
+ case MOVE:
+ case CAPTURE:
+ /* There is one special case here, that of taking a pawn
+ * en passant. In this case we change the move field to
+ * CAPTURE if it's ok.
+ */
+ switch (m->piece.type) {
+ case PAWN:
+ if ((m->type == MOVE) && (m->fromx == m->tox)) {
+ /* A normal move. */
+ if ((m->piece.color == WHITE) && (m->fromy ==
+ m->toy + 1))
+ break;
+ if ((m->piece.color == WHITE) && (m->fromy ==
+ 6) && (m->toy == 4) &&
+ (b->square[5][m->fromx].color
+ == NONE))
+ break;
+ if ((m->piece.color == BLACK) && (m->fromy ==
+ m->toy - 1))
+ break;
+ if ((m->piece.color == BLACK) && (m->fromy ==
+ 1) && (m->toy == 3) &&
+ (b->square[2][m->fromx].color
+ == NONE))
+ break;
+ return (false);
+ } else if (m->type == CAPTURE) {
+ if ((((m->piece.color == WHITE) && (m->fromy ==
+ m->toy + 1)) || ((m->piece.color ==
+ BLACK) && (m->fromy == m->toy -
+ 1))) && ((m->fromx == m->tox + 1) ||
+ (m->fromx == m->tox - 1)))
+ break;
+ /* Now maybe it's enpassant... We've already
+ * checked for some of these things in the
+ * calling routine.
+ */
+ if (m->enpassant) {
+ if (b->square[(m->piece.color == WHITE)
+ ? 3 : 4][m->tox].color ==
+ ((m->piece.color == WHITE) ?
+ BLACK : WHITE))
+ break;
+ }
+ return (false);
+ }
+ return (false);
+
+ case ROOK:
+ if (m->fromx == m->tox) {
+ for (y = m->fromy + ((m->fromy > m->toy) ? -1 :
+ 1); y != m->toy; y += ((m->fromy
+ > m->toy) ? -1 : 1))
+ if (b->square[y][m->tox].color != NONE)
+ return (false);
+ break;
+ }
+ if (m->fromy == m->toy) {
+ for (x = m->fromx + ((m->fromx > m->tox) ? -1 :
+ 1); x != m->tox; x += ((m->fromx
+ > m->tox) ? -1 : 1))
+ if (b->square[m->toy][x].color != NONE)
+ return (false);
+ break;
+ }
+ return (false);
+
+ case KNIGHT:
+ x = m->fromx - m->tox;
+ y = m->fromy - m->toy;
+ if ((((x == 2) || (x == -2)) &&
+ ((y == 1) || (y == -1))) ||
+ (((x == 1) || (x == -1)) &&
+ ((y == 2) || (y == -2))))
+ break;
+ return (false);
+
+ case BISHOP:
+ x = m->fromx - m->tox;
+ y = m->fromy - m->toy;
+ if ((x != y) && (x != - y))
+ return (false);
+ for (x = m->fromx + ((m->fromx > m->tox) ? -1 : 1), y =
+ m->fromy + ((m->fromy > m->toy) ? -1 :
+ 1); x != m->tox;
+ x += ((m->fromx > m->tox) ? -1 : 1),
+ y += ((m->fromy > m->toy) ? -1 : 1))
+ if (b->square[y][x].color != NONE)
+ return (false);
+ break;
+
+ case QUEEN:
+ if (m->fromx == m->tox) {
+ for (y = m->fromy + ((m->fromy > m->toy) ? -1 :
+ 1); y != m->toy; y += ((m->fromy
+ > m->toy) ? -1 : 1))
+ if (b->square[y][m->tox].color != NONE)
+ return (false);
+ break;
+ }
+ if (m->fromy == m->toy) {
+ for (x = m->fromx + ((m->fromx > m->tox) ? -1 :
+ 1); x != m->tox; x += ((m->fromx
+ > m->tox) ? -1 : 1))
+ if (b->square[m->toy][x].color != NONE)
+ return (false);
+ break;
+ }
+ x = m->fromx - m->tox;
+ y = m->fromy - m->toy;
+ if ((x != y) && (x != - y))
+ return (false);
+ for (x = m->fromx + ((m->fromx > m->tox) ? -1 : 1), y =
+ m->fromy + ((m->fromy > m->toy) ? -1 :
+ 1); x != m->tox;
+ x += ((m->fromx > m->tox) ? -1 : 1),
+ y += ((m->fromy > m->toy) ? -1 : 1))
+ if (b->square[y][x].color != NONE)
+ return (false);
+ break;
+
+ case KING:
+ x = m->fromx - m->tox;
+ y = m->fromy - m->toy;
+ if ((x >= -1) && (x <= 1) && (y >= -1) && (y <= 1))
+ break;
+ return (false);
+ }
+ break;
+ }
+ return (true);
+}
+
+/* Say whether either king is in check... If move is non-NULL, say whether he
+ * in in check after the move takes place. We do this in a rather stupid way.
+ */
+
+static bool
+ischeck(b, col)
+ board *b;
+ color col;
+{
+ int x, y, kx, ky;
+ move ch;
+
+ for (x = 0; x < SIZE; x++)
+ for (y = 0; y < SIZE; y++)
+ if ((b->square[y][x].color == col) &&
+ (b->square[y][x].type == KING)) {
+ kx = x;
+ ky = y;
+ }
+
+ for (x = 0; x < SIZE; x++)
+ for (y = 0; y < SIZE; y++)
+ if (b->square[y][x].color == ((col == WHITE) ?
+ BLACK : WHITE)) {
+ ch.type = CAPTURE;
+ ch.piece.color = b->square[y][x].color;
+ ch.piece.type = b->square[y][x].type;
+ ch.fromx = x;
+ ch.fromy = y;
+ ch.tox = kx;
+ ch.toy = ky;
+ ch.enpassant = false;
+ if (couldmove(&ch, b))
+ return (true);
+ }
+
+ return (false);
+}
+
diff --git a/gnu/games/chess/Xchess/window.c b/gnu/games/chess/Xchess/window.c
new file mode 100644
index 000000000000..4aae06d9ad90
--- /dev/null
+++ b/gnu/games/chess/Xchess/window.c
@@ -0,0 +1,952 @@
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.5 $ on $Date: 86/11/26 12:11:15 $
+ * $Source: /users/faustus/xchess/RCS/window.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ *
+ * Deal with the two (or one) windows.
+ */
+
+#include "xchess.h"
+#include <X11/Xutil.h>
+#include <sys/time.h>
+
+#include "pawn.bitmap"
+#include "rook.bitmap"
+#include "knight.bitmap"
+#include "bishop.bitmap"
+#include "queen.bitmap"
+#include "king.bitmap"
+
+#include "pawn_outline.bitmap"
+#include "rook_outline.bitmap"
+#include "knight_outline.bitmap"
+#include "bishop_outline.bitmap"
+#include "queen_outline.bitmap"
+#include "king_outline.bitmap"
+
+#include "pawn_mask.bitmap"
+#include "rook_mask.bitmap"
+#include "knight_mask.bitmap"
+#include "bishop_mask.bitmap"
+#include "queen_mask.bitmap"
+#include "king_mask.bitmap"
+
+#include "shade.bitmap"
+
+#include "xchess.cur"
+#include "xchess_mask.cur"
+
+#include "xchess.icon"
+
+windata *win1, *win2;
+bool win_flashmove = false;
+
+extern bool setup();
+extern void service(), drawgrid(), icon_refresh();
+
+bool
+win_setup(disp1, disp2)
+ char *disp1, *disp2;
+{
+ win1 = alloc(windata);
+ if (!oneboard)
+ win2 = alloc(windata);
+
+ if (!setup(disp1, win1) || (!oneboard && !setup(disp2, win2)))
+ return (false);
+
+ if (blackflag) {
+ win1->color = BLACK;
+ win1->flipped = true;
+ } else
+ win1->color = WHITE;
+ win_drawboard(win1);
+
+ if (!oneboard) {
+ win2->color = BLACK;
+ win2->flipped = true;
+ win_drawboard(win2);
+ }
+
+ return(true);
+}
+
+/* Draw the chess board... */
+
+void
+win_drawboard(win)
+ windata *win;
+{
+ int i, j;
+
+ drawgrid(win);
+
+ /* Now toss on the squares... */
+ for (i = 0; i < SIZE; i++)
+ for (j = 0; j < SIZE; j++)
+ win_erasepiece(j, i, win->color);
+
+ return;
+}
+
+/* Draw one piece. */
+
+void
+win_drawpiece(p, y, x, wnum)
+ piece *p;
+ int y, x;
+ color wnum;
+{
+ char *bits, *maskbits, *outline;
+ windata *win;
+ char buf[BSIZE];
+ XImage *tmpImage;
+ Pixmap tmpPM, maskPM;
+ XGCValues gc;
+
+ if (oneboard || (wnum == win1->color))
+ win = win1;
+ else
+ win = win2;
+
+ if (win->flipped) {
+ y = SIZE - y - 1;
+ x = SIZE - x - 1;
+ }
+
+ /*
+ if (debug)
+ fprintf(stderr, "draw a %s at (%d, %d) on board %d\n",
+ piecenames[(int) p->type], y, x, wnum);
+ */
+
+ if ((x < 0) || (x > 7) || (y < 0) || (y > 7)) exit(1);
+
+ switch (p->type) {
+ case PAWN:
+ bits = pawn_bits;
+ maskbits = pawn_mask_bits;
+ outline = pawn_outline_bits;
+ break;
+
+ case ROOK:
+ bits = rook_bits;
+ maskbits = rook_mask_bits;
+ outline = rook_outline_bits;
+ break;
+
+ case KNIGHT:
+ bits = knight_bits;
+ maskbits = knight_mask_bits;
+ outline = knight_outline_bits;
+ break;
+
+ case BISHOP:
+ bits = bishop_bits;
+ maskbits = bishop_mask_bits;
+ outline = bishop_outline_bits;
+ break;
+
+ case QUEEN:
+ bits = queen_bits;
+ maskbits = queen_mask_bits;
+ outline = queen_outline_bits;
+ break;
+
+ case KING:
+ bits = king_bits;
+ maskbits = king_mask_bits;
+ outline = king_outline_bits;
+ break;
+
+ default:
+ fprintf(stderr,
+ "Internal Error: win_drawpiece: bad piece type %d\n",
+ p->type);
+ }
+
+ /* There are two things we can do... If this is a black and white
+ * display, we have to shade the square and use an outline if the piece
+ * is white. We also have to use a mask... Since we don't want
+ * to use up too many bitmaps, create the mask bitmap, put the bits,
+ * and then destroy it.
+ */
+ if (win->bnw && (p->color == WHITE))
+ bits = outline;
+ if (win->bnw && !iswhite(win, x, y)) {
+ XSetState(win->display, DefaultGC(win->display, 0),
+ BlackPixel(win->display, 0),
+ WhitePixel(win->display, 0), GXcopy, AllPlanes);
+
+ tmpPM = XCreateBitmapFromData(win->display, win->boardwin,
+ shade_bits, SQUARE_WIDTH, SQUARE_HEIGHT);
+
+ XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0),
+ 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
+ x * (SQUARE_WIDTH + BORDER_WIDTH),
+ y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
+
+ XFreePixmap(win->display, tmpPM);
+
+ XSetFunction(win->display, DefaultGC(win->display, 0),
+ GXandInverted);
+ maskPM = XCreateBitmapFromData(win->display, win->boardwin,
+ maskbits, SQUARE_WIDTH, SQUARE_HEIGHT);
+ XCopyPlane(win->display, maskPM, win->boardwin, DefaultGC(win->display, 0),
+ 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
+ x * (SQUARE_WIDTH + BORDER_WIDTH),
+ y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
+ XFreePixmap(win->display, maskPM);
+
+ XSetFunction(win->display, DefaultGC(win->display, 0),
+ GXor);
+ tmpPM = XCreateBitmapFromData(win->display, win->boardwin,
+ bits, SQUARE_WIDTH, SQUARE_HEIGHT);
+ XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0),
+ 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
+ x * (SQUARE_WIDTH + BORDER_WIDTH),
+ y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
+ XFreePixmap(win->display, tmpPM);
+
+ XSetFunction(win->display, DefaultGC(win->display, 0), GXcopy);
+
+ } else if (win->bnw){
+ XSetState(win->display, DefaultGC(win->display, 0),
+ BlackPixel(win->display, 0),
+ WhitePixel(win->display, 0), GXcopy, AllPlanes);
+
+ tmpPM = XCreateBitmapFromData(win->display, win->boardwin,
+ bits, SQUARE_WIDTH, SQUARE_HEIGHT);
+ XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0),
+ 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
+ x * (SQUARE_WIDTH + BORDER_WIDTH),
+ y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
+ XFreePixmap(win->display, tmpPM);
+ } else {
+ XSetState(win->display, DefaultGC(win->display, 0),
+ ((p->color == WHITE) ? win->whitepiece.pixel :
+ win->blackpiece.pixel),
+ (iswhite(win, x, y) ? win->whitesquare.pixel :
+ win->blacksquare.pixel),
+ GXcopy, AllPlanes);
+ tmpPM = XCreateBitmapFromData(win->display, win->boardwin,
+ bits, SQUARE_WIDTH, SQUARE_HEIGHT);
+ XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0),
+ 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
+ x * (SQUARE_WIDTH + BORDER_WIDTH),
+ y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
+ XFreePixmap(win->display, tmpPM);
+ }
+
+ if (!record_english) {
+ gc.foreground = win->textcolor.pixel;
+ if (iswhite(win, x, y) || win->bnw)
+ gc.background = win->whitesquare.pixel;
+ else
+ gc.background = win->blacksquare.pixel;
+
+ gc.font = win->small->fid;
+
+ XChangeGC(win->display, DefaultGC(win->display, 0),
+ GCForeground | GCBackground | GCFont, &gc);
+
+ if (!x) {
+ sprintf(buf, " %d", SIZE - y);
+ XDrawImageString(win->display, win->boardwin,
+ DefaultGC(win->display, 0),
+ 1, (y + 1) * (SQUARE_HEIGHT +
+ BORDER_WIDTH) - BORDER_WIDTH +
+ win->small->max_bounds.ascent - 1, buf, 2);
+ }
+ if (y == SIZE - 1) {
+ sprintf(buf, "%c", 'A' + x);
+ XDrawImageString(win->display, win->boardwin,
+ DefaultGC(win->display, 0),
+ x * (SQUARE_WIDTH + BORDER_WIDTH) + 1,
+ SIZE * (SQUARE_HEIGHT + BORDER_WIDTH) - BORDER_WIDTH +
+ win->small->max_bounds.ascent - 1, buf, 1);
+ }
+ }
+ return;
+}
+
+void
+win_erasepiece(y, x, wnum)
+ int y, x;
+ color wnum;
+{
+ windata *win;
+ char buf[BSIZE];
+ XGCValues gc;
+ Pixmap tmpPM;
+
+ if (oneboard || (wnum == win1->color))
+ win = win1;
+ else
+ win = win2;
+
+ if (win->flipped) {
+ y = SIZE - y - 1;
+ x = SIZE - x - 1;
+ }
+
+ /*
+ if (debug)
+ fprintf(stderr, "erase square (%d, %d) on board %d\n", y, x,
+ wnum);
+ */
+
+ if ((x < 0) || (x > 7) || (y < 0) || (y > 7)) exit(1);
+
+ if (win->bnw && !iswhite(win, x, y)) {
+ XSetState(win->display, DefaultGC(win->display, 0),
+ BlackPixel(win->display, 0),
+ WhitePixel(win->display, 0), GXcopy, AllPlanes);
+ tmpPM = XCreateBitmapFromData(win->display, win->boardwin,
+ shade_bits, SQUARE_WIDTH, SQUARE_HEIGHT);
+
+ XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0),
+ 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
+ x * (SQUARE_WIDTH + BORDER_WIDTH),
+ y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
+
+ XFreePixmap(win->display, tmpPM);
+ } else {
+ XSetFillStyle(win->display, DefaultGC(win->display, 0),
+ FillSolid);
+ XSetForeground(win->display, DefaultGC(win->display, 0),
+ iswhite(win, x, y) ? win->whitesquare.pixel :
+ win->blacksquare.pixel);
+ XFillRectangle(win->display, win->boardwin,
+ DefaultGC(win->display, 0),
+ x * (SQUARE_WIDTH + BORDER_WIDTH),
+ y * (SQUARE_HEIGHT + BORDER_WIDTH),
+ SQUARE_WIDTH, SQUARE_HEIGHT);
+ }
+
+ if (!record_english) {
+ gc.foreground = win->textcolor.pixel;
+ if (iswhite(win, x, y) || win->bnw)
+ gc.background = win->whitesquare.pixel;
+ else
+ gc.background = win->blacksquare.pixel;
+
+ gc.font = win->small->fid;
+
+ XChangeGC(win->display, DefaultGC(win->display, 0),
+ GCForeground | GCBackground | GCFont, &gc);
+
+ if (!x) {
+ sprintf(buf, " %d", SIZE - y);
+ XDrawImageString(win->display, win->boardwin,
+ DefaultGC(win->display, 0),
+ 1, (y + 1) * (SQUARE_HEIGHT +
+ BORDER_WIDTH) - BORDER_WIDTH +
+ win->small->max_bounds.ascent - 1, buf, 2);
+ }
+ if (y == SIZE - 1) {
+ sprintf(buf, "%c", 'A' + x);
+ XDrawImageString(win->display, win->boardwin,
+ DefaultGC(win->display, 0),
+ x * (SQUARE_WIDTH + BORDER_WIDTH) + 1,
+ SIZE * (SQUARE_HEIGHT + BORDER_WIDTH) - BORDER_WIDTH +
+ win->small->max_bounds.ascent - 1, buf, 1);
+ }
+ }
+
+
+ return;
+}
+
+void
+win_flash(m, wnum)
+ move *m;
+ color wnum;
+{
+ windata *win;
+ int sx, sy, ex, ey, i;
+
+ if (oneboard || (wnum == win1->color))
+ win = win1;
+ else
+ win = win2;
+
+ if (win->flipped) {
+ sx = SIZE - m->fromx - 1;
+ sy = SIZE - m->fromy - 1;
+ ex = SIZE - m->tox - 1;
+ ey = SIZE - m->toy - 1;
+ } else {
+ sx = m->fromx;
+ sy = m->fromy;
+ ex = m->tox;
+ ey = m->toy;
+ }
+ sx = sx * (SQUARE_WIDTH + BORDER_WIDTH) + SQUARE_WIDTH / 2;
+ sy = sy * (SQUARE_HEIGHT + BORDER_WIDTH) + SQUARE_HEIGHT / 2;
+ ex = ex * (SQUARE_WIDTH + BORDER_WIDTH) + SQUARE_WIDTH / 2;
+ ey = ey * (SQUARE_HEIGHT + BORDER_WIDTH) + SQUARE_HEIGHT / 2;
+
+ XSetFunction(win->display, DefaultGC(win->display, 0), GXinvert);
+ XSetLineAttributes(win->display, DefaultGC(win->display, 0),
+ 0, LineSolid, 0, 0);
+ for (i = 0; i < num_flashes * 2; i++) {
+ XDrawLine(win->display,win->boardwin,
+ DefaultGC(win->display, 0),
+ sx, sy, ex, ey);
+ }
+
+ XSetFunction(win->display, DefaultGC(win->display, 0), GXcopy);
+ return;
+}
+
+/* Handle input from the players. */
+
+void
+win_process(quick)
+ bool quick;
+{
+ int i, rfd = 0, wfd = 0, xfd = 0;
+ struct timeval timeout;
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = (quick ? 0 : 500000);
+
+ if (XPending(win1->display))
+ service(win1);
+ if (!oneboard) {
+ if (XPending(win1->display))
+ service(win2);
+ }
+
+ if (oneboard)
+ rfd = 1 << win1->display->fd;
+ else
+ rfd = (1 << win1->display->fd) | (1 << win2->display->fd);
+ if (!(i = select(32, &rfd, &wfd, &xfd, &timeout)))
+ return;
+ if (i == -1) {
+ perror("select");
+ exit(1);
+ }
+ if (rfd & (1 << win1->display->fd))
+ service(win1);
+ if (!oneboard && (rfd & (1 << win2->display->fd)))
+ service(win2);
+
+ return;
+}
+
+static void
+service(win)
+ windata *win;
+{
+ XEvent ev;
+
+ while(XPending(win->display)) {
+ XNextEvent(win->display, &ev);
+ if (TxtFilter(win->display, &ev))
+ continue;
+
+ if (ev.xany.window == win->boardwin) {
+ switch (ev.type) {
+ case ButtonPress:
+ button_pressed(&ev, win);
+ break;
+
+ case ButtonRelease:
+ button_released(&ev, win);
+ break;
+
+ case Expose:
+ /* Redraw... */
+ win_redraw(win, &ev);
+ break;
+
+ case 0:
+ case NoExpose:
+ break;
+ default:
+ fprintf(stderr, "Bad event type %d\n", ev.type);
+ exit(1);
+ }
+ } else if (ev.xany.window == win->wclockwin) {
+ switch (ev.type) {
+ case Expose:
+ clock_draw(win, WHITE);
+ break;
+
+ case 0:
+ case NoExpose:
+ break;
+ default:
+ fprintf(stderr, "Bad event type %d\n", ev.type);
+ exit(1);
+ }
+ } else if (ev.xany.window == win->bclockwin) {
+ switch (ev.type) {
+ case Expose:
+ clock_draw(win, BLACK);
+ break;
+
+ case 0:
+ case NoExpose:
+ break;
+ default:
+ fprintf(stderr, "Bad event type %d\n", ev.type);
+ exit(1);
+ }
+ } else if (ev.xany.window == win->jailwin) {
+ switch (ev.type) {
+ case Expose:
+ jail_draw(win);
+ break;
+
+ case 0:
+ case NoExpose:
+ break;
+ default:
+ fprintf(stderr, "Bad event type %d\n", ev.type);
+ exit(1);
+ }
+ } else if (ev.xany.window == win->buttonwin) {
+ switch (ev.type) {
+ case ButtonPress:
+ button_service(win, &ev);
+ break;
+
+ case Expose:
+ button_draw(win);
+ break;
+
+ case 0:
+ case NoExpose:
+ break;
+ default:
+ fprintf(stderr, "Bad event type %d\n", ev.type);
+ exit(1);
+ }
+ } else if (ev.xany.window == win->icon) {
+ icon_refresh(win);
+ } else if (ev.xany.window == win->basewin) {
+ message_send(win, &ev);
+ } else {
+ fprintf(stderr, "Internal Error: service: bad win\n");
+ fprintf(stderr, "window = %d, event = %d\n", ev.xany.window,
+ ev.type);
+ }
+ }
+ return;
+}
+
+void
+win_redraw(win, event)
+ windata *win;
+ XEvent *event;
+{
+ XExposeEvent *ev = &event->xexpose;
+ int x1, y1, x2, y2, i, j;
+
+ drawgrid(win);
+ if (ev) {
+ x1 = ev->x / (SQUARE_WIDTH + BORDER_WIDTH);
+ y1 = ev->y / (SQUARE_HEIGHT + BORDER_WIDTH);
+ x2 = (ev->x + ev->width) / (SQUARE_WIDTH + BORDER_WIDTH);
+ y2 = (ev->y + ev->height) / (SQUARE_HEIGHT + BORDER_WIDTH);
+ } else {
+ x1 = 0;
+ y1 = 0;
+ x2 = SIZE - 1;
+ y2 = SIZE - 1;
+ }
+
+ if (x1 < 0) x1 = 0;
+ if (y1 < 0) y1 = 0;
+ if (x2 < 0) x2 = 0;
+ if (y2 < 0) y2 = 0;
+ if (x1 > SIZE - 1) x1 = SIZE - 1;
+ if (y1 > SIZE - 1) y1 = SIZE - 1;
+ if (x2 > SIZE - 1) x2 = SIZE - 1;
+ if (y2 > SIZE - 1) y2 = SIZE - 1;
+
+ if (win->flipped) {
+ y1 = SIZE - y2 - 1;
+ y2 = SIZE - y1 - 1;
+ x1 = SIZE - x2 - 1;
+ x2 = SIZE - x1 - 1;
+ }
+
+ for (i = x1; i <= x2; i++)
+ for (j = y1; j <= y2; j++) {
+ if (chessboard->square[j][i].color == NONE)
+ win_erasepiece(j, i, WHITE);
+ else
+ win_drawpiece(&chessboard->square[j][i], j, i,
+ WHITE);
+ if (!oneboard) {
+ if (chessboard->square[j][i].color == NONE)
+ win_erasepiece(j, i, BLACK);
+ else
+ win_drawpiece(&chessboard->square[j][i],
+ j, i, BLACK);
+ }
+ }
+
+ return;
+}
+
+static bool
+setup(dispname, win)
+ char *dispname;
+ windata *win;
+{
+ char buf[BSIZE], *s;
+ Pixmap bm, bmask;
+ Cursor cur;
+ extern char *program, *recfile;
+ XSizeHints xsizes;
+
+
+ if (!(win->display = XOpenDisplay(dispname)))
+ return (false);
+
+
+ /* Now get boolean defaults... */
+ if ((s = XGetDefault(win->display, program, "noisy")) && eq(s, "on"))
+ noisyflag = true;
+ if ((s = XGetDefault(win->display, program, "savemoves")) && eq(s, "on"))
+ saveflag = true;
+ if ((s = XGetDefault(win->display, program, "algebraic")) && eq(s, "on"))
+ record_english = false;
+ if ((s = XGetDefault(win->display, program, "blackandwhite")) && eq(s, "on"))
+ bnwflag = true;
+ if ((s = XGetDefault(win->display, program, "quickrestore")) && eq(s, "on"))
+ quickflag = true;
+ if ((s = XGetDefault(win->display, program, "flash")) && eq(s, "on"))
+ win_flashmove = true;
+
+ /* ... numeric variables ... */
+ if (s = XGetDefault(win->display, program, "numflashes"))
+ num_flashes = atoi(s);
+ if (s = XGetDefault(win->display, program, "flashsize"))
+ flash_size = atoi(s);
+
+ /* ... and strings. */
+ if (s = XGetDefault(win->display, program, "progname"))
+ progname = s;
+ if (s = XGetDefault(win->display, program, "proghost"))
+ proghost = s;
+ if (s = XGetDefault(win->display, program, "recordfile"))
+ recfile = s;
+ if (s = XGetDefault(win->display, program, "blackpiece"))
+ black_piece_color = s;
+ if (s = XGetDefault(win->display, program, "whitepiece"))
+ white_piece_color = s;
+ if (s = XGetDefault(win->display, program, "blacksquare"))
+ black_square_color = s;
+ if (s = XGetDefault(win->display, program, "whitesquare"))
+ white_square_color = s;
+ if (s = XGetDefault(win->display, program, "bordercolor"))
+ border_color = s;
+ if (s = XGetDefault(win->display, program, "textcolor"))
+ text_color = s;
+ if (s = XGetDefault(win->display, program, "textback"))
+ text_back = s;
+ if (s = XGetDefault(win->display, program, "errortext"))
+ error_text = s;
+ if (s = XGetDefault(win->display, program, "playertext"))
+ player_text = s;
+ if (s = XGetDefault(win->display, program, "cursorcolor"))
+ cursor_color = s;
+
+ if ((DisplayPlanes(win->display, 0) == 1) || bnwflag)
+ win->bnw = true;
+
+ /* Allocate colors... */
+ if (win->bnw) {
+ win->blackpiece.pixel = BlackPixel (win->display, 0);
+ win->whitepiece.pixel = WhitePixel (win->display, 0);
+ win->blacksquare.pixel = BlackPixel (win->display, 0);
+ win->whitesquare.pixel = WhitePixel (win->display, 0);
+ win->border.pixel = BlackPixel (win->display, 0);
+ win->textcolor.pixel = BlackPixel (win->display, 0);
+ win->textback.pixel = WhitePixel (win->display, 0);
+ win->playertext.pixel = BlackPixel (win->display, 0);
+ win->errortext.pixel = BlackPixel (win->display, 0);
+ win->cursorcolor.pixel = BlackPixel (win->display, 0) ;
+ } else {
+ if (!XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ black_piece_color, &win->blackpiece) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ white_piece_color, &win->whitepiece) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ black_square_color, &win->blacksquare) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ white_square_color, &win->whitesquare) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ border_color, &win->border) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ text_color, &win->textcolor) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ text_back, &win->textback) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ error_text, &win->errortext) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ player_text, &win->playertext) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ cursor_color, &win->cursorcolor) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->blackpiece) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->whitepiece) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->blacksquare) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->whitesquare) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->border) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->textcolor) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->textback) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->errortext) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->playertext) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->cursorcolor))
+ fprintf(stderr, "Can't get colors...\n");
+ }
+
+ /* Get fonts... */
+ if ((win->small = XLoadQueryFont(win->display,SMALL_FONT)) ==
+ NULL)
+ fprintf(stderr, "Can't get small font...\n");
+
+ if ((win->medium = XLoadQueryFont(win->display,MEDIUM_FONT))
+ == NULL)
+ fprintf(stderr, "Can't get medium font...\n");
+
+ if ((win->large = XLoadQueryFont(win->display,LARGE_FONT)) ==
+ NULL)
+ fprintf(stderr, "Can't get large font...\n");
+
+
+ /* Create the windows... */
+
+ win->basewin =
+ XCreateSimpleWindow(win->display,DefaultRootWindow(win->display),
+ BASE_XPOS, BASE_YPOS,
+ BASE_WIDTH, BASE_HEIGHT, 0,
+ BlackPixel(win->display, 0),
+ WhitePixel(win->display, 0));
+ win->boardwin = XCreateSimpleWindow(win->display,win->basewin,
+ BOARD_XPOS, BOARD_YPOS,
+ BOARD_WIDTH, BOARD_HEIGHT,
+ BORDER_WIDTH,
+ win->border.pixel,
+ WhitePixel(win->display, 0));
+ win->recwin = XCreateSimpleWindow(win->display,win->basewin,
+ RECORD_XPOS, RECORD_YPOS,
+ RECORD_WIDTH, RECORD_HEIGHT,
+ BORDER_WIDTH, win->border.pixel,
+ win->textback.pixel);
+ win->jailwin = XCreateSimpleWindow(win->display,win->basewin,
+ JAIL_XPOS, JAIL_YPOS,
+ JAIL_WIDTH, JAIL_HEIGHT,
+ BORDER_WIDTH,
+ win->border.pixel,
+ win->textback.pixel);
+ win->wclockwin = XCreateSimpleWindow(win->display,win->basewin,
+ WCLOCK_XPOS, WCLOCK_YPOS,
+ CLOCK_WIDTH, CLOCK_HEIGHT,
+ BORDER_WIDTH, win->border.pixel,
+ win->textback.pixel);
+ win->bclockwin = XCreateSimpleWindow(win->display,win->basewin,
+ BCLOCK_XPOS, BCLOCK_YPOS,
+ CLOCK_WIDTH, CLOCK_HEIGHT,
+ BORDER_WIDTH, win->border.pixel,
+ win->textback.pixel);
+ win->messagewin = XCreateSimpleWindow(win->display,win->basewin,
+ MESS_XPOS, MESS_YPOS,
+ MESS_WIDTH, MESS_HEIGHT,
+ BORDER_WIDTH, win->border.pixel,
+ win->textback.pixel);
+ win->buttonwin = XCreateSimpleWindow(win->display,win->basewin,
+ BUTTON_XPOS, BUTTON_YPOS,
+ BUTTON_WIDTH, BUTTON_HEIGHT,
+ BORDER_WIDTH, win->border.pixel,
+ win->textback.pixel);
+
+ /* Let's define an icon... */
+ win->iconpixmap = XCreatePixmapFromBitmapData(win->display,
+ win->basewin, icon_bits,
+ icon_width, icon_height,
+ win->blacksquare.pixel,
+ win->whitesquare.pixel,
+ 1);
+ xsizes.flags = PSize | PMinSize | PPosition;
+ xsizes.min_width = BASE_WIDTH;
+ xsizes.min_height = BASE_HEIGHT;
+ xsizes.x = BASE_XPOS;
+ xsizes.y = BASE_YPOS;
+ XSetStandardProperties(win->display, win->basewin,
+ program, program, win->iconpixmap,
+ 0, NULL, &xsizes);
+
+ bm = XCreateBitmapFromData(win->display,
+ win->basewin, xchess_bits,
+ xchess_width, xchess_height);
+ bmask = XCreateBitmapFromData(win->display,
+ win->basewin, xchess_mask_bits,
+ xchess_width, xchess_height);
+ cur = XCreatePixmapCursor(win->display, bm, bmask,
+ &win->cursorcolor,
+ &WhitePixel(win->display, 0),
+ xchess_x_hot, xchess_y_hot);
+ XFreePixmap(win->display, bm);
+ XFreePixmap(win->display, bmask);
+
+ XDefineCursor(win->display,win->basewin, cur);
+
+ XMapSubwindows(win->display,win->basewin);
+ XMapRaised(win->display,win->basewin);
+
+ XSelectInput(win->display,win->basewin, KeyPressMask);
+ XSelectInput(win->display,win->boardwin,
+ ButtonPressMask | ButtonReleaseMask | ExposureMask);
+ XSelectInput(win->display,win->recwin,
+ ButtonReleaseMask | ExposureMask);
+ XSelectInput(win->display,win->jailwin, ExposureMask);
+ XSelectInput(win->display,win->wclockwin, ExposureMask);
+ XSelectInput(win->display,win->bclockwin, ExposureMask);
+ XSelectInput(win->display,win->messagewin,
+ ButtonReleaseMask | ExposureMask);
+ XSelectInput(win->display,win->buttonwin,
+ ButtonPressMask | ExposureMask);
+
+ message_init(win);
+ record_init(win);
+ button_draw(win);
+ jail_init(win);
+ clock_init(win, WHITE);
+ clock_init(win, BLACK);
+ if (timeunit) {
+ if (timeunit > 1800)
+ sprintf(buf, "%d moves every %.2lg hours.\n",
+ movesperunit, ((double) timeunit) / 3600);
+ else if (timeunit > 30)
+ sprintf(buf, "%d moves every %.2lg minutes.\n",
+ movesperunit, ((double) timeunit) / 60);
+ else
+ sprintf(buf, "%d moves every %d seconds.\n",
+ movesperunit, timeunit);
+ message_add(win, buf, false);
+ }
+ return (true);
+}
+
+static void
+drawgrid(win)
+ windata *win;
+{
+ int i;
+ XGCValues gc;
+
+ gc.function = GXcopy;
+ gc.plane_mask = AllPlanes;
+ gc.foreground = win->border.pixel;
+ gc.line_width = 0;
+ gc.line_style = LineSolid;
+
+ XChangeGC(win->display,
+ DefaultGC(win->display, 0),
+ GCFunction | GCPlaneMask | GCForeground |
+ GCLineWidth | GCLineStyle, &gc);
+
+ /* Draw the lines... horizontal, */
+ for (i = 1; i < SIZE; i++)
+ XDrawLine(win->display, win->boardwin,
+ DefaultGC(win->display, 0), 0,
+ i * (SQUARE_WIDTH + BORDER_WIDTH) -
+ BORDER_WIDTH / 2,
+ SIZE * (SQUARE_WIDTH + BORDER_WIDTH),
+ i * (SQUARE_WIDTH + BORDER_WIDTH) -
+ BORDER_WIDTH / 2);
+
+ /* and vertical... */
+ for (i = 1; i < SIZE; i++)
+ XDrawLine(win->display, win->boardwin,
+ DefaultGC(win->display, 0),
+ i * (SQUARE_WIDTH + BORDER_WIDTH) -
+ BORDER_WIDTH / 2, 0,
+ i * (SQUARE_WIDTH + BORDER_WIDTH) -
+ BORDER_WIDTH / 2,
+ SIZE * (SQUARE_WIDTH + BORDER_WIDTH));
+ return;
+}
+
+void
+win_restart()
+{
+ win1->flipped = false;
+ win_redraw(win1, (XEvent *) NULL);
+ if (!oneboard) {
+ win2->flipped = true;
+ win_redraw(win2, (XEvent *) NULL);
+ }
+ return;
+}
+
+static void
+icon_refresh(win)
+ windata *win;
+{
+ XCopyArea(win->display, win->iconpixmap, win->icon,
+ DefaultGC(win->display, 0),
+ 0, 0, icon_width, icon_height, 0, 0);
+ return;
+}
+
diff --git a/gnu/games/chess/Xchess/window.c.bm b/gnu/games/chess/Xchess/window.c.bm
new file mode 100644
index 000000000000..19134d0cdc14
--- /dev/null
+++ b/gnu/games/chess/Xchess/window.c.bm
@@ -0,0 +1,928 @@
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.5 $ on $Date: 86/11/26 12:11:15 $
+ * $Source: /users/faustus/xchess/RCS/window.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ *
+ * Deal with the two (or one) windows.
+ */
+
+#include "xchess.h"
+#include <sys/time.h>
+
+#include "pawn.bitmap"
+#include "rook.bitmap"
+#include "knight.bitmap"
+#include "bishop.bitmap"
+#include "queen.bitmap"
+#include "king.bitmap"
+
+#include "pawn_outline.bitmap"
+#include "rook_outline.bitmap"
+#include "knight_outline.bitmap"
+#include "bishop_outline.bitmap"
+#include "queen_outline.bitmap"
+#include "king_outline.bitmap"
+
+#include "pawn_mask.bitmap"
+#include "rook_mask.bitmap"
+#include "knight_mask.bitmap"
+#include "bishop_mask.bitmap"
+#include "queen_mask.bitmap"
+#include "king_mask.bitmap"
+
+#include "shade.bitmap"
+
+#include "xchess.cur"
+#include "xchess_mask.cur"
+
+#include "xchess.icon"
+
+windata *win1, *win2;
+bool win_flashmove = false;
+
+extern bool setup();
+extern void service(), drawgrid(), icon_refresh();
+
+bool
+win_setup(disp1, disp2)
+ char *disp1, *disp2;
+{
+ win1 = alloc(windata);
+ if (!oneboard)
+ win2 = alloc(windata);
+
+ if (!setup(disp1, win1) || (!oneboard && !setup(disp2, win2)))
+ return (false);
+
+ if (blackflag) {
+ win1->color = BLACK;
+ win1->flipped = true;
+ } else
+ win1->color = WHITE;
+ win_drawboard(win1);
+
+ if (!oneboard) {
+ win2->color = BLACK;
+ win2->flipped = true;
+ win_drawboard(win2);
+ }
+
+ return(true);
+}
+
+/* Draw the chess board... */
+
+void
+win_drawboard(win)
+ windata *win;
+{
+ int i, j;
+
+ drawgrid(win);
+
+ /* Now toss on the squares... */
+ for (i = 0; i < SIZE; i++)
+ for (j = 0; j < SIZE; j++)
+ win_erasepiece(j, i, win->color);
+
+ return;
+}
+
+/* Draw one piece. */
+
+void
+win_drawpiece(p, y, x, wnum)
+ piece *p;
+ int y, x;
+ color wnum;
+{
+ char *bits, *maskbits, *outline;
+ windata *win;
+ char buf[BSIZE];
+ XImage *tmpImage;
+ Pixmap tmpPM, maskPM;
+ XGCValues gc;
+
+ if (oneboard || (wnum == win1->color))
+ win = win1;
+ else
+ win = win2;
+
+ if (win->flipped) {
+ y = SIZE - y - 1;
+ x = SIZE - x - 1;
+ }
+
+ /*
+ if (debug)
+ fprintf(stderr, "draw a %s at (%d, %d) on board %d\n",
+ piecenames[(int) p->type], y, x, wnum);
+ */
+
+ if ((x < 0) || (x > 7) || (y < 0) || (y > 7)) exit(1);
+
+ switch (p->type) {
+ case PAWN:
+ bits = pawn_bits;
+ maskbits = pawn_mask_bits;
+ outline = pawn_outline_bits;
+ break;
+
+ case ROOK:
+ bits = rook_bits;
+ maskbits = rook_mask_bits;
+ outline = rook_outline_bits;
+ break;
+
+ case KNIGHT:
+ bits = knight_bits;
+ maskbits = knight_mask_bits;
+ outline = knight_outline_bits;
+ break;
+
+ case BISHOP:
+ bits = bishop_bits;
+ maskbits = bishop_mask_bits;
+ outline = bishop_outline_bits;
+ break;
+
+ case QUEEN:
+ bits = queen_bits;
+ maskbits = queen_mask_bits;
+ outline = queen_outline_bits;
+ break;
+
+ case KING:
+ bits = king_bits;
+ maskbits = king_mask_bits;
+ outline = king_outline_bits;
+ break;
+
+ default:
+ fprintf(stderr,
+ "Internal Error: win_drawpiece: bad piece type %d\n",
+ p->type);
+ }
+
+ /* There are two things we can do... If this is a black and white
+ * display, we have to shade the square and use an outline if the piece
+ * is white. We also have to use a mask... Since we don't want
+ * to use up too many bitmaps, create the mask bitmap, put the bits,
+ * and then destroy it.
+ */
+ if (win->bnw && (p->color == WHITE))
+ bits = outline;
+ if (win->bnw && !iswhite(win, x, y)) {
+ XSetState(win->display, DefaultGC(win->display, 0),
+ BlackPixel(win->display, 0),
+ WhitePixel(win->display, 0), GXcopy, AllPlanes);
+
+ tmpPM = XCreateBitmapFromData(win->display, win->boardwin,
+ shade_bits, SQUARE_WIDTH, SQUARE_HEIGHT);
+
+ XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0),
+ 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
+ x * (SQUARE_WIDTH + BORDER_WIDTH),
+ y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
+
+ XFreePixmap(win->display, tmpPM);
+
+ XSetFunction(win->display, DefaultGC(win->display, 0),
+ GXandInverted);
+ maskPM = XCreateBitmapFromData(win->display, win->boardwin,
+ maskbits, SQUARE_WIDTH, SQUARE_HEIGHT);
+ XCopyPlane(win->display, maskPM, win->boardwin, DefaultGC(win->display, 0),
+ 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
+ x * (SQUARE_WIDTH + BORDER_WIDTH),
+ y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
+ XFreePixmap(win->display, maskPM);
+
+ XSetFunction(win->display, DefaultGC(win->display, 0),
+ GXor);
+ tmpPM = XCreateBitmapFromData(win->display, win->boardwin,
+ bits, SQUARE_WIDTH, SQUARE_HEIGHT);
+ XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0),
+ 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
+ x * (SQUARE_WIDTH + BORDER_WIDTH),
+ y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
+ XFreePixmap(win->display, tmpPM);
+
+ XSetFunction(win->display, DefaultGC(win->display, 0), GXcopy);
+
+ } else if (win->bnw){
+ XSetState(win->display, DefaultGC(win->display, 0),
+ BlackPixel(win->display, 0),
+ WhitePixel(win->display, 0), GXcopy, AllPlanes);
+
+ tmpPM = XCreateBitmapFromData(win->display, win->boardwin,
+ bits, SQUARE_WIDTH, SQUARE_HEIGHT);
+ XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0),
+ 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
+ x * (SQUARE_WIDTH + BORDER_WIDTH),
+ y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
+ XFreePixmap(win->display, tmpPM);
+ } else {
+ XSetState(win->display, DefaultGC(win->display, 0),
+ ((p->color == WHITE) ? win->whitepiece.pixel :
+ win->blackpiece.pixel),
+ (iswhite(win, x, y) ? win->whitesquare.pixel :
+ win->blacksquare.pixel),
+ GXcopy, AllPlanes);
+ tmpPM = XCreateBitmapFromData(win->display, win->boardwin,
+ bits, SQUARE_WIDTH, SQUARE_HEIGHT);
+ XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0),
+ 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
+ x * (SQUARE_WIDTH + BORDER_WIDTH),
+ y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
+ XFreePixmap(win->display, tmpPM);
+ }
+
+ if (!record_english) {
+ gc.foreground = win->textcolor.pixel;
+ if (iswhite(win, x, y) || win->bnw)
+ gc.background = win->whitesquare.pixel;
+ else
+ gc.background = win->blacksquare.pixel;
+
+ gc.font = win->small->fid;
+
+ XChangeGC(win->display, DefaultGC(win->display, 0),
+ GCForeground | GCBackground | GCFont, &gc);
+
+ if (!x) {
+ sprintf(buf, " %d", SIZE - y);
+ XDrawImageString(win->display, win->boardwin,
+ DefaultGC(win->display, 0),
+ 1, (y + 1) * (SQUARE_HEIGHT +
+ BORDER_WIDTH) - BORDER_WIDTH +
+ win->small->max_bounds.ascent - 1, buf, 2);
+ }
+ if (y == SIZE - 1) {
+ sprintf(buf, "%c", 'A' + x);
+ XDrawImageString(win->display, win->boardwin,
+ DefaultGC(win->display, 0),
+ x * (SQUARE_WIDTH + BORDER_WIDTH) + 1,
+ SIZE * (SQUARE_HEIGHT + BORDER_WIDTH) - BORDER_WIDTH +
+ win->small->max_bounds.ascent - 1, buf, 1);
+ }
+ }
+ return;
+}
+
+void
+win_erasepiece(y, x, wnum)
+ int y, x;
+ color wnum;
+{
+ windata *win;
+ char buf[BSIZE];
+ XGCValues gc;
+ Pixmap tmpPM;
+
+ if (oneboard || (wnum == win1->color))
+ win = win1;
+ else
+ win = win2;
+
+ if (win->flipped) {
+ y = SIZE - y - 1;
+ x = SIZE - x - 1;
+ }
+
+ /*
+ if (debug)
+ fprintf(stderr, "erase square (%d, %d) on board %d\n", y, x,
+ wnum);
+ */
+
+ if ((x < 0) || (x > 7) || (y < 0) || (y > 7)) exit(1);
+
+ if (win->bnw && !iswhite(win, x, y)) {
+ XSetState(win->display, DefaultGC(win->display, 0),
+ BlackPixel(win->display, 0),
+ WhitePixel(win->display, 0), GXcopy, AllPlanes);
+ tmpPM = XCreateBitmapFromData(win->display, win->boardwin,
+ shade_bits, SQUARE_WIDTH, SQUARE_HEIGHT);
+
+ XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0),
+ 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
+ x * (SQUARE_WIDTH + BORDER_WIDTH),
+ y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
+
+ XFreePixmap(win->display, tmpPM);
+ } else {
+ XSetFillStyle(win->display, DefaultGC(win->display, 0),
+ FillSolid);
+ XSetForeground(win->display, DefaultGC(win->display, 0),
+ iswhite(win, x, y) ? win->whitesquare.pixel :
+ win->blacksquare.pixel);
+ XFillRectangle(win->display, win->boardwin,
+ DefaultGC(win->display, 0),
+ x * (SQUARE_WIDTH + BORDER_WIDTH),
+ y * (SQUARE_HEIGHT + BORDER_WIDTH),
+ SQUARE_WIDTH, SQUARE_HEIGHT);
+ }
+
+ if (!record_english) {
+ gc.foreground = win->textcolor.pixel;
+ if (iswhite(win, x, y) || win->bnw)
+ gc.background = win->whitesquare.pixel;
+ else
+ gc.background = win->blacksquare.pixel;
+
+ gc.font = win->small->fid;
+
+ XChangeGC(win->display, DefaultGC(win->display, 0),
+ GCForeground | GCBackground | GCFont, &gc);
+
+ if (!x) {
+ sprintf(buf, " %d", SIZE - y);
+ XDrawImageString(win->display, win->boardwin,
+ DefaultGC(win->display, 0),
+ 1, (y + 1) * (SQUARE_HEIGHT +
+ BORDER_WIDTH) - BORDER_WIDTH +
+ win->small->max_bounds.ascent - 1, buf, 2);
+ }
+ if (y == SIZE - 1) {
+ sprintf(buf, "%c", 'A' + x);
+ XDrawImageString(win->display, win->boardwin,
+ DefaultGC(win->display, 0),
+ x * (SQUARE_WIDTH + BORDER_WIDTH) + 1,
+ SIZE * (SQUARE_HEIGHT + BORDER_WIDTH) - BORDER_WIDTH +
+ win->small->max_bounds.ascent - 1, buf, 1);
+ }
+ }
+
+
+ return;
+}
+
+void
+win_flash(m, wnum)
+ move *m;
+ color wnum;
+{
+ windata *win;
+ int sx, sy, ex, ey, i;
+
+ if (oneboard || (wnum == win1->color))
+ win = win1;
+ else
+ win = win2;
+
+ if (win->flipped) {
+ sx = SIZE - m->fromx - 1;
+ sy = SIZE - m->fromy - 1;
+ ex = SIZE - m->tox - 1;
+ ey = SIZE - m->toy - 1;
+ } else {
+ sx = m->fromx;
+ sy = m->fromy;
+ ex = m->tox;
+ ey = m->toy;
+ }
+ sx = sx * (SQUARE_WIDTH + BORDER_WIDTH) + SQUARE_WIDTH / 2;
+ sy = sy * (SQUARE_HEIGHT + BORDER_WIDTH) + SQUARE_HEIGHT / 2;
+ ex = ex * (SQUARE_WIDTH + BORDER_WIDTH) + SQUARE_WIDTH / 2;
+ ey = ey * (SQUARE_HEIGHT + BORDER_WIDTH) + SQUARE_HEIGHT / 2;
+
+ for (i = 0; i < num_flashes * 2; i++)
+ XDrawLine(win->display,win->boardwin,
+ DefaultGC(win->display, 0),
+ sx, sy, ex, ey);
+ return;
+}
+
+/* Handle input from the players. */
+
+void
+win_process(quick)
+ bool quick;
+{
+ int i, rfd = 0, wfd = 0, xfd = 0;
+ struct timeval timeout;
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = (quick ? 0 : 500000);
+
+ if (XPending(win1->display))
+ service(win1);
+ if (!oneboard) {
+ if (XPending(win1->display))
+ service(win2);
+ }
+
+ if (oneboard)
+ rfd = 1 << win1->display->fd;
+ else
+ rfd = (1 << win1->display->fd) | (1 << win2->display->fd);
+ if (!(i = select(32, &rfd, &wfd, &xfd, &timeout)))
+ return;
+ if (i == -1) {
+ perror("select");
+ exit(1);
+ }
+ if (rfd & (1 << win1->display->fd))
+ service(win1);
+ if (!oneboard && (rfd & (1 << win2->display->fd)))
+ service(win2);
+
+ return;
+}
+
+static void
+service(win)
+ windata *win;
+{
+ XEvent ev;
+
+ while(XPending(win->display)) {
+ XNextEvent(win->display, &ev);
+ if (TxtFilter(win->display, &ev))
+ continue;
+
+ if (ev.xany.window == win->boardwin) {
+ switch (ev.type) {
+ case ButtonPress:
+ button_pressed(&ev, win);
+ break;
+
+ case ButtonRelease:
+ button_released(&ev, win);
+ break;
+
+ case Expose:
+ /* Redraw... */
+ win_redraw(win, &ev);
+ break;
+
+ case 0:
+ case NoExpose:
+ break;
+ default:
+ fprintf(stderr, "Bad event type %d\n", ev.type);
+ exit(1);
+ }
+ } else if (ev.xany.window == win->wclockwin) {
+ switch (ev.type) {
+ case Expose:
+ clock_draw(win, WHITE);
+ break;
+
+ case 0:
+ case NoExpose:
+ break;
+ default:
+ fprintf(stderr, "Bad event type %d\n", ev.type);
+ exit(1);
+ }
+ } else if (ev.xany.window == win->bclockwin) {
+ switch (ev.type) {
+ case Expose:
+ clock_draw(win, BLACK);
+ break;
+
+ case 0:
+ case NoExpose:
+ break;
+ default:
+ fprintf(stderr, "Bad event type %d\n", ev.type);
+ exit(1);
+ }
+ } else if (ev.xany.window == win->jailwin) {
+ switch (ev.type) {
+ case Expose:
+ jail_draw(win);
+ break;
+
+ case 0:
+ case NoExpose:
+ break;
+ default:
+ fprintf(stderr, "Bad event type %d\n", ev.type);
+ exit(1);
+ }
+ } else if (ev.xany.window == win->buttonwin) {
+ switch (ev.type) {
+ case ButtonPress:
+ button_service(win, &ev);
+ break;
+
+ case Expose:
+ button_draw(win);
+ break;
+
+ case 0:
+ case NoExpose:
+ break;
+ default:
+ fprintf(stderr, "Bad event type %d\n", ev.type);
+ exit(1);
+ }
+ } else if (ev.xany.window == win->icon) {
+ icon_refresh(win);
+ } else if (ev.xany.window == win->basewin) {
+ message_send(win, &ev);
+ } else {
+ fprintf(stderr, "Internal Error: service: bad win\n");
+ fprintf(stderr, "window = %d, event = %d\n", ev.xany.window,
+ ev.type);
+ }
+ }
+ return;
+}
+
+void
+win_redraw(win, event)
+ windata *win;
+ XEvent *event;
+{
+ XExposeEvent *ev = &event->xexpose;
+ int x1, y1, x2, y2, i, j;
+
+ drawgrid(win);
+ if (ev) {
+ x1 = ev->x / (SQUARE_WIDTH + BORDER_WIDTH);
+ y1 = ev->y / (SQUARE_HEIGHT + BORDER_WIDTH);
+ x2 = (ev->x + ev->width) / (SQUARE_WIDTH + BORDER_WIDTH);
+ y2 = (ev->y + ev->height) / (SQUARE_HEIGHT + BORDER_WIDTH);
+ } else {
+ x1 = 0;
+ y1 = 0;
+ x2 = SIZE - 1;
+ y2 = SIZE - 1;
+ }
+
+ if (x1 < 0) x1 = 0;
+ if (y1 < 0) y1 = 0;
+ if (x2 < 0) x2 = 0;
+ if (y2 < 0) y2 = 0;
+ if (x1 > SIZE - 1) x1 = SIZE - 1;
+ if (y1 > SIZE - 1) y1 = SIZE - 1;
+ if (x2 > SIZE - 1) x2 = SIZE - 1;
+ if (y2 > SIZE - 1) y2 = SIZE - 1;
+
+ if (win->flipped) {
+ y1 = SIZE - y2 - 1;
+ y2 = SIZE - y1 - 1;
+ x1 = SIZE - x2 - 1;
+ x2 = SIZE - x1 - 1;
+ }
+
+ for (i = x1; i <= x2; i++)
+ for (j = y1; j <= y2; j++) {
+ if (chessboard->square[j][i].color == NONE)
+ win_erasepiece(j, i, WHITE);
+ else
+ win_drawpiece(&chessboard->square[j][i], j, i,
+ WHITE);
+ if (!oneboard) {
+ if (chessboard->square[j][i].color == NONE)
+ win_erasepiece(j, i, BLACK);
+ else
+ win_drawpiece(&chessboard->square[j][i],
+ j, i, BLACK);
+ }
+ }
+
+ return;
+}
+
+static bool
+setup(dispname, win)
+ char *dispname;
+ windata *win;
+{
+ char buf[BSIZE], *s;
+ Pixmap bm, bmask;
+ Cursor cur;
+ extern char *program, *recfile;
+
+
+ if (!(win->display = XOpenDisplay(dispname)))
+ return (false);
+
+
+ /* Now get boolean defaults... */
+ if ((s = XGetDefault(win->display, program, "noisy")) && eq(s, "on"))
+ noisyflag = true;
+ if ((s = XGetDefault(win->display, program, "savemoves")) && eq(s, "on"))
+ saveflag = true;
+ if ((s = XGetDefault(win->display, program, "algebraic")) && eq(s, "on"))
+ record_english = false;
+ if ((s = XGetDefault(win->display, program, "blackandwhite")) && eq(s, "on"))
+ bnwflag = true;
+ if ((s = XGetDefault(win->display, program, "quickrestore")) && eq(s, "on"))
+ quickflag = true;
+ if ((s = XGetDefault(win->display, program, "flash")) && eq(s, "on"))
+ win_flashmove = true;
+
+ /* ... numeric variables ... */
+ if (s = XGetDefault(win->display, program, "numflashes"))
+ num_flashes = atoi(s);
+ if (s = XGetDefault(win->display, program, "flashsize"))
+ flash_size = atoi(s);
+
+ /* ... and strings. */
+ if (s = XGetDefault(win->display, program, "progname"))
+ progname = s;
+ if (s = XGetDefault(win->display, program, "proghost"))
+ proghost = s;
+ if (s = XGetDefault(win->display, program, "recordfile"))
+ recfile = s;
+ if (s = XGetDefault(win->display, program, "blackpiece"))
+ black_piece_color = s;
+ if (s = XGetDefault(win->display, program, "whitepiece"))
+ white_piece_color = s;
+ if (s = XGetDefault(win->display, program, "blacksquare"))
+ black_square_color = s;
+ if (s = XGetDefault(win->display, program, "whitesquare"))
+ white_square_color = s;
+ if (s = XGetDefault(win->display, program, "bordercolor"))
+ border_color = s;
+ if (s = XGetDefault(win->display, program, "textcolor"))
+ text_color = s;
+ if (s = XGetDefault(win->display, program, "textback"))
+ text_back = s;
+ if (s = XGetDefault(win->display, program, "errortext"))
+ error_text = s;
+ if (s = XGetDefault(win->display, program, "playertext"))
+ player_text = s;
+ if (s = XGetDefault(win->display, program, "cursorcolor"))
+ cursor_color = s;
+
+ if ((DisplayPlanes(win->display, 0) == 1) || bnwflag)
+ win->bnw = true;
+
+ /* Allocate colors... */
+ if (win->bnw) {
+ win->blackpiece.pixel = BlackPixel (win->display, 0);
+ win->whitepiece.pixel = WhitePixel (win->display, 0);
+ win->blacksquare.pixel = BlackPixel (win->display, 0);
+ win->whitesquare.pixel = WhitePixel (win->display, 0);
+ win->border.pixel = BlackPixel (win->display, 0);
+ win->textcolor.pixel = BlackPixel (win->display, 0);
+ win->textback.pixel = WhitePixel (win->display, 0);
+ win->playertext.pixel = BlackPixel (win->display, 0);
+ win->errortext.pixel = BlackPixel (win->display, 0);
+ win->cursorcolor.pixel = BlackPixel (win->display, 0) ;
+ } else {
+ if (!XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ black_piece_color, &win->blackpiece) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ white_piece_color, &win->whitepiece) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ black_square_color, &win->blacksquare) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ white_square_color, &win->whitesquare) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ border_color, &win->border) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ text_color, &win->textcolor) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ text_back, &win->textback) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ error_text, &win->errortext) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ player_text, &win->playertext) ||
+ !XParseColor(win->display,
+ DefaultColormap(win->display, 0),
+ cursor_color, &win->cursorcolor) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->blackpiece) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->whitepiece) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->blacksquare) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->whitesquare) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->border) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->textcolor) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->textback) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->errortext) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->playertext) ||
+ !XAllocColor(win->display,
+ DefaultColormap(win->display, 0),
+ &win->cursorcolor))
+ fprintf(stderr, "Can't get color...\n");
+ }
+
+ /* Get fonts... */
+ win->small = XLoadQueryFont(win->display,SMALL_FONT);
+ win->medium = XLoadQueryFont(win->display,MEDIUM_FONT);
+ win->large = XLoadQueryFont(win->display,LARGE_FONT);
+
+ /* Create the windows... */
+
+ win->basewin =
+ XCreateSimpleWindow(win->display,DefaultRootWindow(win->display),
+ BASE_XPOS, BASE_YPOS,
+ BASE_WIDTH, BASE_HEIGHT, 0,
+ BlackPixel(win->display, 0),
+ WhitePixel(win->display, 0));
+ win->boardwin = XCreateSimpleWindow(win->display,win->basewin,
+ BOARD_XPOS, BOARD_YPOS,
+ BOARD_WIDTH, BOARD_HEIGHT,
+ BORDER_WIDTH,
+ win->border.pixel,
+ WhitePixel(win->display, 0));
+ win->recwin = XCreateSimpleWindow(win->display,win->basewin,
+ RECORD_XPOS, RECORD_YPOS,
+ RECORD_WIDTH, RECORD_HEIGHT,
+ BORDER_WIDTH, win->border.pixel,
+ win->textback.pixel);
+ win->jailwin = XCreateSimpleWindow(win->display,win->basewin,
+ JAIL_XPOS, JAIL_YPOS,
+ JAIL_WIDTH, JAIL_HEIGHT,
+ BORDER_WIDTH,
+ win->border.pixel,
+ win->textback.pixel);
+ win->wclockwin = XCreateSimpleWindow(win->display,win->basewin,
+ WCLOCK_XPOS, WCLOCK_YPOS,
+ CLOCK_WIDTH, CLOCK_HEIGHT,
+ BORDER_WIDTH, win->border.pixel,
+ win->textback.pixel);
+ win->bclockwin = XCreateSimpleWindow(win->display,win->basewin,
+ BCLOCK_XPOS, BCLOCK_YPOS,
+ CLOCK_WIDTH, CLOCK_HEIGHT,
+ BORDER_WIDTH, win->border.pixel,
+ win->textback.pixel);
+ win->messagewin = XCreateSimpleWindow(win->display,win->basewin,
+ MESS_XPOS, MESS_YPOS,
+ MESS_WIDTH, MESS_HEIGHT,
+ BORDER_WIDTH, win->border.pixel,
+ win->textback.pixel);
+ win->buttonwin = XCreateSimpleWindow(win->display,win->basewin,
+ BUTTON_XPOS, BUTTON_YPOS,
+ BUTTON_WIDTH, BUTTON_HEIGHT,
+ BORDER_WIDTH, win->border.pixel,
+ win->textback.pixel);
+
+ /* Let's define an icon... */
+ win->iconpixmap = XCreatePixmapFromBitmapData(win->display,
+ win->basewin, icon_bits,
+ icon_width, icon_height,
+ win->blacksquare.pixel,
+ win->whitesquare.pixel,
+ 1);
+
+ bm = XCreateBitmapFromData(win->display,
+ win->basewin, xchess_bits,
+ xchess_width, xchess_height);
+ bmask = XCreateBitmapFromData(win->display,
+ win->basewin, xchess_mask_bits,
+ xchess_width, xchess_height);
+ cur = XCreatePixmapCursor(win->display, bm, bmask,
+ &win->cursorcolor,
+ &WhitePixel(win->display, 0),
+ xchess_x_hot, xchess_y_hot);
+ XFreePixmap(win->display, bm);
+ XFreePixmap(win->display, bmask);
+
+ XDefineCursor(win->display,win->basewin, cur);
+
+ XMapSubwindows(win->display,win->basewin);
+ XMapRaised(win->display,win->basewin);
+
+ XSelectInput(win->display,win->basewin, KeyPressMask);
+ XSelectInput(win->display,win->boardwin,
+ ButtonPressMask | ButtonReleaseMask | ExposureMask);
+ XSelectInput(win->display,win->recwin,
+ ButtonReleaseMask | ExposureMask);
+ XSelectInput(win->display,win->jailwin, ExposureMask);
+ XSelectInput(win->display,win->wclockwin, ExposureMask);
+ XSelectInput(win->display,win->bclockwin, ExposureMask);
+ XSelectInput(win->display,win->messagewin,
+ ButtonReleaseMask | ExposureMask);
+ XSelectInput(win->display,win->buttonwin,
+ ButtonPressMask | ExposureMask);
+
+ message_init(win);
+ record_init(win);
+ button_draw(win);
+ jail_init(win);
+ clock_init(win, WHITE);
+ clock_init(win, BLACK);
+ if (timeunit) {
+ if (timeunit > 1800)
+ sprintf(buf, "%d moves every %.2lg hours.\n",
+ movesperunit, ((double) timeunit) / 3600);
+ else if (timeunit > 30)
+ sprintf(buf, "%d moves every %.2lg minutes.\n",
+ movesperunit, ((double) timeunit) / 60);
+ else
+ sprintf(buf, "%d moves every %d seconds.\n",
+ movesperunit, timeunit);
+ message_add(win, buf, false);
+ }
+
+ return (true);
+}
+
+static void
+drawgrid(win)
+ windata *win;
+{
+ int i;
+ XGCValues gc;
+
+ gc.function = GXcopy;
+ gc.plane_mask = AllPlanes;
+ gc.foreground = win->border.pixel;
+ gc.line_width = 0;
+ gc.line_style = LineSolid;
+
+ XChangeGC(win->display,
+ DefaultGC(win->display, 0),
+ GCFunction | GCPlaneMask | GCForeground |
+ GCLineWidth | GCLineStyle, &gc);
+
+ /* Draw the lines... horizontal, */
+ for (i = 1; i < SIZE; i++)
+ XDrawLine(win->display, win->boardwin,
+ DefaultGC(win->display, 0), 0,
+ i * (SQUARE_WIDTH + BORDER_WIDTH) -
+ BORDER_WIDTH / 2,
+ SIZE * (SQUARE_WIDTH + BORDER_WIDTH),
+ i * (SQUARE_WIDTH + BORDER_WIDTH) -
+ BORDER_WIDTH / 2);
+
+ /* and vertical... */
+ for (i = 1; i < SIZE; i++)
+ XDrawLine(win->display, win->boardwin,
+ DefaultGC(win->display, 0),
+ i * (SQUARE_WIDTH + BORDER_WIDTH) -
+ BORDER_WIDTH / 2, 0,
+ i * (SQUARE_WIDTH + BORDER_WIDTH) -
+ BORDER_WIDTH / 2,
+ SIZE * (SQUARE_WIDTH + BORDER_WIDTH));
+ return;
+}
+
+void
+win_restart()
+{
+ win1->flipped = false;
+ win_redraw(win1, (XEvent *) NULL);
+ if (!oneboard) {
+ win2->flipped = true;
+ win_redraw(win2, (XEvent *) NULL);
+ }
+ return;
+}
+
+static void
+icon_refresh(win)
+ windata *win;
+{
+ XCopyArea(win->display, win->iconpixmap, win->icon,
+ DefaultGC(win->display, 0),
+ 0, 0, icon_width, icon_height, 0, 0);
+ return;
+}
+
diff --git a/gnu/games/chess/Xchess/xchess.1 b/gnu/games/chess/Xchess/xchess.1
new file mode 100644
index 000000000000..e6875136100c
--- /dev/null
+++ b/gnu/games/chess/Xchess/xchess.1
@@ -0,0 +1,217 @@
+
+.TH XCHESS 1 "14 Nov 1986" "X Version 10"
+.SH NAME
+xchess \- X chess display
+.SH SYNOPSIS
+.B xchess
+[ option ... ] [ white-display ] [ black-display ]
+.SH DESCRIPTION
+.PP
+.B xchess
+is a chess display program which allows players to play a game on either
+one or two displays, or play a chess-playing program. It uses the
+.B X
+window system. If one or no display names are given, it will open up one
+window and both black and white at the same board. If two displays are
+given,
+.B xchess
+will accept moves from each player in his turn. Black's board will be drawn
+with his pieces at the bottom.
+.PP
+.B xchess
+will not allow a player to make an illegal move. It accepts all legal moves,
+including castling and pawn capture \fIen passant\fR.
+.SH OPTIONS
+.TP 8
+.B -d
+Turn on debugging.
+.TP 8
+.B -f record-file
+Use \fBrecord-file\fR for saving the game when the \fBSave\fR button is
+selected, or if the \fB-s\fR flag is given. The default is "xchess.game".
+.TP 8
+.B -r saved-game
+Start with the position at the end of the saved game in the named file.
+This file may be the result of the \fBSave\fR command, and may be in
+either English or International format. When reading moves, one move
+it made per second.
+.TP 8
+.B -q
+Don't pause for a second every time a move is made when a game is being
+restored.
+.TP 8
+.B -v
+Whenever a piece is moved, outline the path with a "lightning bolt".
+This option and the \fB-n\fR option are useful if you don't want to miss
+an opponent's move when he makes it.
+.TP 8
+.B -i
+Use International format for recording moves (squares numbered 1-8, a-h)
+as opposed to English (e.g, \fIp/k4xp/q5\fR).
+.TP 8
+.B -t moves/timeunit
+Allows \fBtimeunit\fR seconds for every \fBmoves\fR moves. If either player
+exceeds this allowance both recieve a message saying informing them of
+this fact.
+.TP 8
+.B -c
+Play the computer.
+.B xchess
+will start up a chess-playing program (currently the only one it knows
+how to talk to is \fBGNU Chess\fR).
+.TP 8
+.B -p program
+The name of the program to use if the \fB-c\fR option is given. The
+default is "/usr/public/gnuchess". Note that \fBgnuchess\fR must be
+compiled with the \fIcompat\fR flag (in the file "main.c") set to 1.
+.TP 8
+.B -b
+If the \fB-c\fR flag was given, have the computer play white.
+.TP 8
+.B -bnw
+If the display has more than one display plane (i.e, is color), pretend
+it's black and white.
+.TP 8
+.B -s
+Save the moves in the record file as they are made. This is useful if
+you don't want your game to be lost when \fBxchess\fR core dumps.
+.TP 8
+.B -n
+Be noisy \- beep after every move is made.
+.TP 8
+.B -h host
+Run GNU Chess on the specified \fBhost\fR.
+.TP 8
+.B -R
+Randomly chose who plays white and who plays black, if two displays are
+given.
+.SH CONTROLS
+.PP
+The window is divided up into several sub-windows. The pieces are moved by
+pushing down any mouse button on top of the piece, moving to the destination
+square, and releasing it. Castling is done by moving the king to the
+right square. If you push down on a piece and then let the button
+up without moving it, you must move that piece. ("Touch it, move it.")
+.PP
+The progress of the game is listed in the "Game Record" window. Error
+messages and such things are printed in the "Message" window. Both these
+windows have scroll bars that you can use to move around.
+There are also windows for clocks and for a record of the pieces captured.
+.PP
+If you type any keys in the window, the text will go into the message
+window of both players. This provides a simple communication facility.
+.PP
+There are 9 buttons in the control window. They are as follows:
+.TP 8
+.B Draw
+Both players must push this button to agree on a draw (just one is ok
+if only one display is being used).
+.TP 8
+.B Resign
+The player whose turn it is to move resigns.
+.TP 8
+.B Reset
+Start over from the beginning.
+.TP 8
+.B Back
+Retract a move. If two displays are being used the other player will be
+asked to confirm this.
+.TP 8
+.B Fwd
+This will re-play the most recently retracted move. This button in conjunction
+with \fBBack\fR is useful for "scrolling around" in a saved game.
+.TP 8
+.B Save
+Save the game in the record file.
+.TP 8
+.B Flip
+Rotate the board so that Black will have his pieces at the bottom.
+.TP 8
+.B Switch
+Change the mapping of boards to players.
+.TP 8
+.B Pause
+This button has two functions. When a game is being restored, pieces will
+be moved once a second. Hitting \fBPause\fR will stop this process, and
+hitting it again will restart it. During the time that it is stopped no
+other action can be made except restarting it. While a game is being played,
+\fBPause\fR will stop the clock and restart it.
+.SH DEFAULTS
+.PP
+\fBxchess\fR uses the following \fI.Xdefaults\fR:
+.TP 8
+.B Noisy
+The -n flag.
+.TP 8
+.B SaveMoves
+The -s flag.
+.TP 8
+.B Algebraic
+The -i flag.
+.TP 8
+.B BlackAndWhite
+The -bnw flag.
+.TP 8
+.B QuickRestore
+The -q flag.
+.TP 8
+.B Flash
+The -v flag.
+.TP 8
+.B NumFlashes
+How many times to flash the move. The default is 5.
+.TP 8
+.B FlashWidth
+How big to make the lightning bolt. The default is 10 pixels.
+.TP 8
+.B ProgName
+The -p option. This may also be changed in the Makefile (-DDEF_PROG_NAME).
+.TP 8
+.B ProgHost
+The -h option.
+.TP 8
+.B RecordFile
+The -f option.
+.TP 8
+.B BlackPiece
+The color of the black pieces.
+.TP 8
+.B WhitePiece
+The color of the white pieces.
+.TP 8
+.B BorderColor
+The color of the borders.
+.TP 8
+.B BlackSquare
+The color of the black squares.
+.TP 8
+.B WhiteSquare
+The color of the white squares.
+.TP 8
+.B TextColor
+The color of routine messages and the move record text.
+.TP 8
+.B ErrorText
+The color of error messages.
+.TP 8
+.B PlayerText
+The color of player-entered text.
+.TP 8
+.B TextBack
+The background color for the two text windows.
+.TP 8
+.B CursorColor
+The color of the mouse and the text cursors.
+.SH "SEE ALSO"
+X(8), gnuchess(1), chess(5)
+.SH AUTHOR
+Wayne A. Christopher (faustus@ic.berkeley.edu)
+.SH BUGS
+.PP
+Checkmate and stalemate are not detected, so the appropriate player must resign
+or agree to a draw respectively.
+.PP
+\fBSwitch\fR doesn't work.
+.PP
+If you are playing \fBgnuchess\fR, and you select Undo a few times so that it
+is \fBgnuchess\fR's turn to move, it won't do anything.
diff --git a/gnu/games/chess/Xchess/xchess.c b/gnu/games/chess/Xchess/xchess.c
new file mode 100644
index 000000000000..6de6502ddd28
--- /dev/null
+++ b/gnu/games/chess/Xchess/xchess.c
@@ -0,0 +1,205 @@
+
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.2 $ on $Date: 89/04/28 08:44:02 $
+ * $Source: /usr/local/src/source/X.V11R3/contrib/games/xchess/Xchess/RCS/xchess.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ */
+
+#define USAGE "xchess [ -d ] [ -f recordfile ] [ -r savedfile ] [ -i ]\n\
+\t[ -t moves/timeunit ] [ -c ] [ -p program ] [ -b ] [ -bnw ] [ -s ]\n\
+\t[ -n ] [ -h host ] [ -v ] [ -R ] [ whitedisplay ] [ blackdisplay ]"
+
+#include <signal.h>
+#include "xchess.h"
+
+bool debug = false;
+bool oneboard = false;
+bool bnwflag = false;
+bool progflag = false;
+bool blackflag = false;
+bool quickflag = false;
+
+char *progname = DEF_PROGRAM;
+char *proghost = NULL;
+char *piecenames[] = { "pawn", "rook", "knight", "bishop", "queen", "king" } ;
+char *colornames[] = { "white", "black", "none" } ;
+char *movetypenames[] = { "move", "qcastle", "kcastle", "capture" } ;
+char *dispname1 = NULL, *dispname2 = NULL;
+
+char *black_piece_color = BLACK_PIECE_COLOR;
+char *white_piece_color = WHITE_PIECE_COLOR;
+char *black_square_color = BLACK_SQUARE_COLOR;
+char *white_square_color = WHITE_SQUARE_COLOR;
+char *border_color = BORDER_COLOR;
+char *text_color = TEXT_COLOR;
+char *text_back = TEXT_BACK;
+char *error_text = ERROR_TEXT;
+char *player_text = PLAYER_TEXT;
+char *cursor_color = CURSOR_COLOR;
+
+int num_flashes = NUM_FLASHES;
+int flash_size = FLASH_SIZE;
+char *program;
+char *recfile = NULL;
+
+#ifdef notdef
+/*
+ * Serves no purpose.
+ */
+die () {
+fprintf(stderr, "child proc changed status?!\n");
+}
+#endif
+
+void
+main(ac, av)
+ char **av;
+{
+ bool randflag = false;
+ move *m;
+ char *s;
+
+ program = av[0];
+
+#ifdef notdef
+ signal(SIGCHLD, die);
+#endif
+
+ /* Process args. */
+ av++; ac--;
+ while (ac > 0 && **av == '-') {
+ if (eq(*av, "-d")) {
+ debug = true;
+ } else if (eq(*av, "-f")) {
+ av++; ac--;
+ if (*av)
+ record_file = *av;
+ else
+ goto usage;
+ } else if (eq(*av, "-r")) {
+ av++; ac--;
+ if (*av)
+ recfile = *av;
+ else
+ goto usage;
+ } else if (eq(*av, "-i")) {
+ record_english = false;
+ } else if (eq(*av, "-R")) {
+ randflag = true;
+ } else if (eq(*av, "-v")) {
+ win_flashmove = true;
+ } else if (eq(*av, "-q")) {
+ quickflag = true;
+ } else if (eq(*av, "-t")) {
+ av++; ac--;
+ if (*av) {
+ movesperunit = atoi(*av);
+ if (s = index(*av, '/'))
+ timeunit = atoi(s + 1) * 60;
+ else
+ timeunit = 60;
+ } else
+ goto usage;
+ } else if (eq(*av, "-p")) {
+ av++; ac--;
+ if (*av)
+ progname = *av;
+ else
+ goto usage;
+ } else if (eq(*av, "-h")) {
+ av++; ac--;
+ if (*av)
+ proghost = *av;
+ else
+ goto usage;
+ } else if (eq(*av, "-b")) {
+ blackflag = true;
+ } else if (eq(*av, "-c")) {
+ progflag = true;
+ } else if (eq(*av, "-bnw")) {
+ bnwflag = true;
+ } else if (eq(*av, "-s")) {
+ saveflag = true;
+ } else if (eq(*av, "-n")) {
+ noisyflag = true;
+ } else
+ goto usage;
+ av++; ac--;
+ }
+ if (ac > 0)
+ dispname1 = av[0];
+ if (ac > 1)
+ dispname2 = av[1];
+ if (ac > 2)
+ goto usage;
+
+ if (!dispname2)
+ oneboard = true;
+
+ srandom(getpid());
+
+ if (!oneboard && randflag && (random() % 2)) {
+ s = dispname1;
+ dispname1 = dispname2;
+ dispname2 = s;
+ }
+
+ if (!dispname1)
+ dispname1 = getenv("DISPLAY");
+
+ /* Set up the board. */
+ board_setup();
+
+ /* Create the windows. */
+ win_setup(dispname1, dispname2);
+
+ board_drawall();
+
+ /* Start the program if necessary. */
+ if (progflag)
+ if (!program_init(progname))
+ exit(1);
+
+ if (recfile)
+ load_game(recfile);
+
+ /* Go into a loop of prompting players alternately for moves, checking
+ * them, and updating things.
+ */
+ for (;;) {
+ win_process(false);
+ clock_update();
+ if (progflag && ((!blackflag && (nexttomove == BLACK)) ||
+ (blackflag && (nexttomove == WHITE)))) {
+ m = program_get();
+ if (m)
+ prog_move(m);
+ }
+ }
+
+usage: fprintf(stderr, "Usage: %s\n", USAGE);
+ exit(1);
+}
+
diff --git a/gnu/games/chess/Xchess/xchess.c.150 b/gnu/games/chess/Xchess/xchess.c.150
new file mode 100644
index 000000000000..2c17906c3571
--- /dev/null
+++ b/gnu/games/chess/Xchess/xchess.c.150
@@ -0,0 +1,197 @@
+
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.5 $ on $Date: 86/11/26 12:11:32 $
+ * $Source: /users/faustus/xchess/RCS/xchess.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ */
+
+#define USAGE "xchess [ -d ] [ -f recordfile ] [ -r savedfile ] [ -i ]\n\
+\t[ -t moves/timeunit ] [ -c ] [ -p program ] [ -b ] [ -bnw ] [ -s ]\n\
+\t[ -n ] [ -h host ] [ -v ] [ -R ] [ whitedisplay ] [ blackdisplay ]"
+
+#include <signal.h>
+#include "xchess.h"
+
+bool debug = false;
+bool oneboard = false;
+bool bnwflag = false;
+bool progflag = false;
+bool blackflag = false;
+bool quickflag = false;
+
+char *progname = DEF_PROGRAM;
+char *proghost = NULL;
+char *piecenames[] = { "pawn", "rook", "knight", "bishop", "queen", "king" } ;
+char *colornames[] = { "white", "black", "none" } ;
+char *movetypenames[] = { "move", "qcastle", "kcastle", "capture" } ;
+char *dispname1 = NULL, *dispname2 = NULL;
+
+char *black_piece_color = BLACK_PIECE_COLOR;
+char *white_piece_color = WHITE_PIECE_COLOR;
+char *black_square_color = BLACK_SQUARE_COLOR;
+char *white_square_color = WHITE_SQUARE_COLOR;
+char *border_color = BORDER_COLOR;
+char *text_color = TEXT_COLOR;
+char *text_back = TEXT_BACK;
+char *error_text = ERROR_TEXT;
+char *player_text = PLAYER_TEXT;
+char *cursor_color = CURSOR_COLOR;
+
+int num_flashes = NUM_FLASHES;
+int flash_size = FLASH_SIZE;
+char *program;
+char *recfile = NULL;
+
+die () {
+fprintf(stderr, "child proc changed status?!\n");
+}
+
+void
+main(ac, av)
+ char **av;
+{
+ bool randflag = false;
+ move *m;
+ char *s;
+
+ program = av[0];
+
+ signal(SIGCHLD, die);
+ /* Process args. */
+ av++; ac--;
+ while (ac > 0 && **av == '-') {
+ if (eq(*av, "-d")) {
+ debug = true;
+ } else if (eq(*av, "-f")) {
+ av++; ac--;
+ if (*av)
+ record_file = *av;
+ else
+ goto usage;
+ } else if (eq(*av, "-r")) {
+ av++; ac--;
+ if (*av)
+ recfile = *av;
+ else
+ goto usage;
+ } else if (eq(*av, "-i")) {
+ record_english = false;
+ } else if (eq(*av, "-R")) {
+ randflag = true;
+ } else if (eq(*av, "-v")) {
+ win_flashmove = true;
+ } else if (eq(*av, "-q")) {
+ quickflag = true;
+ } else if (eq(*av, "-t")) {
+ av++; ac--;
+ if (*av) {
+ movesperunit = atoi(*av);
+ if (s = index(*av, '/'))
+ timeunit = atoi(s + 1) * 60;
+ else
+ timeunit = 60;
+ } else
+ goto usage;
+ } else if (eq(*av, "-p")) {
+ av++; ac--;
+ if (*av)
+ progname = *av;
+ else
+ goto usage;
+ } else if (eq(*av, "-h")) {
+ av++; ac--;
+ if (*av)
+ proghost = *av;
+ else
+ goto usage;
+ } else if (eq(*av, "-b")) {
+ blackflag = true;
+ } else if (eq(*av, "-c")) {
+ progflag = true;
+ } else if (eq(*av, "-bnw")) {
+ bnwflag = true;
+ } else if (eq(*av, "-s")) {
+ saveflag = true;
+ } else if (eq(*av, "-n")) {
+ noisyflag = true;
+ } else
+ goto usage;
+ av++; ac--;
+ }
+ if (ac > 0)
+ dispname1 = av[0];
+ if (ac > 1)
+ dispname2 = av[1];
+ if (ac > 2)
+ goto usage;
+
+ if (!dispname2)
+ oneboard = true;
+
+ srandom(getpid());
+
+ if (!oneboard && randflag && (random() % 2)) {
+ s = dispname1;
+ dispname1 = dispname2;
+ dispname2 = s;
+ }
+
+ if (!dispname1)
+ dispname1 = getenv("DISPLAY");
+
+ /* Set up the board. */
+ board_setup();
+
+ /* Create the windows. */
+ win_setup(dispname1, dispname2);
+
+ board_drawall();
+
+ /* Start the program if necessary. */
+ if (progflag)
+ if (!program_init(progname))
+ exit(1);
+
+ if (recfile)
+ load_game(recfile);
+
+ /* Go into a loop of prompting players alternately for moves, checking
+ * them, and updating things.
+ */
+ for (;;) {
+ win_process(false);
+ clock_update();
+ if (progflag && ((!blackflag && (nexttomove == BLACK)) ||
+ (blackflag && (nexttomove == WHITE)))) {
+ m = program_get();
+ if (m)
+ prog_move(m);
+ }
+ }
+
+usage: fprintf(stderr, "Usage: %s\n", USAGE);
+ exit(1);
+}
+
diff --git a/gnu/games/chess/Xchess/xchess.cur b/gnu/games/chess/Xchess/xchess.cur
new file mode 100644
index 000000000000..ef3750dbdd7f
--- /dev/null
+++ b/gnu/games/chess/Xchess/xchess.cur
@@ -0,0 +1,9 @@
+
+#define xchess_width 16
+#define xchess_height 16
+#define xchess_x_hot 9
+#define xchess_y_hot 8
+static char xchess_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0xf8, 0x00, 0xfe, 0x80, 0xff,
+ 0xc0, 0xff, 0x60, 0xff, 0xb0, 0xfd, 0xd8, 0x66, 0x6c, 0x3b, 0x76, 0x1d,
+ 0x98, 0x1d, 0xcc, 0x0c, 0x60, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/Xchess/xchess.game b/gnu/games/chess/Xchess/xchess.game
new file mode 100644
index 000000000000..2302334080c7
--- /dev/null
+++ b/gnu/games/chess/Xchess/xchess.game
@@ -0,0 +1,8 @@
+
+X Chess -- Sun Sep 18 18:01:17 EDT 1988
+ Game played on pitcairn:0
+ english
+ 1. P/kb2-kb4 P/k2-k3
+ 2. P/k2-k4
+Draw agreed.
+Time: white: 6s, black: 43s
diff --git a/gnu/games/chess/Xchess/xchess.h b/gnu/games/chess/Xchess/xchess.h
new file mode 100644
index 000000000000..355731d8b403
--- /dev/null
+++ b/gnu/games/chess/Xchess/xchess.h
@@ -0,0 +1,301 @@
+
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.5 $ on $Date: 86/11/26 12:11:39 $
+ * $Source: /users/faustus/xchess/RCS/xchess.h,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ *
+ * Definitions for the X chess program.
+ */
+
+#include "std.h"
+#include <X11/Xlib.h>
+#include "scrollText/scrollText.h"
+
+#define SIZE 8
+
+typedef enum piecetype { PAWN, ROOK, KNIGHT, BISHOP, QUEEN, KING } piecetype;
+typedef enum movetype { MOVE, QCASTLE, KCASTLE, CAPTURE } movetype;
+typedef enum color { WHITE, BLACK, NONE } color;
+
+typedef struct piece {
+ enum piecetype type;
+ enum color color;
+} piece;
+
+/* The board has y=0 and black at the top... This probably isn't the best
+ * place to keep track of who can castle, but it's part of the game state...
+ */
+
+typedef struct board {
+ piece square[SIZE][SIZE];
+ bool white_cant_castle_k;
+ bool white_cant_castle_q;
+ bool black_cant_castle_k;
+ bool black_cant_castle_q;
+} board;
+
+typedef struct move {
+ movetype type;
+ piece piece;
+ piece taken;
+ int fromx, fromy;
+ int tox, toy;
+ struct move *next;
+ bool enpassant;
+ bool check;
+} move;
+
+#define iswhite(win, i, j) (!(((i) + (j)) % 2))
+
+/* Stuff for the display. */
+
+typedef struct windata {
+ Display *display;
+ Window basewin;
+ Window boardwin;
+ Window recwin;
+ Window wclockwin;
+ Window bclockwin;
+ Window messagewin;
+ Window buttonwin;
+ Window jailwin;
+ Window icon;
+ Pixmap iconpixmap;
+ XColor blackpiece;
+ XColor whitepiece;
+ XColor blacksquare;
+ XColor whitesquare;
+ XColor border;
+ XColor textcolor;
+ XColor textback;
+ XColor errortext;
+ XColor playertext;
+ XColor cursorcolor;
+ XFontStruct *small;
+ XFontStruct *medium;
+ XFontStruct *large;
+ bool bnw;
+ color color;
+ bool flipped;
+ double whitehands[3];
+ double blackhands[3];
+ char *txtassoc;
+} windata;
+
+#define SMALL_FONT "6x10"
+#define MEDIUM_FONT "8x13"
+#define LARGE_FONT "9x15"
+#define JAIL_FONT "6x10"
+
+#define SQUARE_WIDTH 80
+#define SQUARE_HEIGHT 80
+
+#define BORDER_WIDTH 3
+
+#define BOARD_WIDTH 8 * SQUARE_WIDTH + 7 * BORDER_WIDTH
+#define BOARD_HEIGHT 8 * SQUARE_HEIGHT + 7 * BORDER_WIDTH
+#define BOARD_XPOS 0
+#define BOARD_YPOS 0
+
+#define RECORD_WIDTH 265 /* 40 chars * 6 pixels / character. */
+#define RECORD_HEIGHT 433
+#define RECORD_XPOS BOARD_WIDTH + BORDER_WIDTH
+#define RECORD_YPOS 0
+
+#define JAIL_WIDTH RECORD_WIDTH
+#define JAIL_HEIGHT 163
+#define JAIL_XPOS RECORD_XPOS
+#define JAIL_YPOS RECORD_YPOS + RECORD_HEIGHT + BORDER_WIDTH
+
+#define CLOCK_WIDTH 131
+#define CLOCK_HEIGHT 131 + BORDER_WIDTH + 20
+#define WCLOCK_XPOS RECORD_XPOS
+#define WCLOCK_YPOS RECORD_HEIGHT + JAIL_HEIGHT + BORDER_WIDTH * 2
+#define BCLOCK_XPOS WCLOCK_XPOS + CLOCK_WIDTH + BORDER_WIDTH
+#define BCLOCK_YPOS WCLOCK_YPOS
+
+#define MESS_WIDTH 329
+#define MESS_HEIGHT 92
+#define MESS_XPOS 0
+#define MESS_YPOS BOARD_HEIGHT + BORDER_WIDTH
+
+#define BUTTON_WIDTH MESS_WIDTH
+#define BUTTON_HEIGHT MESS_HEIGHT
+#define BUTTON_XPOS MESS_WIDTH + BORDER_WIDTH
+#define BUTTON_YPOS MESS_YPOS
+
+#define BASE_WIDTH BOARD_WIDTH + RECORD_WIDTH + BORDER_WIDTH * 3
+#define BASE_HEIGHT BOARD_HEIGHT + MESS_HEIGHT + BORDER_WIDTH * 3
+
+#define BASE_XPOS 50
+#define BASE_YPOS 50
+
+#define BLACK_PIECE_COLOR "#202020"
+#define WHITE_PIECE_COLOR "#FFFFCC"
+#define BLACK_SQUARE_COLOR "#77A26D"
+#define WHITE_SQUARE_COLOR "#C8C365"
+#define BORDER_COLOR "#902E39"
+#define TEXT_COLOR "#006D6D"
+#define TEXT_BACK "#FFFFDD"
+#define ERROR_TEXT "Red"
+#define PLAYER_TEXT "Blue"
+#define CURSOR_COLOR "#FF606F"
+
+#define DEF_RECORD_FILE "xchess.game"
+
+#define NUM_FLASHES 5
+#define FLASH_SIZE 10
+
+/* xchess.c */
+
+extern void main();
+extern bool debug;
+extern char *progname;
+extern char *proghost;
+extern char *piecenames[];
+extern char *colornames[];
+extern char *movetypenames[];
+extern char *dispname1, *dispname2;
+extern bool oneboard;
+extern bool bnwflag;
+extern bool progflag;
+extern bool blackflag;
+extern bool quickflag;
+extern int num_flashes;
+extern int flash_size;
+extern char *black_piece_color;
+extern char *white_piece_color;
+extern char *black_square_color;
+extern char *white_square_color;
+extern char *border_color;
+extern char *text_color;
+extern char *text_back;
+extern char *error_text;
+extern char *player_text;
+extern char *cursor_color;
+
+/* board.c */
+
+extern void board_setup();
+extern void board_drawall();
+extern void board_move();
+extern board *chessboard;
+extern void board_init();
+
+/* window.c */
+
+extern bool win_setup();
+extern void win_redraw();
+extern void win_restart();
+extern void win_drawboard();
+extern void win_drawpiece();
+extern void win_erasepiece();
+extern void win_process();
+extern void win_flash();
+extern windata *win1, *win2;
+extern bool win_flashmove;
+
+/* control.c */
+
+extern void button_pressed();
+extern void button_released();
+extern void move_piece();
+extern void prog_move();
+extern move *moves;
+extern move *foremoves;
+extern color nexttomove;
+extern void replay();
+extern void forward();
+extern void cleanup();
+extern void restart();
+extern bool noisyflag;
+
+/* valid.c */
+
+extern bool valid_move();
+
+/* record.c */
+
+extern void record_move();
+extern void record_reset();
+extern void record_save();
+extern void record_back();
+extern void record_init();
+extern void record_end();
+extern bool record_english;
+extern char *record_file;
+extern int movenum;
+extern bool saveflag;
+
+/* message.c */
+
+extern void message_init();
+extern void message_add();
+extern void message_send();
+
+/* clock.c */
+
+extern void clock_init();
+extern void clock_draw();
+extern void clock_update();
+extern void clock_switch();
+extern bool clock_started;
+extern int movesperunit;
+extern int timeunit;
+extern int whiteseconds;
+extern int blackseconds;
+
+/* button.c */
+
+extern void button_draw();
+extern void button_service();
+
+/* jail.c */
+
+extern void jail_init();
+extern void jail_draw();
+extern void jail_add();
+extern void jail_remove();
+
+/* program.c */
+extern bool program_init();
+extern void program_end();
+extern void program_send();
+extern void program_undo();
+extern move *program_get();
+
+/* parse.c */
+
+extern void load_game();
+extern move *parse_file();
+extern move *parse_move();
+extern move *parse_imove();
+extern bool loading_flag;
+extern bool loading_paused;
+
+/* popup.c */
+
+extern bool pop_question();
+
diff --git a/gnu/games/chess/Xchess/xchess.icon b/gnu/games/chess/Xchess/xchess.icon
new file mode 100644
index 000000000000..78c68f1ba46b
--- /dev/null
+++ b/gnu/games/chess/Xchess/xchess.icon
@@ -0,0 +1,28 @@
+
+#define icon_width 48
+#define icon_height 48
+static char icon_bits[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0xc1, 0xff, 0xff, 0xff, 0xff, 0x83, 0x41, 0x00, 0x00, 0x00, 0x00, 0x82,
+ 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82,
+ 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82,
+ 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82,
+ 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82,
+ 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82,
+ 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82,
+ 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82,
+ 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82,
+ 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82,
+ 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82,
+ 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82,
+ 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82,
+ 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82,
+ 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82,
+ 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82,
+ 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82,
+ 0x41, 0x00, 0x00, 0x00, 0x00, 0x82, 0xc1, 0xff, 0xff, 0xff, 0xff, 0x83,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, 0xc4, 0x89, 0x3c, 0xcf, 0x83,
+ 0x41, 0x24, 0x88, 0x04, 0x41, 0x80, 0x81, 0x22, 0x88, 0x04, 0x41, 0x80,
+ 0x01, 0x21, 0xf8, 0x1c, 0xcf, 0x83, 0x81, 0x22, 0x88, 0x04, 0x08, 0x82,
+ 0x41, 0x24, 0x88, 0x04, 0x08, 0x82, 0x41, 0xc4, 0x89, 0x3c, 0xcf, 0x83,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
diff --git a/gnu/games/chess/Xchess/xchess_mask.cur b/gnu/games/chess/Xchess/xchess_mask.cur
new file mode 100644
index 000000000000..6408b7e0b915
--- /dev/null
+++ b/gnu/games/chess/Xchess/xchess_mask.cur
@@ -0,0 +1,7 @@
+
+#define xchess_mask_width 16
+#define xchess_mask_height 16
+static char xchess_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0xf8, 0x00, 0xfe, 0x80, 0xff,
+ 0xc0, 0xff, 0x60, 0xff, 0xb0, 0xfd, 0xd8, 0x66, 0x6c, 0x3b, 0x76, 0x1d,
+ 0x98, 0x1d, 0xcc, 0x0c, 0x60, 0x00, 0x00, 0x00};
diff --git a/gnu/games/chess/gnuchess.book b/gnu/games/chess/gnuchess.book
new file mode 100644
index 000000000000..7e8a3b5d756e
--- /dev/null
+++ b/gnu/games/chess/gnuchess.book
@@ -0,0 +1,3878 @@
+!
+! Opening Library for CHESS
+!
+! Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
+! Copyright (c) 1987 by Stuart Cracraft and John Stanback
+!
+! This file is part of CHESS.
+!
+! CHESS is distributed in the hope that it will be useful,
+! but WITHOUT ANY WARRANTY. No author or distributor
+! accepts responsibility to anyone for the consequences of using it
+! or for whether it serves any particular purpose or works at all,
+! unless he says so in writing. Refer to the CHESS General Public
+! License for full details.
+!
+! Everyone is granted permission to copy, modify and redistribute
+! CHESS, but only under the conditions described in the
+! CHESS General Public License. A copy of this license is
+! supposed to have been given to you along with CHESS so you
+! can know your rights and responsibilities. It should be in a
+! file named COPYING. Among other things, the copyright notice
+! and this notice must be preserved on all copies.
+!
+!
+!
+! Four Knight's Game
+e2e4 e7e5
+g1f3 b8c6
+b1c3 g8f6
+f1b5 f8b4
+o-o o-o
+d2d3 b4c3
+b2c3 d7d6
+c1g5 d8e7
+f1e1 c6d8
+d3d4 d8e6
+! Giuoco Piano
+e2e4 e7e5
+g1f3 b8c6
+f1c4 f8c5
+d2d3 g8f6
+b1c3 d7d6
+c1g5 h7h6
+g5f6 d8f6
+c3d5 f6d8
+! Two Knights Defence
+e2e4 e7e5
+g1f3 b8c6
+f1c4 g8f6
+f3g5 d7d5
+e4d5 c6a5
+c4b5 c7c6
+d5c6 b7c6
+b5e2 h7h6
+! Two Knights Defence -- Max Lange Attack
+e2e4 e7e5
+g1f3 b8c6
+f1c4 g8f6
+d2d4 e5d4
+o-o f8c5
+e4e5 d7d5
+e5f6 d5c4
+f6g7 h8g8
+! Petrov's Defence
+e2e4 e7e5
+g1f3 g8f6
+f3e5 d7d6
+e5f3 f6e4
+d2d4 d6d5
+f1d3 f8d6
+o-o o-o
+c2c4 c8g4
+c4d5 f7f5
+b1c3 b8d7
+! Petrov's Defence
+e2e4 e7e5
+g1f3 g8f6
+d2d4 e5d4
+e4e5 f6e4
+d1d4 d7d5
+!
+! Vienna Game
+e2e4 e7e5
+b1c3 f8c5
+g1f3 d7d6
+d2d4 e5d4
+f3d4 g8f6
+c1g5 h7h6
+g5h4 b1c3
+!
+e2e4 e7e5
+b1c3 b8c6
+g1f3 g7g6
+d2d4 e5d4
+c3d5 f8g7
+c1g5 c6e7
+f3d4 c7c6
+d5c3 h7h6
+! - - - - - -
+! ECO C25/1-2
+e2e4 e7e5
+b1c3 f8c5
+f1c4 d7d6
+d2d3 c8e6
+c4e6 f7f6
+d1h5 e7d7
+c1e3 c5b6
+g1e2 b8c6
+o-o g8f6
+h5h3 d8e8
+!
+e2e4 e7e5
+b1c3 f8c5
+g1f3 d7d6
+d2d4 e5d4
+f3d4 g8f6
+c1g5 h7h6
+g5h4 b8c6
+d4c6 b7c6
+f1d3 e8e7
+o-o g7g5
+! ECO C25/3-9
+e2e4 e7e5
+b1c3 b8c6
+f2f4 e5f4
+g1f3 g7g5
+h2h4 g5g4
+f3g5 h7h6
+g5f7 e7f7
+d2d4 d7d5
+c1f4 f8b4
+f1e2 b4c3
+b2c3 g8f6
+!
+e2e4 e7e5
+b1c3 b8c6
+f2f4 e5f4
+g1f3 g7g5
+d2d4 g5g4
+f1c4 g4f3
+o-o d7d5
+e4d5 c8g4
+d1d2 c6e7
+d2f4 g8h6
+!
+e2e4 e7e5
+b1c3 b8c6
+f2f4 e5f4
+d2d4 d8h4
+e1e2 d7d5
+e4d5 c8g4
+g1f3 o-o-o
+d5c6 f8c5
+d1e1 h4h5
+c6b7 e8b8
+e2d2 g4f3
+!
+e2e4 e7e5
+b1c3 b8c6
+f2f4 e5f4
+d2d4 d8h4
+e1e2 d7d6
+g1f3 c8g4
+c1f4 o-o-o
+e2e3 h4h5
+f1e2 g7g5
+f3g5 f7f5
+h2h3 g4e2
+!
+e2e4 e7e5
+b1c3 b8c6
+g2g3 f8c5
+f1g2 a7a6
+g1e2 d7d6
+d1d3 c8g4
+h2h3 g4e6
+o-o g8e7
+c3d5 o-o
+c2c3 c5a7
+g1h2 f7f6
+!
+e2e4 e7e5
+b1c3 b8c6
+g2g3 f8c5
+f1g2 d7d6
+c3a4 g8e7
+a4c5 d6c5
+d2d3 o-o
+g2e3 b7b6
+d1d2 c8e6
+g1e2 d8d7
+o-o a8d8
+!
+e2e4 e7e5
+b1c3 b8c6
+f1c4 f8c5
+d1g4 g7g6
+d4f3 g8f6
+g1e2 d7d6
+d2d3 c8g4
+f3g3 h7h6
+f2f4 d7e7
+c3d5 f6d5
+g3g4 d5e3
+! ECO C26/1-10
+e2e4 e7e5
+b1c3 g8f6
+g2g3 c7c6
+f1g2 d7d6
+g1e2 b7b5
+o-o b8d7
+h2h3 d8c7
+g3g4 b5b4
+c3b1 a7a5
+a2a3 c8a6
+a3b4 a5b4
+!
+e2e4 e7e5
+b1c3 g8f6
+g2g3 d7d5
+e4d5 f6d5
+f1g2 c8e6
+g1f3 b8c6
+o-o f8e7
+f1e1 e7f6
+c3e4 o-o
+d2d3 f6e7
+a2a3 d5b6
+!
+e2e4 e7e5
+b1c3 g8f6
+g2g3 d7d5
+e4d5 f6d5
+f1g2 d5c3
+b2c3 f8d6
+g1f3 o-o
+o-o b8d7
+d2d3 a1b8
+a2a4 b7b6
+a4a5 c8b7
+!
+e2e4 e7e5
+b1c3 g8f6
+g2g3 f8b4
+f1g2 c7c6
+g1e2 o-o
+o-o d7d5
+e4d5 c6d5
+d2d4 e5d4
+e2d4 b8c6
+c1g5 b4e7
+f1e1 h7h6
+!
+e2e4 e7e5
+b1c3 g8f6
+g2g3 f8c5
+f1g2 b8c6
+g1e2 d7d6
+o-o o-o
+d2d3 c8e6
+c3d5 e6d5
+e4d5 c6e7
+c1g5 f6d7
+d3d4 e5d4
+!
+e2e4 e7e5
+b1c3 g8f6
+g2g3 f8c5
+f1g2 b8c6
+g1f3 d7d6
+d2d3 a7a6
+o-o o-o
+c1g5 h7h6
+g5e3 c5e3
+f2e3 d6d5
+e4d5 f6d5
+!
+e2e4 e7e5
+b1c3 g8f6
+g2g3 f8c5
+f1g2 o-o
+d2d3 f8e8
+g1e2 c7c6
+o-o d7d5
+e5d5 f6d5
+g1h1 c8g4
+h2h3 g4e6
+c3e4 c5e7
+!
+e2e4 e7e5
+b1c3 g8f6
+f1c4 f8b4
+g1e2 o-o
+d2d3 c7c6
+o-o d7d5
+c4b3 d5e4
+c3e4 b8d7
+e2g3 f6e4
+d3e4 d7c5
+d1h5 c5b3
+!
+e2e4 e7e5
+b1c3 g8f6
+f1c4 f8c5
+d2d3 d7d6
+c1g5 c8e6
+d1d2 b8d7
+g1e2 e6c4
+d3c4 h7h6
+g5e3 d8e7
+e2g3 c5e3
+f2e3 g7g6
+!
+e2e4 e7e5
+b1c3 g8f6
+f1c4 f8c5
+d2d3 d7d6
+f2f4 b8c6
+f4f5 b6d4
+g1f3 c7c6
+f3d4 c5d4
+d1f3 b7b5
+c4b3 a7a5
+a2a3 a5a4
+! ECO C27/1-2
+e2e4 e7e5
+b1c3 g8f6
+f1c4 f6e4
+d1h5 e4d6
+h5e5 d8e7
+e5e7 f8e7
+c4b3 d6f5
+c3d5 e7d8
+d5e3 f5d4
+b3c4 c7c6
+g1e2 d4e2
+c4e2 d7d5
+!
+e2e4 e7e5
+b1c3 g8f6
+f1c4 f6e4
+d1h5 e4d6
+c4b3 b8c6
+c3b5 g7g6
+h5f3 f7f6
+b5c7 d8c7
+f3f6 b7b6
+g1f3 c8a6
+f3e5 c6e5
+f6e5 e8d8
+! ECO C27/3-5
+e2e4 e7e5
+b1c3 g8f6
+f1c4 f6e4
+d1h5 e4d6
+c4b3 b8c6
+c3b5 g7g6
+h5f3 f7f5
+f3d5 d8e7
+b5c7 e8d8
+c7a8 b7b6
+d2d3 c8b7
+h2h4 f5f4
+d5f3 f8h6
+b3d5 b7a8
+f3g4 h8f8
+g1e2 e5e4
+c1f4 h6f4
+e2f4 e7e5
+g4g5 e5g5
+!
+e2e4 e7e5
+b1c3 g8f6
+f1c4 f6e4
+d1h5 e4d6
+c4b3 b8c6
+c3b5 g7g6
+h5f3 f7f5
+f3d5 d8e7
+b5c7 e8d8
+c7a8 b7b6
+g1f3 c8b7
+d3d4 c6d4
+c1g5 d4f3
+d5f3 e7g5
+b3d5 e5e4
+f3b3 b7a6
+b3a4 f8h6
+a4d4 h8e8
+g2g3 g5g4
+!
+e2e4 e7e5
+b1c3 g8f6
+f1c4 f6e4
+d1h5 e4d6
+c4b3 b8c6
+c3b5 g7g6
+h5f3 f7f5
+f3d5 d8e7
+b5c7 e8d8
+c7a8 b7b6
+a8b6 a7b6
+d5f3 c8b7
+d2d3 c6d4
+f3h3 e5e4
+c1e3 e4d3
+o-o-o d4c2
+e3b6 d8e8
+h3d3 f8h6
+c1b1 b7e4
+! ECO C27/6-7
+e2e4 e7e5
+b1c3 g8f6
+f1c4 f6e4
+d1h5 e4d6
+c4b3 f8e7
+g1f3 b8c6
+f3e5 o-o
+o-o c6d4
+c3d5 d4b3
+a2b3 d6e8
+h5e2 e8f6
+e5c6 d7c6
+d5e7 g8h8
+e7c8 d8c8
+!
+e2e4 e7e5
+b1c3 g8f6
+f1c4 f6e4
+d1h5 e4d6
+c4b3 f8e7
+g1f3 o-o
+h2h4 b8c6
+f3g5 h7h6
+h5g6 e7g5
+h4g5 d8g5
+d2d3 d6f5
+c1g5 c6d4
+c3d5 d4b3
+! ECO C28/1-7
+e2e4 e7e5
+b1c3 g8f6
+f1c4 b8c6
+f2f3 f6e4
+g1f3 e4c3
+d2c3 d8e7
+b2b4 d7d6
+o-o c8e6
+c4e6 e7e6
+b4b5 c6d8
+f4e5 d6e5
+f3e5 f8d6
+!
+e2e4 e7e5
+b1c3 g8f6
+f1c4 b8c6
+d2d3 c6a5
+g1e2 a5c4
+d3c4 d7d6
+o-o c8e6
+b2b3 c7c6
+e2g3 g7g6
+h2h3 h7h5
+d1d3 f8e7
+c1e3 d8d7
+!
+e2e4 e7e5
+b1c3 g8f6
+f1c4 b8c6
+d2d3 f8c5
+c1g5 h7h6
+g5h4 d7d6
+c3a4 c8e6
+a4c5 d6c5
+b2b3 e6c4
+b3c4 d8d6
+g1e2 c6d4
+h4f6
+!
+e2e4 e7e5
+b1c3 g8f6
+f1c4 b8c6
+d2d3 f8b4
+g1e2 d7d5
+e4d5 f6d5
+c4d5 d8d5
+o-o d5d8
+f2f4 e5f4
+c1f4 o-o
+d1e1 b4d6
+e1g3 b6f4
+!
+e2e4 e7e5
+b1c3 g8f6
+f1c4 b8c6
+d2d3 f8b4
+c1g5 d7d6
+g1e2 c8e6
+o-o h7h6
+g5f6 d8f6
+c3d5 e6d5
+c4d5 b4c5
+c2c3 o-o
+g1h1 c6e7
+!
+e2e4 e7e5
+b1c3 g8f6
+f1c4 b8c6
+d2d3 f8b4
+c1g5 h7h6
+g5f6 b4c3
+b2c3 d8f6
+g1e2 d7d6
+d1d2 c1e6
+c4b5 f6g5
+e2g3 o-o
+b5c6 b7c6
+!
+e2e4 e7e5
+b1c3 g8f6
+f1c4 b8c6
+d2d3 f8b4
+g1f3 d7d6
+o-o b4c3
+b2c3 c6a5
+c4b3 a5b3
+a2b3 o-o
+c3c4 b7b6
+d1e2 f6d7
+c1g5 f7f6
+! ECO C29/1
+e2e4 e7e5
+b1c3 g8f6
+f1f4 d7d5
+d2d3 e5f4
+e4d5 f6d5
+c3d5 d8d5
+c1f4 f8d6
+f4d6 d5d6
+d1d2 o-o
+g1f3 c8g4
+f1e2 g4f3
+! ECO C29/2-12
+e2e4 e7e5
+b1c3 g8f6
+f2f4 d7d5
+f4e5 f6e4
+d1f3 b8c6
+f1b5 e4c3
+b2c3 f8e7
+d2d4 o-o
+b5d3 f7f6
+f3h5 g7g6
+d3g6 h7g6
+h5g6 g8h8
+g6h6 h8g8
+!
+e2e4 e7e5
+b1c3 g8f6
+f2f4 d7d5
+f4e5 f6e4
+d1f3 f7f5
+d2d3 e4c3
+b2c3 d5d4
+f3g3 b8c6
+f1e2 c8e6
+e2f3 d8d7
+g1e2 f8c5
+c3c4 o-o
+o-o e6c4
+!
+e2e4 e7e5
+b1c3 g8f6
+f2f4 d7d5
+f4e5 f6e4
+d2d3 d8h4
+g2g3 e4g3
+g1f3 h4h5
+c3d5 c8g4
+f1g2 g3h1
+d5c7 e8d7
+c7h8 b8c6
+c1e3 f7f6
+d3d4 f6e5
+!
+e2e4 e7e5
+b1c3 g8f6
+f2f4 d7d5
+f4e5 f6e4
+d2d3 f1b4
+d3e4 d8h4
+e1e2 b8c6
+g1f3 c8g4
+c3d5 o-o-o
+c2c3 f7f5
+e5f6 h8e8
+c3b4 e8e4
+c1e3 g7f6
+!
+e2e4 e7e5
+b1c3 g8f6
+f2f4 d7d5
+f4e5 f6e4
+d2d3 e4c3
+b2c3 d5d4
+g1f3 b8c6
+c3d4 f8b4
+c1d2 b4d2
+d1d2 c6d4
+c2c3 d4f3
+g2f3 d8h4
+d2f2 h4f2
+!
+e2e4 e7e5
+b1c3 g8f6
+f2f4 d7d5
+f4e5 f6e4
+g1f3 f1b4
+d1e2 b4c3
+b2c3 o-o
+e2e3 b8c6
+f1d3 f7f5
+o-o c8e6
+c1a3 f8e8
+a1b1 a8b8
+a3b5 e6d7
+!
+e2e4 e7e5
+b1c3 g8f6
+f2f4 d7d5
+f4e5 f6e4
+g1f3 b8c6
+f1b5 f8c5
+d2d4 c5b4
+c1d2 b4c3
+b2c3 o-o
+o-o c1g4
+d1e1 f7f6
+d2e3 g4d7
+e5f6 d8f6
+!
+e2e4 e7e5
+b1c3 g8f6
+f2f4 d7d5
+f4e5 f6e4
+g1f3 f8c5
+d1e2 c5f2
+e1d1 e4c3
+d2c3 f2b6
+c3g5 d8d7
+d1d2 o-o
+a1d1 d7a4
+a2a3 c7c5
+d2c1 c8e6
+!
+e2e4 e7e5
+b1c3 g8f6
+f2f4 d7d5
+f4e5 f6e4
+g1f3 c8g4
+d1e2 e4g5
+h2h4 g5f3
+g2f3 g4e6
+d2d4 b8c6
+c1e3 f8e7
+e2f2 d8d7
+o-o-o o-o-o
+f1b5 a7a6
+!
+e2e4 e7e5
+b1c3 g8f6
+f2f4 d7d5
+f4e5 f6e4
+g1f3 f8e7
+d1e2 e4c3
+d2c3 o-o
+c1f4 c7c5
+o-o-o d8a5
+c1b1 b8c6
+a4b5 c8e6
+b5a5 f3g5
+!
+e2e4 e7e5
+b1c3 g8f6
+f2f4 d7d5
+f4e5 f6e4
+g1f3 f8e7
+d2d4 o-o
+f1d3 f7f6
+e5f6 e7f6
+o-o b8c6
+c3e4 d5e4
+d3e4 c6d4
+f3g5 c8f5
+c2c3 f7g5
+!
+! Vienna Game
+e2e4 e7e5
+b1c3 f8c5
+g1f3 d7d6
+d2d4 e5d4
+f3d4 g8f6
+c1g5 h7h6
+g5h4 b1c3
+! Three Knights Game
+e2e4 e7e5
+b1c3 b8c6
+g1f3 g7g6
+d2d4 e5d4
+c3d5 f8g7
+c1g5 c6e7
+f3d4 c7c6
+d5c3 h7h6
+! Bishop's Opening
+e2e4 e7e5
+f1c4 g8f6
+d2d4 e5d4
+g1f3 f6e4
+d1d4 e4c5
+o-o c5e6
+f1e1 c7c6
+b1c3 d7d5
+c4d3 f8e7
+! Ruy Lopez -- Classical Defence
+e2e4 e7e5
+g1f3 b8c6
+f1b5 f8c5
+c2c3 g8f6
+d2d4 e5d4
+e4e5 f6e4
+o-o d7d5
+! Ruy Lopez -- Birds Defence
+e2e4 e7e5
+g1f3 b8c6
+f1b5 c6d4
+b5a4 f8c5
+o-o d4f3
+d1f3 g8e7
+d2d3 o-o
+c1e3 c5b6
+b1c3 d7d6
+! Ruy Lopez -- Schliemann Defence
+e2e4 e7e5
+g1f3 b8c6
+f1b5 f7f5
+b1c3 f5e4
+c3e4 d7d5
+f3e5 d5e4
+e5c6 d8d5
+c2c4 d5d6
+c6a7 c8d7
+! Ruy Lopez -- Old Steinitz Defence
+e2e4 e7e5
+g1f3 b8c6
+f1b5 d7d6
+d2d4 c8d7
+b1c3 g8f6
+o-o f8e7
+f1e1 e5d4
+f3d4 o-o
+d4f5 f8e8
+! Ruy Lopez -- Old Steinitz Defence
+e2e4 e7e5
+g1f3 b8c6
+f1b5 d7d6
+d2d4 c8d7
+b1c3 g8f6
+b5c6 d7c6
+d1d3 e5d4
+f3d4 f8e7
+c1g5 c6d7
+! Ruy Lopez -- Modern Steinitz Defence
+e2e4 e7e5
+g1f3 b8c6
+f1b5 a7a6
+b5a4 d7d6
+d2d4 b7b5
+a4b3 c6d4
+f3d4 e5d4
+c2c3 d4c3
+b1c3 c8b7
+! Ruy Lopez -- Open Defence
+e2e4 e7e5
+g1f3 b8c6
+f1b5 a7a6
+b5a4 g8f6
+o-o f6e4
+d2d4 b7b5
+a4b3 d7d5
+d4e5 c8e6
+c2c3 f8c5
+b1d2 o-o
+! Ruy Lopez -- Open Defence
+e2e4 e7e5
+g1f3 b8c6
+f1b5 a7a6
+b5a4 g8f6
+o-o f8e7
+f1e1 b7b5
+a4b3 d7d6
+c2c3 o-o
+h2h3 c6a5
+b3c2 c2c4
+d2d4 d8c7
+! Ruy Lopez
+e2e4 e7e5
+g1f3 b8c6
+f1b5 a7a6
+b5c6 d7c6
+d2d4 e5d4
+d1d4 d8d4
+f3d4 c8d7
+c1e3 o-o-o
+b1d2 g8e7
+! Scotch Game
+e2e4 e7e5
+g1f3 b8c6
+d2d4 e5d4
+f3d4 f8c5
+c1e3 d8f6
+c2c3 g8e7
+b1d2 d7d6
+e3c5 d6c5
+! Philidor's Defence
+e2e4 e7e5
+g1f3 d7d6
+d2d4 g8f6
+b8c6 b1d2
+f8c5 f1e2
+o-o o-o
+d1e2 c7c6
+! Alekhine's Defence
+e2e4 g8f6
+e4e5 f6d5
+c2c4 d5b6
+d2d4 d7d6
+f2f4 d6e5
+f4e5 b8c6
+c1e3 c8f5
+b1c3 e7e6
+g1f3 f8e7
+! Alekhine's Defence
+e2e4 g8f6
+e4e5 f6d5
+d2d4 d7d6
+g1f3 c8g4
+f1e2 e7e6
+o-o f8e7
+h2h3 g4h5
+c2c4 d5b6
+! Kings Gambit Accepted
+e2e4 e7e5
+f2f4 e5f4
+g1f3 d7d6
+f1c4 h7h6
+d2d4 g7g5
+o-o f8g7
+c2c3 b8c6
+d1b3 d8e7
+! Ponziani's Opening
+e2e4 e7e5
+g1f3 b8c6
+c2c3 d7d5
+d1a4 g8f6
+f3e5 f8d6
+e5c6 b7c6
+d2d3 o-o
+c1g5 h7h6
+! Caro-Kann Defence
+e2e4 c7c6
+d2d4 d7d5
+e4d5 c6d5
+c2c4 g8f6
+b1c3 b8c6
+c1g5 e7e6
+c4c5 f8e7
+f1b5 o-o
+g1f3 f6e4
+! Caro-Kann Defence
+e2e4 c7c6
+d2d4 d7d5
+e4e5 c8f5
+f1d3 f5d3
+d1d3 e7e6
+b1c3 d8b6
+b1d2 c6c5
+d4c5 f8c5
+! Caro-Kann Defence
+e2e4 c7c6
+b1c3 d7d5
+g1f3 c8g4
+h2h3 g4f3
+d1f3 e7e6
+d2d4 g8f6
+f1d3 d5e4
+c3e4 d8d4
+c2c3 d4d8
+! French Defence -- Classical
+e2e4 e7e6
+d2d4 d7d5
+b1c3 g8f6
+c1g5 f8e7
+e4e5 f6d7
+g5e7 d8e7
+d1d2 o-o
+f2f4 c7c5
+g1f3 b8c6
+o-o-o c5c4
+! French Defence -- MacCutcheon
+e2e4 e7e6
+d2d4 d7d5
+b1c3 g8f6
+c1g5 c8g4
+e4e5 h7h6
+g5d2 g4f3
+g2f3 f6e4
+d1g4 e8f8
+h2h4 c7c5
+! French Defence -- Rubenstein
+e2e4 e7e6
+d2d4 d7d5
+b1c3 d5e4
+c3e4 b8d7
+g1f3 g8f6
+e4f6 d7f6
+f1d3 b7b6
+d1e2 c8b7
+c1g5 f8e7
+! French Defence -- Winawer
+e2e4 e7e6
+d2d4 d7d5
+b1c3 f8b4
+e4e5 c7c5
+a2a3 b4c3
+b2c3 b8d7
+d1g4 o-o
+g1f3 b8c6
+f1e3 f7f5
+! French Defence -- Tarrasch
+e2e4 e7e6
+d2d4 d7d5
+b1d2 b8c6
+g1f3 g8f6
+e4e5 f6d7
+d2b3 f7f6
+f1b5 f8e7
+c1f4 o-o
+! Sicilian Defence -- Dragon Variation
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+f1e2 g7g6
+c1e3 f8g7
+o-o o-o
+d4b3 c8e6
+f2f4 c6a5
+f4f5 e6c4
+! Sicilian Defence -- Dragon Variation
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g7g6
+b1c3 f8g7
+c1e3 g8f6
+f1c4 o-o
+! Sicilian Defence -- Boleslavsky Variation
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+f1e2 e7e5
+d4b3 f8e7
+o-o o-o
+c1e3 c8e6
+! Sicilian Defence -- Najdorf
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+d1d2 f8e7
+o-o-o o-o
+! Sicilian Defence -- Najdorf
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+f1e2 e7e5
+d4b3 f8e7
+o-o o-o
+f2f4 b7b5
+a2a3 c8b7
+! Sicilian Defence -- Najdorf
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+g2g3 e7e5
+d4e2 c8e6
+f1g2 b7b5
+o-o b8d7
+! Sicilian Defence -- Closed
+e2e4 c7c5
+b1c3 b8c6
+g2g3 g7g6
+f1g2 f8g7
+d2d3 e7e6
+c1e3 d7d6
+g1e2 c6d4
+d1d2 d8h4
+o-o g8d7
+! Nimzowitsch Defence
+e2e4 b8c6
+d2d4 d7d5
+e4e5 f7f6
+g1f3 c1g4
+f1e2 e7e6
+e5f6 g8f6
+c2c3 f8d6
+c1g5 d8d7
+! Queens Gambit Accepted
+d2d4 d7d5
+c2c4 d5c4
+g1f3 g8f6
+e2e3 e7e6
+f1c4 c7c5
+o-o a7a6
+d1e2 b7b5
+c4d3 c5d4
+e3d4 b8c6
+! Queens Gambit -- Catalan
+d2d4 d7d5
+c2c4 e7e6
+g2g3 g8f6
+g1f3 f8e7
+f1g2 o-o
+o-o f6d7
+d1c2 c7c6
+b1d2 b7b6
+e2e4 c8b7
+b2b3 a8c8
+! Queens Gambit Declined -- Orthodox
+d2d4 d7d5
+c2c4 e7e6
+b1c3 g8f6
+c1g5 f8e7
+e2e3 o-o
+g1f3 b8d7
+a1c1 c7c6
+f8d3 d5c4
+f1c4 f6d5
+! Queens Gambit Declined -- Cambridge Springs
+d2d4 d7d5
+c2c4 e7e6
+b1c3 g8f6
+c1g5 b8d7
+e2e3 c7c6
+g1f3 d8a5
+f3d2 f8b4
+d1c2 o-o
+g5h4 c6c5
+! Queens Gambit Declined -- Exchange Var.
+d2d4 d7d5
+c2c4 e7e6
+b1c3 g8f6
+c1g5 b8d7
+c4d5 e6d5
+e2e3 c7c6
+f1d3 f8e7
+d1c2 o-o
+g1e2 f8e8
+! Queens Gambit Declined -- Semi-Tarrasch
+d2d4 d7d5
+c2c4 e7e6
+b1c3 g8f6
+g1f3 c7c5
+c4d5 c5d4
+d1d4 e6d5
+e2e4 b8c6
+f1b5 f6e4
+! Queens Gambit Declined -- Tarrasch
+d2d4 d7d5
+c2c4 e7e6
+b1c3 c7c5
+c4d5 e6d5
+g1f3 b8c6
+g2g3 g8f6
+f1g2 f8e7
+o-o o-o
+! Queens Gambit Declined -- Vienna
+d2d4 d7d5
+c2c4 e7e6
+g1f3 g8f6
+f1b5 f8b4
+b1c3 d5c4
+e2e4 c7c5
+e4e5 c5d4
+d1a4 b8c6
+o-o-o c1d2
+! Queens Gambit Declined -- Slav (Marshall Gambit)
+d2d4 d7d5
+c2c4 c7c6
+b1c3 e7e6
+e2e4 d4e4
+c3e4 f8b4
+c1d2 d8d4
+d2b4 d4e4
+f1e2 b8a6
+b4d6 b7b6
+! Queens Gambit --Slav (Krause)
+d2d4 d7d5
+c2c4 c7c6
+g1f3 g8f6
+b1c3 d5c4
+a2a4 c8f5
+f3e5 e7e6
+f2f3 f8b4
+c1g5 h7h6
+g5f6 d8f6
+e2e4 f5h7
+! Modern Benoni Counter Gambit
+d2d4 g8f6
+c2c4 c7c5
+d4d5 e7e6
+b1c3 e6d5
+c4d5 d7d6
+e2e4 g7g6
+f1d3 f8g7
+g1e2 o-o
+o-o a7a6
+a2a4 d8c7
+! Queens Pawn Game
+d2d4 d7d5
+g1f3 g8f6
+c1f4 c7c5
+e2e3 b8c6
+c2c3 d8b6
+d1c1 c8f5
+d4c5 b6c5
+b1d2 a8c8
+f3d4 c6d4
+e3d4 c5b6
+! Pirc-Robatsch Defence
+d2d4 d7d6
+e2e4 g8f6
+b1c3 g7g6
+c1g5 f8g7
+d1d2 b8d7
+o-o-o e7e5
+d4e5 d6e5
+g1f3 h7h6
+g5h4 g6g5
+h4g3 d8e7
+! Pirc-Robatsch Defence
+d2d4 d7d6
+e2e4 g8f6
+b1c3 g7g6
+f1c4 c7c6
+d1e2 f8g7
+g1f3 o-o
+c1g5 b7b5
+c4d3 d8c7
+! Queens Indian Defence
+d2d4 g8f6
+c2c4 e7e6
+g1f3 b7b6
+g2g3 c8b7
+f1g2 f8e7
+o-o o-o
+b1c3 f6e4
+d1c2 e4c3
+c2c3 d7d6
+c3c2 f7f5
+! Queens Indian Defence
+d2d4 g8f6
+c2c4 e7e6
+g1f3 b7b6
+e2e3 c8b7
+f1d3 f8e7
+b1c3 d7d5
+o-o o-o
+d1e2 b8d7
+! Nimzo-Indian Defence
+d2d4 g8f6
+c2c4 e7e6
+b1c3 f8b4
+d1c2 d7d5
+a2a3 b4c3
+c2c3 b8c6
+g1f3 f6e4
+c3b3 c6a5
+b3a4 c7c6
+! Nimzo-Indian Defence (Rubenstein)
+d2d4 g8f6
+c2c4 e7e6
+b1c3 f8b4
+e2e3 o-o
+f1d3 d7d5
+g1f3 c7c5
+o-o b8c6
+a2a3 b4c3
+b2c3 d5c4
+d3c4 d8c7
+! Nimzo-Indian Defence -- Samisch
+d2d4 g8f6
+c2c4 e7e6
+b1c3 f8b4
+a2a3 b4c3
+b2c3 o-o
+f2f3 d7d5
+c4d5 e6d5
+e2e3 c8f5
+g1e2 b8d7
+e2g3 f5g6
+! Nimzo-Indian Defence
+d2d4 g8f6
+c2c4 e7e6
+b1c3 f8b4
+c1d2 o-o
+e2e3 d7d5
+g1f3 c7c5
+a2a3 b4c3
+d2c3 f6e4
+a1c1 e4c3
+c1c3 c5d4
+! Grunfeld Defence
+d2d4 g8f6
+c2c4 g7g6
+b1c3 d7d5
+c4d5 f6d5
+e2e4 d5c3
+b2c3 c7c5
+f1c4 f8g7
+g1e2 o-o
+o-o c5d4
+c3d4 b8c6
+! Grunfeld Defence -- Smyslov
+d2d4 g8f6
+c2c4 g7g6
+b1c3 d7d5
+g1f3 f8g7
+d1b3 d5c4
+b3c4 o-o
+e2e4 c8g4
+c1e3 f6d7
+o-o-o b8c6
+! Grunfeld Defence
+d2d4 g8f6
+c2c4 g7g6
+b1c3 d7d5
+c1f4 f8g7
+d2d3 o-o
+c4d5 f6d5
+c3d5 d8d5
+f4c7 b8c6
+! Kings Indian Defence -- Classical
+d2d4 g8f6
+c2c4 g7g6
+b1c3 f8g7
+e2e4 d7d6
+g1f3 o-o
+f1e2 e7e5
+o-o b8c6
+c1e3 f8e8
+d4e5 d6e5
+! Kings Indian Defence -- 4 pawns attack
+d2d4 g8f6
+c2c4 g7g6
+b1c3 f8g7
+e2e4 d7d6
+f2f4 c7c5
+g1f3 o-o
+d4d5 e7e6
+f1d3 e6d5
+c4d5 d8b6
+! Kings Indian Defence -- Samisch
+d2d4 g8f6
+c2c4 g7g6
+b1c3 f8g7
+e2e4 d7d6
+f2f3 o-o
+c1e3 e7e5
+d4d5 c7c6
+g1e2 c6d5
+c3d5 f6d5
+! Kings Indian Defence -- Main Line
+d2d4 g8f6
+c2c4 g7g6
+g2g3 f8g7
+f1g2 o-o
+b1c3 d7d6
+g1f3 b8d7
+o-o e7e5
+e2e4 c7c6
+h2h3 d8b6
+! Kings Indian Defence
+d2d4 g8f6
+c2c4 g7g6
+b1c3 f8g7
+g1f3 o-o
+c1f4 d7d6
+h2h3 b8d7
+e2e3 c7c6
+! Dutch Defence
+d2d4 f7f5
+g2g3 e7e6
+f1g2 g8f6
+g1f3 f8e7
+o-o o-o
+c2c4 d7d6
+b1c3 d8e8
+d1c2 e8h5
+b2b3 b8c6
+c1a3 a7a5
+! English Opening
+c2c4 e7e5
+b1c3 g8f6
+g1f3 b8c6
+e2e4 f8b4
+d2d3 d7d6
+f1e2 o-o
+o-o b4c3
+b2c3 d8e7
+! English Opening
+c2c4 g8f6
+b1c3 d7d5
+c4d5 f6d5
+e2e4 d5f4
+f1c4 c8e6
+c4e6 f7e6
+! English Opening
+c2c4 e7e5
+b1c3 g8f6
+g1f3 b8c6
+g2g3 d7d5
+c4d5 f6d5
+f1g2 d5b6
+o-o f8e7
+d2d3 o-o
+c1e3 f7f5
+! Reti -- Accepted
+g1f3 d7d5
+c2c4 d5c4
+e2e3 c7c5
+f1c4 e7e6
+o-o g8f6
+b2b3 b8c6
+c1b2 a7a6
+a2a4 f8e7
+! Reti -- Neo Catalan
+g1f3 d7d5
+c2c4 e7e6
+g2g3 g8f6
+f1g2 f8e7
+o-o o-o
+b2b3 c7c5
+c4d5 f6d5
+c1b2 b8c6
+d2d4 b7b6
+b1c3 d5c3
+! Reti -- Barcza
+g1f3 d7d5
+g2g3 g8f6
+f1g2 g7g6
+o-o f8g7
+d2d3 o-o
+b1d2 b8c6
+e2e4 e7e5
+c2c3 a7a5
+f1e1 d5e4
+d3e4 f6d7
+! Sicilian Najdorf
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+f2f4 d8b6
+d1d2 b6b2
+a1b1 b2a3
+e4e5 d6e5
+f4e5 f6d7
+c3e4 h7h6
+g5h4 a3a2
+b1b3 b8c6
+d4c6 b7c6
+e4d6 f8d6
+e5d6 a6a5
+f1e2 a5a4
+b3c3 a2a1
+e2d1 a4a3
+o-o a3a2
+d2e3 o-o
+! # Sicilian Defense col. 2f p. 176 MCO 12. (Incomplete game)
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+f2f4 d8b6
+d1d2 b6b2
+a1b1 b2a3
+e4e5 d6e5
+f4e5 f6d7
+f1c4 f8b4
+b1b3 a3a5
+o-o o-o
+g5f6 d7f6
+e5f6 f8d8
+b3b4 a5b4
+d2g5 g7g6
+f1f4 b7b6
+f4h4 b4f8
+g1f1 a8a7
+! # Sicilian Defense col. 3g p. 176 MCO (Incomplete Game)
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+f2f4 d8b6
+d1d2 b6b2
+a1b1 b2a3
+e4e5 d6e5
+f4e5 f6d7
+f1c4 a3a5
+c4e6 f7e6
+d4e6 d7e5
+c3d5 a5d2
+e1d2 e8d7
+e6c7 a8a7
+h1e1 e5c4
+! # Parma vs. Fischer, Havana 1965. Sicilian Defense col. 4j p. 176
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+f2f4 d8b6
+d1d2 b6b2
+a1b1 b2a3
+g5f6 g7f6
+f1e2 f8g7
+o-o f6f5
+f1d1 b8c6
+d4c6 g7c3
+d2e3 b7c6
+b1b3 a3c5
+e3c5 d6c5
+b3c3 f5e4
+c3c5 c8d7
+c5e5 f7f5
+g2g4 h8g8
+g1g2 f5g4
+e5e4 h7h5
+g2g3 e8e7
+! # Matanovic, Sicilian Defense col. 5k p. 176 MCO (partial game)
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+f2f4 d8b6
+d1d2 b6b2
+a1b1 b2a3
+g5f6 g7f6
+f1e2 b8c6
+d4c6 b7c6
+o-o a3a5
+g1h1 f8e7
+f4f5 e6f5
+e4f5 c8f5
+e2a6 a5a6
+f1f5 d6d5
+b1e1 a6b7
+d2h6 o-o-o
+h6h3 b7d7
+c3a4
+! # col. 6a
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+f2f4 d8b6
+d1d2 b6b2
+a1b1 b2a3
+f4f5 b8c6
+f5e6 f7e6
+d4c6 b7c6
+e4e5 d6e5
+g5f6 g7f6
+c3e4 f8e7
+f1e2 h7h6
+c2c4 f6f5
+b1b3 a3a4
+o-o f5e4
+g1h1 c6c5
+d2c3 a4c6
+c3e5 h8f8
+! # col. 7d
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+f2f4 d8b6
+d1d2 b6b2
+a1b1 b2a3
+f4f5 b8c6
+f5e6 f7e6
+d4c6 b7c6
+e4e5 f6d5
+c3d5 c6d5
+f1e2 d6e5
+o-o a8a7
+g1h1 a3c5
+c2c4 d5d4
+e2h5 g7g6
+h5d1 f8e7
+d1a4 e8d8
+f1f7 h7h6
+g5h6 e5e4
+! # col. 8
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+f2f4 d8b6
+d1d2 b6b2
+d4b3 b8d7
+g5f6 g7f6
+f1e2 h7h5
+o-o b2a3
+a1d1 f8e7
+g1h1 d7c5
+e2f3 a8a7
+b3c5 a3c5
+! # col. 9g; Minic-Barczay, Varna 1967 (partial game)
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+f2f4 d8b6
+d1d2 b6b2
+d4b3 b8c6
+f1d3 d6d5
+g5f6 g7f6
+c3a4 b2a3
+a4b6 d5d4
+o-o a8b8
+f4f5 a3b4
+d2b4 f8b4
+b6c8 b8c8
+f5e6 f7e6
+f1f6 e8e7
+a1f1 c6e5
+! # col. 10i; Matulovic-Kavalek, Sousse 1967
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+f2f4 d8b6
+d1d2 b6b2
+d4b3 b8c6
+a1b1 b2a3
+g5f6 g7f6
+f1d3 f8g7
+o-o o-o
+f1f3 g8h8
+f3h3 c6e7
+f4f5 e6f5
+e4f5 c8f5
+d3f5 e7f5
+c3d5
+! # col. 11b; Joppen-Bronstein, Belgrade 1954 (partial game)
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+f2f4 d8b6
+d4b3 b6e3
+d1e2 e3e2
+f1e2 b8d7
+a2a4 f8e7
+o-o-o h7h6
+g5h4 e6e5
+f4f5 b7b6
+e2f3 c8b7
+! # col. 12e; Rajkovic-Udovcic, Yugoslav Chp. 1962 (partial game)
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+f2f4 d8b6
+d4b3 b8d7
+d1f3 f8e7
+o-o-o b6c7
+f1d3 h7h6
+g5h4 g7g5
+f4g5 d7e5
+f3e2 f6g4
+b3d4 h6g5
+h4g3 c8d7
+d4f3 c7c5
+! # col. 13i; Fischer-Vukovic (partial game)
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+f2f4 f8e7
+d1f3 d8c7
+o-o-o b8d7
+g2g4 b7b5
+g5f6 d7f6
+g4g5 f6d7
+a2a3 a8b8
+h2h4 b5b4
+a3b4 b8b4
+f1h3 o-o
+d4e6 f7e6
+h3e6 g8h8
+c3d5 c7c4
+e6f5 f8f5
+e4f5 c8b7
+h1e1 e7f8
+! # col. 14m Parma-Tatai, Athens 1968 (partial game)
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+f2f4 b7b5
+e4e5 d6e5
+f4e5 d8c7
+e5f6 c7e5
+f1e2 e5g5
+d1d3 a8a7
+c3e4 g5e5
+d4f3 e5b2
+o-o a7d7
+d3e3 c8b7
+a1b1 b2c2
+f3g5 c2c6
+f6g7 f8g7
+! # col. 15; slight advantage for white.
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+f2f4 h7h6
+g5h4 d8b6
+d1d3 b6b2
+a1b1 b2a3
+e4e5 f6d5
+c3d5 a3d3
+f1d3 e6d5
+e5e6
+! # col. 16c; Fichtl-Dolezal, CSSR 1954
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+d1f3 b8d7
+o-o-o d8c7
+f3g3 b7b5
+f1b5 a6b5
+d4b5 c7b8
+b5d6 f8d6
+g3d6 b8d6
+d1d6 h7h6
+g5f6 d7f6
+h1d1 c8b7
+f2f3
+! # col. 17e; Vasyukov-Zukharov, USSR 1960
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 e7e6
+d1d2 b8c6
+o-o-o h7h6
+g5h4 f6e4
+d2f4 e4g5
+d4c6 b7c6
+f4a4 d8b6
+f2f4 g5h7
+f4f5 a8b8
+f5e6 c8e6
+f1c4
+! # col. 18g (somewhat questionable)
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1g5 b8d7
+f1c4 d8a5
+d1d2 e7e6
+o-o-o b7b5
+c4b3 c8b7
+h1e1 a8c8
+e4e5 d7e5
+d4e6 f7e6
+e1e5 d6e5
+g5f6
+! # col. 19m; Yanofsky-Bolbochan, Stockholm 1962
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+f1e2 e7e5
+d4b3 f8e7
+o-o o-o
+f2f4 b7b5
+a2a3 c8b7
+e2f3 b8d7
+g2g3 a8c8
+d1e1 d7b6
+g1h1 b6c4
+b3d2 d8d7
+d2c4 c8c4
+c1d2 d6d5
+! # col. 20p
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+f1e2 e7e5
+d4b3 f8e7
+o-o o-o
+c1e3 b8d7
+a2a4 b7b6
+d1d2 c8b7
+f2f3 d8c7
+f1d1 f8c8
+b3c1
+! # col. 21b
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+g2g3 e7e5
+d4e2 f8e7
+f1g2 o-o
+o-o b7b5
+h2h3 c8b7
+c3d5 f6d5
+e4d5 b8d7
+a2a4 d7c5
+e2c3 d8d7
+a4b5 a6b5
+a1a8 f8a8
+! # col. 22
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+f2f4 e7e6
+d1f3 d8b6
+d4b3 b8c6
+f1d3 f8e7
+c1e3 b6c7
+o-o o-o
+a1e1 c6b4
+! # col. 23f
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+c1e3 e7e5
+d4b3 c8e6
+d1d2 b8d7
+f2f3 f8e7
+g2g4 b7b5
+g4g5 f6h5
+o-o-o o-o
+h1g1 a8c8
+c3e2
+! # col. 24k; Kotkov-Polugayevski, USSR 1959
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+f1c4 e7e6
+o-o f8e7
+c4b3 o-o
+f2f4 b7b5
+a2a3 c8b7
+f4f5 e6e5
+d4e2 b8d7
+e2g3 d7c5
+b3d5 b7d5
+e4d5 a8c8
+c1g5 c5d7
+g5f6 d7f6
+c3e4 c8c4
+! # col. 25o; Ciocaltea-Minic, Bucharest 1966
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 a7a6
+f1c4 e7e6
+c4b3 b7b5
+f2f4 c8b7
+f4f5 e6e5
+d4e2 b8d7
+o-o f8e7
+e2g3 a8c8
+c1g5 o-o
+! # col. 26e
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+c1e3 f8g7
+f2f3 o-o
+d1d2 b8c6
+o-o-o d6d5
+e4d5 f6d5
+d4c6 b7c6
+c3d5 c6d5
+d2d5 d8c7
+d5a8 c8f5
+a8f8 g8f8
+d1d2 h7h5
+f1e2 f8g8
+a2a3 c7b8
+! # col. 27i; Bikhovski-Gik, Moscow 1968
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+c1e3 f8g7
+f2f3 o-o
+d1d2 b8c6
+f1c4 c8d7
+o-o-o d8a5
+c4b3 f8c8
+g2g4 c6e5
+h2h4 e5c4
+b3c4 c8c4
+d4b3 a5a6
+h4h5 c4c3
+b2c3 d7e6
+c1b1 a8c8
+e3d4 c8c4
+h5g6 h7g6
+! # col. 28k
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+c1e3 f8g7
+f2f3 o-o
+d1d2 b8c6
+f1c4 c8d7
+o-o-o d8a5
+c4b3 f8c8
+h2h4 c6e5
+h4h5 f6h5
+e3h6 e5d3
+c1b1 d3b2
+b1b2 g7h6
+d2h6 c8c3
+g2g4 h5f6
+g4g5 f6h5
+! # col. 29m; Ostojic-Honfi, Monte Carlo 1968
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+c1e3 f8g7
+f2f3 o-o
+d1d2 b8c6
+f1c4 c8d7
+o-o-o d8a5
+c4b3 f8c8
+c1b1 c6e5
+h2h4 e5c4
+b3c4 c8c4
+d4b3 a5c7
+h4h5 c4c3
+d2c3 c7c3
+b2c3 f6h5
+e3d4 d7e6
+h1e1 h5f6
+e4e5 d6e5
+d4e5 f6d5
+b1b2 a8c8
+! # col. 30p; Karpov-Korchnoi, 2nd match game 1974.
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+c1e3 f8g7
+f2f3 o-o
+d1d2 b8c6
+f1c4 c8d7
+h2h4 a8c8
+c4b3 c6e5
+h4h5 f6h5
+o-o-o e5c4
+b3c4 c8c4
+g2g4 h5f6
+d4e2 d8a5
+e3h6 g7h6
+d2h6 f8c8
+d1d3 c4c5
+g4g5 c5g5
+d3d5 g5d5
+c3d5 c8e8
+e2c3 d7c6
+e4e5 c6d5
+e5f6 e7f6
+h6h7 g8f8
+h7h8 f8e7
+c3d5
+! # col. 31
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+g2g3 b8c6
+f1g2 c6d4
+d1d4 f8g7
+o-o o-o
+d4d3 c8e6
+c3d5 f6d5
+e4d5 e6f5
+! # col. 32c; Pulsen-Cortlever, Buenos Aires 1939.
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+c1g5 f8g7
+d1d2 b8c6
+o-o-o o-o
+d4b3 f8e8
+f2f3 a7a6
+c1b1 b7b5
+h2h4 c8e6
+g2g4 c6e5
+! # col. 33h
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+f2f4 b8c6
+d4c6 b7c6
+e4e5 d6e5
+d1d8 e8d8
+f4e5 f6g4
+c1f4 c8e6
+c3e4 f8g7
+e4g5 g7e5
+o-o-o d8c7
+g5e6 f7e6
+f4e5 g4e5
+d1e1 c7d6
+g2g3 e5g4
+f1c4 e6e5
+e1e2
+! # col. 34j
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+f2f4 b8c6
+f1b5 d8c7
+c3d5 f6d5
+e4d5 a7a6
+b5c6 b7c6
+d4c6 c8b7
+c1e3 f8g7
+e3d4 g7d4
+d1d4 o-o
+o-o b7c6
+! # col. 35l
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+f2f4 b8d7
+f1e2 f8g7
+c1e3 o-o
+e2f3 d7b6
+d1e2 e7e5
+d4b3 f6g4
+f3g4 d8h4
+g2g3 h4g4
+e2g4 c8g4
+! # col. 36a
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+f1e2 f8g7
+c1e3 b8c6
+o-o o-o
+d4b3 c8e6
+f2f4 c6a5
+f4f5 e6c4
+b3a5 c4e2
+d1e2 d8a5
+g2g4 a8c8
+g4g5 c8c3
+g5f6 c3e3
+e2e3 g7f6
+c2c3 f8c8
+a2a3 c8c4
+a1e1 b7b5
+! # col. 37c; Domnitz-Kraidman, Tel Aviv 1964
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+f1e2 f8g7
+c1e3 b8c6
+o-o o-o
+d4b3 c8e6
+f2f4 d8c8
+d1e1 f6g4
+e2g4 e6g4
+f4f5 g6f5
+h2h3 g4h3
+g2h3 f5e4
+e1h4 f7f5
+g1h1 f8f7
+f1g1 c6e5
+c3d5 c8d7
+b3d4 e5g6
+g1g6 h7g6
+a1g1 e7e5
+g1g6 d7d8
+e3g5 d8a5
+d5f6 g8f8
+d4e6
+! # col. 38f; Unzicker-Geller, W. Germany-USSR 1960 (drawn)
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+f1e2 f8g7
+c1e3 b8c6
+o-o o-o
+d1d2 f6g4
+e2g4 c8g4
+f2f4 c6d4
+e3d4 e7e5
+d4e3 e5f4
+f1f4 g4e6
+f4f2 g7e5
+e3d4 a8c8
+a1d1 d8a5
+a2a3 c8c4
+c3e2 a5d2
+d1d2
+! # col. 39
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+f1e2 f8g7
+c1e3 b8c6
+o-o o-o
+f2f4 d8b6
+d1d3 f6g4
+c3d5 g7d4
+e2g4 d4e3
+d3e3 b6b2
+g4c8 a8c8
+a1b1 b2a2
+b1b7 e7e6
+! # col. 40h
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+f1e2 f8g7
+c1e3 b8c6
+o-o o-o
+f2f4 d8b6
+e4e5 d6e5
+f4e5 c6e5
+d4f5 b6b2
+f5e7 g8h8
+e3d4 b2b4
+d4e5 b4e7
+d1d4 f6e8
+e5g7 e8g7
+e2d3 c8e6
+! # col. 41b; Smyslov-Botvinnik, match 1958
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+f1e2 f8g7
+c1e3 b8c6
+h2h4 h7h5
+f2f3 o-o
+d1d2 d6d5
+d4c6 b7c6
+e4e5 f6e8
+f3f4 f7f6
+o-o-o f6e5
+f4e5 g7e5
+g2g4 c8g4
+e2g4 h5g4
+h4h5 g6g5
+! # col. 42d; Van den Burg-Rajkovic, Orebro 1966
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+f1e2 f8g7
+c1e3 b8c6
+d4b3 o-o
+f2f4 c6a5
+g2g4 b7b6
+g4g5 f6d7
+o-o c8b7
+e2d3 a8c8
+b3a5 b6a5
+d1e1 d7c5
+f4f5 g7e5
+e1h4 e7e6
+f5f6 h7h5
+d3e2 g8h7
+e2h5 f8h8
+! # col. 43f
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+f1e2 f8g7
+c1e3 b8c6
+d4b3 o-o
+f2f4 c6a5
+g2g4 c8e6
+g4g5 f6d7
+e3d4 f7f6
+h2h4 f6g5
+d4g7 g8g7
+b3d4 e6g8
+f4f5 d8b6
+! # col. 44
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+f1e2 f8g7
+o-o b8c6
+d4b3 o-o
+f2f4 b7b5
+e2f3 b5b4
+c3d5 f6d5
+e4d5 c6a5
+b3a5 d8a5
+f1e1 f8e8
+! # col. 45i; Smyslov-Korchnoi, Moscow 1960
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 g7g6
+f1e2 f8g7
+d4b3 b8c6
+g2g4 b7b6
+f2f4 c8b7
+e2f3 o-o
+h2h4 a7a5
+a2a4 c6b4
+h4h5 d6d5
+e4e5 f6g4
+b3d4 g4h6
+h5g6 f7g6
+d4e6 d8d7
+e6f8 a8f8
+c3b5 d5d4
+! # col. 46
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+f3d4 g8f6
+f2f3 e7e5
+f1b5 c8d7
+b5d7 b8d7
+d4f5 d6d5
+e4d5 d8a5
+b1c3 d7b6
+! # col. 47h; Schweber-Najdorf, Buenos Aires 1970
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+d1d4 b8c6
+f1b5 c8d7
+b5c6 d7c6
+c2c4 g8f6
+b1c3 e7e6
+c1g5 f8e7
+o-o o-o
+f1e1 h7h6
+g5h4 a7a6
+a1d1 d8a5
+d4d2 a5b6
+f3d4 a8c8
+e1e3 f8e8
+! # col. 48i
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+d1d4 a7a6
+c1e3 g8f6
+b1c3 b8c6
+d4b6 d8b6
+e3b6 g7g6
+o-o-o f8h6
+c1b1 o-o
+f3d4 c8d7
+f2f3 c6e5
+d4b3 f8c8
+b3a5 d7c6
+c3d5 c6d5
+e4d5 f6d7
+b6d4 b7b6
+! # col. 49m; Fischer-Korchnoi, Buenos-Aires 1960
+e2e4 c7c5
+g1f3 d7d6
+d2d4 c5d4
+c2c3 d4c3
+b1c3 b8c6
+f1c4 e7e6
+o-o a7a6
+d1e2 g8f6
+f1d1 d8c7
+c1g5 f8e7
+a1c1 o-o
+c4b3 h7h6
+g5f4 e6e5
+f4e3 c7d8
+c3d5 f6d5
+b3d5 c8d7
+! # col. 50
+e2e4 c7c5
+g1f3 d7d6
+d2d4 g8f6
+d4c5 f6e4
+c5d6 e7e6
+d1d3 e4d6
+b1c3 b8c6
+c1f4 f7f6
+o-o-o e6e5
+c3b5
+! # col. 51c; Pfeiffer-Kottnauer, Helsinki 1952
+e2e4 c7c5
+g1f3 d7d6
+c2c3 g8f6
+f1d3 b8c6
+d3c2 c8g4
+h2h3 g4h5
+d2d3 d6d5
+d1e2 e7e6
+b1d2 f8e7
+d2f1 d8a5
+! # col. 52d; Brasket-Evans, U.S. Open Chp. 1960
+e2e4 c7c5
+g1f3 d7d6
+c2c3 g8f6
+d2d3 g7g6
+g2g3 f8g7
+b1d2 o-o
+f1g2 e7e5
+o-o b8c6
+a2a4 h7h6
+d2b1 d8a5
+! # col. 53h; Ciocaltea-Fischer, Varna 1962
+e2e4 c7c5
+g1f3 d7d6
+g2g3 g7g6
+f1g2 f8g7
+o-o b8c6
+c2c3 e7e5
+d2d3 g8e7
+f3h4 o-o
+f2f4 e5f4
+g3f4 f7f5
+b1d2 g8h8
+d2f3
+! # col. 54k; Tarjan-Mednis, U.S. Chp. 1973
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 e7e6
+f1e2 g7g6
+d4b3
+! e2e4 c7c5
+g1f3 d7d6
+b1c3 g8f6
+e4e5 d6e5
+f3e5 a7a6
+f1e2 e7e6
+o-o d8c7
+e5c4 b7b5
+c4e3 f8d6
+h2h3 b8c6
+a2a4 b5b4
+c3b1 c8b7
+d2d3 c6d4
+b1d2 o-o
+d2f3 d4e2
+d1e2 f8e8
+e3c4 e6e5
+f3g5 e5e4
+c4d6 c7d6
+g5e4 f6e4
+d3e4 b7e4
+c1e3 d6c6
+! # col. 55o; Medina-Pomar, Santander 1947
+e2e4 c7c5
+g1f3 d7d6
+b2b4 c5b4
+d2d4 g8f6
+f1d3 d6d5
+b1d2 d5e4
+d2e4 b8d7
+e4g5 d8c7
+c2c4 h7h6
+g5h3 g7g5
+h3g1 f8g7
+g1e2 e7e5
+e2g3 e5e4
+d1e2 o-o
+! # col. 56e; del Corral-Benko, Mallorca 1968
+e2e4 c7c5
+g1f3 d7d6
+f1b5 c8d7
+b5d7 d8d7
+o-o b8c6
+f1e1 g8f6
+c2c3 e7e6
+d2d3 f8e7
+a2a4 o-o
+b1d2 d7c7
+! # col. 57g; Radovich-Lombardy, Leipzig 1960
+e2e4 c7c5
+g1f3 d7d6
+f1b5 b8c6
+o-o a7a6
+b5c6 b7c6
+d2d4 c5d4
+d1d4 e7e5
+d4d3 f7f6
+c2c4 c8e6
+b1c3 d8c7
+! # col. 58j; Gurgenidze-Osnos, Alma Ata 1969
+e2e4 c7c5
+g1f3 b8c6
+f1b5 e7e6
+b1c3 g8e7
+o-o a7a6
+b5c6 e7c6
+d2d4 c5d4
+f3d4 d7d6
+d4c6 b7c6
+d1g4 g7g6
+e4e5 d6d5
+c1g5 f8e7
+! # col. 59m
+e2e4 c7c5
+g1f3 b8c6
+f1b5 g7g6
+o-o f8g7
+c2c3 g8f6
+f1e1 o-o
+d2d4 c5d4
+c3d4 d7d5
+e4e5 f6e4
+b1c3 e4c3
+b2c3 c6a5
+c1g5 c8f5
+f3d2 f8e8
+! # col. 60o
+e2e4 c7c5
+g1f3 b8c6
+f1b5 g7g6
+o-o f8g7
+f1e1 e7e5
+f1e1 o-o
+d2d4 c5d4
+c3d4 d7d5
+e4e5 f6e4
+b1c3 e4c3
+b2c3 c6a5
+c1g5 c8f5
+f3d2 f8e8
+! # col. 61c; Barczay-Szilagyi, Hungarian Chp. 1969
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 c8d7
+g5f6 g7f6
+d4b3 h8g8
+g2g3 f6f5
+d1d2 f8g7
+e4f5 d7f5
+f1g2 d8d7
+o-o g7c3
+b2c3 f5h3
+g2h3 d7h3
+! # col. 62e
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 c8d7
+d4b3 h7h6
+g5h4 a8c8
+f1e2 g7g5
+h4g3 h6h5
+h2h4 g5g4
+g3f4 c6e5
+d1d4 e5g6
+f4g5 f8g7
+o-o
+! # col. 63g; Matulovic-Masic, Sombor 1968
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 c8d7
+f2f4 d8b6
+d4b3 f6g4
+d1e2 c6d4
+c3d5 d4e2
+d5b6 a7b6
+e1e2 h7h6
+g5h4 g7g5
+h4g3 g5f4
+g3f4 f8g7
+c2c3 d7c6
+! # col. 64j; Liberzo-Stein, USSR Chp. 1969-70. Complete game (draw).
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 c8d7
+d1d3 c6d4
+d3d4 d8a5
+f2f4 e7e5
+d4d3 f8e7
+o-o-o d7c6
+c1b1 e5f4
+g5f4 o-o
+f1e2 f8e8
+e2f3 e7f8
+c3d5 f6d7
+d3d2 a5d2
+d1d2 a8c8
+h1d1 d7e5
+b2b3
+! # col. 65m; Bronstein-Stein, USSR 1969
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 c8d7
+d1d3 c6d4
+d3d4 d8a5
+f1e2 e7e5
+d4d3 a5c7
+e2g4 f8e7
+g5f6 e7f6
+o-o-o f6e7
+c3b5 d7b5
+d3b5 c7c6
+b5d5 c6d5
+d1d5
+! # col. 66b; Benko-R. Byrne, US Open Chp. 1968
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 c8d7
+d1d2 a8c8
+o-o-o c6d4
+d2d4 d8a5
+g5d2 a7a6
+f1c4 a5c5
+d4c5 c8c5
+c4b3 g7g6
+d2e3 c5c8
+e3d4 f8g7
+c3d5 f6h5
+d4g7 h5g7
+e4e5 c8c6
+d5b4 c6b6
+! # col. 66b alternate; Polgar-Nagy, Hungarian Chp. 1972
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 c8d7
+d1d2 a8c8
+o-o-o c6d4
+d2d4 d8a5
+g5d2 e7e5
+d4d3 a7a6
+c1b1 h7h6
+f2f3 a5c7
+g2g3 f8e7
+h2h4 b7b5
+! # col. 67c; Suetin-Gheorghiu, Hastings 1967/8. Draw.
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 c8d7
+d1d2 a8c8
+o-o-o c6d4
+d2d4 d8a5
+g5e3 a7a6
+f2f3 e7e6
+d4b6 a5b6
+e3b6 d7c6
+f1c4 c6e4
+c4e6 f7e6
+c3e4 f6e4
+f3e4 f8e7
+h1f1 e7g5
+c1b1 e8e7
+c2c3 h8f8
+b1c2 f8f1
+d1f1 c8f8
+! # col. 68d
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 c8d7
+d1d2 a8c8
+o-o-o c6d4
+d2d4 d8a5
+f2f4 e7e6
+e4e5 d6e5
+f4e5 c8c3
+g5d2 a5a2
+d2c3 g7g6
+! # col. 69fA1; Janosevic-Larsen, Belgrade 1964
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 c8d7
+d1d2 a8c8
+o-o-o c6d4
+d2d4 d8a5
+f2f4 c8c3
+b2c3 e7e5
+d4b4 a5b4
+c3b4 f6e4
+f1c4 b7b5
+c4d5 e4c3
+f4e5 h7h6
+g5h4 g7g5
+h4g3 c3e2
+c1b2 e2g3
+h2g3 f8g7
+! # col. 70g; Bednarski-Simagin, Polanica Zdroj 1968
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 c8d7
+d1d2 a8c8
+o-o-o c6d4
+d2d4 c8c3
+d4c3 f6e4
+c3e3 e4g5
+e3g5 d8b6
+f1c4 e7e6
+g5g3 g7g6
+c4b3 f8e7
+h2h4 h7h5
+h1e1 b6b4
+g3e3 a7a5
+e3d4
+! # col. 71d
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 e7e6
+d1d2 f8e7
+o-o-o c6d4
+d2d4 o-o
+f2f4 h7h6
+g5h4 d8a5
+f1c4 e6e5
+f4e5 d6e5
+d4d3 a5c5
+h4f6 e7f6
+! # col. 72g
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 e7e6
+d1d2 f8e7
+o-o-o c6d4
+d2d4 o-o
+f2f4 d8a5
+f1c4 c8d7
+c4b3 d7c6
+h1f1 b7b5
+g5f6 e7f6
+d4d6 f6c3
+d6c6 a8c8
+c6d7 c8d8
+d7e7 c3d2
+c1b1 d2f4
+d1d8 a5d8
+! # col. 73i
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 e7e6
+d1d2 f8e7
+o-o-o o-o
+d4b3 d8b6
+f2f3 a7a6
+g2g4 f8d8
+g5e3 b6c7
+h2h4 b7b5
+g4g5 f6d7
+g5g6 f7g6
+h4h5 g6h5
+h1h5 d7f6
+h5g5 c6e5
+d2g2 e7f8
+f3f4 e5c4
+f1c4 b5c4
+b3d4 a8b8
+d1g1 b8b7
+! # col. 74; Tal-Larsen, match 1969
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 e7e6
+d1d2 f8e7
+o-o-o o-o
+d4b3 a7a6
+g5f6 g7f6
+f1e2 g8h8
+e2h5 c8d7
+f2f4 b7b5
+c1b1
+! # col. 75k
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 e7e6
+d1d2 f8e7
+o-o-o o-o
+d4b5 d8a5
+g5f6 e7f6
+b5d6 f8d8
+f2f4 e6e5
+d2d5 a5c7
+f4f5 c6d4
+d6b5 c7a5
+d5c4 c8f5
+b2b4 a5a6
+! # col. 76b; Spasski-Larsen, Santa Monica 1966
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 e7e6
+d1d2 f8e7
+o-o-o o-o
+f2f4 h7h6
+g5h4 e6e5
+d4f5 c8f5
+e4f5 d8a5
+c1b1 a8d8
+h4f6 e7f6
+c3d5 a5d2
+d5f6 g7f6
+d1d2 e5f4
+! # col. 77e; Kujpers-Minev, Halle 1967
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 e7e6
+d1d2 f8e7
+o-o-o o-o
+f2f4 d6d5
+e4e5 f6d7
+h2h4 d7b6
+d2e3 c8d7
+g5e7 d8e7
+h4h5 c6a5
+d4b3 a5c4
+e3d4 f8c8
+c1b1 a7a5
+f4f5 a5a4
+f5f6 e7f8
+h1h3 c4b2
+b1b2 b6c4
+f1c4 c8c4
+d4d2
+! # col. 78h
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 e7e6
+d1d2 a7a6
+o-o-o c8d7
+f2f4 h7h6
+g5h4 f6e4
+d2e1 e4f6
+d4f5 d8a5
+f5d6 f8d6
+d1d6 o-o-o
+d6d1 e6e5
+f1c4 e5f4
+c3e4 d7e6
+c4e6 f7e6
+e4d6 c8b8
+e1e6 h8f8
+! # col. 79j; O'Kelly-Simagin corr. 1964
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 e7e6
+d1d2 a7a6
+o-o-o h7h6
+g5h4 f6e4
+d2f4 e4g5
+d4c6 b7c6
+f4a4 d8b6
+f2f4 g5h7
+f4f5 f8e7
+c3e4 a8b8
+a4a3 b6b5
+! # col. 80k; Di Camillo-R. Byrne, US Open Chp. 1958
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 e7e6
+d1d2 h7h6
+g5f6 g7f6
+o-o-o a7a6
+f2f4 c8d7
+f1e2 h6h5
+c1b1 d8b6
+d4b3 o-o-o
+h1f1 f8e7
+c3a4 b6a7
+c2c4 c6d4
+! # col. 81b
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 e7e6
+d4c6 b7c6
+e4e5 d6e5
+d1f3 f8e7
+f3c6 c8d7
+c6f3 e5e4
+c3e4 f6e4
+g5e7 d8a5
+! # col. 82e
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1g5 e7e6
+d1d3 f8e7
+a1d1 o-o
+f1e2 c8d7
+o-o c6d4
+d3d4 d7c6
+g1h1 d8a5
+f2f4 f8e8
+! # col. 83
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+h2h3 g7g6
+c1e3 f8g7
+d1d2 o-o
+o-o-o c6d4
+e3d4 d8a5
+c1b1 e7e5
+d4e3 c8e6
+! # BAD! -- col. 84i; Karaklajic-Taimanov, Yugoslavia-USSR, match 1956
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+c1e3 f6g4
+f1b5 g4e3
+f2e3 c8d7
+o-o e7e6
+5c6 b7c6
+e4e5 f8e7
+d1h5 o-o
+e5d6 e7d6
+c3e4 d6e7
+a1d1 d8c7
+d4b3 h7h6
+! # col. 85
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+d4e2 e7e6
+g2g3 d6d5
+e4d5 f6d5
+f1g2 d5c3
+d1d8 e8d8
+e2c3 c8d7
+c1d2 f8e7
+! # col. 86c; Carcia-Pomar, Havana 1969
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+f1c4 e7e5
+d4e2 c8e6
+c4e6 f7e6
+o-o f8e7
+f2f4 o-o
+e2g3 e5f4
+f1f4 d8b6
+g1h1 a8d8
+b2b3 d6d5
+e4d5 f6d5
+f4f8 e7f8
+c3d5 d8d5
+d1e1 c6d4
+c1e3 f8c5
+! # col. 87
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+f1c4 d8b6
+d4b3 e7e6
+o-o f8e7
+c1e3 b6c7
+f2f4 o-o
+c4d3 a7a6
+d1f3
+! # col. 88
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+f1c4 e7e6
+c1e3 d8c7
+d1e2 a7a6
+c4b3 c6a5
+g2g4 b7b5
+g4g5 f6d7
+o-o-o d7c5
+! # col. 89mA; Spasjevic-Ostojic, Belgrade 1966 (draw)
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+f1c4 e7e6
+c1e3 f8e7
+d1e2 a7a6
+o-o-o o-o
+c4b3 d8c7
+g2g4 c6d4
+d1d4 e6e5
+d4c4 c7d8
+g4g5 f6e8
+h1g1 c8d7
+c3d5 d7b5
+e3b6 d8d7
+e2g4 e7d8
+g4d7 b5d7
+c4c3 d7e6
+b6d8 a8d8
+d5e3 d8d7
+b3a4 d7c7
+! # col. 90o; Bogdanovic-Shamkovich, Sarajevo 1963
+e2e4 c7c5
+g1f3 b8c6
+d2d4 c5d4
+f3d4 g8f6
+b1c3 d7d6
+f1c4 e7e6
+c1e3 f8e7
+d1e2 o-o
+o-o-o c6d4
+e3d4 d8a5
+e4e5 d6e5
+d4e5 b7b6
+c3b5 c8a6
+e5c3 a5a4
+d1d4 a6b5
+c4b5 a4a2
+h1d1 f8d8
+d4a4 d8d1
+e2d1 a2d5
+d1d5 f6d5
+c3d4 e7g5
+c1b1 h7h5
+b5c6 a8d8
+a4a7 d5b4
+c6d7 b4c6
+! # Queen's Catalan, col. 1c; Kramer-Fichtl, Varna Olympics 1962
+d2d4 d7d5
+c2c4 e7e6
+g2g3 g8f6
+g1f3 f8e7
+f1g2 o-o
+o-o b8d7
+b1c3 c7c6
+b2b3 b7b6
+c1b2 c8b7
+d1c2 a8c8
+a1d1 d8c7
+e2e4 d5e4
+c3e4 f6e4
+c2e4 c6c5
+d4d5 e7f6
+e4c2 e6d5
+c4d5 f6b2
+c2b2 c8d8
+! # col. 2f
+d2d4 d7d5
+c2c4 e7e6
+g2g3 g8f6
+g1f3 f8e7
+f1g2 o-o
+o-o b8d7
+b1c3 d5c4
+e2e4 c7c6
+a2a4 a7a5
+d1e2 d7b6
+f1d1 e7b4
+f3e5 d8e7
+c1e3 c8d7
+e5c4 b6c4
+e2c4 e6e5
+d4e5 f6g4
+! # col. 3i; Geller-Medina, Beverwijk 1965
+d2d4 d7d5
+c2c4 e7e6
+g2g3 g8f6
+g1f3 f8e7
+f1g2 o-o
+o-o b8d7
+d1c2 b7b6
+c4d5 f6d5
+b1c3 c8b7
+c3d5 b7d5
+e2e4 d5b7
+f1d1 c7c5
+d4d5 e6d5
+e4d5 e7f6
+h2h4 h7h6
+! # col. 4k; Geller-Bisguier, Bled 1961
+d2d4 d7d5
+c2c4 e7e6
+g2g3 g8f6
+g1f3 f8e7
+f1g2 o-o
+o-o b8d7
+d1c2 c7c6
+b2b3 b7b6
+c1b2 c8b7
+b1c3 a8c8
+a1d1 b6b5
+c4c5 b5b4
+c3b1 f6e4
+f3e1 f7f5
+e1d3 a7a5
+d3f4 f8f6
+f2f3 e4g5
+! # col. 5m; Benko-Pachman, Budapest 1948
+d2d4 d7d5
+c2c4 e7e6
+g2g3 g8f6
+g1f3 f8e7
+f1g2 o-o
+o-o b8d7
+d1c2 c7c6
+b1d2 b7b6
+e2e4 c8b7
+b2b3 a8c8
+f1d1 d8c7
+c1b2 f8d8
+a1c1 c7b8
+c2b1 a7a5
+f3e5 b8a8
+! # col. 6
+d2d4 d7d5
+c2c4 e7e6
+g2g3 g8f6
+g1f3 f8e7
+f1g2 o-o
+o-o c7c6
+b1c3 b7b6
+f3e5 a7a5
+d1c2 c8a6
+f1d1 b6b5
+! # col. 7d; Evans-Poschel, US Jr. Chp. 1947
+d2d4 d7d5
+c2c4 e7e6
+g2g3 g8f6
+g1f3 c7c5
+c4d5 f6d5
+f1g2 c5d4
+o-o f8c5
+f3d4 o-o
+a2a3 b8c6
+d4c6 b7c6
+b2b4 c5e7
+c1b2 e7f6
+d1c2 f6b2
+c2b2 a7a5
+! # col. 8g; O'Kelly-Euwe, New York 1951
+d2d4 d7d5
+c2c4 e7e6
+g2g3 g8f6
+g1f3 d5c4
+f1g2 c7c5
+o-o b8c6
+d1a4 f6d7
+d4c5 f8c5
+a4c4 o-o
+b1c3 a7a6
+c3e4 c5e7
+c1e3 d7b6
+c4b3 b6d5
+f1d1 d8c7
+! # col. 9
+d2d4 d7d5
+c2c4 e7e6
+g2g3 g8f6
+g1f3 d5c4
+f1g2 b7b5
+a2a4 c7c6
+o-o c8b7
+f3e5 d8c8
+b2b3 c4b3
+d1b3 b5b4
+a4a5 f6d7
+! # col. 10l; Keres-Korchnoi, Curacao 1962
+d2d4 d7d5
+c2c4 e7e6
+g2g3 g8f6
+g1f3 d5c4
+d1a4 b8d7
+f1g2 a7a6
+a4c4 c7c5
+d4c5 f8c5
+o-o b7b5
+c4h4 c8b7
+b1d2 c5e7
+d2b3 a8c8
+h4d4 o-o
+c1d2 d7c5
+! # col. -- Accelerated Catalan
+d2d4 d7d5
+c2c4 e7e6
+g2g3 g8f6
+f1g2 d5c4
+d1a4 b8d7
+b1d2 c7c6
+a4c4 e6e5
+g1f3 d7b6
+c4d3 e5d4
+f3d4 f8e7
+o-o o-o
+! # col. 12e; Muller-Ratzek, Vienna 1951
+d2d4 d7d5
+c2c4 e7e6
+g2g3 g8f6
+f1g2 d5c4
+d1a4 c8d7
+a4c4 d7c6
+g1f3 c6d5
+c4d3 c7c5
+b1c3 d5c6
+o-o b8d7
+f1d1 d8b6
+e2e4 c5d4
+f3d4 f8c5
+d4c6 c5f2
+g1f1 b7c6
+c3a4 b6a5
+f1f2 a5a4
+d3d6
+! # col. 13f; Smyslov-Kere, USSR Chp. 1948
+d2d4 d7d5
+c2c4 e7e6
+g2g3 g8f6
+f1g2 d5c4
+d1a4 c8d7
+a4c4 d7c6
+g1f3 b8d7
+b1c3 d7b6
+c4d3 f8b4
+o-o o-o
+f1d1 h7h6
+c1d2 d8e7
+a2a3 b4c3
+d3c3 f8d8
+! # col. 14g
+d2d4 d7d5
+c2c4 e7e6
+g2g3 g8f6
+b1c3 d5c4
+d1a4 b8c6
+f1g2 c8d7
+a4c4 c6b4
+c4b3 c7c5
+g1f3 c5d4
+f3d4 e6e5
+d4f3 d7e6
+b3a4 e6d7
+! # col. 15; Stoltz-Vidmar, Groningen 1946
+d2d4 d7d5
+c2c4 e7e6
+g2g3 g8f6
+b1c3 f8e7
+f1g2 o-o
+g1f3 d5c4
+d1a4 a7a6
+a4c4 b7b5
+c4d3 c8b7
+! # col. 16
+d2d4 d7d5
+c2c4 e7e6
+g2g3 g8f6
+b1d2 c7c5
+d4c5 f8c5
+f1g2 b8c6
+g1f3 o-o
+o-o a7a5
+c4d5 e6d5
+d2b3 c5b6
+! # col. 17d; Mikenas-Aronin, USSR Chp. 1963
+d2d4 d7d5
+c2c4 e7e6
+g2g3 c7c5
+c4d5 e6d5
+g1f3 b8c6
+f1g2 g8f6
+o-o f8e7
+d4c5 e7c5
+b1d2 o-o
+d2b3 c5b6
+b3d4 f8e8
+b2b3 c6d4
+f3d4 b6d4
+d1d4 e8e2
+! # col. 18e
+d2d4 d7d5
+c2c4 e7e6
+g2g3 d5c4
+d1a4 c8d7
+a4c4 c7c5
+d4c5 d7c6
+g1f3 b8d7
+c1e3 g8f6
+f1g2 d8c7
+o-o c6d5
+c4a4 f8c5
+e3c5 c7c5
+b1c3 d5c6
+! # col. 19
+d2d4 d7d5
+c2c4 e7e6
+g2g3 f8b4
+c1d2 b4d2
+d1d2 g8f6
+g1f3 o-o
+f1g2 d8e7
+o-o b8c6
+f1c1
+! # col. 20
+d2d4 d7d5
+c2c4 e7e6
+g2g3 f8b4
+c1d2 b4e7
+f1g2 g8f6
+g1f3 o-o
+d1b3 b7b6
+c4d5 e6d5
+b1c3 c8b7
+o-o
+! # col. 21
+d2d4 g8f6
+c2c4 e7e6
+g2g3 e6e5
+g1f3 e5d4
+f3d4 d7d5
+f1g2 d5c4
+d1a4 c7c6
+a4c4 f8e7
+o-o o-o
+f1d1
+! # col. 22
+d2d4 g8f6
+c2c4 e7e6
+g2g3 c7c5
+g1f3 c5d4
+f3d4 d7d5
+f1g2 e6e5
+d4f3 d5d4
+o-o b8c6
+e2e3 f8e7
+e3d4 e5d4
+! # col. 23g
+d2d4 g8f6
+c2c4 e7e6
+g2g3 c7c5
+g1f3 c5d4
+f3d4 b8c6
+f1g2 d8b6
+d4c2 f8c5
+e2e3 o-o
+b1c3 b6a6
+d1d2 f8d8
+a2a3 d7d5
+b2b4 d5d4
+c3e4
+! # col. 24j; Smyslov-Petrosian, Moscow 1967
+d2d4 g8f6
+c2c4 e7e6
+g2g3 f8b4
+b1d2 c7c5
+d4c5 b4c5
+f1g2 b8c6
+g1f3 b7b6
+o-o c8b7
+a2a3 o-o
+b2b4 c5e7
+c1b2 a8c8
+d1b1
+! # col. 25
+d2d4 g8f6
+c2c4 e7e6
+g2g3 f8b4
+c1d2 b4d2
+d1d2 f6e4
+d2c2 f7f5
+f2f3 e4f6
+e2e4 f5e4
+f3e4 e6e5
+! # Alternate openings leading to the Catalan, line C
+g1f3 d7d5
+c2c4 e7e6
+g2g3 g8f6
+d2d4
+! # line D
+c2c4 g8f6
+d2d4 e7e6
+g2g3 d7d5
+! # line E
+d2d4 g8f6
+c2c4 e7e6
+g2g3 d7d5
+! # The Reti Opening, col. 1c; Muller-Lilenthal, Budapest 1933
+g1f3 d7d5
+c2c4 c7c6
+b2b3 g8f6
+g2g3 c8f5
+c1b2 e7e6
+f1g2 b8d7
+o-o f8d6
+d2d3 o-o
+b1c3 d8e7
+f1e1 e6e5
+c4d5 c6d5
+e2e4 d5e4
+d3e4 f5g6
+! # col. 2g; Bilek-Geller, Sousse 1967
+g1f3 d7d5
+c2c4 c7c6
+b2b3 g8f6
+g2g3 c8g4
+f1g2 e7e6
+c1b2 b8d7
+o-o f8e7
+d2d3 o-o
+b1d2 a7a5
+a2a3 d8b6
+d1c2 h7h6
+b2c3 f8c8
+f1e1 b6d8
+e2e4 d8f8
+! # col. 3k; Botvinnik-Fine, Nottingham 1936
+g1f3 d7d5
+c2c4 d5c4
+b1a3 c7c5
+a3c4 b8c6
+g2g3 e7e5
+f1g2 f7f6
+b2b3 g8e7
+c1b2 e7d5
+o-o f8e7
+f3h4 o-o
+d1b1 f8f7
+h4f5 c8e6
+f2f4 e5f4
+g3f4 d5b6
+g2e4 e6c4
+! # col. 4n; Katetov-Alekhin, Prague 1943
+g1f3 d7d5
+c2c4 d5d4
+e2e3 b8c6
+e3d4 c6d4
+f3d4 d8d4
+b1c3 e7e5
+d2d3 f8c5
+c1e3 d4d6
+c3b5 d6e7
+e3c5 e7c5
+d3d4 e5d4
+d1d4 c5d4
+b5d4 c8g4
+! # col. 5o
+g1f3 d7d5
+c2c4 d5d4
+e2e3 c7c5
+e3d4 c5d4
+g2g3 b8c6
+f1g2 g7g6
+d2d3 f8g7
+o-o e7e5
+f1e1 f7f6
+b2b4 c6b4
+d1a4 b4c6
+f3d4 d8d4
+g2c6 c8d7
+! # col. 6
+g1f3 d7d5
+c2c4 e7e6
+g2g3 g8f6
+f1g2 f8e7
+o-o o-o
+b2b3 c7c5
+c4d5 f6d5
+c1b2 b8c6
+d2d4 d5b4
+a2a3 b4a6
+d4c5 d8d1
+! # col. 7
+g1f3 d7d5
+c2c4 e7e6
+g2g3 g8f6
+f1g2 f8e7
+b1c3 o-o
+b2b3 c7c5
+c1b2 b8c6
+c4d5 e6d5
+a1c1 c8e6
+o-o a8c8
+d2d4 f8e8
+! # col. 8g; Kashdan-Horowitz, New York 1931
+g1f3 d7d5
+c2c4 e7e6
+g2g3 g8f6
+f1g2 b8d7
+b2b3 c7c6
+o-o f8d6
+c1b2 o-o
+b1c3 b7b6
+d2d3 c8b7
+e2e4 d5e4
+d3e4 d8c7
+d1e2 f8d8
+f1d1
+! # col. 9h; Abroshin-Krykov corr. 1960
+g1f3 d7d5
+c2c4 e7e6
+g2g3 g8f6
+f1g2 d5c4
+d1a4 c8d7
+a4c4 d7c6
+o-o c6d5
+c4a4 d8d7
+a4c2 b8c6
+b1c3 d5f3
+g2f3 c6d4
+c2d3 c7c6
+! # col. 10m; Teti-Tartakover, Semmering 1926
+g1f3 d7d5
+c2c4 e7e6
+g2g3 d5c4
+d1a4 c8d7
+a4c4 c7c5
+f3e5 b8c6
+e5d7 d8d7
+f1g2 g8f6
+d2d3 f8e7
+o-o c6d4
+b1c3 a8d8
+a2a4 f6d5
+! # Barcza System, col. 11
+g1f3 d7d5
+g2g3 g8f6
+f1g2 c8f5
+o-o c7c6
+c2c4 d5c4
+b1a3 e7e5
+a3c4 e5e4
+f3e1 f8c5
+d2d3 o-o
+c1e3 b8d7
+! # col. 12d; Benko-Petrosian, Curacao 1962
+g1f3 d7d5
+g2g3 g8f6
+f1g2 c8f5
+o-o c7c6
+d2d3 b8d7
+b1d2 h7h6
+d1e1 e7e6
+e2e4 f5h7
+e1e2 f8e7
+e4e5 f6g8
+d2b3 e7f8
+c2c4 g8e7
+b3d4 e7f5
+d4f5 h7f5
+c4d5 c6d5
+d3d4 a7a5
+c1e3 f8e7
+f1c1 o-o
+! # col. 13f; Bronstein-O'Kelly, Beverwijk 1963
+g1f3 d7d5
+g2g3 g8f6
+f1g2 c7c5
+o-o e7e6
+d2d3 b8c6
+b1d2 f8e7
+e2e4 o-o
+f1e1 d8c7
+e4e5 f6d7
+d1e2 b7b5
+h2h4 a7a5
+d2f1 c8a6
+f1h2 c6b4
+h4h5
+! # col. 14i; Evans-Olafsson, Dallas 1957
+g1f3 d7d5
+g2g3 g8f6
+f1g2 g7g6
+o-o f8g7
+d2d3 o-o
+b1d2 b8c6
+e2e4 e7e5
+c2c3 a7a5
+f1e1 d5e4
+d3e4 f6d7
+d1e2 b7b6
+d2c4 c8a6
+g2f1 d8f6
+! # col. 15
+g1f3 d7d5
+g2g3 g8f6
+f1g2 g7g6
+d2d4 f8g7
+o-o c7c6
+b2b3 b8d7
+c1b2 e7e5
+d4e5 f6g4
+b1d2 d7e5
+f3e5 g4e5
+! # col. 16d; Larsen-Mecking, Mallorca 1969
+g1f3 d7d5
+g2g3 c7c5
+f1g2 b8c6
+o-o e7e6
+d2d3 g7g6
+b1c3 f8g7
+a2a3 g8e7
+a1b1 o-o
+c1d2 a8b8
+b2b4 c5b4
+a3b4 b7b5
+e2e4 a7a5
+! # col. 17h; Benko-Bisguier, US Chp. 1963
+g1f3 d7d5
+g2g3 c8g4
+f1g2 b8d7
+c2c4 c7c6
+c4d5 c6d5
+b1c3 e7e6
+d1b3 d8b6
+b3b6 d7b6
+d2d3 a8c8
+c1e3 f8d6
+c3b5 d6b8
+o-o g8e7
+f1c1 c8c1
+a1c1 e7c6
+f3d4 e8d7
+! # col. 18j; Keene-Basman, Hastings 1966-7
+g1f3 d7d5
+g2g3 c8g4
+f1g2 g8f6
+c2c4 c7c6
+c4d5 g4f3
+g2f3 c6d5
+d1b3 d8d7
+b1c3 e7e6
+o-o b8c6
+f3g2 f8e7
+d2d3 o-o
+! # col. 19k
+g1f3 d7d5
+g2g3 c8g4
+f1g2 g8f6
+c2c4 c7c6
+d1c2 e7e6
+o-o f8e7
+b2b3 b8d7
+c1b2 o-o
+d2d3 a7a5
+b1d2 a5a4
+b2c3 a4b3
+a2b3 d8b6
+! # col. 20m
+g1f3 d7d5
+g2g3 c8g4
+f1g2 g8f6
+o-o c7c6
+c2c4 e7e6
+c4d5 g4f3
+g2f3 c6d5
+b1c3 b8c6
+d2d3 f8e7
+f3g2
+! # col. 21b; Savon-Aronin, USSR 1963
+g1f3 d7d5
+g2g3 b8c6
+d2d4 c8f5
+f1g2 c6b4
+b1a3 e7e6
+o-o g8f6
+f3h4 f5g4
+c2c4 c7c6
+a3c2 b4c2
+d1c2 f8e7
+h2h3 g4h5
+f2f3 h5g6
+h4g6 h7g6
+! # col. 22d; Fischer-Ivkov, Santa Monica 1966
+g1f3 d7d5
+g2g3 e7e6
+f1g2 c7c5
+o-o b8c6
+d2d3 f8d6
+e2e4 g8e7
+b1d2 o-o
+f3h4 b7b6
+f2f4 d5e4
+d3e4 c8a6
+f1e1 c5c4
+c2c3
+! # col. 23
+g1f3 d7d5
+g2g3 b8d7
+c2c4 e7e6
+f1g2 g8f6
+b1c3 f8e7
+o-o o-o
+d2d3 c7c5
+c4d5 e6d5
+c1g5 b7b6
+! # col. 24g; Benko-Bisguier, US Chp. 1976-7
+g1f3 d7d5
+g2g3 g8f6
+f1g2 b7b6
+c2c4 e7e6
+c4d5 e6d5
+o-o f8d6
+d2d4 o-o
+b1c3 c7c6
+f3e5 c8b7
+c1g5 h7h6
+g5f6 d8f6
+f2f4 f8d8
+e2e4
+! # col. 25; Rabinovich-Rauser, Moscow 1934
+g1f3 d7d5
+b2b3 c8g4
+c1b2 b8d7
+c2c4 e7e6
+e2e3 g8f6
+f1e2 c7c6
+f3d4 g4e2
+d1e2 f8d6
+f2f4 o-o
+! # col. 26e; Evans-Najdorf, Dallas 1967
+g1f3 c7c5
+g2g3 b8c6
+f1g2 g7g6
+o-o f8g7
+e2e4 d7d6
+c2c3 e7e5
+d2d3 g8h6
+f3e1 o-o
+f2f4 e5f4
+c1f4 h6g4
+b1a3 g4e5
+g1h1 d8b6
+d1d2 c8e6
+! # col. 27h; Van den Pol-Barden, Holland v. England 1960
+g1f3 f7f5
+g2g3 g8f6
+f1g2 g7g6
+d2d3 f8g7
+b1d2 d7d6
+e2e4 e7e5
+d2c4 o-o
+e4f5 g6f5
+c1e3 b8c6
+d3d4 e5e4
+! # col. 28m; Gufeld-Bokuchava, USSR Chp. prelims 1968
+g1f3 f7f5
+g2g3 g8f6
+f1g2 e7e6
+c2c4 f8e7
+o-o o-o
+d2d3 d7d6
+b1c3 b8c6
+a1b1 a7a5
+a2a3 d8e8
+b2b4 a5b4
+a3b4 e6e5
+! # col. 29p; Lundin-Tartakover, Groningen 1946
+g1f3 f7f5
+g2g3 g8f6
+f1g2 e7e6
+c2c4 f8e7
+o-o o-o
+b2b3 c7c5
+c1b2 b8c6
+b1c3 e6e5
+e2e3 d7d6
+d2d4
+! # col. 30
+g1f3 g7g6
+g2g3 f8g7
+f1g2 e7e5
+d2d3 b8c6
+e2e4 d7d6
+b1c3 g8e7
+c1e3 o-o
+d1d2 c6d4
+o-o
+! # King's Indian attack, col. 31a
+g1f3 g8f6
+g2g3 b7b5
+h2h4 b5b4
+d2d3 c8b7
+e2e4 d7d6
+f1g2 b8d7
+o-o e7e6
+h4h5 a8b8
+b1d2 f8e7
+d2c4 o-o
+! # col. 32d
+g1f3 g8f6
+g2g3 g7g6
+b2b4 f8g7
+c1b2 o-o
+f1g2 d7d5
+o-o c8g4
+c2c4 c7c6
+b1a3 b8d7
+a1c1 a7a5
+b4b5 a5a4
+d2d3 e7e5
+! # col. 33e; Olafsson-Kavalek, Wijik aan Zee 1969
+g1f3 g8f6
+g2g3 g7g6
+b2b3 f8g7
+c1b2 o-o
+f1g2 d7d6
+d2d4 f6d7
+b1c3 e7e5
+d1d2 f8e8
+d4e5 d7e5
+f3e5 g7e5
+! # col. 34h
+g1f3 g8f6
+g2g3 g7g6
+c2c4 d7d6
+f1g2 f8g7
+o-o o-o
+b1c3 b8d7
+d2d3 e7e5
+c1d2 d7c5
+b2b4 c5e6
+a1b1 f6e8
+a2a4 c7c6
+a4a5 e8c7
+! # col. 35
+g1f3 g8f6
+c2c4 g7g6
+b2b3 f8g7
+c1b2 o-o
+e2e3 d7d6
+f1e2 e7e5
+o-o f8e8
+b1c3 b8d7
+d2d3 c7c6
+! # col. 36d
+g1f3 g8f6
+c2c4 g7g6
+b1c3 d7d5
+c4d5 f6d5
+d1a4 c8d7
+a4b3 d5b6
+d2d4 f8g7
+c1f4 d7e6
+b3c2 b8c6
+a1d1
+! # col. 37f
+g1f3 g8f6
+c2c4 b7b6
+g2g3 c8b7
+f1g2 c7c5
+o-o g7g6
+b2b3 f8g7
+c1b2 o-o
+b1c3 d7d5
+c3d5 f6d5
+b2g7 g8g7
+c4d5 d8d5
+d2d4 b8a6
+! # col. 38h; Geller-Kholmov, Moscow 1969
+g1f3 g8f6
+c2c4 b7b6
+g2g3 c8b7
+f1g2 e7e6
+o-o f8e7
+b2b3 o-o
+c1b2 d7d5
+e2e3 b8d7
+b1c3 f6e4
+c4d5 e4c3
+b2c3 e6d5
+! # col. 39
+g1f3 g8f6
+b2b3 g7g6
+c2c4 f8g7
+c1b2 o-o
+g2g3 c7c5
+f1g2 b7b6
+o-o c8b7
+b1c3 e7e6
+a1b1 d8e7
+! # col. 40o; Lombardy-Burger, US Chp. 1969-70
+g1f3 g8f6
+b2b3 d7d5
+c1b2 e7e6
+e2e3 f8e7
+c2c4 o-o
+d2d4 b7b6
+f1d3 c8b7
+o-o b8d7
+b1d2 c7c5
+d1e2 f6e4
+a1c1 a8c8
+!
diff --git a/gnu/games/chess/gnuchess.c b/gnu/games/chess/gnuchess.c
new file mode 100644
index 000000000000..ac62953678d3
--- /dev/null
+++ b/gnu/games/chess/gnuchess.c
@@ -0,0 +1,2307 @@
+/*
+ C source for CHESS
+
+ Revision: 4-25-88
+
+ Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
+ Copyright (c) 1988 John Stanback
+
+ This file is part of CHESS.
+
+ CHESS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY. No author or distributor
+ accepts responsibility to anyone for the consequences of using it
+ or for whether it serves any particular purpose or works at all,
+ unless he says so in writing. Refer to the CHESS General Public
+ License for full details.
+
+ Everyone is granted permission to copy, modify and redistribute
+ CHESS, but only under the conditions described in the
+ CHESS General Public License. A copy of this license is
+ supposed to have been given to you along with CHESS so you
+ can know your rights and responsibilities. It should be in a
+ file named COPYING. Among other things, the copyright notice
+ and this notice must be preserved on all copies.
+*/
+
+
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef MSDOS
+#include <stdlib.h>
+#include <time.h>
+#include <alloc.h>
+#define ttblsz 4096
+#else
+#include <sys/param.h>
+#include <sys/times.h>
+#define ttblsz 16384
+#define huge
+#endif MSDOS
+
+#include "move.h"
+
+#define neutral 2
+#define white 0
+#define black 1
+#define no_piece 0
+#define pawn 1
+#define knight 2
+#define bishop 3
+#define rook 4
+#define queen 5
+#define king 6
+#define valueP 100
+#define valueN 350
+#define valueB 355
+#define valueR 550
+#define valueQ 1100
+#define valueK 1200
+#define ctlP 0x4000
+#define ctlN 0x2800
+#define ctlB 0x1800
+#define ctlR 0x0400
+#define ctlQ 0x0200
+#define ctlK 0x0100
+#define ctlBQ 0x1200
+#define ctlRQ 0x0600
+#define ctlNN 0x2000
+#define pxx " PNBRQK"
+#define qxx " pnbrqk"
+#define rxx "12345678"
+#define cxx "abcdefgh"
+#define check 0x0001
+#define capture 0x0002
+#define draw 0x0004
+#define promote 0x0008
+#define cstlmask 0x0010
+#define epmask 0x0020
+#define exact 0x0040
+#define pwnthrt 0x0080
+#define truescore 0x0001
+#define lowerbound 0x0002
+#define upperbound 0x0004
+#define maxdepth 30
+#define true 1
+#define false 0
+#define absv(x) ((x) < 0 ? -(x) : (x))
+#if (NEWMOVE < 1)
+#define taxicab(a,b) (abs(column[a]-column[b]) + abs(row[a]-row[b]))
+#endif
+struct leaf
+ {
+ short f,t,score,reply;
+ unsigned short flags;
+ };
+struct GameRec
+ {
+ unsigned short gmove;
+ short score,depth,time,piece,color;
+ long nodes;
+ };
+struct TimeControlRec
+ {
+ short moves[2];
+ long clock[2];
+ };
+struct BookEntry
+ {
+ struct BookEntry *next;
+ unsigned short *mv;
+ };
+struct hashval
+ {
+ unsigned long bd;
+ unsigned short key;
+ };
+struct hashentry
+ {
+ unsigned long hashbd;
+ unsigned short mv,flags;
+ short score,depth;
+ };
+
+char mvstr1[5],mvstr2[5];
+struct leaf Tree[2000],*root;
+short TrPnt[maxdepth],board[64],color[64];
+short row[64],column[64],locn[8][8],Pindex[64],svalue[64];
+short PieceList[2][16],PieceCnt[2],atak[2][64],PawnCnt[2][8];
+short castld[2],kingmoved[2],mtl[2],pmtl[2],emtl[2],hung[2];
+short c1,c2,*atk1,*atk2,*PC1,*PC2,EnemyKing;
+short mate,post,opponent,computer,Sdepth,Awindow,Bwindow,dither;
+long ResponseTime,ExtraTime,Level,et,et0,time0,cputimer,ft;
+long NodeCnt,evrate,ETnodes,EvalNodes,HashCnt;
+short quit,reverse,bothsides,hashflag,InChk,player,force,easy,beep;
+short wking,bking,FROMsquare,TOsquare,timeout,Zscore,zwndw,xwndw,slk;
+short INCscore;
+short HasPawn[2],HasKnight[2],HasBishop[2],HasRook[2],HasQueen[2];
+short ChkFlag[maxdepth],CptrFlag[maxdepth],PawnThreat[maxdepth];
+short Pscore[maxdepth],Tscore[maxdepth],Threat[maxdepth];
+struct GameRec GameList[240];
+short GameCnt,Game50,epsquare,lpost,rcptr,contempt;
+short MaxSearchDepth;
+struct BookEntry *Book;
+struct TimeControlRec TimeControl;
+short TCflag,TCmoves,TCminutes,OperatorTime;
+short otherside[3]={1,0,2};
+short rank7[3]={6,1,0};
+short map[64]=
+ {0,1,2,3,4,5,6,7,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
+ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
+ 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
+ 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,
+ 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
+ 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77};
+short unmap[120]=
+ {0,1,2,3,4,5,6,7,-1,-1,-1,-1,-1,-1,-1,-1,
+ 8,9,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,
+ 16,17,18,19,20,21,22,23,-1,-1,-1,-1,-1,-1,-1,-1,
+ 24,25,26,27,28,29,30,31,-1,-1,-1,-1,-1,-1,-1,-1,
+ 32,33,34,35,36,37,38,39,-1,-1,-1,-1,-1,-1,-1,-1,
+ 40,41,42,43,44,45,46,47,-1,-1,-1,-1,-1,-1,-1,-1,
+ 48,49,50,51,52,53,54,55,-1,-1,-1,-1,-1,-1,-1,-1,
+ 56,57,58,59,60,61,62,63};
+short Dcode[120]=
+ {0,1,1,1,1,1,1,1,0,0,0,0,0,0,0x0E,0x0F,
+ 0x10,0x11,0x12,0,0,0,0,0,0,0,0,0,0,0,0x0F,0x1F,
+ 0x10,0x21,0x11,0,0,0,0,0,0,0,0,0,0,0x0F,0,0,
+ 0x10,0,0,0x11,0,0,0,0,0,0,0,0,0x0F,0,0,0,
+ 0x10,0,0,0,0x11,0,0,0,0,0,0,0x0F,0,0,0,0,
+ 0x10,0,0,0,0,0x11,0,0,0,0,0x0F,0,0,0,0,0,
+ 0x10,0,0,0,0,0,0x11,0,0,0x0F,0,0,0,0,0,0,
+ 0x10,0,0,0,0,0,0,0x11};
+short Stboard[64]=
+ {rook,knight,bishop,queen,king,bishop,knight,rook,
+ pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn,
+ rook,knight,bishop,queen,king,bishop,knight,rook};
+short Stcolor[64]=
+ {white,white,white,white,white,white,white,white,
+ white,white,white,white,white,white,white,white,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ black,black,black,black,black,black,black,black,
+ black,black,black,black,black,black,black,black};
+short sweep[7]= {false,false,false,true,true,true,false};
+short Dpwn[3]={4,6,0};
+short Dstart[7]={6,4,8,4,0,0,0};
+short Dstop[7]={7,5,15,7,3,7,7};
+short Dir[16]={1,0x10,-1,-0x10,0x0F,0x11,-0x0F,-0x11,
+ 0x0E,-0x0E,0x12,-0x12,0x1F,-0x1F,0x21,-0x21};
+short Pdir[34]={0,0x38,0,0,0,0,0,0,0,0,0,0,0,0,0x02,0x35,
+ 0x38,0x35,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0x02,
+ 0,0x02};
+short pbit[7]={0,0x01,0x02,0x04,0x08,0x10,0x20};
+unsigned short killr0[maxdepth],killr1[maxdepth],killr2[maxdepth];
+unsigned short killr3[maxdepth],PrVar[maxdepth];
+unsigned short PV,hint,Swag0,Swag1,Swag2,Swag3,Swag4;
+unsigned short hashkey;
+unsigned long hashbd;
+struct hashval hashcode[2][7][64];
+struct hashentry huge *ttable,*ptbl;
+unsigned char history[8192];
+
+short Mwpawn[64],Mbpawn[64],Mknight[2][64],Mbishop[2][64];
+short Mking[2][64],Kfield[2][64];
+short value[7]={0,valueP,valueN,valueB,valueR,valueQ,valueK};
+short control[7]={0,ctlP,ctlN,ctlB,ctlR,ctlQ,ctlK};
+short PassedPawn0[8]={0,60,80,120,200,360,600,800};
+short PassedPawn1[8]={0,30,40,60,100,180,300,800};
+short PassedPawn2[8]={0,15,25,35,50,90,140,800};
+short PassedPawn3[8]={0,5,10,15,20,30,140,800};
+short ISOLANI[8] = {-12,-16,-20,-24,-24,-20,-16,-12};
+short BACKWARD[8] = {-6,-10,-15,-21,-28,-28,-28,-28};
+short BMBLTY[14] = {-2,0,2,4,6,8,10,12,13,14,15,16,16,16};
+short RMBLTY[14] = {0,2,4,6,8,10,11,12,13,14,14,14,14,14};
+short Kthreat[16] = {0,-8,-20,-36,-52,-68,-80,-80,-80,-80,-80,-80,
+ -80,-80,-80,-80};
+short KNIGHTPOST,KNIGHTSTRONG,BISHOPSTRONG,KATAK,KBNKsq;
+short PEDRNK2B,PWEAKH,PADVNCM,PADVNCI,PAWNSHIELD,PDOUBLED,PBLOK;
+short RHOPN,RHOPNX,KHOPN,KHOPNX,KSFTY;
+short ATAKD,HUNGP,HUNGX,KCASTLD,KMOVD,XRAY,PINVAL;
+short stage,stage2,Zwmtl,Zbmtl,Developed[2],PawnStorm;
+short PawnBonus,BishopBonus,RookBonus;
+short KingOpening[64]=
+ { 0, 0, -4,-10,-10, -4, 0, 0,
+ -4, -4, -8,-12,-12, -8, -4, -4,
+ -12,-16,-20,-20,-20,-20,-16,-12,
+ -16,-20,-24,-24,-24,-24,-20,-16,
+ -16,-20,-24,-24,-24,-24,-20,-16,
+ -12,-16,-20,-20,-20,-20,-16,-12,
+ -4, -4, -8,-12,-12, -8, -4, -4,
+ 0, 0, -4,-10,-10, -4, 0, 0};
+short KingEnding[64]=
+ { 0, 6,12,18,18,12, 6, 0,
+ 6,12,18,24,24,18,12, 6,
+ 12,18,24,30,30,24,18,12,
+ 18,24,30,36,36,30,24,18,
+ 18,24,30,36,36,30,24,18,
+ 12,18,24,30,30,24,18,12,
+ 6,12,18,24,24,18,12, 6,
+ 0, 6,12,18,18,12, 6, 0};
+short DyingKing[64]=
+ { 0, 8,16,24,24,16, 8, 0,
+ 8,32,40,48,48,40,32, 8,
+ 16,40,56,64,64,56,40,16,
+ 24,48,64,72,72,64,48,24,
+ 24,48,64,72,72,64,48,24,
+ 16,40,56,64,64,56,40,16,
+ 8,32,40,48,48,40,32, 8,
+ 0, 8,16,24,24,16, 8, 0};
+short KBNK[64]=
+ {99,90,80,70,60,50,40,40,
+ 90,80,60,50,40,30,20,40,
+ 80,60,40,30,20,10,30,50,
+ 70,50,30,10, 0,20,40,60,
+ 60,40,20, 0,10,30,50,70,
+ 50,30,10,20,30,40,60,80,
+ 40,20,30,40,50,60,80,90,
+ 40,40,50,60,70,80,90,99};
+short pknight[64]=
+ { 0, 4, 8,10,10, 8, 4, 0,
+ 4, 8,16,20,20,16, 8, 4,
+ 8,16,24,28,28,24,16, 8,
+ 10,20,28,32,32,28,20,10,
+ 10,20,28,32,32,28,20,10,
+ 8,16,24,28,28,24,16, 8,
+ 4, 8,16,20,20,16, 8, 4,
+ 0, 4, 8,10,10, 8, 4, 0};
+short pbishop[64]=
+ {14,14,14,14,14,14,14,14,
+ 14,22,18,18,18,18,22,14,
+ 14,18,22,22,22,22,18,14,
+ 14,18,22,22,22,22,18,14,
+ 14,18,22,22,22,22,18,14,
+ 14,18,22,22,22,22,18,14,
+ 14,22,18,18,18,18,22,14,
+ 14,14,14,14,14,14,14,14};
+short PawnAdvance[64]=
+ { 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 4, 0, 0, 4, 4, 4,
+ 6, 8, 2,10,10, 2, 8, 6,
+ 6, 8,12,16,16,12, 8, 6,
+ 8,12,16,24,24,16,12, 8,
+ 12,16,24,32,32,24,16,12,
+ 12,16,24,32,32,24,16,12,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+
+
+main(argc,argv)
+int argc; char *argv[];
+{
+#ifdef MSDOS
+ ttable = (struct hashentry huge *)farmalloc(ttblsz *
+ (unsigned long)sizeof(struct hashentry));
+#else
+ ttable = (struct hashentry *)malloc(ttblsz *
+ (unsigned long)sizeof(struct hashentry));
+#endif
+ Level = 0; TCflag = false; OperatorTime = 0;
+ if (argc == 2) Level = atoi(argv[1]);
+ if (argc == 3)
+ {
+ TCmoves = atoi(argv[1]); TCminutes = atoi(argv[2]); TCflag = true;
+ }
+ Initialize();
+ NewGame();
+#if (NEWMOVE > 0)
+ Initialize_dist();
+#if (NEWMOVE > 1)
+ Initialize_moves();
+#endif
+#endif
+ while (!(quit))
+ {
+ if (bothsides && !mate) SelectMove(opponent,1); else InputCommand();
+ if (!(quit || mate || force)) SelectMove(computer,1);
+ }
+ ExitChess();
+}
+
+
+
+/* ............ INTERFACE ROUTINES ........................... */
+
+int VerifyMove(s,iop,mv)
+char s[];
+short iop;
+unsigned short *mv;
+
+/*
+ Compare the string 's' to the list of legal moves available for the
+ opponent. If a match is found, make the move on the board.
+*/
+
+{
+static short pnt,tempb,tempc,tempsf,tempst,cnt;
+static struct leaf xnode;
+struct leaf *node;
+
+ *mv = 0;
+ if (iop == 2)
+ {
+ UnmakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst);
+ return(false);
+ }
+ cnt = 0;
+ MoveList(opponent,2);
+ pnt = TrPnt[2];
+ while (pnt < TrPnt[3])
+ {
+ node = &Tree[pnt++];
+ algbr(node->f,node->t,(short) node->flags & cstlmask);
+ if (strcmp(s,mvstr1) == 0 || strcmp(s,mvstr2) == 0)
+ {
+ cnt++; xnode = *node;
+ }
+ }
+ if (cnt == 1)
+ {
+ MakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst);
+ if (SqAtakd(PieceList[opponent][0],computer))
+ {
+ UnmakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst);
+ ShowMessage("Illegal Move!!");
+ return(false);
+ }
+ else
+ {
+ if (iop == 1) return(true);
+ if (xnode.flags & epmask) UpdateDisplay(0,0,1,0);
+ else UpdateDisplay(xnode.f,xnode.t,0,xnode.flags & cstlmask);
+ if (xnode.flags & cstlmask) Game50 = GameCnt;
+ else if (board[xnode.t] == pawn || (xnode.flags & capture))
+ Game50 = GameCnt;
+ GameList[GameCnt].depth = GameList[GameCnt].score = 0;
+ GameList[GameCnt].nodes = 0;
+ ElapsedTime(1);
+ GameList[GameCnt].time = (short)et;
+ TimeControl.clock[opponent] -= et;
+ --TimeControl.moves[opponent];
+ *mv = (xnode.f << 8) + xnode.t;
+ algbr(xnode.f,xnode.t,false);
+ return(true);
+ }
+ }
+ if (cnt > 1) ShowMessage("Ambiguous Move!");
+ return(false);
+}
+
+
+NewGame()
+
+/*
+ Reset the board and other variables to start a new game.
+*/
+
+{
+short l,r,c,p;
+
+ mate = quit = reverse = bothsides = post = false;
+ hashflag = force = PawnStorm = false;
+ beep = rcptr = easy = true;
+ lpost = NodeCnt = epsquare = et0 = 0;
+ dither = 0;
+ Awindow = 90;
+ Bwindow = 90;
+ xwndw = 90;
+ MaxSearchDepth = 29;
+ contempt = 0;
+ GameCnt = -1; Game50 = 0;
+ Zwmtl = Zbmtl = 0;
+ Developed[white] = Developed[black] = false;
+ castld[white] = castld[black] = false;
+ kingmoved[white] = kingmoved[black] = 0;
+ PawnThreat[0] = CptrFlag[0] = Threat[0] = false;
+ Pscore[0] = 12000; Tscore[0] = 12000;
+ opponent = white; computer = black;
+ for (r = 0; r < 8; r++)
+ for (c = 0; c < 8; c++)
+ {
+ l = 8*r+c; locn[r][c] = l;
+ row[l] = r; column[l] = c;
+ board[l] = Stboard[l]; color[l] = Stcolor[l];
+ }
+ for (c = white; c <= black; c++)
+ for (p = pawn; p <= king; p++)
+ for (l = 0; l < 64; l++)
+ {
+ hashcode[c][p][l].key = (unsigned short)rand();
+ hashcode[c][p][l].bd = ((unsigned long)rand() << 16) +
+ (unsigned long)rand();
+ }
+ ClrScreen();
+ if (TCflag) SetTimeControl();
+ else if (Level == 0) SelectLevel();
+ UpdateDisplay(0,0,1,0);
+ InitializeStats();
+ time0 = time((long *)0);
+ ElapsedTime(1);
+ GetOpenings();
+}
+
+
+algbr(f,t,iscastle)
+short f,t,iscastle;
+{
+ mvstr1[0] = cxx[column[f]]; mvstr1[1] = rxx[row[f]];
+ mvstr1[2] = cxx[column[t]]; mvstr1[3] = rxx[row[t]];
+ mvstr2[0] = qxx[board[f]];
+ mvstr2[1] = mvstr1[2]; mvstr2[2] = mvstr1[3];
+ mvstr1[4] = '\0'; mvstr2[3] = '\0';
+ if (iscastle)
+ if (t > f) strcpy(mvstr2,"o-o");
+ else strcpy(mvstr2,"o-o-o");
+}
+
+
+/* ............ MOVE GENERATION & SEARCH ROUTINES .............. */
+
+SelectMove(side,iop)
+short side,iop;
+
+/*
+ Select a move by calling function search() at progressively deeper
+ ply until time is up or a mate or draw is reached. An alpha-beta
+ window of -90 to +90 points is set around the score returned from the
+ previous iteration. If Sdepth != 0 then the program has correctly
+ predicted the opponents move and the search will start at a depth of
+ Sdepth+1 rather than a depth of 1.
+*/
+
+{
+static short i,alpha,beta,score,tempb,tempc,tempsf,tempst,xside,rpt;
+
+ timeout = false;
+ xside = otherside[side];
+ if (iop != 2) player = side;
+ if (TCflag)
+ {
+ if (((TimeControl.moves[side] + 3) - OperatorTime) != 0)
+ ResponseTime = (TimeControl.clock[side]) /
+ (TimeControl.moves[side] + 3) -
+ OperatorTime;
+ else ResponseTime = 0;
+ ResponseTime += (ResponseTime*TimeControl.moves[side])/(2*TCmoves+1);
+ }
+ else ResponseTime = Level;
+ if (iop == 2) ResponseTime = 999;
+ if (Sdepth > 0 && root->score > Zscore-zwndw) ResponseTime -= ft;
+ else if (ResponseTime < 1) ResponseTime = 1;
+ ExtraTime = 0;
+ ExaminePosition();
+ ScorePosition(side,&score);
+ ShowSidetomove();
+
+ if (Sdepth == 0)
+ {
+ ZeroTTable();
+ SearchStartStuff(side);
+ for (i = 0; i < 8192; i++) history[i] = 0;
+ FROMsquare = TOsquare = -1;
+ PV = 0;
+ if (iop != 2) hint = 0;
+ for (i = 0; i < maxdepth; i++)
+ PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
+ alpha = score-90; beta = score+90;
+ rpt = 0;
+ TrPnt[1] = 0; root = &Tree[0];
+ MoveList(side,1);
+ for (i = TrPnt[1]; i < TrPnt[2]; i++) pick(i,TrPnt[2]-1);
+ if (Book != NULL) OpeningBook();
+ if (Book != NULL) timeout = true;
+ NodeCnt = ETnodes = EvalNodes = HashCnt = 0;
+ Zscore = 0; zwndw = 20;
+ }
+
+ while (!timeout && Sdepth < MaxSearchDepth)
+ {
+ Sdepth++;
+ ShowDepth(' ');
+ score = search(side,1,Sdepth,alpha,beta,PrVar,&rpt);
+ for (i = 1; i <= Sdepth; i++) killr0[i] = PrVar[i];
+ if (score < alpha)
+ {
+ ShowDepth('-');
+ ExtraTime = 10*ResponseTime;
+ ZeroTTable();
+ score = search(side,1,Sdepth,-9000,beta,PrVar,&rpt);
+ }
+ if (score > beta && !(root->flags & exact))
+ {
+ ShowDepth('+');
+ ExtraTime = 0;
+ ZeroTTable();
+ score = search(side,1,Sdepth,alpha,9000,PrVar,&rpt);
+ }
+ score = root->score;
+ if (!timeout)
+ for (i = TrPnt[1]+1; i < TrPnt[2]; i++) pick(i,TrPnt[2]-1);
+ ShowResults(score,PrVar,'.');
+ for (i = 1; i <= Sdepth; i++) killr0[i] = PrVar[i];
+ if (score > Zscore-zwndw && score > Tree[1].score+250) ExtraTime = 0;
+ else if (score > Zscore-3*zwndw) ExtraTime = ResponseTime;
+ else ExtraTime = 3*ResponseTime;
+ if (root->flags & exact) timeout = true;
+ if (Tree[1].score < -9000) timeout = true;
+ if (4*et > 2*ResponseTime + ExtraTime) timeout = true;
+ if (!timeout)
+ {
+ Tscore[0] = score;
+ if (Zscore == 0) Zscore = score;
+ else Zscore = (Zscore+score)/2;
+ }
+ zwndw = 20+abs(Zscore/12);
+ beta = score + Bwindow;
+ if (Zscore < score) alpha = Zscore - Awindow - zwndw;
+ else alpha = score - Awindow - zwndw;
+ }
+
+ score = root->score;
+ if (rpt >= 2 || score < -12000) root->flags |= draw;
+ if (iop == 2) return(0);
+ if (Book == NULL) hint = PrVar[2];
+ ElapsedTime(1);
+
+ if (score > -9999 && rpt <= 2)
+ {
+ MakeMove(side,root,&tempb,&tempc,&tempsf,&tempst);
+ algbr(root->f,root->t,(short) root->flags & cstlmask);
+ }
+ else mvstr1[0] = '\0';
+ OutputMove();
+ if (score == -9999 || score == 9998) mate = true;
+ if (mate) hint = 0;
+ if (root->flags & cstlmask) Game50 = GameCnt;
+ else if (board[root->t] == pawn || (root->flags & capture))
+ Game50 = GameCnt;
+ GameList[GameCnt].score = score;
+ GameList[GameCnt].nodes = NodeCnt;
+ GameList[GameCnt].time = (short)et;
+ GameList[GameCnt].depth = Sdepth;
+ if (TCflag)
+ {
+ TimeControl.clock[side] -= (et + OperatorTime);
+ if (--TimeControl.moves[side] == 0) SetTimeControl();
+ }
+ if ((root->flags & draw) && bothsides) quit = true;
+ if (GameCnt > 238) quit = true;
+ player = xside;
+ Sdepth = 0;
+ fflush(stdin);
+ return(0);
+}
+
+
+OpeningBook()
+
+/*
+ Go thru each of the opening lines of play and check for a match with
+ the current game listing. If a match occurs, generate a random number.
+ If this number is the largest generated so far then the next move in
+ this line becomes the current "candidate". After all lines are
+ checked, the candidate move is put at the top of the Tree[] array and
+ will be played by the program. Note that the program does not handle
+ book transpositions.
+*/
+
+{
+short j,pnt;
+unsigned short m,*mp;
+unsigned r,r0;
+struct BookEntry *p;
+
+ srand((unsigned)time0);
+ r0 = m = 0;
+ p = Book;
+ while (p != NULL)
+ {
+ mp = p->mv;
+ for (j = 0; j <= GameCnt; j++)
+ if (GameList[j].gmove != *(mp++)) break;
+ if (j > GameCnt)
+ if ((r=rand()) > r0)
+ {
+ r0 = r; m = *mp;
+ hint = *(++mp);
+ }
+ p = p->next;
+ }
+
+ for (pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++)
+ if ((Tree[pnt].f<<8) + Tree[pnt].t == m) Tree[pnt].score = 0;
+ pick(TrPnt[1],TrPnt[2]-1);
+ if (Tree[TrPnt[1]].score < 0) Book = NULL;
+}
+
+
+#define UpdateSearchStatus\
+{\
+ if (post) ShowCurrentMove(pnt,node->f,node->t);\
+ if (pnt > TrPnt[1])\
+ {\
+ d = best-Zscore; e = best-node->score;\
+ if (best < alpha) ExtraTime = 10*ResponseTime;\
+ else if (d > -zwndw && e > 4*zwndw) ExtraTime = -ResponseTime/3;\
+ else if (d > -zwndw) ExtraTime = 0;\
+ else if (d > -3*zwndw) ExtraTime = ResponseTime;\
+ else if (d > -9*zwndw) ExtraTime = 3*ResponseTime;\
+ else ExtraTime = 5*ResponseTime;\
+ }\
+}
+
+int search(side,ply,depth,alpha,beta,bstline,rpt)
+short side,ply,depth,alpha,beta,*rpt;
+unsigned short bstline[];
+
+/*
+ Perform an alpha-beta search to determine the score for the current
+ board position. If depth <= 0 only capturing moves, pawn promotions
+ and responses to check are generated and searched, otherwise all
+ moves are processed. The search depth is modified for check evasions,
+ certain re-captures and threats. Extensions may continue for up to 11
+ ply beyond the nominal search depth.
+*/
+
+#define prune (cf && score+node->score < alpha)
+#define ReCapture (rcptr && score > alpha && score < beta &&\
+ ply > 2 && CptrFlag[ply-1] && CptrFlag[ply-2])
+#define MateThreat (ply < Sdepth+4 && ply > 4 &&\
+ ChkFlag[ply-2] && ChkFlag[ply-4] &&\
+ ChkFlag[ply-2] != ChkFlag[ply-4])
+
+{
+register short j,pnt;
+short best,tempb,tempc,tempsf,tempst;
+short xside,pbst,d,e,cf,score,rcnt;
+unsigned short mv,nxtline[maxdepth];
+struct leaf *node,tmp;
+
+ NodeCnt++;
+ xside = otherside[side];
+ if (depth < 0) depth = 0;
+
+ if (ply <= Sdepth+3) repetition(rpt); else *rpt = 0;
+ if (*rpt >= 2) return(0);
+
+ score = evaluate(side,xside,ply,alpha,beta);
+ if (score > 9000)
+ {
+ bstline[ply] = 0;
+ return(score);
+ }
+
+ if (depth > 0)
+ {
+ if (InChk || PawnThreat[ply-1] || ReCapture) ++depth;
+ }
+ else
+ {
+ if (score >= alpha &&
+ (InChk || PawnThreat[ply-1] || Threat[ply-1])) ++depth;
+ else if (score <= beta && MateThreat) ++depth;
+ }
+
+ if (depth > 0 && hashflag && ply > 1)
+ {
+ ProbeTTable(side,depth,&alpha,&beta,&score);
+ bstline[ply] = PV;
+ bstline[ply+1] = 0;
+ if (beta == -20000) return(score);
+ if (alpha > beta) return(alpha);
+ }
+
+ if (Sdepth == 1) d = 7; else d = 11;
+ if (ply > Sdepth+d || (depth < 1 && score > beta)) return(score);
+
+ if (ply > 1)
+ if (depth > 0) MoveList(side,ply);
+ else CaptureList(side,xside,ply);
+
+ if (TrPnt[ply] == TrPnt[ply+1]) return(score);
+
+ cf = (depth < 1 && ply > Sdepth+1 && !ChkFlag[ply-2] && !slk);
+
+ if (depth > 0) best = -12000; else best = score;
+ if (best > alpha) alpha = best;
+
+ for (pnt = pbst = TrPnt[ply];
+ pnt < TrPnt[ply+1] && best <= beta;
+ pnt++)
+ {
+ if (ply > 1) pick(pnt,TrPnt[ply+1]-1);
+ node = &Tree[pnt];
+ mv = (node->f << 8) + node->t;
+ nxtline[ply+1] = 0;
+
+ if (prune) break;
+ if (ply == 1) UpdateSearchStatus;
+
+ if (!(node->flags & exact))
+ {
+ MakeMove(side,node,&tempb,&tempc,&tempsf,&tempst);
+ CptrFlag[ply] = (node->flags & capture);
+ PawnThreat[ply] = (node->flags & pwnthrt);
+ Tscore[ply] = node->score;
+ PV = node->reply;
+ node->score = -search(xside,ply+1,depth-1,-beta,-alpha,
+ nxtline,&rcnt);
+ if (abs(node->score) > 9000) node->flags |= exact;
+ else if (rcnt == 1) node->score /= 2;
+ if (rcnt >= 2 || GameCnt-Game50 > 99 ||
+ (node->score == 9999-ply && !ChkFlag[ply]))
+ {
+ node->flags |= draw; node->flags |= exact;
+ if (side == computer) node->score = contempt;
+ else node->score = -contempt;
+ }
+ node->reply = nxtline[ply+1];
+ UnmakeMove(side,node,&tempb,&tempc,&tempsf,&tempst);
+ }
+ if (node->score > best && !timeout)
+ {
+ if (depth > 0)
+ if (node->score > alpha && !(node->flags & exact))
+ node->score += depth;
+ best = node->score; pbst = pnt;
+ if (best > alpha) alpha = best;
+ for (j = ply+1; nxtline[j] > 0; j++) bstline[j] = nxtline[j];
+ bstline[j] = 0;
+ bstline[ply] = mv;
+ if (ply == 1)
+ {
+ if (best == alpha)
+ {
+ tmp = Tree[pnt];
+ for (j = pnt-1; j >= 0; j--) Tree[j+1] = Tree[j];
+ Tree[0] = tmp;
+ pbst = 0;
+ }
+ if (Sdepth > 2)
+ if (best > beta) ShowResults(best,bstline,'+');
+ else if (best < alpha) ShowResults(best,bstline,'-');
+ else ShowResults(best,bstline,'&');
+ }
+ }
+ if (NodeCnt > ETnodes) ElapsedTime(0);
+ if (timeout) return(-Tscore[ply-1]);
+ }
+
+ node = &Tree[pbst];
+ mv = (node->f<<8) + node->t;
+ if (hashflag && ply <= Sdepth && *rpt == 0 && best == alpha)
+ PutInTTable(side,best,depth,alpha,beta,mv);
+ if (depth > 0)
+ {
+ j = (node->f<<6) + node->t; if (side == black) j |= 0x1000;
+ if (history[j] < 150) history[j] += 2*depth;
+ if (node->t != (GameList[GameCnt].gmove & 0xFF))
+ if (best <= beta) killr3[ply] = mv;
+ else if (mv != killr1[ply])
+ {
+ killr2[ply] = killr1[ply];
+ killr1[ply] = mv;
+ }
+ if (best > 9000) killr0[ply] = mv; else killr0[ply] = 0;
+ }
+ return(best);
+}
+
+
+evaluate(side,xside,ply,alpha,beta)
+short side,xside,ply,alpha,beta;
+
+/*
+ Compute an estimate of the score by adding the positional score from
+ the previous ply to the material difference. If this score falls
+ inside a window which is 180 points wider than the alpha-beta window
+ (or within a 50 point window during quiescence search) call
+ ScorePosition() to determine a score, otherwise return the estimated
+ score. If one side has only a king and the other either has no pawns
+ or no pieces then the function ScoreLoneKing() is called.
+*/
+
+{
+short s,evflag;
+
+ hung[white] = hung[black] = 0;
+ slk = ((mtl[white] == valueK && (pmtl[black] == 0 || emtl[black] == 0)) ||
+ (mtl[black] == valueK && (pmtl[white] == 0 || emtl[white] == 0)));
+ s = -Pscore[ply-1] + mtl[side] - mtl[xside];
+ s -= INCscore;
+
+ if (slk) evflag = false;
+ else evflag =
+ (ply == 1 || ply < Sdepth ||
+ ((ply == Sdepth+1 || ply == Sdepth+2) &&
+ (s > alpha-xwndw && s < beta+xwndw)) ||
+ (ply > Sdepth+2 && s >= alpha-25 && s <= beta+25));
+
+ if (evflag)
+ {
+ EvalNodes++;
+ ataks(side,atak[side]);
+ if (atak[side][PieceList[xside][0]] > 0) return(10001-ply);
+ ataks(xside,atak[xside]);
+ InChk = (atak[xside][PieceList[side][0]] > 0);
+ ScorePosition(side,&s);
+ }
+ else
+ {
+ if (SqAtakd(PieceList[xside][0],side)) return(10001-ply);
+ InChk = SqAtakd(PieceList[side][0],xside);
+ if (slk) ScoreLoneKing(side,&s);
+ }
+
+ Pscore[ply] = s - mtl[side] + mtl[xside];
+ if (InChk) ChkFlag[ply-1] = Pindex[TOsquare];
+ else ChkFlag[ply-1] = 0;
+ Threat[ply-1] = (hung[side] > 1 && ply == Sdepth+1);
+ return(s);
+}
+
+
+ProbeTTable(side,depth,alpha,beta,score)
+short side,depth,*alpha,*beta,*score;
+
+/*
+ Look for the current board position in the transposition table.
+*/
+
+{
+short hindx;
+ if (side == white) hashkey |= 1; else hashkey &= 0xFFFE;
+ hindx = (hashkey & (ttblsz-1));
+ ptbl = (ttable + hindx);
+ if (ptbl->depth >= depth && ptbl->hashbd == hashbd)
+ {
+ HashCnt++;
+ PV = ptbl->mv;
+ if (ptbl->flags & truescore)
+ {
+ *score = ptbl->score;
+ *beta = -20000;
+ return(true);
+ }
+/*
+ else if (ptbl->flags & upperbound)
+ {
+ if (ptbl->score < *beta) *beta = ptbl->score+1;
+ }
+*/
+ else if (ptbl->flags & lowerbound)
+ {
+ if (ptbl->score > *alpha) *alpha = ptbl->score-1;
+ }
+ }
+ return(false);
+}
+
+
+PutInTTable(side,score,depth,alpha,beta,mv)
+short side,score,depth,alpha,beta;
+unsigned short mv;
+
+/*
+ Store the current board position in the transposition table.
+*/
+
+{
+short hindx;
+ if (side == white) hashkey |= 1; else hashkey &= 0xFFFE;
+ hindx = (hashkey & (ttblsz-1));
+ ptbl = (ttable + hindx);
+ ptbl->hashbd = hashbd;
+ ptbl->depth = depth;
+ ptbl->score = score;
+ ptbl->mv = mv;
+ ptbl->flags = 0;
+ if (score < alpha) ptbl->flags |= upperbound;
+ else if (score > beta) ptbl->flags |= lowerbound;
+ else ptbl->flags |= truescore;
+}
+
+
+ZeroTTable()
+{
+int i;
+ if (hashflag)
+ for (i = 0; i < ttblsz; i++)
+ {
+ ptbl = (ttable + i);
+ ptbl->depth = 0;
+ }
+}
+
+
+MoveList(side,ply)
+short side,ply;
+
+/*
+ Fill the array Tree[] with all available moves for side to play. Array
+ TrPnt[ply] contains the index into Tree[] of the first move at a ply.
+*/
+
+{
+register short i;
+short xside,f;
+
+ xside = otherside[side];
+ if (PV == 0) Swag0 = killr0[ply]; else Swag0 = PV;
+ Swag1 = killr1[ply]; Swag2 = killr2[ply];
+ Swag3 = killr3[ply]; Swag4 = 0;
+ if (ply > 2) Swag4 = killr1[ply-2];
+ TrPnt[ply+1] = TrPnt[ply];
+ Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
+ for (i = PieceCnt[side]; i >= 0; i--)
+ GenMoves(ply,PieceList[side][i],side,xside);
+ if (kingmoved[side] == 0 && !castld[side])
+ {
+ f = PieceList[side][0];
+ if (castle(side,f,f+2,0))
+ {
+ LinkMove(ply,f,f+2,xside);
+ Tree[TrPnt[ply+1]-1].flags |= cstlmask;
+ }
+ if (castle(side,f,f-2,0))
+ {
+ LinkMove(ply,f,f-2,xside);
+ Tree[TrPnt[ply+1]-1].flags |= cstlmask;
+ }
+ }
+}
+
+#if (NEWMOVE < 11)
+GenMoves(ply,sq,side,xside)
+short ply,sq,side,xside;
+
+/*
+ Generate moves for a piece. The from square is mapped onto a special
+ board and offsets (taken from array Dir[]) are added to the mapped
+ location. The newly generated square is tested to see if it falls off
+ the board by ANDing the square with 88 HEX. Legal moves are linked
+ into the tree.
+*/
+
+{
+register short m,u,d;
+short i,m0,piece;
+
+ piece = board[sq]; m0 = map[sq];
+ if (sweep[piece])
+ for (i = Dstart[piece]; i <= Dstop[piece]; i++)
+ {
+ d = Dir[i]; m = m0+d;
+ while (!(m & 0x88))
+ {
+ u = unmap[m];
+ if (color[u] == neutral)
+ {
+ LinkMove(ply,sq,u,xside);
+ m += d;
+ }
+ else if (color[u] == xside)
+ {
+ LinkMove(ply,sq,u,xside);
+ break;
+ }
+ else break;
+ }
+ }
+ else if (piece == pawn)
+ {
+ if (side == white && color[sq+8] == neutral)
+ {
+ LinkMove(ply,sq,sq+8,xside);
+ if (row[sq] == 1)
+ if (color[sq+16] == neutral)
+ LinkMove(ply,sq,sq+16,xside);
+ }
+ else if (side == black && color[sq-8] == neutral)
+ {
+ LinkMove(ply,sq,sq-8,xside);
+ if (row[sq] == 6)
+ if (color[sq-16] == neutral)
+ LinkMove(ply,sq,sq-16,xside);
+ }
+ for (i = Dstart[piece]; i <= Dstop[piece]; i++)
+ if (!((m = m0+Dir[i]) & 0x88))
+ {
+ u = unmap[m];
+ if (color[u] == xside || u == epsquare)
+ LinkMove(ply,sq,u,xside);
+ }
+ }
+ else
+ {
+ for (i = Dstart[piece]; i <= Dstop[piece]; i++)
+ if (!((m = m0+Dir[i]) & 0x88))
+ {
+ u = unmap[m];
+ if (color[u] != side) LinkMove(ply,sq,u,xside);
+ }
+ }
+}
+#endif
+
+LinkMove(ply,f,t,xside)
+short ply,f,t,xside;
+
+/*
+ Add a move to the tree. Assign a bonus to order the moves
+ as follows:
+ 1. Principle variation
+ 2. Capture of last moved piece
+ 3. Other captures (major pieces first)
+ 4. Killer moves
+ 5. "history" killers
+*/
+
+{
+register short s,z;
+unsigned short mv;
+struct leaf *node;
+
+ node = &Tree[TrPnt[ply+1]];
+ ++TrPnt[ply+1];
+ node->flags = node->reply = 0;
+ node->f = f; node->t = t;
+ mv = (f<<8) + t;
+ s = 0;
+ if (mv == Swag0) s = 2000;
+ else if (mv == Swag1) s = 60;
+ else if (mv == Swag2) s = 50;
+ else if (mv == Swag3) s = 40;
+ else if (mv == Swag4) s = 30;
+ if (color[t] != neutral)
+ {
+ node->flags |= capture;
+ if (t == TOsquare) s += 500;
+ s += value[board[t]] - board[f];
+ }
+ if (board[f] == pawn)
+ if (row[t] == 0 || row[t] == 7)
+ {
+ node->flags |= promote;
+ s += 800;
+ }
+ else if (row[t] == 1 || row[t] == 6)
+ {
+ node->flags |= pwnthrt;
+ s += 600;
+ }
+ else if (t == epsquare) node->flags |= epmask;
+ z = (f<<6) + t; if (xside == white) z |= 0x1000;
+ s += history[z];
+ node->score = s - 20000;
+}
+
+#if (NEWMOVE < 10)
+CaptureList(side,xside,ply)
+short side,xside,ply;
+
+/*
+ Generate captures and Pawn promotions only.
+*/
+
+#define LinkCapture\
+{\
+ node->f = sq; node->t = u;\
+ node->reply = 0;\
+ node->flags = capture;\
+ node->score = value[board[u]] + svalue[board[u]] - piece;\
+ if (piece == pawn && (u < 8 || u > 55))\
+ {\
+ node->flags |= promote;\
+ node->score = valueQ;\
+ }\
+ ++node;\
+ ++TrPnt[ply+1];\
+}
+
+{
+register short m,u;
+short d,sq,i,j,j1,j2,m0,r7,d0,piece,*PL;
+struct leaf *node;
+
+ TrPnt[ply+1] = TrPnt[ply];
+ node = &Tree[TrPnt[ply]];
+ Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
+ if (side == white)
+ {
+ r7 = 6; d0 = 8;
+ }
+ else
+ {
+ r7 = 1; d0 = -8;
+ }
+ PL = PieceList[side];
+ for (i = 0; i <= PieceCnt[side]; i++)
+ {
+ sq = PL[i];
+ m0 = map[sq]; piece = board[sq];
+ j1 = Dstart[piece]; j2 = Dstop[piece];
+ if (sweep[piece])
+ for (j = j1; j <= j2; j++)
+ {
+ d = Dir[j]; m = m0+d;
+ while (!(m & 0x88))
+ {
+ u = unmap[m];
+ if (color[u] == neutral) m += d;
+ else
+ {
+ if (color[u] == xside) LinkCapture;
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (j = j1; j <= j2; j++)
+ if (!((m = m0+Dir[j]) & 0x88))
+ {
+ u = unmap[m];
+ if (color[u] == xside) LinkCapture;
+ }
+ if (piece == pawn && row[sq] == r7)
+ {
+ u = sq+d0;
+ if (color[u] == neutral) LinkCapture;
+ }
+ }
+ }
+}
+#endif
+
+int castle(side,kf,kt,iop)
+short side,kf,kt,iop;
+
+/*
+ Make or Unmake a castling move.
+*/
+
+{
+short rf,rt,d,t0,xside;
+
+ xside = otherside[side];
+ if (kt > kf)
+ {
+ rf = kf+3; rt = kt-1; d = 1;
+ }
+ else
+ {
+ rf = kf-4; rt = kt+1; d = -1;
+ }
+ if (iop == 0)
+ {
+ if (board[kf] != king || board[rf] != rook || color[rf] != side)
+ return(false);
+ if (color[kt] != neutral || color[rt] != neutral) return(false);
+ if (d == -1 && color[kt+d] != neutral) return(false);
+ if (SqAtakd(kf,xside)) return(false);
+ if (SqAtakd(kt,xside)) return(false);
+ if (SqAtakd(kf+d,xside)) return(false);
+ }
+ else
+ {
+ if (iop == 1) castld[side] = true; else castld[side] = false;
+ if (iop == 2)
+ {
+ t0 = kt; kt = kf; kf = t0;
+ t0 = rt; rt = rf; rf = t0;
+ }
+ board[kt] = king; color[kt] = side; Pindex[kt] = 0;
+ board[kf] = no_piece; color[kf] = neutral;
+ board[rt] = rook; color[rt] = side; Pindex[rt] = Pindex[rf];
+ board[rf] = no_piece; color[rf] = neutral;
+ PieceList[side][Pindex[kt]] = kt;
+ PieceList[side][Pindex[rt]] = rt;
+ if (hashflag)
+ {
+ UpdateHashbd(side,king,kf,kt);
+ UpdateHashbd(side,rook,rf,rt);
+ }
+ }
+ return(true);
+}
+
+
+EnPassant(xside,f,t,iop)
+short xside,f,t,iop;
+
+/*
+ Make or unmake an en passant move.
+*/
+
+{
+short l;
+ if (t > f) l = t-8; else l = t+8;
+ if (iop == 1)
+ {
+ board[l] = no_piece; color[l] = neutral;
+ }
+ else
+ {
+ board[l] = pawn; color[l] = xside;
+ }
+ InitializeStats();
+}
+
+
+MakeMove(side,node,tempb,tempc,tempsf,tempst)
+short side,*tempc,*tempb,*tempsf,*tempst;
+struct leaf *node;
+
+/*
+ Update Arrays board[], color[], and Pindex[] to reflect the new board
+ position obtained after making the move pointed to by node. Also
+ update miscellaneous stuff that changes when a move is made.
+*/
+
+{
+register short f,t;
+short xside,ct,cf;
+
+ xside = otherside[side];
+ f = node->f; t = node->t; epsquare = -1;
+ FROMsquare = f; TOsquare = t;
+ INCscore = 0;
+ GameList[++GameCnt].gmove = (f<<8) + t;
+ if (node->flags & cstlmask)
+ {
+ GameList[GameCnt].piece = no_piece;
+ GameList[GameCnt].color = side;
+ castle(side,f,t,1);
+ }
+ else
+ {
+ *tempc = color[t]; *tempb = board[t];
+ *tempsf = svalue[f]; *tempst = svalue[t];
+ GameList[GameCnt].piece = *tempb;
+ GameList[GameCnt].color = *tempc;
+ if (*tempc != neutral)
+ {
+ UpdatePieceList(*tempc,t,1);
+ if (*tempb == pawn) --PawnCnt[*tempc][column[t]];
+ if (board[f] == pawn)
+ {
+ --PawnCnt[side][column[f]];
+ ++PawnCnt[side][column[t]];
+ cf = column[f]; ct = column[t];
+ if (PawnCnt[side][ct] > 1+PawnCnt[side][cf])
+ INCscore -= 15;
+ else if (PawnCnt[side][ct] < 1+PawnCnt[side][cf])
+ INCscore += 15;
+ else if (ct == 0 || ct == 7 || PawnCnt[side][ct+ct-cf] == 0)
+ INCscore -= 15;
+ }
+ mtl[xside] -= value[*tempb];
+ if (*tempb == pawn) pmtl[xside] -= valueP;
+ if (hashflag) UpdateHashbd(xside,*tempb,-1,t);
+ INCscore += *tempst;
+ }
+ color[t] = color[f]; board[t] = board[f]; svalue[t] = svalue[f];
+ Pindex[t] = Pindex[f]; PieceList[side][Pindex[t]] = t;
+ color[f] = neutral; board[f] = no_piece;
+ if (board[t] == pawn)
+ if (t-f == 16) epsquare = f+8;
+ else if (f-t == 16) epsquare = f-8;
+ if (node->flags & promote)
+ {
+ board[t] = queen;
+ --PawnCnt[side][column[t]];
+ mtl[side] += valueQ - valueP;
+ pmtl[side] -= valueP;
+ HasQueen[side] = true;
+ if (hashflag)
+ {
+ UpdateHashbd(side,pawn,f,-1);
+ UpdateHashbd(side,queen,f,-1);
+ }
+ INCscore -= *tempsf;
+ }
+ if (board[t] == king) ++kingmoved[side];
+ if (node->flags & epmask) EnPassant(xside,f,t,1);
+ else if (hashflag) UpdateHashbd(side,board[t],f,t);
+ }
+}
+
+
+UnmakeMove(side,node,tempb,tempc,tempsf,tempst)
+short side,*tempc,*tempb,*tempsf,*tempst;
+struct leaf *node;
+
+/*
+ Take back a move.
+*/
+
+{
+register short f,t;
+short xside;
+
+ xside = otherside[side];
+ f = node->f; t = node->t; epsquare = -1;
+ GameCnt--;
+ if (node->flags & cstlmask) castle(side,f,t,2);
+ else
+ {
+ color[f] = color[t]; board[f] = board[t]; svalue[f] = *tempsf;
+ Pindex[f] = Pindex[t]; PieceList[side][Pindex[f]] = f;
+ color[t] = *tempc; board[t] = *tempb; svalue[t] = *tempst;
+ if (node->flags & promote)
+ {
+ board[f] = pawn;
+ ++PawnCnt[side][column[t]];
+ mtl[side] += valueP - valueQ;
+ pmtl[side] += valueP;
+ if (hashflag)
+ {
+ UpdateHashbd(side,queen,-1,t);
+ UpdateHashbd(side,pawn,-1,t);
+ }
+ }
+ if (*tempc != neutral)
+ {
+ UpdatePieceList(*tempc,t,2);
+ if (*tempb == pawn) ++PawnCnt[*tempc][column[t]];
+ if (board[f] == pawn)
+ {
+ --PawnCnt[side][column[t]];
+ ++PawnCnt[side][column[f]];
+ }
+ mtl[xside] += value[*tempb];
+ if (*tempb == pawn) pmtl[xside] += valueP;
+ if (hashflag) UpdateHashbd(xside,*tempb,-1,t);
+ }
+ if (board[f] == king) --kingmoved[side];
+ if (node->flags & epmask) EnPassant(xside,f,t,2);
+ else if (hashflag) UpdateHashbd(side,board[f],f,t);
+ }
+}
+
+
+UpdateHashbd(side,piece,f,t)
+short side,piece,f,t;
+
+/*
+ hashbd contains a 32 bit "signature" of the board position. hashkey
+ contains a 16 bit code used to address the hash table. When a move is
+ made, XOR'ing the hashcode of moved piece on the from and to squares
+ with the hashbd and hashkey values keeps things current.
+*/
+
+{
+ if (f >= 0)
+ {
+ hashbd ^= hashcode[side][piece][f].bd;
+ hashkey ^= hashcode[side][piece][f].key;
+ }
+ if (t >= 0)
+ {
+ hashbd ^= hashcode[side][piece][t].bd;
+ hashkey ^= hashcode[side][piece][t].key;
+ }
+}
+
+
+UpdatePieceList(side,sq,iop)
+short side,sq,iop;
+
+/*
+ Update the PieceList and Pindex arrays when a piece is captured or
+ when a capture is unmade.
+*/
+
+{
+register short i;
+ if (iop == 1)
+ {
+ PieceCnt[side]--;
+ for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
+ {
+ PieceList[side][i] = PieceList[side][i+1];
+ Pindex[PieceList[side][i]] = i;
+ }
+ }
+ else
+ {
+ PieceCnt[side]++;
+ PieceList[side][PieceCnt[side]] = sq;
+ Pindex[sq] = PieceCnt[side];
+ }
+}
+
+
+InitializeStats()
+
+/*
+ Scan thru the board seeing what's on each square. If a piece is found,
+ update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
+ determine the material for each side and set the hashkey and hashbd
+ variables to represent the current board position. Array
+ PieceList[side][indx] contains the location of all the pieces of
+ either side. Array Pindex[sq] contains the indx into PieceList for a
+ given square.
+*/
+
+{
+register short i,sq;
+ epsquare = -1;
+ for (i = 0; i < 8; i++)
+ PawnCnt[white][i] = PawnCnt[black][i] = 0;
+ mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
+ PieceCnt[white] = PieceCnt[black] = 0;
+ hashbd = hashkey = 0;
+ for (sq = 0; sq < 64; sq++)
+ if (color[sq] != neutral)
+ {
+ mtl[color[sq]] += value[board[sq]];
+ if (board[sq] == pawn)
+ {
+ pmtl[color[sq]] += valueP;
+ ++PawnCnt[color[sq]][column[sq]];
+ }
+ if (board[sq] == king) Pindex[sq] = 0;
+ else Pindex[sq] = ++PieceCnt[color[sq]];
+ PieceList[color[sq]][Pindex[sq]] = sq;
+ hashbd ^= hashcode[color[sq]][board[sq]][sq].bd;
+ hashkey ^= hashcode[color[sq]][board[sq]][sq].key;
+ }
+}
+
+
+pick(p1,p2)
+short p1,p2;
+
+/*
+ Find the best move in the tree between indexes p1 and p2. Swap the
+ best move into the p1 element.
+*/
+
+{
+register short p,s;
+short p0,s0;
+struct leaf temp;
+
+ s0 = Tree[p1].score; p0 = p1;
+ for (p = p1+1; p <= p2; p++)
+ if ((s = Tree[p].score) > s0)
+ {
+ s0 = s; p0 = p;
+ }
+ if (p0 != p1)
+ {
+ temp = Tree[p1]; Tree[p1] = Tree[p0]; Tree[p0] = temp;
+ }
+}
+
+
+repetition(cnt)
+short *cnt;
+
+/*
+ Check for draw by threefold repetition.
+*/
+
+{
+register short i,c;
+short f,t,b[64];
+unsigned short m;
+ *cnt = c = 0;
+ if (GameCnt > Game50+3)
+ {
+/*
+ memset((char *)b,0,64*sizeof(short));
+*/
+ for (i = 0; i < 64; b[i++] = 0);
+ for (i = GameCnt; i > Game50; i--)
+ {
+ m = GameList[i].gmove; f = m>>8; t = m & 0xFF;
+ if (++b[f] == 0) c--; else c++;
+ if (--b[t] == 0) c--; else c++;
+ if (c == 0) (*cnt)++;
+ }
+ }
+}
+
+#if (NEWMOVE < 3)
+int SqAtakd(sq,side)
+short sq,side;
+
+/*
+ See if any piece with color 'side' ataks sq. First check for pawns
+ or king, then try other pieces. Array Dcode is used to check for
+ knight attacks or R,B,Q co-linearity.
+*/
+
+{
+register short m,d;
+short i,m0,m1,loc,piece,*PL;
+
+ m1 = map[sq];
+ if (side == white) m = m1-0x0F; else m = m1+0x0F;
+ if (!(m & 0x88))
+ if (board[unmap[m]] == pawn && color[unmap[m]] == side) return(true);
+ if (side == white) m = m1-0x11; else m = m1+0x11;
+ if (!(m & 0x88))
+ if (board[unmap[m]] == pawn && color[unmap[m]] == side) return(true);
+ if (distance(sq,PieceList[side][0]) == 1) return(true);
+
+ PL = PieceList[side];
+ for (i = 1; i <= PieceCnt[side]; i++)
+ {
+ loc = PL[i]; piece = board[loc];
+ if (piece == pawn) continue;
+ m0 = map[loc]; d = Dcode[abs(m1-m0)];
+ if (d == 0 || (Pdir[d] & pbit[piece]) == 0) continue;
+ if (piece == knight) return(true);
+ else
+ {
+ if (m1 < m0) d = -d;
+ for (m = m0+d; m != m1; m += d)
+ if (color[unmap[m]] != neutral) break;
+ if (m == m1) return(true);
+ }
+ }
+ return(false);
+}
+#endif
+
+#if (NEWMOVE < 2)
+ataks(side,a)
+short side,*a;
+
+/*
+ Fill array atak[][] with info about ataks to a square. Bits 8-15
+ are set if the piece (king..pawn) ataks the square. Bits 0-7
+ contain a count of total ataks to the square.
+*/
+
+{
+register short u,m;
+short d,c,j,j1,j2,piece,i,m0,sq,*PL;
+
+/*
+ memset((char *)a,0,64*sizeof(short));
+*/
+ for (u = 0; u < 64; a[u++] = 0);
+ Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
+ PL = PieceList[side];
+ for (i = 0; i <= PieceCnt[side]; i++)
+ {
+ sq = PL[i];
+ m0 = map[sq];
+ piece = board[sq];
+ c = control[piece]; j1 = Dstart[piece]; j2 = Dstop[piece];
+ if (sweep[piece])
+ for (j = j1; j <= j2; j++)
+ {
+ d = Dir[j]; m = m0+d;
+ while (!(m & 0x88))
+ {
+ u = unmap[m];
+ a[u] = ++a[u] | c;
+ if (color[u] == neutral) m += d;
+ else break;
+ }
+ }
+ else
+ for (j = j1; j <= j2; j++)
+ if (!((m = m0+Dir[j]) & 0x88))
+ {
+ u = unmap[m];
+ a[u] = ++a[u] | c;
+ }
+ }
+}
+#endif
+
+/* ............ POSITIONAL EVALUATION ROUTINES ............ */
+
+ScorePosition(side,score)
+short side,*score;
+
+/*
+ Perform normal static evaluation of board position. A score is
+ generated for each piece and these are summed to get a score for each
+ side.
+*/
+
+{
+register short sq,s;
+short i,xside,pscore[3];
+
+ wking = PieceList[white][0]; bking = PieceList[black][0];
+ UpdateWeights();
+ xside = otherside[side];
+ pscore[white] = pscore[black] = 0;
+
+ for (c1 = white; c1 <= black; c1++)
+ {
+ c2 = otherside[c1];
+ if (c1 == white) EnemyKing = bking; else EnemyKing = wking;
+ atk1 = atak[c1]; atk2 = atak[c2];
+ PC1 = PawnCnt[c1]; PC2 = PawnCnt[c2];
+ for (i = 0; i <= PieceCnt[c1]; i++)
+ {
+ sq = PieceList[c1][i];
+ s = SqValue(sq,side);
+ pscore[c1] += s;
+ svalue[sq] = s;
+ }
+ }
+ if (hung[side] > 1) pscore[side] += HUNGX;
+ if (hung[xside] > 1) pscore[xside] += HUNGX;
+
+ *score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10;
+ if (dither) *score += rand() % dither;
+
+ if (*score > 0 && pmtl[side] == 0)
+ if (emtl[side] < valueR) *score = 0;
+ else if (*score < valueR) *score /= 2;
+ if (*score < 0 && pmtl[xside] == 0)
+ if (emtl[xside] < valueR) *score = 0;
+ else if (-*score < valueR) *score /= 2;
+
+ if (mtl[xside] == valueK && emtl[side] > valueB) *score += 200;
+ if (mtl[side] == valueK && emtl[xside] > valueB) *score -= 200;
+}
+
+
+ScoreLoneKing(side,score)
+short side,*score;
+
+/*
+ Static evaluation when loser has only a king and winner has no pawns
+ or no pieces.
+*/
+
+{
+short winner,loser,king1,king2,s,i;
+
+ UpdateWeights();
+ if (mtl[white] > mtl[black]) winner = white; else winner = black;
+ loser = otherside[winner];
+ king1 = PieceList[winner][0]; king2 = PieceList[loser][0];
+
+ s = 0;
+
+ if (pmtl[winner] > 0)
+ for (i = 1; i <= PieceCnt[winner]; i++)
+ s += ScoreKPK(side,winner,loser,king1,king2,PieceList[winner][i]);
+
+ else if (emtl[winner] == valueB+valueN)
+ s = ScoreKBNK(winner,king1,king2);
+
+ else if (emtl[winner] > valueB)
+ s = 500 + emtl[winner] - DyingKing[king2] - 2*distance(king1,king2);
+
+ if (side == winner) *score = s; else *score = -s;
+}
+
+
+int ScoreKPK(side,winner,loser,king1,king2,sq)
+short side,winner,loser,king1,king2,sq;
+
+/*
+ Score King and Pawns versus King endings.
+*/
+
+{
+short s,r;
+
+ if (PieceCnt[winner] == 1) s = 50; else s = 120;
+ if (winner == white)
+ {
+ if (side == loser) r = row[sq]-1; else r = row[sq];
+ if (row[king2] >= r && distance(sq,king2) < 8-r) s += 10*row[sq];
+ else s = 500+50*row[sq];
+ if (row[sq] < 6) sq += 16; else sq += 8;
+ }
+ else
+ {
+ if (side == loser) r = row[sq]+1; else r = row[sq];
+ if (row[king2] <= r && distance(sq,king2) < r+1) s += 10*(7-row[sq]);
+ else s = 500+50*(7-row[sq]);
+ if (row[sq] > 1) sq -= 16; else sq -= 8;
+ }
+ s += 8*(taxicab(king2,sq) - taxicab(king1,sq));
+ return(s);
+}
+
+
+int ScoreKBNK(winner,king1,king2)
+short winner,king1,king2;
+
+/*
+ Score King+Bishop+Knight versus King endings.
+ This doesn't work all that well but it's better than nothing.
+*/
+
+{
+short s;
+ s = emtl[winner] - 300;
+ if (KBNKsq == 0) s += KBNK[king2];
+ else s += KBNK[locn[row[king2]][7-column[king2]]];
+ s -= taxicab(king1,king2);
+ s -= distance(PieceList[winner][1],king2);
+ s -= distance(PieceList[winner][2],king2);
+ return(s);
+}
+
+
+SqValue(sq,side)
+short sq,side;
+
+/*
+ Calculate the positional value for the piece on 'sq'.
+*/
+
+{
+register short j,fyle,rank;
+short s,piece,a1,a2,in_square,r,mob,e,c;
+
+ piece = board[sq];
+ a1 = (atk1[sq] & 0x4FFF); a2 = (atk2[sq] & 0x4FFF);
+ rank = row[sq]; fyle = column[sq];
+ s = 0;
+ if (piece == pawn && c1 == white)
+ {
+ s = Mwpawn[sq];
+ if (sq == 11 || sq == 12)
+ if (color[sq+8] != neutral) s += PEDRNK2B;
+ if ((fyle == 0 || PC1[fyle-1] == 0) &&
+ (fyle == 7 || PC1[fyle+1] == 0))
+ s += ISOLANI[fyle];
+ else if (PC1[fyle] > 1) s += PDOUBLED;
+ if (a1 < ctlP && atk1[sq+8] < ctlP)
+ {
+ s += BACKWARD[a2 & 0xFF];
+ if (PC2[fyle] == 0) s += PWEAKH;
+ if (color[sq+8] != neutral) s += PBLOK;
+ }
+ if (PC2[fyle] == 0)
+ {
+ if (side == black) r = rank-1; else r = rank;
+ in_square = (row[bking] >= r && distance(sq,bking) < 8-r);
+ if (a2 == 0 || side == white) e = 0; else e = 1;
+ for (j = sq+8; j < 64; j += 8)
+ if (atk2[j] >= ctlP) { e = 2; break; }
+ else if (atk2[j] > 0 || color[j] != neutral) e = 1;
+ if (e == 2) s += (stage*PassedPawn3[rank]) / 10;
+ else if (in_square || e == 1) s += (stage*PassedPawn2[rank]) / 10;
+ else if (emtl[black] > 0) s += (stage*PassedPawn1[rank]) / 10;
+ else s += PassedPawn0[rank];
+ }
+ }
+ else if (piece == pawn && c1 == black)
+ {
+ s = Mbpawn[sq];
+ if (sq == 51 || sq == 52)
+ if (color[sq-8] != neutral) s += PEDRNK2B;
+ if ((fyle == 0 || PC1[fyle-1] == 0) &&
+ (fyle == 7 || PC1[fyle+1] == 0))
+ s += ISOLANI[fyle];
+ else if (PC1[fyle] > 1) s += PDOUBLED;
+ if (a1 < ctlP && atk1[sq-8] < ctlP)
+ {
+ s += BACKWARD[a2 & 0xFF];
+ if (PC2[fyle] == 0) s += PWEAKH;
+ if (color[sq-8] != neutral) s += PBLOK;
+ }
+ if (PC2[fyle] == 0)
+ {
+ if (side == white) r = rank+1; else r = rank;
+ in_square = (row[wking] <= r && distance(sq,wking) < r+1);
+ if (a2 == 0 || side == black) e = 0; else e = 1;
+ for (j = sq-8; j >= 0; j -= 8)
+ if (atk2[j] >= ctlP) { e = 2; break; }
+ else if (atk2[j] > 0 || color[j] != neutral) e = 1;
+ if (e == 2) s += (stage*PassedPawn3[7-rank]) / 10;
+ else if (in_square || e == 1) s += (stage*PassedPawn2[7-rank]) / 10;
+ else if (emtl[white] > 0) s += (stage*PassedPawn1[7-rank]) / 10;
+ else s += PassedPawn0[7-rank];
+ }
+ }
+ else if (piece == knight)
+ {
+ s = Mknight[c1][sq];
+ }
+ else if (piece == bishop)
+ {
+ s = Mbishop[c1][sq];
+ BRscan(sq,&s,&mob);
+ s += BMBLTY[mob];
+ }
+ else if (piece == rook)
+ {
+ s += RookBonus;
+ BRscan(sq,&s,&mob);
+ s += RMBLTY[mob];
+ if (PC1[fyle] == 0) s += RHOPN;
+ if (PC2[fyle] == 0) s += RHOPNX;
+ if (rank == rank7[c1] && pmtl[c2] > 100) s += 10;
+ if (stage > 2) s += 14 - taxicab(sq,EnemyKing);
+ }
+ else if (piece == queen)
+ {
+ if (stage > 2) s += 14 - taxicab(sq,EnemyKing);
+ if (distance(sq,EnemyKing) < 3) s += 12;
+ }
+ else if (piece == king)
+ {
+ s = Mking[c1][sq];
+ if (KSFTY > 0)
+ if (Developed[c2] || stage > 0) KingScan(sq,&s);
+ if (castld[c1]) s += KCASTLD;
+ else if (kingmoved[c1]) s += KMOVD;
+
+ if (PC1[fyle] == 0) s += KHOPN;
+ if (PC2[fyle] == 0) s += KHOPNX;
+ if (fyle == 1 || fyle == 2 || fyle == 3 || fyle == 7)
+ {
+ if (PC1[fyle-1] == 0) s += KHOPN;
+ if (PC2[fyle-1] == 0) s += KHOPNX;
+ }
+ if (fyle == 4 || fyle == 5 || fyle == 6 || fyle == 0)
+ {
+ if (PC1[fyle+1] == 0) s += KHOPN;
+ if (PC2[fyle+1] == 0) s += KHOPNX;
+ }
+ if (fyle == 2)
+ {
+ if (PC1[0] == 0) s += KHOPN;
+ if (PC2[0] == 0) s += KHOPNX;
+ }
+ if (fyle == 5)
+ {
+ if (PC1[7] == 0) s += KHOPN;
+ if (PC2[7] == 0) s += KHOPNX;
+ }
+ }
+
+ if (a2 > 0)
+ {
+ c = (control[piece] & 0x4FFF);
+ if (a1 == 0 || a2 > c+1)
+ {
+ s += HUNGP;
+ ++hung[c1];
+ if (piece != king && trapped(sq,piece)) ++hung[c1];
+ }
+ else if (piece != pawn || a2 > a1)
+ if (a2 >= c || a1 < ctlP) s += ATAKD;
+ }
+ return(s);
+}
+
+#if (NEWMOVE > 6)
+KingScan(sq,s)
+short sq,*s;
+
+/*
+ Assign penalties if king can be threatened by checks, if squares
+ near the king are controlled by the enemy (especially the queen),
+ or if there are no pawns near the king.
+*/
+
+#define ScoreThreat\
+ if (color[u] != c2)\
+ if (atk1[u] == 0 || (atk2[u] & 0xFF) > 1) ++cnt;\
+ else *s -= 3
+
+{
+register short m,u;
+short d,i,m0,cnt,ok;
+
+ cnt = 0;
+ m0 = map[sq];
+ if (HasBishop[c2] || HasQueen[c2])
+ for (i = Dstart[bishop]; i <= Dstop[bishop]; i++)
+ {
+ d = Dir[i]; m = m0+d;
+ while (!(m & 0x88))
+ {
+ u = unmap[m];
+ if (atk2[u] & ctlBQ) ScoreThreat;
+ if (color[u] != neutral) break;
+ m += d;
+ }
+ }
+ if (HasRook[c2] || HasQueen[c2])
+ for (i = Dstart[rook]; i <= Dstop[rook]; i++)
+ {
+ d = Dir[i]; m = m0+d;
+ while (!(m & 0x88))
+ {
+ u = unmap[m];
+ if (atk2[u] & ctlRQ) ScoreThreat;
+ if (color[u] != neutral) break;
+ m += d;
+ }
+ }
+ if (HasKnight[c2])
+ for (i = Dstart[knight]; i <= Dstop[knight]; i++)
+ if (!((m = m0+Dir[i]) & 0x88))
+ {
+ u = unmap[m];
+ if (atk2[u] & ctlNN) ScoreThreat;
+ }
+ *s += (KSFTY*Kthreat[cnt]) / 16;
+
+ cnt = 0; ok = false;
+ m0 = map[sq];
+ for (i = Dstart[king]; i <= Dstop[king]; i++)
+ if (!((m = m0+Dir[i]) & 0x88))
+ {
+ u = unmap[m];
+ if (board[u] == pawn) ok = true;
+ if (atk2[u] > atk1[u])
+ {
+ ++cnt;
+ if (atk2[u] & ctlQ)
+ if (atk2[u] > ctlQ+1 && atk1[u] < ctlQ) *s -= 4*KSFTY;
+ }
+ }
+ if (!ok) *s -= KSFTY;
+ if (cnt > 1) *s -= KSFTY;
+}
+#endif
+
+#if (NEWMOVE < 4)
+BRscan(sq,s,mob)
+short sq,*s,*mob;
+
+/*
+ Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the
+ hung[] array if a pin is found.
+*/
+
+{
+register short m,u;
+short d,j,m0,piece,pin,*Kf;
+
+ Kf = Kfield[c1];
+ *mob = 0;
+ m0 = map[sq]; piece = board[sq];
+ for (j = Dstart[piece]; j <= Dstop[piece]; j++)
+ {
+ pin = -1;
+ d = Dir[j]; m = m0+d;
+ while (!(m & 0x88))
+ {
+ u = unmap[m]; *s += Kf[u];
+ if (color[u] == neutral)
+ {
+ (*mob)++;
+ m += d;
+ }
+ else if (pin < 0)
+ {
+ if (board[u] == pawn || board[u] == king) break;
+ pin = u;
+ m += d;
+ }
+ else if (color[u] == c2 && (board[u] > piece || atk2[u] == 0))
+ {
+ if (color[pin] == c2)
+ {
+ *s += PINVAL;
+ if (atk2[pin] == 0 ||
+ atk1[pin] > control[board[pin]]+1)
+ ++hung[c2];
+ }
+ else *s += XRAY;
+ break;
+ }
+ else break;
+ }
+ }
+}
+#endif
+
+#if (NEWMOVE > 5)
+int trapped(sq,piece)
+short sq,piece;
+
+/*
+ See if the attacked piece has unattacked squares to move to.
+*/
+
+{
+register short u,m,d;
+short i,m0;
+
+ m0 = map[sq];
+ if (sweep[piece])
+ for (i = Dstart[piece]; i <= Dstop[piece]; i++)
+ {
+ d = Dir[i]; m = m0+d;
+ while (!(m & 0x88))
+ {
+ u = unmap[m];
+ if (color[u] == c1) break;
+ if (atk2[u] == 0 || board[u] >= piece) return(false);
+ if (color[u] == c2) break;
+ m += d;
+ }
+ }
+ else if (piece == pawn)
+ {
+ if (c1 == white) u = sq+8; else u = sq-8;
+ if (color[u] == neutral && atk1[u] >= atk2[u])
+ return(false);
+ if (!((m = m0+Dir[Dpwn[c1]]) & 0x88))
+ if (color[unmap[m]] == c2) return(false);
+ if (!((m = m0+Dir[Dpwn[c1]+1]) & 0x88))
+ if (color[unmap[m]] == c2) return(false);
+ }
+ else
+ {
+ for (i = Dstart[piece]; i <= Dstop[piece]; i++)
+ if (!((m = m0+Dir[i]) & 0x88))
+ {
+ u = unmap[m];
+ if (color[u] != c1)
+ if (atk2[u] == 0 || board[u] >= piece) return(false);
+ }
+ }
+ return(true);
+}
+#endif
+
+ExaminePosition()
+
+/*
+ This is done one time before the search is started. Set up arrays
+ Mwpawn, Mbpawn, Mknight, Mbishop, Mking which are used in the
+ SqValue() function to determine the positional value of each piece.
+*/
+
+{
+register short i,sq;
+short wpadv,bpadv,wstrong,bstrong,z,side,pp,j,val,Pd,fyle,rank;
+
+ wking = PieceList[white][0]; bking = PieceList[black][0];
+ ataks(white,atak[white]); ataks(black,atak[black]);
+ Zwmtl = Zbmtl = 0;
+ UpdateWeights();
+ HasPawn[white] = HasPawn[black] = 0;
+ HasKnight[white] = HasKnight[black] = 0;
+ HasBishop[white] = HasBishop[black] = 0;
+ HasRook[white] = HasRook[black] = 0;
+ HasQueen[white] = HasQueen[black] = 0;
+ for (side = white; side <= black; side++)
+ for (i = 0; i <= PieceCnt[side]; i++)
+ switch (board[PieceList[side][i]])
+ {
+ case pawn : ++HasPawn[side]; break;
+ case knight : ++HasKnight[side]; break;
+ case bishop : ++HasBishop[side]; break;
+ case rook : ++HasRook[side]; break;
+ case queen : ++HasQueen[side]; break;
+ }
+ if (!Developed[white])
+ Developed[white] = (board[1] != knight && board[2] != bishop &&
+ board[5] != bishop && board[6] != knight);
+ if (!Developed[black])
+ Developed[black] = (board[57] != knight && board[58] != bishop &&
+ board[61] != bishop && board[62] != knight);
+ if (!PawnStorm && stage < 5)
+ PawnStorm = ((column[wking] < 3 && column[bking] > 4) ||
+ (column[wking] > 4 && column[bking] < 3));
+
+ CopyBoard(pknight,Mknight[white]);
+ CopyBoard(pknight,Mknight[black]);
+ CopyBoard(pbishop,Mbishop[white]);
+ CopyBoard(pbishop,Mbishop[black]);
+ BlendBoard(KingOpening,KingEnding,Mking[white]);
+ BlendBoard(KingOpening,KingEnding,Mking[black]);
+
+ for (sq = 0; sq < 64; sq++)
+ {
+ fyle = column[sq]; rank = row[sq];
+ wstrong = bstrong = true;
+ for (i = sq; i < 64; i += 8)
+ if (atak[black][i] >= ctlP) wstrong = false;
+ for (i = sq; i >= 0; i -= 8)
+ if (atak[white][i] >= ctlP) bstrong = false;
+ wpadv = bpadv = PADVNCM;
+ if ((fyle == 0 || PawnCnt[white][fyle-1] == 0) &&
+ (fyle == 7 || PawnCnt[white][fyle+1] == 0)) wpadv = PADVNCI;
+ if ((fyle == 0 || PawnCnt[black][fyle-1] == 0) &&
+ (fyle == 7 || PawnCnt[black][fyle+1] == 0)) bpadv = PADVNCI;
+ Mwpawn[sq] = (wpadv*PawnAdvance[sq]) / 10;
+ Mbpawn[sq] = (bpadv*PawnAdvance[63-sq]) / 10;
+ Mwpawn[sq] += PawnBonus; Mbpawn[sq] += PawnBonus;
+ if (castld[white] || kingmoved[white])
+ {
+ if ((fyle < 3 || fyle > 4) && distance(sq,wking) < 3)
+ Mwpawn[sq] += PAWNSHIELD;
+ }
+ else if (rank < 3 && (fyle < 2 || fyle > 5))
+ Mwpawn[sq] += PAWNSHIELD / 2;
+ if (castld[black] || kingmoved[black])
+ {
+ if ((fyle < 3 || fyle > 4) && distance(sq,bking) < 3)
+ Mbpawn[sq] += PAWNSHIELD;
+ }
+ else if (rank > 4 && (fyle < 2 || fyle > 5))
+ Mbpawn[sq] += PAWNSHIELD / 2;
+ if (PawnStorm)
+ {
+ if ((column[wking] < 4 && fyle > 4) ||
+ (column[wking] > 3 && fyle < 3)) Mwpawn[sq] += 3*rank - 21;
+ if ((column[bking] < 4 && fyle > 4) ||
+ (column[bking] > 3 && fyle < 3)) Mbpawn[sq] -= 3*rank;
+ }
+
+ Mknight[white][sq] += 5 - distance(sq,bking);
+ Mknight[white][sq] += 5 - distance(sq,wking);
+ Mknight[black][sq] += 5 - distance(sq,wking);
+ Mknight[black][sq] += 5 - distance(sq,bking);
+ Mbishop[white][sq] += BishopBonus;
+ Mbishop[black][sq] += BishopBonus;
+ for (i = 0; i <= PieceCnt[black]; i++)
+ if (distance(sq,PieceList[black][i]) < 3)
+ Mknight[white][sq] += KNIGHTPOST;
+ for (i = 0; i <= PieceCnt[white]; i++)
+ if (distance(sq,PieceList[white][i]) < 3)
+ Mknight[black][sq] += KNIGHTPOST;
+ if (wstrong) Mknight[white][sq] += KNIGHTSTRONG;
+ if (bstrong) Mknight[black][sq] += KNIGHTSTRONG;
+ if (wstrong) Mbishop[white][sq] += BISHOPSTRONG;
+ if (bstrong) Mbishop[black][sq] += BISHOPSTRONG;
+
+ if (HasBishop[white] == 2) Mbishop[white][sq] += 8;
+ if (HasBishop[black] == 2) Mbishop[black][sq] += 8;
+ if (HasKnight[white] == 2) Mknight[white][sq] += 5;
+ if (HasKnight[black] == 2) Mknight[black][sq] += 5;
+
+ if (board[sq] == bishop)
+ if (rank % 2 == fyle % 2) KBNKsq = 0; else KBNKsq = 7;
+
+ Kfield[white][sq] = Kfield[black][sq] = 0;
+ if (distance(sq,wking) == 1) Kfield[black][sq] = KATAK;
+ if (distance(sq,bking) == 1) Kfield[white][sq] = KATAK;
+
+ Pd = 0;
+ for (i = 0; i < 64; i++)
+ if (board[i] == pawn)
+ {
+ if (color[i] == white)
+ {
+ pp = true;
+ if (row[i] == 6) z = i+8; else z = i+16;
+ for (j = i+8; j < 64; j += 8)
+ if (atak[black][j] > ctlP || board[j] == pawn) pp = false;
+ }
+ else
+ {
+ pp = true;
+ if (row[i] == 1) z = i-8; else z = i-16;
+ for (j = i-8; j >= 0; j -= 8)
+ if (atak[white][j] > ctlP || board[j] == pawn) pp = false;
+ }
+ if (pp) Pd += 5*taxicab(sq,z); else Pd += taxicab(sq,z);
+ }
+ if (Pd != 0)
+ {
+ val = (Pd*stage2) / 10;
+ Mking[white][sq] -= val;
+ Mking[black][sq] -= val;
+ }
+ }
+}
+
+
+UpdateWeights()
+
+/*
+ If material balance has changed, determine the values for the
+ positional evaluation terms.
+*/
+
+{
+short tmtl;
+
+ if (mtl[white] != Zwmtl || mtl[black] != Zbmtl)
+ {
+ Zwmtl = mtl[white]; Zbmtl = mtl[black];
+ emtl[white] = Zwmtl - pmtl[white] - valueK;
+ emtl[black] = Zbmtl - pmtl[black] - valueK;
+ tmtl = emtl[white] + emtl[black];
+ if (tmtl > 6600) stage = 0;
+ else if (tmtl < 1400) stage = 10;
+ else stage = (6600-tmtl) / 520;
+ if (tmtl > 3600) stage2 = 0;
+ else if (tmtl < 1400) stage2 = 10;
+ else stage2 = (3600-tmtl) / 220;
+
+ PEDRNK2B = -15; /* centre pawn on 2nd rank & blocked */
+ PBLOK = -4; /* blocked backward pawn */
+ PDOUBLED = -14; /* doubled pawn */
+ PWEAKH = -4; /* weak pawn on half open file */
+ PAWNSHIELD = 10-stage; /* pawn near friendly king */
+ PADVNCM = 10; /* advanced pawn multiplier */
+ PADVNCI = 7; /* muliplier for isolated pawn */
+ PawnBonus = stage;
+
+ KNIGHTPOST = (stage+2)/3; /* knight near enemy pieces */
+ KNIGHTSTRONG = (stage+6)/2; /* occupies pawn hole */
+
+ BISHOPSTRONG = (stage+6)/2; /* occupies pawn hole */
+ BishopBonus = 2*stage;
+
+ RHOPN = 10; /* rook on half open file */
+ RHOPNX = 4;
+ RookBonus = 6*stage;
+
+ XRAY = 8; /* Xray attack on piece */
+ PINVAL = 10; /* Pin */
+
+ KHOPN = (3*stage-30) / 2; /* king on half open file */
+ KHOPNX = KHOPN / 2;
+ KCASTLD = 10 - stage;
+ KMOVD = -40 / (stage+1); /* king moved before castling */
+ KATAK = (10-stage) / 2; /* B,R attacks near enemy king */
+ if (stage < 8) KSFTY = 16-2*stage; else KSFTY = 0;
+
+ ATAKD = -6; /* defender > attacker */
+ HUNGP = -8; /* each hung piece */
+ HUNGX = -12; /* extra for >1 hung piece */
+ }
+}
+
+#if (NEWMOVE < 1)
+int distance(a,b)
+short a,b;
+{
+register short d1,d2;
+
+ d1 = abs(column[a]-column[b]);
+ d2 = abs(row[a]-row[b]);
+ return(d1 > d2 ? d1 : d2);
+}
+#endif
+
+BlendBoard(a,b,c)
+short a[64],b[64],c[64];
+{
+register int sq;
+ for (sq = 0; sq < 64; sq++)
+ c[sq] = (a[sq]*(10-stage) + b[sq]*stage) / 10;
+}
+
+
+CopyBoard(a,b)
+short a[64],b[64];
+{
+register int sq;
+ for (sq = 0; sq < 64; sq++)
+ b[sq] = a[sq];
+}
diff --git a/gnu/games/chess/gnuchess.h b/gnu/games/chess/gnuchess.h
new file mode 100644
index 000000000000..6e9c74bcbc22
--- /dev/null
+++ b/gnu/games/chess/gnuchess.h
@@ -0,0 +1,97 @@
+/*
+ This file contains code for CHESS.
+ Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
+
+ This file is part of CHESS.
+
+ CHESS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY. No author or distributor
+ accepts responsibility to anyone for the consequences of using it
+ or for whether it serves any particular purpose or works at all,
+ unless he says so in writing. Refer to the CHESS General Public
+ License for full details.
+
+ Everyone is granted permission to copy, modify and redistribute
+ CHESS, but only under the conditions described in the
+ CHESS General Public License. A copy of this license is
+ supposed to have been given to you along with CHESS so you
+ can know your rights and responsibilities. It should be in a
+ file named COPYING. Among other things, the copyright notice
+ and this notice must be preserved on all copies.
+*/
+
+
+/* Header file for GNU CHESS */
+
+#define neutral 2
+#define white 0
+#define black 1
+#define no_piece 0
+#define pawn 1
+#define knight 2
+#define bishop 3
+#define rook 4
+#define queen 5
+#define king 6
+#define pxx " PNBRQK"
+#define qxx " pnbrqk"
+#define rxx "12345678"
+#define cxx "abcdefgh"
+#define check 0x0001
+#define capture 0x0002
+#define draw 0x0004
+#define promote 0x0008
+#define cstlmask 0x0010
+#define epmask 0x0020
+#define exact 0x0040
+#define pwnthrt 0x0080
+#define maxdepth 30
+#define true 1
+#define false 0
+
+struct leaf
+ {
+ short f,t,score,reply;
+ unsigned short flags;
+ };
+struct GameRec
+ {
+ unsigned short gmove;
+ short score,depth,time,piece,color;
+ long nodes;
+ };
+struct TimeControlRec
+ {
+ short moves[2];
+ long clock[2];
+ };
+struct BookEntry
+ {
+ struct BookEntry *next;
+ unsigned short *mv;
+ };
+
+extern char mvstr1[5],mvstr2[5];
+extern struct leaf Tree[2000],*root;
+extern short TrPnt[maxdepth],board[64],color[64];
+extern short row[64],column[64],locn[8][8];
+extern short atak[2][64],PawnCnt[2][8];
+extern short castld[2],kingmoved[2];
+extern short c1,c2,*atk1,*atk2,*PC1,*PC2;
+extern short mate,post,opponent,computer,Sdepth,Awindow,Bwindow,dither;
+extern long ResponseTime,ExtraTime,Level,et,et0,time0,cputimer,ft;
+extern long NodeCnt,evrate,ETnodes,EvalNodes,HashCnt;
+extern short quit,reverse,bothsides,hashflag,InChk,player,force,easy,beep,meter;
+extern short timeout,xwndw;
+extern struct GameRec GameList[240];
+extern short GameCnt,Game50,epsquare,lpost,rcptr,contempt;
+extern short MaxSearchDepth;
+extern struct BookEntry *Book;
+extern struct TimeControlRec TimeControl;
+extern short TCflag,TCmoves,TCminutes,OperatorTime;
+extern short otherside[3];
+extern short Stboard[64];
+extern short Stcolor[64];
+extern unsigned short hint,PrVar[maxdepth];
+
+#define HZ 60
diff --git a/gnu/games/chess/move.c b/gnu/games/chess/move.c
new file mode 100644
index 000000000000..4ce686c1b40a
--- /dev/null
+++ b/gnu/games/chess/move.c
@@ -0,0 +1,357 @@
+/* move generator hes@log-sv.se 890318
+ Modified: 890606 NEWMOVE Levels 1-6 for easier debugging */
+#include "move.h"
+#include "gnuchess.h"
+
+short distdata[64][64];
+short taxidata[64][64];
+
+void Initialize_dist() {
+register short a,b,d,di;
+
+ /* init taxi and dist data */
+ for(a=0;a<64;a++)
+ for(b=0;b<64;b++) {
+ d = abs(column[a]-column[b]);
+ di = abs(row[a]-row[b]);
+ taxidata[a][b] = d + di;
+ distdata[a][b] = (d > di ? d : di);
+ };
+}
+
+#if (NEWMOVE > 1)
+struct sqdata posdata[3][8][64][64];
+
+static short direc[8][8] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, /* no_piece = 0 */
+ -10,-11, -9, 0, 0, 0, 0, 0, /* wpawn = 1 */
+ -21,-19,-12, -8, 21, 19, 12, 8, /* knight = 2 */
+ -11, -9, 11, 9, 0, 0, 0, 0, /* bishop = 3 */
+ -10, -1, 10, 1, 0, 0, 0, 0, /* rook = 4 */
+ -11, -9,-10, -1, 11, 9, 10, 1, /* queen = 5 */
+ -11, -9,-10, -1, 11, 9, 10, 1, /* king = 6 */
+ 0, 0, 0, 0, 0, 0, 0, 0};/* no_piece = 7 */
+
+static short dc[3] = {-1,1,0};
+
+static short max_steps [8] = {0,2,1,7,7,7,1,0};
+
+static short unmap[120] = {
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1, 0, 1, 2, 3, 4, 5, 6, 7,-1,
+ -1, 8, 9,10,11,12,13,14,15,-1,
+ -1,16,17,18,19,20,21,22,23,-1,
+ -1,24,25,26,27,28,29,30,31,-1,
+ -1,32,33,34,35,36,37,38,39,-1,
+ -1,40,41,42,43,44,45,46,47,-1,
+ -1,48,49,50,51,52,53,54,55,-1,
+ -1,56,57,58,59,60,61,62,63,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
+
+void Initialize_moves() {
+ short c,ptyp,po,p0,d,di,s;
+ struct sqdata *p;
+ short dest[8][8];
+ short steps[8];
+ short sorted[8];
+
+ /* init posdata */
+ for(c=0;c<3;c++)
+ for(ptyp=0;ptyp<8;ptyp++)
+ for(po=0;po<64;po++)
+ for(p0=0;p0<64;p0++) {
+ posdata[c][ptyp][po][p0].nextpos = po;
+ posdata[c][ptyp][po][p0].nextdir = po;
+ };
+ /* dest is a function of dir and step */
+ for(c=0;c<2;c++)
+ for(ptyp=1;ptyp<7;ptyp++)
+ for(po=21;po<99;po++)
+ if (unmap[po] >= 0) {
+ p = posdata[c][ptyp][unmap[po]];
+ for(d=0;d<8;d++) {
+ dest[d][0] = unmap[po];
+ if (dc[c]*direc[ptyp][d] != 0) {
+ p0=po;
+ for(s=0;s<max_steps[ptyp];s++) {
+ p0 = p0 + dc[c]*direc[ptyp][d];
+ /* break if (off board) or
+ (pawns move two steps from home square) */
+ if (unmap[p0] < 0 ||
+ (ptyp == pawn && s>0 && (d>0 || Stboard[unmap[po]] != ptyp)))
+ break;
+ else
+ dest[d][s] = unmap[p0];
+ }
+ }
+ else s=0;
+ /* sort dest in number of steps order */
+ steps[d] = s;
+ for(di=d;di>0;di--)
+ if (steps[sorted[di-1]] < s)
+ sorted[di] = sorted[di-1];
+ else
+ break;
+ sorted[di] = d;
+ }
+ /* update posdata, pawns have two threads (capture and no capture) */
+ p0=unmap[po];
+ if (ptyp == pawn) {
+ for(s=0;s<steps[0];s++) {
+ p[p0].nextpos = dest[0][s];
+ p0 = dest[0][s];
+ }
+ p0=unmap[po];
+ for(d=1;d<3;d++) {
+ p[p0].nextdir = dest[d][0];
+ p0 = dest[d][0];
+ }
+ }
+ else {
+ p[p0].nextdir = dest[sorted[0]][0];
+ for(d=0;d<8;d++)
+ for(s=0;s<steps[sorted[d]];s++) {
+ p[p0].nextpos = dest[sorted[d]][s];
+ p0 = dest[sorted[d]][s];
+ if (d < 7)
+ p[p0].nextdir = dest[sorted[d+1]][0];
+ /* else is already initialised */
+ }
+ }
+#ifdef DEBUG
+ printf("Ptyp:%d Position:%d\n{",ptyp,unmap[po]);
+ for(p0=0;p0<63;p0++) printf("%d,",p[p0].nextpos);
+ printf("%d};\n",p[63].nextpos);
+ for(p0=0;p0<63;p0++) printf("%d,",p[p0].nextdir);
+ printf("%d};\n",p[63].nextdir);
+#endif DEBUG
+ }
+}
+#endif
+
+
+#if (NEWMOVE > 2)
+int SqAtakd(sq,side)
+short sq,side;
+
+/*
+ See if any piece with color 'side' ataks sq. First check pawns
+ Then Queen, Bishop, Rook and King and last Knight.
+*/
+
+{
+ register short u;
+ register struct sqdata *p;
+
+ p = posdata[1-side][pawn][sq];
+ u = p[sq].nextdir; /* follow captures thread */
+ while (u != sq) {
+ if (board[u] == pawn && color[u] == side) return(true);
+ u = p[u].nextdir;
+ }
+ /* king capture */
+ if (distance(sq,PieceList[side][0]) == 1) return(true);
+ /* try a queen bishop capture */
+ p = posdata[side][bishop][sq];
+ u = p[sq].nextpos;
+ while (u != sq) {
+ if (color[u] == neutral) {
+ u = p[u].nextpos;
+ }
+ else {
+ if (color[u] == side &&
+ (board[u] == queen || board[u] == bishop))
+ return(true);
+ u = p[u].nextdir;
+ }
+ }
+ /* try a queen rook capture */
+ p = posdata[side][rook][sq];
+ u = p[sq].nextpos;
+ while (u != sq) {
+ if (color[u] == neutral) {
+ u = p[u].nextpos;
+ }
+ else {
+ if (color[u] == side &&
+ (board[u] == queen || board[u] == rook))
+ return(true);
+ u = p[u].nextdir;
+ }
+ }
+ /* try a knight capture */
+ p = posdata[side][knight][sq];
+ u = p[sq].nextpos;
+ while (u != sq) {
+ if (color[u] == neutral) {
+ u = p[u].nextpos;
+ }
+ else {
+ if (color[u] == side && board[u] == knight) return(true);
+ u = p[u].nextdir;
+ }
+ }
+ return(false);
+}
+#endif
+
+#if (NEWMOVE > 3)
+BRscan(sq,s,mob)
+short sq,*s,*mob;
+/*
+ Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the
+ hung[] array if a pin is found.
+*/
+{
+ register short u,piece,pin;
+ register struct sqdata *p;
+ short *Kf;
+
+ Kf = Kfield[c1];
+ *mob = 0;
+ piece = board[sq];
+ p = posdata[color[sq]][piece][sq];
+ u = p[sq].nextpos;
+ pin = -1; /* start new direction */
+ while (u != sq) {
+ *s += Kf[u];
+ if (color[u] == neutral) {
+ (*mob)++;
+ if (p[u].nextpos == p[u].nextdir) pin = -1; /* oops new direction */
+ u = p[u].nextpos;
+ }
+ else if (pin < 0) {
+ if (board[u] == pawn || board[u] == king)
+ u = p[u].nextdir;
+ else {
+ if (p[u].nextpos != p[u].nextdir)
+ pin = u; /* not on the edge and on to find a pin */
+ u = p[u].nextpos;
+ }
+ }
+ else if (color[u] == c2 && (board[u] > piece || atk2[u] == 0))
+ {
+ if (color[pin] == c2)
+ {
+ *s += PINVAL;
+ if (atk2[pin] == 0 ||
+ atk1[pin] > control[board[pin]]+1)
+ ++hung[c2];
+ }
+ else *s += XRAY;
+ pin = -1; /* new direction */
+ u = p[u].nextdir;
+ }
+ else {
+ pin = -1; /* new direction */
+ u = p[u].nextdir;
+ }
+ }
+}
+#endif
+
+#if (NEWMOVE >= 5)
+CaptureList(side,xside,ply)
+short side,xside,ply;
+{
+ register short u,sq;
+ register struct sqdata *p;
+ short i,piece,*PL;
+ struct leaf *node;
+
+ TrPnt[ply+1] = TrPnt[ply];
+ node = &Tree[TrPnt[ply]];
+ PL = PieceList[side];
+ for (i = 0; i <= PieceCnt[side]; i++)
+ {
+ sq = PL[i];
+ piece = board[sq];
+ p = posdata[side][piece][sq];
+ if (piece == pawn) {
+ u = p[sq].nextdir; /* follow captures thread */
+ while (u != sq) {
+ if (color[u] == xside) {
+ node->f = sq; node->t = u;
+ node->flags = capture;
+ if (u < 8 || u > 55)
+ {
+ node->flags |= promote;
+ node->score = valueQ;
+ }
+ else
+ node->score = value[board[u]] + svalue[board[u]] - piece;
+ ++node;
+ ++TrPnt[ply+1];
+ }
+ u = p[u].nextdir;
+ }
+ }
+ else {
+ u = p[sq].nextpos;
+ while (u != sq) {
+ if (color[u] == neutral)
+ u = p[u].nextpos;
+ else {
+ if (color[u] == xside) {
+ node->f = sq; node->t = u;
+ node->flags = capture;
+ node->score = value[board[u]] + svalue[board[u]] - piece;
+ ++node;
+ ++TrPnt[ply+1];
+ }
+ u = p[u].nextdir;
+ }
+ }
+ }
+ }
+}
+#endif
+
+#if (NEWMOVE > 5)
+GenMoves(ply,sq,side,xside)
+ short ply,sq,side,xside;
+
+/*
+ Generate moves for a piece. The moves are taken from the
+ precalulated array posdata. If the board is free, next move
+ is choosen from nextpos else from nextdir.
+*/
+
+{
+ register short u,piece;
+ register struct sqdata *p;
+
+ piece = board[sq];
+ p = posdata[side][piece][sq];
+ if (piece == pawn) {
+ u = p[sq].nextdir; /* follow captures thread */
+ while (u != sq) {
+ if (color[u] == xside) LinkMove(ply,sq,u,xside);
+ u = p[u].nextdir;
+ }
+ u = p[sq].nextpos; /* and follow no captures thread */
+ while (u != sq) {
+ if (color[u] == neutral && (u != sq+16 || color[u-8] == neutral)
+ && (u != sq-16 || color[u+8] == neutral)) {
+ LinkMove(ply,sq,u,xside);
+ }
+ u = p[u].nextpos;
+ }
+ }
+ else {
+ u = p[sq].nextpos;
+ while (u != sq) {
+ if (color[u] == neutral) {
+ LinkMove(ply,sq,u,xside);
+ u = p[u].nextpos;
+ }
+ else {
+ if (color[u] == xside) LinkMove(ply,sq,u,xside);
+ u = p[u].nextdir;
+ }
+ }
+ }
+}
+#endif
diff --git a/gnu/games/chess/move.h b/gnu/games/chess/move.h
new file mode 100644
index 000000000000..2f328303763f
--- /dev/null
+++ b/gnu/games/chess/move.h
@@ -0,0 +1,81 @@
+/* header file for move generator hes 890318
+ Modified: 890510 minor bug fixed in Newataks
+ 890606 NEWMOVE levels 1-6 */
+
+#if (NEWMOVE >= 1)
+extern short distdata[64][64];
+extern short taxidata[64][64];
+
+#define taxicab(a,b) taxidata[a][b]
+#define distance(a,b) distdata[a][b]
+
+extern void Initialize_dist();
+#endif
+
+#if (NEWMOVE >= 2)
+struct sqdata {
+ short nextpos;
+ short nextdir;
+};
+extern struct sqdata posdata[3][8][64][64];
+
+extern void Initialize_moves();
+
+#define ataks(side,a)\
+{\
+ register short u,c,sq;\
+ register struct sqdata *p;\
+ short i,piece,*PL;\
+ \
+ for (u = 64; u; a[--u] = 0); \
+ PL = PieceList[side];\
+ for (i = 0; i <= PieceCnt[side]; i++)\
+ {\
+ sq = PL[i];\
+ piece = board[sq];\
+ c = control[piece];\
+ p = posdata[side][piece][sq];\
+ if (piece == pawn) {\
+ u = p[sq].nextdir; /* follow captures thread */\
+ while (u != sq) {\
+ a[u] = ++a[u] | c;\
+ u = p[u].nextdir;\
+ }\
+ }\
+ else {\
+ u = p[sq].nextpos;\
+ while (u != sq) {\
+ a[u] = ++a[u] | c;\
+ if (color[u] == neutral)\
+ u = p[u].nextpos;\
+ else\
+ u = p[u].nextdir;\
+ }\
+ }\
+ }\
+}
+#endif
+
+#if (NEWMOVE >= 3)
+extern short PieceList[2][16];
+
+extern int Sqatakd();
+#endif
+
+#if (NEWMOVE > 3)
+extern short Kfield[2][64],PINVAL,control[7],hung[2],XRAY;
+
+extern BRscan();
+#endif
+
+#if (NEWMOVE > 4)
+#define valueQ 1100
+
+extern short PieceCnt[2],value[7],svalue[64];
+
+extern CaptureList();
+#endif
+
+#if (NEWMOVE > 5)
+extern GenMoves();
+#endif
diff --git a/gnu/games/chess/nondsp.c b/gnu/games/chess/nondsp.c
new file mode 100644
index 000000000000..0b29ad5504c5
--- /dev/null
+++ b/gnu/games/chess/nondsp.c
@@ -0,0 +1,791 @@
+/*
+ UNIX & MSDOS NON-DISPLAY, AND CHESSTOOL interface for Chess
+
+ Revision: 4-25-88
+
+ Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
+ Copyright (c) 1988 John Stanback
+
+ This file is part of CHESS.
+
+ CHESS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY. No author or distributor
+ accepts responsibility to anyone for the consequences of using it
+ or for whether it serves any particular purpose or works at all,
+ unless he says so in writing. Refer to the CHESS General Public
+ License for full details.
+
+ Everyone is granted permission to copy, modify and redistribute
+ CHESS, but only under the conditions described in the
+ CHESS General Public License. A copy of this license is
+ supposed to have been given to you along with CHESS so you
+ can know your rights and responsibilities. It should be in a
+ file named COPYING. Among other things, the copyright notice
+ and this notice must be preserved on all copies.
+*/
+
+
+#include <stdio.h>
+#include <ctype.h>
+#ifdef MSDOS
+#include <dos.h>
+#include <stdlib.h>
+#include <time.h>
+#else
+#include <sys/param.h>
+#include <sys/times.h>
+#include <sys/file.h>
+struct tms tmbuf1,tmbuf2;
+int TerminateSearch(),Die();
+#endif MSDOS
+
+#include "gnuchess.h"
+#ifdef NEWMOVE
+#include "move.h"
+#endif
+
+#define printz printf
+#define scanz scanf
+int mycnt1,mycnt2;
+
+
+Initialize()
+{
+ mycnt1 = mycnt2 = 0;
+#ifndef MSDOS
+#endif
+#ifdef CHESSTOOL
+ setlinebuf(stdout);
+/*
+ setvbuf(stdout,NULL,_IOLBF,BUFSIZ);
+*/
+ printf("Chess\n");
+ if (Level == 0 && !TCflag) Level = 15;
+#endif CHESSTOOL
+}
+
+ExitChess()
+{
+ ListGame();
+ exit(0);
+}
+
+#ifndef MSDOS
+Die()
+{
+char s[80];
+ printz("Abort? ");
+ scanz("%s",s);
+ if (strcmp(s,"yes") == 0) ExitChess();
+}
+
+TerminateSearch()
+{
+ timeout = true;
+ bothsides = false;
+}
+#endif MSDOS
+
+
+InputCommand()
+
+/*
+ Process the users command. If easy mode is OFF (the computer is
+ thinking on opponents time) and the program is out of book, then make
+ the 'hint' move on the board and call SelectMove() to find a response.
+ The user terminates the search by entering ^C (quit siqnal) before
+ entering a command. If the opponent does not make the hint move, then
+ set Sdepth to zero.
+*/
+
+{
+int i;
+short ok,tmp;
+long cnt,rate,t1,t2;
+unsigned short mv;
+char s[80];
+
+ ok = quit = false;
+ player = opponent;
+ ft = 0;
+ if (hint > 0 && !easy && Book == NULL)
+ {
+ fflush(stdout);
+ time0 = time((long *)0);
+ algbr(hint>>8,hint & 0xFF,false);
+ strcpy(s,mvstr1);
+ tmp = epsquare;
+ if (VerifyMove(s,1,&mv))
+ {
+ SelectMove(computer,2);
+ VerifyMove(mvstr1,2,&mv);
+ if (Sdepth > 0) Sdepth--;
+ }
+ ft = time((long *)0) - time0;
+ epsquare = tmp;
+ }
+
+#ifndef MSDOS
+#endif
+ while (!(ok || quit))
+ {
+ PromptForMove();
+ i = scanz("%s",s);
+ if (i == EOF || s[0] == 0) ExitChess();
+ player = opponent;
+ ok = VerifyMove(s,0,&mv);
+ if (ok && mv != hint)
+ {
+ Sdepth = 0;
+ ft = 0;
+ }
+
+ if (strcmp(s,"bd") == 0)
+ {
+ ClrScreen();
+ UpdateDisplay(0,0,1,0);
+ }
+ if (strcmp(s,"quit") == 0) quit = true;
+ if (strcmp(s,"post") == 0) post = !post;
+ if (strcmp(s,"set") == 0) EditBoard();
+ if (strcmp(s,"go") == 0) ok = true;
+ if (strcmp(s,"help") == 0) help();
+ if (strcmp(s,"force") == 0) force = !force;
+ if (strcmp(s,"book") == 0) Book = NULL;
+ if (strcmp(s,"new") == 0) NewGame();
+ if (strcmp(s,"list") == 0) ListGame();
+ if (strcmp(s,"level") == 0) SelectLevel();
+ if (strcmp(s,"hash") == 0) hashflag = !hashflag;
+ if (strcmp(s,"beep") == 0) beep = !beep;
+ if (strcmp(s,"Awindow") == 0) ChangeAlphaWindow();
+ if (strcmp(s,"Bwindow") == 0) ChangeBetaWindow();
+ if (strcmp(s,"rcptr") == 0) rcptr = !rcptr;
+ if (strcmp(s,"hint") == 0) GiveHint();
+ if (strcmp(s,"zero") == 0) ZeroTTable();
+ if (strcmp(s,"both") == 0)
+ {
+ bothsides = !bothsides;
+ Sdepth = 0;
+ SelectMove(opponent,1);
+ ok = true;
+ }
+ if (strcmp(s,"reverse") == 0)
+ {
+ reverse = !reverse;
+ ClrScreen();
+ UpdateDisplay(0,0,1,0);
+ }
+ if (strcmp(s,"switch") == 0)
+ {
+ computer = otherside[computer];
+ opponent = otherside[opponent];
+ force = false;
+ Sdepth = 0;
+ ok = true;
+ }
+ if (strcmp(s,"white") == 0)
+ {
+ computer = white; opponent = black;
+ ok = true; force = false;
+ Sdepth = 0;
+ }
+ if (strcmp(s,"black") == 0)
+ {
+ computer = black; opponent = white;
+ ok = true; force = false;
+ Sdepth = 0;
+ }
+ if (strcmp(s,"undo") == 0 && GameCnt >= 0) Undo();
+ if (strcmp(s,"remove") == 0 && GameCnt >= 1)
+ {
+ Undo(); Undo();
+ }
+ if (strcmp(s,"get") == 0) GetGame();
+ if (strcmp(s,"save") == 0) SaveGame();
+ if (strcmp(s,"depth") == 0) ChangeSearchDepth();
+ if (strcmp(s,"random") == 0) dither = 6;
+ if (strcmp(s,"easy") == 0) easy = !easy;
+ if (strcmp(s,"contempt") == 0) SetContempt();
+ if (strcmp(s,"xwndw") == 0) ChangeXwindow();
+ if (strcmp(s,"test") == 0)
+ {
+ t1 = time(0);
+ cnt = 0;
+ for (i = 0; i < 10000; i++)
+ {
+ MoveList(opponent,2);
+ cnt += TrPnt[3] - TrPnt[2];
+ }
+ t2 = time(0);
+ rate = cnt / (t2-t1);
+ printz("cnt= %ld rate= %ld\n",cnt,rate);
+ }
+ }
+
+ ElapsedTime(1);
+ if (force)
+ {
+ computer = opponent; opponent = otherside[computer];
+ }
+#ifndef MSDOS
+ (void) times(&tmbuf1);
+#ifdef CHESSTOOL
+ printf("%d. %s\n",++mycnt2,s);
+#endif CHESSTOOL
+#endif MSDOS
+}
+
+
+help()
+{
+ ClrScreen();
+ printz("CHESS command summary\n");
+ printz("g1f3 move from g1 to f3\n");
+ printz("nf3 move knight to f3\n");
+ printz("o-o castle king side\n");
+ printz("o-o-o castle queen side\n");
+ printz("set edit board\n");
+ printz("switch sides with computer\n");
+ printz("white computer plays white\n");
+ printz("black computer plays black\n");
+ printz("reverse board display\n");
+ printz("both computer match\n");
+ printz("random randomize play\n");
+ printz("undo undo last move\n");
+ printz("time change level\n");
+ printz("depth set search depth\n");
+ printz("post principle variation\n");
+ printz("hint suggest a move\n");
+ printz("bd redraw board\n");
+ printz("clock set time control\n");
+ printz("force enter game moves\n");
+ printz("list game to chess.lst\n");
+ printz("save game to file\n");
+ printz("get game from file\n");
+ printz("new start new game\n");
+ printz("quit exit CHESS\n");
+ printz("Computer: ");
+ if (computer == white) printz("WHITE\n"); else printz("BLACK\n");
+ printz("Opponent: ");
+ if (opponent == white) printz("WHITE\n"); else printz("BLACK\n");
+ printz("Response time: %ld",Level," sec.\n");
+ printz("Easy mode: ");
+ if (easy) printz("ON\n"); else printz("OFF\n");
+ printz("Depth: %d\n",MaxSearchDepth);
+ printz("Random: ");
+ if (dither) printz("ON\n"); else printz("OFF\n");
+ printz("Transposition table: ");
+ if (hashflag) printz("ON\n"); else printz("OFF\n");
+ UpdateDisplay(0,0,1,0);
+}
+
+
+EditBoard()
+
+/*
+ Set up a board position. Pieces are entered by typing the piece
+ followed by the location. For example, Nf3 will place a knight on
+ square f3.
+*/
+
+{
+short a,r,c,sq;
+char s[80];
+
+ ClrScreen();
+ UpdateDisplay(0,0,1,0);
+ printz(". exit to main\n");
+ printz("# clear board\n");
+ printz("enter piece & location: \n");
+
+ a = white;
+ do
+ {
+ scanz("%s",s);
+ if (s[0] == '#')
+ {
+ for (sq = 0; sq < 64; sq++)
+ {
+ board[sq] = no_piece; color[sq] = neutral;
+ }
+ UpdateDisplay(0,0,1,0);
+ }
+ if (s[0] == 'c' || s[0] == 'C') a = otherside[a];
+ c = s[1]-'a'; r = s[2]-'1';
+ if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8))
+ {
+ sq = locn[r][c];
+ color[sq] = a;
+ if (s[0] == 'p') board[sq] = pawn;
+ else if (s[0] == 'n') board[sq] = knight;
+ else if (s[0] == 'b') board[sq] = bishop;
+ else if (s[0] == 'r') board[sq] = rook;
+ else if (s[0] == 'q') board[sq] = queen;
+ else if (s[0] == 'k') board[sq] = king;
+ else { board[sq] = no_piece; color[sq] = neutral; }
+ }
+ }
+ while (s[0] != '.');
+ if (board[4] != king) kingmoved[white] = 10;
+ if (board[60] != king) kingmoved[black] = 10;
+ GameCnt = -1; Game50 = 0; Sdepth = 0;
+ InitializeStats();
+ ClrScreen();
+ UpdateDisplay(0,0,1,0);
+}
+
+
+ShowDepth(ch)
+char ch;
+{
+}
+
+ShowResults(score,bstline,ch)
+short score;
+unsigned short bstline[];
+char ch;
+{
+#ifndef CHESSTOOL
+register int i;
+ printz("%2d%c %5d %4ld %7ld ",Sdepth,ch,score,et,NodeCnt);
+ for (i = 1; bstline[i] > 0; i++)
+ {
+ algbr((short)(bstline[i] >> 8),(short)(bstline[i] & 0xFF),false);
+ if (i == 9 || i == 17) printz("\n ");
+ printz("%5s ",mvstr1);
+ }
+ printz("\n");
+#endif
+}
+
+
+SearchStartStuff(side)
+short side;
+{
+#ifndef MSDOS
+#endif
+#ifndef CHESSTOOL
+ printz("\nMove# %d Target= %ld Clock: %ld\n",
+ TCmoves-TimeControl.moves[side]+1,
+ ResponseTime,TimeControl.clock[side]);
+#endif
+}
+
+
+OutputMove()
+{
+#ifdef CHESSTOOL
+ printz("%d. ... %s\n",++mycnt1,mvstr1);
+ if (root->flags & draw)
+ {
+ printz("Draw\n");
+ ListGame();
+ exit(0);
+ }
+ if (root->score == -9999)
+ {
+ if (opponent == white) printz("White\n"); else printz("Black\n");
+ ListGame();
+ exit(0);
+ }
+ if (root->score == 9998)
+ {
+ if (computer == white) printz("White\n"); else printz("Black\n");
+ ListGame();
+ exit(0);
+ }
+#else
+ printz("Nodes= %ld Eval= %ld Hash= %ld Rate= %ld ",
+ NodeCnt,EvalNodes,HashCnt,evrate);
+ printz("CPU= %.2ld:%.2ld.%.2ld\n\n",
+ cputimer/6000,(cputimer % 6000)/100,cputimer % 100);
+
+ if (root->flags & epmask) UpdateDisplay(0,0,1,0);
+ else UpdateDisplay(root->f,root->t,0,root->flags & cstlmask);
+ printz("My move is: %s\n\n",mvstr1);
+ if (beep) printz("%c",7);
+
+ if (root->flags & draw) printz("Draw game!\n");
+ else if (root->score == -9999) printz("opponent mates!\n");
+ else if (root->score == 9998) printz("computer mates!\n");
+ else if (root->score < -9000) printz("opponent will soon mate!\n");
+ else if (root->score > 9000) printz("computer will soon mate!\n");
+#endif CHESSTOOL
+}
+
+
+ElapsedTime(iop)
+short iop;
+
+/*
+ Determine the time that has passed since the search was started. If
+ the elapsed time exceeds the target (ResponseTime+ExtraTime) then set
+ timeout to true which will terminate the search.
+*/
+
+{
+ et = time((long *)0) - time0;
+ if (et < 0) et = 0;
+ ETnodes += 50;
+ if (et > et0 || iop == 1)
+ {
+ if (et > ResponseTime+ExtraTime && Sdepth > 1) timeout = true;
+ et0 = et;
+ if (iop == 1)
+ {
+ time0 = time((long *)0); et0 = 0;
+ }
+#ifdef MSDOS
+ cputimer = 100*et;
+ if (et > 0) evrate = NodeCnt/(et+ft); else evrate = 0;
+ if (kbhit() && Sdepth > 1)
+ {
+ timeout = true;
+ bothsides = false;
+ }
+#else
+ (void) times(&tmbuf2);
+ cputimer = 100*(tmbuf2.tms_utime - tmbuf1.tms_utime) / HZ;
+ if (cputimer > 0) evrate = (100*NodeCnt)/(cputimer+100*ft);
+ else evrate = 0;
+#endif MSDOS
+ ETnodes = NodeCnt + 50;
+ }
+}
+
+
+SetTimeControl()
+{
+ if (TCflag)
+ {
+ TimeControl.moves[white] = TimeControl.moves[black] = TCmoves;
+ TimeControl.clock[white] = TimeControl.clock[black] = 60*(long)TCminutes;
+ }
+ else
+ {
+ TimeControl.moves[white] = TimeControl.moves[black] = 0;
+ TimeControl.clock[white] = TimeControl.clock[black] = 0;
+ Level = 60*(long)TCminutes;
+ }
+ et = 0;
+ ElapsedTime(1);
+}
+
+
+ClrScreen()
+{
+#ifndef CHESSTOOL
+ printz("\n");
+#endif
+}
+
+
+UpdateDisplay(f,t,flag,iscastle)
+short f,t,flag,iscastle;
+{
+#ifndef CHESSTOOL
+short r,c,l;
+ if (flag)
+ {
+ printz("\n");
+ for (r = 7; r >= 0; r--)
+ {
+ for (c = 0; c <= 7; c++)
+ {
+ if (reverse) l = locn[7-r][7-c]; else l = locn[r][c];
+ if (color[l] == neutral) printz(" -");
+ else if (color[l] == white) printz(" %c",qxx[board[l]]);
+ else printz(" %c",pxx[board[l]]);
+ }
+ printz("\n");
+ }
+ printz("\n");
+ }
+#endif CHESSTOOL
+}
+
+
+GetOpenings()
+
+/*
+ Read in the Opening Book file and parse the algebraic notation for a
+ move into an unsigned integer format indicating the from and to
+ square. Create a linked list of opening lines of play, with
+ entry->next pointing to the next line and entry->move pointing to a
+ chunk of memory containing the moves. More Opening lines of up to 256
+ half moves may be added to gnuchess.book.
+*/
+
+{
+FILE *fd;
+int c,i,j,side;
+char buffr[2048];
+struct BookEntry *entry;
+unsigned short mv,*mp,tmp[100];
+
+ if ((fd = fopen("gnuchess.book","r")) != NULL)
+ {
+/*
+ setvbuf(fd,buffr,_IOFBF,2048);
+*/
+ Book = NULL;
+ i = 0; side = white;
+ while ((c = parse(fd,&mv,side)) >= 0)
+ if (c == 1)
+ {
+ tmp[++i] = mv;
+ side = otherside[side];
+ }
+ else if (c == 0 && i > 0)
+ {
+ entry = (struct BookEntry *)malloc(sizeof(struct BookEntry));
+ mp = (unsigned short *)malloc((i+1)*sizeof(unsigned short));
+ entry->mv = mp;
+ entry->next = Book;
+ Book = entry;
+ for (j = 1; j <= i; j++) *(mp++) = tmp[j];
+ *mp = 0;
+ i = 0; side = white;
+ }
+ fclose(fd);
+ }
+}
+
+
+int parse(fd,mv,side)
+FILE *fd;
+unsigned short *mv;
+short side;
+{
+int c,i,r1,r2,c1,c2;
+char s[100];
+ while ((c = getc(fd)) == ' ');
+ i = 0; s[0] = c;
+ while (c != ' ' && c != '\n' && c != EOF) s[++i] = c = getc(fd);
+ s[++i] = '\0';
+ if (c == EOF) return(-1);
+ if (s[0] == '!' || i < 3)
+ {
+ while (c != '\n' && c != EOF) c = getc(fd);
+ return(0);
+ }
+ if (s[4] == 'o')
+ if (side == black) *mv = 0x3C3A; else *mv = 0x0402;
+ else if (s[0] == 'o')
+ if (side == black) *mv = 0x3C3E; else *mv = 0x0406;
+ else
+ {
+ c1 = s[0] - 'a'; r1 = s[1] - '1';
+ c2 = s[2] - 'a'; r2 = s[3] - '1';
+ *mv = (locn[r1][c1]<<8) + locn[r2][c2];
+ }
+ return(1);
+}
+
+
+GetGame()
+{
+FILE *fd;
+char fname[40];
+int c;
+short sq;
+unsigned short m;
+
+ printz("Enter file name: ");
+ scanz("%s",fname);
+ if (fname[0] == '\0') strcpy(fname,"chess.000");
+ if ((fd = fopen(fname,"r")) != NULL)
+ {
+ fscanf(fd,"%hd%hd%hd",&computer,&opponent,&Game50);
+ fscanf(fd,"%hd%hd%hd%hd",
+ &castld[white],&castld[black],
+ &kingmoved[white],&kingmoved[black]);
+ fscanf(fd,"%hd%hd",&TCflag,&OperatorTime);
+ fscanf(fd,"%ld%ld%hd%hd",
+ &TimeControl.clock[white],&TimeControl.clock[black],
+ &TimeControl.moves[white],&TimeControl.moves[black]);
+ for (sq = 0; sq < 64; sq++)
+ {
+ fscanf(fd,"%hd",&m);
+ board[sq] = (m >> 8); color[sq] = (m & 0xFF);
+ if (color[sq] == 0) color[sq] = neutral; else --color[sq];
+ }
+ GameCnt = -1; c = '?';
+ while (c != EOF)
+ {
+ ++GameCnt;
+ c = fscanf(fd,"%hd%hd%hd%ld%hd%hd%hd",&GameList[GameCnt].gmove,
+ &GameList[GameCnt].score,&GameList[GameCnt].depth,
+ &GameList[GameCnt].nodes,&GameList[GameCnt].time,
+ &GameList[GameCnt].piece,&GameList[GameCnt].color);
+ if (GameList[GameCnt].color == 0) GameList[GameCnt].color = neutral;
+ else --GameList[GameCnt].color;
+ }
+ GameCnt--;
+ if (TimeControl.clock[white] > 0) TCflag = true;
+ computer--; opponent--;
+ }
+ fclose(fd);
+ InitializeStats();
+ UpdateDisplay(0,0,1,0);
+ Sdepth = 0;
+}
+
+
+SaveGame()
+{
+FILE *fd;
+char fname[40];
+short sq,i,c;
+
+ printz("Enter file name: ");
+ scanz("%s",fname);
+
+ if (fname[0] == '\0' || access(fname,W_OK) == -1) strcpy(fname,"chess.000");
+ fd = fopen(fname,"w");
+ fprintf(fd,"%d %d %d\n",computer+1,opponent+1,Game50);
+ fprintf(fd,"%d %d %d %d\n",
+ castld[white],castld[black],kingmoved[white],kingmoved[black]);
+ fprintf(fd,"%d %d\n",TCflag,OperatorTime);
+ fprintf(fd,"%ld %ld %d %d\n",
+ TimeControl.clock[white],TimeControl.clock[black],
+ TimeControl.moves[white],TimeControl.moves[black]);
+ for (sq = 0; sq < 64; sq++)
+ {
+ if (color[sq] == neutral) c = 0; else c = color[sq]+1;
+ fprintf(fd,"%d\n",256*board[sq] + c);
+ }
+ for (i = 0; i <= GameCnt; i++)
+ {
+ if (GameList[i].color == neutral) c = 0;
+ else c = GameList[i].color + 1;
+ fprintf(fd,"%d %d %d %ld %d %d %d\n",
+ GameList[i].gmove,GameList[i].score,GameList[i].depth,
+ GameList[i].nodes,GameList[i].time,
+ GameList[i].piece,c);
+ }
+ fclose(fd);
+}
+
+
+ListGame()
+{
+FILE *fd;
+short i,f,t;
+ fd = fopen("chess.lst","w");
+ fprintf(fd,"\n");
+ fprintf(fd," score depth nodes time ");
+ fprintf(fd," score depth nodes time\n");
+ for (i = 0; i <= GameCnt; i++)
+ {
+ f = GameList[i].gmove>>8; t = (GameList[i].gmove & 0xFF);
+ algbr(f,t,false);
+ if ((i % 2) == 0) fprintf(fd,"\n"); else fprintf(fd," ");
+ fprintf(fd,"%5s %5d %2d %6ld %5d",mvstr1,
+ GameList[i].score,GameList[i].depth,
+ GameList[i].nodes,GameList[i].time);
+ }
+ fprintf(fd,"\n\n");
+ fclose(fd);
+}
+
+
+Undo()
+
+/*
+ Undo the most recent half-move.
+*/
+
+{
+short f,t;
+ f = GameList[GameCnt].gmove>>8;
+ t = GameList[GameCnt].gmove & 0xFF;
+ if (board[t] == king && distance(t,f) > 1)
+ castle(GameList[GameCnt].color,f,t,2);
+ else
+ {
+ board[f] = board[t]; color[f] = color[t];
+ board[t] = GameList[GameCnt].piece;
+ color[t] = GameList[GameCnt].color;
+ if (board[f] == king) --kingmoved[color[f]];
+ }
+ if (TCflag) ++TimeControl.moves[color[f]];
+ GameCnt--; mate = false; Sdepth = 0;
+ UpdateDisplay(0,0,1,0);
+ InitializeStats();
+}
+
+
+ShowMessage(s)
+char *s;
+{
+#ifndef CHESSTOOL
+ printz("%s\n");
+#endif CHESSTOOL
+}
+
+ShowSidetomove()
+{
+}
+
+PromptForMove()
+{
+#ifndef CHESSTOOL
+ printz("\nYour move is? ");
+#endif CHESSTOOL
+}
+
+
+ShowCurrentMove(pnt,f,t)
+short pnt,f,t;
+{
+}
+
+ChangeAlphaWindow()
+{
+ printz("window: ");
+ scanz("%hd",&Awindow);
+}
+
+ChangeBetaWindow()
+{
+ printz("window: ");
+ scanz("%hd",&Bwindow);
+}
+
+GiveHint()
+{
+ algbr((short)(hint>>8),(short)(hint & 0xFF),false);
+ printz("try %s\n",mvstr1);
+}
+
+
+SelectLevel()
+{
+ OperatorTime = 30000;
+ printz("Enter #moves #minutes: ");
+ scanz("%hd %hd",&TCmoves,&TCminutes);
+ printz("Operator time= ");
+ scanz("%hd",&OperatorTime);
+ TCflag = (TCmoves > 1);
+ SetTimeControl();
+}
+
+
+ChangeSearchDepth()
+{
+ printz("depth= ");
+ scanz("%hd",&MaxSearchDepth);
+}
+
+SetContempt()
+{
+ printz("contempt= ");
+ scanz("%hd",&contempt);
+}
+
+ChangeXwindow()
+{
+ printz("xwndw= ");
+ scanz("%hd",&xwndw);
+}
diff --git a/gnu/games/chess/pathnames.h b/gnu/games/chess/pathnames.h
new file mode 100644
index 000000000000..b70a0f0d417d
--- /dev/null
+++ b/gnu/games/chess/pathnames.h
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pathnames.h 5.1 (Berkeley) 5/2/90
+ */
+
+#define _PATH_CHESSBOOK "/usr/share/games/gnuchess.book"
diff --git a/gnu/games/chess/uxdsp.c b/gnu/games/chess/uxdsp.c
new file mode 100644
index 000000000000..d584738042a9
--- /dev/null
+++ b/gnu/games/chess/uxdsp.c
@@ -0,0 +1,933 @@
+/*
+ ALPHA interface for CHESS
+
+ Revision: 4-25-88
+
+ Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
+ Copyright (c) 1988 John Stanback
+
+ This file is part of CHESS.
+
+ CHESS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY. No author or distributor
+ accepts responsibility to anyone for the consequences of using it
+ or for whether it serves any particular purpose or works at all,
+ unless he says so in writing. Refer to the CHESS General Public
+ License for full details.
+
+ Everyone is granted permission to copy, modify and redistribute
+ CHESS, but only under the conditions described in the
+ CHESS General Public License. A copy of this license is
+ supposed to have been given to you along with CHESS so you
+ can know your rights and responsibilities. It should be in a
+ file named COPYING. Among other things, the copyright notice
+ and this notice must be preserved on all copies.
+*/
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/param.h>
+#include <sys/times.h>
+#include <sys/file.h>
+#include <curses.h>
+#include <signal.h>
+#include "gnuchess.h"
+#ifdef NEWMOVE
+#include "move.h"
+#endif
+#include "pathnames.h"
+
+struct tms tmbuf1,tmbuf2;
+void TerminateSearch(),Die();
+
+#define scanz fflush(stdout),scanw
+#define printz printw
+
+
+Initialize()
+{
+ signal(SIGINT,Die); signal(SIGQUIT,Die);
+ initscr();
+ crmode();
+}
+
+
+ExitChess()
+{
+ nocrmode();
+ endwin();
+ exit(0);
+}
+
+
+void
+Die()
+{
+char s[80];
+ signal(SIGINT,SIG_IGN);
+ signal(SIGQUIT,SIG_IGN);
+ ShowMessage("Abort? ");
+ scanz("%s",s);
+ if (strcmp(s,"yes") == 0) ExitChess();
+ signal(SIGINT,Die); signal(SIGQUIT,Die);
+}
+
+
+void
+TerminateSearch()
+{
+ signal(SIGINT,SIG_IGN);
+ signal(SIGQUIT,SIG_IGN);
+ timeout = true;
+ bothsides = false;
+ signal(SIGINT,Die); signal(SIGQUIT,Die);
+}
+
+
+InputCommand()
+
+/*
+ Process the users command. If easy mode is OFF (the computer is
+ thinking on opponents time) and the program is out of book, then make
+ the 'hint' move on the board and call SelectMove() to find a response.
+ The user terminates the search by entering ^C (quit siqnal) before
+ entering a command. If the opponent does not make the hint move, then
+ set Sdepth to zero.
+*/
+
+{
+short ok,i,tmp;
+long cnt,rate,t1,t2;
+unsigned short mv;
+char s[80];
+
+ ok = quit = false;
+ player = opponent;
+ ShowSidetomove();
+ ft = 0;
+ if (hint > 0 && !easy && Book == NULL)
+ {
+ fflush(stdout);
+ time0 = time((long *)0);
+ algbr(hint>>8,hint & 0xFF,false);
+ strcpy(s,mvstr1);
+ tmp = epsquare;
+ if (VerifyMove(s,1,&mv))
+ {
+ PromptForMove();
+ SelectMove(computer,2);
+ VerifyMove(mvstr1,2,&mv);
+ if (Sdepth > 0) Sdepth--;
+ }
+ ft = time((time_t *)0) - time0;
+ epsquare = tmp;
+ }
+
+ signal(SIGINT,Die); signal(SIGQUIT,Die);
+ while (!(ok || quit))
+ {
+ PromptForMove();
+ scanz("%s",s);
+ player = opponent;
+ ok = VerifyMove(s,0,&mv);
+ if (ok && mv != hint)
+ {
+ Sdepth = 0;
+ ft = 0;
+ }
+
+ if (strcmp(s,"bd") == 0)
+ {
+ ClrScreen();
+ UpdateDisplay(0,0,1,0);
+ }
+ if (strcmp(s,"quit") == 0) quit = true;
+ if (strcmp(s,"post") == 0) post = !post;
+ if (strcmp(s,"edit") == 0) EditBoard();
+ if (strcmp(s,"go") == 0) ok = true;
+ if (strcmp(s,"help") == 0) help();
+ if (strcmp(s,"force") == 0) force = !force;
+ if (strcmp(s,"book") == 0) Book = NULL;
+ if (strcmp(s,"undo") == 0 && GameCnt >= 0) Undo();
+ if (strcmp(s,"new") == 0) NewGame();
+ if (strcmp(s,"list") == 0) ListGame();
+ if (strcmp(s,"level") == 0) SelectLevel();
+ if (strcmp(s,"hash") == 0) hashflag = !hashflag;
+ if (strcmp(s,"beep") == 0) beep = !beep;
+ if (strcmp(s,"Awindow") == 0) ChangeAlphaWindow();
+ if (strcmp(s,"Bwindow") == 0) ChangeBetaWindow();
+ if (strcmp(s,"hint") == 0) GiveHint();
+ if (strcmp(s,"both") == 0)
+ {
+ bothsides = !bothsides;
+ Sdepth = 0;
+ SelectMove(opponent,1);
+ ok = true;
+ }
+ if (strcmp(s,"reverse") == 0)
+ {
+ reverse = !reverse;
+ ClrScreen();
+ UpdateDisplay(0,0,1,0);
+ }
+ if (strcmp(s,"switch") == 0)
+ {
+ computer = otherside[computer];
+ opponent = otherside[opponent];
+ force = false;
+ Sdepth = 0;
+ ok = true;
+ }
+ if (strcmp(s,"white") == 0)
+ {
+ computer = white; opponent = black;
+ ok = true; force = false;
+ Sdepth = 0;
+ }
+ if (strcmp(s,"black") == 0)
+ {
+ computer = black; opponent = white;
+ ok = true; force = false;
+ Sdepth = 0;
+ }
+ if (strcmp(s,"remove") == 0 && GameCnt >= 1)
+ {
+ Undo(); Undo();
+ }
+ if (strcmp(s,"get") == 0) GetGame();
+ if (strcmp(s,"save") == 0) SaveGame();
+ if (strcmp(s,"depth") == 0) ChangeSearchDepth();
+ if (strcmp(s,"random") == 0) dither = 6;
+ if (strcmp(s,"easy") == 0) easy = !easy;
+ if (strcmp(s,"contempt") == 0) SetContempt();
+ if (strcmp(s,"xwndw") == 0) ChangeXwindow();
+ if (strcmp(s,"test") == 0)
+ {
+ t1 = time(0);
+ cnt = 0;
+ for (i = 0; i < 10000; i++)
+ {
+ MoveList(opponent,2);
+ cnt += TrPnt[3] - TrPnt[2];
+ }
+ t2 = time(0);
+ rate = cnt / (t2-t1);
+ gotoXY(50,24);
+ printz("cnt= %ld rate= %ld",cnt,rate);
+ ClrEoln();
+ }
+ if (strcmp(s,"p") == 0) ShowPostnValues();
+ if (strcmp(s,"debug") == 0) DoDebug();
+ }
+
+ ClearMessage();
+ ElapsedTime(1);
+ if (force)
+ {
+ computer = opponent; opponent = otherside[computer];
+ }
+ (void) times(&tmbuf1);
+ signal(SIGINT,TerminateSearch); signal(SIGQUIT,TerminateSearch);
+}
+
+
+EditBoard()
+
+/*
+ Set up a board position. Pieces are entered by typing the piece
+ followed by the location. For example, Nf3 will place a knight on
+ square f3.
+*/
+
+{
+short a,r,c,sq;
+char s[80];
+
+ ClrScreen();
+ UpdateDisplay(0,0,1,0);
+ gotoXY(50,2); printz(". Exit to main");
+ gotoXY(50,3); printz("# Clear board");
+ gotoXY(49,5); printz("Enter piece & location: ");
+ a = white;
+ do
+ {
+ gotoXY(73,5); ClrEoln(); scanz("%s",s);
+ if (s[0] == '#')
+ {
+ for (sq = 0; sq < 64; sq++)
+ {
+ board[sq] = no_piece; color[sq] = neutral;
+ }
+ UpdateDisplay(0,0,1,0);
+ }
+ if (s[0] == 'c' || s[0] == 'C') a = otherside[a];
+ c = s[1]-'a'; r = s[2]-'1';
+ if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8))
+ {
+ sq = locn[r][c];
+ color[sq] = a;
+ if (s[0] == 'p') board[sq] = pawn;
+ else if (s[0] == 'n') board[sq] = knight;
+ else if (s[0] == 'b') board[sq] = bishop;
+ else if (s[0] == 'r') board[sq] = rook;
+ else if (s[0] == 'q') board[sq] = queen;
+ else if (s[0] == 'k') board[sq] = king;
+ else { board[sq] = no_piece; color[sq] = neutral; }
+ DrawPiece(sq);
+ }
+ }
+ while (s[0] != '.');
+ if (board[4] != king) kingmoved[white] = 10;
+ if (board[60] != king) kingmoved[black] = 10;
+ GameCnt = -1; Game50 = 0; Sdepth = 0;
+ InitializeStats();
+ ClrScreen();
+ UpdateDisplay(0,0,1,0);
+}
+
+
+help()
+{
+ ClrScreen();
+ gotoXY(28,1); printz("CHESS command summary");
+ gotoXY(1,3); printz("g1f3 move from g1 to f3");
+ gotoXY(1,4); printz("nf3 move knight to f3");
+ gotoXY(1,5); printz("o-o castle king side");
+ gotoXY(1,6); printz("o-o-o castle queen side");
+ gotoXY(1,7); printz("edit edit board");
+ gotoXY(1,8); printz("switch sides with computer");
+ gotoXY(1,9); printz("white computer plays white");
+ gotoXY(1,10); printz("black computer plays black");
+ gotoXY(1,11); printz("reverse board display");
+ gotoXY(1,12); printz("both computer match");
+ gotoXY(1,13); printz("random randomize play");
+ gotoXY(1,14); printz("undo undo last move");
+ gotoXY(42,3); printz("level change level");
+ gotoXY(42,4); printz("depth set search depth");
+ gotoXY(42,5); printz("post principle variation");
+ gotoXY(42,6); printz("hint suggest a move");
+ gotoXY(42,7); printz("bd redraw board");
+ gotoXY(42,8); printz("force enter game moves");
+ gotoXY(42,9); printz("list game to chess.lst");
+ gotoXY(42,10); printz("save game to file");
+ gotoXY(42,11); printz("get game from file");
+ gotoXY(42,12); printz("new start new game");
+ gotoXY(42,13); printz("quit exit CHESS");
+ gotoXY(10,21); printz("Computer: ");
+ if (computer == white) printz("WHITE"); else printz("BLACK");
+ gotoXY(10,22); printz("Opponent: ");
+ if (opponent == white) printz("WHITE"); else printz("BLACK");
+ gotoXY(10,23); printz("Level: %ld",Level," sec.");
+ gotoXY(10,24); printz("Easy mode: ");
+ if (easy) printz("ON"); else printz("OFF");
+ gotoXY(40,21); printz("Depth: %d",MaxSearchDepth);
+ gotoXY(40,22); printz("Random: ");
+ if (dither) printz("ON"); else printz("OFF");
+ gotoXY(40,23); printz("Transposition table: ");
+ if (hashflag) printz("ON"); else printz("OFF");
+ refresh();
+ while (getchar() != 27);
+ ClrScreen();
+ UpdateDisplay(0,0,1,0);
+}
+
+
+ShowDepth(ch)
+char ch;
+{
+ gotoXY(50,4); printz("Depth= %d%c ",Sdepth,ch); ClrEoln();
+}
+
+
+ShowResults(score,bstline,ch)
+short score;
+unsigned short bstline[];
+char ch;
+{
+short d,e,ply;
+ if (post && player == computer)
+ {
+ e = lpost;
+ gotoXY(50,5); printz("Score= %d",score); ClrEoln();
+ d = 8; gotoXY(50,d); ClrEoln();
+ for (ply = 1; bstline[ply] > 0; ply++)
+ {
+ algbr(bstline[ply] >> 8,bstline[ply] & 0xFF,false);
+ if (ply == 5 || ply == 9 || ply == 13 || ply == 17)
+ {
+ gotoXY(50,++d); ClrEoln();
+ }
+ printz("%5s ",mvstr1);
+ }
+ ClrEoln();
+ lpost = d;
+ while (++d <= e)
+ {
+ gotoXY(50,d); ClrEoln();
+ }
+ }
+}
+
+
+SearchStartStuff(side)
+short side;
+{
+short i;
+ signal(SIGINT,TerminateSearch); signal(SIGQUIT,TerminateSearch);
+ if (player == computer)
+ for (i = 5; i < 14; i++)
+ {
+ gotoXY(50,i); ClrEoln();
+ }
+}
+
+
+OutputMove()
+{
+ if (root->flags & epmask) UpdateDisplay(0,0,1,0);
+ else UpdateDisplay(root->f,root->t,0,root->flags & cstlmask);
+ gotoXY(50,17); printz("My move is: %s",mvstr1);
+ if (beep) putchar(7);
+ ClrEoln();
+
+ gotoXY(50,24);
+ if (root->flags & draw) printz("Draw game!");
+ else if (root->score == -9999) printz("opponent mates!");
+ else if (root->score == 9998) printz("computer mates!");
+ else if (root->score < -9000) printz("opponent will soon mate!");
+ else if (root->score > 9000) printz("computer will soon mate!");
+ ClrEoln();
+
+ if (post)
+ {
+ gotoXY(50,22); printz("Nodes= %6ld",NodeCnt); ClrEoln();
+ gotoXY(50,23); printz("Nodes/Sec= %4ld",evrate); ClrEoln();
+ }
+}
+
+
+ElapsedTime(iop)
+
+/*
+ Determine the time that has passed since the search was started. If
+ the elapsed time exceeds the target (ResponseTime+ExtraTime) then set
+ timeout to true which will terminate the search.
+*/
+
+short iop;
+{
+ et = time((time_t *)0) - time0;
+ if (et < 0) et = 0;
+ ETnodes += 50;
+ if (et > et0 || iop == 1)
+ {
+ if (et > ResponseTime+ExtraTime && Sdepth > 1) timeout = true;
+ et0 = et;
+ if (iop == 1)
+ {
+ time0 = time((time_t *)0); et0 = 0;
+ }
+ (void) times(&tmbuf2);
+ cputimer = 100*(tmbuf2.tms_utime - tmbuf1.tms_utime) / HZ;
+ if (cputimer > 0) evrate = (100*NodeCnt)/(cputimer+100*ft);
+ else evrate = 0;
+ ETnodes = NodeCnt + 50;
+ UpdateClocks();
+ }
+}
+
+
+UpdateClocks()
+{
+short m,s;
+ m = et/60; s = (et - 60*m);
+ if (TCflag)
+ {
+ m = (TimeControl.clock[player] - et) / 60;
+ s = TimeControl.clock[player] - et - 60*m;
+ }
+ if (m < 0) m = 0;
+ if (s < 0) s = 0;
+ if (player == white)
+ if (reverse) gotoXY(20,2); else gotoXY(20,23);
+ else
+ if (reverse) gotoXY(20,23); else gotoXY(20,2);
+ printz("%d:%2d ",m,s);
+ if (post)
+ {
+ gotoXY(50,22); printz("Nodes= %6ld",NodeCnt);
+ gotoXY(50,23); printz("Nodes/Sec= %4ld",evrate);
+ }
+ refresh();
+}
+
+
+
+SetTimeControl()
+{
+ if (TCflag)
+ {
+ TimeControl.moves[white] = TimeControl.moves[black] = TCmoves;
+ TimeControl.clock[white] = TimeControl.clock[black] = 60*(long)TCminutes;
+ }
+ else
+ {
+ TimeControl.moves[white] = TimeControl.moves[black] = 0;
+ TimeControl.clock[white] = TimeControl.clock[black] = 0;
+ Level = 60*(long)TCminutes;
+ }
+ et = 0;
+ ElapsedTime(1);
+}
+
+
+gotoXY(x,y)
+short x,y;
+{
+ move(y-1,x-1);
+}
+
+
+ClrScreen()
+{
+ clear(); refresh();
+}
+
+
+ClrEoln()
+{
+ clrtoeol(); refresh();
+}
+
+
+DrawPiece(sq)
+short sq;
+{
+short r,c; char x;
+ if (reverse) r = 7-row[sq]; else r = row[sq];
+ if (reverse) c = 7-column[sq]; else c = column[sq];
+ if (color[sq] == black) x = '*'; else x = ' ';
+ gotoXY(5+5*c,5+2*(7-r)); printz("%c%c ",x,pxx[board[sq]]);
+}
+
+
+UpdateDisplay(f,t,flag,iscastle)
+short f,t,flag,iscastle;
+{
+short i,l,z;
+ if (flag)
+ {
+ gotoXY(56,2); printz("CHESS");
+ i = 3;
+ gotoXY(3,++i);
+ printz("|----|----|----|----|----|----|----|----|");
+ while (i<19)
+ {
+ gotoXY(1,++i);
+ if (reverse) z = (i/2)-1; else z = 10-(i/2);
+ printz("%d | | | | | | | | |",z);
+ gotoXY(3,++i);
+ if (i < 19)
+ printz("+----+----+----+----+----+----+----+----+");
+ }
+ printz("|----|----|----|----|----|----|----|----|");
+ gotoXY(3,21);
+ if (reverse) printz(" h g f e d c b a");
+ else printz(" a b c d e f g h");
+ if (reverse) gotoXY(5,23); else gotoXY(5,2);
+ if (computer == black) printz("Computer"); else printz("Human ");
+ if (reverse) gotoXY(5,2); else gotoXY(5,23);
+ if (computer == white) printz("Computer"); else printz("Human ");
+ for (l = 0; l < 64; l++) DrawPiece(l);
+ }
+ else
+ {
+ DrawPiece(f); DrawPiece(t);
+ if (iscastle)
+ if (t > f)
+ { DrawPiece(f+3); DrawPiece(t-1); }
+ else
+ { DrawPiece(f-4); DrawPiece(t+1); }
+ }
+ refresh();
+}
+
+
+GetOpenings()
+
+/*
+ Read in the Opening Book file and parse the algebraic notation for a
+ move into an unsigned integer format indicating the from and to
+ square. Create a linked list of opening lines of play, with
+ entry->next pointing to the next line and entry->move pointing to a
+ chunk of memory containing the moves. More Opening lines of up to 256
+ half moves may be added to gnuchess.book.
+*/
+
+{
+FILE *fd;
+int c,i,j,side;
+struct BookEntry *entry;
+unsigned short mv,*mp,tmp[100];
+
+ if ((fd = fopen(_PATH_CHESSBOOK,"r")) != NULL)
+ {
+ Book = NULL;
+ i = 0; side = white;
+ while ((c = parse(fd,&mv,side)) >= 0)
+ if (c == 1)
+ {
+ tmp[++i] = mv;
+ side = otherside[side];
+ }
+ else if (c == 0 && i > 0)
+ {
+ entry = (struct BookEntry *)malloc(sizeof(struct BookEntry));
+ mp = (unsigned short *)malloc((i+1)*sizeof(unsigned short));
+ entry->mv = mp;
+ entry->next = Book;
+ Book = entry;
+ for (j = 1; j <= i; j++) *(mp++) = tmp[j];
+ *mp = 0;
+ i = 0; side = white;
+ }
+ fclose(fd);
+ }
+ else
+ {
+ fprintf(stderr, "\nchess: can't read %s.\n", _PATH_CHESSBOOK);
+ exit(1);
+ }
+}
+
+
+int parse(fd,mv,side)
+FILE *fd;
+unsigned short *mv;
+short side;
+{
+int c,i,r1,r2,c1,c2;
+char s[100];
+ while ((c = getc(fd)) == ' ');
+ i = 0; s[0] = c;
+ while (c != ' ' && c != '\n' && c != EOF) s[++i] = c = getc(fd);
+ s[++i] = '\0';
+ if (c == EOF) return(-1);
+ if (s[0] == '!' || i < 3)
+ {
+ while (c != '\n' && c != EOF) c = getc(fd);
+ return(0);
+ }
+ if (s[4] == 'o')
+ if (side == black) *mv = 0x3C3A; else *mv = 0x0402;
+ else if (s[0] == 'o')
+ if (side == black) *mv = 0x3C3E; else *mv = 0x0406;
+ else
+ {
+ c1 = s[0] - 'a'; r1 = s[1] - '1';
+ c2 = s[2] - 'a'; r2 = s[3] - '1';
+ *mv = (locn[r1][c1]<<8) + locn[r2][c2];
+ }
+ return(1);
+}
+
+
+GetGame()
+{
+FILE *fd;
+char fname[40];
+int c;
+short sq;
+unsigned short m;
+
+ ShowMessage("File name: ");
+ scanz("%s",fname);
+ if (fname[0] == '\0') strcpy(fname,"chess.000");
+ if ((fd = fopen(fname,"r")) != NULL)
+ {
+ fscanf(fd,"%hd%hd%hd",&computer,&opponent,&Game50);
+ fscanf(fd,"%hd%hd%hd%hd",
+ &castld[white],&castld[black],
+ &kingmoved[white],&kingmoved[black]);
+ fscanf(fd,"%hd%hd",&TCflag,&OperatorTime);
+ fscanf(fd,"%ld%ld%hd%hd",
+ &TimeControl.clock[white],&TimeControl.clock[black],
+ &TimeControl.moves[white],&TimeControl.moves[black]);
+ for (sq = 0; sq < 64; sq++)
+ {
+ fscanf(fd,"%hd",&m);
+ board[sq] = (m >> 8); color[sq] = (m & 0xFF);
+ if (color[sq] == 0) color[sq] = neutral; else --color[sq];
+ }
+ GameCnt = -1; c = '?';
+ while (c != EOF)
+ {
+ ++GameCnt;
+ c = fscanf(fd,"%hd%hd%hd%ld%hd%hd%hd",&GameList[GameCnt].gmove,
+ &GameList[GameCnt].score,&GameList[GameCnt].depth,
+ &GameList[GameCnt].nodes,&GameList[GameCnt].time,
+ &GameList[GameCnt].piece,&GameList[GameCnt].color);
+ if (GameList[GameCnt].color == 0) GameList[GameCnt].color = neutral;
+ else --GameList[GameCnt].color;
+ }
+ GameCnt--;
+ if (TimeControl.clock[white] > 0) TCflag = true;
+ computer--; opponent--;
+ }
+ fclose(fd);
+ InitializeStats();
+ UpdateDisplay(0,0,1,0);
+ Sdepth = 0;
+}
+
+
+SaveGame()
+{
+FILE *fd;
+char fname[40];
+short sq,i,c;
+
+ ShowMessage("File name: ");
+ scanz("%s",fname);
+
+ if (fname[0] == '\0' || access(fname,W_OK) == -1) strcpy(fname,"chess.000");
+ fd = fopen(fname,"w");
+ fprintf(fd,"%d %d %d\n",computer+1,opponent+1,Game50);
+ fprintf(fd,"%d %d %d %d\n",
+ castld[white],castld[black],kingmoved[white],kingmoved[black]);
+ fprintf(fd,"%d %d\n",TCflag,OperatorTime);
+ fprintf(fd,"%ld %ld %d %d\n",
+ TimeControl.clock[white],TimeControl.clock[black],
+ TimeControl.moves[white],TimeControl.moves[black]);
+ for (sq = 0; sq < 64; sq++)
+ {
+ if (color[sq] == neutral) c = 0; else c = color[sq]+1;
+ fprintf(fd,"%d\n",256*board[sq] + c);
+ }
+ for (i = 0; i <= GameCnt; i++)
+ {
+ if (GameList[i].color == neutral) c = 0;
+ else c = GameList[i].color + 1;
+ fprintf(fd,"%d %d %d %ld %d %d %d\n",
+ GameList[i].gmove,GameList[i].score,GameList[i].depth,
+ GameList[i].nodes,GameList[i].time,
+ GameList[i].piece,c);
+ }
+ fclose(fd);
+}
+
+
+ListGame()
+{
+FILE *fd;
+short i,f,t;
+ fd = fopen("chess.lst","w");
+ fprintf(fd,"\n");
+ fprintf(fd," score depth nodes time ");
+ fprintf(fd," score depth nodes time\n");
+ for (i = 0; i <= GameCnt; i++)
+ {
+ f = GameList[i].gmove>>8; t = (GameList[i].gmove & 0xFF);
+ algbr(f,t,false);
+ if ((i % 2) == 0) fprintf(fd,"\n"); else fprintf(fd," ");
+ fprintf(fd,"%5s %5d %2d %6ld %5d",mvstr1,
+ GameList[i].score,GameList[i].depth,
+ GameList[i].nodes,GameList[i].time);
+ }
+ fprintf(fd,"\n\n");
+ fclose(fd);
+}
+
+
+Undo()
+
+/*
+ Undo the most recent half-move.
+*/
+
+{
+short f,t;
+ f = GameList[GameCnt].gmove>>8;
+ t = GameList[GameCnt].gmove & 0xFF;
+ if (board[t] == king && distance(t,f) > 1)
+ castle(GameList[GameCnt].color,f,t,2);
+ else
+ {
+ board[f] = board[t]; color[f] = color[t];
+ board[t] = GameList[GameCnt].piece;
+ color[t] = GameList[GameCnt].color;
+ if (board[f] == king) --kingmoved[color[f]];
+ }
+ if (TCflag) ++TimeControl.moves[color[f]];
+ GameCnt--; mate = false; Sdepth = 0;
+ UpdateDisplay(0,0,1,0);
+ InitializeStats();
+}
+
+
+ShowMessage(s)
+char *s;
+{
+ gotoXY(50,24); printz("%s",s); ClrEoln();
+}
+
+ClearMessage()
+{
+ gotoXY(50,24); ClrEoln();
+}
+
+ShowSidetomove()
+{
+ gotoXY(50,14);
+ if (player == white) printz("%2d: WHITE",1+(GameCnt+1)/2);
+ else printz("%2d: BLACK",1+(GameCnt+1)/2);
+ ClrEoln();
+}
+
+PromptForMove()
+{
+ gotoXY(50,19); printz("Your move is? "); ClrEoln();
+}
+
+ShowCurrentMove(pnt,f,t)
+short pnt,f,t;
+{
+ algbr(f,t,false);
+ gotoXY(50,7); printz("(%2d) %4s",pnt,mvstr1);
+}
+
+ChangeAlphaWindow()
+{
+ ShowMessage("window: ");
+ scanz("%hd",&Awindow);
+}
+
+ChangeBetaWindow()
+{
+ ShowMessage("window: ");
+ scanz("%hd",&Bwindow);
+}
+
+GiveHint()
+{
+char s[40];
+ algbr((short)(hint>>8),(short)(hint & 0xFF),false);
+ strcpy(s,"try ");
+ strcat(s,mvstr1);
+ ShowMessage(s);
+}
+
+ChangeSearchDepth()
+{
+ ShowMessage("depth= ");
+ scanz("%hd",&MaxSearchDepth);
+}
+
+SetContempt()
+{
+ ShowMessage("contempt= ");
+ scanz("%hd",&contempt);
+}
+
+ChangeXwindow()
+{
+ ShowMessage("xwndw= ");
+ scanz("%hd",&xwndw);
+}
+
+
+SelectLevel()
+{
+ ClrScreen();
+ gotoXY(32,2); printz("CHESS");
+ gotoXY(20,4); printz(" 1. 60 moves in 5 minutes");
+ gotoXY(20,5); printz(" 2. 60 moves in 15 minutes");
+ gotoXY(20,6); printz(" 3. 60 moves in 30 minutes");
+ gotoXY(20,7); printz(" 4. 40 moves in 30 minutes");
+ gotoXY(20,8); printz(" 5. 40 moves in 60 minutes");
+ gotoXY(20,9); printz(" 6. 40 moves in 120 minutes");
+ gotoXY(20,10); printz(" 7. 40 moves in 240 minutes");
+ gotoXY(20,11); printz(" 8. 1 move in 15 minutes");
+ gotoXY(20,12); printz(" 9. 1 move in 60 minutes");
+ gotoXY(20,13); printz("10. 1 move in 600 minutes");
+
+ OperatorTime = 0; TCmoves = 60; TCminutes = 5;
+
+ gotoXY(20,17); printz("Enter Level: ");
+ refresh();
+ scanz("%ld",&Level);
+ switch (Level)
+ {
+ case 1 : TCmoves = 60; TCminutes = 5; break;
+ case 2 : TCmoves = 60; TCminutes = 15; break;
+ case 3 : TCmoves = 60; TCminutes = 30; break;
+ case 4 : TCmoves = 40; TCminutes = 30; break;
+ case 5 : TCmoves = 40; TCminutes = 60; break;
+ case 6 : TCmoves = 40; TCminutes = 120; break;
+ case 7 : TCmoves = 40; TCminutes = 240; break;
+ case 8 : TCmoves = 1; TCminutes = 15; break;
+ case 9 : TCmoves = 1; TCminutes = 60; break;
+ case 10 : TCmoves = 1; TCminutes = 600; break;
+ }
+
+ TCflag = (TCmoves > 1);
+ SetTimeControl();
+ ClrScreen();
+ UpdateDisplay(0,0,1,0);
+}
+
+
+ShowPostnValues()
+{
+short i,r,c;
+ ExaminePosition();
+ for (i = 0; i < 64; i++)
+ {
+ if (reverse) r = 7-row[i]; else r = row[i];
+ if (reverse) c = 7-column[i]; else c = column[i];
+ gotoXY(4+5*c,5+2*(7-r));
+ c1 = color[i]; c2 = otherside[c1];
+ PC1 = PawnCnt[c1]; PC2 = PawnCnt[c2];
+ atk1 = atak[c1]; atk2 = atak[c2];
+ if (color[i] == neutral) printz(" ");
+ else printz("%3d ",SqValue(i,opponent));
+ }
+ ScorePosition(opponent,&i);
+ gotoXY(50,24);
+ printz("Score= %d",i); ClrEoln();
+}
+
+
+DoDebug()
+{
+short k,p,i,r,c,tp,tc;
+char s[40];
+ ExaminePosition();
+ ShowMessage("Enter piece: ");
+ scanz("%s",s);
+ if (s[0] == 'w') k = white; else k = black;
+ if (s[1] == 'p') p = pawn;
+ else if (s[1] == 'n') p = knight;
+ else if (s[1] == 'b') p = bishop;
+ else if (s[1] == 'r') p = rook;
+ else if (s[1] == 'q') p = queen;
+ else if (s[1] == 'k') p = king;
+ else p = no_piece;
+ for (i = 0; i < 64; i++)
+ {
+ if (reverse) r = 7-row[i]; else r = row[i];
+ if (reverse) c = 7-column[i]; else c = column[i];
+ gotoXY(4+5*c,5+2*(7-r));
+ tp = board[i]; tc = color[i];
+ board[i] = p; color[i] = k;
+ c1 = k; c2 = otherside[c1];
+ PC1 = PawnCnt[c1]; PC2 = PawnCnt[c2];
+ atk1 = atak[c1]; atk2 = atak[c2];
+ printz("%3d ",SqValue(i,opponent));
+ board[i] = tp; color[i] = tc;
+ }
+ ScorePosition(opponent,&i);
+ gotoXY(50,24);
+ printz("Score= %d",i); ClrEoln();
+}
diff --git a/share/man/man4/man4.i386/Makefile b/share/man/man4/man4.i386/Makefile
new file mode 100644
index 000000000000..b675c4b994cb
--- /dev/null
+++ b/share/man/man4/man4.i386/Makefile
@@ -0,0 +1,7 @@
+# @(#)Makefile 0.1 (RWGrimes) 3/25/93
+
+MAN4= mem.0 spkr.0
+MLINKS= mem.4 kmem.4
+MANSUBDIR=/i386
+
+.include <bsd.prog.mk>
diff --git a/share/man/man4/man4.i386/mem.4 b/share/man/man4/man4.i386/mem.4
new file mode 100644
index 000000000000..1080cac5f687
--- /dev/null
+++ b/share/man/man4/man4.i386/mem.4
@@ -0,0 +1,82 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mem.4 5.3 (Berkeley) 5/2/91
+.\"
+.Dd May 2, 1991
+.Dt MEM 4 i386
+.Os
+.Sh NAME
+.Nm mem ,
+.Nm kmem
+.Nd memory files
+.Sh DESCRIPTION
+The special file
+.Nm /dev/mem
+is an interface to the physical memory of the computer.
+Byte offsets in this file are interpreted as physical memory addresses.
+Reading and writing this file is equivalent to reading and writing
+memory itself.
+Only offsets within the bounds of
+.Nm /dev/mem
+are allowed.
+.Pp
+Kernel virtual memory is accessed through the interface
+.Nm /dev/kmem
+in the same manner as
+.Nm /dev/mem .
+Only kernel virtual addresses that are currently mapped to memory are allowed.
+.Pp
+On
+.Tn ISA
+the
+.Tn I/O
+memory space begins at physical address 0x000a0000
+and runs to 0x00100000.
+The
+per-process data
+size
+for the current process
+is
+.Dv UPAGES
+long, and ends at virtual
+address 0xfe000000.
+.Sh FILES
+.Bl -tag -width Pa -compact
+.It Pa /dev/mem
+.It Pa /dev/kmem
+.El
+.Sh HISTORY
+The
+.Nm mem ,
+.Nm kmem
+files appeared in
+.At v6 .
diff --git a/share/man/man4/man4.i386/spkr.4 b/share/man/man4/man4.i386/spkr.4
new file mode 100644
index 000000000000..b211674893f0
--- /dev/null
+++ b/share/man/man4/man4.i386/spkr.4
@@ -0,0 +1,117 @@
+.TH SPKR 4
+.SH NAME
+spkr \- console speaker device driver
+.SH DESCRIPTION
+The speaker device driver allows applications to control the PC console
+speaker on an IBM-PC-compatible machine running UNIX.
+.PP
+Only one process may have this device open at any given time; open() and
+close() are used to lock and relinquish it. An attempt to open() when
+another process has the device locked will return -1 with an EBUSY error
+indication. Writes to the device are interpreted as 'play strings' in a
+simple ASCII melody notation. An ioctl() for tone generation at arbitrary
+frequencies is also supported.
+.PP
+Sound-generation does \fInot\fR monopolize the processor; in fact, the driver
+spends most of its time sleeping while the PC hardware is emitting
+tones. Other processes may emit beeps while the driver is running.
+.PP
+Applications may call ioctl() on a speaker file descriptor to control the
+speaker driver directly; definitions for the ioctl() interface are in
+sys/spkr.h. The tone_t structure used in these calls has two fields,
+specifying a frequency (in hz) and a duration (in 1/100ths of a second).
+A frequency of zero is interpreted as a rest.
+.PP
+At present there are two such ioctls. SPKRTONE accepts a pointer to a
+single tone structure as third argument and plays it. SPKRTUNE accepts a
+pointer to the first of an array of tone structures and plays them in
+continuous sequence; this array must be terminated by a final member with
+a zero duration.
+.PP
+The play-string language is modelled on the PLAY statement conventions of
+IBM BASIC 2.0. The MB, MF and X primitives of PLAY are not useful in a UNIX
+environment and are omitted. The `octave-tracking' feature is also new.
+.PP
+There are 84 accessible notes numbered 1-83 in 7 octaves, each running from
+C to B, numbered 0-6; the scale is equal-tempered A440 and octave 3 starts
+with middle C. By default, the play function emits half-second notes with the
+last 1/16th second being `rest time'.
+.PP
+Play strings are interpreted left to right as a series of play command groups;
+letter case is ignored. Play command groups are as follows:
+.PP
+CDEFGAB -- letters A through G cause the corresponding note to be played in the
+current octave. A note letter may optionally be followed by an \fIaccidental
+sign\fR, one of # + or -; the first two of these cause it to be sharped one
+half-tone, the last causes it to be flatted one half-tone. It may also be
+followed by a time value number and by sustain dots (see below). Time values
+are interpreted as for the L command below;.
+.PP
+O <n> -- if <n> is numeric, this sets the current octave. <n> may also be one
+of 'L' or 'N' to enable or disable octave-tracking (it is disabled by default).
+When octave-tracking is on, interpretation of a pair of letter notes will
+change octaves if necessary in order to make the smallest possible jump between
+notes. Thus "olbc" will be played as "olb>c", and "olcb" as "olc<b". Octave
+locking is disabled for one letter note following by >, < and O[0123456].
+.PP
+> -- bump the current octave up one.
+.PP
+< -- drop the current octave down one.
+.PP
+N <n> -- play note n, n being 1 to 84 or 0 for a rest of current time value.
+May be followedv by sustain dots.
+.PP
+L <n> -- sets the current time value for notes. The default is L4, quarter
+notes. The lowest possible value is 1; values up to 64 are accepted. L1 sets
+whole notes, L2 sets half notes, L4 sets quarter notes, etc..
+.PP
+P <n> -- pause (rest), with <n> interpreted as for L. May be followed by
+sustain dots. May also be written '~'.
+.PP
+T <n> -- Sets the number of quarter notes per minute; default is 120. Musical
+names for common tempi are:
+
+.TS
+a a a.
+ Tempo Beats Per Minute
+very slow Larghissimo
+ Largo 40-60
+ Larghetto 60-66
+ Grave
+ Lento
+ Adagio 66-76
+slow Adagietto
+ Andante 76-108
+medium Andantino
+ Moderato 108-120
+fast Allegretto
+ Allegro 120-168
+ Vivace
+ Veloce
+ Presto 168-208
+very fast Prestissimo
+.TE
+.PP
+M[LNS] -- set articulation. MN (N for normal) is the default; the last 1/8th of
+the note's value is rest time. You can set ML for legato (no rest space) or
+MS (staccato) 1/4 rest space.
+.PP
+Notes (that is, CDEFGAB or N command character groups) may be followed by
+sustain dots. Each dot causes the note's value to be lengthened by one-half
+for each one. Thus, a note dotted once is held for 3/2 of its undotted value;
+dotted twice, it is held 9/4, and three times would give 27/8.
+.PP
+Whitespace in play strings is simply skipped and may be used to separate
+melody sections.
+.SH BUGS
+Due to roundoff in the pitch tables and slop in the tone-generation and timer
+hardware (neither of which was designed for precision), neither pitch accuracy
+nor timings will be mathematically exact. There is no volume control.
+.PP
+In play strings which are very long (longer than your system's physical I/O
+blocks) note suffixes or numbers may occasionally be parsed incorrectly due
+to crossing a block boundary.
+.SH FILES
+/dev/speaker -- speaker device file
+.SH AUTHOR
+Eric S. Raymond (esr@snark.thyrsus.com) Feb 1990
diff --git a/share/man/man4/mem.4 b/share/man/man4/mem.4
new file mode 100644
index 000000000000..1080cac5f687
--- /dev/null
+++ b/share/man/man4/mem.4
@@ -0,0 +1,82 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mem.4 5.3 (Berkeley) 5/2/91
+.\"
+.Dd May 2, 1991
+.Dt MEM 4 i386
+.Os
+.Sh NAME
+.Nm mem ,
+.Nm kmem
+.Nd memory files
+.Sh DESCRIPTION
+The special file
+.Nm /dev/mem
+is an interface to the physical memory of the computer.
+Byte offsets in this file are interpreted as physical memory addresses.
+Reading and writing this file is equivalent to reading and writing
+memory itself.
+Only offsets within the bounds of
+.Nm /dev/mem
+are allowed.
+.Pp
+Kernel virtual memory is accessed through the interface
+.Nm /dev/kmem
+in the same manner as
+.Nm /dev/mem .
+Only kernel virtual addresses that are currently mapped to memory are allowed.
+.Pp
+On
+.Tn ISA
+the
+.Tn I/O
+memory space begins at physical address 0x000a0000
+and runs to 0x00100000.
+The
+per-process data
+size
+for the current process
+is
+.Dv UPAGES
+long, and ends at virtual
+address 0xfe000000.
+.Sh FILES
+.Bl -tag -width Pa -compact
+.It Pa /dev/mem
+.It Pa /dev/kmem
+.El
+.Sh HISTORY
+The
+.Nm mem ,
+.Nm kmem
+files appeared in
+.At v6 .
diff --git a/share/man/man4/spkr.4 b/share/man/man4/spkr.4
new file mode 100644
index 000000000000..b211674893f0
--- /dev/null
+++ b/share/man/man4/spkr.4
@@ -0,0 +1,117 @@
+.TH SPKR 4
+.SH NAME
+spkr \- console speaker device driver
+.SH DESCRIPTION
+The speaker device driver allows applications to control the PC console
+speaker on an IBM-PC-compatible machine running UNIX.
+.PP
+Only one process may have this device open at any given time; open() and
+close() are used to lock and relinquish it. An attempt to open() when
+another process has the device locked will return -1 with an EBUSY error
+indication. Writes to the device are interpreted as 'play strings' in a
+simple ASCII melody notation. An ioctl() for tone generation at arbitrary
+frequencies is also supported.
+.PP
+Sound-generation does \fInot\fR monopolize the processor; in fact, the driver
+spends most of its time sleeping while the PC hardware is emitting
+tones. Other processes may emit beeps while the driver is running.
+.PP
+Applications may call ioctl() on a speaker file descriptor to control the
+speaker driver directly; definitions for the ioctl() interface are in
+sys/spkr.h. The tone_t structure used in these calls has two fields,
+specifying a frequency (in hz) and a duration (in 1/100ths of a second).
+A frequency of zero is interpreted as a rest.
+.PP
+At present there are two such ioctls. SPKRTONE accepts a pointer to a
+single tone structure as third argument and plays it. SPKRTUNE accepts a
+pointer to the first of an array of tone structures and plays them in
+continuous sequence; this array must be terminated by a final member with
+a zero duration.
+.PP
+The play-string language is modelled on the PLAY statement conventions of
+IBM BASIC 2.0. The MB, MF and X primitives of PLAY are not useful in a UNIX
+environment and are omitted. The `octave-tracking' feature is also new.
+.PP
+There are 84 accessible notes numbered 1-83 in 7 octaves, each running from
+C to B, numbered 0-6; the scale is equal-tempered A440 and octave 3 starts
+with middle C. By default, the play function emits half-second notes with the
+last 1/16th second being `rest time'.
+.PP
+Play strings are interpreted left to right as a series of play command groups;
+letter case is ignored. Play command groups are as follows:
+.PP
+CDEFGAB -- letters A through G cause the corresponding note to be played in the
+current octave. A note letter may optionally be followed by an \fIaccidental
+sign\fR, one of # + or -; the first two of these cause it to be sharped one
+half-tone, the last causes it to be flatted one half-tone. It may also be
+followed by a time value number and by sustain dots (see below). Time values
+are interpreted as for the L command below;.
+.PP
+O <n> -- if <n> is numeric, this sets the current octave. <n> may also be one
+of 'L' or 'N' to enable or disable octave-tracking (it is disabled by default).
+When octave-tracking is on, interpretation of a pair of letter notes will
+change octaves if necessary in order to make the smallest possible jump between
+notes. Thus "olbc" will be played as "olb>c", and "olcb" as "olc<b". Octave
+locking is disabled for one letter note following by >, < and O[0123456].
+.PP
+> -- bump the current octave up one.
+.PP
+< -- drop the current octave down one.
+.PP
+N <n> -- play note n, n being 1 to 84 or 0 for a rest of current time value.
+May be followedv by sustain dots.
+.PP
+L <n> -- sets the current time value for notes. The default is L4, quarter
+notes. The lowest possible value is 1; values up to 64 are accepted. L1 sets
+whole notes, L2 sets half notes, L4 sets quarter notes, etc..
+.PP
+P <n> -- pause (rest), with <n> interpreted as for L. May be followed by
+sustain dots. May also be written '~'.
+.PP
+T <n> -- Sets the number of quarter notes per minute; default is 120. Musical
+names for common tempi are:
+
+.TS
+a a a.
+ Tempo Beats Per Minute
+very slow Larghissimo
+ Largo 40-60
+ Larghetto 60-66
+ Grave
+ Lento
+ Adagio 66-76
+slow Adagietto
+ Andante 76-108
+medium Andantino
+ Moderato 108-120
+fast Allegretto
+ Allegro 120-168
+ Vivace
+ Veloce
+ Presto 168-208
+very fast Prestissimo
+.TE
+.PP
+M[LNS] -- set articulation. MN (N for normal) is the default; the last 1/8th of
+the note's value is rest time. You can set ML for legato (no rest space) or
+MS (staccato) 1/4 rest space.
+.PP
+Notes (that is, CDEFGAB or N command character groups) may be followed by
+sustain dots. Each dot causes the note's value to be lengthened by one-half
+for each one. Thus, a note dotted once is held for 3/2 of its undotted value;
+dotted twice, it is held 9/4, and three times would give 27/8.
+.PP
+Whitespace in play strings is simply skipped and may be used to separate
+melody sections.
+.SH BUGS
+Due to roundoff in the pitch tables and slop in the tone-generation and timer
+hardware (neither of which was designed for precision), neither pitch accuracy
+nor timings will be mathematically exact. There is no volume control.
+.PP
+In play strings which are very long (longer than your system's physical I/O
+blocks) note suffixes or numbers may occasionally be parsed incorrectly due
+to crossing a block boundary.
+.SH FILES
+/dev/speaker -- speaker device file
+.SH AUTHOR
+Eric S. Raymond (esr@snark.thyrsus.com) Feb 1990
diff --git a/usr.bin/symorder/Makefile b/usr.bin/symorder/Makefile
new file mode 100644
index 000000000000..5fe1caf67046
--- /dev/null
+++ b/usr.bin/symorder/Makefile
@@ -0,0 +1,5 @@
+# @(#)Makefile 5.3 (Berkeley) 5/11/90
+
+PROG= symorder
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/symorder/symorder.1 b/usr.bin/symorder/symorder.1
new file mode 100644
index 000000000000..f113bcafd40d
--- /dev/null
+++ b/usr.bin/symorder/symorder.1
@@ -0,0 +1,81 @@
+.\" Copyright (c) 1980, 1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)symorder.1 6.5 (Berkeley) 4/22/91
+.\"
+.Dd April 22, 1991
+.Dt SYMORDER 1
+.Os BSD 3
+.Sh NAME
+.Nm symorder
+.Nd rearrange name list
+.Sh SYNOPSIS
+.Nm symorder
+.Fl t Ar symlist file
+.Sh DESCRIPTION
+The file
+.Ar symlist
+contains a list of symbols to be found in
+.Ar file,
+one symbol per line.
+.Pp
+The symbol table of
+.Ar file
+is updated in place;
+symbols read from
+.Ar symlist
+are relocated to the beginning of the table and in the order given.
+.Bl -tag -width flag
+.It Fl t
+Restrict the symbol table to the symbols listed in
+.Ar symlist .
+.El
+.Pp
+This program was specifically designed to cut down on the
+overhead of getting symbols from
+.Pa /vmunix.
+.Sh DIAGNOSTICS
+The
+.Nm symorder
+utility exits 0 on success, 1 if a symbol
+listed in the
+.Ar symlist
+file was not found in the symbol
+table, and >1 if an error occurs.
+.Sh SEE ALSO
+.Xr nm 3 ,
+.Xr nlist 3 ,
+.Xr strip 3
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
diff --git a/usr.bin/symorder/symorder.c b/usr.bin/symorder/symorder.c
new file mode 100644
index 000000000000..4c41a14b7055
--- /dev/null
+++ b/usr.bin/symorder/symorder.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 1980 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1980 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)symorder.c 5.8 (Berkeley) 4/1/91";
+#endif /* not lint */
+
+/*
+ * symorder - reorder symbol table
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <a.out.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define SPACE 500
+
+#define OKEXIT 0
+#define NOTFOUNDEXIT 1
+#define ERREXIT 2
+
+struct nlist order[SPACE];
+
+struct exec exec;
+struct stat stb;
+struct nlist *newtab, *symtab;
+off_t sa;
+int nsym, strtabsize, symfound, small;
+char *kfile, *newstrings, *strings, asym[BUFSIZ];
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ extern char *optarg;
+ extern int optind;
+ register struct nlist *p, *symp;
+ register FILE *f;
+ register int i;
+ register char *start, *t;
+ int ch, n, o;
+
+ while ((ch = getopt(argc, argv, "t")) != EOF)
+ switch(ch) {
+ case 't':
+ small = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 2)
+ usage();
+
+ if ((f = fopen(argv[0], "r")) == NULL)
+ error(argv[0]);
+
+ for (p = order; fgets(asym, sizeof(asym), f) != NULL;) {
+ for (t = asym; isspace(*t); ++t);
+ if (!*(start = t))
+ continue;
+ while (*++t);
+ if (*--t == '\n')
+ *t = '\0';
+ p->n_un.n_name = strdup(start);
+ ++p;
+ ++nsym;
+ }
+ (void)fclose(f);
+
+ kfile = argv[1];
+ if ((f = fopen(kfile, "r")) == NULL)
+ error(kfile);
+ if ((o = open(kfile, O_WRONLY)) < 0)
+ error(kfile);
+
+ /* read exec header */
+ if ((fread(&exec, sizeof(exec), 1, f)) != 1)
+ badfmt("no exec header");
+ if (N_BADMAG(exec))
+ badfmt("bad magic number");
+ if (exec.a_syms == 0)
+ badfmt("stripped");
+ (void)fstat(fileno(f), &stb);
+ if (stb.st_size < N_STROFF(exec) + sizeof(off_t))
+ badfmt("no string table");
+
+ /* seek to and read the symbol table */
+ sa = N_SYMOFF(exec);
+ (void)fseek(f, sa, SEEK_SET);
+ n = exec.a_syms;
+ if (!(symtab = (struct nlist *)malloc(n)))
+ error(NULL);
+ if (fread((void *)symtab, 1, n, f) != n)
+ badfmt("corrupted symbol table");
+
+ /* read string table size and string table */
+ if (fread((void *)&strtabsize, sizeof(int), 1, f) != 1 ||
+ strtabsize <= 0)
+ badfmt("corrupted string table");
+ strings = malloc(strtabsize);
+ if (strings == NULL)
+ error(NULL);
+ /*
+ * Subtract four from strtabsize since strtabsize includes itself,
+ * and we've already read it.
+ */
+ if (fread(strings, 1, strtabsize - sizeof(int), f) !=
+ strtabsize - sizeof(int))
+ badfmt("corrupted string table");
+
+ newtab = (struct nlist *)malloc(n);
+ if (newtab == (struct nlist *)NULL)
+ error(NULL);
+
+ i = n / sizeof(struct nlist);
+ reorder(symtab, newtab, i);
+ free((void *)symtab);
+ symtab = newtab;
+
+ newstrings = malloc(strtabsize);
+ if (newstrings == NULL)
+ error(NULL);
+ t = newstrings;
+ for (symp = symtab; --i >= 0; symp++) {
+ if (symp->n_un.n_strx == 0)
+ continue;
+ if (small && inlist(symp) < 0) continue;
+ symp->n_un.n_strx -= sizeof(int);
+ (void)strcpy(t, &strings[symp->n_un.n_strx]);
+ symp->n_un.n_strx = (t - newstrings) + sizeof(int);
+ t += strlen(t) + 1;
+ }
+
+ /* update shrunk sizes */
+ if(small) {
+ strtabsize = t - newstrings + sizeof(int);
+ n = symfound * sizeof(struct nlist);
+ /* fix exec sym size */
+ (void)lseek(o, 0, SEEK_SET);
+ exec.a_syms = n;
+ if (write(o, (void *)&exec, sizeof(exec)) != sizeof(exec))
+ error(kfile);
+ }
+
+ (void)lseek(o, sa, SEEK_SET);
+ if (write(o, (void *)symtab, n) != n)
+ error(kfile);
+ if (write(o, (void *)&strtabsize, sizeof(int)) != sizeof(int))
+ error(kfile);
+ if (write(o, newstrings, strtabsize - sizeof(int)) !=
+ strtabsize - sizeof(int))
+ error(kfile);
+
+ if (small) ftruncate(o, lseek(o, 0, SEEK_CUR));
+
+ if ((i = nsym - symfound) > 0) {
+ (void)printf("symorder: %d symbol%s not found:\n",
+ i, i == 1 ? "" : "s");
+ for (i = 0; i < nsym; i++)
+ if (order[i].n_value == 0)
+ printf("%s\n", order[i].n_un.n_name);
+ exit(NOTFOUNDEXIT);
+ }
+ exit(OKEXIT);
+}
+
+reorder(st1, st2, entries)
+ register struct nlist *st1, *st2;
+ int entries;
+{
+ register struct nlist *p;
+ register int i, n;
+
+ for (p = st1, n = entries; --n >= 0; ++p)
+ if (inlist(p) != -1)
+ ++symfound;
+ for (p = st2 + symfound, n = entries; --n >= 0; ++st1) {
+ i = inlist(st1);
+ if (i == -1)
+ *p++ = *st1;
+ else
+ st2[i] = *st1;
+ }
+}
+
+inlist(p)
+ register struct nlist *p;
+{
+ register char *nam;
+ register struct nlist *op;
+
+ if (p->n_type & N_STAB)
+ return (-1);
+ if (p->n_un.n_strx == 0)
+ return (-1);
+
+ if (p->n_un.n_strx >= strtabsize)
+ badfmt("corrupted symbol table");
+
+ nam = &strings[p->n_un.n_strx - sizeof(int)];
+ for (op = &order[nsym]; --op >= order; ) {
+ if (strcmp(op->n_un.n_name, nam) != 0)
+ continue;
+ op->n_value = 1;
+ return (op - order);
+ }
+ return (-1);
+}
+
+badfmt(why)
+ char *why;
+{
+ (void)fprintf(stderr,
+ "symorder: %s: %s: %s\n", kfile, why, strerror(EFTYPE));
+ exit(ERREXIT);
+}
+
+error(n)
+ char *n;
+{
+ int sverr;
+
+ sverr = errno;
+ (void)fprintf(stderr, "symorder: ");
+ if (n)
+ (void)fprintf(stderr, "%s: ", n);
+ (void)fprintf(stderr, "%s\n", strerror(sverr));
+ exit(ERREXIT);
+}
+
+usage()
+{
+ (void)fprintf(stderr, "usage: symorder [-t] symlist file\n");
+ exit(ERREXIT);
+}
diff --git a/usr.sbin/dbsym/Makefile b/usr.sbin/dbsym/Makefile
new file mode 100644
index 000000000000..95ab527a9dd2
--- /dev/null
+++ b/usr.sbin/dbsym/Makefile
@@ -0,0 +1,4 @@
+PROG= dbsym
+NOMAN= noman
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/dbsym/dbsym.c b/usr.sbin/dbsym/dbsym.c
new file mode 100644
index 000000000000..46514b4c1e32
--- /dev/null
+++ b/usr.sbin/dbsym/dbsym.c
@@ -0,0 +1,192 @@
+/* Written by Pace Willisson (pace@blitz.com)
+ * and placed in the public domain.
+ */
+#include <stdio.h>
+#include <a.out.h>
+
+char *malloc ();
+
+#define FILE_OFFSET(vadr) (((vadr) & ~0xff000000)-N_DATADDR(hdr)+N_DATOFF(hdr))
+
+struct nlist *old_syms;
+int num_old_syms;
+char *old_strtab;
+int old_strtab_size;
+
+struct nlist *new_syms;
+int num_new_syms;
+int new_syms_bytes;
+char *new_strtab;
+int new_strtab_size;
+
+int db_symtabsize_adr;
+int db_symtab_adr;
+
+int avail;
+
+
+usage ()
+{
+ fprintf (stderr, "usage: dbsym file\n");
+ exit (1);
+}
+
+struct exec hdr;
+
+main (argc, argv)
+char **argv;
+{
+ FILE *f;
+ char *name;
+ extern int optind;
+ int c, i;
+ int need;
+ char *buf, *p;
+ struct nlist *nsp, *sp;
+ int len;
+
+
+ while ((c = getopt (argc, argv, "")) != EOF) {
+ switch (c) {
+ default:
+ usage ();
+ }
+ }
+
+ if (optind >= argc)
+ usage ();
+
+ name = argv[optind++];
+
+ if (optind != argc)
+ usage ();
+
+ if ((f = fopen (name, "r+")) == NULL) {
+ fprintf (stderr, "can't open %s\n", name);
+ exit (1);
+ }
+
+ if (fread ((char *)&hdr, sizeof hdr, 1, f) != 1) {
+ fprintf (stderr, "can't read header\n");
+ exit (1);
+ }
+
+ if (N_BADMAG (hdr)) {
+ fprintf (stderr, "bad magic number\n");
+ exit (1);
+ }
+
+ if (hdr.a_syms == 0) {
+ fprintf (stderr, "no symbols\n");
+ exit (1);
+ }
+
+ fseek (f, N_STROFF (hdr), 0);
+ if (fread ((char *)&old_strtab_size, sizeof (int), 1, f) != 1) {
+ fprintf (stderr, "can't read old strtab size\n");
+ exit (1);
+ }
+
+ if ((old_syms = (struct nlist *)malloc (hdr.a_syms)) == NULL
+ || ((old_strtab = malloc (old_strtab_size)) == NULL)
+ || ((new_syms = (struct nlist *)malloc (hdr.a_syms)) == NULL)
+ || ((new_strtab = malloc (old_strtab_size)) == NULL)) {
+ fprintf (stderr, "out of memory\n");
+ exit (1);
+ }
+
+ fseek (f, N_SYMOFF (hdr), 0);
+ if (fread ((char *)old_syms, hdr.a_syms, 1, f) != 1) {
+ fprintf (stderr, "can't read symbols\n");
+ exit (1);
+ }
+
+ fseek (f, N_STROFF (hdr), 0);
+ if (fread ((char *)old_strtab, old_strtab_size, 1, f) != 1) {
+ fprintf (stderr, "can't read string table\n");
+ exit (1);
+ }
+
+ num_old_syms = hdr.a_syms / sizeof (struct nlist);
+
+ new_strtab_size = 4;
+
+ nsp = new_syms;
+ for (i = 0, sp = old_syms; i < num_old_syms; i++, sp++) {
+ if (sp->n_type & N_STAB)
+ continue;
+ if (sp->n_un.n_strx == 0)
+ continue;
+
+ if (sp->n_value < 0xfe000000)
+ continue;
+
+ if (sp->n_value >= 0xff000000)
+ continue;
+
+ name = old_strtab + sp->n_un.n_strx;
+
+ len = strlen (name);
+
+ if (len == 0)
+ continue;
+
+ if (len >= 2 && name[len - 2] == '.' && name[len - 1] == 'o')
+ continue;
+
+ if (strcmp (name, "gcc_compiled.") == 0)
+ continue;
+
+ *nsp = *sp;
+
+ nsp->n_un.n_strx = new_strtab_size;
+ strcpy (new_strtab + new_strtab_size, name);
+ new_strtab_size += len + 1;
+ nsp++;
+
+ if (strcmp (name, "_db_symtab") == 0)
+ db_symtab_adr = sp->n_value;
+ if (strcmp (name, "_db_symtabsize") == 0)
+ db_symtabsize_adr = sp->n_value;
+ }
+
+ if (db_symtab_adr == 0 || db_symtabsize_adr == 0) {
+ fprintf (stderr, "couldn't find db_symtab symbols\n");
+ exit (1);
+ }
+
+ *(int *)new_strtab = new_strtab_size;
+ num_new_syms = nsp - new_syms;
+ new_syms_bytes = num_new_syms * sizeof (struct nlist);
+
+ need = sizeof (int)
+ + num_new_syms * sizeof (struct nlist)
+ + new_strtab_size;
+
+ fseek (f, FILE_OFFSET (db_symtabsize_adr), 0);
+
+ if (fread ((char *)&avail, sizeof (int), 1, f) != 1) {
+ fprintf (stderr, "can't read symtabsize\n");
+ exit (1);
+ }
+
+ printf ("dbsym: need %d; avail %d\n", need, avail);
+
+ if (need > avail) {
+ fprintf (stderr, "not enough room in db_symtab array\n");
+ exit (1);
+ }
+
+ fseek (f, FILE_OFFSET (db_symtab_adr), 0);
+ fwrite ((char *)&new_syms_bytes, sizeof (int), 1, f);
+ fwrite ((char *)new_syms, new_syms_bytes, 1, f);
+ fwrite (new_strtab, new_strtab_size, 1, f);
+ fflush (f);
+
+ if (feof (f) || ferror (f)) {
+ fprintf (stderr, "write error\n");
+ exit (1);
+ }
+ exit (0);
+}
+
diff --git a/usr.sbin/tcpdump/Makefile b/usr.sbin/tcpdump/Makefile
new file mode 100644
index 000000000000..0a1f2533744b
--- /dev/null
+++ b/usr.sbin/tcpdump/Makefile
@@ -0,0 +1,5 @@
+# @(#)Makefile 0.1 (RGrimes) 4/4/93
+
+SUBDIR= tcpdump tcpslice
+
+.include <bsd.subdir.mk>
diff --git a/usr.sbin/tcpdump/Makefile.inc b/usr.sbin/tcpdump/Makefile.inc
new file mode 100644
index 000000000000..948999506171
--- /dev/null
+++ b/usr.sbin/tcpdump/Makefile.inc
@@ -0,0 +1,3 @@
+# @(#)Makefile.inc 5.1 (Berkeley) 5/11/90
+
+BINDIR?= /usr/local/bin
diff --git a/usr.sbin/tcpdump/tcpdump/Makefile b/usr.sbin/tcpdump/tcpdump/Makefile
new file mode 100644
index 000000000000..fee95540b94b
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/Makefile
@@ -0,0 +1,24 @@
+# @(#)Makefile 0.1 (RWGrimes) 3/24/93
+
+PROG= tcpdump
+CFLAGS+=-DCSLIP -I.
+MAN1= tcpdump.0
+SRCS= version.c addrtoname.c bpf_dump.c bpf_filter.c bpf_image.c etherent.c \
+ gencode.c inet.c md.c nametoaddr.c optimize.c os.c pcap.c \
+ print-arp.c print-atalk.c print-bootp.c print-domain.c \
+ print-egp.c print-ether.c print-fddi.c print-icmp.c print-ip.c \
+ print-nfs.c print-ntp.c print-null.c print-ospf.c print-ppp.c \
+ print-rip.c print-sl.c print-snmp.c print-sunrpc.c print-tcp.c \
+ print-tftp.c print-udp.c savefile.c tcpdump.c tcpgram.c \
+ tcplex.c util.c
+.PATH: /sys/net
+CLEANFILES+= tcpgram.c tcplex.c y.tab.h y.tab.c version.c version.h
+
+version.c version.h: VERSION
+ rm -f version.c ; \
+ sed 's/.*/char version[] = "&";/' $(.CURDIR)/VERSION > version.c
+ set `sed 's/\([0-9]*\)\.\([0-9]*\).*/\1 \2/' $(.CURDIR)/VERSION` ; \
+ { echo '#define VERSION_MAJOR' $$1 ; \
+ echo '#define VERSION_MINOR' $$2 ; } > version.h
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/tcpdump/tcpdump/VERSION b/usr.sbin/tcpdump/tcpdump/VERSION
new file mode 100644
index 000000000000..c043eea7767e
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/VERSION
@@ -0,0 +1 @@
+2.2.1
diff --git a/usr.sbin/tcpdump/tcpdump/addrtoname.c b/usr.sbin/tcpdump/tcpdump/addrtoname.c
new file mode 100644
index 000000000000..5c7086518a56
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/addrtoname.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 1988, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Internet, ethernet, port, and protocol string to address
+ * and address to string conversion routines
+ */
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: addrtoname.c,v 1.14 92/05/25 14:29:07 mccanne Exp $ (LBL)";
+#endif
+
+#include <stdio.h>
+#include <strings.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <arpa/inet.h>
+#include <signal.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "nametoaddr.h"
+#include "etherent.h"
+
+/*
+ * hash tables for whatever-to-name translations
+ */
+
+#define HASHNAMESIZE 4096
+
+struct hnamemem {
+ u_long addr;
+ char *name;
+ struct hnamemem *nxt;
+};
+
+struct hnamemem hnametable[HASHNAMESIZE];
+struct hnamemem tporttable[HASHNAMESIZE];
+struct hnamemem uporttable[HASHNAMESIZE];
+struct hnamemem eprototable[HASHNAMESIZE];
+
+struct enamemem {
+ u_short e_addr0;
+ u_short e_addr1;
+ u_short e_addr2;
+ char *e_name;
+ struct enamemem *e_nxt;
+};
+
+struct enamemem enametable[HASHNAMESIZE];
+
+
+/*
+ * A faster replacement for inet_ntoa().
+ */
+char *
+intoa(addr)
+ u_long addr;
+{
+ register char *cp;
+ register u_int byte;
+ register int n;
+ static char buf[sizeof(".xxx.xxx.xxx.xxx")];
+
+ NTOHL(addr);
+ cp = &buf[sizeof buf];
+ *--cp = '\0';
+
+ n = 4;
+ do {
+ byte = addr & 0xff;
+ *--cp = byte % 10 + '0';
+ byte /= 10;
+ if (byte > 0) {
+ *--cp = byte % 10 + '0';
+ byte /= 10;
+ if (byte > 0)
+ *--cp = byte + '0';
+ }
+ *--cp = '.';
+ addr >>= 8;
+ } while (--n > 0);
+
+ return cp + 1;
+}
+
+static u_long f_netmask;
+static u_long f_localnet;
+static u_long netmask;
+
+/*
+ * "getname" is written in this atrocious way to make sure we don't
+ * wait forever while trying to get hostnames from yp.
+ */
+#include <setjmp.h>
+
+jmp_buf getname_env;
+
+static void
+nohostname()
+{
+ longjmp(getname_env, 1);
+}
+
+/*
+ * Return a name for the IP address pointed to by ap. This address
+ * is assumed to be in network byte order.
+ */
+char *
+getname(ap)
+ u_char *ap;
+{
+ register struct hnamemem *p;
+ register struct hostent *hp;
+ register char *cp;
+ u_long addr;
+
+#ifndef TCPDUMP_ALIGN
+ addr = *(u_long *)ap;
+#else
+ /*
+ * Deal with alignment.
+ */
+ switch ((int)ap & 3) {
+
+ case 0:
+ addr = *(u_long *)ap;
+ break;
+
+ case 2:
+#if BYTE_ORDER == LITTLE_ENDIAN
+ addr = ((u_long)*(u_short *)(ap + 2) << 16) |
+ (u_long)*(u_short *)ap;
+#else
+ addr = ((u_long)*(u_short *)ap << 16) |
+ (u_long)*(u_short *)(ap + 2);
+#endif
+ break;
+
+ default:
+#if BYTE_ORDER == LITTLE_ENDIAN
+ addr = ((u_long)ap[0] << 24) |
+ ((u_long)ap[1] << 16) |
+ ((u_long)ap[2] << 8) |
+ (u_long)ap[3];
+#else
+ addr = ((u_long)ap[3] << 24) |
+ ((u_long)ap[2] << 16) |
+ ((u_long)ap[1] << 8) |
+ (u_long)ap[0];
+#endif
+ break;
+ }
+#endif
+ p = &hnametable[addr & (HASHNAMESIZE-1)];
+ for (; p->nxt; p = p->nxt) {
+ if (p->addr == addr)
+ return (p->name);
+ }
+ p->addr = addr;
+ p->nxt = (struct hnamemem *)calloc(1, sizeof (*p));
+
+ /*
+ * Only print names when:
+ * (1) -n was not given.
+ * (2) Address is foreign and -f was given. If -f was not
+ * present, f_netmask and f_local are 0 and the second
+ * test will succeed.
+ * (3) The host portion is not 0 (i.e., a network address).
+ * (4) The host portion is not broadcast.
+ */
+ if (!nflag && (addr & f_netmask) == f_localnet
+ && (addr &~ netmask) != 0 && (addr | netmask) != 0xffffffff) {
+ if (!setjmp(getname_env)) {
+ (void)signal(SIGALRM, nohostname);
+ (void)alarm(20);
+ hp = gethostbyaddr((char *)&addr, 4, AF_INET);
+ (void)alarm(0);
+ if (hp) {
+ char *index();
+ char *dotp;
+ u_int len = strlen(hp->h_name) + 1;
+ p->name = (char *)malloc(len);
+ (void)strcpy(p->name, hp->h_name);
+ if (Nflag) {
+ /* Remove domain qualifications */
+ dotp = index(p->name, '.');
+ if (dotp)
+ *dotp = 0;
+ }
+ return (p->name);
+ }
+ }
+ }
+ cp = intoa(addr);
+ p->name = (char *)malloc((unsigned)(strlen(cp) + 1));
+ (void)strcpy(p->name, cp);
+ return (p->name);
+}
+
+static char hex[] = "0123456789abcdef";
+
+
+/* Find the hash node that corresponds the ether address 'ep'. */
+
+static inline struct enamemem *
+lookup_emem(ep)
+ u_char *ep;
+{
+ register u_int i, j, k;
+ struct enamemem *tp;
+
+ k = (ep[0] << 8) | ep[1];
+ j = (ep[2] << 8) | ep[3];
+ i = (ep[4] << 8) | ep[5];
+
+ tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)];
+ while (tp->e_nxt)
+ if (tp->e_addr0 == i &&
+ tp->e_addr1 == j &&
+ tp->e_addr2 == k)
+ return tp;
+ else
+ tp = tp->e_nxt;
+ tp->e_addr0 = i;
+ tp->e_addr1 = j;
+ tp->e_addr2 = k;
+ tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
+
+ return tp;
+}
+
+char *
+etheraddr_string(ep)
+ register u_char *ep;
+{
+ register u_int i, j;
+ register char *cp;
+ register struct enamemem *tp;
+
+ tp = lookup_emem(ep);
+ if (tp->e_name)
+ return tp->e_name;
+
+#ifdef ETHER_SERVICE
+ if (!nflag) {
+ cp = ETHER_ntohost(ep);
+ if (cp) {
+ tp->e_name = cp;
+ return cp;
+ }
+ }
+#endif
+ tp->e_name = cp = (char *)malloc(sizeof("00:00:00:00:00:00"));
+
+ if (j = *ep >> 4)
+ *cp++ = hex[j];
+ *cp++ = hex[*ep++ & 0xf];
+ for (i = 5; (int)--i >= 0;) {
+ *cp++ = ':';
+ if (j = *ep >> 4)
+ *cp++ = hex[j];
+ *cp++ = hex[*ep++ & 0xf];
+ }
+ *cp = '\0';
+ return (tp->e_name);
+}
+
+char *
+etherproto_string(port)
+ u_short port;
+{
+ register char *cp;
+ register struct hnamemem *tp;
+ register u_long i = port;
+
+ for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
+ if (tp->addr == i)
+ return (tp->name);
+
+ tp->name = cp = (char *)malloc(sizeof("0000"));
+ tp->addr = i;
+ tp->nxt = (struct hnamemem *)calloc(1, sizeof (*tp));
+
+ NTOHS(port);
+ *cp++ = hex[port >> 12 & 0xf];
+ *cp++ = hex[port >> 8 & 0xf];
+ *cp++ = hex[port >> 4 & 0xf];
+ *cp++ = hex[port & 0xf];
+ *cp++ = '\0';
+ return (tp->name);
+}
+
+char *
+tcpport_string(port)
+ u_short port;
+{
+ register struct hnamemem *tp;
+ register int i = port;
+
+ for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
+ if (tp->addr == i)
+ return (tp->name);
+
+ tp->name = (char *)malloc(sizeof("00000"));
+ tp->addr = i;
+ tp->nxt = (struct hnamemem *)calloc(1, sizeof (*tp));
+
+ (void)sprintf(tp->name, "%d", i);
+ return (tp->name);
+}
+
+char *
+udpport_string(port)
+ register u_short port;
+{
+ register struct hnamemem *tp;
+ register int i = port;
+
+ for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
+ if (tp->addr == i)
+ return (tp->name);
+
+ tp->name = (char *)malloc(sizeof("00000"));
+ tp->addr = i;
+ tp->nxt = (struct hnamemem *)calloc(1, sizeof(*tp));
+
+ (void)sprintf(tp->name, "%d", i);
+
+ return (tp->name);
+}
+
+static void
+init_servarray()
+{
+ struct servent *sv;
+ register struct hnamemem *table;
+ register int i;
+
+ while (sv = getservent()) {
+ NTOHS(sv->s_port);
+ i = sv->s_port & (HASHNAMESIZE-1);
+ if (strcmp(sv->s_proto, "tcp") == 0)
+ table = &tporttable[i];
+ else if (strcmp(sv->s_proto, "udp") == 0)
+ table = &uporttable[i];
+ else
+ continue;
+
+ while (table->name)
+ table = table->nxt;
+ if (nflag) {
+ char buf[32];
+
+ (void)sprintf(buf, "%d", sv->s_port);
+ table->name = (char *)malloc((unsigned)strlen(buf)+1);
+ (void)strcpy(table->name, buf);
+ } else {
+ table->name =
+ (char *)malloc((unsigned)strlen(sv->s_name)+1);
+ (void)strcpy(table->name, sv->s_name);
+ }
+ table->addr = sv->s_port;
+ table->nxt = (struct hnamemem *)calloc(1, sizeof(*table));
+ }
+ endservent();
+}
+
+#include "etherproto.h"
+
+/* Static data base of ether protocol types. */
+struct eproto eproto_db[] = {
+ { "pup", ETHERTYPE_PUP },
+ { "xns", ETHERTYPE_NS },
+ { "ip", ETHERTYPE_IP },
+ { "arp", ETHERTYPE_ARP },
+ { "rarp", ETHERTYPE_REVARP },
+ { "sprite", ETHERTYPE_SPRITE },
+ { "mopdl", ETHERTYPE_MOPDL },
+ { "moprc", ETHERTYPE_MOPRC },
+ { "decnet", ETHERTYPE_DN },
+ { "lat", ETHERTYPE_LAT },
+ { "lanbridge", ETHERTYPE_LANBRIDGE },
+ { "vexp", ETHERTYPE_VEXP },
+ { "vprod", ETHERTYPE_VPROD },
+ { "atalk", ETHERTYPE_ATALK },
+ { "atalkarp", ETHERTYPE_AARP },
+ { "loopback", ETHERTYPE_LOOPBACK },
+ { (char *)0, 0 }
+};
+
+static void
+init_eprotoarray()
+{
+ register int i;
+ register struct hnamemem *table;
+
+ for (i = 0; eproto_db[i].s; i++) {
+ int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1);
+ table = &eprototable[j];
+ while (table->name)
+ table = table->nxt;
+ table->name = eproto_db[i].s;
+ table->addr = ntohs(eproto_db[i].p);
+ table->nxt = (struct hnamemem *)calloc(1, sizeof(*table));
+ }
+}
+
+static void
+init_etherarray()
+{
+#ifndef ETHER_SERVICE
+ FILE *fp;
+ struct etherent *ep;
+ struct enamemem *tp;
+
+ fp = fopen(ETHERS_FILE, "r");
+ if (fp == 0)
+ /* No data base; will have to settle for
+ numeric addresses. */
+ return;
+
+ while (ep = next_etherent(fp)) {
+ tp = lookup_emem(ep->addr);
+ tp->e_name = (char *)malloc((unsigned)strlen(ep->name)+1);
+ strcpy(tp->e_name, ep->name);
+ }
+#endif
+}
+
+/*
+ * Initialize the address to name translation machinery. We map all
+ * non-local IP addresses to numeric addresses if fflag is true (i.e.,
+ * to prevent blocking on the nameserver). localnet is the IP address
+ * of the local network. mask is its subnet mask.
+ */
+void
+init_addrtoname(fflag, localnet, mask)
+ int fflag;
+ u_long localnet;
+ u_long mask;
+{
+ netmask = mask;
+ if (fflag) {
+ f_localnet = localnet;
+ f_netmask = mask;
+ }
+ if (nflag)
+ /*
+ * Simplest way to suppress names.
+ */
+ return;
+
+ init_etherarray();
+ init_servarray();
+ init_eprotoarray();
+}
diff --git a/usr.sbin/tcpdump/tcpdump/addrtoname.h b/usr.sbin/tcpdump/tcpdump/addrtoname.h
new file mode 100644
index 000000000000..6dc6979895c9
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/addrtoname.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 1988, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: addrtoname.h,v 1.5 92/03/17 13:41:37 mccanne Exp $ (LBL)
+ */
+
+/* Name to address translation routines. */
+
+extern char *etheraddr_string();
+extern char *etherproto_string();
+extern char *tcpport_string();
+extern char *udpport_string();
+extern char *getname();
+extern char *intoa();
+
+extern void init_addrtoname();
+extern void no_foreign_names();
+
+#define ipaddr_string(p) getname((u_char *)(p))
diff --git a/usr.sbin/tcpdump/tcpdump/appletalk.h b/usr.sbin/tcpdump/tcpdump/appletalk.h
new file mode 100644
index 000000000000..90c8c806330f
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/appletalk.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * AppleTalk protocol formats (courtesy Bill Croft of Stanford/SUMEX).
+ *
+ * @(#) $Header: appletalk.h,v 1.6 90/10/03 22:14:26 leres Exp $ (LBL)
+ */
+
+/* Datagram Delivery Protocol */
+
+struct atDDP {
+ u_short length;
+ u_short checksum;
+ u_short dstNet;
+ u_short srcNet;
+ u_char dstNode;
+ u_char srcNode;
+ u_char dstSkt;
+ u_char srcSkt;
+ u_char type;
+};
+
+struct atShortDDP {
+ u_short length;
+ u_char dstSkt;
+ u_char srcSkt;
+ u_char type;
+};
+
+#define ddpMaxWKS 0x7F
+#define ddpMaxData 586
+#define ddpLengthMask 0x3FF
+#define ddpHopShift 10
+#define ddpSize 13 /* size of DDP header (avoid struct padding) */
+#define ddpSSize 5
+#define ddpWKS 128 /* boundary of DDP well known sockets */
+#define ddpRTMP 1 /* RTMP type */
+#define ddpRTMPrequest 5 /* RTMP request type */
+#define ddpNBP 2 /* NBP type */
+#define ddpATP 3 /* ATP type */
+#define ddpECHO 4 /* ECHO type */
+#define ddpIP 22 /* IP type */
+#define ddpARP 23 /* ARP type */
+#define ddpKLAP 0x4b /* Kinetics KLAP type */
+
+
+/* AppleTalk Transaction Protocol */
+
+struct atATP {
+ u_char control;
+ u_char bitmap;
+ u_short transID;
+ long userData;
+};
+
+#define atpReqCode 0x40
+#define atpRspCode 0x80
+#define atpRelCode 0xC0
+#define atpXO 0x20
+#define atpEOM 0x10
+#define atpSTS 0x08
+#define atpFlagMask 0x3F
+#define atpControlMask 0xF8
+#define atpMaxNum 8
+#define atpMaxData 578
+
+
+/* AppleTalk Echo Protocol */
+
+struct atEcho {
+ u_char echoFunction;
+ u_char *echoData;
+};
+
+#define echoSkt 4 /* the echoer socket */
+#define echoSize 1 /* size of echo header */
+#define echoRequest 1 /* echo request */
+#define echoReply 2 /* echo request */
+
+
+/* Name Binding Protocol */
+
+struct atNBP {
+ u_char control;
+ u_char id;
+};
+
+struct atNBPtuple {
+ u_short net;
+ u_char node;
+ u_char skt;
+ u_char enumerator;
+};
+
+#define nbpBrRq 0x10
+#define nbpLkUp 0x20
+#define nbpLkUpReply 0x30
+
+#define nbpNIS 2
+#define nbpTupleMax 15
+
+#define nbpHeaderSize 2
+#define nbpTupleSize 5;
+
+
+/* Routing Table Maint. Protocol */
+
+#define rtmpSkt 1 /* number of RTMP socket */
+#define rtmpSize 4 /* minimum size */
+#define rtmpTupleSize 3
+
+
+/* Zone Information Protocol */
+
+struct zipHeader {
+ u_char command;
+ u_char netcount;
+};
+
+#define zipHeaderSize 2
+#define zipQuery 1
+#define zipReply 2
+#define zipTakedown 3
+#define zipBringup 4
+#define ddpZIP 6
+#define zipSkt 6
+#define GetMyZone 7
+#define GetZoneList 8
+
+/*
+ * UDP port range used for ddp-in-udp encapsulation is 16512-16639
+ * for client sockets (128-255) and 200-327 for server sockets
+ * (0-127). We also try to recognize the pre-April 88 server
+ * socket range of 768-895.
+ */
+#define atalk_port(p) \
+ (((unsigned)((p) - 16512) < 128) || \
+ ((unsigned)((p) - 200) < 128) || \
+ ((unsigned)((p) - 768) < 128))
diff --git a/usr.sbin/tcpdump/tcpdump/bootp.h b/usr.sbin/tcpdump/tcpdump/bootp.h
new file mode 100644
index 000000000000..ab474cf4d638
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/bootp.h
@@ -0,0 +1,103 @@
+/* @(#) $Header: bootp.h,v 1.2 90/05/29 21:29:16 leres Exp $ (LBL) */
+/*
+ * Bootstrap Protocol (BOOTP). RFC951 and RFC1048.
+ *
+ * This file specifies the "implementation-independent" BOOTP protocol
+ * information which is common to both client and server.
+ *
+ * Copyright 1988 by Carnegie Mellon.
+ *
+ * Permission to use, copy, modify, and distribute this program for any
+ * purpose and without fee is hereby granted, provided that this copyright
+ * and permission notice appear on all copies and supporting documentation,
+ * the name of Carnegie Mellon not be used in advertising or publicity
+ * pertaining to distribution of the program without specific prior
+ * permission, and notice be given in supporting documentation that copying
+ * and distribution is by permission of Carnegie Mellon and Stanford
+ * University. Carnegie Mellon makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ */
+
+
+struct bootp {
+ unsigned char bp_op; /* packet opcode type */
+ unsigned char bp_htype; /* hardware addr type */
+ unsigned char bp_hlen; /* hardware addr length */
+ unsigned char bp_hops; /* gateway hops */
+ unsigned long bp_xid; /* transaction ID */
+ unsigned short bp_secs; /* seconds since boot began */
+ unsigned short bp_unused;
+ struct in_addr bp_ciaddr; /* client IP address */
+ struct in_addr bp_yiaddr; /* 'your' IP address */
+ struct in_addr bp_siaddr; /* server IP address */
+ struct in_addr bp_giaddr; /* gateway IP address */
+ unsigned char bp_chaddr[16]; /* client hardware address */
+ unsigned char bp_sname[64]; /* server host name */
+ unsigned char bp_file[128]; /* boot file name */
+ unsigned char bp_vend[64]; /* vendor-specific area */
+};
+
+/*
+ * UDP port numbers, server and client.
+ */
+#define IPPORT_BOOTPS 67
+#define IPPORT_BOOTPC 68
+
+#define BOOTREPLY 2
+#define BOOTREQUEST 1
+
+
+/*
+ * Vendor magic cookie (v_magic) for CMU
+ */
+#define VM_CMU "CMU"
+
+/*
+ * Vendor magic cookie (v_magic) for RFC1048
+ */
+#define VM_RFC1048 { 99, 130, 83, 99 }
+
+
+
+/*
+ * RFC1048 tag values used to specify what information is being supplied in
+ * the vendor field of the packet.
+ */
+
+#define TAG_PAD ((unsigned char) 0)
+#define TAG_SUBNET_MASK ((unsigned char) 1)
+#define TAG_TIME_OFFSET ((unsigned char) 2)
+#define TAG_GATEWAY ((unsigned char) 3)
+#define TAG_TIME_SERVER ((unsigned char) 4)
+#define TAG_NAME_SERVER ((unsigned char) 5)
+#define TAG_DOMAIN_SERVER ((unsigned char) 6)
+#define TAG_LOG_SERVER ((unsigned char) 7)
+#define TAG_COOKIE_SERVER ((unsigned char) 8)
+#define TAG_LPR_SERVER ((unsigned char) 9)
+#define TAG_IMPRESS_SERVER ((unsigned char) 10)
+#define TAG_RLP_SERVER ((unsigned char) 11)
+#define TAG_HOSTNAME ((unsigned char) 12)
+#define TAG_BOOTSIZE ((unsigned char) 13)
+#define TAG_END ((unsigned char) 255)
+
+
+
+/*
+ * "vendor" data permitted for CMU bootp clients.
+ */
+
+struct cmu_vend {
+ unsigned char v_magic[4]; /* magic number */
+ unsigned long v_flags; /* flags/opcodes, etc. */
+ struct in_addr v_smask; /* Subnet mask */
+ struct in_addr v_dgate; /* Default gateway */
+ struct in_addr v_dns1, v_dns2; /* Domain name servers */
+ struct in_addr v_ins1, v_ins2; /* IEN-116 name servers */
+ struct in_addr v_ts1, v_ts2; /* Time servers */
+ unsigned char v_unused[25]; /* currently unused */
+};
+
+
+/* v_flags values */
+#define VF_SMASK 1 /* Subnet mask field contains valid data */
diff --git a/usr.sbin/tcpdump/tcpdump/bpf_dump.c b/usr.sbin/tcpdump/tcpdump/bpf_dump.c
new file mode 100644
index 000000000000..fab9596d2f44
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/bpf_dump.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: bpf_dump.c,v 1.1 92/01/29 13:25:30 mccanne Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <net/bpf.h>
+
+void
+bpf_dump(p, option)
+ struct bpf_program *p;
+ int option;
+{
+ struct bpf_insn *insn;
+ int i;
+ int n = p->bf_len;
+
+ insn = p->bf_insns;
+ if (option > 2) {
+ printf("%d\n", n);
+ for (i = 0; i < n; ++insn, ++i) {
+ printf("%lu %lu %lu %lu\n", insn->code,
+ insn->jt, insn->jf, insn->k);
+ }
+ return ;
+ }
+ if (option > 1) {
+ for (i = 0; i < n; ++insn, ++i)
+ printf("{ 0x%x, %d, %d, 0x%08x },\n",
+ insn->code, insn->jt, insn->jf, insn->k);
+ return;
+ }
+ for (i = 0; i < n; ++insn, ++i) {
+#ifdef BDEBUG
+ extern int bids[];
+ printf(bids[i] > 0 ? "[%02d]" : " -- ", bids[i] - 1);
+#endif
+ puts(bpf_image(insn, i));
+ }
+}
diff --git a/usr.sbin/tcpdump/tcpdump/bpf_image.c b/usr.sbin/tcpdump/tcpdump/bpf_image.c
new file mode 100644
index 000000000000..d36eab252f7c
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/bpf_image.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: bpf_image.c,v 1.10 92/01/26 21:01:16 mccanne Exp $ (LBL)";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <net/bpf.h>
+
+char *
+bpf_image(p, n)
+ struct bpf_insn *p;
+ int n;
+{
+ int v;
+ char *fmt, *op;
+ static char image[256];
+ char operand[64];
+
+ v = p->k;
+ switch (p->code) {
+
+ default:
+ op = "unimp";
+ fmt = "0x%x";
+ v = p->code;
+ break;
+
+ case BPF_RET|BPF_K:
+ op = "ret";
+ fmt = "#%d";
+ break;
+
+ case BPF_RET|BPF_A:
+ op = "ret";
+ fmt = "";
+ break;
+
+ case BPF_LD|BPF_W|BPF_ABS:
+ op = "ld";
+ fmt = "[%d]";
+ break;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ op = "ldh";
+ fmt = "[%d]";
+ break;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ op = "ldb";
+ fmt = "[%d]";
+ break;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ op = "ld";
+ fmt = "#pktlen";
+ break;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ op = "ld";
+ fmt = "[x + %d]";
+ break;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ op = "ldh";
+ fmt = "[x + %d]";
+ break;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ op = "ldb";
+ fmt = "[x + %d]";
+ break;
+
+ case BPF_LD|BPF_IMM:
+ op = "ld";
+ fmt = "#0x%x";
+ break;
+
+ case BPF_LDX|BPF_IMM:
+ op = "ldx";
+ fmt = "#0x%x";
+ break;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ op = "ldxb";
+ fmt = "4*([%d]&0xf)";
+ break;
+
+ case BPF_LD|BPF_MEM:
+ op = "ld";
+ fmt = "M[%d]";
+ break;
+
+ case BPF_LDX|BPF_MEM:
+ op = "ldx";
+ fmt = "M[%d]";
+ break;
+
+ case BPF_ST:
+ op = "st";
+ fmt = "M[%d]";
+ break;
+
+ case BPF_STX:
+ op = "stx";
+ fmt = "M[%d]";
+ break;
+
+ case BPF_JMP|BPF_JA:
+ op = "ja";
+ fmt = "%d";
+ v = n + p->k;
+ break;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ op = "jgt";
+ fmt = "#0x%x";
+ break;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ op = "jge";
+ fmt = "#0x%x";
+ break;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ op = "jeq";
+ fmt = "#0x%x";
+ break;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ op = "jset";
+ fmt = "#0x%x";
+ break;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ op = "jgt";
+ fmt = "x";
+ break;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ op = "jge";
+ fmt = "x";
+ break;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ op = "jeq";
+ fmt = "x";
+ break;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ op = "jset";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ op = "add";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ op = "sub";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ op = "mul";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ op = "div";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ op = "and";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ op = "or";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ op = "lsh";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ op = "rsh";
+ fmt = "x";
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ op = "add";
+ fmt = "#%d";
+ break;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ op = "sub";
+ fmt = "#%d";
+ break;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ op = "mul";
+ fmt = "#%d";
+ break;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ op = "div";
+ fmt = "#%d";
+ break;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ op = "and";
+ fmt = "#%d";
+ break;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ op = "or";
+ fmt = "#%d";
+ break;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ op = "lsh";
+ fmt = "#%d";
+ break;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ op = "rsh";
+ fmt = "#%d";
+ break;
+
+ case BPF_ALU|BPF_NEG:
+ op = "neg";
+ fmt = "";
+ break;
+
+ case BPF_MISC|BPF_TAX:
+ op = "tax";
+ fmt = "";
+ break;
+
+ case BPF_MISC|BPF_TXA:
+ op = "txa";
+ fmt = "";
+ break;
+ }
+ (void)sprintf(operand, fmt, v);
+ (void)sprintf(image,
+ (BPF_CLASS(p->code) == BPF_JMP &&
+ BPF_OP(p->code) != BPF_JA) ?
+ "(%03d) %-8s %-16s jt %d\tjf %d"
+ : "(%03d) %-8s %s",
+ n, op, operand, n + 1 + p->jt, n + 1 + p->jf);
+ return image;
+}
diff --git a/usr.sbin/tcpdump/tcpdump/etherent.c b/usr.sbin/tcpdump/tcpdump/etherent.c
new file mode 100644
index 000000000000..9d7ee8009600
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/etherent.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: etherent.c,v 1.2 90/09/20 23:16:06 mccanne Exp $ (LBL)";
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include "interface.h"
+
+#ifndef ETHER_SERVICE
+
+#include "etherent.h"
+
+/* Hex digit to integer. */
+static inline int
+xdtoi(c)
+{
+ if (isdigit(c))
+ return c - '0';
+ else if (islower(c))
+ return c - 'a' + 10;
+ else
+ return c - 'A' + 10;
+}
+
+static inline int
+skip_space(f)
+ FILE *f;
+{
+ int c;
+
+ do {
+ c = getc(f);
+ } while (isspace(c) && c != '\n');
+
+ return c;
+}
+
+static inline int
+skip_line(f)
+ FILE *f;
+{
+ int c;
+
+ do
+ c = getc(f);
+ while (c != '\n' && c != EOF);
+
+ return c;
+}
+
+struct etherent *
+next_etherent(fp)
+ FILE *fp;
+{
+ register int c, d, i;
+ char *bp;
+ static struct etherent e;
+ static int nline = 1;
+ top:
+ while (nline) {
+ /* Find addr */
+ c = skip_space(fp);
+ if (c == '\n')
+ continue;
+ /* If this is a comment, or first thing on line
+ cannot be etehrnet address, skip the line. */
+ else if (!isxdigit(c))
+ c = skip_line(fp);
+ else {
+ /* must be the start of an address */
+ for (i = 0; i < 6; i += 1) {
+ d = xdtoi(c);
+ c = getc(fp);
+ if (c != ':') {
+ d <<= 4;
+ d |= xdtoi(c);
+ c = getc(fp);
+ }
+ e.addr[i] = d;
+ if (c != ':')
+ break;
+ c = getc(fp);
+ }
+ nline = 0;
+ }
+ if (c == EOF)
+ return 0;
+ }
+
+ /* If we started a new line, 'c' holds the char past the ether addr,
+ which we assume is white space. If we are continuning a line,
+ 'c' is garbage. In either case, we can throw it away. */
+
+ c = skip_space(fp);
+ if (c == '\n') {
+ nline = 1;
+ goto top;
+ }
+ else if (c == '#') {
+ (void)skip_line(fp);
+ nline = 1;
+ goto top;
+ }
+ else if (c == EOF)
+ return 0;
+
+ /* Must be a name. */
+ bp = e.name;
+ /* Use 'd' to prevent buffer overflow. */
+ d = sizeof(e.name) - 1;
+ do {
+ *bp++ = c;
+ c = getc(fp);
+ } while (!isspace(c) && c != EOF && --d > 0);
+ *bp = '\0';
+ if (c == '\n')
+ nline = 1;
+
+ return &e;
+}
+
+#endif
diff --git a/usr.sbin/tcpdump/tcpdump/etherent.h b/usr.sbin/tcpdump/tcpdump/etherent.h
new file mode 100644
index 000000000000..83ebaabb8647
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/etherent.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: etherent.h,v 1.2 90/09/20 23:16:17 mccanne Exp $ (LBL)
+ */
+
+/* File name of ethernet address data base. */
+
+#define ETHERS_FILE "/etc/ethers"
+
+struct etherent {
+ u_char addr[6];
+ char name[122];
+};
+
+struct etherent *next_etherent();
+
diff --git a/usr.sbin/tcpdump/tcpdump/etherproto.h b/usr.sbin/tcpdump/tcpdump/etherproto.h
new file mode 100644
index 000000000000..5c0e245cee72
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/etherproto.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: etherproto.h,v 1.7 90/10/10 15:04:04 mccanne Exp $ (LBL)
+ */
+
+/* Map between Ethernet protocol types and names */
+
+/* Add other Ethernet packet types here */
+#ifndef ETHERTYPE_SPRITE
+#define ETHERTYPE_SPRITE 0x0500
+#endif
+#ifndef ETHERTYPE_MOPDL
+#define ETHERTYPE_MOPDL 0x6001
+#endif
+#ifndef ETHERTYPE_MOPRC
+#define ETHERTYPE_MOPRC 0x6002
+#endif
+#ifndef ETHERTYPE_DN
+#define ETHERTYPE_DN 0x6003
+#endif
+#ifndef ETHERTYPE_LAT
+#define ETHERTYPE_LAT 0x6004
+#endif
+#ifndef ETHERTYPE_LANBRIDGE
+#define ETHERTYPE_LANBRIDGE 0x8038
+#endif
+#ifndef ETHERTYPE_VEXP
+#define ETHERTYPE_VEXP 0x805b
+#endif
+#ifndef ETHERTYPE_VPROD
+#define ETHERTYPE_VPROD 0x805c
+#endif
+#ifndef ETHERTYPE_LOOPBACK
+#define ETHERTYPE_LOOPBACK 0x9000
+#endif
+
+#ifndef ETHERTYPE_ATALK
+#define ETHERTYPE_ATALK 0x809b /* XXX */
+#endif
+#ifndef ETHERTYPE_AARP
+#define ETHERTYPE_AARP 0x80f3
+#endif
+#ifndef ETHERTYPE_NS
+#define ETHERTYPE_NS 0x0600
+#endif
+
+struct eproto {
+ char *s;
+ u_short p;
+};
+
+extern struct eproto eproto_db[];
diff --git a/usr.sbin/tcpdump/tcpdump/extract.h b/usr.sbin/tcpdump/tcpdump/extract.h
new file mode 100644
index 000000000000..bd45c59b3e9e
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/extract.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: extract.h,v 1.4 92/05/25 14:28:36 mccanne Exp $ (LBL)
+ */
+
+#ifdef TCPDUMP_ALIGN
+#if BYTEORDER == LITTLE_ENDIAN
+#define EXTRACT_SHORT(p)\
+ ((u_short)\
+ ((u_short)*((u_char *)p+1)<<8|\
+ (u_short)*((u_char *)p+0)<<0))
+#define EXTRACT_LONG(p)\
+ ((u_long)*((u_char *)p+3)<<24|\
+ (u_long)*((u_char *)p+2)<<16|\
+ (u_long)*((u_char *)p+1)<<8|\
+ (u_long)*((u_char *)p+0)<<0)
+#else
+#define EXTRACT_SHORT(p)\
+ ((u_short)\
+ ((u_short)*((u_char *)p+0)<<8|\
+ (u_short)*((u_char *)p+1)<<0))
+#define EXTRACT_LONG(p)\
+ ((u_long)*((u_char *)p+0)<<24|\
+ (u_long)*((u_char *)p+1)<<16|\
+ (u_long)*((u_char *)p+2)<<8|\
+ (u_long)*((u_char *)p+3)<<0)
+#endif
+#else
+#define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p))
+#define EXTRACT_LONG(p) (ntohl(*(u_long *)p))
+#endif
diff --git a/usr.sbin/tcpdump/tcpdump/gencode.c b/usr.sbin/tcpdump/tcpdump/gencode.c
new file mode 100644
index 000000000000..8cb48ea05483
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/gencode.c
@@ -0,0 +1,1384 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: gencode.c,v 1.33 92/05/22 16:38:39 mccanne Exp $ (LBL)";
+#endif
+
+#ifdef __STDC__
+#include <stdlib.h>
+#endif
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <sys/time.h>
+#include <net/bpf.h>
+
+#include "interface.h"
+#include "gencode.h"
+#include "nametoaddr.h"
+#include "extract.h"
+
+#define JMP(c) ((c)|BPF_JMP|BPF_K)
+
+extern struct bpf_insn *icode_to_fcode();
+extern u_long net_mask();
+static void init_linktype();
+
+static int alloc_reg();
+static void free_reg();
+
+static struct block *root;
+
+/*
+ * We divy out chunks of memory rather than call malloc each time so
+ * we don't have to worry about leaking memory. It's probably
+ * not a big deal if all this memory was wasted but it this ever
+ * goes into a library that would probably not be a good idea.
+ */
+#define NCHUNKS 16
+#define CHUNK0SIZE 1024
+struct chunk {
+ u_int n_left;
+ void *m;
+};
+
+static struct chunk chunks[NCHUNKS];
+static int cur_chunk;
+
+static void *
+newchunk(n)
+ u_int n;
+{
+ struct chunk *cp;
+ int k, size;
+
+ /* XXX Round up to nearest long. */
+ n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1);
+
+ cp = &chunks[cur_chunk];
+ if (n > cp->n_left) {
+ ++cp, k = ++cur_chunk;
+ if (k >= NCHUNKS)
+ error("out of memory");
+ size = CHUNK0SIZE << k;
+ cp->m = (void *)malloc(size);
+ bzero((char *)cp->m, size);
+ cp->n_left = size;
+ if (n > size)
+ error("out of memory");
+ }
+ cp->n_left -= n;
+ return (void *)((char *)cp->m + cp->n_left);
+}
+
+static void
+freechunks()
+{
+ int i;
+
+ for (i = 0; i < NCHUNKS; ++i)
+ if (chunks[i].m)
+ free(chunks[i].m);
+}
+
+static inline struct block *
+new_block(code)
+ int code;
+{
+ struct block *p;
+
+ p = (struct block *)newchunk(sizeof(*p));
+ p->s.code = code;
+ p->head = p;
+
+ return p;
+}
+
+static inline struct slist *
+new_stmt(code)
+ int code;
+{
+ struct slist *p;
+
+ p = (struct slist *)newchunk(sizeof(*p));
+ p->s.code = code;
+
+ return p;
+}
+
+static struct block *
+gen_retblk(v)
+ int v;
+{
+ struct block *b = new_block(BPF_RET|BPF_K);
+
+ b->s.k = v;
+ return b;
+}
+
+static inline void
+syntax()
+{
+ error("syntax error in filter expression");
+}
+
+static u_long netmask;
+
+struct bpf_program *
+parse(buf, Oflag, linktype, mask)
+ char *buf;
+ int Oflag;
+ int linktype;
+ u_long mask;
+{
+ extern int n_errors;
+ static struct bpf_program F;
+ struct bpf_insn *p;
+ int len;
+
+ netmask = mask;
+
+ F.bf_insns = 0;
+ F.bf_len = 0;
+
+ lex_init(buf ? buf : "");
+ init_linktype(linktype);
+ yyparse();
+
+ if (n_errors)
+ syntax();
+
+ if (root == 0)
+ root = gen_retblk(snaplen);
+
+ if (Oflag) {
+ optimize(&root);
+ if (root == 0 ||
+ (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0))
+ error("expression rejects all packets");
+ }
+ p = icode_to_fcode(root, &len);
+ F.bf_insns = p;
+ F.bf_len = len;
+
+ freechunks();
+ return &F;
+}
+
+/*
+ * Backpatch the blocks in 'list' to 'target'. The 'sense' field indicates
+ * which of the jt and jf fields has been resolved and which is a pointer
+ * back to another unresolved block (or nil). At least one of the fields
+ * in each block is already resolved.
+ */
+static void
+backpatch(list, target)
+ struct block *list, *target;
+{
+ struct block *next;
+
+ while (list) {
+ if (!list->sense) {
+ next = JT(list);
+ JT(list) = target;
+ } else {
+ next = JF(list);
+ JF(list) = target;
+ }
+ list = next;
+ }
+}
+
+/*
+ * Merge the lists in b0 and b1, using the 'sense' field to indicate
+ * which of jt and jf is the link.
+ */
+static void
+merge(b0, b1)
+ struct block *b0, *b1;
+{
+ register struct block **p = &b0;
+
+ /* Find end of list. */
+ while (*p)
+ p = !((*p)->sense) ? &JT(*p) : &JF(*p);
+
+ /* Concatenate the lists. */
+ *p = b1;
+}
+
+void
+finish_parse(p)
+ struct block *p;
+{
+ backpatch(p, gen_retblk(snaplen));
+ p->sense = !p->sense;
+ backpatch(p, gen_retblk(0));
+ root = p->head;
+}
+
+void
+gen_and(b0, b1)
+ struct block *b0, *b1;
+{
+ backpatch(b0, b1->head);
+ b0->sense = !b0->sense;
+ b1->sense = !b1->sense;
+ merge(b1, b0);
+ b1->sense = !b1->sense;
+ b1->head = b0->head;
+}
+
+void
+gen_or(b0, b1)
+ struct block *b0, *b1;
+{
+ b0->sense = !b0->sense;
+ backpatch(b0, b1->head);
+ b0->sense = !b0->sense;
+ merge(b1, b0);
+ b1->head = b0->head;
+}
+
+void
+gen_not(b)
+ struct block *b;
+{
+ b->sense = !b->sense;
+}
+
+static struct block *
+gen_cmp(offset, size, v)
+ u_int offset, size;
+ long v;
+{
+ struct slist *s;
+ struct block *b;
+
+ s = new_stmt(BPF_LD|BPF_ABS|size);
+ s->s.k = offset;
+
+ b = new_block(JMP(BPF_JEQ));
+ b->stmts = s;
+ b->s.k = v;
+
+ return b;
+}
+
+struct block *
+gen_mcmp(offset, size, v, mask)
+ u_int offset, size;
+ long v;
+ u_long mask;
+{
+ struct block *b = gen_cmp(offset, size, v);
+ struct slist *s;
+
+ if (mask != 0xffffffff) {
+ s = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+ s->s.k = mask;
+ b->stmts->next = s;
+ }
+ return b;
+}
+
+struct block *
+gen_bcmp(offset, size, v)
+ u_int offset;
+ u_int size;
+ u_char *v;
+{
+ struct block *b, *tmp;
+ int k;
+
+ b = 0;
+ while (size >= 4) {
+ k = size - 4;
+ tmp = gen_cmp(offset + k, BPF_W, EXTRACT_LONG(&v[k]));
+ if (b != 0)
+ gen_and(b, tmp);
+ b = tmp;
+ size -= 4;
+ }
+ while (size >= 2) {
+ k = size - 2;
+ tmp = gen_cmp(offset + k, BPF_H, (long)EXTRACT_SHORT(&v[k]));
+ if (b != 0)
+ gen_and(b, tmp);
+ b = tmp;
+ size -= 2;
+ }
+ if (size > 0) {
+ tmp = gen_cmp(offset, BPF_B, (long)v[0]);
+ if (b != 0)
+ gen_and(b, tmp);
+ b = tmp;
+ }
+ return b;
+}
+
+/*
+ * Various code contructs need to know the layout of the data link
+ * layer. These variables give the necessary offsets. off_linktype
+ * is set to -1 for no encapsulation, in which case, IP is assumed.
+ */
+static u_int off_linktype;
+static u_int off_nl;
+static int linktype;
+
+static void
+init_linktype(type)
+ int type;
+{
+ linktype = type;
+
+ switch (type) {
+
+ case DLT_EN10MB:
+ off_linktype = 12;
+ off_nl = 14;
+ return;
+
+ case DLT_SLIP:
+ /*
+ * SLIP doesn't have a link level type. The 16 byte
+ * header is hacked into our SLIP driver.
+ */
+ off_linktype = -1;
+ off_nl = 16;
+ return;
+
+ case DLT_NULL:
+ off_linktype = -1;
+ off_nl = 0;
+ return;
+
+ case DLT_PPP:
+ off_linktype = 2;
+ off_nl = 4;
+ return;
+
+ case DLT_FDDI:
+ off_linktype = 19;
+ off_nl = 21;
+ return;
+
+ case DLT_IEEE802:
+ off_linktype = 20;
+ off_nl = 22;
+ return;
+ }
+ error("unknown data link type 0x%x", linktype);
+ /* NOTREACHED */
+}
+
+static struct block *
+gen_uncond(rsense)
+ int rsense;
+{
+ struct block *b;
+ struct slist *s;
+
+ s = new_stmt(BPF_LD|BPF_IMM);
+ s->s.k = !rsense;
+ b = new_block(JMP(BPF_JEQ));
+ b->stmts = s;
+
+ return b;
+}
+
+static inline struct block *
+gen_true()
+{
+ return gen_uncond(1);
+}
+
+static inline struct block *
+gen_false()
+{
+ return gen_uncond(0);
+}
+
+struct block *
+gen_linktype(proto)
+ int proto;
+{
+ switch (linktype) {
+ case DLT_SLIP:
+ if (proto == ETHERTYPE_IP)
+ return gen_true();
+ else
+ return gen_false();
+
+ case DLT_PPP:
+ if (proto == ETHERTYPE_IP)
+ proto = 0x0021; /* XXX - need ppp.h defs */
+ break;
+ }
+ return gen_cmp(off_linktype, BPF_H, (long)proto);
+}
+
+static struct block *
+gen_hostop(addr, mask, dir, proto, src_off, dst_off)
+ u_long addr;
+ u_long mask;
+ int dir, proto;
+ u_int src_off, dst_off;
+{
+ struct block *b0, *b1;
+ u_int offset;
+
+ switch (dir) {
+
+ case Q_SRC:
+ offset = src_off;
+ break;
+
+ case Q_DST:
+ offset = dst_off;
+ break;
+
+ case Q_AND:
+ b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
+ b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_OR:
+ case Q_DEFAULT:
+ b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
+ b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
+ gen_or(b0, b1);
+ return b1;
+
+ default:
+ abort();
+ }
+ b0 = gen_linktype(proto);
+ b1 = gen_mcmp(offset, BPF_W, (long)addr, mask);
+ gen_and(b0, b1);
+ return b1;
+}
+
+static struct block *
+gen_ehostop(eaddr, dir)
+ u_char *eaddr;
+ int dir;
+{
+ struct block *b0, *b1;
+
+ switch (dir) {
+ case Q_SRC:
+ return gen_bcmp(6, 6, eaddr);
+
+ case Q_DST:
+ return gen_bcmp(0, 6, eaddr);
+
+ case Q_AND:
+ b0 = gen_ehostop(eaddr, Q_SRC);
+ b1 = gen_ehostop(eaddr, Q_DST);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_DEFAULT:
+ case Q_OR:
+ b0 = gen_ehostop(eaddr, Q_SRC);
+ b1 = gen_ehostop(eaddr, Q_DST);
+ gen_or(b0, b1);
+ return b1;
+ }
+ abort();
+ /* NOTREACHED */
+}
+
+static struct block *
+gen_host(addr, mask, proto, dir)
+ u_long addr;
+ u_long mask;
+ int proto;
+ int dir;
+{
+ struct block *b0, *b1;
+
+ switch (proto) {
+
+ case Q_DEFAULT:
+ b0 = gen_host(addr, mask, Q_IP, dir);
+ b1 = gen_host(addr, mask, Q_ARP, dir);
+ gen_or(b0, b1);
+ b0 = gen_host(addr, mask, Q_RARP, dir);
+ gen_or(b1, b0);
+ return b0;
+
+ case Q_IP:
+ return gen_hostop(addr, mask, dir, ETHERTYPE_IP,
+ off_nl + 12, off_nl + 16);
+
+ case Q_RARP:
+ return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP,
+ off_nl + 14, off_nl + 24);
+
+ case Q_ARP:
+ return gen_hostop(addr, mask, dir, ETHERTYPE_ARP,
+ off_nl + 14, off_nl + 24);
+
+ case Q_TCP:
+ error("'tcp' modifier applied to host");
+
+ case Q_UDP:
+ error("'udp' modifier applied to host");
+
+ case Q_ICMP:
+ error("'icmp' modifier applied to host");
+ }
+ abort();
+ /* NOTREACHED */
+}
+
+static struct block *
+gen_gateway(eaddr, alist, proto, dir)
+ u_char *eaddr;
+ u_long **alist;
+ int proto;
+ int dir;
+{
+ struct block *b0, *b1, *tmp;
+
+ if (dir != 0)
+ error("direction applied to 'gateway'");
+
+ switch (proto) {
+ case Q_DEFAULT:
+ case Q_IP:
+ case Q_ARP:
+ case Q_RARP:
+ b0 = gen_ehostop(eaddr, Q_OR);
+ b1 = gen_host(**alist++, 0xffffffffL, proto, Q_OR);
+ while (*alist) {
+ tmp = gen_host(**alist++, 0xffffffffL, proto, Q_OR);
+ gen_or(b1, tmp);
+ b1 = tmp;
+ }
+ gen_not(b1);
+ gen_and(b0, b1);
+ return b1;
+ }
+ error("illegal modifier of 'gateway'");
+ /* NOTREACHED */
+}
+
+struct block *
+gen_proto_abbrev(proto)
+ int proto;
+{
+ struct block *b0, *b1;
+
+ switch (proto) {
+
+ case Q_TCP:
+ b0 = gen_linktype(ETHERTYPE_IP);
+ b1 = gen_cmp(off_nl + 9, BPF_B, (long)IPPROTO_TCP);
+ gen_and(b0, b1);
+ break;
+
+ case Q_UDP:
+ b0 = gen_linktype(ETHERTYPE_IP);
+ b1 = gen_cmp(off_nl + 9, BPF_B, (long)IPPROTO_UDP);
+ gen_and(b0, b1);
+ break;
+
+ case Q_ICMP:
+ b0 = gen_linktype(ETHERTYPE_IP);
+ b1 = gen_cmp(off_nl + 9, BPF_B, (long)IPPROTO_ICMP);
+ gen_and(b0, b1);
+ break;
+
+ case Q_IP:
+ b1 = gen_linktype(ETHERTYPE_IP);
+ break;
+
+ case Q_ARP:
+ b1 = gen_linktype(ETHERTYPE_ARP);
+ break;
+
+ case Q_RARP:
+ b1 = gen_linktype(ETHERTYPE_REVARP);
+ break;
+
+ case Q_LINK:
+ error("link layer applied in wrong context");
+
+ default:
+ abort();
+ }
+ return b1;
+}
+
+static struct block *
+gen_ipfrag()
+{
+ struct slist *s;
+ struct block *b;
+
+ /* not ip frag */
+ s = new_stmt(BPF_LD|BPF_H|BPF_ABS);
+ s->s.k = off_nl + 6;
+ b = new_block(JMP(BPF_JSET));
+ b->s.k = 0x1fff;
+ b->stmts = s;
+ gen_not(b);
+
+ return b;
+}
+
+static struct block *
+gen_portatom(off, v)
+ int off;
+ long v;
+{
+ struct slist *s;
+ struct block *b;
+
+ s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
+ s->s.k = off_nl;
+
+ s->next = new_stmt(BPF_LD|BPF_IND|BPF_H);
+ s->next->s.k = off_nl + off;
+
+ b = new_block(JMP(BPF_JEQ));
+ b->stmts = s;
+ b->s.k = v;
+
+ return b;
+}
+
+struct block *
+gen_portop(port, proto, dir)
+ int port;
+ int proto;
+ int dir;
+{
+ struct block *b0, *b1, *tmp;
+
+ /* ip proto 'proto' */
+ tmp = gen_cmp(off_nl + 9, BPF_B, (long)proto);
+ b0 = gen_ipfrag();
+ gen_and(tmp, b0);
+
+ switch (dir) {
+ case Q_SRC:
+ b1 = gen_portatom(0, (long)port);
+ break;
+
+ case Q_DST:
+ b1 = gen_portatom(2, (long)port);
+ break;
+
+ case Q_OR:
+ case Q_DEFAULT:
+ tmp = gen_portatom(0, (long)port);
+ b1 = gen_portatom(2, (long)port);
+ gen_or(tmp, b1);
+ break;
+
+ case Q_AND:
+ tmp = gen_portatom(0, (long)port);
+ b1 = gen_portatom(2, (long)port);
+ gen_and(tmp, b1);
+ break;
+
+ default:
+ abort();
+ }
+ gen_and(b0, b1);
+
+ return b1;
+}
+
+static struct block *
+gen_port(port, ip_proto, dir)
+ int port;
+ int ip_proto;
+ int dir;
+{
+ struct block *b0, *b1, *tmp;
+
+ /* ether proto ip */
+ b0 = gen_linktype(ETHERTYPE_IP);
+
+ switch (ip_proto) {
+ case IPPROTO_UDP:
+ case IPPROTO_TCP:
+ b1 = gen_portop(port, ip_proto, dir);
+ break;
+
+ case PROTO_UNDEF:
+ tmp = gen_portop(port, IPPROTO_TCP, dir);
+ b1 = gen_portop(port, IPPROTO_UDP, dir);
+ gen_or(tmp, b1);
+ break;
+
+ default:
+ abort();
+ }
+ gen_and(b0, b1);
+ return b1;
+}
+
+int
+lookup_proto(name, proto)
+ char *name;
+ int proto;
+{
+ int v;
+
+ switch (proto) {
+ case Q_DEFAULT:
+ case Q_IP:
+ v = s_nametoproto(name);
+ if (v == PROTO_UNDEF)
+ error("unknown ip proto '%s'", name);
+ break;
+
+ case Q_LINK:
+ /* XXX should look up h/w protocol type based on linktype */
+ v = s_nametoeproto(name);
+ if (v == PROTO_UNDEF)
+ error("unknown ether proto '%s'", name);
+ break;
+
+ default:
+ v = PROTO_UNDEF;
+ break;
+ }
+ return v;
+}
+
+struct block *
+gen_proto(v, proto, dir)
+ int v;
+ int proto;
+ int dir;
+{
+ struct block *b0, *b1;
+
+ if (dir != Q_DEFAULT)
+ error("direction applied to 'proto'");
+
+ switch (proto) {
+ case Q_DEFAULT:
+ case Q_IP:
+ b0 = gen_linktype(ETHERTYPE_IP);
+ b1 = gen_cmp(off_nl + 9, BPF_B, (long)v);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_ARP:
+ error("arp does not encapsulate another protocol");
+ /* NOTREACHED */
+
+ case Q_RARP:
+ error("rarp does not encapsulate another protocol");
+ /* NOTREACHED */
+
+ case Q_LINK:
+ return gen_linktype(v);
+
+ case Q_UDP:
+ error("'udp proto' is bogus");
+
+ case Q_TCP:
+ error("'tcp proto' is bogus");
+
+ case Q_ICMP:
+ error("'icmp proto' is bogus");
+ }
+ abort();
+ /* NOTREACHED */
+}
+
+struct block *
+gen_scode(name, q)
+ char *name;
+ struct qual q;
+{
+ int proto = q.proto;
+ int dir = q.dir;
+ u_char *eaddr;
+ u_long mask, addr, **alist;
+ struct block *b, *tmp;
+ int port, real_proto;
+
+ switch (q.addr) {
+
+ case Q_NET:
+ addr = s_nametonetaddr(name);
+ if (addr == 0)
+ error("unknown network '%s'", name);
+ mask = net_mask(&addr);
+ return gen_host(addr, mask, proto, dir);
+
+ case Q_DEFAULT:
+ case Q_HOST:
+ if (proto == Q_LINK) {
+ /* XXX Should lookup hw addr based on link layer */
+ eaddr = ETHER_hostton(name);
+ if (eaddr == 0)
+ error("unknown ether host '%s'", name);
+ return gen_ehostop(eaddr, dir);
+
+ } else {
+ alist = s_nametoaddr(name);
+ if (alist == 0 || *alist == 0)
+ error("uknown host '%s'", name);
+ b = gen_host(**alist++, 0xffffffffL, proto, dir);
+ while (*alist) {
+ tmp = gen_host(**alist++, 0xffffffffL,
+ proto, dir);
+ gen_or(b, tmp);
+ b = tmp;
+ }
+ return b;
+ }
+
+ case Q_PORT:
+ if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP)
+ error("illegal qualifier of 'port'");
+ if (s_nametoport(name, &port, &real_proto) == 0)
+ error("unknown port '%s'", name);
+ if (proto == Q_UDP) {
+ if (real_proto == IPPROTO_TCP)
+ error("port '%s' is tcp", name);
+ else
+ /* override PROTO_UNDEF */
+ real_proto = IPPROTO_UDP;
+ }
+ if (proto == Q_TCP) {
+ if (real_proto == IPPROTO_UDP)
+ error("port '%s' is udp", name);
+ else
+ /* override PROTO_UNDEF */
+ real_proto = IPPROTO_TCP;
+ }
+ return gen_port(port, real_proto, dir);
+
+ case Q_GATEWAY:
+ eaddr = ETHER_hostton(name);
+ if (eaddr == 0)
+ error("unknown ether host: %s", name);
+
+ alist = s_nametoaddr(name);
+ if (alist == 0 || *alist == 0)
+ error("uknown host '%s'", name);
+ return gen_gateway(eaddr, alist, proto, dir);
+
+ case Q_PROTO:
+ real_proto = lookup_proto(name, proto);
+ if (real_proto >= 0)
+ return gen_proto(real_proto, proto, dir);
+ else
+ error("unknown protocol: %s", name);
+
+ case Q_UNDEF:
+ syntax();
+ /* NOTREACHED */
+ }
+ abort();
+ /* NOTREACHED */
+}
+
+struct block *
+gen_ncode(v, q)
+ u_long v;
+ struct qual q;
+{
+ u_long mask;
+ int proto = q.proto;
+ int dir = q.dir;
+
+ switch (q.addr) {
+
+ case Q_DEFAULT:
+ case Q_HOST:
+ case Q_NET:
+ mask = net_mask(&v);
+ return gen_host(v, mask, proto, dir);
+
+ case Q_PORT:
+ if (proto == Q_UDP)
+ proto = IPPROTO_UDP;
+ else if (proto == Q_TCP)
+ proto = IPPROTO_TCP;
+ else if (proto == Q_DEFAULT)
+ proto = PROTO_UNDEF;
+ else
+ error("illegal qualifier of 'port'");
+
+ return gen_port((int)v, proto, dir);
+
+ case Q_GATEWAY:
+ error("'gateway' requires a name");
+ /* NOTREACHED */
+
+ case Q_PROTO:
+ return gen_proto((int)v, proto, dir);
+
+ case Q_UNDEF:
+ syntax();
+ /* NOTREACHED */
+ }
+ abort();
+ /* NOTREACHED */
+}
+
+struct block *
+gen_ecode(eaddr, q)
+ u_char *eaddr;
+ struct qual q;
+{
+ if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK)
+ return gen_ehostop(eaddr, (int)q.dir);
+ else
+ error("ethernet address used in non-ether expression");
+ /* NOTREACHED */
+}
+
+void
+sappend(s0, s1)
+ struct slist *s0, *s1;
+{
+ /*
+ * This is definitely not the best way to do this, but the
+ * lists will rarely get long.
+ */
+ while (s0->next)
+ s0 = s0->next;
+ s0->next = s1;
+}
+
+struct slist *
+xfer_to_x(a)
+ struct arth *a;
+{
+ struct slist *s;
+
+ s = new_stmt(BPF_LDX|BPF_MEM);
+ s->s.k = a->regno;
+ return s;
+}
+
+struct slist *
+xfer_to_a(a)
+ struct arth *a;
+{
+ struct slist *s;
+
+ s = new_stmt(BPF_LD|BPF_MEM);
+ s->s.k = a->regno;
+ return s;
+}
+
+struct arth *
+gen_load(proto, index, size)
+ int proto;
+ struct arth *index;
+ int size;
+{
+ struct slist *s, *tmp;
+ struct block *b;
+ int regno = alloc_reg();
+
+ free_reg(index->regno);
+ switch (size) {
+
+ default:
+ error("data size must be 1, 2, or 4");
+
+ case 1:
+ size = BPF_B;
+ break;
+
+ case 2:
+ size = BPF_H;
+ break;
+
+ case 4:
+ size = BPF_W;
+ break;
+ }
+ switch (proto) {
+ default:
+ error("unsupported index operation");
+
+ case Q_LINK:
+ s = xfer_to_x(index);
+ tmp = new_stmt(BPF_LD|BPF_IND|size);
+ sappend(s, tmp);
+ sappend(index->s, s);
+ break;
+
+ case Q_IP:
+ case Q_ARP:
+ case Q_RARP:
+ /* XXX Note that we assume a fixed link link header here. */
+ s = xfer_to_x(index);
+ tmp = new_stmt(BPF_LD|BPF_IND|size);
+ tmp->s.k = off_nl;
+ sappend(s, tmp);
+ sappend(index->s, s);
+
+ b = gen_proto_abbrev(proto);
+ if (index->b)
+ gen_and(index->b, b);
+ index->b = b;
+ break;
+
+ case Q_TCP:
+ case Q_UDP:
+ case Q_ICMP:
+ s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
+ s->s.k = off_nl;
+ sappend(s, xfer_to_a(index));
+ sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
+ sappend(s, new_stmt(BPF_MISC|BPF_TAX));
+ sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size));
+ tmp->s.k = off_nl;
+ sappend(index->s, s);
+
+ gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
+ if (index->b)
+ gen_and(index->b, b);
+ index->b = b;
+ break;
+ }
+ index->regno = regno;
+ s = new_stmt(BPF_ST);
+ s->s.k = regno;
+ sappend(index->s, s);
+
+ return index;
+}
+
+struct block *
+gen_relation(code, a0, a1, reversed)
+ int code;
+ struct arth *a0, *a1;
+ int reversed;
+{
+ struct slist *s0, *s1, *s2;
+ struct block *b, *tmp;
+
+ s0 = xfer_to_x(a1);
+ s1 = xfer_to_a(a0);
+ s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X);
+ b = new_block(JMP(code));
+ if (reversed)
+ gen_not(b);
+
+ sappend(s1, s2);
+ sappend(s0, s1);
+ sappend(a1->s, s0);
+ sappend(a0->s, a1->s);
+
+ b->stmts = a0->s;
+
+ free_reg(a0->regno);
+ free_reg(a1->regno);
+
+ /* 'and' together protocol checks */
+ if (a0->b) {
+ if (a1->b) {
+ gen_and(a0->b, tmp = a1->b);
+ }
+ else
+ tmp = a0->b;
+ } else
+ tmp = a1->b;
+
+ if (tmp)
+ gen_and(tmp, b);
+
+ return b;
+}
+
+struct arth *
+gen_loadlen()
+{
+ int regno = alloc_reg();
+ struct arth *a = (struct arth *)newchunk(sizeof(*a));
+ struct slist *s;
+
+ s = new_stmt(BPF_LD|BPF_LEN);
+ s->next = new_stmt(BPF_ST);
+ s->next->s.k = regno;
+ a->s = s;
+ a->regno = regno;
+
+ return a;
+}
+
+struct arth *
+gen_loadi(val)
+ int val;
+{
+ struct arth *a;
+ struct slist *s;
+ int reg;
+
+ a = (struct arth *)newchunk(sizeof(*a));
+
+ reg = alloc_reg();
+
+ s = new_stmt(BPF_LD|BPF_IMM);
+ s->s.k = val;
+ s->next = new_stmt(BPF_ST);
+ s->next->s.k = reg;
+ a->s = s;
+ a->regno = reg;
+
+ return a;
+}
+
+struct arth *
+gen_neg(a)
+ struct arth *a;
+{
+ struct slist *s;
+
+ s = xfer_to_a(a);
+ sappend(a->s, s);
+ s = new_stmt(BPF_ALU|BPF_NEG);
+ s->s.k = 0;
+ sappend(a->s, s);
+ s = new_stmt(BPF_ST);
+ s->s.k = a->regno;
+ sappend(a->s, s);
+
+ return a;
+}
+
+struct arth *
+gen_arth(code, a0, a1)
+ int code;
+ struct arth *a0, *a1;
+{
+ struct slist *s0, *s1, *s2;
+
+ s0 = xfer_to_x(a1);
+ s1 = xfer_to_a(a0);
+ s2 = new_stmt(BPF_ALU|BPF_X|code);
+
+ sappend(s1, s2);
+ sappend(s0, s1);
+ sappend(a1->s, s0);
+ sappend(a0->s, a1->s);
+
+ free_reg(a1->regno);
+
+ s0 = new_stmt(BPF_ST);
+ a0->regno = s0->s.k = alloc_reg();
+ sappend(a0->s, s0);
+
+ return a0;
+}
+
+/*
+ * Here we handle simple allocation of the scratch registers.
+ * If too many registers are alloc'd, the allocator punts.
+ */
+static int regused[BPF_MEMWORDS];
+static int curreg;
+
+/*
+ * Return the next free register.
+ */
+static int
+alloc_reg()
+{
+ int n = BPF_MEMWORDS;
+
+ while (--n >= 0) {
+ if (regused[curreg])
+ curreg = (curreg + 1) % BPF_MEMWORDS;
+ else {
+ regused[curreg] = 1;
+ return curreg;
+ }
+ }
+ error("too many registers needed to evaluate expression");
+ /* NOTREACHED */
+}
+
+/*
+ * Return a register to the table so it can
+ * be used later.
+ */
+static void
+free_reg(n)
+ int n;
+{
+ regused[n] = 0;
+}
+
+static struct block *
+gen_len(jmp, n)
+ int jmp;
+ int n;
+{
+ struct slist *s;
+ struct block *b;
+
+ s = new_stmt(BPF_LD|BPF_LEN);
+ s->next = new_stmt(BPF_SUB|BPF_IMM);
+ s->next->s.k = n;
+ b = new_block(JMP(jmp));
+ b->stmts = s;
+
+ return b;
+}
+
+struct block *
+gen_greater(n)
+ int n;
+{
+ return gen_len(BPF_JGE, n);
+}
+
+struct block *
+gen_less(n)
+ int n;
+{
+ struct block *b;
+
+ b = gen_len(BPF_JGT, n);
+ gen_not(b);
+
+ return b;
+}
+
+struct block *
+gen_byteop(op, idx, val)
+ int op;
+ int idx;
+ int val;
+{
+ struct block *b;
+ struct slist *s;
+
+ switch (op) {
+ default:
+ abort();
+
+ case '=':
+ return gen_cmp((u_int)idx, BPF_B, (long)val);
+
+ case '<':
+ b = gen_cmp((u_int)idx, BPF_B, (long)val);
+ b->s.code = JMP(BPF_JGE);
+ gen_not(b);
+ return b;
+
+ case '>':
+ b = gen_cmp((u_int)idx, BPF_B, (long)val);
+ b->s.code = JMP(BPF_JGT);
+ return b;
+
+ case '|':
+ s = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+ break;
+
+ case '&':
+ s = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+ break;
+ }
+ s->s.k = val;
+ b = new_block(JMP(BPF_JEQ));
+ b->stmts = s;
+ gen_not(b);
+
+ return b;
+}
+
+struct block *
+gen_broadcast(proto)
+ int proto;
+{
+ u_long hostmask;
+ struct block *b0, *b1, *b2;
+ static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+ switch (proto) {
+
+ case Q_DEFAULT:
+ case Q_LINK:
+ if (linktype == DLT_EN10MB)
+ return gen_ehostop(ebroadcast, Q_DST);
+ error("not a broadcast link");
+ break;
+
+ case Q_IP:
+ b0 = gen_linktype(ETHERTYPE_IP);
+ hostmask = ~netmask;
+ b1 = gen_mcmp(off_nl + 16, BPF_W, (long)0, hostmask);
+ b2 = gen_mcmp(off_nl + 16, BPF_W,
+ (long)(~0 & hostmask), hostmask);
+ gen_or(b1, b2);
+ gen_and(b0, b2);
+ return b2;
+ }
+ error("only ether/ip broadcast filters supported");
+}
+
+struct block *
+gen_multicast(proto)
+ int proto;
+{
+ register struct block *b0, *b1, *b2;
+ register struct slist *s;
+
+ switch (proto) {
+
+ case Q_DEFAULT:
+ case Q_LINK:
+ if (linktype != DLT_EN10MB)
+ break;
+
+ /* ether[0] & 1 != 0 */
+ s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+ s->s.k = 0;
+ b0 = new_block(JMP(BPF_JSET));
+ b0->s.k = 1;
+ b0->stmts = s;
+ return b0;
+
+ case Q_IP:
+ b0 = gen_linktype(ETHERTYPE_IP);
+ b1 = gen_cmp(off_nl + 16, BPF_B, (long)224);
+ b1->s.code = JMP(BPF_JGE);
+ gen_and(b0, b1);
+ return b1;
+ }
+ error("only ether/ip multicast filters supported");
+}
diff --git a/usr.sbin/tcpdump/tcpdump/gencode.h b/usr.sbin/tcpdump/tcpdump/gencode.h
new file mode 100644
index 000000000000..b8f342d6b629
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/gencode.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: gencode.h,v 1.14 92/02/14 15:18:55 mccanne Exp $ (LBL)
+ */
+
+/*
+ * filter.h must be included before this file.
+ */
+
+/* Address qualifers. */
+
+#define Q_HOST 1
+#define Q_NET 2
+#define Q_PORT 3
+#define Q_GATEWAY 4
+#define Q_PROTO 5
+
+/* Protocol qualifiers. */
+
+#define Q_LINK 1
+#define Q_IP 2
+#define Q_ARP 3
+#define Q_RARP 4
+#define Q_TCP 5
+#define Q_UDP 6
+#define Q_ICMP 7
+
+/* Directional qualifers. */
+
+#define Q_SRC 1
+#define Q_DST 2
+#define Q_OR 3
+#define Q_AND 4
+
+#define Q_DEFAULT 0
+#define Q_UNDEF 255
+
+struct stmt {
+ int code;
+ long k;
+};
+
+struct slist {
+ struct stmt s;
+ struct slist *next;
+};
+
+/*
+ * A bit vector to represent definition sets. We assume TOT_REGISTERS
+ * is smaller than 8*sizeof(atomset).
+ */
+typedef u_long atomset;
+#define ATOMMASK(n) (1 << (n))
+#define ATOMELEM(d, n) (d & ATOMMASK(n))
+
+/*
+ * An unbounded set.
+ */
+typedef u_long *uset;
+
+/*
+ * Total number of atomic entities, including accumulator (A) and index (X).
+ * We treat all these guys similarly during flow analysis.
+ */
+#define N_ATOMS (BPF_MEMWORDS+2)
+
+struct edge {
+ int id;
+ int code;
+ uset edom;
+ struct block *succ;
+ struct block *pred;
+ struct edge *next; /* link list of incoming edges for a node */
+};
+
+struct block {
+ int id;
+ struct slist *stmts; /* side effect stmts */
+ struct stmt s; /* branch stmt */
+ int mark;
+ int level;
+ int offset;
+ int sense;
+ struct edge et;
+ struct edge ef;
+ struct block *head;
+ struct block *link; /* link field used by optimizer */
+ uset dom;
+ uset closure;
+ struct edge *in_edges;
+ atomset def, kill;
+ atomset in_use;
+ atomset out_use;
+ long oval;
+ long val[N_ATOMS];
+};
+
+struct arth {
+ struct block *b; /* protocol checks */
+ struct slist *s; /* stmt list */
+ int regno; /* virtual register number of result */
+};
+
+extern struct arth *gen_loadi();
+extern struct arth *gen_load();
+extern struct arth *gen_loadlen();
+extern struct arth *gen_neg();
+extern struct arth *gen_arth();
+
+extern void gen_and();
+extern void gen_or();
+extern void gen_not();
+
+extern struct block *gen_scode();
+extern struct block *gen_ecode();
+extern struct block *gen_ncode();
+extern struct block *gen_proto_abbrev();
+extern struct block *gen_relation();
+extern struct block *gen_less();
+extern struct block *gen_greater();
+extern struct block *gen_byteop();
+extern struct block *gen_broadcast();
+extern struct block *gen_multicast();
+
+extern void optimize();
+
+extern void finish_parse();
+
+struct qual {
+ unsigned char addr;
+ unsigned char proto;
+ unsigned char dir;
+ unsigned char pad;
+};
+
+/* XXX */
+#define JT(b) ((b)->et.succ)
+#define JF(b) ((b)->ef.succ)
diff --git a/usr.sbin/tcpdump/tcpdump/inet.c b/usr.sbin/tcpdump/tcpdump/inet.c
new file mode 100644
index 000000000000..550129e1af55
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/inet.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#)$Header: inet.c,v 1.12 92/01/29 12:46:18 mccanne Exp $ (LBL)";
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include "interface.h"
+
+/* Not all systems have IFF_LOOPBACK */
+#ifdef IFF_LOOPBACK
+#define ISLOOPBACK(p) ((p)->ifr_flags & IFF_LOOPBACK)
+#else
+#define ISLOOPBACK(p) (strcmp((p)->ifr_name, "lo0") == 0)
+#endif
+
+/*
+ * Return the name of a network interface attached to the system, or 0
+ * if none can be found. The interface must be configured up; the
+ * lowest unit number is preferred; loopback is ignored.
+ */
+char *
+lookup_device()
+{
+ struct ifreq ibuf[16], *ifrp, *ifend, *mp;
+ struct ifconf ifc;
+ int fd;
+ int minunit, n;
+ char *cp;
+ static char device[sizeof(ifrp->ifr_name)];
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ perror("tcpdump: socket");
+ exit(1);
+ }
+ ifc.ifc_len = sizeof ibuf;
+ ifc.ifc_buf = (caddr_t)ibuf;
+
+ if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
+ ifc.ifc_len < sizeof(struct ifreq)) {
+ perror("tcpdump: SIOCGIFCONF: ");
+ exit(1);
+ }
+ ifrp = ibuf;
+ ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
+
+ mp = 0;
+ minunit = 666;
+ while (ifrp < ifend) {
+ struct ifreq ifr;
+ /*
+ * Need a template to preserve address info that is
+ * used below to locate the next entry. (Otherwise,
+ * SIOCGIFFLAGS stomps over it because the requests
+ * are returned in a union.)
+ */
+ bcopy(ifrp->ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name));
+ if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
+ fprintf(stderr, "tcpdump: SIOCGIFFLAGS: ");
+ perror(ifrp->ifr_name);
+ exit(1);
+ }
+ if ((ifr.ifr_flags & IFF_UP) && !ISLOOPBACK(&ifr)) {
+ for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp)
+ ;
+ n = atoi(cp);
+ if (n < minunit) {
+ minunit = n;
+ mp = ifrp;
+ }
+ }
+#if BSD >= 199006
+ n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
+ if (n < sizeof(*ifrp))
+ ++ifrp;
+ else
+ ifrp = (struct ifreq *)((char *)ifrp + n);
+#else
+ ++ifrp;
+#endif
+ }
+ close(fd);
+ if (mp == 0)
+ return (0);
+
+ (void)strcpy(device, mp->ifr_name);
+ return (device);
+}
+
+/*
+ * Get the netmask of an IP address. This routine is used if
+ * SIOCGIFNETMASK doesn't work.
+ */
+static u_long
+ipaddrtonetmask(addr)
+ u_long addr;
+{
+ if (IN_CLASSA(addr))
+ return (IN_CLASSA_NET);
+ if (IN_CLASSB(addr))
+ return (IN_CLASSB_NET);
+ if (IN_CLASSC(addr))
+ return (IN_CLASSC_NET);
+ error("unknown IP address class: %08X", addr);
+ /* NOTREACHED */
+}
+
+void
+lookup_net(device, netp, maskp)
+ char *device;
+ u_long *netp;
+ u_long *maskp;
+{
+ int fd;
+ struct ifreq ifr;
+ struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
+
+ /* Use data gram socket to get IP address. */
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("tcpdump: socket");
+ exit(1);
+ }
+ (void)strncpy(ifr.ifr_name, device, sizeof ifr.ifr_name);
+ if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
+ /*
+ * This will fail if an IP address hasn't been assigned.
+ */
+ *netp = 0;
+ *maskp = 0;
+ return;
+ }
+ *netp = sin->sin_addr.s_addr;
+ if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0)
+ *maskp = 0;
+ else
+ *maskp = sin->sin_addr.s_addr;
+ if (*maskp == 0)
+ *maskp = ipaddrtonetmask(*netp);
+ *netp &= *maskp;
+ (void)close(fd);
+}
diff --git a/usr.sbin/tcpdump/tcpdump/interface.h b/usr.sbin/tcpdump/tcpdump/interface.h
new file mode 100644
index 000000000000..dfccba6e6730
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/interface.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: interface.h,v 1.46 92/06/02 17:57:22 mccanne Exp $ (LBL)
+ */
+
+#ifdef __GNUC__
+#define inline __inline
+#else
+#define inline
+#endif
+
+#include "os.h" /* operating system stuff */
+#include "md.h" /* machine dependent stuff */
+
+#ifndef __STDC__
+extern char *malloc();
+extern char *calloc();
+#endif
+
+extern int dflag; /* print filter code */
+extern int eflag; /* print ethernet header */
+extern int nflag; /* leave addresses as numbers */
+extern int Nflag; /* remove domains from printed host names */
+extern int qflag; /* quick (shorter) output */
+extern int Sflag; /* print raw TCP sequence numbers */
+extern int tflag; /* print packet arrival time */
+extern int vflag; /* verbose */
+extern int xflag; /* print packet in hex */
+
+extern char *program_name; /* used to generate self-identifying messages */
+
+extern int snaplen;
+/* global pointers to beginning and end of current packet (during printing) */
+extern unsigned char *packetp;
+extern unsigned char *snapend;
+
+extern long thiszone; /* gmt to local correction */
+
+extern void ts_print();
+extern int clock_sigfigs();
+
+extern char *lookup_device();
+
+extern void error();
+extern void warning();
+
+extern char *read_infile();
+extern char *copy_argv();
+
+extern void usage();
+extern void show_code();
+extern void init_addrtoname();
+
+/* The printer routines. */
+
+extern void ether_if_print();
+extern void arp_print();
+extern void ip_print();
+extern void tcp_print();
+extern void udp_print();
+extern void icmp_print();
+extern void default_print();
+
+extern void ntp_print();
+extern void nfsreq_print();
+extern void nfsreply_print();
+extern void ns_print();
+extern void ddp_print();
+extern void rip_print();
+extern void tftp_print();
+extern void bootp_print();
+extern void snmp_print();
+extern void sl_if_print();
+extern void ppp_if_print();
+extern void fddi_if_print();
+extern void null_if_print();
+extern void egp_print();
+
+#define min(a,b) ((a)>(b)?(b):(a))
+#define max(a,b) ((b)>(a)?(b):(a))
+
+/*
+ * The default snapshot length. This value allows most printers to print
+ * useful information while keeping the amount of unwanted data down.
+ * In particular, it allows for an ethernet header, tcp/ip header, and
+ * 14 bytes of data (assuming no ip options).
+ */
+#define DEFAULT_SNAPLEN 68
+
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN 4321
+#define LITTLE_ENDIAN 1234
+#endif
diff --git a/usr.sbin/tcpdump/tcpdump/md.c b/usr.sbin/tcpdump/tcpdump/md.c
new file mode 100644
index 000000000000..6bb04b72cade
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/md.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: md-vax.c,v 1.3 90/10/03 14:14:33 mccanne Locked $ (LBL)";
+#endif
+
+/* Vaxen appear to have clocks accurate to 1 us,
+ but packetfilter is timestamping to 10 ms. */
+
+int
+clock_sigfigs()
+{
+ return 2;
+}
+
diff --git a/usr.sbin/tcpdump/tcpdump/md.h b/usr.sbin/tcpdump/tcpdump/md.h
new file mode 100644
index 000000000000..f83d81fcf0e0
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/md.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: md-vax.h,v 1.2 90/09/21 02:23:16 mccanne Exp $ (LBL)
+ */
+
+#ifndef BYTE_ORDER
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+/* These should be fixed to be real macros, for speed */
+
+#ifndef NTOHL
+#define NTOHL(x) (x) = ntohl(x)
+#define NTOHS(x) (x) = ntohs(x)
+#define HTONL(x) (x) = htonl(x)
+#define HTONS(x) (x) = htons(x)
+#endif
+
+#ifndef vax
+/* Some Ultrix header files may need this */
+#define vax 1
+#endif vax
diff --git a/usr.sbin/tcpdump/tcpdump/mib.h b/usr.sbin/tcpdump/tcpdump/mib.h
new file mode 100644
index 000000000000..a81897ce8b2a
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/mib.h
@@ -0,0 +1,1256 @@
+/*
+ * This file was generated by tcpdump/makemib on Wed Sep 26 12:12:31 EDT 1990
+ * You probably don't want to edit this by hand!
+ *
+ * struct mib somename = { desc, oid-octet, type, child-pointer, next-pointer
+};
+ */
+
+/* parse problem: new name "mib" for mgmt.mib(1) ignored */
+/* parse problem: no parent for 0.nullSpecific(0) */
+struct obj
+_proteon_obj = {
+ "proteon", 1, 0,
+ NULL, NULL
+},
+_ibm_obj = {
+ "ibm", 2, 0,
+ NULL, &_proteon_obj
+},
+_cmu_obj = {
+ "cmu", 3, 0,
+ NULL, &_ibm_obj
+},
+_unix_obj = {
+ "unix", 4, 0,
+ NULL, &_cmu_obj
+},
+_acc_obj = {
+ "acc", 5, 0,
+ NULL, &_unix_obj
+},
+_twg_obj = {
+ "twg", 6, 0,
+ NULL, &_acc_obj
+},
+_cayman_obj = {
+ "cayman", 7, 0,
+ NULL, &_twg_obj
+},
+_nysernet_obj = {
+ "nysernet", 8, 0,
+ NULL, &_cayman_obj
+},
+_cisco_obj = {
+ "cisco", 9, 0,
+ NULL, &_nysernet_obj
+},
+_nsc_obj = {
+ "nsc", 10, 0,
+ NULL, &_cisco_obj
+},
+_hp_obj = {
+ "hp", 11, 0,
+ NULL, &_nsc_obj
+},
+_epilogue_obj = {
+ "epilogue", 12, 0,
+ NULL, &_hp_obj
+},
+_utennessee_obj = {
+ "utennessee", 13, 0,
+ NULL, &_epilogue_obj
+},
+_bbn_obj = {
+ "bbn", 14, 0,
+ NULL, &_utennessee_obj
+},
+_xylogics_obj = {
+ "xylogics", 15, 0,
+ NULL, &_bbn_obj
+},
+_unisys_obj = {
+ "unisys", 16, 0,
+ NULL, &_xylogics_obj
+},
+_canstar_obj = {
+ "canstar", 17, 0,
+ NULL, &_unisys_obj
+},
+_wellfleet_obj = {
+ "wellfleet", 18, 0,
+ NULL, &_canstar_obj
+},
+_trw_obj = {
+ "trw", 19, 0,
+ NULL, &_wellfleet_obj
+},
+_mit_obj = {
+ "mit", 20, 0,
+ NULL, &_trw_obj
+},
+_eon_obj = {
+ "eon", 21, 0,
+ NULL, &_mit_obj
+},
+_spartacus_obj = {
+ "spartacus", 22, 0,
+ NULL, &_eon_obj
+},
+_excelan_obj = {
+ "excelan", 23, 0,
+ NULL, &_spartacus_obj
+},
+_spider_obj = {
+ "spider", 24, 0,
+ NULL, &_excelan_obj
+},
+_nsfnet_obj = {
+ "nsfnet", 25, 0,
+ NULL, &_spider_obj
+},
+_sytek_obj = {
+ "sytek", 26, 0,
+ NULL, &_nsfnet_obj
+},
+_intergraph_obj = {
+ "intergraph", 27, 0,
+ NULL, &_sytek_obj
+},
+_interlan_obj = {
+ "interlan", 28, 0,
+ NULL, &_intergraph_obj
+},
+_vitalink_obj = {
+ "vitalink", 29, 0,
+ NULL, &_interlan_obj
+},
+_ulana_obj = {
+ "ulana", 30, 0,
+ NULL, &_vitalink_obj
+},
+_nswc_obj = {
+ "nswc", 31, 0,
+ NULL, &_ulana_obj
+},
+_santacruzoperation_obj = {
+ "santacruzoperation", 32, 0,
+ NULL, &_nswc_obj
+},
+_xyplex_obj = {
+ "xyplex", 33, 0,
+ NULL, &_santacruzoperation_obj
+},
+_cray_obj = {
+ "cray", 34, 0,
+ NULL, &_xyplex_obj
+},
+_bellnorthernresearch_obj = {
+ "bellnorthernresearch", 35, 0,
+ NULL, &_cray_obj
+},
+_dec_obj = {
+ "dec", 36, 0,
+ NULL, &_bellnorthernresearch_obj
+},
+_touch_obj = {
+ "touch", 37, 0,
+ NULL, &_dec_obj
+},
+_networkresearchcorp_obj = {
+ "networkresearchcorp", 38, 0,
+ NULL, &_touch_obj
+},
+_baylor_obj = {
+ "baylor", 39, 0,
+ NULL, &_networkresearchcorp_obj
+},
+_nmfeccllnl_obj = {
+ "nmfeccllnl", 40, 0,
+ NULL, &_baylor_obj
+},
+_sri_obj = {
+ "sri", 41, 0,
+ NULL, &_nmfeccllnl_obj
+},
+_sun_obj = {
+ "sun", 42, 0,
+ NULL, &_sri_obj
+},
+_3com_obj = {
+ "3com", 43, 0,
+ NULL, &_sun_obj
+},
+_cmc_obj = {
+ "cmc", 44, 0,
+ NULL, &_3com_obj
+},
+_synoptics_obj = {
+ "synoptics", 45, 0,
+ NULL, &_cmc_obj
+},
+_cheyenne_obj = {
+ "cheyenne", 46, 0,
+ NULL, &_synoptics_obj
+},
+_prime_obj = {
+ "prime", 47, 0,
+ NULL, &_cheyenne_obj
+},
+_mcnc_obj = {
+ "mcnc", 48, 0,
+ NULL, &_prime_obj
+},
+_chipcom_obj = {
+ "chipcom", 49, 0,
+ NULL, &_mcnc_obj
+},
+_opticaldatasystems_obj = {
+ "opticaldatasystems", 50, 0,
+ NULL, &_chipcom_obj
+},
+_gated_obj = {
+ "gated", 51, 0,
+ NULL, &_opticaldatasystems_obj
+},
+_cabletron_obj = {
+ "cabletron", 52, 0,
+ NULL, &_gated_obj
+},
+_apollo_obj = {
+ "apollo", 53, 0,
+ NULL, &_cabletron_obj
+},
+_desktalksystems_obj = {
+ "desktalksystems", 54, 0,
+ NULL, &_apollo_obj
+},
+_ssds_obj = {
+ "ssds", 55, 0,
+ NULL, &_desktalksystems_obj
+},
+_castlerock_obj = {
+ "castlerock", 56, 0,
+ NULL, &_ssds_obj
+},
+_mips_obj = {
+ "mips", 57, 0,
+ NULL, &_castlerock_obj
+},
+_tgv_obj = {
+ "tgv", 58, 0,
+ NULL, &_mips_obj
+},
+_silicongraphics_obj = {
+ "silicongraphics", 59, 0,
+ NULL, &_tgv_obj
+},
+_ubc_obj = {
+ "ubc", 60, 0,
+ NULL, &_silicongraphics_obj
+},
+_merit_obj = {
+ "merit", 61, 0,
+ NULL, &_ubc_obj
+},
+_fibercom_obj = {
+ "fibercom", 62, 0,
+ NULL, &_merit_obj
+},
+_apple_obj = {
+ "apple", 63, 0,
+ NULL, &_fibercom_obj
+},
+_gandalf_obj = {
+ "gandalf", 64, 0,
+ NULL, &_apple_obj
+},
+_dartmouth_obj = {
+ "dartmouth", 65, 0,
+ NULL, &_gandalf_obj
+},
+_davidsystems_obj = {
+ "davidsystems", 66, 0,
+ NULL, &_dartmouth_obj
+},
+_reuter_obj = {
+ "reuter", 67, 0,
+ NULL, &_davidsystems_obj
+},
+_cornell_obj = {
+ "cornell", 68, 0,
+ NULL, &_reuter_obj
+},
+_tmac_obj = {
+ "tmac", 69, 0,
+ NULL, &_cornell_obj
+},
+_locus_obj = {
+ "locus", 70, 0,
+ NULL, &_tmac_obj
+},
+_nasa_obj = {
+ "nasa", 71, 0,
+ NULL, &_locus_obj
+},
+_retix_obj = {
+ "retix", 72, 0,
+ NULL, &_nasa_obj
+},
+_boeing_obj = {
+ "boeing", 73, 0,
+ NULL, &_retix_obj
+},
+_att_obj = {
+ "att", 74, 0,
+ NULL, &_boeing_obj
+},
+_ungermannbass_obj = {
+ "ungermannbass", 75, 0,
+ NULL, &_att_obj
+},
+_digitalanalysis_obj = {
+ "digitalanalysis", 76, 0,
+ NULL, &_ungermannbass_obj
+},
+_hplanman_obj = {
+ "hplanman", 77, 0,
+ NULL, &_digitalanalysis_obj
+},
+_netlabs_obj = {
+ "netlabs", 78, 0,
+ NULL, &_hplanman_obj
+},
+_icl_obj = {
+ "icl", 79, 0,
+ NULL, &_netlabs_obj
+},
+_auspex_obj = {
+ "auspex", 80, 0,
+ NULL, &_icl_obj
+},
+_lannet_obj = {
+ "lannet", 81, 0,
+ NULL, &_auspex_obj
+},
+_ncd_obj = {
+ "ncd", 82, 0,
+ NULL, &_lannet_obj
+},
+_raycom_obj = {
+ "raycom", 83, 0,
+ NULL, &_ncd_obj
+},
+_pirellifocom_obj = {
+ "pirellifocom", 84, 0,
+ NULL, &_raycom_obj
+},
+_datability_obj = {
+ "datability", 85, 0,
+ NULL, &_pirellifocom_obj
+},
+_networkappltech_obj = {
+ "networkappltech", 86, 0,
+ NULL, &_datability_obj
+},
+_link_obj = {
+ "link", 87, 0,
+ NULL, &_networkappltech_obj
+},
+_nyu_obj = {
+ "nyu", 88, 0,
+ NULL, &_link_obj
+},
+_rnd_obj = {
+ "rnd", 89, 0,
+ NULL, &_nyu_obj
+},
+_intercon_obj = {
+ "intercon", 90, 0,
+ NULL, &_rnd_obj
+},
+_learningtree_obj = {
+ "learningtree", 91, 0,
+ NULL, &_intercon_obj
+},
+_webstercomputer_obj = {
+ "webstercomputer", 92, 0,
+ NULL, &_learningtree_obj
+},
+_frontier_obj = {
+ "frontier", 93, 0,
+ NULL, &_webstercomputer_obj
+},
+_nokia_obj = {
+ "nokia", 94, 0,
+ NULL, &_frontier_obj
+},
+_allenbradley_obj = {
+ "allenbradley", 95, 0,
+ NULL, &_nokia_obj
+},
+_cern_obj = {
+ "cern", 96, 0,
+ NULL, &_allenbradley_obj
+},
+_sigma_obj = {
+ "sigma", 97, 0,
+ NULL, &_cern_obj
+},
+_emergingtech_obj = {
+ "emergingtech", 98, 0,
+ NULL, &_sigma_obj
+},
+_snmpresearch_obj = {
+ "snmpresearch", 99, 0,
+ NULL, &_emergingtech_obj
+},
+_ohiostate_obj = {
+ "ohiostate", 100, 0,
+ NULL, &_snmpresearch_obj
+},
+_ultra_obj = {
+ "ultra", 101, 0,
+ NULL, &_ohiostate_obj
+},
+_ccur_obj = {
+ "ccur", 136, 0,
+ NULL, &_ultra_obj
+},
+_enterprises_obj = {
+ "enterprises", 1, 0,
+ &_ccur_obj, NULL
+},
+_snmpInPkts_obj = {
+ "snmpInPkts", 1, 0,
+ NULL, NULL
+},
+_snmpOutPkts_obj = {
+ "snmpOutPkts", 2, 0,
+ NULL, &_snmpInPkts_obj
+},
+_snmpInBadVersions_obj = {
+ "snmpInBadVersions", 3, 0,
+ NULL, &_snmpOutPkts_obj
+},
+_snmpInBadCommunityNames_obj = {
+ "snmpInBadCommunityNames", 4, 0,
+ NULL, &_snmpInBadVersions_obj
+},
+_snmpInBadCommunityUses_obj = {
+ "snmpInBadCommunityUses", 5, 0,
+ NULL, &_snmpInBadCommunityNames_obj
+},
+_snmpInASNParseErrs_obj = {
+ "snmpInASNParseErrs", 6, 0,
+ NULL, &_snmpInBadCommunityUses_obj
+},
+_snmpInBadTypes_obj = {
+ "snmpInBadTypes", 7, 0,
+ NULL, &_snmpInASNParseErrs_obj
+},
+_snmpInTooBigs_obj = {
+ "snmpInTooBigs", 8, 0,
+ NULL, &_snmpInBadTypes_obj
+},
+_snmpInNoSuchNames_obj = {
+ "snmpInNoSuchNames", 9, 0,
+ NULL, &_snmpInTooBigs_obj
+},
+_snmpInBadValues_obj = {
+ "snmpInBadValues", 10, 0,
+ NULL, &_snmpInNoSuchNames_obj
+},
+_snmpInReadOnlys_obj = {
+ "snmpInReadOnlys", 11, 0,
+ NULL, &_snmpInBadValues_obj
+},
+_snmpInGenErrs_obj = {
+ "snmpInGenErrs", 12, 0,
+ NULL, &_snmpInReadOnlys_obj
+},
+_snmpInTotalReqVars_obj = {
+ "snmpInTotalReqVars", 13, 0,
+ NULL, &_snmpInGenErrs_obj
+},
+_snmpInTotalSetVars_obj = {
+ "snmpInTotalSetVars", 14, 0,
+ NULL, &_snmpInTotalReqVars_obj
+},
+_snmpInGetRequests_obj = {
+ "snmpInGetRequests", 15, 0,
+ NULL, &_snmpInTotalSetVars_obj
+},
+_snmpInGetNexts_obj = {
+ "snmpInGetNexts", 16, 0,
+ NULL, &_snmpInGetRequests_obj
+},
+_snmpInSetRequests_obj = {
+ "snmpInSetRequests", 17, 0,
+ NULL, &_snmpInGetNexts_obj
+},
+_snmpInGetResponses_obj = {
+ "snmpInGetResponses", 18, 0,
+ NULL, &_snmpInSetRequests_obj
+},
+_snmpInTraps_obj = {
+ "snmpInTraps", 19, 0,
+ NULL, &_snmpInGetResponses_obj
+},
+_snmpOutTooBigs_obj = {
+ "snmpOutTooBigs", 20, 0,
+ NULL, &_snmpInTraps_obj
+},
+_snmpOutNoSuchNames_obj = {
+ "snmpOutNoSuchNames", 21, 0,
+ NULL, &_snmpOutTooBigs_obj
+},
+_snmpOutBadValues_obj = {
+ "snmpOutBadValues", 22, 0,
+ NULL, &_snmpOutNoSuchNames_obj
+},
+_snmpOutReadOnlys_obj = {
+ "snmpOutReadOnlys", 23, 0,
+ NULL, &_snmpOutBadValues_obj
+},
+_snmpOutGenErrs_obj = {
+ "snmpOutGenErrs", 24, 0,
+ NULL, &_snmpOutReadOnlys_obj
+},
+_snmpOutGetRequests_obj = {
+ "snmpOutGetRequests", 25, 0,
+ NULL, &_snmpOutGenErrs_obj
+},
+_snmpOutGetNexts_obj = {
+ "snmpOutGetNexts", 26, 0,
+ NULL, &_snmpOutGetRequests_obj
+},
+_snmpOutSetRequests_obj = {
+ "snmpOutSetRequests", 27, 0,
+ NULL, &_snmpOutGetNexts_obj
+},
+_snmpOutGetResponses_obj = {
+ "snmpOutGetResponses", 28, 0,
+ NULL, &_snmpOutSetRequests_obj
+},
+_snmpOutTraps_obj = {
+ "snmpOutTraps", 29, 0,
+ NULL, &_snmpOutGetResponses_obj
+},
+_snmpEnableAuthTraps_obj = {
+ "snmpEnableAuthTraps", 30, 0,
+ NULL, &_snmpOutTraps_obj
+},
+_egpNeighState_obj = {
+ "egpNeighState", 1, 0,
+ NULL, NULL
+},
+_egpNeighAddr_obj = {
+ "egpNeighAddr", 2, 0,
+ NULL, &_egpNeighState_obj
+},
+_egpNeighAs_obj = {
+ "egpNeighAs", 3, 0,
+ NULL, &_egpNeighAddr_obj
+},
+_egpNeighInMsgs_obj = {
+ "egpNeighInMsgs", 4, 0,
+ NULL, &_egpNeighAs_obj
+},
+_egpNeighInErrs_obj = {
+ "egpNeighInErrs", 5, 0,
+ NULL, &_egpNeighInMsgs_obj
+},
+_egpNeighOutMsgs_obj = {
+ "egpNeighOutMsgs", 6, 0,
+ NULL, &_egpNeighInErrs_obj
+},
+_egpNeighOutErrs_obj = {
+ "egpNeighOutErrs", 7, 0,
+ NULL, &_egpNeighOutMsgs_obj
+},
+_egpNeighInErrMsgs_obj = {
+ "egpNeighInErrMsgs", 8, 0,
+ NULL, &_egpNeighOutErrs_obj
+},
+_egpNeighOutErrMsgs_obj = {
+ "egpNeighOutErrMsgs", 9, 0,
+ NULL, &_egpNeighInErrMsgs_obj
+},
+_egpNeighStateUps_obj = {
+ "egpNeighStateUps", 10, 0,
+ NULL, &_egpNeighOutErrMsgs_obj
+},
+_egpNeighStateDowns_obj = {
+ "egpNeighStateDowns", 11, 0,
+ NULL, &_egpNeighStateUps_obj
+},
+_egpNeighIntervalHello_obj = {
+ "egpNeighIntervalHello", 12, 0,
+ NULL, &_egpNeighStateDowns_obj
+},
+_egpNeighIntervalPoll_obj = {
+ "egpNeighIntervalPoll", 13, 0,
+ NULL, &_egpNeighIntervalHello_obj
+},
+_egpNeighMode_obj = {
+ "egpNeighMode", 14, 0,
+ NULL, &_egpNeighIntervalPoll_obj
+},
+_egpNeighEventTrigger_obj = {
+ "egpNeighEventTrigger", 15, 0,
+ NULL, &_egpNeighMode_obj
+},
+_egpNeighEntry_obj = {
+ "egpNeighEntry", 1, 0,
+ &_egpNeighEventTrigger_obj, NULL
+},
+_egpInMsgs_obj = {
+ "egpInMsgs", 1, 0,
+ NULL, NULL
+},
+_egpInErrors_obj = {
+ "egpInErrors", 2, 0,
+ NULL, &_egpInMsgs_obj
+},
+_egpOutMsgs_obj = {
+ "egpOutMsgs", 3, 0,
+ NULL, &_egpInErrors_obj
+},
+_egpOutErrors_obj = {
+ "egpOutErrors", 4, 0,
+ NULL, &_egpOutMsgs_obj
+},
+_egpNeighTable_obj = {
+ "egpNeighTable", 5, 0,
+ &_egpNeighEntry_obj, &_egpOutErrors_obj
+},
+_egpAs_obj = {
+ "egpAs", 6, 0,
+ NULL, &_egpNeighTable_obj
+},
+_udpLocalAddress_obj = {
+ "udpLocalAddress", 1, 0,
+ NULL, NULL
+},
+_udpLocalPort_obj = {
+ "udpLocalPort", 2, 0,
+ NULL, &_udpLocalAddress_obj
+},
+_udpEntry_obj = {
+ "udpEntry", 1, 0,
+ &_udpLocalPort_obj, NULL
+},
+_udpInDatagrams_obj = {
+ "udpInDatagrams", 1, 0,
+ NULL, NULL
+},
+_udpNoPorts_obj = {
+ "udpNoPorts", 2, 0,
+ NULL, &_udpInDatagrams_obj
+},
+_udpInErrors_obj = {
+ "udpInErrors", 3, 0,
+ NULL, &_udpNoPorts_obj
+},
+_udpOutDatagrams_obj = {
+ "udpOutDatagrams", 4, 0,
+ NULL, &_udpInErrors_obj
+},
+_udpTable_obj = {
+ "udpTable", 5, 0,
+ &_udpEntry_obj, &_udpOutDatagrams_obj
+},
+_tcpConnState_obj = {
+ "tcpConnState", 1, 0,
+ NULL, NULL
+},
+_tcpConnLocalAddress_obj = {
+ "tcpConnLocalAddress", 2, 0,
+ NULL, &_tcpConnState_obj
+},
+_tcpConnLocalPort_obj = {
+ "tcpConnLocalPort", 3, 0,
+ NULL, &_tcpConnLocalAddress_obj
+},
+_tcpConnRemAddress_obj = {
+ "tcpConnRemAddress", 4, 0,
+ NULL, &_tcpConnLocalPort_obj
+},
+_tcpConnRemPort_obj = {
+ "tcpConnRemPort", 5, 0,
+ NULL, &_tcpConnRemAddress_obj
+},
+_tcpConnEntry_obj = {
+ "tcpConnEntry", 1, 0,
+ &_tcpConnRemPort_obj, NULL
+},
+_tcpRtoAlgorithm_obj = {
+ "tcpRtoAlgorithm", 1, 0,
+ NULL, NULL
+},
+_tcpRtoMin_obj = {
+ "tcpRtoMin", 2, 0,
+ NULL, &_tcpRtoAlgorithm_obj
+},
+_tcpRtoMax_obj = {
+ "tcpRtoMax", 3, 0,
+ NULL, &_tcpRtoMin_obj
+},
+_tcpMaxConn_obj = {
+ "tcpMaxConn", 4, 0,
+ NULL, &_tcpRtoMax_obj
+},
+_tcpActiveOpens_obj = {
+ "tcpActiveOpens", 5, 0,
+ NULL, &_tcpMaxConn_obj
+},
+_tcpPassiveOpens_obj = {
+ "tcpPassiveOpens", 6, 0,
+ NULL, &_tcpActiveOpens_obj
+},
+_tcpAttemptFails_obj = {
+ "tcpAttemptFails", 7, 0,
+ NULL, &_tcpPassiveOpens_obj
+},
+_tcpEstabResets_obj = {
+ "tcpEstabResets", 8, 0,
+ NULL, &_tcpAttemptFails_obj
+},
+_tcpCurrEstab_obj = {
+ "tcpCurrEstab", 9, 0,
+ NULL, &_tcpEstabResets_obj
+},
+_tcpInSegs_obj = {
+ "tcpInSegs", 10, 0,
+ NULL, &_tcpCurrEstab_obj
+},
+_tcpOutSegs_obj = {
+ "tcpOutSegs", 11, 0,
+ NULL, &_tcpInSegs_obj
+},
+_tcpRetransSegs_obj = {
+ "tcpRetransSegs", 12, 0,
+ NULL, &_tcpOutSegs_obj
+},
+_tcpConnTable_obj = {
+ "tcpConnTable", 13, 0,
+ &_tcpConnEntry_obj, &_tcpRetransSegs_obj
+},
+_tcpInErrs_obj = {
+ "tcpInErrs", 14, 0,
+ NULL, &_tcpConnTable_obj
+},
+_tcpOutRsts_obj = {
+ "tcpOutRsts", 15, 0,
+ NULL, &_tcpInErrs_obj
+},
+_icmpInMsgs_obj = {
+ "icmpInMsgs", 1, 0,
+ NULL, NULL
+},
+_icmpInErrors_obj = {
+ "icmpInErrors", 2, 0,
+ NULL, &_icmpInMsgs_obj
+},
+_icmpInDestUnreachs_obj = {
+ "icmpInDestUnreachs", 3, 0,
+ NULL, &_icmpInErrors_obj
+},
+_icmpInTimeExcds_obj = {
+ "icmpInTimeExcds", 4, 0,
+ NULL, &_icmpInDestUnreachs_obj
+},
+_icmpInParmProbs_obj = {
+ "icmpInParmProbs", 5, 0,
+ NULL, &_icmpInTimeExcds_obj
+},
+_icmpInSrcQuenchs_obj = {
+ "icmpInSrcQuenchs", 6, 0,
+ NULL, &_icmpInParmProbs_obj
+},
+_icmpInRedirects_obj = {
+ "icmpInRedirects", 7, 0,
+ NULL, &_icmpInSrcQuenchs_obj
+},
+_icmpInEchos_obj = {
+ "icmpInEchos", 8, 0,
+ NULL, &_icmpInRedirects_obj
+},
+_icmpInEchoReps_obj = {
+ "icmpInEchoReps", 9, 0,
+ NULL, &_icmpInEchos_obj
+},
+_icmpInTimestamps_obj = {
+ "icmpInTimestamps", 10, 0,
+ NULL, &_icmpInEchoReps_obj
+},
+_icmpInTimestampReps_obj = {
+ "icmpInTimestampReps", 11, 0,
+ NULL, &_icmpInTimestamps_obj
+},
+_icmpInAddrMasks_obj = {
+ "icmpInAddrMasks", 12, 0,
+ NULL, &_icmpInTimestampReps_obj
+},
+_icmpInAddrMaskReps_obj = {
+ "icmpInAddrMaskReps", 13, 0,
+ NULL, &_icmpInAddrMasks_obj
+},
+_icmpOutMsgs_obj = {
+ "icmpOutMsgs", 14, 0,
+ NULL, &_icmpInAddrMaskReps_obj
+},
+_icmpOutErrors_obj = {
+ "icmpOutErrors", 15, 0,
+ NULL, &_icmpOutMsgs_obj
+},
+_icmpOutDestUnreachs_obj = {
+ "icmpOutDestUnreachs", 16, 0,
+ NULL, &_icmpOutErrors_obj
+},
+_icmpOutTimeExcds_obj = {
+ "icmpOutTimeExcds", 17, 0,
+ NULL, &_icmpOutDestUnreachs_obj
+},
+_icmpOutParmProbs_obj = {
+ "icmpOutParmProbs", 18, 0,
+ NULL, &_icmpOutTimeExcds_obj
+},
+_icmpOutSrcQuenchs_obj = {
+ "icmpOutSrcQuenchs", 19, 0,
+ NULL, &_icmpOutParmProbs_obj
+},
+_icmpOutRedirects_obj = {
+ "icmpOutRedirects", 20, 0,
+ NULL, &_icmpOutSrcQuenchs_obj
+},
+_icmpOutEchos_obj = {
+ "icmpOutEchos", 21, 0,
+ NULL, &_icmpOutRedirects_obj
+},
+_icmpOutEchoReps_obj = {
+ "icmpOutEchoReps", 22, 0,
+ NULL, &_icmpOutEchos_obj
+},
+_icmpOutTimestamps_obj = {
+ "icmpOutTimestamps", 23, 0,
+ NULL, &_icmpOutEchoReps_obj
+},
+_icmpOutTimestampReps_obj = {
+ "icmpOutTimestampReps", 24, 0,
+ NULL, &_icmpOutTimestamps_obj
+},
+_icmpOutAddrMasks_obj = {
+ "icmpOutAddrMasks", 25, 0,
+ NULL, &_icmpOutTimestampReps_obj
+},
+_icmpOutAddrMaskReps_obj = {
+ "icmpOutAddrMaskReps", 26, 0,
+ NULL, &_icmpOutAddrMasks_obj
+},
+_ipNetToMediaIfIndex_obj = {
+ "ipNetToMediaIfIndex", 1, 0,
+ NULL, NULL
+},
+_ipNetToMediaPhysAddress_obj = {
+ "ipNetToMediaPhysAddress", 2, 0,
+ NULL, &_ipNetToMediaIfIndex_obj
+},
+_ipNetToMediaNetAddress_obj = {
+ "ipNetToMediaNetAddress", 3, 0,
+ NULL, &_ipNetToMediaPhysAddress_obj
+},
+_ipNetToMediaType_obj = {
+ "ipNetToMediaType", 4, 0,
+ NULL, &_ipNetToMediaNetAddress_obj
+},
+_ipNetToMediaEntry_obj = {
+ "ipNetToMediaEntry", 1, 0,
+ &_ipNetToMediaType_obj, NULL
+},
+_ipRouteDest_obj = {
+ "ipRouteDest", 1, 0,
+ NULL, NULL
+},
+_ipRouteIfIndex_obj = {
+ "ipRouteIfIndex", 2, 0,
+ NULL, &_ipRouteDest_obj
+},
+_ipRouteMetric1_obj = {
+ "ipRouteMetric1", 3, 0,
+ NULL, &_ipRouteIfIndex_obj
+},
+_ipRouteMetric2_obj = {
+ "ipRouteMetric2", 4, 0,
+ NULL, &_ipRouteMetric1_obj
+},
+_ipRouteMetric3_obj = {
+ "ipRouteMetric3", 5, 0,
+ NULL, &_ipRouteMetric2_obj
+},
+_ipRouteMetric4_obj = {
+ "ipRouteMetric4", 6, 0,
+ NULL, &_ipRouteMetric3_obj
+},
+_ipRouteNextHop_obj = {
+ "ipRouteNextHop", 7, 0,
+ NULL, &_ipRouteMetric4_obj
+},
+_ipRouteType_obj = {
+ "ipRouteType", 8, 0,
+ NULL, &_ipRouteNextHop_obj
+},
+_ipRouteProto_obj = {
+ "ipRouteProto", 9, 0,
+ NULL, &_ipRouteType_obj
+},
+_ipRouteAge_obj = {
+ "ipRouteAge", 10, 0,
+ NULL, &_ipRouteProto_obj
+},
+_ipRouteMask_obj = {
+ "ipRouteMask", 11, 0,
+ NULL, &_ipRouteAge_obj
+},
+_ipRouteEntry_obj = {
+ "ipRouteEntry", 1, 0,
+ &_ipRouteMask_obj, NULL
+},
+_ipAdEntAddr_obj = {
+ "ipAdEntAddr", 1, 0,
+ NULL, NULL
+},
+_ipAdEntIfIndex_obj = {
+ "ipAdEntIfIndex", 2, 0,
+ NULL, &_ipAdEntAddr_obj
+},
+_ipAdEntNetMask_obj = {
+ "ipAdEntNetMask", 3, 0,
+ NULL, &_ipAdEntIfIndex_obj
+},
+_ipAdEntBcastAddr_obj = {
+ "ipAdEntBcastAddr", 4, 0,
+ NULL, &_ipAdEntNetMask_obj
+},
+_ipAdEntReasmMaxSize_obj = {
+ "ipAdEntReasmMaxSize", 5, 0,
+ NULL, &_ipAdEntBcastAddr_obj
+},
+_ipAddrEntry_obj = {
+ "ipAddrEntry", 1, 0,
+ &_ipAdEntReasmMaxSize_obj, NULL
+},
+_ipForwarding_obj = {
+ "ipForwarding", 1, 0,
+ NULL, NULL
+},
+_ipDefaultTTL_obj = {
+ "ipDefaultTTL", 2, 0,
+ NULL, &_ipForwarding_obj
+},
+_ipInReceives_obj = {
+ "ipInReceives", 3, 0,
+ NULL, &_ipDefaultTTL_obj
+},
+_ipInHdrErrors_obj = {
+ "ipInHdrErrors", 4, 0,
+ NULL, &_ipInReceives_obj
+},
+_ipInAddrErrors_obj = {
+ "ipInAddrErrors", 5, 0,
+ NULL, &_ipInHdrErrors_obj
+},
+_ipForwDatagrams_obj = {
+ "ipForwDatagrams", 6, 0,
+ NULL, &_ipInAddrErrors_obj
+},
+_ipInUnknownProtos_obj = {
+ "ipInUnknownProtos", 7, 0,
+ NULL, &_ipForwDatagrams_obj
+},
+_ipInDiscards_obj = {
+ "ipInDiscards", 8, 0,
+ NULL, &_ipInUnknownProtos_obj
+},
+_ipInDelivers_obj = {
+ "ipInDelivers", 9, 0,
+ NULL, &_ipInDiscards_obj
+},
+_ipOutRequests_obj = {
+ "ipOutRequests", 10, 0,
+ NULL, &_ipInDelivers_obj
+},
+_ipOutDiscards_obj = {
+ "ipOutDiscards", 11, 0,
+ NULL, &_ipOutRequests_obj
+},
+_ipOutNoRoutes_obj = {
+ "ipOutNoRoutes", 12, 0,
+ NULL, &_ipOutDiscards_obj
+},
+_ipReasmTimeout_obj = {
+ "ipReasmTimeout", 13, 0,
+ NULL, &_ipOutNoRoutes_obj
+},
+_ipReasmReqds_obj = {
+ "ipReasmReqds", 14, 0,
+ NULL, &_ipReasmTimeout_obj
+},
+_ipReasmOKs_obj = {
+ "ipReasmOKs", 15, 0,
+ NULL, &_ipReasmReqds_obj
+},
+_ipReasmFails_obj = {
+ "ipReasmFails", 16, 0,
+ NULL, &_ipReasmOKs_obj
+},
+_ipFragOKs_obj = {
+ "ipFragOKs", 17, 0,
+ NULL, &_ipReasmFails_obj
+},
+_ipFragFails_obj = {
+ "ipFragFails", 18, 0,
+ NULL, &_ipFragOKs_obj
+},
+_ipFragCreates_obj = {
+ "ipFragCreates", 19, 0,
+ NULL, &_ipFragFails_obj
+},
+_ipAddrTable_obj = {
+ "ipAddrTable", 20, 0,
+ &_ipAddrEntry_obj, &_ipFragCreates_obj
+},
+_ipRoutingTable_obj = {
+ "ipRoutingTable", 21, 0,
+ &_ipRouteEntry_obj, &_ipAddrTable_obj
+},
+_ipNetToMediaTable_obj = {
+ "ipNetToMediaTable", 22, 0,
+ &_ipNetToMediaEntry_obj, &_ipRoutingTable_obj
+},
+_atIfIndex_obj = {
+ "atIfIndex", 1, 0,
+ NULL, NULL
+},
+_atPhysAddress_obj = {
+ "atPhysAddress", 2, 0,
+ NULL, &_atIfIndex_obj
+},
+_atNetAddress_obj = {
+ "atNetAddress", 3, 0,
+ NULL, &_atPhysAddress_obj
+},
+_atEntry_obj = {
+ "atEntry", 1, 0,
+ &_atNetAddress_obj, NULL
+},
+_atTable_obj = {
+ "atTable", 1, 0,
+ &_atEntry_obj, NULL
+},
+_ifIndex_obj = {
+ "ifIndex", 1, 0,
+ NULL, NULL
+},
+_ifDescr_obj = {
+ "ifDescr", 2, 0,
+ NULL, &_ifIndex_obj
+},
+_ifType_obj = {
+ "ifType", 3, 0,
+ NULL, &_ifDescr_obj
+},
+_ifMtu_obj = {
+ "ifMtu", 4, 0,
+ NULL, &_ifType_obj
+},
+_ifSpeed_obj = {
+ "ifSpeed", 5, 0,
+ NULL, &_ifMtu_obj
+},
+_ifPhysAddress_obj = {
+ "ifPhysAddress", 6, 0,
+ NULL, &_ifSpeed_obj
+},
+_ifAdminStatus_obj = {
+ "ifAdminStatus", 7, 0,
+ NULL, &_ifPhysAddress_obj
+},
+_ifOperStatus_obj = {
+ "ifOperStatus", 8, 0,
+ NULL, &_ifAdminStatus_obj
+},
+_ifLastChange_obj = {
+ "ifLastChange", 9, 0,
+ NULL, &_ifOperStatus_obj
+},
+_ifInOctets_obj = {
+ "ifInOctets", 10, 0,
+ NULL, &_ifLastChange_obj
+},
+_ifInUcastPkts_obj = {
+ "ifInUcastPkts", 11, 0,
+ NULL, &_ifInOctets_obj
+},
+_ifInNUcastPkts_obj = {
+ "ifInNUcastPkts", 12, 0,
+ NULL, &_ifInUcastPkts_obj
+},
+_ifInDiscards_obj = {
+ "ifInDiscards", 13, 0,
+ NULL, &_ifInNUcastPkts_obj
+},
+_ifInErrors_obj = {
+ "ifInErrors", 14, 0,
+ NULL, &_ifInDiscards_obj
+},
+_ifInUnknownProtos_obj = {
+ "ifInUnknownProtos", 15, 0,
+ NULL, &_ifInErrors_obj
+},
+_ifOutOctets_obj = {
+ "ifOutOctets", 16, 0,
+ NULL, &_ifInUnknownProtos_obj
+},
+_ifOutUcastPkts_obj = {
+ "ifOutUcastPkts", 17, 0,
+ NULL, &_ifOutOctets_obj
+},
+_ifOutNUcastPkts_obj = {
+ "ifOutNUcastPkts", 18, 0,
+ NULL, &_ifOutUcastPkts_obj
+},
+_ifOutDiscards_obj = {
+ "ifOutDiscards", 19, 0,
+ NULL, &_ifOutNUcastPkts_obj
+},
+_ifOutErrors_obj = {
+ "ifOutErrors", 20, 0,
+ NULL, &_ifOutDiscards_obj
+},
+_ifOutQLen_obj = {
+ "ifOutQLen", 21, 0,
+ NULL, &_ifOutErrors_obj
+},
+_ifSpecific_obj = {
+ "ifSpecific", 22, 0,
+ NULL, &_ifOutQLen_obj
+},
+_ifEntry_obj = {
+ "ifEntry", 1, 0,
+ &_ifSpecific_obj, NULL
+},
+_ifNumber_obj = {
+ "ifNumber", 1, 0,
+ NULL, NULL
+},
+_ifTable_obj = {
+ "ifTable", 2, 0,
+ &_ifEntry_obj, &_ifNumber_obj
+},
+_sysDescr_obj = {
+ "sysDescr", 1, 0,
+ NULL, NULL
+},
+_sysObjectID_obj = {
+ "sysObjectID", 2, 0,
+ NULL, &_sysDescr_obj
+},
+_sysUpTime_obj = {
+ "sysUpTime", 3, 0,
+ NULL, &_sysObjectID_obj
+},
+_sysContact_obj = {
+ "sysContact", 4, 0,
+ NULL, &_sysUpTime_obj
+},
+_sysName_obj = {
+ "sysName", 5, 0,
+ NULL, &_sysContact_obj
+},
+_sysLocation_obj = {
+ "sysLocation", 6, 0,
+ NULL, &_sysName_obj
+},
+_sysServices_obj = {
+ "sysServices", 7, 0,
+ NULL, &_sysLocation_obj
+},
+_system_obj = {
+ "system", 1, 0,
+ &_sysServices_obj, NULL
+},
+_interfaces_obj = {
+ "interfaces", 2, 0,
+ &_ifTable_obj, &_system_obj
+},
+_at_obj = {
+ "at", 3, 0,
+ &_atTable_obj, &_interfaces_obj
+},
+_ip_obj = {
+ "ip", 4, 0,
+ &_ipNetToMediaTable_obj, &_at_obj
+},
+_icmp_obj = {
+ "icmp", 5, 0,
+ &_icmpOutAddrMaskReps_obj, &_ip_obj
+},
+_tcp_obj = {
+ "tcp", 6, 0,
+ &_tcpOutRsts_obj, &_icmp_obj
+},
+_udp_obj = {
+ "udp", 7, 0,
+ &_udpTable_obj, &_tcp_obj
+},
+_egp_obj = {
+ "egp", 8, 0,
+ &_egpAs_obj, &_udp_obj
+},
+_transmission_obj = {
+ "transmission", 10, 0,
+ NULL, &_egp_obj
+},
+_snmp_obj = {
+ "snmp", 11, 0,
+ &_snmpEnableAuthTraps_obj, &_transmission_obj
+},
+_mib_obj = {
+ "mib", 1, 0,
+ &_snmp_obj, NULL
+},
+_directory_obj = {
+ "directory", 1, 0,
+ NULL, NULL
+},
+_mgmt_obj = {
+ "mgmt", 2, 0,
+ &_mib_obj, &_directory_obj
+},
+_experimental_obj = {
+ "experimental", 3, 0,
+ NULL, &_mgmt_obj
+},
+_private_obj = {
+ "private", 4, 0,
+ &_enterprises_obj, &_experimental_obj
+},
+_internet_obj = {
+ "internet", 1, 0,
+ &_private_obj, NULL
+},
+_dod_obj = {
+ "dod", 6, 0,
+ &_internet_obj, NULL
+},
+_org_obj = {
+ "org", 3, 0,
+ &_dod_obj, NULL
+},
+_iso_obj = {
+ "iso", 1, 0,
+ &_org_obj, NULL
+},
+*mibroot = &_iso_obj;
diff --git a/usr.sbin/tcpdump/tcpdump/nametoaddr.c b/usr.sbin/tcpdump/tcpdump/nametoaddr.c
new file mode 100644
index 000000000000..6f2330f141c1
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/nametoaddr.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Name to id translation routines used by the scanner.
+ * These functions are not time critical.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: nametoaddr.c,v 1.9 91/02/04 16:56:46 mccanne Exp $ (LBL)";
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+#ifdef ultrix
+#include <sys/time.h>
+#include <rpc/types.h>
+#include <nfs/nfs.h>
+#endif
+
+#include "interface.h"
+#include "etherent.h"
+#include "nametoaddr.h"
+
+/*
+ * Convert host name to internet address.
+ * Return 0 upon failure.
+ */
+u_long **
+s_nametoaddr(name)
+ char *name;
+{
+#ifndef h_addr
+ static u_long *hlist[2];
+#endif
+ u_long **p;
+ struct hostent *hp;
+
+ if (hp = gethostbyname(name)) {
+#ifndef h_addr
+ hlist[0] = (u_long *)hp->h_addr;
+ NTOHL(hp->h_addr);
+ return hlist;
+#else
+ for (p = (u_long **)hp->h_addr_list; *p; ++p)
+ NTOHL(**p);
+ return (u_long **)hp->h_addr_list;
+#endif
+ }
+ else
+ return 0;
+}
+
+/*
+ * Convert net name to internet address.
+ * Return 0 upon failure.
+ */
+u_long
+s_nametonetaddr(name)
+ char *name;
+{
+ struct netent *np;
+
+ if (np = getnetbyname(name))
+ return np->n_net;
+ else
+ return 0;
+}
+
+/*
+ * Convert a port name to its port and protocol numbers.
+ * We assume only TCP or UDP.
+ * Return 0 upon failure.
+ */
+s_nametoport(name, port, proto)
+ char *name;
+ int *port;
+ int *proto;
+{
+ struct servent *sp;
+ char *other;
+
+ sp = getservbyname(name, (char *)0);
+ if (sp != 0) {
+ NTOHS(sp->s_port);
+ *port = sp->s_port;
+ *proto = s_nametoproto(sp->s_proto);
+ /*
+ * We need to check /etc/services for ambiguous entries.
+ * If we find the ambiguous entry, and it has the
+ * same port number, change the proto to PROTO_UNDEF
+ * so both TCP and UDP will be checked.
+ */
+ if (*proto == IPPROTO_TCP)
+ other = "udp";
+ else
+ other = "tcp";
+
+ sp = getservbyname(name, other);
+ if (sp != 0) {
+ NTOHS(sp->s_port);
+ if (*port != sp->s_port)
+ /* Can't handle ambigous names that refer
+ to different port numbers. */
+ warning("ambiguous port %s in /etc/services",
+ name);
+ *proto = PROTO_UNDEF;
+ }
+ return 1;
+ }
+#ifdef ultrix
+ /* Special hack in case NFS isn't in /etc/services */
+ if (strcmp(name, "nfs") == 0) {
+ *port = NFS_PORT;
+ *proto = PROTO_UNDEF;
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+int
+s_nametoproto(str)
+ char *str;
+{
+ struct protoent *p;
+
+ p = getprotobyname(str);
+ if (p != 0)
+ return p->p_proto;
+ else
+ return PROTO_UNDEF;
+}
+
+#include "etherproto.h"
+
+int
+s_nametoeproto(s)
+ char *s;
+{
+ struct eproto *p = eproto_db;
+
+ while (p->s != 0) {
+ if (strcmp(p->s, s) == 0)
+ return p->p;
+ p += 1;
+ }
+ return PROTO_UNDEF;
+}
+
+/* Hex digit to integer. */
+static inline int
+xdtoi(c)
+{
+ if (isdigit(c))
+ return c - '0';
+ else if (islower(c))
+ return c - 'a' + 10;
+ else
+ return c - 'A' + 10;
+}
+
+u_long
+atoin(s)
+ char *s;
+{
+ u_long addr = 0;
+ u_int n;
+
+ while (1) {
+ n = 0;
+ while (*s && *s != '.')
+ n = n * 10 + *s++ - '0';
+ addr <<= 8;
+ addr |= n & 0xff;
+ if (*s == '\0')
+ return addr;
+ ++s;
+ }
+ /* NOTREACHED */
+}
+
+
+/*
+ * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new
+ * ethernet address. Assumes 's' is well formed.
+ */
+u_char *
+ETHER_aton(s)
+ char *s;
+{
+ register u_char *ep, *e;
+ register u_int d;
+
+ e = ep = (u_char *)malloc(6);
+
+ while (*s) {
+ if (*s == ':')
+ s += 1;
+ d = xdtoi(*s++);
+ if (isxdigit(*s)) {
+ d <<= 4;
+ d |= xdtoi(*s++);
+ }
+ *ep++ = d;
+ }
+
+ return e;
+}
+
+#ifndef ETHER_SERVICE
+u_char *
+ETHER_hostton(name)
+ char *name;
+{
+ struct etherent *ep;
+ FILE *fp;
+ u_char *ap;
+
+ fp = fopen(ETHERS_FILE, "r");
+ if (fp != 0) {
+ while (ep = next_etherent(fp)) {
+ if (strcmp(ep->name, name) == 0) {
+ ap = (u_char *)malloc(6);
+ bcopy(ep->addr, ap, 6);
+ return ap;
+ }
+ }
+ }
+ return (u_char *)0;
+}
+#endif
diff --git a/usr.sbin/tcpdump/tcpdump/nametoaddr.h b/usr.sbin/tcpdump/tcpdump/nametoaddr.h
new file mode 100644
index 000000000000..23da3f2580f7
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/nametoaddr.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: nametoaddr.h,v 1.6 90/09/24 12:50:41 mccanne Exp $ (LBL)
+ *
+ * Address to name translation routines.
+ */
+
+extern u_long **s_nametoaddr();
+extern u_long s_nametonetaddr();
+
+extern int s_nametoport();
+extern int s_nametoproto();
+extern int s_nametoeproto();
+
+extern u_char *ETHER_hostton();
+extern u_char *ETHER_aton();
+
+/*
+ * If a protocol is unknown, PROTO_UNDEF is returned.
+ * Also, s_nametoport() returns the protocol along with the port number.
+ * If there are ambiguous entried in /etc/services (i.e. domain
+ * can be either tcp or udp) PROTO_UNDEF is returned.
+ */
+#define PROTO_UNDEF -1
+
diff --git a/usr.sbin/tcpdump/tcpdump/ntp.h b/usr.sbin/tcpdump/tcpdump/ntp.h
new file mode 100644
index 000000000000..493686d95c48
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/ntp.h
@@ -0,0 +1,117 @@
+/* $Header: ntp.h,v 1.1 90/08/07 11:08:27 mogul Exp $ */
+
+/*
+ * Based on ntp.h from the U of MD implementation
+ * This file is based on Version 2 of the NTP spec (RFC1119).
+ */
+
+/*
+ * Definitions for the masses
+ */
+#define JAN_1970 2208988800 /* 1970 - 1900 in seconds */
+
+/*
+ * Structure definitions for NTP fixed point values
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Integer Part |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Fraction Part |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Integer Part | Fraction Part |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+struct l_fixedpt {
+ u_long int_part;
+ u_long fraction;
+};
+
+struct s_fixedpt {
+ u_short int_part;
+ u_short fraction;
+};
+
+/* ================= Table 3.3. Packet Variables ================= */
+/*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |LI | VN | Mode| Stratum | Poll | Precision |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Synchronizing Distance |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Synchronizing Dispersion |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reference Clock Identifier |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | |
+ * | Reference Timestamp (64 bits) |
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | |
+ * | Originate Timestamp (64 bits) |
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | |
+ * | Receive Timestamp (64 bits) |
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | |
+ * | Transmit Timestamp (64 bits) |
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+struct ntpdata {
+ u_char status; /* status of local clock and leap info */
+ u_char stratum; /* Stratum level */
+ u_char ppoll; /* poll value */
+ int precision:8;
+ struct s_fixedpt distance;
+ struct s_fixedpt dispersion;
+ u_long refid;
+ struct l_fixedpt reftime;
+ struct l_fixedpt org;
+ struct l_fixedpt rec;
+ struct l_fixedpt xmt;
+};
+/*
+ * Leap Second Codes (high order two bits)
+ */
+#define NO_WARNING 0x00 /* no warning */
+#define PLUS_SEC 0x40 /* add a second (61 seconds) */
+#define MINUS_SEC 0x80 /* minus a second (59 seconds) */
+#define ALARM 0xc0 /* alarm condition (clock unsynchronized) */
+
+/*
+ * Clock Status Bits that Encode Version
+ */
+#define NTPVERSION_1 0x08
+#define VERSIONMASK 0x38
+#define LEAPMASK 0xc0
+#define MODEMASK 0x07
+
+/*
+ * Code values
+ */
+#define MODE_UNSPEC 0 /* unspecified */
+#define MODE_SYM_ACT 1 /* symmetric active */
+#define MODE_SYM_PAS 2 /* symmetric passive */
+#define MODE_CLIENT 3 /* client */
+#define MODE_SERVER 4 /* server */
+#define MODE_BROADCAST 5 /* broadcast */
+#define MODE_RES1 6 /* reserved */
+#define MODE_RES2 7 /* reserved */
+
+/*
+ * Stratum Definitions
+ */
+#define UNSPECIFIED 0
+#define PRIM_REF 1 /* radio clock */
+#define INFO_QUERY 62 /* **** THIS implementation dependent **** */
+#define INFO_REPLY 63 /* **** THIS implementation dependent **** */
diff --git a/usr.sbin/tcpdump/tcpdump/optimize.c b/usr.sbin/tcpdump/tcpdump/optimize.c
new file mode 100644
index 000000000000..50640112fb05
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/optimize.c
@@ -0,0 +1,1871 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Optimization module for tcpdump intermediate representation.
+ */
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: optimize.c,v 1.35 91/07/18 09:27:55 mccanne Exp $ (LBL)";
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include <sys/time.h>
+#include <net/bpf.h>
+
+#include "interface.h"
+#include "gencode.h"
+
+#define A_ATOM BPF_MEMWORDS
+#define X_ATOM (BPF_MEMWORDS+1)
+
+#define NOP -1
+
+/*
+ * This define is used to represent *both* the accumulator and
+ * x register in use-def computations.
+ * Currently, the use-def code assumes only one definition per instruction.
+ */
+#define AX_ATOM N_ATOMS
+
+/*
+ * A flag to indicate that further optimization is needed.
+ * Iterative passes are continued until a given pass yields no
+ * branch movement.
+ */
+static int done;
+
+/*
+ * A block is marked if only if its mark equals the current mark.
+ * Rather than traverse the code array, marking each item, 'cur_mark' is
+ * incremented. This automatically makes each element unmarked.
+ */
+static int cur_mark;
+#define isMarked(p) ((p)->mark == cur_mark)
+#define unMarkAll() cur_mark += 1
+#define Mark(p) ((p)->mark = cur_mark)
+
+static void opt_init();
+static void opt_cleanup();
+
+static void make_marks();
+static void mark_code();
+
+static void intern_blocks();
+
+static int eq_slist();
+
+static int n_blocks;
+struct block **blocks;
+static int n_edges;
+struct edge **edges;
+
+/*
+ * A bit vector set representation of the dominators.
+ * We round up the set size to the next power of two.
+ */
+static int nodewords;
+static int edgewords;
+struct block **levels;
+u_long *space;
+#define BITS_PER_WORD (8*sizeof(u_long))
+/*
+ * True if a is in uset {p}
+ */
+#define SET_MEMBER(p, a) \
+((p)[(unsigned)(a) / BITS_PER_WORD] & (1 << ((unsigned)(a) % BITS_PER_WORD)))
+
+/*
+ * Add 'a' to uset p.
+ */
+#define SET_INSERT(p, a) \
+(p)[(unsigned)(a) / BITS_PER_WORD] |= (1 << ((unsigned)(a) % BITS_PER_WORD))
+
+/*
+ * Delete 'a' from uset p.
+ */
+#define SET_DELETE(p, a) \
+(p)[(unsigned)(a) / BITS_PER_WORD] &= ~(1 << ((unsigned)(a) % BITS_PER_WORD))
+
+/*
+ * a := a intersect b
+ */
+#define SET_INTERSECT(a, b, n)\
+{\
+ register u_long *_x = a, *_y = b;\
+ register int _n = n;\
+ while (--_n >= 0) *_x++ &= *_y++;\
+}
+
+/*
+ * a := a - b
+ */
+#define SET_SUBTRACT(a, b, n)\
+{\
+ register u_long *_x = a, *_y = b;\
+ register int _n = n;\
+ while (--_n >= 0) *_x++ &=~ *_y++;\
+}
+
+/*
+ * a := a union b
+ */
+#define SET_UNION(a, b, n)\
+{\
+ register u_long *_x = a, *_y = b;\
+ register int _n = n;\
+ while (--_n >= 0) *_x++ |= *_y++;\
+}
+
+static uset all_dom_sets;
+static uset all_closure_sets;
+static uset all_edge_sets;
+
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+static void
+find_levels_r(b)
+ struct block *b;
+{
+ int level;
+
+ if (isMarked(b))
+ return;
+
+ Mark(b);
+ b->link = 0;
+
+ if (JT(b)) {
+ find_levels_r(JT(b));
+ find_levels_r(JF(b));
+ level = MAX(JT(b)->level, JF(b)->level) + 1;
+ } else
+ level = 0;
+ b->level = level;
+ b->link = levels[level];
+ levels[level] = b;
+}
+
+/*
+ * Level graph. The levels go from 0 at the leaves to
+ * N_LEVELS at the root. The levels[] array points to the
+ * first node of the level list, whose elements are linked
+ * with the 'link' field of the struct block.
+ */
+static void
+find_levels(root)
+ struct block *root;
+{
+ bzero((char *)levels, n_blocks * sizeof(*levels));
+ unMarkAll();
+ find_levels_r(root);
+}
+
+/*
+ * Find dominator relationships.
+ * Assumes graph has been leveled.
+ */
+static void
+find_dom(root)
+ struct block *root;
+{
+ int i;
+ struct block *b;
+ u_long *x;
+
+ /*
+ * Initialize sets to contain all nodes.
+ */
+ x = all_dom_sets;
+ i = n_blocks * nodewords;
+ while (--i >= 0)
+ *x++ = ~0;
+ /* Root starts off empty. */
+ for (i = nodewords; --i >= 0;)
+ root->dom[i] = 0;
+
+ /* root->level is the highest level no found. */
+ for (i = root->level; i >= 0; --i) {
+ for (b = levels[i]; b; b = b->link) {
+ SET_INSERT(b->dom, b->id);
+ if (JT(b) == 0)
+ continue;
+ SET_INTERSECT(JT(b)->dom, b->dom, nodewords);
+ SET_INTERSECT(JF(b)->dom, b->dom, nodewords);
+ }
+ }
+}
+
+static void
+propedom(ep)
+ struct edge *ep;
+{
+ SET_INSERT(ep->edom, ep->id);
+ if (ep->succ) {
+ SET_INTERSECT(ep->succ->et.edom, ep->edom, edgewords);
+ SET_INTERSECT(ep->succ->ef.edom, ep->edom, edgewords);
+ }
+}
+
+/*
+ * Compute edge dominators.
+ * Assumes graph has been leveled and predecessors estabished.
+ */
+static void
+find_edom(root)
+ struct block *root;
+{
+ int i;
+ uset x;
+ struct block *b;
+
+ x = all_edge_sets;
+ for (i = n_edges * edgewords; --i >= 0; )
+ x[i] = ~0;
+
+ /* root->level is the highest level no found. */
+ bzero(root->et.edom, edgewords * sizeof(*(uset)0));
+ bzero(root->ef.edom, edgewords * sizeof(*(uset)0));
+ for (i = root->level; i >= 0; --i) {
+ for (b = levels[i]; b != 0; b = b->link) {
+ propedom(&b->et);
+ propedom(&b->ef);
+ }
+ }
+}
+
+/*
+ * Find the backwards transitive closure of the flow graph. These sets
+ * are backwards in the sense that we find the set of nodes that reach
+ * a given node, not the set of nodes that can be reached by a node.
+ *
+ * Assumes graph has been leveled.
+ */
+static void
+find_closure(root)
+ struct block *root;
+{
+ int i;
+ struct block *b;
+
+ /*
+ * Initialize sets to contain no nodes.
+ */
+ bzero((char *)all_closure_sets,
+ n_blocks * nodewords * sizeof(*all_closure_sets));
+
+ /* root->level is the highest level no found. */
+ for (i = root->level; i >= 0; --i) {
+ for (b = levels[i]; b; b = b->link) {
+ SET_INSERT(b->closure, b->id);
+ if (JT(b) == 0)
+ continue;
+ SET_UNION(JT(b)->closure, b->closure, nodewords);
+ SET_UNION(JF(b)->closure, b->closure, nodewords);
+ }
+ }
+}
+
+/*
+ * Return the register number that is used by s. If A and X are both
+ * used, return AX_ATOM. If no register is used, return -1.
+ *
+ * The implementation should probably change to an array access.
+ */
+static int
+atomuse(s)
+ struct stmt *s;
+{
+ register int c = s->code;
+
+ if (c == NOP)
+ return -1;
+
+ switch (BPF_CLASS(c)) {
+
+ case BPF_RET:
+ return (BPF_RVAL(c) == BPF_A) ? A_ATOM :
+ (BPF_RVAL(c) == BPF_X) ? X_ATOM : -1;
+
+ case BPF_LD:
+ case BPF_LDX:
+ return (BPF_MODE(c) == BPF_IND) ? X_ATOM :
+ (BPF_MODE(c) == BPF_MEM) ? s->k : -1;
+
+ case BPF_ST:
+ return A_ATOM;
+
+ case BPF_STX:
+ return X_ATOM;
+
+ case BPF_JMP:
+ case BPF_ALU:
+ if (BPF_SRC(c) == BPF_X)
+ return AX_ATOM;
+ return A_ATOM;
+
+ case BPF_MISC:
+ return BPF_MISCOP(c) == BPF_TXA ? X_ATOM : A_ATOM;
+ }
+ abort();
+ /* NOTREACHED */
+}
+
+/*
+ * Return the register number that is defined by 's'. We assume that
+ * a single stmt cannot define more than one register. If no register
+ * is defined, return -1.
+ *
+ * The implementation should probably change to an array access.
+ */
+static int
+atomdef(s)
+ struct stmt *s;
+{
+ if (s->code == NOP)
+ return -1;
+
+ switch (BPF_CLASS(s->code)) {
+
+ case BPF_LD:
+ case BPF_ALU:
+ return A_ATOM;
+
+ case BPF_LDX:
+ return X_ATOM;
+
+ case BPF_ST:
+ case BPF_STX:
+ return s->k;
+
+ case BPF_MISC:
+ return BPF_MISCOP(s->code) == BPF_TAX ? X_ATOM : A_ATOM;
+ }
+ return -1;
+}
+
+static void
+compute_local_ud(b)
+ struct block *b;
+{
+ struct slist *s;
+ atomset def = 0, use = 0, kill = 0;
+ int atom;
+
+ for (s = b->stmts; s; s = s->next) {
+ if (s->s.code == NOP)
+ continue;
+ atom = atomuse(&s->s);
+ if (atom >= 0) {
+ if (atom == AX_ATOM) {
+ if (!ATOMELEM(def, X_ATOM))
+ use |= ATOMMASK(X_ATOM);
+ if (!ATOMELEM(def, A_ATOM))
+ use |= ATOMMASK(A_ATOM);
+ }
+ else if (atom < N_ATOMS) {
+ if (!ATOMELEM(def, atom))
+ use |= ATOMMASK(atom);
+ }
+ else
+ abort();
+ }
+ atom = atomdef(&s->s);
+ if (atom >= 0) {
+ if (!ATOMELEM(atom, use))
+ kill |= ATOMMASK(atom);
+ def |= ATOMMASK(atom);
+ }
+ }
+ if (!ATOMELEM(def, A_ATOM) && BPF_CLASS(b->s.code) == BPF_JMP)
+ use |= ATOMMASK(A_ATOM);
+
+ b->def = def;
+ b->kill = kill;
+ b->in_use = use;
+}
+
+/*
+ * Assume graph is already leveled.
+ */
+static void
+find_ud(root)
+ struct block *root;
+{
+ int i, maxlevel;
+ struct block *p;
+
+ /*
+ * root->level is the highest level no found;
+ * count down from there.
+ */
+ maxlevel = root->level;
+ for (i = maxlevel; i >= 0; --i)
+ for (p = levels[i]; p; p = p->link) {
+ compute_local_ud(p);
+ p->out_use = 0;
+ }
+
+ for (i = 1; i <= maxlevel; ++i) {
+ for (p = levels[i]; p; p = p->link) {
+ p->out_use |= JT(p)->in_use | JF(p)->in_use;
+ p->in_use |= p->out_use &~ p->kill;
+ }
+ }
+}
+
+/*
+ * These data structures are used in a Cocke and Shwarz style
+ * value numbering scheme. Since the flowgraph is acyclic,
+ * exit values can be propagated from a node's predecessors
+ * provided it is uniquely defined.
+ */
+struct valnode {
+ int code;
+ long v0, v1;
+ long val;
+ struct valnode *next;
+};
+
+#define MODULUS 213
+static struct valnode *hashtbl[MODULUS];
+static int curval;
+static int maxval;
+
+/* Integer constants mapped with the load immediate opcode. */
+#define K(i) F(BPF_LD|BPF_IMM|BPF_W, i, 0L)
+
+struct vmapinfo {
+ int is_const;
+ long const_val;
+};
+
+struct vmapinfo *vmap;
+struct valnode *vnode_base;
+struct valnode *next_vnode;
+
+static void
+init_val()
+{
+ curval = 0;
+ next_vnode = vnode_base;
+ bzero((char *)vmap, maxval * sizeof(*vmap));
+ bzero((char *)hashtbl, sizeof hashtbl);
+}
+
+/* Because we really don't have an IR, this stuff is a little messy. */
+static long
+F(code, v0, v1)
+ int code;
+ long v0, v1;
+{
+ u_int hash;
+ int val;
+ struct valnode *p;
+
+ hash = (u_int)code ^ (v0 << 4) ^ (v1 << 8);
+ hash %= MODULUS;
+
+ for (p = hashtbl[hash]; p; p = p->next)
+ if (p->code == code && p->v0 == v0 && p->v1 == v1)
+ return p->val;
+
+ val = ++curval;
+ if (BPF_MODE(code) == BPF_IMM &&
+ (BPF_CLASS(code) == BPF_LD || BPF_CLASS(code) == BPF_LDX)) {
+ vmap[val].const_val = v0;
+ vmap[val].is_const = 1;
+ }
+ p = next_vnode++;
+ p->val = val;
+ p->code = code;
+ p->v0 = v0;
+ p->v1 = v1;
+ p->next = hashtbl[hash];
+ hashtbl[hash] = p;
+
+ return val;
+}
+
+static inline void
+vstore(s, valp, newval, alter)
+ struct stmt *s;
+ long *valp;
+ long newval;
+ int alter;
+{
+ if (alter && *valp == newval)
+ s->code = NOP;
+ else
+ *valp = newval;
+}
+
+static void
+fold_op(s, v0, v1)
+ struct stmt *s;
+ long v0, v1;
+{
+ long a, b;
+
+ a = vmap[v0].const_val;
+ b = vmap[v1].const_val;
+
+ switch (BPF_OP(s->code)) {
+ case BPF_ADD:
+ a += b;
+ break;
+
+ case BPF_SUB:
+ a -= b;
+ break;
+
+ case BPF_MUL:
+ a *= b;
+ break;
+
+ case BPF_DIV:
+ if (b == 0)
+ error("division by zero");
+ a /= b;
+ break;
+
+ case BPF_AND:
+ a &= b;
+ break;
+
+ case BPF_OR:
+ a |= b;
+ break;
+
+ case BPF_LSH:
+ a <<= b;
+ break;
+
+ case BPF_RSH:
+ a >>= b;
+ break;
+
+ case BPF_NEG:
+ a = -a;
+ break;
+
+ default:
+ abort();
+ }
+ s->k = a;
+ s->code = BPF_LD|BPF_IMM;
+ done = 0;
+}
+
+static inline struct slist *
+this_op(s)
+ struct slist *s;
+{
+ while (s != 0 && s->s.code == NOP)
+ s = s->next;
+ return s;
+}
+
+static void
+opt_not(b)
+ struct block *b;
+{
+ struct block *tmp = JT(b);
+
+ JT(b) = JF(b);
+ JF(b) = tmp;
+}
+
+static void
+opt_peep(b)
+ struct block *b;
+{
+ struct slist *s;
+ struct slist *next, *last;
+ int val;
+ long v;
+
+ s = b->stmts;
+ if (s == 0)
+ return;
+
+ last = s;
+ while (1) {
+ s = this_op(s);
+ if (s == 0)
+ break;
+ next = this_op(s->next);
+ if (next == 0)
+ break;
+ last = next;
+
+ /*
+ * st M[k] --> st M[k]
+ * ldx M[k] tax
+ */
+ if (s->s.code == BPF_ST &&
+ next->s.code == (BPF_LDX|BPF_MEM) &&
+ s->s.k == next->s.k) {
+ done = 0;
+ next->s.code = BPF_MISC|BPF_TAX;
+ }
+ /*
+ * ld #k --> ldx #k
+ * tax txa
+ */
+ if (s->s.code == (BPF_LD|BPF_IMM) &&
+ next->s.code == (BPF_MISC|BPF_TAX)) {
+ s->s.code = BPF_LDX|BPF_IMM;
+ next->s.code = BPF_MISC|BPF_TXA;
+ done = 0;
+ }
+ /*
+ * This is an ugly special case, but it happens
+ * when you say tcp[k] or udp[k] where k is a constant.
+ */
+ if (s->s.code == (BPF_LD|BPF_IMM)) {
+ struct slist *add, *tax, *ild;
+
+ /*
+ * Check that X isn't used on exit from this
+ * block (which the optimizer might cause).
+ * We know the code generator won't generate
+ * any local dependencies.
+ */
+ if (ATOMELEM(b->out_use, X_ATOM))
+ break;
+
+ if (next->s.code != (BPF_LDX|BPF_MSH|BPF_B))
+ add = next;
+ else
+ add = this_op(next->next);
+ if (add == 0 || add->s.code != (BPF_ALU|BPF_ADD|BPF_X))
+ break;
+
+ tax = this_op(add->next);
+ if (tax == 0 || tax->s.code != (BPF_MISC|BPF_TAX))
+ break;
+
+ ild = this_op(tax->next);
+ if (ild == 0 || BPF_CLASS(ild->s.code) != BPF_LD ||
+ BPF_MODE(ild->s.code) != BPF_IND)
+ break;
+ /*
+ * XXX We need to check that X is not
+ * subsequently used. We know we can eliminate the
+ * accumulator modifications since it is defined
+ * by the last stmt of this sequence.
+ *
+ * We want to turn this sequence:
+ *
+ * (004) ldi #0x2 {s}
+ * (005) ldxms [14] {next} -- optional
+ * (006) addx {add}
+ * (007) tax {tax}
+ * (008) ild [x+0] {ild}
+ *
+ * into this sequence:
+ *
+ * (004) nop
+ * (005) ldxms [14]
+ * (006) nop
+ * (007) nop
+ * (008) ild [x+2]
+ *
+ */
+ ild->s.k += s->s.k;
+ s->s.code = NOP;
+ add->s.code = NOP;
+ tax->s.code = NOP;
+ done = 0;
+ }
+ s = next;
+ }
+ /*
+ * If we have a subtract to do a comparsion, and the X register
+ * is a known constant, we can merge this value into the
+ * comparison.
+ */
+ if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X) &&
+ !ATOMELEM(b->out_use, A_ATOM)) {
+ val = b->val[X_ATOM];
+ if (vmap[val].is_const) {
+ b->s.k += vmap[val].const_val;
+ last->s.code = NOP;
+ done = 0;
+ } else if (b->s.k == 0) {
+ /*
+ * sub x -> nop
+ * j #0 j x
+ */
+ last->s.code = NOP;
+ b->s.code = BPF_CLASS(b->s.code) | BPF_OP(b->s.code) |
+ BPF_X;
+ done = 0;
+ }
+ }
+ /*
+ * Likewise, a constant subtract can be simplified.
+ */
+ else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K) &&
+ !ATOMELEM(b->out_use, A_ATOM)) {
+ b->s.k += last->s.k;
+ last->s.code = NOP;
+ done = 0;
+ }
+ /*
+ * and #k nop
+ * jeq #0 -> jset #k
+ */
+ if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) &&
+ !ATOMELEM(b->out_use, A_ATOM) && b->s.k == 0) {
+ b->s.k = last->s.k;
+ b->s.code = BPF_JMP|BPF_K|BPF_JSET;
+ last->s.code = NOP;
+ done = 0;
+ opt_not(b);
+ }
+ /*
+ * If the accumulator is a known constant, we can compute the
+ * comparison result.
+ */
+ val = b->val[A_ATOM];
+ if (vmap[val].is_const && BPF_SRC(b->s.code) == BPF_K) {
+ v = vmap[val].const_val;
+ switch (BPF_OP(b->s.code)) {
+
+ case BPF_JEQ:
+ v = v == b->s.k;
+ break;
+
+ case BPF_JGT:
+ v = v > b->s.k;
+ break;
+
+ case BPF_JGE:
+ v = v >= b->s.k;
+ break;
+
+ case BPF_JSET:
+ v &= b->s.k;
+ break;
+
+ default:
+ abort();
+ }
+ if (JF(b) != JT(b))
+ done = 0;
+ if (v)
+ JF(b) = JT(b);
+ else
+ JT(b) = JF(b);
+ }
+}
+
+/*
+ * Compute the symbolic value of expression of 's', and update
+ * anything it defines in the value table 'val'. If 'alter' is true,
+ * do various optimizations. This code would be cleaner if symblic
+ * evaluation and code transformations weren't folded together.
+ */
+static void
+opt_stmt(s, val, alter)
+ struct stmt *s;
+ long val[];
+ int alter;
+{
+ int op;
+ long v;
+
+ switch (s->code) {
+
+ case BPF_LD|BPF_ABS|BPF_W:
+ case BPF_LD|BPF_ABS|BPF_H:
+ case BPF_LD|BPF_ABS|BPF_B:
+ v = F(s->code, s->k, 0L);
+ vstore(s, &val[A_ATOM], v, alter);
+ break;
+
+ case BPF_LD|BPF_IND|BPF_W:
+ case BPF_LD|BPF_IND|BPF_H:
+ case BPF_LD|BPF_IND|BPF_B:
+ v = val[X_ATOM];
+ if (alter && vmap[v].is_const) {
+ s->code = BPF_LD|BPF_ABS|BPF_SIZE(s->code);
+ s->k += vmap[v].const_val;
+ v = F(s->code, s->k, 0L);
+ done = 0;
+ }
+ else
+ v = F(s->code, s->k, v);
+ vstore(s, &val[A_ATOM], v, alter);
+ break;
+
+ case BPF_LD|BPF_LEN:
+ v = F(s->code, 0L, 0L);
+ vstore(s, &val[A_ATOM], v, alter);
+ break;
+
+ case BPF_LD|BPF_IMM:
+ v = K(s->k);
+ vstore(s, &val[A_ATOM], v, alter);
+ break;
+
+ case BPF_LDX|BPF_IMM:
+ v = K(s->k);
+ vstore(s, &val[X_ATOM], v, alter);
+ break;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ v = F(s->code, s->k, 0L);
+ vstore(s, &val[X_ATOM], v, alter);
+ break;
+
+ case BPF_ALU|BPF_NEG:
+ if (alter && vmap[val[A_ATOM]].is_const) {
+ s->code = BPF_LD|BPF_IMM;
+ s->k = -vmap[val[A_ATOM]].const_val;
+ val[A_ATOM] = K(s->k);
+ }
+ else
+ val[A_ATOM] = F(s->code, val[A_ATOM], 0L);
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ case BPF_ALU|BPF_SUB|BPF_K:
+ case BPF_ALU|BPF_MUL|BPF_K:
+ case BPF_ALU|BPF_DIV|BPF_K:
+ case BPF_ALU|BPF_AND|BPF_K:
+ case BPF_ALU|BPF_OR|BPF_K:
+ case BPF_ALU|BPF_LSH|BPF_K:
+ case BPF_ALU|BPF_RSH|BPF_K:
+ op = BPF_OP(s->code);
+ if (alter) {
+ if (s->k == 0) {
+ if (op == BPF_ADD || op == BPF_SUB ||
+ op == BPF_LSH || op == BPF_RSH ||
+ op == BPF_OR) {
+ s->code = NOP;
+ break;
+ }
+ if (op == BPF_MUL || op == BPF_AND) {
+ s->code = BPF_LD|BPF_IMM;
+ val[A_ATOM] = K(s->k);
+ break;
+ }
+ }
+ if (vmap[val[A_ATOM]].is_const) {
+ fold_op(s, val[A_ATOM], K(s->k));
+ val[A_ATOM] = K(s->k);
+ break;
+ }
+ }
+ val[A_ATOM] = F(s->code, val[A_ATOM], K(s->k));
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ case BPF_ALU|BPF_SUB|BPF_X:
+ case BPF_ALU|BPF_MUL|BPF_X:
+ case BPF_ALU|BPF_DIV|BPF_X:
+ case BPF_ALU|BPF_AND|BPF_X:
+ case BPF_ALU|BPF_OR|BPF_X:
+ case BPF_ALU|BPF_LSH|BPF_X:
+ case BPF_ALU|BPF_RSH|BPF_X:
+ op = BPF_OP(s->code);
+ if (alter && vmap[val[X_ATOM]].is_const) {
+ if (vmap[val[A_ATOM]].is_const) {
+ fold_op(s, val[A_ATOM], val[X_ATOM]);
+ val[A_ATOM] = K(s->k);
+ }
+ else {
+ s->code = BPF_ALU|BPF_K|op;
+ s->k = vmap[val[X_ATOM]].const_val;
+ done = 0;
+ val[A_ATOM] =
+ F(s->code, val[A_ATOM], K(s->k));
+ }
+ break;
+ }
+ /*
+ * Check if we're doing something to an accumulator
+ * that is 0, and simplify. This may not seem like
+ * much of a simplification but it could open up further
+ * optimizations.
+ * XXX We could also check for mul by 1, and -1, etc.
+ */
+ if (alter && vmap[val[A_ATOM]].is_const
+ && vmap[val[A_ATOM]].const_val == 0) {
+ if (op == BPF_ADD || op == BPF_OR ||
+ op == BPF_LSH || op == BPF_RSH || op == BPF_SUB) {
+ s->code = BPF_MISC|BPF_TXA;
+ vstore(s, &val[A_ATOM], val[X_ATOM], alter);
+ break;
+ }
+ else if (op == BPF_MUL || op == BPF_DIV ||
+ op == BPF_AND) {
+ s->code = BPF_LD|BPF_IMM;
+ s->k = 0;
+ vstore(s, &val[A_ATOM], K(s->k), alter);
+ break;
+ }
+ else if (op == BPF_NEG) {
+ s->code = NOP;
+ break;
+ }
+ }
+ val[A_ATOM] = F(s->code, val[A_ATOM], val[X_ATOM]);
+ break;
+
+ case BPF_MISC|BPF_TXA:
+ vstore(s, &val[A_ATOM], val[X_ATOM], alter);
+ break;
+
+ case BPF_LD|BPF_MEM:
+ v = val[s->k];
+ if (alter && vmap[v].is_const) {
+ s->code = BPF_LD|BPF_IMM;
+ s->k = vmap[v].const_val;
+ done = 0;
+ }
+ vstore(s, &val[A_ATOM], v, alter);
+ break;
+
+ case BPF_MISC|BPF_TAX:
+ vstore(s, &val[X_ATOM], val[A_ATOM], alter);
+ break;
+
+ case BPF_LDX|BPF_MEM:
+ v = val[s->k];
+ if (alter && vmap[v].is_const) {
+ s->code = BPF_LDX|BPF_IMM;
+ s->k = vmap[v].const_val;
+ done = 0;
+ }
+ vstore(s, &val[X_ATOM], v, alter);
+ break;
+
+ case BPF_ST:
+ vstore(s, &val[s->k], val[A_ATOM], alter);
+ break;
+
+ case BPF_STX:
+ vstore(s, &val[s->k], val[X_ATOM], alter);
+ break;
+ }
+}
+
+static void
+deadstmt(s, last)
+ register struct stmt *s;
+ register struct stmt *last[];
+{
+ register int atom;
+
+ atom = atomuse(s);
+ if (atom >= 0) {
+ if (atom == AX_ATOM) {
+ last[X_ATOM] = 0;
+ last[A_ATOM] = 0;
+ }
+ else
+ last[atom] = 0;
+ }
+ atom = atomdef(s);
+ if (atom >= 0) {
+ if (last[atom]) {
+ done = 0;
+ last[atom]->code = NOP;
+ }
+ last[atom] = s;
+ }
+}
+
+static void
+opt_deadstores(b)
+ register struct block *b;
+{
+ register struct slist *s;
+ register int atom;
+ struct stmt *last[N_ATOMS];
+
+ bzero((char *)last, sizeof last);
+
+ for (s = b->stmts; s != 0; s = s->next)
+ deadstmt(&s->s, last);
+ deadstmt(&b->s, last);
+
+ for (atom = 0; atom < N_ATOMS; ++atom)
+ if (last[atom] && !ATOMELEM(b->out_use, atom)) {
+ last[atom]->code = NOP;
+ done = 0;
+ }
+}
+
+static void
+opt_blk(b, do_stmts)
+ struct block *b;
+{
+ struct slist *s;
+ struct edge *p;
+ int i;
+ long aval;
+
+ /*
+ * Initialize the atom values.
+ * If we have no predecessors, everything is undefined.
+ * Otherwise, we inherent our values from our predecessors.
+ * If any register has an ambiguous value (i.e. control paths are
+ * merging) give it the undefined value of 0.
+ */
+ p = b->in_edges;
+ if (p == 0)
+ bzero((char *)b->val, sizeof(b->val));
+ else {
+ bcopy((char *)p->pred->val, (char *)b->val, sizeof(b->val));
+ while (p = p->next) {
+ for (i = 0; i < N_ATOMS; ++i)
+ if (b->val[i] != p->pred->val[i])
+ b->val[i] = 0;
+ }
+ }
+ aval = b->val[A_ATOM];
+ for (s = b->stmts; s; s = s->next)
+ opt_stmt(&s->s, b->val, do_stmts);
+
+ /*
+ * This is a special case: if we don't use anything from this
+ * block, and we load the accumulator with value that is
+ * already there, eliminate all the statements.
+ */
+ if (do_stmts && b->out_use == 0 && aval != 0 &&
+ b->val[A_ATOM] == aval)
+ b->stmts = 0;
+ else {
+ opt_peep(b);
+ opt_deadstores(b);
+ }
+ /*
+ * Set up values for branch optimizer.
+ */
+ if (BPF_SRC(b->s.code) == BPF_K)
+ b->oval = K(b->s.k);
+ else
+ b->oval = b->val[X_ATOM];
+ b->et.code = b->s.code;
+ b->ef.code = -b->s.code;
+}
+
+/*
+ * Return true if any register that is used on exit from 'succ', has
+ * an exit value that is different from the corresponding exit value
+ * from 'b'.
+ */
+static int
+use_conflict(b, succ)
+ struct block *b, *succ;
+{
+ int atom;
+ atomset use = succ->out_use;
+
+ if (use == 0)
+ return 0;
+
+ for (atom = 0; atom < N_ATOMS; ++atom)
+ if (ATOMELEM(use, atom))
+ if (b->val[atom] != succ->val[atom])
+ return 1;
+ return 0;
+}
+
+struct block *
+fold_edge(child, ep)
+ struct block *child;
+ struct edge *ep;
+{
+ int sense;
+ int aval0, aval1, oval0, oval1;
+ int code = ep->code;
+
+ if (code < 0) {
+ code = -code;
+ sense = 0;
+ } else
+ sense = 1;
+
+ if (child->s.code != code)
+ return 0;
+
+ aval0 = child->val[A_ATOM];
+ oval0 = child->oval;
+ aval1 = ep->pred->val[A_ATOM];
+ oval1 = ep->pred->oval;
+
+ if (aval0 != aval1)
+ return 0;
+
+ if (oval0 == oval1)
+ /*
+ * The operands are identical, so the
+ * result is true if a true branch was
+ * taken to get here, otherwise false.
+ */
+ return sense ? JT(child) : JF(child);
+
+ if (sense && code == (BPF_JMP|BPF_JEQ|BPF_K))
+ /*
+ * At this point, we only know the comparison if we
+ * came down the true branch, and it was an equility
+ * comparison with a constant. We rely on the fact that
+ * distinct constants have distinct value numbers.
+ */
+ return JF(child);
+
+ return 0;
+}
+
+static void
+opt_j(ep)
+ struct edge *ep;
+{
+ register int i, k;
+ register struct block *target;
+
+ if (JT(ep->succ) == 0)
+ return;
+
+ if (JT(ep->succ) == JF(ep->succ)) {
+ /*
+ * Common branch targets can be eliminated, provided
+ * there is no data dependency.
+ */
+ if (!use_conflict(ep->pred, ep->succ->et.succ)) {
+ done = 0;
+ ep->succ = JT(ep->succ);
+ }
+ }
+ /*
+ * For each edge dominator that matches the successor of this
+ * edge, promote the edge succesor to the its grandchild.
+ *
+ * XXX We violate the set abstraction here in favor a reasonbly
+ * efficient loop.
+ */
+ top:
+ for (i = 0; i < edgewords; ++i) {
+ register u_long x = ep->edom[i];
+
+ while (x != 0) {
+ k = ffs(x) - 1;
+ x &=~ 1 << k;
+ k += i * BITS_PER_WORD;
+
+ target = fold_edge(ep->succ, edges[k]);
+ /*
+ * Check that there is no data dependency between
+ * nodes that will be violated if we move the edge.
+ */
+ if (target != 0 && !use_conflict(ep->pred, target)) {
+ done = 0;
+ ep->succ = target;
+ if (JT(target) != 0)
+ /*
+ * Start over unless we hit a leaf.
+ */
+ goto top;
+ return;
+ }
+ }
+ }
+}
+
+
+static void
+or_pullup(b)
+ struct block *b;
+{
+ int val, at_top;
+ struct block *pull;
+ struct block **diffp, **samep;
+ struct edge *ep;
+
+ ep = b->in_edges;
+ if (ep == 0)
+ return;
+
+ /*
+ * Make sure each predecessor loads the same value.
+ * XXX why?
+ */
+ val = ep->pred->val[A_ATOM];
+ for (ep = ep->next; ep != 0; ep = ep->next)
+ if (val != ep->pred->val[A_ATOM])
+ return;
+
+ if (JT(b->in_edges->pred) == b)
+ diffp = &JT(b->in_edges->pred);
+ else
+ diffp = &JF(b->in_edges->pred);
+
+ at_top = 1;
+ while (1) {
+ if (*diffp == 0)
+ return;
+
+ if (JT(*diffp) != JT(b))
+ return;
+
+ if (!SET_MEMBER((*diffp)->dom, b->id))
+ return;
+
+ if ((*diffp)->val[A_ATOM] != val)
+ break;
+
+ diffp = &JF(*diffp);
+ at_top = 0;
+ }
+ samep = &JF(*diffp);
+ while (1) {
+ if (*samep == 0)
+ return;
+
+ if (JT(*samep) != JT(b))
+ return;
+
+ if (!SET_MEMBER((*samep)->dom, b->id))
+ return;
+
+ if ((*samep)->val[A_ATOM] == val)
+ break;
+
+ /* XXX Need to check that there are no data dependencies
+ between dp0 and dp1. Currently, the code generator
+ will not produce such dependencies. */
+ samep = &JF(*samep);
+ }
+#ifdef notdef
+ /* XXX This doesn't cover everything. */
+ for (i = 0; i < N_ATOMS; ++i)
+ if ((*samep)->val[i] != pred->val[i])
+ return;
+#endif
+ /* Pull up the node. */
+ pull = *samep;
+ *samep = JF(pull);
+ JF(pull) = *diffp;
+
+ /*
+ * At the top of the chain, each predecessor needs to point at the
+ * pulled up node. Inside the chain, there is only one predecessor
+ * to worry about.
+ */
+ if (at_top) {
+ for (ep = b->in_edges; ep != 0; ep = ep->next) {
+ if (JT(ep->pred) == b)
+ JT(ep->pred) = pull;
+ else
+ JF(ep->pred) = pull;
+ }
+ }
+ else
+ *diffp = pull;
+
+ done = 0;
+}
+
+static void
+and_pullup(b)
+ struct block *b;
+{
+ int val, at_top;
+ struct block *pull;
+ struct block **diffp, **samep;
+ struct edge *ep;
+
+ ep = b->in_edges;
+ if (ep == 0)
+ return;
+
+ /*
+ * Make sure each predecessor loads the same value.
+ */
+ val = ep->pred->val[A_ATOM];
+ for (ep = ep->next; ep != 0; ep = ep->next)
+ if (val != ep->pred->val[A_ATOM])
+ return;
+
+ if (JT(b->in_edges->pred) == b)
+ diffp = &JT(b->in_edges->pred);
+ else
+ diffp = &JF(b->in_edges->pred);
+
+ at_top = 1;
+ while (1) {
+ if (*diffp == 0)
+ return;
+
+ if (JF(*diffp) != JF(b))
+ return;
+
+ if (!SET_MEMBER((*diffp)->dom, b->id))
+ return;
+
+ if ((*diffp)->val[A_ATOM] != val)
+ break;
+
+ diffp = &JT(*diffp);
+ at_top = 0;
+ }
+ samep = &JT(*diffp);
+ while (1) {
+ if (*samep == 0)
+ return;
+
+ if (JF(*samep) != JF(b))
+ return;
+
+ if (!SET_MEMBER((*samep)->dom, b->id))
+ return;
+
+ if ((*samep)->val[A_ATOM] == val)
+ break;
+
+ /* XXX Need to check that there are no data dependencies
+ between diffp and samep. Currently, the code generator
+ will not produce such dependencies. */
+ samep = &JT(*samep);
+ }
+#ifdef notdef
+ /* XXX This doesn't cover everything. */
+ for (i = 0; i < N_ATOMS; ++i)
+ if ((*samep)->val[i] != pred->val[i])
+ return;
+#endif
+ /* Pull up the node. */
+ pull = *samep;
+ *samep = JT(pull);
+ JT(pull) = *diffp;
+
+ /*
+ * At the top of the chain, each predecessor needs to point at the
+ * pulled up node. Inside the chain, there is only one predecessor
+ * to worry about.
+ */
+ if (at_top) {
+ for (ep = b->in_edges; ep != 0; ep = ep->next) {
+ if (JT(ep->pred) == b)
+ JT(ep->pred) = pull;
+ else
+ JF(ep->pred) = pull;
+ }
+ }
+ else
+ *diffp = pull;
+
+ done = 0;
+}
+
+static void
+opt_blks(root, do_stmts)
+ struct block *root;
+{
+ int i, maxlevel;
+ struct block *p;
+
+ init_val();
+ maxlevel = root->level;
+ for (i = maxlevel; i >= 0; --i)
+ for (p = levels[i]; p; p = p->link)
+ opt_blk(p, do_stmts);
+
+ if (do_stmts)
+ /*
+ * No point trying to move branches; it can't possibly
+ * make a difference at this point.
+ */
+ return;
+
+ for (i = 1; i <= maxlevel; ++i) {
+ for (p = levels[i]; p; p = p->link) {
+ opt_j(&p->et);
+ opt_j(&p->ef);
+ }
+ }
+ for (i = 1; i <= maxlevel; ++i) {
+ for (p = levels[i]; p; p = p->link) {
+ or_pullup(p);
+ and_pullup(p);
+ }
+ }
+}
+
+static inline void
+link_inedge(parent, child)
+ struct edge *parent;
+ struct block *child;
+{
+ parent->next = child->in_edges;
+ child->in_edges = parent;
+}
+
+static void
+find_inedges(root)
+ struct block *root;
+{
+ int i;
+ struct block *b;
+ struct edge *ep;
+
+ for (i = 0; i < n_blocks; ++i)
+ blocks[i]->in_edges = 0;
+
+ /*
+ * Traverse the graph, adding each edge to the predecessor
+ * list of its sucessors. Skip the leaves (i.e. level 0).
+ */
+ for (i = root->level; i > 0; --i) {
+ for (b = levels[i]; b != 0; b = b->link) {
+ link_inedge(&b->et, JT(b));
+ link_inedge(&b->ef, JF(b));
+ }
+ }
+}
+
+static void
+opt_root(b)
+ struct block **b;
+{
+ struct slist *tmp, *s;
+
+ s = (*b)->stmts;
+ (*b)->stmts = 0;
+ while (BPF_CLASS((*b)->s.code) == BPF_JMP && JT(*b) == JF(*b))
+ *b = JT(*b);
+
+ tmp = (*b)->stmts;
+ if (tmp != 0)
+ sappend(s, tmp);
+ (*b)->stmts = s;
+}
+
+static void
+opt_loop(root, do_stmts)
+ struct block *root;
+ int do_stmts;
+{
+ int passes = 0;
+#ifdef BDEBUG
+ if (dflag > 1)
+ opt_dump(root);
+#endif
+ do {
+ done = 1;
+ find_levels(root);
+ find_dom(root);
+ find_closure(root);
+ find_inedges(root);
+ find_ud(root);
+ find_edom(root);
+ opt_blks(root, do_stmts);
+#ifdef BDEBUG
+ if (dflag > 1)
+ opt_dump(root);
+#endif
+ } while (!done);
+}
+
+/*
+ * Optimize the filter code in its dag representation.
+ */
+void
+optimize(rootp)
+ struct block **rootp;
+{
+ struct block *root;
+
+ root = *rootp;
+
+ opt_init(root);
+ opt_loop(root, 0);
+ opt_loop(root, 1);
+ intern_blocks(root);
+ opt_root(rootp);
+ opt_cleanup();
+}
+
+static void
+make_marks(p)
+ struct block *p;
+{
+ if (!isMarked(p)) {
+ Mark(p);
+ if (BPF_CLASS(p->s.code) != BPF_RET) {
+ make_marks(JT(p));
+ make_marks(JF(p));
+ }
+ }
+}
+
+/*
+ * Mark code array such that isMarked(i) is true
+ * only for nodes that are alive.
+ */
+static void
+mark_code(p)
+ struct block *p;
+{
+ cur_mark += 1;
+ make_marks(p);
+}
+
+/*
+ * True iff the two stmt lists load the same value from the packet into
+ * the accumulator.
+ */
+static int
+eq_slist(x, y)
+ struct slist *x, *y;
+{
+ while (1) {
+ while (x && x->s.code == NOP)
+ x = x->next;
+ while (y && y->s.code == NOP)
+ y = y->next;
+ if (x == 0)
+ return y == 0;
+ if (y == 0)
+ return x == 0;
+ if (x->s.code != y->s.code || x->s.k != y->s.k)
+ return 0;
+ x = x->next;
+ y = y->next;
+ }
+}
+
+static inline int
+eq_blk(b0, b1)
+ struct block *b0, *b1;
+{
+ if (b0->s.code == b1->s.code &&
+ b0->s.k == b1->s.k &&
+ b0->et.succ == b1->et.succ &&
+ b0->ef.succ == b1->ef.succ)
+ return eq_slist(b0->stmts, b1->stmts);
+ return 0;
+}
+
+static void
+intern_blocks(root)
+ struct block *root;
+{
+ struct block *p;
+ int i, j;
+ int done;
+ top:
+ done = 1;
+ for (i = 0; i < n_blocks; ++i)
+ blocks[i]->link = 0;
+
+ mark_code(root);
+
+ for (i = n_blocks - 1; --i >= 0; ) {
+ if (!isMarked(blocks[i]))
+ continue;
+ for (j = i + 1; j < n_blocks; ++j) {
+ if (!isMarked(blocks[j]))
+ continue;
+ if (eq_blk(blocks[i], blocks[j])) {
+ blocks[i]->link = blocks[j]->link ?
+ blocks[j]->link : blocks[j];
+ break;
+ }
+ }
+ }
+ for (i = 0; i < n_blocks; ++i) {
+ p = blocks[i];
+ if (JT(p) == 0)
+ continue;
+ if (JT(p)->link) {
+ done = 0;
+ JT(p) = JT(p)->link;
+ }
+ if (JF(p)->link) {
+ done = 0;
+ JF(p) = JF(p)->link;
+ }
+ }
+ if (!done)
+ goto top;
+}
+
+static void
+opt_cleanup()
+{
+ free((void *)vnode_base);
+ free((void *)vmap);
+ free((void *)edges);
+ free((void *)space);
+ free((void *)levels);
+ free((void *)blocks);
+}
+
+/*
+ * Return the number of stmts in 's'.
+ */
+static int
+slength(s)
+ struct slist *s;
+{
+ int n = 0;
+
+ for (; s; s = s->next)
+ if (s->s.code != NOP)
+ ++n;
+ return n;
+}
+
+/*
+ * Return the number of nodes reachable by 'p'.
+ * All nodes should be initially unmarked.
+ */
+static int
+count_blocks(p)
+ struct block *p;
+{
+ if (p == 0 || isMarked(p))
+ return 0;
+ Mark(p);
+ return count_blocks(JT(p)) + count_blocks(JF(p)) + 1;
+}
+
+/*
+ * Do a depth first search on the flow graph, numbering the
+ * the basic blocks, and entering them into the 'blocks' array.`
+ */
+static void
+number_blks_r(p)
+ struct block *p;
+{
+ int n;
+
+ if (p == 0 || isMarked(p))
+ return;
+
+ Mark(p);
+ n = n_blocks++;
+ p->id = n;
+ blocks[n] = p;
+
+ number_blks_r(JT(p));
+ number_blks_r(JF(p));
+}
+
+/*
+ * Return the number of stmts in the flowgraph reachable by 'p'.
+ * The nodes should be unmarked before calling.
+ */
+static int
+count_stmts(p)
+ struct block *p;
+{
+ int n;
+
+ if (p == 0 || isMarked(p))
+ return 0;
+ Mark(p);
+ n = count_stmts(JT(p)) + count_stmts(JF(p));
+ return slength(p->stmts) + n + 1;
+}
+
+/*
+ * Allocate memory. All allocation is done before optimization
+ * is begun. A linear bound on the size of all data structures is computed
+ * from the total number of blocks and/or statements.
+ */
+static void
+opt_init(root)
+ struct block *root;
+{
+ u_long *p;
+ int i, n, max_stmts;
+
+ /*
+ * First, count the blocks, so we can malloc an array to map
+ * block number to block. Then, put the blocks into the array.
+ */
+ unMarkAll();
+ n = count_blocks(root);
+ blocks = (struct block **)malloc(n * sizeof(*blocks));
+ unMarkAll();
+ n_blocks = 0;
+ number_blks_r(root);
+
+ n_edges = 2 * n_blocks;
+ edges = (struct edge **)malloc(n_edges * sizeof(*edges));
+
+ /*
+ * The number of levels is bounded by the number of nodes.
+ */
+ levels = (struct block **)malloc(n_blocks * sizeof(*levels));
+
+ edgewords = n_edges / (8 * sizeof(u_long)) + 1;
+ nodewords = n_blocks / (8 * sizeof(u_long)) + 1;
+
+ /* XXX */
+ space = (u_long *)malloc(2 * n_blocks * nodewords * sizeof(*space)
+ + n_edges * edgewords * sizeof(*space));
+ p = space;
+ all_dom_sets = p;
+ for (i = 0; i < n; ++i) {
+ blocks[i]->dom = p;
+ p += nodewords;
+ }
+ all_closure_sets = p;
+ for (i = 0; i < n; ++i) {
+ blocks[i]->closure = p;
+ p += nodewords;
+ }
+ all_edge_sets = p;
+ for (i = 0; i < n; ++i) {
+ register struct block *b = blocks[i];
+
+ b->et.edom = p;
+ p += edgewords;
+ b->ef.edom = p;
+ p += edgewords;
+ b->et.id = i;
+ edges[i] = &b->et;
+ b->ef.id = n_blocks + i;
+ edges[n_blocks + i] = &b->ef;
+ b->et.pred = b;
+ b->ef.pred = b;
+ }
+ max_stmts = 0;
+ for (i = 0; i < n; ++i)
+ max_stmts += slength(blocks[i]->stmts) + 1;
+ /*
+ * We allocate at most 3 value numbers per statement,
+ * so this is an upper bound on the number of valnodes
+ * we'll need.
+ */
+ maxval = 3 * max_stmts;
+ vmap = (struct vmapinfo *)malloc(maxval * sizeof(*vmap));
+ vnode_base = (struct valnode *)malloc(maxval * sizeof(*vmap));
+}
+
+/*
+ * Some pointers used to convert the basic block form of the code,
+ * into the array form that BPF requires. 'fstart' will point to
+ * the malloc'd array while 'ftail' is used during the recursive traversal.
+ */
+static struct bpf_insn *fstart;
+static struct bpf_insn *ftail;
+
+#ifdef BDEBUG
+int bids[1000];
+#endif
+
+static void
+convert_code_r(p)
+ struct block *p;
+{
+ struct bpf_insn *dst;
+ struct slist *src;
+ int slen;
+ u_int off;
+
+ if (p == 0 || isMarked(p))
+ return;
+ Mark(p);
+
+ convert_code_r(JF(p));
+ convert_code_r(JT(p));
+
+ slen = slength(p->stmts);
+ dst = ftail -= slen + 1;
+
+ p->offset = dst - fstart;
+
+ for (src = p->stmts; src; src = src->next) {
+ if (src->s.code == NOP)
+ continue;
+ dst->code = (u_short)src->s.code;
+ dst->k = src->s.k;
+ ++dst;
+ }
+#ifdef BDEBUG
+ bids[dst - fstart] = p->id + 1;
+#endif
+ dst->code = (u_short)p->s.code;
+ dst->k = p->s.k;
+ if (JT(p)) {
+ off = JT(p)->offset - (p->offset + slen) - 1;
+ if (off >= 256)
+ error("long jumps not supported");
+ dst->jt = off;
+ off = JF(p)->offset - (p->offset + slen) - 1;
+ if (off >= 256)
+ error("long jumps not supported");
+ dst->jf = off;
+ }
+}
+
+
+/*
+ * Convert flowgraph intermediate representation to the
+ * BPF array representation. Set *lenp to the number of instructions.
+ */
+struct bpf_insn *
+icode_to_fcode(root, lenp)
+ struct block *root;
+ int *lenp;
+{
+ int n;
+ struct bpf_insn *fp;
+
+ unMarkAll();
+ n = *lenp = count_stmts(root);
+
+ fp = (struct bpf_insn *)malloc(sizeof(*fp) * n);
+ bzero((char *)fp, sizeof(*fp) * n);
+ fstart = fp;
+ ftail = fp + n;
+
+ unMarkAll();
+ convert_code_r(root);
+
+ return fp;
+}
+
+#ifdef BDEBUG
+opt_dump(root)
+ struct block *root;
+{
+ struct bpf_program f;
+
+ bzero(bids, sizeof bids);
+ f.bf_insns = icode_to_fcode(root, &f.bf_len);
+ bpf_dump(&f, 1);
+ putchar('\n');
+ free((char *)f.bf_insns);
+}
+#endif
diff --git a/usr.sbin/tcpdump/tcpdump/os.c b/usr.sbin/tcpdump/tcpdump/os.c
new file mode 100644
index 000000000000..856fb5a2bc66
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/os.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: os-bsd.c,v 1.2 90/09/21 02:12:17 mccanne Exp $ (LBL)";
+#endif
+
diff --git a/usr.sbin/tcpdump/tcpdump/os.h b/usr.sbin/tcpdump/tcpdump/os.h
new file mode 100644
index 000000000000..e0d01cf9484a
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/os.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: os-bsd.h,v 1.15 91/05/05 23:59:11 mccanne Exp $ (LBL)
+ */
+
+#include <sys/param.h>
+
+#ifndef BSD
+#define BSD
+#endif
+
+#define SHA(ap) ((ap)->arp_sha)
+#define SPA(ap) ((ap)->arp_spa)
+#define THA(ap) ((ap)->arp_tha)
+#define TPA(ap) ((ap)->arp_tpa)
+
+#define EDST(ep) ((ep)->ether_dhost)
+#define ESRC(ep) ((ep)->ether_shost)
+
+#ifndef ETHERTYPE_REVARP
+#define ETHERTYPE_REVARP 0x8035
+#endif
+
+#ifndef IPPROTO_ND
+/* From <netinet/in.h> on a Sun somewhere. */
+#define IPPROTO_ND 77
+#endif
+
+#ifndef REVARP_REQUEST
+#define REVARP_REQUEST 3
+#endif
+#ifndef REVARP_REPLY
+#define REVARP_REPLY 4
+#endif
+
+/* newish RIP commands */
+#ifndef RIPCMD_POLL
+#define RIPCMD_POLL 5
+#endif
+#ifndef RIPCMD_POLLENTRY
+#define RIPCMD_POLLENTRY 6
+#endif
+
+/*
+ * Map BSD names to SunOS names.
+ */
+#if BSD >= 199006
+#define RFS_NULL NFSPROC_NULL
+#define RFS_GETATTR NFSPROC_GETATTR
+#define RFS_SETATTR NFSPROC_SETATTR
+#define RFS_ROOT NFSPROC_ROOT
+#define RFS_LOOKUP NFSPROC_LOOKUP
+#define RFS_READLINK NFSPROC_READLINK
+#define RFS_READ NFSPROC_READ
+#define RFS_WRITECACHE NFSPROC_WRITECACHE
+#define RFS_WRITE NFSPROC_WRITE
+#define RFS_CREATE NFSPROC_CREATE
+#define RFS_REMOVE NFSPROC_REMOVE
+#define RFS_RENAME NFSPROC_RENAME
+#define RFS_LINK NFSPROC_LINK
+#define RFS_SYMLINK NFSPROC_SYMLINK
+#define RFS_MKDIR NFSPROC_MKDIR
+#define RFS_RMDIR NFSPROC_RMDIR
+#define RFS_READDIR NFSPROC_READDIR
+#define RFS_STATFS NFSPROC_STATFS
+#define RFS_NPROC NFSPROC_NPROC
+#endif
diff --git a/usr.sbin/tcpdump/tcpdump/ospf.h b/usr.sbin/tcpdump/tcpdump/ospf.h
new file mode 100644
index 000000000000..e3a3a6d65d3e
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/ospf.h
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu)
+ */
+#define OSPF_TYPE_UMD 0 /* UMd's special monitoring packets */
+#define OSPF_TYPE_HELLO 1 /* Hello */
+#define OSPF_TYPE_DB 2 /* Database Description */
+#define OSPF_TYPE_LSR 3 /* Link State Request */
+#define OSPF_TYPE_LSU 4 /* Link State Update */
+#define OSPF_TYPE_LSA 5 /* Link State Ack */
+#define OSPF_TYPE_MAX 6
+
+/* Options *_options */
+#define OSPF_OPTION_T 0x01 /* T bit: TOS support */
+#define OSPF_OPTION_E 0x02 /* E bit: External routes advertised */
+#define OSPF_OPTION_MC 0x04 /* MC bit: Multicast capable */
+
+/* ospf_authtype */
+#define OSPF_AUTH_NONE 0 /* No auth-data */
+#define OSPF_AUTH_SIMPLE 1 /* Simple password */
+
+/* db_flags */
+#define OSPF_DB_INIT 0x04 /* */
+#define OSPF_DB_MORE 0x02
+#define OSPF_DB_MASTER 0x01
+
+/* ls_type */
+#define LS_TYPE_ROUTER 1 /* router link */
+#define LS_TYPE_NETWORK 2 /* network link */
+#define LS_TYPE_SUM_IP 3 /* summary link */
+#define LS_TYPE_SUM_ABR 4 /* summary area link */
+#define LS_TYPE_ASE 5 /* ASE */
+#define LS_TYPE_GROUP 6 /* Group membership (multicast */
+ /* extensions 23 July 1991) */
+#define LS_TYPE_MAX 7
+
+/*************************************************
+ *
+ * is the above a bug in the documentation?
+ *
+ *************************************************/
+
+
+/* rla_link.link_type */
+#define RLA_TYPE_ROUTER 1 /* point-to-point to another router */
+#define RLA_TYPE_TRANSIT 2 /* connection to transit network */
+#define RLA_TYPE_STUB 3 /* connection to stub network */
+#define RLA_TYPE_VIRTUAL 4 /* virtual link */
+
+/* rla_flags */
+#define RLA_FLAG_B 0x01
+#define RLA_FLAG_E 0x02
+#define RLA_FLAG_W1 0x04
+#define RLA_FLAG_W2 0x08
+
+/* sla_tosmetric breakdown */
+#define SLA_MASK_TOS 0x7f000000
+#define SLA_MASK_METRIC 0x00ffffff
+#define SLA_SHIFT_TOS 24
+
+/* asla_tosmetric breakdown */
+#define ASLA_FLAG_EXTERNAL 0x80000000
+#define ASLA_MASK_TOS 0x7f000000
+#define ASLA_SHIFT_TOS 24
+#define ASLA_MASK_METRIC 0x00ffffff
+
+/* multicast vertex type */
+#define MCLA_VERTEX_ROUTER 1
+#define MCLA_VERTEX_NETWORK 2
+
+/* link state advertisement header */
+struct lsa_hdr {
+ u_short ls_age;
+ u_char ls_options;
+ u_char ls_type;
+ struct in_addr ls_stateid;
+ struct in_addr ls_router;
+ u_long ls_seq;
+ u_short ls_chksum;
+ u_short ls_length;
+} ;
+
+/* link state advertisement */
+struct lsa {
+ struct lsa_hdr ls_hdr;
+
+ /* Link state types */
+ union {
+ /* Router links advertisements */
+ struct {
+ u_char rla_flags;
+ u_char rla_zero[1];
+ u_short rla_count;
+ struct rlalink {
+ struct in_addr link_id;
+ struct in_addr link_data;
+ u_char link_type;
+ u_char link_toscount;
+ u_short link_tos0metric;
+ } rla_link[1]; /* may repeat */
+ } un_rla;
+
+ /* Network links advertisements */
+ struct {
+ struct in_addr nla_mask;
+ struct in_addr nla_router[1]; /* may repeat */
+ } un_nla;
+
+ /* Summary links advertisements */
+ struct {
+ struct in_addr sla_mask;
+ u_long sla_tosmetric[1]; /* may repeat */
+ } un_sla;
+
+ /* AS external links advertisements */
+ struct {
+ struct in_addr asla_mask;
+ struct aslametric {
+ u_long asla_tosmetric;
+ struct in_addr asla_forward;
+ struct in_addr asla_tag;
+ } asla_metric[1]; /* may repeat */
+ } un_asla;
+
+ /* Multicast group membership */
+ struct mcla {
+ u_long mcla_vtype;
+ struct in_addr mcla_vid;
+ } un_mcla[1];
+ } lsa_un;
+} ;
+
+
+/*
+ * TOS metric struct (will be 0 or more in router links update)
+ */
+struct tos_metric {
+ u_char tos_type;
+ u_char tos_zero;
+ u_short tos_metric;
+} ;
+
+#define OSPF_AUTH_SIZE 8
+
+/*
+ * the main header
+ */
+struct ospfhdr {
+ u_char ospf_version;
+ u_char ospf_type;
+ u_short ospf_len;
+ struct in_addr ospf_routerid;
+ struct in_addr ospf_areaid;
+ u_short ospf_chksum;
+ u_short ospf_authtype;
+ u_char ospf_authdata[OSPF_AUTH_SIZE];
+ union {
+
+ /* Hello packet */
+ struct {
+ struct in_addr hello_mask;
+ u_short hello_helloint;
+ u_char hello_options;
+ u_char hello_priority;
+ u_long hello_deadint;
+ struct in_addr hello_dr;
+ struct in_addr hello_bdr;
+ struct in_addr hello_neighbor[1]; /* may repeat */
+ } un_hello;
+
+ /* Database Description packet */
+ struct {
+ u_char db_zero[2];
+ u_char db_options;
+ u_char db_flags;
+ u_long db_seq;
+ struct lsa_hdr db_lshdr[1]; /* may repeat */
+ } un_db;
+
+ /* Link State Request */
+ struct lsr {
+ u_long ls_type;
+ struct in_addr ls_stateid;
+ struct in_addr ls_router;
+ } un_lsr[1]; /* may repeat */
+
+ /* Link State Update */
+ struct {
+ u_long lsu_count;
+ struct lsa lsu_lsa[1]; /* may repeat */
+ } un_lsu;
+
+ /* Link State Acknowledment */
+ struct {
+ struct lsa_hdr lsa_lshdr[1]; /* may repeat */
+ } un_lsa ;
+ } ospf_un ;
+} ;
+
+#define ospf_hello ospf_un.un_hello
+#define ospf_db ospf_un.un_db
+#define ospf_lsr ospf_un.un_lsr
+#define ospf_lsu ospf_un.un_lsu
+#define ospf_lsa ospf_un.un_lsa
+
diff --git a/usr.sbin/tcpdump/tcpdump/pcap.c b/usr.sbin/tcpdump/tcpdump/pcap.c
new file mode 100644
index 000000000000..04c96953766b
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/pcap.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static char rcsid[] =
+ "@(#)$Header: pcap-bpf.c,v 1.29 92/06/02 17:57:29 mccanne Exp $ (LBL)";
+#endif
+
+#include <stdio.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/param.h> /* optionally get BSD define */
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <net/bpf.h>
+#include <net/if.h>
+#include <string.h>
+
+#include "interface.h"
+
+extern int errno;
+
+static void
+bpf_stats(fd)
+ int fd;
+{
+ struct bpf_stat s;
+
+ if (ioctl(fd, BIOCGSTATS, &s) < 0)
+ return;
+
+ (void)fflush(stdout);
+ (void)fprintf(stderr, "%d packets received by filter\n", s.bs_recv);
+ (void)fprintf(stderr, "%d packets dropped by kernel\n", s.bs_drop);
+}
+
+void
+readloop(cnt, if_fd, fp, printit)
+ int cnt;
+ int if_fd;
+ struct bpf_program *fp;
+ void (*printit)();
+{
+ u_char *buf;
+ u_int bufsize;
+ int cc;
+
+ if (ioctl(if_fd, BIOCGBLEN, (caddr_t)&bufsize) < 0) {
+ perror("tcpdump: BIOCGBLEN");
+ exit(1);
+ }
+ buf = (u_char *)malloc(bufsize);
+
+ if (ioctl(if_fd, BIOCSETF, (caddr_t)fp) < 0) {
+ perror("tcpdump: BIOCSETF");
+ exit(1);
+ }
+ while (1) {
+ register u_char *bp, *ep;
+
+ if ((cc = read(if_fd, (char *)buf, (int)bufsize)) < 0) {
+ /* Don't choke when we get ptraced */
+ if (errno == EINTR)
+ continue;
+#if defined(sun) && !defined(BSD)
+ /*
+ * Due to a SunOS bug, after 2^31 bytes, the kernel
+ * file offset overflows and read fails with EINVAL.
+ * The lseek() to 0 will fix things.
+ */
+ if (errno == EINVAL &&
+ (long)(tell(if_fd) + bufsize) < 0) {
+ (void)lseek(if_fd, 0, 0);
+ continue;
+ }
+#endif
+ perror("tcpdump: read");
+ exit(1);
+ }
+ /*
+ * Loop through each packet.
+ */
+#define bhp ((struct bpf_hdr *)bp)
+ bp = buf;
+ ep = bp + cc;
+ while (bp < ep) {
+ register int caplen, hdrlen;
+ if (cnt >= 0 && --cnt < 0)
+ goto out;
+ (*printit)(bp + (hdrlen = bhp->bh_hdrlen),
+ &bhp->bh_tstamp, bhp->bh_datalen,
+ caplen = bhp->bh_caplen);
+ bp += BPF_WORDALIGN(caplen + hdrlen);
+ }
+#undef bhp
+ }
+ out:
+ wrapup(if_fd);
+}
+
+wrapup(fd)
+ int fd;
+{
+ bpf_stats(fd);
+ close(fd);
+}
+
+static inline int
+bpf_open()
+{
+ int fd;
+ int n = 0;
+ char device[sizeof "/dev/bpf000"];
+
+ /*
+ * Go through all the minors and find one that isn't in use.
+ */
+ do {
+ (void)sprintf(device, "/dev/bpf%d", n++);
+ fd = open(device, O_RDONLY);
+ } while (fd < 0 && errno == EBUSY);
+
+ if (fd < 0) {
+ (void) fprintf(stderr, "tcpdump: ");
+ perror(device);
+ exit(-1);
+ }
+ return fd;
+}
+
+int
+initdevice(device, pflag, linktype)
+ char *device;
+ int pflag;
+ int *linktype;
+{
+ struct timeval timeout;
+ int if_fd;
+ struct ifreq ifr;
+ struct bpf_version bv;
+
+ if_fd = bpf_open();
+
+ if (ioctl(if_fd, BIOCVERSION, (caddr_t)&bv) < 0)
+ warning("kernel bpf interpreter may be out of date");
+ else if (bv.bv_major != BPF_MAJOR_VERSION ||
+ bv.bv_minor < BPF_MINOR_VERSION)
+ error("requires bpf language %d.%d or higher; kernel is %d.%d",
+ BPF_MAJOR_VERSION, BPF_MINOR_VERSION,
+ bv.bv_major, bv.bv_minor);
+
+ (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ if (ioctl(if_fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
+ (void) fprintf(stderr, "tcpdump: BIOCSETIF: ");
+ perror(device);
+ exit(-1);
+ }
+ /* Get the data link layer type. */
+ if (ioctl(if_fd, BIOCGDLT, (caddr_t)linktype) < 0) {
+ perror("tcpdump: BIOCGDLT");
+ exit(-1);
+ }
+ /* set timeout */
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+ if (ioctl(if_fd, BIOCSRTIMEOUT, (caddr_t)&timeout) < 0) {
+ perror("tcpdump: BIOCSRTIMEOUT");
+ exit(-1);
+ }
+ /* set promiscuous mode if requested, but only for broadcast nets */
+ if (pflag == 0) {
+ switch (*linktype) {
+
+ case DLT_SLIP:
+ case DLT_PPP:
+ case DLT_NULL:
+ break;
+
+ default:
+ if (ioctl(if_fd, BIOCPROMISC, (void *)0) < 0) {
+ perror("tcpdump: BIOCPROMISC");
+ exit(-1);
+ }
+ }
+ }
+ return(if_fd);
+}
diff --git a/usr.sbin/tcpdump/tcpdump/print-arp.c b/usr.sbin/tcpdump/tcpdump/print-arp.c
new file mode 100644
index 000000000000..3f0671a4ba58
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-arp.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: print-arp.c,v 1.16 91/04/19 10:45:56 mccanne Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+void
+arp_print(ap, length, caplen)
+ register struct ether_arp *ap;
+ int length;
+ int caplen;
+{
+ if ((u_char *)(ap + 1) > snapend) {
+ printf("[|arp]");
+ return;
+ }
+ if (length < sizeof(struct ether_arp)) {
+ (void)printf("truncated-arp");
+ default_print((u_short *)ap, length);
+ return;
+ }
+
+ NTOHS(ap->arp_hrd);
+ NTOHS(ap->arp_pro);
+ NTOHS(ap->arp_op);
+
+ if (ap->arp_hrd != ARPHRD_ETHER
+ || (ap->arp_pro != ETHERTYPE_IP
+ && ap->arp_pro != ETHERTYPE_TRAIL)
+ || ap->arp_hln != sizeof(SHA(ap))
+ || ap->arp_pln != sizeof(SPA(ap))) {
+ (void)printf("arp-req #%d for proto #%d (%d) hardware %d (%d)",
+ ap->arp_op, ap->arp_pro, ap->arp_pln,
+ ap->arp_hrd, ap->arp_hln);
+ return;
+ }
+ if (ap->arp_pro == ETHERTYPE_TRAIL)
+ (void)printf("trailer");
+ switch (ap->arp_op) {
+
+ case ARPOP_REQUEST:
+ (void)printf("arp who-has %s tell %s",
+ ipaddr_string(TPA(ap)),
+ ipaddr_string(SPA(ap)));
+ break;
+
+ case ARPOP_REPLY:
+ (void)printf("arp reply %s is-at %s",
+ ipaddr_string(SPA(ap)),
+ etheraddr_string(SHA(ap)));
+ break;
+
+ case REVARP_REQUEST:
+ (void)printf("rarp who-is %s tell %s",
+ etheraddr_string(THA(ap)),
+ etheraddr_string(SHA(ap)));
+ break;
+
+ case REVARP_REPLY:
+ (void)printf("rarp reply %s at %s",
+ etheraddr_string(THA(ap)),
+ ipaddr_string(TPA(ap)));
+ break;
+
+ default:
+ (void)printf("arp-%d", ap->arp_op);
+ default_print((u_short *)ap, caplen);
+ break;
+ }
+}
diff --git a/usr.sbin/tcpdump/tcpdump/print-atalk.c b/usr.sbin/tcpdump/tcpdump/print-atalk.c
new file mode 100644
index 000000000000..203585ef5a8b
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-atalk.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Format and print AppleTalk packets.
+ */
+#ifndef lint
+static char rcsid[] =
+ "@(#)$Header: print-atalk.c,v 1.22 92/03/26 14:15:34 mccanne Exp $ (LBL)";
+#endif
+
+#ifdef __STDC__
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "appletalk.h"
+#include <strings.h>
+#include "extract.h"
+
+static char *ataddr_string();
+static struct atNBPtuple *nbp_tuple_print();
+static struct atNBPtuple *nbp_name_print();
+static void atp_print();
+static void nbp_print();
+static void atp_bitmap_print();
+
+/*
+ * Print AppleTalk Datagram Delivery Protocol packets.
+ */
+void
+ddp_print(dp, length)
+ register struct atDDP *dp;
+ int length;
+{
+ if (length < ddpSize) {
+ (void)printf(" truncated-ddp %d", length);
+ return;
+ }
+ (void)printf("%s.%d > %s.%d:",
+ ataddr_string(EXTRACT_SHORT(&dp->srcNet), dp->srcNode),
+ dp->srcSkt,
+ ataddr_string(EXTRACT_SHORT(&dp->dstNet), dp->dstNode),
+ dp->dstSkt);
+
+ /* 'type' is the last field of 'dp' so we need the whole thing.
+ If we cannot determine the type, bail out. (This last byte
+ happens to be *one* byte past the end of tcpdump's minimum
+ snapshot length.) */
+ if ((u_char *)(dp + 1) > snapend) {
+ printf(" [|atalk]");
+ return;
+ }
+
+ length -= ddpSize;
+ switch (dp->type) {
+
+ case ddpRTMP:
+ (void)printf(" at-rtmp %d", length);
+ break;
+ case ddpRTMPrequest:
+ (void)printf(" at-rtmpReq %d", length);
+ break;
+ case ddpNBP:
+ nbp_print((struct atNBP *)((u_char *)dp + ddpSize),
+ length, dp);
+ break;
+ case ddpATP:
+ atp_print((struct atATP *)((u_char *)dp + ddpSize), length);
+ break;
+ case ddpECHO:
+ (void)printf(" at-echo %d", length);
+ break;
+ case ddpIP:
+ (void)printf(" at-IP %d", length);
+ break;
+ case ddpARP:
+ (void)printf(" at-ARP %d", length);
+ break;
+ case ddpKLAP:
+ (void)printf(" at-KLAP %d", length);
+ break;
+ default:
+ (void)printf(" at-#%d %d", length);
+ break;
+ }
+}
+
+static void
+atp_print(ap, length)
+ register struct atATP *ap;
+ int length;
+{
+ char c;
+ long data;
+
+ if ((u_char *)(ap + 1) > snapend) {
+ /* Just bail if we don't have the whole chunk. */
+ printf(" [|atalk]");
+ return;
+ }
+ length -= sizeof(*ap);
+ switch (ap->control & 0xc0) {
+
+ case atpReqCode:
+ (void)printf(" atp-req%s %d",
+ ap->control & atpXO? " " : "*",
+ EXTRACT_SHORT(&ap->transID));
+
+ atp_bitmap_print(ap->bitmap);
+
+ if (length != 0)
+ (void)printf(" [len=%d]", length);
+
+ switch (ap->control & (atpEOM|atpSTS)) {
+ case atpEOM:
+ (void)printf(" [EOM]");
+ break;
+ case atpSTS:
+ (void)printf(" [STS]");
+ break;
+ case atpEOM|atpSTS:
+ (void)printf(" [EOM,STS]");
+ break;
+ }
+ break;
+
+ case atpRspCode:
+ (void)printf(" atp-resp%s%d:%d (%d)",
+ ap->control & atpEOM? "*" : " ",
+ EXTRACT_SHORT(&ap->transID), ap->bitmap, length);
+ switch (ap->control & (atpXO|atpSTS)) {
+ case atpXO:
+ (void)printf(" [XO]");
+ break;
+ case atpSTS:
+ (void)printf(" [STS]");
+ break;
+ case atpXO|atpSTS:
+ (void)printf(" [XO,STS]");
+ break;
+ }
+ break;
+
+ case atpRelCode:
+ (void)printf(" atp-rel %d", EXTRACT_SHORT(&ap->transID));
+
+ atp_bitmap_print(ap->bitmap);
+
+ /* length should be zero */
+ if (length)
+ (void)printf(" [len=%d]", length);
+
+ /* there shouldn't be any control flags */
+ if (ap->control & (atpXO|atpEOM|atpSTS)) {
+ c = '[';
+ if (ap->control & atpXO) {
+ (void)printf("%cXO", c);
+ c = ',';
+ }
+ if (ap->control & atpEOM) {
+ (void)printf("%cEOM", c);
+ c = ',';
+ }
+ if (ap->control & atpSTS) {
+ (void)printf("%cSTS", c);
+ c = ',';
+ }
+ (void)printf("]");
+ }
+ break;
+
+ default:
+ (void)printf(" atp-0x%x %d (%d)", ap->control,
+ EXTRACT_SHORT(&ap->transID), length);
+ break;
+ }
+ data = EXTRACT_LONG(&ap->userData);
+ if (data != 0)
+ (void)printf(" 0x%x", data);
+}
+
+static void
+atp_bitmap_print(bm)
+ register u_char bm;
+{
+ register char c;
+ register int i;
+
+ /*
+ * The '& 0xff' below is needed for compilers that want to sign
+ * extend a u_char, which is the case with the Ultrix compiler.
+ * (gcc is smart enough to eliminate it, at least on the Sparc).
+ */
+ if ((bm + 1) & (bm & 0xff)) {
+ c = '<';
+ for (i = 0; bm; ++i) {
+ if (bm & 1) {
+ (void)printf("%c%d", c, i);
+ c = ',';
+ }
+ bm >>= 1;
+ }
+ (void)printf(">");
+ } else {
+ for (i = 0; bm; ++i)
+ bm >>= 1;
+ if (i > 1)
+ (void)printf("<0-%d>", i - 1);
+ else
+ (void)printf("<0>");
+ }
+}
+
+static void
+nbp_print(np, length, dp)
+ register struct atNBP *np;
+ int length;
+ register struct atDDP *dp;
+{
+ register struct atNBPtuple *tp =
+ (struct atNBPtuple *)((u_char *)np + nbpHeaderSize);
+ int i = length;
+ u_char *ep;
+
+ length -= nbpHeaderSize;
+ if (length < 8) {
+ /* must be room for at least one tuple */
+ (void)printf(" truncated-nbp %d", length + nbpHeaderSize);
+ return;
+ }
+ /* ep points to end of available data */
+ ep = snapend;
+ if ((u_char *)tp > ep) {
+ printf(" [|atalk]");
+ return;
+ }
+ switch (i = np->control & 0xf0) {
+
+ case nbpBrRq:
+ case nbpLkUp:
+ (void)printf(i == nbpLkUp? " nbp-lkup %d:":" nbp-brRq %d:",
+ np->id);
+ if ((u_char *)(tp + 1) > ep) {
+ printf(" [|atalk]");
+ return;
+ }
+ (void)nbp_name_print(tp, ep);
+ /*
+ * look for anomalies: the spec says there can only
+ * be one tuple, the address must match the source
+ * address and the enumerator should be zero.
+ */
+ if ((np->control & 0xf) != 1)
+ (void)printf(" [ntup=%d]", np->control & 0xf);
+ if (tp->enumerator)
+ (void)printf(" [enum=%d]", tp->enumerator);
+ if (EXTRACT_SHORT(&tp->net) != EXTRACT_SHORT(&dp->srcNet) ||
+ tp->node != dp->srcNode || tp->skt != dp->srcSkt)
+ (void)printf(" [addr=%s.%d]",
+ ataddr_string(EXTRACT_SHORT(&tp->net),
+ tp->node),
+ tp->skt);
+ break;
+
+ case nbpLkUpReply:
+ (void)printf(" nbp-reply %d:", np->id);
+
+ /* print each of the tuples in the reply */
+ for (i = np->control & 0xf; --i >= 0 && tp; )
+ tp = nbp_tuple_print(tp, ep, dp);
+ break;
+
+ default:
+ (void)printf(" nbp-0x%x %d (%d)", np->control, np->id,
+ length);
+ break;
+ }
+}
+
+/* print a counted string */
+static char *
+print_cstring(cp, ep)
+ register char *cp;
+ register u_char *ep;
+{
+ register int length;
+
+ if (cp >= (char *)ep) {
+ (void)printf("[|atalk]");
+ return (0);
+ }
+ length = *cp++;
+
+ /* Spec says string can be at most 32 bytes long */
+ if (length < 0 || length > 32) {
+ (void)printf("[len=%d]", length);
+ return (0);
+ }
+ while (--length >= 0) {
+ if (cp >= (char *)ep) {
+ (void)printf("[|atalk]");
+ return (0);
+ }
+ putchar(*cp++);
+ }
+ return (cp);
+}
+
+static struct atNBPtuple *
+nbp_tuple_print(tp, ep, dp)
+ register struct atNBPtuple *tp;
+ register u_char *ep;
+ register struct atDDP *dp;
+{
+ register struct atNBPtuple *tpn;
+
+ if ((u_char *)(tp + 1) > ep) {
+ printf(" [|atalk]");
+ return 0;
+ }
+ tpn = nbp_name_print(tp, ep);
+
+ /* if the enumerator isn't 1, print it */
+ if (tp->enumerator != 1)
+ (void)printf("(%d)", tp->enumerator);
+
+ /* if the socket doesn't match the src socket, print it */
+ if (tp->skt != dp->srcSkt)
+ (void)printf(" %d", tp->skt);
+
+ /* if the address doesn't match the src address, it's an anomaly */
+ if (EXTRACT_SHORT(&tp->net) != EXTRACT_SHORT(&dp->srcNet) ||
+ tp->node != dp->srcNode)
+ (void)printf(" [addr=%s]",
+ ataddr_string(EXTRACT_SHORT(&tp->net), tp->node));
+
+ return (tpn);
+}
+
+static struct atNBPtuple *
+nbp_name_print(tp, ep)
+ struct atNBPtuple *tp;
+ register u_char *ep;
+{
+ register char *cp = (char *)tp + nbpTupleSize;
+
+ putchar(' ');
+
+ /* Object */
+ putchar('"');
+ if (cp = print_cstring(cp, ep)) {
+ /* Type */
+ putchar(':');
+ if (cp = print_cstring(cp, ep)) {
+ /* Zone */
+ putchar('@');
+ if (cp = print_cstring(cp, ep))
+ putchar('"');
+ }
+ }
+ return ((struct atNBPtuple *)cp);
+}
+
+
+#define HASHNAMESIZE 4096
+
+struct hnamemem {
+ int addr;
+ char *name;
+ struct hnamemem *nxt;
+};
+
+static struct hnamemem hnametable[HASHNAMESIZE];
+
+static char *
+ataddr_string(atnet, athost)
+ u_short atnet;
+ u_char athost;
+{
+ register struct hnamemem *tp, *tp2;
+ register int i = (atnet << 8) | athost;
+ char nambuf[256];
+ static int first = 1;
+ FILE *fp;
+
+ /*
+ * if this is the first call, see if there's an AppleTalk
+ * number to name map file.
+ */
+ if (first && (first = 0, !nflag)
+ && (fp = fopen("/etc/atalk.names", "r"))) {
+ char line[256];
+ int i1, i2, i3;
+
+ while (fgets(line, sizeof(line), fp)) {
+ if (line[0] == '\n' || line[0] == 0 || line[0] == '#')
+ continue;
+ if (sscanf(line, "%d.%d.%d %s", &i1, &i2, &i3,
+ nambuf) == 4)
+ /* got a hostname. */
+ i3 |= ((i1 << 8) | i2) << 8;
+ else if (sscanf(line, "%d.%d %s", &i1, &i2,
+ nambuf) == 3)
+ /* got a net name */
+ i3 = (((i1 << 8) | i2) << 8) | 255;
+ else
+ continue;
+
+ for (tp = &hnametable[i3 & (HASHNAMESIZE-1)];
+ tp->nxt; tp = tp->nxt)
+ ;
+ tp->addr = i3;
+ tp->nxt = (struct hnamemem *)calloc(1, sizeof(*tp));
+ i3 = strlen(nambuf) + 1;
+ tp->name = strcpy(malloc((unsigned) i3), nambuf);
+ }
+ fclose(fp);
+ }
+
+ for (tp = &hnametable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
+ if (tp->addr == i)
+ return (tp->name);
+
+ /* didn't have the node name -- see if we've got the net name */
+ i |= 255;
+ for (tp2 = &hnametable[i & (HASHNAMESIZE-1)]; tp2->nxt; tp2 = tp2->nxt)
+ if (tp2->addr == i) {
+ tp->addr = (atnet << 8) | athost;
+ tp->nxt = (struct hnamemem *)calloc(1, sizeof(*tp));
+ (void)sprintf(nambuf, "%s.%d", tp2->name, athost);
+ i = strlen(nambuf) + 1;
+ tp->name = strcpy(malloc((unsigned) i), nambuf);
+ return (tp->name);
+ }
+
+ tp->addr = (atnet << 8) | athost;
+ tp->nxt = (struct hnamemem *)calloc(1, sizeof(*tp));
+ if (athost != 255)
+ (void)sprintf(nambuf, "%d.%d.%d",
+ atnet >> 8, atnet & 0xff, athost);
+ else
+ (void)sprintf(nambuf, "%d.%d", atnet >> 8, atnet & 0xff);
+ i = strlen(nambuf) + 1;
+ tp->name = strcpy(malloc((unsigned) i), nambuf);
+
+ return (tp->name);
+}
diff --git a/usr.sbin/tcpdump/tcpdump/print-bootp.c b/usr.sbin/tcpdump/tcpdump/print-bootp.c
new file mode 100644
index 000000000000..0641d825ff4f
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-bootp.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Format and print bootp packets.
+ */
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: print-bootp.c,v 1.17 91/11/14 22:21:34 leres Exp $ (LBL)";
+#endif
+
+#include <stdio.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <strings.h>
+#include <ctype.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "bootp.h"
+
+void rfc1048_print();
+void cmu_print();
+
+/*
+ * Print bootp requests
+ */
+void
+bootp_print(bp, length, sport, dport)
+ register struct bootp *bp;
+ int length;
+ u_short sport, dport;
+{
+ static char tstr[] = " [|bootp]";
+ static unsigned char vm_cmu[4] = VM_CMU;
+ static unsigned char vm_rfc1048[4] = VM_RFC1048;
+ u_char *ep;
+
+#define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc
+
+ /* Note funny sized packets */
+ if (length != sizeof(struct bootp))
+ (void)printf(" [len=%d]", length);
+
+ /* 'ep' points to the end of avaible data. */
+ ep = (u_char *)snapend;
+
+ switch (bp->bp_op) {
+
+ case BOOTREQUEST:
+ /* Usually, a request goes from a client to a server */
+ if (sport != IPPORT_BOOTPC || dport != IPPORT_BOOTPS)
+ printf(" (request)");
+ break;
+
+ case BOOTREPLY:
+ /* Usually, a reply goes from a server to a client */
+ if (sport != IPPORT_BOOTPS || dport != IPPORT_BOOTPC)
+ printf(" (reply)");
+ break;
+
+ default:
+ printf(" bootp-#%d", bp->bp_op);
+ }
+
+ NTOHL(bp->bp_xid);
+ NTOHS(bp->bp_secs);
+
+ /* The usual hardware address type is 1 (10Mb Ethernet) */
+ if (bp->bp_htype != 1)
+ printf(" htype-#%d", bp->bp_htype);
+
+ /* The usual length for 10Mb Ethernet address is 6 bytes */
+ if (bp->bp_htype != 1 || bp->bp_hlen != 6)
+ printf(" hlen:%d", bp->bp_hlen);
+
+ /* Only print interesting fields */
+ if (bp->bp_hops)
+ printf(" hops:%d", bp->bp_hops);
+ if (bp->bp_xid)
+ printf(" xid:0x%x", bp->bp_xid);
+ if (bp->bp_secs)
+ printf(" secs:%d", bp->bp_secs);
+
+ /* Client's ip address */
+ TCHECK(bp->bp_ciaddr, sizeof(bp->bp_ciaddr));
+ if (bp->bp_ciaddr.s_addr)
+ printf(" C:%s", ipaddr_string(&bp->bp_ciaddr));
+
+ /* 'your' ip address (bootp client) */
+ TCHECK(bp->bp_yiaddr, sizeof(bp->bp_yiaddr));
+ if (bp->bp_yiaddr.s_addr)
+ printf(" Y:%s", ipaddr_string(&bp->bp_yiaddr));
+
+ /* Server's ip address */
+ TCHECK(bp->bp_siaddr, sizeof(bp->bp_siaddr));
+ if (bp->bp_siaddr.s_addr)
+ printf(" S:%s", ipaddr_string(&bp->bp_siaddr));
+
+ /* Gateway's ip address */
+ TCHECK(bp->bp_giaddr, sizeof(bp->bp_giaddr));
+ if (bp->bp_giaddr.s_addr)
+ printf(" G:%s", ipaddr_string(&bp->bp_giaddr));
+
+ /* Client's Ethernet address */
+ if (bp->bp_htype == 1 && bp->bp_hlen == 6) {
+ register struct ether_header *eh;
+ register char *e;
+
+ TCHECK(bp->bp_chaddr[0], 6);
+ eh = (struct ether_header *)packetp;
+ if (bp->bp_op == BOOTREQUEST)
+ e = (char *)ESRC(eh);
+ else if (bp->bp_op == BOOTREPLY)
+ e = (char *)EDST(eh);
+ else
+ e = 0;
+ if (e == 0 || bcmp((char *)bp->bp_chaddr, e, 6) != 0)
+ printf(" ether %s", etheraddr_string(bp->bp_chaddr));
+ }
+
+ TCHECK(bp->bp_sname[0], sizeof(bp->bp_sname));
+ if (*bp->bp_sname) {
+ printf(" sname ");
+ if (printfn(bp->bp_sname, ep)) {
+ fputs(tstr + 1, stdout);
+ return;
+ }
+ }
+ TCHECK(bp->bp_file[0], sizeof(bp->bp_file));
+ if (*bp->bp_file) {
+ printf(" file ");
+ if (printfn(bp->bp_file, ep)) {
+ fputs(tstr + 1, stdout);
+ return;
+ }
+ }
+
+ /* Don't try to decode the vendor buffer unless we're verbose */
+ if (vflag <= 0)
+ return;
+
+ TCHECK(bp->bp_vend[0], sizeof(bp->bp_vend));
+ printf(" vend");
+ if (bcmp(bp->bp_vend, vm_rfc1048, sizeof(u_long)) == 0)
+ rfc1048_print(bp->bp_vend, sizeof(bp->bp_vend));
+ else if (bcmp(bp->bp_vend, vm_cmu, sizeof(u_long)) == 0)
+ cmu_print(bp->bp_vend, sizeof(bp->bp_vend));
+ else {
+ u_long ul;
+
+ bcopy((char *)bp->bp_vend, (char *)&ul, sizeof(ul));
+ printf("-#0x%x", ul);
+ }
+
+ return;
+trunc:
+ fputs(tstr, stdout);
+#undef TCHECK
+}
+
+void
+rfc1048_print(bp, length)
+ register u_char *bp;
+ int length;
+{
+ u_char tag;
+ u_char *ep;
+ register int i;
+ u_long ul;
+
+ printf("-rfc1048");
+
+ /* Step over magic cookie */
+ bp += sizeof(long);
+
+ /* Setup end pointer */
+ ep = bp + length;
+
+ while (bp < ep) {
+ tag = *bp++;
+ i = *bp++;
+ switch (tag) {
+
+ case TAG_PAD:
+ /* no-op */
+ break;
+
+ case TAG_SUBNET_MASK:
+ ul = 0;
+ bcopy((char *)bp, (char *)&ul, i);
+ printf(" SM:%s", ipaddr_string(&ul));
+ break;
+
+ case TAG_TIME_SERVER:
+ ul = 0;
+ bcopy((char *)bp, (char *)&ul, i);
+ printf(" TS:%s", ipaddr_string(&ul));
+ break;
+
+ case TAG_GATEWAY:
+ ul = 0;
+ bcopy((char *)bp, (char *)&ul, i);
+ printf(" G:%s", ipaddr_string(&ul));
+ break;
+
+ case TAG_TIME_OFFSET:
+ case TAG_NAME_SERVER:
+ case TAG_DOMAIN_SERVER:
+ case TAG_LOG_SERVER:
+ case TAG_COOKIE_SERVER:
+ case TAG_LPR_SERVER:
+ case TAG_IMPRESS_SERVER:
+ case TAG_RLP_SERVER:
+ case TAG_HOSTNAME:
+ case TAG_BOOTSIZE:
+ printf(" tag-#%d", tag);
+ if (i == sizeof(long)) {
+ bcopy((char *)bp, (char *)&ul, sizeof(long));
+ printf(":0x%x", ul);
+ } else
+ printf(":?");
+ break;
+
+ case TAG_END:
+ return;
+
+ default:
+ printf("[tag-#%d]", tag);
+ return;
+ }
+ }
+}
+
+void
+cmu_print(bp, length)
+ register u_char *bp;
+ int length;
+{
+ /* XXX not really implemented */
+ printf("-cmu [...]");
+}
diff --git a/usr.sbin/tcpdump/tcpdump/print-domain.c b/usr.sbin/tcpdump/tcpdump/print-domain.c
new file mode 100644
index 000000000000..04cf5aa47ea6
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-domain.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: print-domain.c,v 1.16 92/05/25 14:28:59 mccanne Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <arpa/nameser.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+static char *ns_ops[] = {
+ "", " inv_q", " stat", " op3", " op4", " op5", " op6", " op7",
+ " op8", " updataA", " updateD", " updateDA",
+ " updateM", " updateMA", " zoneInit", " zoneRef",
+};
+
+static char *ns_resp[] = {
+ "", " FormErr", " ServFail", " NXDomain",
+ " NotImp", " Refused", " Resp6", " Resp7",
+ " Resp8", " Resp9", " Resp10", " Resp11",
+ " Resp12", " Resp13", " Resp14", " NoChange",
+};
+
+
+/* skip over a domain name */
+static u_char *
+ns_nskip(cp)
+ register u_char *cp;
+{
+ register u_char i;
+
+ if (((i = *cp++) & 0xc0) == 0xc0)
+ return (cp + 1);
+ while (i) {
+ cp += i;
+ i = *cp++;
+ }
+ return (cp);
+}
+
+/* print a domain name */
+static void
+ns_nprint(cp, bp, ep)
+ register u_char *cp;
+ register u_char *bp;
+ register u_char *ep;
+{
+ register u_int i;
+
+ putchar(' ');
+ if (i = *cp++)
+ while (i && cp < ep) {
+ if ((i & 0xc0) == 0xc0) {
+ cp = bp + (((i << 8) | *cp) & 0x3fff);
+ i = *cp++;
+ continue;
+ }
+ do {
+ putchar(*cp++);
+ } while (--i);
+ putchar('.');
+ i = *cp++;
+ }
+ else
+ putchar('.');
+}
+
+
+/* print a query */
+static void
+ns_qprint(cp, bp, ep)
+ register u_char *cp;
+ register u_char *bp;
+ register u_char *ep;
+{
+ u_char *np = cp;
+ register u_int i;
+
+ cp = ns_nskip(cp);
+
+ if (cp + 4 > ep)
+ return;
+
+ /* print the qtype and qclass (if it's not IN) */
+ i = *cp++ << 8;
+ switch (i |= *cp++) {
+ case T_A: printf(" A"); break;
+ case T_NS: printf(" NS"); break;
+ case T_MD: printf(" MD"); break;
+ case T_MF: printf(" MF"); break;
+ case T_CNAME: printf(" CNAME"); break;
+ case T_SOA: printf(" SOA"); break;
+ case T_MB: printf(" MB"); break;
+ case T_MG: printf(" MG"); break;
+ case T_MR: printf(" MR"); break;
+ case T_NULL: printf(" NULL"); break;
+ case T_WKS: printf(" WKS"); break;
+ case T_PTR: printf(" PTR"); break;
+ case T_HINFO: printf(" HINFO"); break;
+ case T_MINFO: printf(" MINFO"); break;
+ case T_MX: printf(" MX"); break;
+ case T_UINFO: printf(" UINFO"); break;
+ case T_UID: printf(" UID"); break;
+ case T_GID: printf(" GID"); break;
+#ifdef T_UNSPEC
+ case T_UNSPEC: printf(" UNSPEC"); break;
+#endif
+ case T_AXFR: printf(" AXFR"); break;
+ case T_MAILB: printf(" MAILB"); break;
+ case T_MAILA: printf(" MAILA"); break;
+ case T_ANY: printf(" ANY"); break;
+ default: printf(" Type%d", i); break;
+ }
+ i = *cp++ << 8;
+ if ((i |= *cp++) != C_IN)
+ if (i == C_ANY)
+ printf("(c_any)");
+ else
+ printf("(Class %d)", i);
+
+ putchar('?');
+ ns_nprint(np, bp, ep);
+}
+
+
+/* print a reply */
+static void
+ns_rprint(cp, bp, ep)
+ register u_char *cp;
+ register u_char *bp;
+ register u_char *ep;
+{
+ register u_int i;
+ u_short typ;
+
+ cp = ns_nskip(cp);
+
+ if (cp + 10 > ep)
+ return;
+
+ /* print the type/qtype and class (if it's not IN) */
+ typ = *cp++ << 8;
+ typ |= *cp++;
+ i = *cp++ << 8;
+ if ((i |= *cp++) != C_IN)
+ if (i == C_ANY)
+ printf("(c_any)");
+ else
+ printf("(Class %d)", i);
+
+ /* ignore ttl & len */
+ cp += 6;
+ switch (typ) {
+ case T_A: printf(" A %s", ipaddr_string(cp)); break;
+ case T_NS: printf(" NS"); ns_nprint(cp, bp, ep); break;
+ case T_MD: printf(" MD"); break;
+ case T_MF: printf(" MF"); break;
+ case T_CNAME: printf(" CNAME"); ns_nprint(cp, bp, ep); break;
+ case T_SOA: printf(" SOA"); break;
+ case T_MB: printf(" MB"); break;
+ case T_MG: printf(" MG"); break;
+ case T_MR: printf(" MR"); break;
+ case T_NULL: printf(" NULL"); break;
+ case T_WKS: printf(" WKS"); break;
+ case T_PTR: printf(" PTR"); ns_nprint(cp, bp, ep); break;
+ case T_HINFO: printf(" HINFO"); break;
+ case T_MINFO: printf(" MINFO"); break;
+ case T_MX: printf(" MX"); ns_nprint(cp+2, bp, ep);
+#ifndef TCPDUMP_ALIGN
+ printf(" %d", *(short *)cp);
+#else
+ {
+ u_short x = *cp | cp[1] << 8;
+ printf(" %d", ntohs(x));
+ }
+#endif
+ break;
+ case T_UINFO: printf(" UINFO"); break;
+ case T_UID: printf(" UID"); break;
+ case T_GID: printf(" GID"); break;
+#ifdef T_UNSPEC
+ case T_UNSPEC: printf(" UNSPEC"); break;
+#endif
+ case T_AXFR: printf(" AXFR"); break;
+ case T_MAILB: printf(" MAILB"); break;
+ case T_MAILA: printf(" MAILA"); break;
+ case T_ANY: printf(" ANY"); break;
+ default: printf(" Type%d", typ); break;
+ }
+}
+
+void
+ns_print(np, length)
+ register HEADER *np;
+ int length;
+{
+ u_char *ep = (u_char *)snapend;
+
+ /* get the byte-order right */
+ NTOHS(np->id);
+ NTOHS(np->qdcount);
+ NTOHS(np->ancount);
+ NTOHS(np->nscount);
+ NTOHS(np->arcount);
+
+ if (np->qr) {
+ /* this is a response */
+ printf(" %d%s%s%s%s%s",
+ np->id,
+ ns_ops[np->opcode],
+ ns_resp[np->rcode],
+ np->aa? "*" : "",
+ np->ra? "" : "-",
+ np->tc? "|" : "");
+ if (np->qdcount != 1)
+ printf(" [%dq]", np->qdcount);
+ printf(" %d/%d/%d", np->ancount, np->nscount, np->arcount);
+ if (np->ancount)
+ ns_rprint(ns_nskip((u_char *)(np + 1)) + 4,
+ (u_char *)np, ep);
+ }
+ else {
+ /* this is a request */
+ printf(" %d%s%s",
+ np->id,
+ ns_ops[np->opcode],
+ np->rd? "+" : "");
+
+ /* any weirdness? */
+ if (*(((u_short *)np)+1) & htons(0x6ff))
+ printf(" [b2&3=0x%x]", ntohs(*(((u_short *)np)+1)));
+
+ if (np->opcode == IQUERY) {
+ if (np->qdcount)
+ printf(" [%dq]", np->qdcount);
+ if (np->ancount != 1)
+ printf(" [%da]", np->ancount);
+ }
+ else {
+ if (np->ancount)
+ printf(" [%da]", np->ancount);
+ if (np->qdcount != 1)
+ printf(" [%dq]", np->qdcount);
+ }
+ if (np->nscount)
+ printf(" [%dn]", np->nscount);
+ if (np->arcount)
+ printf(" [%dau]", np->arcount);
+
+ ns_qprint((u_char *)(np + 1), (u_char *)np, ep);
+ }
+ printf(" (%d)", length);
+}
diff --git a/usr.sbin/tcpdump/tcpdump/print-egp.c b/usr.sbin/tcpdump/tcpdump/print-egp.c
new file mode 100644
index 000000000000..a88a68364525
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-egp.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 1991 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Lawrence Berkeley Laboratory,
+ * Berkeley, CA. The name of the University may not be used to
+ * endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Initial contribution from Jeff Honig (jch@MITCHELL.CIT.CORNELL.EDU).
+ */
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netdb.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+struct egp_packet {
+ u_char egp_version;
+#define EGP_VERSION 2
+ u_char egp_type;
+#define EGPT_ACQUIRE 3
+#define EGPT_REACH 5
+#define EGPT_POLL 2
+#define EGPT_UPDATE 1
+#define EGPT_ERROR 8
+ u_char egp_code;
+#define EGPC_REQUEST 0
+#define EGPC_CONFIRM 1
+#define EGPC_REFUSE 2
+#define EGPC_CEASE 3
+#define EGPC_CEASEACK 4
+#define EGPC_HELLO 0
+#define EGPC_HEARDU 1
+ u_char egp_status;
+#define EGPS_UNSPEC 0
+#define EGPS_ACTIVE 1
+#define EGPS_PASSIVE 2
+#define EGPS_NORES 3
+#define EGPS_ADMIN 4
+#define EGPS_GODOWN 5
+#define EGPS_PARAM 6
+#define EGPS_PROTO 7
+#define EGPS_INDET 0
+#define EGPS_UP 1
+#define EGPS_DOWN 2
+#define EGPS_UNSOL 0x80
+ u_short egp_checksum;
+ u_short egp_as;
+ u_short egp_sequence;
+ union {
+ u_short egpu_hello;
+ u_char egpu_gws[2];
+ u_short egpu_reason;
+#define EGPR_UNSPEC 0
+#define EGPR_BADHEAD 1
+#define EGPR_BADDATA 2
+#define EGPR_NOREACH 3
+#define EGPR_XSPOLL 4
+#define EGPR_NORESP 5
+#define EGPR_UVERSION 6
+ } egp_handg;
+#define egp_hello egp_handg.egpu_hello
+#define egp_intgw egp_handg.egpu_gws[0]
+#define egp_extgw egp_handg.egpu_gws[1]
+#define egp_reason egp_handg.egpu_reason
+ union {
+ u_short egpu_poll;
+ u_long egpu_sourcenet;
+ } egp_pands;
+#define egp_poll egp_pands.egpu_poll
+#define egp_sourcenet egp_pands.egpu_sourcenet
+};
+
+char *egp_acquire_codes[] = {
+ "request",
+ "confirm",
+ "refuse",
+ "cease",
+ "cease_ack"
+};
+
+char *egp_acquire_status[] = {
+ "unspecified",
+ "active_mode",
+ "passive_mode",
+ "insufficient_resources",
+ "administratively_prohibited",
+ "going_down",
+ "parameter_violation",
+ "protocol_violation"
+};
+
+char *egp_reach_codes[] = {
+ "hello",
+ "i-h-u"
+};
+
+char *egp_status_updown[] = {
+ "indeterminate",
+ "up",
+ "down"
+};
+
+char *egp_reasons[] = {
+ "unspecified",
+ "bad_EGP_header_format",
+ "bad_EGP_data_field_format",
+ "reachability_info_unavailable",
+ "excessive_polling_rate",
+ "no_response",
+ "unsupported_version"
+};
+
+static void
+egpnrprint(egp, length)
+ register struct egp_packet *egp;
+ register int length;
+{
+ register u_char *cp, *ep;
+#define TCHECK(n) if (cp > ep - n) goto trunc
+ register u_long addr;
+ register u_long net;
+ register int netlen;
+ int gateways, distances, networks;
+ int t_gateways;
+ char *comma;
+
+ addr = egp->egp_sourcenet;
+ if (IN_CLASSA(addr)) {
+ net = addr & IN_CLASSA_NET;
+ netlen = 1;
+ } else if (IN_CLASSB(addr)) {
+ net = addr & IN_CLASSB_NET;
+ netlen = 2;
+ } else if (IN_CLASSC(addr)) {
+ net = addr & IN_CLASSC_NET;
+ netlen = 3;
+ } else {
+ net = 0;
+ netlen = 0;
+ }
+ cp = (u_char *)(egp + 1);
+ ep = snapend;
+
+ t_gateways = egp->egp_intgw + egp->egp_extgw;
+ for (gateways = 0; gateways < t_gateways; ++gateways) {
+ /* Pickup host part of gateway address */
+ addr = 0;
+ TCHECK(4 - netlen);
+ switch (netlen) {
+
+ case 1:
+ addr = *cp++;
+ /* fall through */
+ case 2:
+ addr = (addr << 8) | *cp++;
+ /* fall through */
+ case 3:
+ addr = (addr << 8) | *cp++;
+ }
+ addr |= net;
+ TCHECK(1);
+ distances = *cp++;
+ printf(" %s %s ",
+ gateways < egp->egp_intgw ? "int" : "ext",
+ intoa(addr));
+
+ comma = "";
+ putchar('(');
+ while (--distances >= 0) {
+ TCHECK(2);
+ printf("%sd%d:", comma, (int)*cp++);
+ comma = ", ";
+ networks = *cp++;
+ while (--networks >= 0) {
+ /* Pickup network number */
+ TCHECK(1);
+ addr = (u_long)*cp++ << 24;
+ if (IN_CLASSB(addr)) {
+ TCHECK(1);
+ addr |= (u_long)*cp++ << 16;
+ } else if (!IN_CLASSA(addr)) {
+ TCHECK(2);
+ addr |= (u_long)*cp++ << 16;
+ addr |= (u_long)*cp++ << 8;
+ }
+ printf(" %s", intoa(addr));
+ }
+ }
+ putchar(')');
+ }
+ return;
+trunc:
+ fputs("[|]", stdout);
+}
+
+void
+egp_print(egp, length, ip)
+ register struct egp_packet *egp;
+ register int length;
+ register struct ip *ip;
+{
+ register int status;
+ register int code;
+ register int type;
+
+ (void)printf("%s > %s: egp: ",
+ ipaddr_string(&ip->ip_src),
+ ipaddr_string(&ip->ip_dst));
+
+ if (egp->egp_version != EGP_VERSION) {
+ printf("[version %d]", egp->egp_version);
+ return;
+ }
+ printf("as:%d seq:%d", ntohs(egp->egp_as), ntohs(egp->egp_sequence));
+
+ type = egp->egp_type;
+ code = egp->egp_code;
+ status = egp->egp_status;
+
+ switch (type) {
+ case EGPT_ACQUIRE:
+ printf(" acquire");
+ switch (code) {
+ case EGPC_REQUEST:
+ case EGPC_CONFIRM:
+ printf(" %s", egp_acquire_codes[code]);
+ switch (status) {
+ case EGPS_UNSPEC:
+ case EGPS_ACTIVE:
+ case EGPS_PASSIVE:
+ printf(" %s", egp_acquire_status[status]);
+ break;
+
+ default:
+ printf(" [status %d]", status);
+ break;
+ }
+ printf(" hello:%d poll:%d",
+ ntohs(egp->egp_hello),
+ ntohs(egp->egp_poll));
+ break;
+
+ case EGPC_REFUSE:
+ case EGPC_CEASE:
+ case EGPC_CEASEACK:
+ printf(" %s", egp_acquire_codes[code]);
+ switch (status ) {
+ case EGPS_UNSPEC:
+ case EGPS_NORES:
+ case EGPS_ADMIN:
+ case EGPS_GODOWN:
+ case EGPS_PARAM:
+ case EGPS_PROTO:
+ printf(" %s", egp_acquire_status[status]);
+ break;
+
+ default:
+ printf("[status %d], status");
+ break;
+ }
+ break;
+
+ default:
+ printf("[code %d]", code);
+ break;
+ }
+ break;
+
+ case EGPT_REACH:
+ switch (code) {
+
+ case EGPC_HELLO:
+ case EGPC_HEARDU:
+ printf(" %s", egp_reach_codes[code]);
+ if (status <= EGPS_DOWN)
+ printf(" state:%s", egp_status_updown[status]);
+ else
+ printf(" [status %d], status");
+ break;
+
+ default:
+ printf("[reach code %d], code");
+ break;
+ }
+ break;
+
+ case EGPT_POLL:
+ printf(" poll");
+ if (egp->egp_status <= EGPS_DOWN)
+ printf(" state:%s", egp_status_updown[status]);
+ else
+ printf(" [status %d]", status);
+ printf(" net:%s", intoa(egp->egp_sourcenet));
+ break;
+
+ case EGPT_UPDATE:
+ printf(" update");
+ if (status & EGPS_UNSOL) {
+ status &= ~EGPS_UNSOL;
+ printf(" unsolicitied");
+ }
+ if (status <= EGPS_DOWN)
+ printf(" state:%s", egp_status_updown[status]);
+ else
+ printf(" [status %d]", status);
+ printf(" %s int %d ext %d",
+ intoa(egp->egp_sourcenet),
+ egp->egp_intgw,
+ egp->egp_extgw);
+ if (vflag)
+ egpnrprint(egp, length);
+ break;
+
+ case EGPT_ERROR:
+ printf(" error");
+ if (status <= EGPS_DOWN)
+ printf(" state:%s", egp_status_updown[status]);
+ else
+ printf(" [status]", status);
+
+ if (ntohs(egp->egp_reason) <= EGPR_UVERSION)
+ printf(" %s", egp_reasons[ntohs(egp->egp_reason)]);
+ else
+ printf(" [reason]", ntohs(egp->egp_reason));
+ break;
+
+ default:
+ printf("[type %d]", type);
+ break;
+ }
+}
diff --git a/usr.sbin/tcpdump/tcpdump/print-ether.c b/usr.sbin/tcpdump/tcpdump/print-ether.c
new file mode 100644
index 000000000000..2d01c17ce17c
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-ether.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: print-ether.c,v 1.22 91/10/07 20:18:28 leres Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+u_char *packetp;
+u_char *snapend;
+
+static inline void
+ether_print(ep, length)
+ register struct ether_header *ep;
+ int length;
+{
+ if (qflag)
+ (void)printf("%s %s %d: ",
+ etheraddr_string(ESRC(ep)),
+ etheraddr_string(EDST(ep)),
+ length);
+ else
+ (void)printf("%s %s %s %d: ",
+ etheraddr_string(ESRC(ep)),
+ etheraddr_string(EDST(ep)),
+ etherproto_string(ep->ether_type),
+ length);
+}
+
+/*
+ * This is the top level routine of the printer. 'p' is the points
+ * to the ether header of the packet, 'tvp' is the timestamp,
+ * 'length' is the length of the packet off the wire, and 'caplen'
+ * is the number of bytes actually captured.
+ */
+void
+ether_if_print(p, tvp, length, caplen)
+ u_char *p;
+ struct timeval *tvp;
+ int length;
+ int caplen;
+{
+ struct ether_header *ep;
+ register int i;
+
+ ts_print(tvp);
+
+ if (caplen < sizeof(struct ether_header)) {
+ printf("[|ether]");
+ goto out;
+ }
+
+ if (eflag)
+ ether_print((struct ether_header *)p, length);
+
+ /*
+ * Some printers want to get back at the ethernet addresses,
+ * and/or check that they're not walking off the end of the packet.
+ * Rather than pass them all the way down, we set these globals.
+ */
+ packetp = p;
+ snapend = p + caplen;
+
+ length -= sizeof(struct ether_header);
+ ep = (struct ether_header *)p;
+ p += sizeof(struct ether_header);
+ switch (ntohs(ep->ether_type)) {
+
+ case ETHERTYPE_IP:
+ ip_print((struct ip *)p, length);
+ break;
+
+ case ETHERTYPE_ARP:
+ case ETHERTYPE_REVARP:
+ arp_print((struct ether_arp *)p, length, caplen - sizeof(*ep));
+ break;
+
+ default:
+ if (!eflag)
+ ether_print(ep, length);
+ if (!xflag && !qflag)
+ default_print((u_short *)p, caplen - sizeof(*ep));
+ break;
+ }
+ if (xflag)
+ default_print((u_short *)p, caplen - sizeof(*ep));
+ out:
+ putchar('\n');
+}
diff --git a/usr.sbin/tcpdump/tcpdump/print-fddi.c b/usr.sbin/tcpdump/tcpdump/print-fddi.c
new file mode 100644
index 000000000000..77831126088e
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-fddi.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#)$Header: print-fddi.c,v 1.4 92/02/03 16:04:02 van Exp $ (LBL)";
+#endif
+
+#ifdef FDDI
+#include <stdio.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/mbuf.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <net/bpf.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+/*
+ * NOTE: This is a very preliminary hack for FDDI support.
+ * There are all sorts of wired in constants & nothing (yet)
+ * to print SMT packets as anything other than hex dumps.
+ * Most of the necessary changes are waiting on my redoing
+ * the "header" that a kernel fddi driver supplies to bpf: I
+ * want it to look like one byte of 'direction' (0 or 1
+ * depending on whether the packet was inbound or outbound),
+ * two bytes of system/driver dependent data (anything an
+ * implementor thinks would be useful to filter on and/or
+ * save per-packet, then the real 21-byte FDDI header.
+ * Steve McCanne & I have also talked about adding the
+ * 'direction' byte to all bpf headers (e.g., in the two
+ * bytes of padding on an ethernet header). It's not clear
+ * we could do this in a backwards compatible way & we hate
+ * the idea of an incompatible bpf change. Discussions are
+ * proceeding.
+ *
+ * Also, to really support FDDI (and better support 802.2
+ * over ethernet) we really need to re-think the rather simple
+ * minded assumptions about fixed length & fixed format link
+ * level headers made in gencode.c. One day...
+ *
+ * - vj
+ */
+
+/* XXX This goes somewhere else. */
+#define FDDI_HDRLEN 21
+
+static u_char fddi_bit_swap[] = {
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+};
+
+static inline void
+fddi_print(p, length)
+ u_char *p;
+ int length;
+{
+ u_char fsrc[6], fdst[6];
+ register char *srcname, *dstname;
+ register int i;
+
+ /*
+ * bit-swap the fddi addresses (isn't the IEEE standards
+ * process wonderful!) then convert them to names.
+ */
+
+ for (i = 0; i < sizeof(fdst); ++i)
+ fdst[i] = fddi_bit_swap[p[i+1]];
+ for (i = 0; i < sizeof(fsrc); ++i)
+ fsrc[i] = fddi_bit_swap[p[i+7]];
+ dstname = etheraddr_string(fdst);
+ srcname = etheraddr_string(fsrc);
+
+ if (vflag)
+ printf("%s %s %02x %02x %02x %02x %02x%02x%02x %s %d: ",
+ dstname, srcname,
+ p[0],
+ p[13], p[14], p[15],
+ p[16], p[17], p[18],
+ etherproto_string((p[19] << 8) | p[20]),
+ length);
+ else if (qflag)
+ printf("%s %s %d: ", dstname, srcname, length);
+ else
+ printf("%s %s %02x %s %d: ",
+ dstname, srcname,
+ p[0],
+ etherproto_string((p[19] << 8) | p[20]),
+ length);
+}
+
+void
+fddi_if_print(p, tvp, length, caplen)
+ u_char *p;
+ struct timeval *tvp;
+ int length;
+ int caplen;
+{
+ struct ip *ip;
+ u_short type;
+
+ ts_print(tvp);
+
+ if (caplen < FDDI_HDRLEN) {
+ printf("[|fddi]");
+ goto out;
+ }
+
+ /*
+ * Some printers want to get back at the link level addresses,
+ * and/or check that they're not walking off the end of the packet.
+ * Rather than pass them all the way down, we set these globals.
+ */
+ packetp = (u_char *)p;
+ snapend = (u_char *)p + caplen;
+
+ /*
+ * If the frame is not an LLC frame or is not an LLC/UI frame
+ * or doesn't have SNAP as a dest NSAP, use the default printer.
+ * (XXX - should interpret SMT packets here.)
+ */
+ if ((p[0] & 0xf8) != 0x50)
+ /* not LLC frame -- use default printer */
+ type = 0;
+ else if ((p[15] &~ 0x10) != 0x03)
+ /* not UI frame -- use default printer */
+ type = 0;
+ else if (p[13] != 170)
+ /* DSAP not SNAP -- use default printer */
+ type = 0;
+ else
+ type = (p[19] << 8) | p[20];
+ if (eflag)
+ fddi_print(p, length);
+
+ length -= FDDI_HDRLEN;
+ p += FDDI_HDRLEN;
+
+ switch (ntohs(type)) {
+
+ case ETHERTYPE_IP:
+ ip_print((struct ip *)p, length);
+ break;
+
+ case ETHERTYPE_ARP:
+ case ETHERTYPE_REVARP:
+ arp_print((struct ether_arp *)p, length, caplen - FDDI_HDRLEN);
+ break;
+
+ default:
+ if (!eflag)
+ fddi_print(p, length);
+ if (!xflag && !qflag)
+ default_print((u_short *)p, caplen - FDDI_HDRLEN);
+ break;
+ }
+ if (xflag)
+ default_print((u_short *)p, caplen - sizeof(FDDI_HDRLEN));
+out:
+ putchar('\n');
+}
+#else
+#include <stdio.h>
+void
+fddi_if_print()
+{
+ void error();
+
+ error("not configured for fddi");
+ /* NOTREACHED */
+}
+#endif
diff --git a/usr.sbin/tcpdump/tcpdump/print-icmp.c b/usr.sbin/tcpdump/tcpdump/print-icmp.c
new file mode 100644
index 000000000000..928d8664517d
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-icmp.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: print-icmp.c,v 1.11 91/03/27 17:42:58 leres Exp $ (LBL)";
+#endif
+
+#include <stdio.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <netinet/ip_icmp.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+void
+icmp_print(dp, ip)
+ register struct icmp *dp;
+ register struct ip *ip;
+{
+ char buf[256];
+ register char *str = buf;
+ register struct ip *oip;
+ register struct udphdr *ouh;
+ register int hlen;
+ u_char *ep;
+
+#define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc
+
+ /* 'ep' points to the end of avaible data. */
+ ep = (u_char *)snapend;
+
+ (void)printf("%s > %s: ",
+ ipaddr_string(&ip->ip_src),
+ ipaddr_string(&ip->ip_dst));
+ strcpy(str, "[?]");
+
+ TCHECK(dp->icmp_code, sizeof(dp->icmp_code));
+ switch (dp->icmp_type) {
+ case ICMP_ECHOREPLY:
+ str = "echo reply";
+ break;
+ case ICMP_UNREACH:
+ TCHECK(dp->icmp_ip.ip_dst, sizeof(dp->icmp_ip.ip_dst));
+ switch (dp->icmp_code) {
+ case ICMP_UNREACH_NET:
+ (void)sprintf(buf, "net %s unreachable",
+ ipaddr_string(&dp->icmp_ip.ip_dst));
+ break;
+ case ICMP_UNREACH_HOST:
+ (void)sprintf(buf, "host %s unreachable",
+ ipaddr_string(&dp->icmp_ip.ip_dst));
+ break;
+ case ICMP_UNREACH_PROTOCOL:
+ TCHECK(dp->icmp_ip.ip_p, sizeof(dp->icmp_ip.ip_p));
+ (void)sprintf(buf, "%s protocol %d unreachable",
+ ipaddr_string(&dp->icmp_ip.ip_dst),
+ dp->icmp_ip.ip_p);
+ break;
+ case ICMP_UNREACH_PORT:
+ TCHECK(dp->icmp_ip.ip_p, sizeof(dp->icmp_ip.ip_p));
+ oip = &dp->icmp_ip;
+ hlen = oip->ip_hl * 4;
+ ouh = (struct udphdr *)(((u_char *)oip) + hlen);
+ NTOHS(ouh->uh_dport);
+ switch (oip->ip_p) {
+ case IPPROTO_TCP:
+ (void)sprintf(buf,
+ "%s tcp port %s unreachable",
+ ipaddr_string(&oip->ip_dst),
+ tcpport_string(ouh->uh_dport));
+ break;
+ case IPPROTO_UDP:
+ (void)sprintf(buf,
+ "%s udp port %s unreachable",
+ ipaddr_string(&oip->ip_dst),
+ udpport_string(ouh->uh_dport));
+ break;
+ default:
+ (void)sprintf(buf,
+ "%s protocol %d port %d unreachable",
+ ipaddr_string(&oip->ip_dst),
+ oip->ip_p, ouh->uh_dport);
+ break;
+ }
+ break;
+ case ICMP_UNREACH_NEEDFRAG:
+ (void)sprintf(buf, "%s unreachable - need to frag",
+ ipaddr_string(&dp->icmp_ip.ip_dst));
+ break;
+ case ICMP_UNREACH_SRCFAIL:
+ (void)sprintf(buf,
+ "%s unreachable - source route failed",
+ ipaddr_string(&dp->icmp_ip.ip_dst));
+ break;
+ }
+ break;
+ case ICMP_SOURCEQUENCH:
+ str = "source quench";
+ break;
+ case ICMP_REDIRECT:
+ TCHECK(dp->icmp_ip.ip_dst, sizeof(dp->icmp_ip.ip_dst));
+ switch (dp->icmp_code) {
+ case ICMP_REDIRECT_NET:
+ (void)sprintf(buf, "redirect %s to net %s",
+ ipaddr_string(&dp->icmp_ip.ip_dst),
+ ipaddr_string(&dp->icmp_gwaddr));
+ break;
+ case ICMP_REDIRECT_HOST:
+ (void)sprintf(buf, "redirect %s to host %s",
+ ipaddr_string(&dp->icmp_ip.ip_dst),
+ ipaddr_string(&dp->icmp_gwaddr));
+ break;
+ case ICMP_REDIRECT_TOSNET:
+ (void)sprintf(buf, "redirect-tos %s to net %s",
+ ipaddr_string(&dp->icmp_ip.ip_dst),
+ ipaddr_string(&dp->icmp_gwaddr));
+ break;
+ case ICMP_REDIRECT_TOSHOST:
+ (void)sprintf(buf, "redirect-tos %s to host %s",
+ ipaddr_string(&dp->icmp_ip.ip_dst),
+ ipaddr_string(&dp->icmp_gwaddr));
+ break;
+ }
+ break;
+ case ICMP_ECHO:
+ str = "echo request";
+ break;
+ case ICMP_TIMXCEED:
+ TCHECK(dp->icmp_ip.ip_dst, sizeof(dp->icmp_ip.ip_dst));
+ switch (dp->icmp_code) {
+ case ICMP_TIMXCEED_INTRANS:
+ str = "time exceeded in-transit";
+ break;
+ case ICMP_TIMXCEED_REASS:
+ str = "ip reassembly time exceeded";
+ break;
+ }
+ break;
+ case ICMP_PARAMPROB:
+ if (dp->icmp_code)
+ (void)sprintf(buf, "parameter problem - code %d",
+ dp->icmp_code);
+ else {
+ TCHECK(dp->icmp_pptr, sizeof(dp->icmp_pptr));
+ (void)sprintf(buf, "parameter problem - octet %d",
+ dp->icmp_pptr);
+ }
+ break;
+ case ICMP_TSTAMP:
+ str = "time stamp request";
+ break;
+ case ICMP_TSTAMPREPLY:
+ str = "time stamp reply";
+ break;
+ case ICMP_IREQ:
+ str = "information request";
+ break;
+ case ICMP_IREQREPLY:
+ str = "information reply";
+ break;
+ case ICMP_MASKREQ:
+ str = "address mask request";
+ break;
+ case ICMP_MASKREPLY:
+ TCHECK(dp->icmp_mask, sizeof(dp->icmp_mask));
+ (void)sprintf(buf, "address mask is 0x%08x", dp->icmp_mask);
+ break;
+ }
+ (void)printf("icmp: %s", str);
+ return;
+trunc:
+ fputs("[|icmp]", stdout);
+#undef TCHECK
+}
diff --git a/usr.sbin/tcpdump/tcpdump/print-ip.c b/usr.sbin/tcpdump/tcpdump/print-ip.c
new file mode 100644
index 000000000000..8716a016d14a
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-ip.c
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: print-ip.c,v 1.28 92/05/25 14:29:02 mccanne Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+void
+igmp_print(cp, len, ip)
+ register u_char *cp;
+ register int len;
+ register struct ip *ip;
+{
+ register u_char *ep = (u_char *)snapend;
+
+ (void)printf("%s > %s: ",
+ ipaddr_string(&ip->ip_src),
+ ipaddr_string(&ip->ip_dst));
+
+ if (cp + 7 > ep) {
+ (void)printf("[|igmp]");
+ return;
+ }
+ switch (cp[0] & 0xf) {
+ case 1:
+ (void)printf("igmp query");
+ if (*(int *)&cp[4])
+ (void)printf(" [gaddr %s]", ipaddr_string(&cp[4]));
+ if (len != 8)
+ (void)printf(" [len %d]", len);
+ break;
+ case 2:
+ (void)printf("igmp report %s", ipaddr_string(&cp[4]));
+ if (len != 8)
+ (void)printf(" [len %d]", len);
+ break;
+ case 3:
+ (void)printf("igmp dvmrp", ipaddr_string(&cp[4]));
+ if (len < 8)
+ (void)printf(" [len %d]", len);
+ break;
+ default:
+ (void)printf("igmp-%d", cp[0] & 0xf);
+ break;
+ }
+ if ((cp[0] >> 4) != 1)
+ (void)printf(" [v%d]", cp[0] >> 4);
+ if (cp[1])
+ (void)printf(" [b1=0x%x]", cp[1]);
+}
+
+/*
+ * print the recorded route in an IP RR, LSRR or SSRR option.
+ */
+static void
+ip_printroute(type, cp, length)
+ char *type;
+ register u_char *cp;
+ int length;
+{
+ int ptr = cp[2] - 1;
+ int len;
+
+ printf(" %s{", type);
+ if ((length + 1) & 3)
+ printf(" [bad length %d]", length);
+ if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
+ printf(" [bad ptr %d]", cp[2]);
+
+ type = "";
+ for (len = 3; len < length; len += 4) {
+ if (ptr == len)
+ type = "#";
+#ifdef TCPDUMP_ALIGN
+ {
+ struct in_addr addr;
+ bcopy((char *)&cp[len], (char *)&addr, sizeof(addr));
+ printf("%s%s", type, ipaddr_string(&addr));
+ }
+#else
+ printf("%s%s", type, ipaddr_string(&cp[len]));
+#endif
+ type = " ";
+ }
+ printf("%s}", ptr == len? "#" : "");
+}
+
+/*
+ * print IP options.
+ */
+static void
+ip_optprint(cp, length)
+ register u_char *cp;
+ int length;
+{
+ int len;
+
+ for (; length > 0; cp += len, length -= len) {
+ int tt = *cp;
+
+ len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1];
+ if (&cp[1] >= snapend || cp + len > snapend) {
+ printf("[|ip]");
+ return;
+ }
+ switch (tt) {
+
+ case IPOPT_EOL:
+ printf(" EOL");
+ if (length > 1)
+ printf("-%d", length - 1);
+ return;
+
+ case IPOPT_NOP:
+ printf(" NOP");
+ break;
+
+ case IPOPT_TS:
+ printf(" TS{%d}", len);
+ break;
+
+ case IPOPT_SECURITY:
+ printf(" SECURITY{%d}", len);
+ break;
+
+ case IPOPT_RR:
+ printf(" RR{%d}=", len);
+ ip_printroute("RR", cp, len);
+ break;
+
+ case IPOPT_SSRR:
+ ip_printroute("SSRR", cp, len);
+ break;
+
+ case IPOPT_LSRR:
+ ip_printroute("LSRR", cp, len);
+ break;
+
+ default:
+ printf(" IPOPT-%d{%d}", cp[0], len);
+ break;
+ }
+ }
+}
+
+/*
+ * print an IP datagram.
+ */
+void
+ip_print(ip, length)
+ register struct ip *ip;
+ register int length;
+{
+ register int hlen;
+ register int len;
+ register unsigned char *cp;
+
+#ifdef TCPDUMP_ALIGN
+ static u_char *abuf;
+ /*
+ * The IP header is not word aligned, so copy into abuf.
+ * This will never happen with BPF. It does happen raw packet
+ * dumps from -r.
+ */
+ if ((int)ip & (sizeof(long)-1)) {
+ if (abuf == 0)
+ abuf = (u_char *)malloc(snaplen);
+ bcopy((char *)ip, (char *)abuf, min(length, snaplen));
+ snapend += abuf - (u_char *)ip;
+ packetp = abuf;
+ ip = (struct ip *)abuf;
+ }
+#endif
+ if ((u_char *)(ip + 1) > snapend) {
+ printf("[|ip]");
+ return;
+ }
+ if (length < sizeof (struct ip)) {
+ (void)printf("truncated-ip %d", length);
+ return;
+ }
+ hlen = ip->ip_hl * 4;
+
+ NTOHS(ip->ip_len);
+ NTOHS(ip->ip_off);
+ NTOHS(ip->ip_id);
+
+ len = ip->ip_len - hlen;
+ if (length < ip->ip_len)
+ (void)printf("truncated-ip - %d bytes missing!",
+ ip->ip_len - length);
+
+ /*
+ * If this is fragment zero, hand it to the next higher
+ * level protocol.
+ */
+ if ((ip->ip_off & 0x1fff) == 0) {
+ cp = (unsigned char *)ip + hlen;
+ switch (ip->ip_p) {
+
+ case IPPROTO_TCP:
+ tcp_print((struct tcphdr *)cp, len, ip);
+ break;
+ case IPPROTO_UDP:
+ udp_print((struct udphdr *)cp, len, ip);
+ break;
+ case IPPROTO_ICMP:
+ icmp_print((struct icmp *)cp, ip);
+ break;
+ case IPPROTO_ND:
+ (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
+ ipaddr_string(&ip->ip_dst));
+ (void)printf(" nd %d", len);
+ break;
+ case IPPROTO_EGP:
+ egp_print((struct egp_packet *)cp, len, ip);
+ break;
+#ifndef IPPROTO_OSPF
+#define IPPROTO_OSPF 89
+#endif
+ case IPPROTO_OSPF:
+ ospf_print((struct ospfhdr *)cp, len, ip);
+ break;
+#ifndef IPPROTO_IGMP
+#define IPPROTO_IGMP 2
+#endif
+ case IPPROTO_IGMP:
+ igmp_print(cp, len, ip);
+ break;
+ default:
+ (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
+ ipaddr_string(&ip->ip_dst));
+ (void)printf(" ip-proto-%d %d", ip->ip_p, len);
+ break;
+ }
+ }
+ /*
+ * for fragmented datagrams, print id:size@offset. On all
+ * but the last stick a "+". For unfragmented datagrams, note
+ * the don't fragment flag.
+ */
+ if (ip->ip_off & 0x3fff) {
+ /*
+ * if this isn't the first frag, we're missing the
+ * next level protocol header. print the ip addr.
+ */
+ if (ip->ip_off & 0x1fff)
+ (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
+ ipaddr_string(&ip->ip_dst));
+ (void)printf(" (frag %d:%d@%d%s)", ip->ip_id, len,
+ (ip->ip_off & 0x1fff) * 8,
+ (ip->ip_off & IP_MF)? "+" : "");
+ } else if (ip->ip_off & IP_DF)
+ (void)printf(" (DF)");
+
+ if (ip->ip_tos)
+ (void)printf(" [tos 0x%x]", (int)ip->ip_tos);
+ if (ip->ip_ttl <= 1)
+ (void)printf(" [ttl %d]", (int)ip->ip_ttl);
+
+ if (vflag) {
+ char *sep = "";
+
+ printf(" (");
+ if (ip->ip_ttl > 1) {
+ (void)printf("%sttl %d", sep, (int)ip->ip_ttl);
+ sep = ", ";
+ }
+ if ((ip->ip_off & 0x3fff) == 0) {
+ (void)printf("%sid %d", sep, (int)ip->ip_id);
+ sep = ", ";
+ }
+ if ((hlen -= sizeof(struct ip)) > 0) {
+ (void)printf("%soptlen=%d", sep, hlen);
+ ip_optprint((u_char *)(ip + 1), hlen);
+ }
+ printf(")");
+ }
+}
diff --git a/usr.sbin/tcpdump/tcpdump/print-nfs.c b/usr.sbin/tcpdump/tcpdump/print-nfs.c
new file mode 100644
index 000000000000..8b3169771184
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-nfs.c
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 1990, 1991, 1992 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: print-nfs.c,v 1.24 92/01/31 12:27:46 mccanne Exp $ (LBL)";
+#endif
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+
+#include <sys/time.h>
+#include <errno.h>
+#include <rpc/types.h>
+#include <rpc/auth.h>
+#include <rpc/auth_unix.h>
+#include <rpc/svc.h>
+#include <rpc/xdr.h>
+#include <rpc/rpc_msg.h>
+
+#include <ctype.h>
+
+#include "interface.h"
+/* These must come after interface.h for BSD. */
+#if BSD >= 199006
+#include <sys/ucred.h>
+#include <nfs/nfsv2.h>
+#endif
+#include <nfs/nfs.h>
+
+#include "addrtoname.h"
+#include "extract.h"
+
+static void nfs_printfh();
+static void nfs_printfn();
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+/*
+ * Byte swap an array of n words.
+ * Assume input is word-aligned.
+ * Check that buffer is bounded by "snapend".
+ */
+static void
+bswap(bp, n)
+ register u_long *bp;
+ register u_int n;
+{
+ register int nwords = ((char *)snapend - (char *)bp) / sizeof(*bp);
+
+ if (nwords > n)
+ nwords = n;
+ for (; --nwords >= 0; ++bp)
+ *bp = ntohl(*bp);
+}
+#endif
+
+void
+nfsreply_print(rp, length, ip)
+ register struct rpc_msg *rp;
+ int length;
+ register struct ip *ip;
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ bswap((u_long *)rp, sizeof(*rp) / sizeof(u_long));
+#endif
+ if (!nflag)
+ (void)printf("%s.nfs > %s.%x: reply %s %d",
+ ipaddr_string(&ip->ip_src),
+ ipaddr_string(&ip->ip_dst),
+ rp->rm_xid,
+ rp->rm_reply.rp_stat == MSG_ACCEPTED? "ok":"ERR",
+ length);
+ else
+ (void)printf("%s.%x > %s.%x: reply %s %d",
+ ipaddr_string(&ip->ip_src),
+ NFS_PORT,
+ ipaddr_string(&ip->ip_dst),
+ rp->rm_xid,
+ rp->rm_reply.rp_stat == MSG_ACCEPTED? "ok":"ERR",
+ length);
+}
+
+/*
+ * Return a pointer to the first file handle in the packet.
+ * If the packet was truncated, return 0.
+ */
+static u_long *
+parsereq(rp, length)
+ register struct rpc_msg *rp;
+ register int length;
+{
+ register u_long *dp = (u_long *)&rp->rm_call.cb_cred;
+ register u_long *ep = (u_long *)snapend;
+
+ /*
+ * find the start of the req data (if we captured it)
+ * note that dp[1] was already byte swapped by bswap()
+ */
+ if (dp < ep && dp[1] < length) {
+ dp += (dp[1] + (2*sizeof(u_long) + 3)) / sizeof(u_long);
+ if ((dp < ep) && (dp[1] < length)) {
+ dp += (dp[1] + (2*sizeof(u_long) + 3)) /
+ sizeof(u_long);
+ if (dp < ep)
+ return (dp);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Print out an NFS file handle and return a pointer to following word.
+ * If packet was truncated, return 0.
+ */
+static u_long *
+parsefh(dp)
+ register u_long *dp;
+{
+ if (dp + 8 <= (u_long *)snapend) {
+ nfs_printfh(dp);
+ return (dp + 8);
+ }
+ return (0);
+}
+
+/*
+ * Print out a file name and return pointer to longword past it.
+ * If packet was truncated, return 0.
+ */
+static u_long *
+parsefn(dp)
+ register u_long *dp;
+{
+ register int len;
+ register u_char *cp;
+
+ /* Bail if we don't have the string length */
+ if ((u_char *)dp > snapend - sizeof(*dp))
+ return(0);
+
+ /* Fetch string length; convert to host order */
+ len = *dp++;
+ NTOHL(len);
+
+ cp = (u_char *)dp;
+ /* Update long pointer (NFS filenames are padded to long) */
+ dp += ((len + 3) & ~3) / sizeof(*dp);
+ if ((u_char *)dp > snapend)
+ return (0);
+ nfs_printfn(cp, len);
+
+ return (dp);
+}
+
+/*
+ * Print out file handle and file name.
+ * Return pointer to longword past file name.
+ * If packet was truncated (or there was some other error), return 0.
+ */
+static u_long *
+parsefhn(dp)
+ register u_long *dp;
+{
+ dp = parsefh(dp);
+ if (dp == 0)
+ return (0);
+ putchar(' ');
+ return (parsefn(dp));
+}
+
+void
+nfsreq_print(rp, length, ip)
+ register struct rpc_msg *rp;
+ int length;
+ register struct ip *ip;
+{
+ register u_long *dp;
+ register u_char *ep = snapend;
+#define TCHECK(p, l) if ((u_char *)(p) > ep - l) break
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ bswap((u_long *)rp, sizeof(*rp) / sizeof(u_long));
+#endif
+
+ if (!nflag)
+ (void)printf("%s.%x > %s.nfs: %d",
+ ipaddr_string(&ip->ip_src),
+ rp->rm_xid,
+ ipaddr_string(&ip->ip_dst),
+ length);
+ else
+ (void)printf("%s.%x > %s.%x: %d",
+ ipaddr_string(&ip->ip_src),
+ rp->rm_xid,
+ ipaddr_string(&ip->ip_dst),
+ NFS_PORT,
+ length);
+
+ switch (rp->rm_call.cb_proc) {
+#ifdef NFSPROC_NOOP
+ case NFSPROC_NOOP:
+ printf(" nop");
+ return;
+#else
+#define NFSPROC_NOOP -1
+#endif
+ case RFS_NULL:
+ printf(" null");
+ return;
+
+ case RFS_GETATTR:
+ printf(" getattr");
+ if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0)
+ return;
+ break;
+
+ case RFS_SETATTR:
+ printf(" setattr");
+ if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0)
+ return;
+ break;
+
+#if RFS_ROOT != NFSPROC_NOOP
+ case RFS_ROOT:
+ printf(" root");
+ break;
+#endif
+ case RFS_LOOKUP:
+ printf(" lookup");
+ if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0)
+ return;
+ break;
+
+ case RFS_READLINK:
+ printf(" readlink");
+ if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0)
+ return;
+ break;
+
+ case RFS_READ:
+ printf(" read");
+ if ((dp = parsereq(rp, length)) != 0 &&
+ (dp = parsefh(dp)) != 0) {
+ TCHECK(dp, 3 * sizeof(*dp));
+ printf(" %lu (%lu) bytes @ %lu",
+ ntohl(dp[1]), ntohl(dp[2]), ntohl(dp[0]));
+ return;
+ }
+ break;
+
+#if RFS_WRITECACHE != NFSPROC_NOOP
+ case RFS_WRITECACHE:
+ printf(" writecache");
+ if ((dp = parsereq(rp, length)) != 0 &&
+ (dp = parsefh(dp)) != 0) {
+ TCHECK(dp, 4 * sizeof(*dp));
+ printf(" %lu (%lu) bytes @ %lu (%lu)",
+ ntohl(dp[3]), ntohl(dp[2]),
+ ntohl(dp[1]), ntohl(dp[0]));
+ return;
+ }
+ break;
+#endif
+ case RFS_WRITE:
+ printf(" write");
+ if ((dp = parsereq(rp, length)) != 0 &&
+ (dp = parsefh(dp)) != 0) {
+ TCHECK(dp, 4 * sizeof(*dp));
+ printf(" %lu (%lu) bytes @ %lu (%lu)",
+ ntohl(dp[3]), ntohl(dp[2]),
+ ntohl(dp[1]), ntohl(dp[0]));
+ return;
+ }
+ break;
+
+ case RFS_CREATE:
+ printf(" create");
+ if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0)
+ return;
+ break;
+
+ case RFS_REMOVE:
+ printf(" remove");
+ if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0)
+ return;
+ break;
+
+ case RFS_RENAME:
+ printf(" rename");
+ if ((dp = parsereq(rp, length)) != 0 &&
+ (dp = parsefhn(dp)) != 0) {
+ fputs(" ->", stdout);
+ if (parsefhn(dp) != 0)
+ return;
+ }
+ break;
+
+ case RFS_LINK:
+ printf(" link");
+ if ((dp = parsereq(rp, length)) != 0 &&
+ (dp = parsefh(dp)) != 0) {
+ fputs(" ->", stdout);
+ if (parsefhn(dp) != 0)
+ return;
+ }
+ break;
+
+ case RFS_SYMLINK:
+ printf(" symlink");
+ if ((dp = parsereq(rp, length)) != 0 &&
+ (dp = parsefhn(dp)) != 0) {
+ fputs(" -> ", stdout);
+ if (parsefn(dp) != 0)
+ return;
+ }
+ break;
+
+ case RFS_MKDIR:
+ printf(" mkdir");
+ if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0)
+ return;
+ break;
+
+ case RFS_RMDIR:
+ printf(" rmdir");
+ if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0)
+ return;
+ break;
+
+ case RFS_READDIR:
+ printf(" readdir");
+ if ((dp = parsereq(rp, length)) != 0 &&
+ (dp = parsefh(dp)) != 0) {
+ TCHECK(dp, 2 * sizeof(*dp));
+ printf(" %lu bytes @ %lu", ntohl(dp[1]), ntohl(dp[0]));
+ return;
+ }
+ break;
+
+ case RFS_STATFS:
+ printf(" statfs");
+ if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0)
+ return;
+ break;
+
+ default:
+ printf(" proc-%lu", rp->rm_call.cb_proc);
+ return;
+ }
+ fputs(" [|nfs]", stdout);
+#undef TCHECK
+}
+
+/*
+ * Print out an NFS file handle.
+ * We assume packet was not truncated before the end of the
+ * file handle pointed to by dp.
+ */
+static void
+nfs_printfh(dp)
+ register u_long *dp;
+{
+ /*
+ * take a wild guess at the structure of file handles.
+ * On sun 3s, there are 2 longs of fsid, a short
+ * len == 8, a long of inode & a long of generation number.
+ * On sun 4s, the len == 10 & there are 2 bytes of
+ * padding immediately following it.
+ */
+ if (dp[2] == 0xa0000) {
+ if (dp[1])
+ (void) printf(" fh %ld.%ld.%lu", dp[0], dp[1], dp[3]);
+ else
+ (void) printf(" fh %ld.%ld", dp[0], dp[3]);
+ } else if ((dp[2] >> 16) == 8)
+ /*
+ * 'dp' is longword aligned, so we must use the extract
+ * macros below for dp+10 which cannot possibly be aligned.
+ */
+ if (dp[1])
+ (void) printf(" fh %ld.%ld.%lu", dp[0], dp[1],
+ EXTRACT_LONG((u_char *)dp + 10));
+ else
+ (void) printf(" fh %ld.%ld", dp[0],
+ EXTRACT_LONG((u_char *)dp + 10));
+ /* On Ultrix pre-4.0, three longs: fsid, fno, fgen and then zeros */
+ else if (dp[3] == 0) {
+ (void)printf(" fh %d,%d/%ld.%ld", major(dp[0]), minor(dp[0]),
+ dp[1], dp[2]);
+ }
+ /*
+ * On Ultrix 4.0,
+ * five longs: fsid, fno, fgen, eno, egen and then zeros
+ */
+ else if (dp[5] == 0) {
+ (void)printf(" fh %d,%d/%ld.%ld", major(dp[0]), minor(dp[0]),
+ dp[1], dp[2]);
+ if (vflag) {
+ /* print additional info */
+ (void)printf("[%ld.%ld]", dp[3], dp[4]);
+ }
+ }
+ else
+ (void) printf(" fh %lu.%lu.%lu.%lu",
+ dp[0], dp[1], dp[2], dp[3]);
+}
+
+/*
+ * Print out an NFS filename.
+ * Assumes that len bytes from cp are present in packet.
+ */
+static void
+nfs_printfn(cp, len)
+ register u_char *cp;
+ register int len;
+{
+ register char c;
+
+ /* Sanity */
+ if (len >= 64) {
+ fputs("[\">]", stdout);
+ return;
+ }
+ /* Print out the filename */
+ putchar('"');
+ while (--len >= 0) {
+ c = toascii(*cp++);
+ if (!isascii(c)) {
+ c = toascii(c);
+ putchar('M');
+ putchar('-');
+ }
+ if (!isprint(c)) {
+ c ^= 0x40; /* DEL to ?, others to alpha */
+ putchar('^');
+ }
+ putchar(c);
+ }
+ putchar('"');
+}
diff --git a/usr.sbin/tcpdump/tcpdump/print-ntp.c b/usr.sbin/tcpdump/tcpdump/print-ntp.c
new file mode 100644
index 000000000000..86f6ba76c1f2
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-ntp.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Format and print ntp packets.
+ * By Jeffrey Mogul/DECWRL
+ * loosely based on print-bootp.c
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: print-ntp.c,v 1.7 92/01/04 01:45:16 leres Exp $ (LBL)";
+#endif
+
+#include <stdio.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <strings.h>
+#include <ctype.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "ntp.h"
+
+/*
+ * Print ntp requests
+ */
+void
+ntp_print(bp, length)
+ register struct ntpdata *bp;
+ int length;
+{
+ u_char *ep;
+ int mode, version, leapind;
+ static char rclock[5];
+
+#define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc
+
+ /* Note funny sized packets */
+ if (length != sizeof(struct ntpdata))
+ (void)printf(" [len=%d]", length);
+
+ /* 'ep' points to the end of avaible data. */
+ ep = (u_char *)snapend;
+
+ TCHECK(bp->status, sizeof(bp->status));
+
+ version = (bp->status & VERSIONMASK) >> 3;
+ printf(" v%d", version);
+
+ leapind = bp->status & LEAPMASK;
+ switch (leapind) {
+
+ case NO_WARNING:
+ break;
+
+ case PLUS_SEC:
+ fputs(" +1s", stdout);
+ break;
+
+ case MINUS_SEC:
+ fputs(" -1s", stdout);
+ break;
+ }
+
+ mode = bp->status & MODEMASK;
+ switch (mode) {
+
+ case MODE_UNSPEC: /* unspecified */
+ fputs(" unspec", stdout);
+ break;
+
+ case MODE_SYM_ACT: /* symmetric active */
+ fputs(" sym_act", stdout);
+ break;
+
+ case MODE_SYM_PAS: /* symmetric passive */
+ fputs(" sym_pas", stdout);
+ break;
+
+ case MODE_CLIENT: /* client */
+ fputs(" client", stdout);
+ break;
+
+ case MODE_SERVER: /* server */
+ fputs(" server", stdout);
+ break;
+
+ case MODE_BROADCAST: /* broadcast */
+ fputs(" bcast", stdout);
+ break;
+
+ case MODE_RES1: /* reserved */
+ fputs(" res1", stdout);
+ break;
+
+ case MODE_RES2: /* reserved */
+ fputs(" res2", stdout);
+ break;
+
+ }
+
+ TCHECK(bp->stratum, sizeof(bp->stratum));
+ printf(" strat %d", bp->stratum);
+
+ TCHECK(bp->ppoll, sizeof(bp->ppoll));
+ printf(" poll %d", bp->ppoll);
+
+ /* Can't TCHECK bp->precision bitfield so bp->distance + 0 instead */
+ TCHECK(bp->distance, 0);
+ printf(" prec %d", bp->precision);
+
+ if (!vflag)
+ return;
+
+ TCHECK(bp->distance, sizeof(bp->distance));
+ fputs(" dist ", stdout);
+ p_sfix(&bp->distance);
+
+ TCHECK(bp->dispersion, sizeof(bp->dispersion));
+ fputs(" disp ", stdout);
+ p_sfix(&bp->dispersion);
+
+ TCHECK(bp->refid, sizeof(bp->refid));
+ fputs(" ref ", stdout);
+ /* Interpretation depends on stratum */
+ switch (bp->stratum) {
+
+ case UNSPECIFIED:
+ case PRIM_REF:
+ strncpy(rclock, (char *)&(bp->refid), 4);
+ rclock[4] = '\0';
+ fputs(rclock, stdout);
+ break;
+
+ case INFO_QUERY:
+ printf("%s INFO_QUERY", ipaddr_string(&(bp->refid)));
+ /* this doesn't have more content */
+ return;
+
+ case INFO_REPLY:
+ printf("%s INFO_REPLY", ipaddr_string(&(bp->refid)));
+ /* this is too complex to be worth printing */
+ return;
+
+ default:
+ printf("%s", ipaddr_string(&(bp->refid)));
+ break;
+ }
+
+ TCHECK(bp->reftime, sizeof(bp->reftime));
+ putchar('@');
+ p_ntp_time(&(bp->reftime));
+
+ TCHECK(bp->org, sizeof(bp->org));
+ fputs(" orig ", stdout);
+ p_ntp_time(&(bp->org));
+
+ TCHECK(bp->rec, sizeof(bp->rec));
+ fputs(" rec ", stdout);
+ p_ntp_delta(&(bp->org), &(bp->rec));
+
+ TCHECK(bp->xmt, sizeof(bp->xmt));
+ fputs(" xmt ", stdout);
+ p_ntp_delta(&(bp->org), &(bp->xmt));
+
+ return;
+
+trunc:
+ fputs(" [|ntp]", stdout);
+#undef TCHECK
+}
+
+p_sfix(sfp)
+ register struct s_fixedpt *sfp;
+{
+ register int i;
+ register int f;
+ register float ff;
+
+ i = ntohs(sfp->int_part);
+ f = ntohs(sfp->fraction);
+ ff = f / 65536.0; /* shift radix point by 16 bits */
+ f = ff * 1000000.0; /* Treat fraction as parts per million */
+ printf("%d.%06d", i, f);
+}
+
+#define FMAXINT (4294967296.0) /* floating point rep. of MAXINT */
+
+p_ntp_time(lfp)
+ register struct l_fixedpt *lfp;
+{
+ register long i;
+ register unsigned long uf;
+ register unsigned long f;
+ register float ff;
+
+ i = ntohl(lfp->int_part);
+ uf = ntohl(lfp->fraction);
+ ff = uf;
+ if (ff < 0.0) /* some compilers are buggy */
+ ff += FMAXINT;
+ ff = ff / FMAXINT; /* shift radix point by 32 bits */
+ f = ff * 1000000000.0; /* treat fraction as parts per billion */
+ printf("%lu.%09d", i, f);
+}
+
+/* Prints time difference between *lfp and *olfp */
+p_ntp_delta(olfp, lfp)
+ register struct l_fixedpt *olfp;
+ register struct l_fixedpt *lfp;
+{
+ register long i;
+ register unsigned long uf;
+ register unsigned long ouf;
+ register unsigned long f;
+ register float ff;
+ int signbit;
+
+ i = ntohl(lfp->int_part) - ntohl(olfp->int_part);
+
+ uf = ntohl(lfp->fraction);
+ ouf = ntohl(olfp->fraction);
+
+ if (i > 0) { /* new is definitely greater than old */
+ signbit = 0;
+ f = uf - ouf;
+ if (ouf > uf) /* must borrow from high-order bits */
+ i -= 1;
+ } else if (i < 0) { /* new is definitely less than old */
+ signbit = 1;
+ f = ouf - uf;
+ if (uf > ouf) /* must carry into the high-order bits */
+ i += 1;
+ i = -i;
+ } else { /* int_part is zero */
+ if (uf > ouf) {
+ signbit = 0;
+ f = uf - ouf;
+ } else {
+ signbit = 1;
+ f = ouf - uf;
+ }
+ }
+
+ ff = f;
+ if (ff < 0.0) /* some compilers are buggy */
+ ff += FMAXINT;
+ ff = ff / FMAXINT; /* shift radix point by 32 bits */
+ f = ff * 1000000000.0; /* treat fraction as parts per billion */
+ if (signbit)
+ putchar('-');
+ else
+ putchar('+');
+ printf("%d.%09d", i, f);
+}
diff --git a/usr.sbin/tcpdump/tcpdump/print-null.c b/usr.sbin/tcpdump/tcpdump/print-null.c
new file mode 100644
index 000000000000..b1860685b84d
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-null.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#)$Header: print-null.c,v 1.3 91/10/07 20:19:11 leres Exp $ (LBL)";
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/mbuf.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <net/bpf.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+#define NULL_HDRLEN 4
+
+static void
+null_print(p, ip, length)
+ u_char *p;
+ struct ip *ip;
+ int length;
+{
+ u_int family;
+
+ bcopy(p, &family, sizeof(family));
+
+ if (nflag) {
+ /* XXX just dump the header */
+ return;
+ }
+ switch (family) {
+
+ case AF_INET:
+ printf("ip: ");
+ break;
+
+ case AF_NS:
+ printf("ns: ");
+ break;
+
+ default:
+ printf("AF %d: ", family);
+ break;
+ }
+}
+
+void
+null_if_print(p, tvp, length, caplen)
+ u_char *p;
+ struct timeval *tvp;
+ int length;
+ int caplen;
+{
+ struct ip *ip;
+
+ ts_print(tvp);
+
+ /*
+ * Some printers want to get back at the link level addresses,
+ * and/or check that they're not walking off the end of the packet.
+ * Rather than pass them all the way down, we set these globals.
+ */
+ packetp = (u_char *)p;
+ snapend = (u_char *)p + caplen;
+
+ length -= NULL_HDRLEN;
+
+ ip = (struct ip *)(p + NULL_HDRLEN);
+
+ if (eflag)
+ null_print(p, ip, length);
+
+ ip_print(ip, length);
+
+ if (xflag)
+ default_print((u_short *)ip, caplen - NULL_HDRLEN);
+ putchar('\n');
+}
+
diff --git a/usr.sbin/tcpdump/tcpdump/print-ospf.c b/usr.sbin/tcpdump/tcpdump/print-ospf.c
new file mode 100644
index 000000000000..90daf9447a05
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-ospf.c
@@ -0,0 +1,586 @@
+/*
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu)
+ */
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: print-ospf.c,v 1.1 92/01/29 12:44:17 mccanne Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+
+#include <errno.h>
+#include <ctype.h>
+
+#include "ospf.h"
+#include "interface.h"
+#include "addrtoname.h"
+
+#ifndef __GNUC__
+#define inline
+#endif
+
+#if !defined(__STDC__) && !defined(const)
+#define const
+#endif /* !defined(__STDC__) && !defined(const) */
+
+struct bits {
+ u_long bit;
+ const char *str;
+};
+
+static const struct bits ospf_option_bits[] = {
+ OSPF_OPTION_T, "T",
+ OSPF_OPTION_E, "E",
+ OSPF_OPTION_MC, "MC",
+ 0, (char *) 0
+};
+
+static const struct bits ospf_rla_flag_bits[] = {
+ RLA_FLAG_B, "B",
+ RLA_FLAG_E, "E",
+ RLA_FLAG_W1, "W1",
+ RLA_FLAG_W2, "W2",
+ 0, (char *) 0
+};
+
+static const char *ospf_types[OSPF_TYPE_MAX] = {
+ (char *) 0,
+ "hello",
+ "dd",
+ "ls_req",
+ "ls_upd",
+ "ls_ack"
+};
+
+static inline void
+ospf_print_seqage(seq, us)
+register u_long seq;
+register time_t us;
+{
+ register time_t sec = us % 60;
+ register time_t mins = (us / 60) % 60;
+ register time_t hour = us/3600;
+
+ printf(" S %X age ",
+ seq);
+ if (hour) {
+ printf("%d:%02d:%02d",
+ hour,
+ mins,
+ sec);
+ } else if (mins) {
+ printf("%d:%02d",
+ mins,
+ sec);
+ } else {
+ printf("%d",
+ sec);
+ }
+}
+
+
+static inline void
+ospf_print_bits(bp, options)
+register struct bits *bp;
+register u_char options;
+{
+ char sep = ' ';
+
+ do {
+ if (options & bp->bit) {
+ printf("%c%s",
+ sep,
+ bp->str);
+ sep = '/';
+ }
+ } while ((++bp)->bit) ;
+}
+
+
+#define LS_PRINT(lsp, type) switch (type) { \
+ case LS_TYPE_ROUTER: \
+ printf(" rtr %s ", ipaddr_string(&lsp->ls_router)); break; \
+ case LS_TYPE_NETWORK: \
+ printf(" net dr %s if %s", ipaddr_string(&lsp->ls_router), ipaddr_string(&lsp->ls_stateid)); break; \
+ case LS_TYPE_SUM_IP: \
+ printf(" sum %s abr %s", ipaddr_string(&lsp->ls_stateid), ipaddr_string(&lsp->ls_router)); break; \
+ case LS_TYPE_SUM_ABR: \
+ printf(" abr %s rtr %s", ipaddr_string(&lsp->ls_router), ipaddr_string(&lsp->ls_stateid)); break; \
+ case LS_TYPE_ASE: \
+ printf(" ase %s asbr %s", ipaddr_string(&lsp->ls_stateid), ipaddr_string(&lsp->ls_router)); break; \
+ case LS_TYPE_GROUP: \
+ printf(" group %s rtr %s", ipaddr_string(&lsp->ls_stateid), ipaddr_string(&lsp->ls_router)); break; \
+ }
+
+static int
+ospf_print_lshdr(lshp, end)
+register struct lsa_hdr *lshp;
+caddr_t end;
+{
+ if ((caddr_t) (lshp + 1) > end) {
+ return 1;
+ }
+
+ printf(" {");
+
+ if (!lshp->ls_type || lshp->ls_type >= LS_TYPE_MAX) {
+ printf(" ??LS type %d?? }",
+ lshp->ls_type);
+ return 1;
+ }
+
+ ospf_print_bits(ospf_option_bits, lshp->ls_options);
+ ospf_print_seqage(ntohl(lshp->ls_seq),
+ ntohs(lshp->ls_age));
+
+ LS_PRINT(lshp, lshp->ls_type);
+
+ return 0;
+}
+
+
+/*
+ * Print a single link state advertisement. If truncated return 1, else 0.
+ */
+
+static int
+ospf_print_lsa(lsap, end)
+register struct lsa *lsap;
+caddr_t end;
+{
+ register caddr_t ls_end;
+ struct rlalink *rlp;
+ struct tos_metric *tosp;
+ struct in_addr *ap;
+ struct aslametric *almp;
+ struct mcla *mcp;
+ u_long *lp;
+ int j, k;
+
+ if (ospf_print_lshdr(&lsap->ls_hdr, end)) {
+ return 1;
+ }
+
+ ls_end = (caddr_t) lsap + ntohs(lsap->ls_hdr.ls_length);
+
+ if (ls_end > end) {
+ printf(" }");
+ return 1;
+ }
+
+ switch (lsap->ls_hdr.ls_type) {
+ case LS_TYPE_ROUTER:
+ ospf_print_bits(ospf_rla_flag_bits, lsap->lsa_un.un_rla.rla_flags);
+
+ j = ntohs(lsap->lsa_un.un_rla.rla_count);
+ rlp = lsap->lsa_un.un_rla.rla_link;
+ while (j--) {
+ struct rlalink *rln = (struct rlalink *) ((caddr_t) (rlp + 1) + ((rlp->link_toscount) * sizeof (struct tos_metric)));
+
+ if ((caddr_t) rln > ls_end) {
+ break;
+ }
+ printf(" {");
+
+ switch (rlp->link_type) {
+ case RLA_TYPE_VIRTUAL:
+ printf(" virt");
+ /* Fall through */
+
+ case RLA_TYPE_ROUTER:
+ printf(" nbrid %s if %s",
+ ipaddr_string(&rlp->link_id),
+ ipaddr_string(&rlp->link_data));
+ break;
+
+ case RLA_TYPE_TRANSIT:
+ printf(" dr %s if %s",
+ ipaddr_string(&rlp->link_id),
+ ipaddr_string(&rlp->link_data));
+ break;
+
+ case RLA_TYPE_STUB:
+ printf(" net %s mask %s",
+ ipaddr_string(&rlp->link_id),
+ ipaddr_string(&rlp->link_data));
+ break;
+
+ default:
+ printf(" ??RouterLinksType %d?? }",
+ rlp->link_type);
+ return 0;
+ }
+ printf(" tos 0 metric %d",
+ ntohs(rlp->link_tos0metric));
+ tosp = (struct tos_metric *) ((sizeof rlp->link_tos0metric) + (caddr_t) rlp);
+ for (k = 0; k < rlp->link_toscount; k++, tosp++) {
+ printf(" tos %d metric %d",
+ ntohs(tosp->tos_type),
+ ntohs(tosp->tos_metric));
+ }
+ printf(" }");
+ rlp = rln;
+ }
+ break;
+
+ case LS_TYPE_NETWORK:
+ printf(" mask %s rtrs",
+ ipaddr_string(&lsap->lsa_un.un_nla.nla_mask));
+ for (ap = lsap->lsa_un.un_nla.nla_router;
+ (caddr_t) (ap + 1) <= ls_end;
+ ap++) {
+ printf(" %s",
+ ipaddr_string(ap));
+ }
+ break;
+
+ case LS_TYPE_SUM_IP:
+ printf(" mask %s",
+ ipaddr_string(&lsap->lsa_un.un_sla.sla_mask));
+ /* Fall through */
+
+ case LS_TYPE_SUM_ABR:
+
+ for (lp = lsap->lsa_un.un_sla.sla_tosmetric;
+ (caddr_t) (lp + 1) <= ls_end;
+ lp++) {
+ u_long ul = ntohl(*lp);
+
+ printf(" tos %d metric %d",
+ (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS,
+ ul & SLA_MASK_METRIC);
+ }
+ break;
+
+ case LS_TYPE_ASE:
+ printf(" mask %s",
+ ipaddr_string(&lsap->lsa_un.un_asla.asla_mask));
+
+ for (almp = lsap->lsa_un.un_asla.asla_metric;
+ (caddr_t) (almp + 1) <= ls_end;
+ almp++) {
+ u_long ul = ntohl(almp->asla_tosmetric);
+
+ printf(" type %d tos %d metric %d",
+ (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1,
+ (ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS,
+ (ul & ASLA_MASK_METRIC));
+ if (almp->asla_forward.s_addr) {
+ printf(" forward %s",
+ ipaddr_string(&almp->asla_forward));
+ }
+ if (almp->asla_tag.s_addr) {
+ printf(" tag %s",
+ ipaddr_string(&almp->asla_tag));
+ }
+ }
+ break;
+
+ case LS_TYPE_GROUP:
+ /* Multicast extensions as of 23 July 1991 */
+ for (mcp = lsap->lsa_un.un_mcla;
+ (caddr_t) (mcp + 1) <= ls_end;
+ mcp++) {
+ switch (ntohl(mcp->mcla_vtype)) {
+ case MCLA_VERTEX_ROUTER:
+ printf(" rtr rtrid %s",
+ ipaddr_string(&mcp->mcla_vid));
+ break;
+
+ case MCLA_VERTEX_NETWORK:
+ printf(" net dr %s",
+ ipaddr_string(&mcp->mcla_vid));
+ break;
+
+ default:
+ printf(" ??VertexType %d??",
+ ntohl(mcp->mcla_vtype));
+ break;
+ }
+ }
+ }
+
+ printf(" }");
+ return 0;
+}
+
+
+void
+ospf_print(dat, length, ip)
+u_char *dat;
+int length;
+struct ip *ip;
+{
+ register struct ospfhdr *op = (struct ospfhdr *) dat;
+ register caddr_t end = (caddr_t)snapend;
+ register struct lsa *lsap;
+ register struct lsa_hdr *lshp;
+ char sep;
+ int i, j;
+ struct in_addr *ap;
+ struct lsr *lsrp;
+
+ /* Print the source and destination address */
+ (void) printf(" %s > %s:",
+ ipaddr_string(&ip->ip_src),
+ ipaddr_string(&ip->ip_dst));
+
+ if ((caddr_t) (&op->ospf_len + 1) > end) {
+ goto trunc_test;
+ }
+
+ /* If the type is valid translate it, or just print the type */
+ /* value. If it's not valid, say so and return */
+ if (op->ospf_type || op->ospf_type < OSPF_TYPE_MAX) {
+ printf(" OSPFv%d-%s %d:",
+ op->ospf_version,
+ ospf_types[op->ospf_type],
+ length);
+ } else {
+ printf(" ospf-v%d-??type %d?? %d:",
+ op->ospf_version,
+ op->ospf_type,
+ length);
+ return;
+ }
+
+ if (length != ntohs(op->ospf_len)) {
+ printf(" ??len %d??",
+ ntohs(op->ospf_len));
+ goto trunc_test;
+ }
+
+ if ((caddr_t) (&op->ospf_routerid + 1) > end) {
+ goto trunc_test;
+ }
+
+ /* Print the routerid if it is not the same as the source */
+ if (ip->ip_src.s_addr != op->ospf_routerid.s_addr) {
+ printf(" rtrid %s",
+ ipaddr_string(&op->ospf_routerid));
+ }
+
+ if ((caddr_t) (&op->ospf_areaid + 1) > end) {
+ goto trunc_test;
+ }
+
+ if (op->ospf_areaid.s_addr) {
+ printf(" area %s",
+ ipaddr_string(&op->ospf_areaid));
+ } else {
+ printf(" backbone");
+ }
+
+ if ((caddr_t) (op->ospf_authdata + OSPF_AUTH_SIZE) > end) {
+ goto trunc_test;
+ }
+
+ if (vflag) {
+ /* Print authentication data (should we really do this?) */
+ switch (ntohs(op->ospf_authtype)) {
+ case OSPF_AUTH_NONE:
+ break;
+
+ case OSPF_AUTH_SIMPLE:
+ printf(" auth ");
+ j = 0;
+ for (i = 0; i < sizeof (op->ospf_authdata); i++) {
+ if (!isprint(op->ospf_authdata[i])) {
+ j = 1;
+ break;
+ }
+ }
+ if (j) {
+ /* Print the auth-data as a string of octets */
+ printf("%s.%s",
+ ipaddr_string((struct in_addr *) op->ospf_authdata),
+ ipaddr_string((struct in_addr *) &op->ospf_authdata[sizeof (struct in_addr)]));
+ } else {
+ /* Print the auth-data as a text string */
+ printf("'%.8s'",
+ op->ospf_authdata);
+ }
+ break;
+
+ default:
+ printf(" ??authtype-%d??",
+ ntohs(op->ospf_authtype));
+ return;
+ }
+ }
+
+
+ /* Do rest according to version. */
+ switch (op->ospf_version) {
+ case 2:
+ /* ospf version 2 */
+ switch (op->ospf_type) {
+ case OSPF_TYPE_UMD: /* Rob Coltun's special monitoring packets; do nothing */
+ break;
+
+ case OSPF_TYPE_HELLO:
+ if ((caddr_t) (&op->ospf_hello.hello_deadint + 1) > end) {
+ break;
+ }
+ if (vflag) {
+ ospf_print_bits(ospf_option_bits, op->ospf_hello.hello_options);
+ printf(" mask %s int %d pri %d dead %d",
+ ipaddr_string(&op->ospf_hello.hello_mask),
+ ntohs(op->ospf_hello.hello_helloint),
+ op->ospf_hello.hello_priority,
+ ntohl(op->ospf_hello.hello_deadint));
+ }
+
+ if ((caddr_t) (&op->ospf_hello.hello_dr + 1) > end) {
+ break;
+ }
+ if (op->ospf_hello.hello_dr.s_addr) {
+ printf(" dr %s",
+ ipaddr_string(&op->ospf_hello.hello_dr));
+ }
+
+ if ((caddr_t) (&op->ospf_hello.hello_bdr + 1) > end) {
+ break;
+ }
+ if (op->ospf_hello.hello_bdr.s_addr) {
+ printf(" bdr %s",
+ ipaddr_string(&op->ospf_hello.hello_bdr));
+ }
+
+ if (vflag) {
+ if ((caddr_t) (op->ospf_hello.hello_neighbor + 1) > end) {
+ break;
+ }
+ printf(" nbrs");
+ for (ap = op->ospf_hello.hello_neighbor;
+ (caddr_t) (ap + 1) <= end;
+ ap++) {
+ printf(" %s",
+ ipaddr_string(ap));
+ }
+ }
+ break; /* HELLO */
+
+ case OSPF_TYPE_DB:
+ if ((caddr_t) (&op->ospf_db.db_seq + 1) > end) {
+ break;
+ }
+ ospf_print_bits(ospf_option_bits, op->ospf_db.db_options);
+ sep = ' ';
+ if (op->ospf_db.db_flags & OSPF_DB_INIT) {
+ printf("%cI",
+ sep);
+ sep = '/';
+ }
+ if (op->ospf_db.db_flags & OSPF_DB_MORE) {
+ printf("%cM",
+ sep);
+ sep = '/';
+ }
+ if (op->ospf_db.db_flags & OSPF_DB_MASTER) {
+ printf("%cMS",
+ sep);
+ sep = '/';
+ }
+ printf(" S %X",
+ ntohl(op->ospf_db.db_seq));
+
+ if (vflag) {
+ /* Print all the LS adv's */
+ lshp = op->ospf_db.db_lshdr;
+
+ while (!ospf_print_lshdr(lshp, end)) {
+ printf(" }");
+ lshp++;
+ }
+ }
+ break;
+
+ case OSPF_TYPE_LSR:
+ if (vflag) {
+ for (lsrp = op->ospf_lsr; (caddr_t) (lsrp+1) <= end; lsrp++) {
+ long type;
+
+ if ((caddr_t) (lsrp + 1) > end) {
+ break;
+ }
+
+ printf(" {");
+ if (!(type = lsrp->ls_type) || type >= LS_TYPE_MAX) {
+ printf(" ??LinkStateType %d }",
+ type);
+ printf(" }");
+ break;
+ }
+
+ LS_PRINT(lsrp, type);
+ printf(" }");
+ }
+ }
+ break;
+
+ case OSPF_TYPE_LSU:
+ if (vflag) {
+ lsap = op->ospf_lsu.lsu_lsa;
+ i = ntohl(op->ospf_lsu.lsu_count);
+
+ while (i-- &&
+ !ospf_print_lsa(lsap, end)) {
+ lsap = (struct lsa *) ((caddr_t) lsap + ntohs(lsap->ls_hdr.ls_length));
+ }
+ }
+ break;
+
+
+ case OSPF_TYPE_LSA:
+ if (vflag) {
+ lshp = op->ospf_lsa.lsa_lshdr;
+
+ while (!ospf_print_lshdr(lshp, end)) {
+ printf(" }");
+ lshp++;
+ }
+ break;
+ }
+ } /* end switch on v2 packet type */
+ break;
+
+ default:
+ printf(" ospf [version %d]",
+ op->ospf_version);
+ break;
+ } /* end switch on version */
+
+ trunc_test:
+ if ((snapend - dat) < length) {
+ printf(" [|]");
+ }
+
+ return; /* from ospf_print */
+}
+
+
diff --git a/usr.sbin/tcpdump/tcpdump/print-ppp.c b/usr.sbin/tcpdump/tcpdump/print-ppp.c
new file mode 100644
index 000000000000..c83cc7d41dfd
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-ppp.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#)$Header: print-ppp.c,v 1.7 91/10/07 20:18:33 leres Exp $ (LBL)";
+#endif
+
+#ifdef PPP
+#include <stdio.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/mbuf.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <net/bpf.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+/* XXX This goes somewhere else. */
+#define PPP_HDRLEN 4
+
+void
+ppp_if_print(p, tvp, length, caplen)
+ u_char *p;
+ struct timeval *tvp;
+ int length;
+ int caplen;
+{
+ struct ip *ip;
+
+ ts_print(tvp);
+
+ if (caplen < PPP_HDRLEN) {
+ printf("[|ppp]");
+ goto out;
+ }
+
+ /*
+ * Some printers want to get back at the link level addresses,
+ * and/or check that they're not walking off the end of the packet.
+ * Rather than pass them all the way down, we set these globals.
+ */
+ packetp = (u_char *)p;
+ snapend = (u_char *)p + caplen;
+
+ if (eflag)
+ printf("%c %4d %02x %04x: ", p[0] ? 'O' : 'I', length,
+ p[1], ntohs(*(u_short *)&p[2]));
+
+ length -= PPP_HDRLEN;
+ ip = (struct ip *)(p + PPP_HDRLEN);
+ ip_print(ip, length);
+
+ if (xflag)
+ default_print((u_short *)ip, caplen - PPP_HDRLEN);
+out:
+ putchar('\n');
+}
+#else
+#include <stdio.h>
+void
+ppp_if_print()
+{
+ void error();
+
+ error("not configured for ppp");
+ /* NOTREACHED */
+}
+#endif
diff --git a/usr.sbin/tcpdump/tcpdump/print-rip.c b/usr.sbin/tcpdump/tcpdump/print-rip.c
new file mode 100644
index 000000000000..d123fe9a48bb
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-rip.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: print-rip.c,v 1.12 91/04/19 10:46:46 mccanne Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <protocols/routed.h>
+
+#include <errno.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+static void
+rip_entry_print(ni)
+ register struct netinfo *ni;
+{
+ if (ntohs(ni->rip_dst.sa_family) != AF_INET) {
+ register int i;
+
+ printf(" [family %d:", ntohs(ni->rip_dst.sa_family));
+ for (i = 0; i < 14; i += 2)
+ printf(" %02x%02x", ni->rip_dst.sa_data[i],
+ ni->rip_dst.sa_data[i+1]);
+ printf("]");
+ } else {
+ register struct sockaddr_in *sin =
+ (struct sockaddr_in *)&ni->rip_dst;
+ printf(" %s", ipaddr_string(&sin->sin_addr));
+ if (sin->sin_port)
+ printf(" [port %d]", sin->sin_port);
+ }
+ printf("(%d)", ntohl(ni->rip_metric));
+}
+
+void
+rip_print(dat, length)
+ u_char *dat;
+ int length;
+{
+ register struct rip *rp = (struct rip *)dat;
+ register struct netinfo *ni;
+ register int amt = (u_char *)snapend - dat;
+ register int i = min(length, amt) -
+ (sizeof(struct rip) - sizeof(struct netinfo));
+ int j;
+ int trunc;
+
+ if (i < 0)
+ return;
+
+ switch (rp->rip_cmd) {
+
+ case RIPCMD_REQUEST:
+ printf(" rip-req %d", length);
+ break;
+ case RIPCMD_RESPONSE:
+ j = length / sizeof(*ni);
+ if (j * sizeof(*ni) != length - 4)
+ printf(" rip-resp %d[%d]:", j, length);
+ else
+ printf(" rip-resp %d:", j);
+ trunc = ((i / sizeof(*ni)) * sizeof(*ni) != i);
+ for (ni = rp->rip_nets; (i -= sizeof(*ni)) >= 0; ++ni)
+ rip_entry_print(ni);
+ if (trunc)
+ printf("[|rip]");
+ break;
+ case RIPCMD_TRACEON:
+ printf(" rip-traceon %d: \"%s\"", length, rp->rip_tracefile);
+ break;
+ case RIPCMD_TRACEOFF:
+ printf(" rip-traceoff %d", length);
+ break;
+ case RIPCMD_POLL:
+ printf(" rip-poll %d", length);
+ break;
+ case RIPCMD_POLLENTRY:
+ printf(" rip-pollentry %d", length);
+ break;
+ default:
+ printf(" rip-%d ?? %d", rp->rip_cmd, length);
+ break;
+ }
+ if (rp->rip_vers != RIPVERSION)
+ printf(" [vers %d]", rp->rip_vers);
+}
diff --git a/usr.sbin/tcpdump/tcpdump/print-sl.c b/usr.sbin/tcpdump/tcpdump/print-sl.c
new file mode 100644
index 000000000000..2c89b42d4322
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-sl.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#)$Header: print-sl.c,v 1.17 91/10/07 20:18:35 leres Exp $ (LBL)";
+#endif
+
+#ifdef CSLIP
+#include <stdio.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/mbuf.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <net/slcompress.h>
+#include <net/slip.h>
+#include <net/bpf.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+static int lastlen[2][256];
+static int lastconn = 255;
+
+static void compressed_sl_print();
+
+void
+sl_if_print(p, tvp, length, caplen)
+ u_char *p;
+ struct timeval *tvp;
+ int length;
+ int caplen;
+{
+ struct ip *ip;
+
+ ts_print(tvp);
+
+ if (caplen < SLIP_HDRLEN) {
+ printf("[|slip]");
+ goto out;
+ }
+ /*
+ * Some printers want to get back at the link level addresses,
+ * and/or check that they're not walking off the end of the packet.
+ * Rather than pass them all the way down, we set these globals.
+ */
+ packetp = (u_char *)p;
+ snapend = (u_char *)p + caplen;
+
+ length -= SLIP_HDRLEN;
+
+ ip = (struct ip *)(p + SLIP_HDRLEN);
+
+ if (eflag)
+ sliplink_print(p, ip, length);
+
+ ip_print(ip, length);
+
+ if (xflag)
+ default_print((u_short *)ip, caplen - SLIP_HDRLEN);
+ out:
+ putchar('\n');
+}
+
+sliplink_print(p, ip, length)
+ u_char *p;
+ struct ip *ip;
+ int length;
+{
+ int dir;
+ int hlen;
+
+ dir = p[SLX_DIR];
+ putchar(dir == SLIPDIR_IN ? 'I' : 'O');
+ putchar(' ');
+
+ if (nflag) {
+ /* XXX just dump the header */
+ int i;
+
+ for (i = 0; i < 15; ++i)
+ printf("%02x.", p[SLX_CHDR + i]);
+ printf("%02x: ", p[SLX_CHDR + 15]);
+ return;
+ }
+ switch (p[SLX_CHDR] & 0xf0) {
+
+ case TYPE_IP:
+ printf("ip %d: ", length + SLIP_HDRLEN);
+ break;
+
+ case TYPE_UNCOMPRESSED_TCP:
+ /*
+ * The connection id is stode in the IP protcol field.
+ */
+ lastconn = ip->ip_p;
+ hlen = ip->ip_hl;
+ hlen += ((struct tcphdr *)&((int *)ip)[hlen])->th_off;
+ lastlen[dir][lastconn] = length - (hlen << 2);
+ printf("utcp %d: ", lastconn);
+ break;
+
+ default:
+ if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) {
+ compressed_sl_print(&p[SLX_CHDR], ip, length, dir);
+ printf(": ");
+ } else
+ printf("slip-%d!: ", p[SLX_CHDR]);
+ }
+}
+
+static u_char *
+print_sl_change(str, cp)
+ char *str;
+ register u_char *cp;
+{
+ register u_int i;
+
+ if ((i = *cp++) == 0) {
+ i = (cp[0] << 8) | cp[1];
+ cp += 2;
+ }
+ printf(" %s%d", str, i);
+ return (cp);
+}
+
+static u_char *
+print_sl_winchange(cp)
+ register u_char *cp;
+{
+ register short i;
+
+ if ((i = *cp++) == 0) {
+ i = (cp[0] << 8) | cp[1];
+ cp += 2;
+ }
+ if (i >= 0)
+ printf(" W+%d", i);
+ else
+ printf(" W%d", i);
+ return (cp);
+}
+
+static void
+compressed_sl_print(chdr, ip, length, dir)
+ u_char *chdr;
+ int length;
+ struct ip *ip;
+ int dir;
+{
+ register u_char *cp = chdr;
+ register u_int flags;
+ int hlen;
+
+ flags = *cp++;
+ if (flags & NEW_C) {
+ lastconn = *cp++;
+ printf("ctcp %d", lastconn);
+ } else
+ printf("ctcp *");
+
+ /* skip tcp checksum */
+ cp += 2;
+
+ switch (flags & SPECIALS_MASK) {
+ case SPECIAL_I:
+ printf(" *SA+%d", lastlen[dir][lastconn]);
+ break;
+
+ case SPECIAL_D:
+ printf(" *S+%d", lastlen[dir][lastconn]);
+ break;
+
+ default:
+ if (flags & NEW_U)
+ cp = print_sl_change("U=", cp);
+ if (flags & NEW_W)
+ cp = print_sl_winchange(cp);
+ if (flags & NEW_A)
+ cp = print_sl_change("A+", cp);
+ if (flags & NEW_S)
+ cp = print_sl_change("S+", cp);
+ break;
+ }
+ if (flags & NEW_I)
+ cp = print_sl_change("I+", cp);
+
+ /*
+ * 'hlen' is the length of the uncompressed TCP/IP header (in longs).
+ * 'cp - chdr' is the length of the compressed header.
+ * 'length - hlen' is the amount of data in the packet.
+ */
+ hlen = ip->ip_hl;
+ hlen += ((struct tcphdr *)&((long *)ip)[hlen])->th_off;
+ lastlen[dir][lastconn] = length - (hlen << 2);
+ printf(" %d (%d)", lastlen[dir][lastconn], cp - chdr);
+}
+#else
+#include <stdio.h>
+void
+sl_if_print()
+{
+ void error();
+
+ error("not configured for slip");
+ /* NOTREACHED */
+}
+#endif
diff --git a/usr.sbin/tcpdump/tcpdump/print-snmp.c b/usr.sbin/tcpdump/tcpdump/print-snmp.c
new file mode 100644
index 000000000000..d1996c07a292
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-snmp.c
@@ -0,0 +1,1043 @@
+/*
+ * Copyright (c) 1990, by John Robert LoVerso.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by John Robert LoVerso.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * This implementaion has been influenced by the CMU SNMP release,
+ * by Steve Waldbusser. However, this shares no code with that system.
+ * Additional ASN.1 insight gained from Marshall T. Rose's _The_Open_Book_.
+ * Earlier forms of this implemention were derived and/or inspired by an
+ * awk script originally written by C. Philip Wood of LANL (but later
+ * heavily modified by John Robert LoVerso). The copyright notice for
+ * that work is preserved below, even though it may not rightly apply
+ * to this file.
+ *
+ * This started out as a very simple program, but the incremental decoding
+ * (into the BE structure) complicated things.
+ *
+ # Los Alamos National Laboratory
+ #
+ # Copyright, 1990. The Regents of the University of California.
+ # This software was produced under a U.S. Government contract
+ # (W-7405-ENG-36) by Los Alamos National Laboratory, which is
+ # operated by the University of California for the U.S. Department
+ # of Energy. The U.S. Government is licensed to use, reproduce,
+ # and distribute this software. Permission is granted to the
+ # public to copy and use this software without charge, provided
+ # that this Notice and any statement of authorship are reproduced
+ # on all copies. Neither the Government nor the University makes
+ # any warranty, express or implied, or assumes any liability or
+ # responsibility for the use of this software.
+ # @(#)snmp.awk.x 1.1 (LANL) 1/15/90
+ */
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Id: print-snmp.c,v 3.10 91/01/17 01:18:13 loverso Exp Locker: loverso $ (jlv)";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+/*
+ * Universal ASN.1 types
+ * (we only care about the tag values for those allowed in the Internet SMI)
+ */
+char *Universal[] = {
+ "U-0",
+ "Boolean",
+ "Integer",
+#define INTEGER 2
+ "Bitstring",
+ "String",
+#define STRING 4
+ "Null",
+#define ASN_NULL 5
+ "ObjID",
+#define OBJECTID 6
+ "ObjectDes",
+ "U-8","U-9","U-10","U-11", /* 8-11 */
+ "U-12","U-13","U-14","U-15", /* 12-15 */
+ "Sequence",
+#define SEQUENCE 16
+ "Set"
+};
+
+/*
+ * Application-wide ASN.1 types from the Internet SMI and their tags
+ */
+char *Application[] = {
+ "IpAddress",
+#define IPADDR 0
+ "Counter",
+#define COUNTER 1
+ "Gauge",
+#define GAUGE 2
+ "TimeTicks",
+#define TIMETICKS 3
+ "Opaque"
+};
+
+/*
+ * Context-specific ASN.1 types for the SNMP PDUs and their tags
+ */
+char *Context[] = {
+ "GetRequest",
+#define GETREQ 0
+ "GetNextRequest",
+#define GETNEXTREQ 1
+ "GetResponse",
+#define GETRESP 2
+ "SetRequest",
+#define SETREQ 3
+ "Trap"
+#define TRAP 4
+};
+
+/*
+ * Private ASN.1 types
+ * The Internet SMI does not specify any
+ */
+char *Private[] = {
+ "P-0"
+};
+
+/*
+ * error-status values for any SNMP PDU
+ */
+char *ErrorStatus[] = {
+ "noError",
+ "tooBig",
+ "noSuchName",
+ "badValue",
+ "readOnly",
+ "genErr"
+};
+#define DECODE_ErrorStatus(e) \
+ ( e >= 0 && e <= sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \
+ ? ErrorStatus[e] : (sprintf(errbuf, "err=%d", e), errbuf))
+
+/*
+ * generic-trap values in the SNMP Trap-PDU
+ */
+char *GenericTrap[] = {
+ "coldStart",
+ "warmStart",
+ "linkDown",
+ "linkUp",
+ "authenticationFailure",
+ "egpNeighborLoss",
+ "enterpriseSpecific"
+#define GT_ENTERPRISE 7
+};
+#define DECODE_GenericTrap(t) \
+ ( t >= 0 && t <= sizeof(GenericTrap)/sizeof(GenericTrap[0]) \
+ ? GenericTrap[t] : (sprintf(buf, "gt=%d", t), buf))
+
+/*
+ * ASN.1 type class table
+ * Ties together the preceding Universal, Application, Context, and Private
+ * type definitions.
+ */
+#define defineCLASS(x) { "x", x, sizeof(x)/sizeof(x[0]) } /* not ANSI-C */
+struct {
+ char *name;
+ char **Id;
+ int numIDs;
+} Class[] = {
+ defineCLASS(Universal),
+#define UNIVERSAL 0
+ defineCLASS(Application),
+#define APPLICATION 1
+ defineCLASS(Context),
+#define CONTEXT 2
+ defineCLASS(Private),
+#define PRIVATE 3
+};
+
+/*
+ * defined forms for ASN.1 types
+ */
+char *Form[] = {
+ "Primitive",
+#define PRIMITIVE 0
+ "Constructed",
+#define CONSTRUCTED 1
+};
+
+/*
+ * A structure for the OID tree for the compiled-in MIB.
+ * This is stored as a general-order tree.
+ */
+struct obj {
+ char *desc; /* name of object */
+ u_char oid; /* sub-id following parent */
+ u_char type; /* object type (unused) */
+ struct obj *child, *next; /* child and next sibling pointers */
+} *objp = NULL;
+
+/*
+ * Include the compiled in SNMP MIB. "mib.h" is produced by feeding
+ * RFC-1156 format files into "makemib". "mib.h" MUST define at least
+ * a value for `mibroot'.
+ *
+ * In particluar, this is gross, as this is including initialized structures,
+ * and by right shouldn't be an "include" file.
+ */
+#include "mib.h"
+
+/*
+ * This defines a list of OIDs which will be abreviated on output.
+ * Currently, this includes the prefixes for the Internet MIB, the
+ * private enterprises tree, and the experimental tree.
+ */
+struct obj_abrev {
+ char *prefix; /* prefix for this abrev */
+ struct obj *node; /* pointer into object table */
+ char *oid; /* ASN.1 encoded OID */
+} obj_abrev_list[] = {
+#ifndef NO_ABREV_MIB
+ /* .iso.org.dod.internet.mgmt.mib */
+ { "", &_mib_obj, "\53\6\1\2\1" },
+#endif
+#ifndef NO_ABREV_ENTER
+ /* .iso.org.dod.internet.private.enterprises */
+ { "E:", &_enterprises_obj, "\53\6\1\4\1" },
+#endif
+#ifndef NO_ABREV_EXPERI
+ /* .iso.org.dod.internet.experimental */
+ { "X:", &_experimental_obj, "\53\6\1\3" },
+#endif
+ { 0,0,0 }
+};
+
+/*
+ * This is used in the OID print routine to walk down the object tree
+ * rooted at `mibroot'.
+ */
+#define OBJ_PRINT(o, suppressdot) \
+{ \
+ if (objp) { \
+ do { \
+ if ((o) == objp->oid) \
+ break; \
+ } while (objp = objp->next); \
+ } \
+ if (objp) { \
+ printf(suppressdot?"%s":".%s", objp->desc); \
+ objp = objp->child; \
+ } else \
+ printf(suppressdot?"%u":".%u", (o)); \
+}
+
+/*
+ * This is the definition for the Any-Data-Type storage used purely for
+ * temporary internal representation while decoding an ASN.1 data stream.
+ */
+struct be {
+ unsigned long asnlen;
+ union {
+ caddr_t raw;
+ long integer;
+ unsigned long uns;
+ unsigned char *str;
+ } data;
+ unsigned char form, class, id; /* tag info */
+ u_char type;
+#define BE_ANY 255
+#define BE_NONE 0
+#define BE_NULL 1
+#define BE_OCTET 2
+#define BE_OID 3
+#define BE_INT 4
+#define BE_UNS 5
+#define BE_STR 6
+#define BE_SEQ 7
+#define BE_INETADDR 8
+#define BE_PDU 9
+};
+
+/*
+ * Defaults for SNMP PDU components
+ */
+#define DEF_COMMUNITY "public"
+#define DEF_VERSION 0
+
+/*
+ * constants for ASN.1 decoding
+ */
+#define OIDMUX 40
+#define ASNLEN_INETADDR 4
+#define ASN_SHIFT7 7
+#define ASN_SHIFT8 8
+#define ASN_BIT8 0x80
+#define ASN_LONGLEN 0x80
+
+#define ASN_ID_BITS 0x1f
+#define ASN_FORM_BITS 0x20
+#define ASN_FORM_SHIFT 5
+#define ASN_CLASS_BITS 0xc0
+#define ASN_CLASS_SHIFT 6
+
+#define ASN_ID_EXT 0x1f /* extension ID in tag field */
+
+/*
+ * truncated==1 means the packet was complete, but we don't have all of
+ * it to decode.
+ */
+static int truncated;
+#define ifNotTruncated if (truncated) fputs("[|snmp]", stdout); else
+
+/*
+ * This decodes the next ASN.1 object in the stream pointed to by "p"
+ * (and of real-length "len") and stores the intermediate data in the
+ * provided BE object.
+ *
+ * This returns -l if it fails (i.e., the ASN.1 stream is not valid).
+ * O/w, this returns the number of bytes parsed from "p".
+ */
+int
+asn1_parse(p, len, elem)
+ register u_char *p;
+ int len;
+ struct be *elem;
+{
+ unsigned char form, class, id;
+ int indent=0, i, hdr;
+ char *classstr;
+
+ elem->asnlen = 0;
+ elem->type = BE_ANY;
+ if (len < 1) {
+ ifNotTruncated puts("[nothing to parse], stdout");
+ return -1;
+ }
+
+ /*
+ * it would be nice to use a bit field, but you can't depend on them.
+ * +---+---+---+---+---+---+---+---+
+ * + class |frm| id |
+ * +---+---+---+---+---+---+---+---+
+ * 7 6 5 4 3 2 1 0
+ */
+ id = *p & ASN_ID_BITS; /* lower 5 bits, range 00-1f */
+#ifdef notdef
+ form = (*p & 0xe0) >> 5; /* move upper 3 bits to lower 3 */
+ class = form >> 1; /* bits 7&6 -> bits 1&0, range 0-3 */
+ form &= 0x1; /* bit 5 -> bit 0, range 0-1 */
+#else
+ form = (*p & ASN_FORM_BITS) >> ASN_FORM_SHIFT;
+ class = (*p & ASN_CLASS_BITS) >> ASN_CLASS_SHIFT;
+#endif
+ elem->form = form;
+ elem->class = class;
+ elem->id = id;
+ if (vflag)
+ printf("|%.2x", *p);
+ p++; len--; hdr = 1;
+ /* extended tag field */
+ if (id == ASN_ID_EXT) {
+ for (id = 0; *p & ASN_BIT8 && len > 0; len--, hdr++, p++) {
+ if (vflag)
+ printf("|%.2x", *p);
+ id += *p & ~ASN_BIT8;
+ }
+ if (len == 0 && *p & ASN_BIT8) {
+ ifNotTruncated fputs("[Xtagfield?]", stdout);
+ return -1;
+ }
+ }
+ if (len < 1) {
+ ifNotTruncated fputs("[no asnlen]", stdout);
+ return -1;
+ }
+ elem->asnlen = *p;
+ if (vflag)
+ printf("|%.2x", *p);
+ p++; len--; hdr++;
+ if (elem->asnlen & ASN_BIT8) {
+ int noct = elem->asnlen % ASN_BIT8;
+ elem->asnlen = 0;
+ if (len < noct) {
+ ifNotTruncated printf("[asnlen? %d<%d]", len, noct);
+ return -1;
+ }
+ for (; noct-- > 0; len--, hdr++) {
+ if (vflag)
+ printf("|%.2x", *p);
+ elem->asnlen = (elem->asnlen << ASN_SHIFT8) | *p++;
+ }
+ }
+ if (len < elem->asnlen) {
+ if (!truncated) {
+ printf("[len%d<asnlen%u]", len, elem->asnlen);
+ return -1;
+ }
+ /* maybe should check at least 4? */
+ elem->asnlen = len;
+ }
+ if (form >= sizeof(Form)/sizeof(Form[0])) {
+ ifNotTruncated printf("[form?%d]", form);
+ return -1;
+ }
+ if (class >= sizeof(Class)/sizeof(Class[0])) {
+ ifNotTruncated printf("[class?%c/%d]", *Form[form], class);
+ return -1;
+ }
+ if (id >= Class[class].numIDs) {
+ ifNotTruncated printf("[id?%c/%s/%d]", *Form[form],
+ Class[class].name, id);
+ return -1;
+ }
+
+ switch (form) {
+ case PRIMITIVE:
+ switch (class) {
+ case UNIVERSAL:
+ switch (id) {
+ case STRING:
+ elem->type = BE_STR;
+ elem->data.str = p;
+ break;
+
+ case INTEGER: {
+ register long data;
+ elem->type = BE_INT;
+ data = 0;
+
+ if (*p & ASN_BIT8) /* negative */
+ data = -1;
+ for (i = elem->asnlen; i-- > 0; p++)
+ data = (data << ASN_SHIFT8) | *p;
+ elem->data.integer = data;
+ break;
+ }
+
+ case OBJECTID:
+ elem->type = BE_OID;
+ elem->data.raw = (caddr_t)p;
+ break;
+
+ case ASN_NULL:
+ elem->type = BE_NULL;
+ elem->data.raw = NULL;
+ break;
+
+ default:
+ elem->type = BE_OCTET;
+ elem->data.raw = (caddr_t)p;
+ printf("[P/U/%s]",
+ Class[class].Id[id]);
+ break;
+ }
+ break;
+
+ case APPLICATION:
+ switch (id) {
+ case IPADDR:
+ elem->type = BE_INETADDR;
+ elem->data.raw = (caddr_t)p;
+ break;
+
+ case COUNTER:
+ case GAUGE:
+ case TIMETICKS: {
+ register unsigned long data;
+ elem->type = BE_UNS;
+ data = 0;
+ for (i = elem->asnlen; i-- > 0; p++)
+ data = (data << 8) + *p;
+ elem->data.uns = data;
+ break;
+ }
+
+ default:
+ elem->type = BE_OCTET;
+ elem->data.raw = (caddr_t)p;
+ printf("[P/A/%s]",
+ Class[class].Id[id]);
+ break;
+ }
+ break;
+
+ default:
+ elem->type = BE_OCTET;
+ elem->data.raw = (caddr_t)p;
+ printf("[P/%s/%s]",
+ Class[class].name, Class[class].Id[id]);
+ break;
+ }
+ break;
+
+ case CONSTRUCTED:
+ switch (class) {
+ case UNIVERSAL:
+ switch (id) {
+ case SEQUENCE:
+ elem->type = BE_SEQ;
+ elem->data.raw = (caddr_t)p;
+ break;
+
+ default:
+ elem->type = BE_OCTET;
+ elem->data.raw = (caddr_t)p;
+ printf("C/U/%s", Class[class].Id[id]);
+ break;
+ }
+ break;
+
+ case CONTEXT:
+ elem->type = BE_PDU;
+ elem->data.raw = (caddr_t)p;
+ break;
+
+ default:
+ elem->type = BE_OCTET;
+ elem->data.raw = (caddr_t)p;
+ printf("C/%s/%s",
+ Class[class].name, Class[class].Id[id]);
+ break;
+ }
+ break;
+ }
+ p += elem->asnlen;
+ len -= elem->asnlen;
+ return elem->asnlen + hdr;
+}
+
+/*
+ * Display the ASN.1 object represented by the BE object.
+ * This used to be an integral part of asn1_parse() before the intermediate
+ * BE form was added.
+ */
+void
+asn1_print(elem)
+ struct be *elem;
+{
+ u_char *p = (u_char *)elem->data.raw;
+ u_long asnlen = elem->asnlen;
+ int i;
+
+ switch (elem->type) {
+
+ case BE_OCTET:
+ for (i = asnlen; i-- > 0; p++);
+ printf("_%.2x", *p);
+ break;
+
+ case BE_NULL:
+ break;
+
+ case BE_OID: {
+ int o = 0, first = -1, i = asnlen;
+
+ if (!nflag && asnlen > 2) {
+ struct obj_abrev *a = &obj_abrev_list[0];
+ for (; a->node; a++) {
+ if (!memcmp(a->oid, p, strlen(a->oid))) {
+ objp = a->node->child;
+ i -= strlen(a->oid);
+ p += strlen(a->oid);
+ fputs(a->prefix, stdout);
+ first = 1;
+ break;
+ }
+ }
+ }
+ for (; i-- > 0; p++) {
+ o = (o << ASN_SHIFT7) + (*p & ~ASN_BIT8);
+ if (*p & ASN_LONGLEN)
+ continue;
+
+ /*
+ * first subitem encodes two items with 1st*OIDMUX+2nd
+ */
+ if (first < 0) {
+ if (!nflag)
+ objp = mibroot;
+ first = 0;
+ OBJ_PRINT(o/OIDMUX, first);
+ o %= OIDMUX;
+ }
+ OBJ_PRINT(o, first);
+ if (--first < 0)
+ first = 0;
+ o = 0;
+ }
+ break;
+ }
+
+ case BE_INT:
+ printf("%ld", elem->data.integer);
+ break;
+
+ case BE_UNS:
+ printf("%ld", elem->data.uns);
+ break;
+
+ case BE_STR: {
+ register int printable = 1, first = 1;
+ u_char *p = elem->data.str;
+ for (i = asnlen; printable && i-- > 0; p++)
+ printable = isprint(*p) || isspace(*p);
+ p = elem->data.str;
+ if (printable)
+ (void)printfn(p, p+asnlen);
+ else
+ for (i = asnlen; i-- > 0; p++) {
+ printf(first ? "%.2x" : "_%.2x", *p);
+ first = 0;
+ }
+ break;
+ }
+
+ case BE_SEQ:
+ printf("Seq(%d)", elem->asnlen);
+ break;
+
+ case BE_INETADDR: {
+ char sep;
+ if (asnlen != ASNLEN_INETADDR)
+ printf("[inetaddr len!=%d]", ASNLEN_INETADDR);
+ sep='[';
+ for (i = asnlen; i-- > 0; p++) {
+ printf("%c%u", sep, *p);
+ sep='.';
+ }
+ putchar(']');
+ break;
+ }
+
+ case BE_PDU:
+ printf("%s(%d)",
+ Class[CONTEXT].Id[elem->id], elem->asnlen);
+ break;
+
+ case BE_ANY:
+ fputs("[BE_ANY!?]", stdout);
+ break;
+
+ default:
+ fputs("[be!?]", stdout);
+ break;
+ }
+}
+
+#ifdef notdef
+/*
+ * This is a brute force ASN.1 printer: recurses to dump an entire structure.
+ * This will work for any ASN.1 stream, not just an SNMP PDU.
+ *
+ * By adding newlines and spaces at the correct places, this would print in
+ * Rose-Normal-Form.
+ *
+ * This is not currently used.
+ */
+void
+asn1_decode(p, length)
+ u_char *p;
+ int length;
+{
+ struct be elem;
+ int i = 0;
+
+ while (i >= 0 && length > 0) {
+ i = asn1_parse(p, length, &elem);
+ if (i >= 0) {
+ fputs(" ", stdout);
+ asn1_print(&elem);
+ if (elem.type == BE_SEQ || elem.type == BE_PDU) {
+ fputs(" {", stdout);
+ asn1_decode(elem.data.raw, elem.asnlen);
+ fputs(" }", stdout);
+ }
+ length -= i;
+ p += i;
+ }
+ }
+}
+#endif
+
+/*
+ * General SNMP header
+ * SEQUENCE {
+ * version INTEGER {version-1(0)},
+ * community OCTET STRING,
+ * data ANY -- PDUs
+ * }
+ * PDUs for all but Trap: (see rfc1157 from page 15 on)
+ * SEQUENCE {
+ * request-id INTEGER,
+ * error-status INTEGER,
+ * error-index INTEGER,
+ * varbindlist SEQUENCE OF
+ * SEQUENCE {
+ * name ObjectName,
+ * value ObjectValue
+ * }
+ * }
+ * PDU for Trap:
+ * SEQUENCE {
+ * enterprise OBJECT IDENTIFIER,
+ * agent-addr NetworkAddress,
+ * generic-trap INTEGER,
+ * specific-trap INTEGER,
+ * time-stamp TimeTicks,
+ * varbindlist SEQUENCE OF
+ * SEQUENCE {
+ * name ObjectName,
+ * value ObjectValue
+ * }
+ * }
+ */
+
+/*
+ * Decode SNMP varBind
+ */
+void
+varbind_print (pduid, np, length, error)
+ u_char pduid, *np;
+ int length, error;
+{
+ struct be elem;
+ int count = 0, index;
+
+ /* Sequence of varBind */
+ if ((count = asn1_parse(np, length, &elem)) < 0)
+ return;
+ if (elem.type != BE_SEQ) {
+ fputs("[!SEQ of varbind]", stdout);
+ asn1_print(&elem);
+ return;
+ }
+ if (count < length)
+ printf("[%d extra after SEQ of varbind]", length - count);
+ /* descend */
+ length = elem.asnlen;
+ np = (u_char *)elem.data.raw;
+
+ for (index = 1; length > 0; index++) {
+ u_char *vbend;
+ int vblength;
+
+ if (!error || index == error)
+ fputs(" ", stdout);
+
+ /* Sequence */
+ if ((count = asn1_parse(np, length, &elem)) < 0)
+ return;
+ if (elem.type != BE_SEQ) {
+ fputs("[!varbind]", stdout);
+ asn1_print(&elem);
+ return;
+ }
+ vbend = np + count;
+ vblength = length - count;
+ /* descend */
+ length = elem.asnlen;
+ np = (u_char *)elem.data.raw;
+
+ /* objName (OID) */
+ if ((count = asn1_parse(np, length, &elem)) < 0)
+ return;
+ if (elem.type != BE_OID) {
+ fputs("[objName!=OID]", stdout);
+ asn1_print(&elem);
+ return;
+ }
+ if (!error || index == error)
+ asn1_print(&elem);
+ length -= count;
+ np += count;
+
+ if (pduid != GETREQ && pduid != GETNEXTREQ && !error)
+ fputs("=", stdout);
+
+ /* objVal (ANY) */
+ if ((count = asn1_parse(np, length, &elem)) < 0)
+ return;
+ if (pduid == GETREQ || pduid == GETNEXTREQ) {
+ if (elem.type != BE_NULL) {
+ fputs("[objVal!=NULL]", stdout);
+ asn1_print(&elem);
+ }
+ } else
+ if (error && index == error && elem.type != BE_NULL)
+ fputs("[err objVal!=NULL]", stdout);
+ if (!error || index == error)
+ asn1_print(&elem);
+
+ length = vblength;
+ np = vbend;
+ }
+}
+
+/*
+ * Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, and SetRequest
+ */
+void
+snmppdu_print (pduid, np, length)
+ u_char pduid, *np;
+ int length;
+{
+ struct be elem;
+ int count = 0, error;
+
+ /* reqId (Integer) */
+ if ((count = asn1_parse(np, length, &elem)) < 0)
+ return;
+ if (elem.type != BE_INT) {
+ fputs("[reqId!=INT]", stdout);
+ asn1_print(&elem);
+ return;
+ }
+ /* ignore the reqId */
+ length -= count;
+ np += count;
+
+ /* errorStatus (Integer) */
+ if ((count = asn1_parse(np, length, &elem)) < 0)
+ return;
+ if (elem.type != BE_INT) {
+ fputs("[errorStatus!=INT]", stdout);
+ asn1_print(&elem);
+ return;
+ }
+ error = 0;
+ if ((pduid == GETREQ || pduid == GETNEXTREQ)
+ && elem.data.integer != 0) {
+ char errbuf[10];
+ printf("[errorStatus(%s)!=0]",
+ DECODE_ErrorStatus(elem.data.integer));
+ } else if (elem.data.integer != 0) {
+ char errbuf[10];
+ printf(" %s", DECODE_ErrorStatus(elem.data.integer));
+ error = elem.data.integer;
+ }
+ length -= count;
+ np += count;
+
+ /* errorIndex (Integer) */
+ if ((count = asn1_parse(np, length, &elem)) < 0)
+ return;
+ if (elem.type != BE_INT) {
+ fputs("[errorIndex!=INT]", stdout);
+ asn1_print(&elem);
+ return;
+ }
+ if ((pduid == GETREQ || pduid == GETNEXTREQ)
+ && elem.data.integer != 0)
+ printf("[errorIndex(%d)!=0]", elem.data.integer);
+ else if (elem.data.integer != 0) {
+ if (!error)
+ printf("[errorIndex(%d) w/o errorStatus]",
+ elem.data.integer);
+ else {
+ printf("@%d", elem.data.integer);
+ error = elem.data.integer;
+ }
+ } else if (error) {
+ fputs("[errorIndex==0]", stdout);
+ error = 0;
+ }
+ length -= count;
+ np += count;
+
+ varbind_print(pduid, np, length, error);
+ return;
+}
+
+/*
+ * Decode SNMP Trap PDU
+ */
+void
+trap_print (np, length)
+ u_char *np;
+ int length;
+{
+ struct be elem;
+ int count = 0, generic;
+
+ putchar(' ');
+
+ /* enterprise (oid) */
+ if ((count = asn1_parse(np, length, &elem)) < 0)
+ return;
+ if (elem.type != BE_OID) {
+ fputs("[enterprise!=OID]", stdout);
+ asn1_print(&elem);
+ return;
+ }
+ asn1_print(&elem);
+ length -= count;
+ np += count;
+
+ putchar(' ');
+
+ /* agent-addr (inetaddr) */
+ if ((count = asn1_parse(np, length, &elem)) < 0)
+ return;
+ if (elem.type != BE_INETADDR) {
+ fputs("[agent-addr!=INETADDR]", stdout);
+ asn1_print(&elem);
+ return;
+ }
+ asn1_print(&elem);
+ length -= count;
+ np += count;
+
+ /* generic-trap (Integer) */
+ if ((count = asn1_parse(np, length, &elem)) < 0)
+ return;
+ if (elem.type != BE_INT) {
+ fputs("[generic-trap!=INT]", stdout);
+ asn1_print(&elem);
+ return;
+ }
+ generic = elem.data.integer;
+ {
+ char buf[10];
+ printf(" %s", DECODE_GenericTrap(generic));
+ }
+ length -= count;
+ np += count;
+
+ /* specific-trap (Integer) */
+ if ((count = asn1_parse(np, length, &elem)) < 0)
+ return;
+ if (elem.type != BE_INT) {
+ fputs("[specific-trap!=INT]", stdout);
+ asn1_print(&elem);
+ return;
+ }
+ if (generic != GT_ENTERPRISE) {
+ if (elem.data.integer != 0)
+ printf("[specific-trap(%d)!=0]", elem.data.integer);
+ } else
+ printf(" s=%d", elem.data.integer);
+ length -= count;
+ np += count;
+
+ putchar(' ');
+
+ /* time-stamp (TimeTicks) */
+ if ((count = asn1_parse(np, length, &elem)) < 0)
+ return;
+ if (elem.type != BE_UNS) { /* XXX */
+ fputs("[time-stamp!=TIMETICKS]", stdout);
+ asn1_print(&elem);
+ return;
+ }
+ asn1_print(&elem);
+ length -= count;
+ np += count;
+
+ varbind_print (TRAP, np, length, 0);
+ return;
+}
+
+/*
+ * Decode SNMP header and pass on to PDU printing routines
+ */
+void
+snmp_print (np, length)
+ u_char *np;
+ int length;
+{
+ struct be elem, pdu;
+ int count = 0;
+
+ truncated = 0;
+
+ /* truncated packet? */
+ if (np + length > snapend) {
+ truncated = 1;
+ length = snapend - np;
+ }
+
+ putchar(' ');
+
+ /* initial Sequence */
+ if ((count = asn1_parse(np, length, &elem)) < 0)
+ return;
+ if (elem.type != BE_SEQ) {
+ fputs("[!init SEQ]", stdout);
+ asn1_print(&elem);
+ return;
+ }
+ if (count < length)
+ printf("[%d extra after iSEQ]", length - count);
+ /* descend */
+ length = elem.asnlen;
+ np = (u_char *)elem.data.raw;
+ /* Version (Integer) */
+ if ((count = asn1_parse(np, length, &elem)) < 0)
+ return;
+ if (elem.type != BE_INT) {
+ fputs("[version!=INT]", stdout);
+ asn1_print(&elem);
+ return;
+ }
+ /* only handle version==0 */
+ if (elem.data.integer != DEF_VERSION) {
+ printf("[version(%d)!=0]", elem.data.integer);
+ return;
+ }
+ length -= count;
+ np += count;
+
+ /* Community (String) */
+ if ((count = asn1_parse(np, length, &elem)) < 0)
+ return;
+ if (elem.type != BE_STR) {
+ fputs("[comm!=STR]", stdout);
+ asn1_print(&elem);
+ return;
+ }
+ /* default community */
+ if (strncmp(elem.data.str, DEF_COMMUNITY, sizeof(DEF_COMMUNITY)-1))
+ /* ! "public" */
+ printf("C=%.*s ", elem.asnlen, elem.data.str);
+ length -= count;
+ np += count;
+
+ /* PDU (Context) */
+ if ((count = asn1_parse(np, length, &pdu)) < 0)
+ return;
+ if (pdu.type != BE_PDU) {
+ fputs("[no PDU]", stdout);
+ return;
+ }
+ if (count < length)
+ printf("[%d extra after PDU]", length - count);
+ asn1_print(&pdu);
+ /* descend into PDU */
+ length = pdu.asnlen;
+ np = (u_char *)pdu.data.raw;
+
+ switch (pdu.id) {
+ case TRAP:
+ trap_print(np, length);
+ break;
+ case GETREQ:
+ case GETNEXTREQ:
+ case GETRESP:
+ case SETREQ:
+ snmppdu_print(pdu.id, np, length);
+ break;
+ }
+ return;
+}
diff --git a/usr.sbin/tcpdump/tcpdump/print-sunrpc.c b/usr.sbin/tcpdump/tcpdump/print-sunrpc.c
new file mode 100644
index 000000000000..ad28e93b46c0
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-sunrpc.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 1992 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: print-sunrpc.c,v 1.1 92/06/02 11:36:37 mccanne Exp $ (LBL)";
+#endif
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+
+#include <sys/time.h>
+#include <errno.h>
+#include <rpc/types.h>
+#include <rpc/auth.h>
+#include <rpc/auth_unix.h>
+#include <rpc/svc.h>
+#include <rpc/xdr.h>
+#include <rpc/rpc_msg.h>
+
+#include <rpc/pmap_prot.h>
+
+#include <ctype.h>
+
+#include "interface.h"
+
+#include "addrtoname.h"
+#include "extract.h"
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+/*
+ * Byte swap an array of n words.
+ * Assume input is word-aligned.
+ * Check that buffer is bounded by "snapend".
+ */
+static void
+bswap(bp, n)
+ register u_long *bp;
+ register u_int n;
+{
+ register int nwords = ((char *)snapend - (char *)bp) / sizeof(*bp);
+
+ if (nwords > n)
+ nwords = n;
+ for (; --nwords >= 0; ++bp)
+ *bp = ntohl(*bp);
+}
+#endif
+
+void
+sunrpcrequest_print(rp, length, ip)
+ register struct rpc_msg *rp;
+ int length;
+ register struct ip *ip;
+{
+ register u_long *dp;
+ register u_char *ep = snapend;
+#define TCHECK(p, l) if ((u_char *)(p) > ep - l) break
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ bswap((u_long *)rp, sizeof(*rp) / sizeof(u_long));
+#endif
+
+ if (!nflag)
+ (void)printf("%s.%x > %s.sunrpc: %d",
+ ipaddr_string(&ip->ip_src),
+ rp->rm_xid,
+ ipaddr_string(&ip->ip_dst),
+ length);
+ else
+ (void)printf("%s.%x > %s.%x: %d",
+ ipaddr_string(&ip->ip_src),
+ rp->rm_xid,
+ ipaddr_string(&ip->ip_dst),
+ PMAPPORT,
+ length);
+
+ switch (rp->rm_call.cb_proc) {
+
+ case PMAPPROC_NULL:
+ printf(" null");
+ break;
+
+ case PMAPPROC_SET:
+ printf(" set");
+ break;
+
+ case PMAPPROC_UNSET:
+ printf(" unset");
+ break;
+
+ case PMAPPROC_GETPORT:
+ printf(" getport");
+ break;
+
+ case PMAPPROC_DUMP:
+ printf(" dump");
+ break;
+
+ case PMAPPROC_CALLIT:
+ printf(" callit");
+ break;
+
+ default:
+ printf(" proc #%d", rp->rm_call.cb_proc);
+ }
+ printf(" prog #%d", rp->rm_call.cb_prog);
+ putchar('\n');
+}
+
diff --git a/usr.sbin/tcpdump/tcpdump/print-tcp.c b/usr.sbin/tcpdump/tcpdump/print-tcp.c
new file mode 100644
index 000000000000..9974b3c0d027
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-tcp.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: print-tcp.c,v 1.18 92/05/25 14:29:04 mccanne Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#ifdef X10
+#include <X/X.h>
+#include <X/Xproto.h>
+#endif
+
+#include "interface.h"
+#include "addrtoname.h"
+
+#ifndef TCPOPT_WSCALE
+#define TCPOPT_WSCALE 3 /* window scale factor (rfc1072) */
+#endif
+#ifndef TCPOPT_SACKOK
+#define TCPOPT_SACKOK 4 /* selective ack ok (rfc1072) */
+#endif
+#ifndef TCPOPT_SACK
+#define TCPOPT_SACK 5 /* selective ack (rfc1072) */
+#endif
+#ifndef TCPOPT_ECHO
+#define TCPOPT_ECHO 6 /* echo (rfc1072) */
+#endif
+#ifndef TCPOPT_ECHOREPLY
+#define TCPOPT_ECHOREPLY 7 /* echo (rfc1072) */
+#endif
+
+struct tha {
+ struct in_addr src;
+ struct in_addr dst;
+ u_int port;
+};
+
+struct tcp_seq_hash {
+ struct tcp_seq_hash *nxt;
+ struct tha addr;
+ tcp_seq seq;
+ tcp_seq ack;
+};
+
+#define TSEQ_HASHSIZE 919
+
+static struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE];
+
+
+void
+tcp_print(tp, length, ip)
+ register struct tcphdr *tp;
+ register int length;
+ register struct ip *ip;
+{
+ register u_char flags;
+ register int hlen;
+
+ if ((u_char *)(tp + 1) > snapend) {
+ printf("[|tcp]");
+ return;
+ }
+ if (length < sizeof(struct tcphdr)) {
+ (void)printf("truncated-tcp %d", length);
+ return;
+ }
+
+ NTOHS(tp->th_sport);
+ NTOHS(tp->th_dport);
+ NTOHL(tp->th_seq);
+ NTOHL(tp->th_ack);
+ NTOHS(tp->th_win);
+ NTOHS(tp->th_urp);
+
+ (void)printf("%s.%s > %s.%s: ",
+ ipaddr_string(&ip->ip_src), tcpport_string(tp->th_sport),
+ ipaddr_string(&ip->ip_dst), tcpport_string(tp->th_dport));
+
+ if (!qflag) {
+#ifdef X10
+ register int be;
+
+ if ((be = (tp->th_sport == X_TCP_BI_PORT ||
+ tp->th_dport == X_TCP_BI_PORT)) ||
+ tp->th_sport == X_TCP_LI_PORT ||
+ tp->th_dport == X_TCP_LI_PORT) {
+ register XReq *xp = (XReq *)(tp + 1);
+
+ x10_print(xp, length - sizeof(struct tcphdr), be);
+ return;
+ }
+#endif
+ }
+
+ if (qflag) {
+ (void)printf("tcp %d", length - tp->th_off * 4);
+ return;
+ }
+ if ((flags = tp->th_flags) & (TH_SYN|TH_FIN|TH_RST|TH_PUSH)) {
+ if (flags & TH_SYN)
+ putchar('S');
+ if (flags & TH_FIN)
+ putchar('F');
+ if (flags & TH_RST)
+ putchar('R');
+ if (flags & TH_PUSH)
+ putchar('P');
+ } else
+ putchar('.');
+
+ if (!Sflag && (flags & TH_ACK)) {
+ register struct tcp_seq_hash *th;
+ register int rev;
+ struct tha tha;
+ /*
+ * Find (or record) the initial sequence numbers for
+ * this conversation. (we pick an arbitrary
+ * collating order so there's only one entry for
+ * both directions).
+ */
+ if (tp->th_sport < tp->th_dport ||
+ (tp->th_sport == tp->th_dport &&
+ ip->ip_src.s_addr < ip->ip_dst.s_addr)) {
+ tha.src = ip->ip_src, tha.dst = ip->ip_dst;
+ tha.port = tp->th_sport << 16 | tp->th_dport;
+ rev = 0;
+ } else {
+ tha.src = ip->ip_dst, tha.dst = ip->ip_src;
+ tha.port = tp->th_dport << 16 | tp->th_sport;
+ rev = 1;
+ }
+
+ for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
+ th->nxt; th = th->nxt)
+ if (!bcmp((char *)&tha, (char *)&th->addr,
+ sizeof(th->addr)))
+ break;
+
+ if (!th->nxt || flags & TH_SYN) {
+ /* didn't find it or new conversation */
+ if (!th->nxt)
+ th->nxt = (struct tcp_seq_hash *)
+ calloc(1, sizeof (*th));
+ th->addr = tha;
+ if (rev)
+ th->ack = tp->th_seq, th->seq = tp->th_ack - 1;
+ else
+ th->seq = tp->th_seq, th->ack = tp->th_ack - 1;
+ } else {
+ if (rev)
+ tp->th_seq -= th->ack, tp->th_ack -= th->seq;
+ else
+ tp->th_seq -= th->seq, tp->th_ack -= th->ack;
+ }
+ }
+ hlen = tp->th_off * 4;
+ length -= hlen;
+ if (length > 0 || flags & (TH_SYN | TH_FIN | TH_RST))
+ (void)printf(" %lu:%lu(%d)", tp->th_seq, tp->th_seq + length,
+ length);
+ if (flags & TH_ACK)
+ (void)printf(" ack %lu", tp->th_ack);
+
+ (void)printf(" win %d", tp->th_win);
+
+ if (flags & TH_URG)
+ (void)printf(" urg %d", tp->th_urp);
+ /*
+ * Handle any options.
+ */
+ if ((hlen -= sizeof(struct tcphdr)) > 0) {
+ register u_char *cp = (u_char *)tp + sizeof(struct tcphdr);
+ int i;
+ char ch = '<';
+
+ putchar(' ');
+ while (--hlen >= 0) {
+ putchar(ch);
+ switch (*cp++) {
+ case TCPOPT_MAXSEG:
+ {
+ u_short mss;
+#ifdef TCPDUMP_ALIGN
+ bcopy((char *)cp + 1, (char *)&mss,
+ sizeof(mss));
+#else
+ mss = *(u_short *)(cp + 1);
+#endif
+ (void)printf("mss %d", ntohs(mss));
+ if (*cp != 4)
+ (void)printf("[len %d]", *cp);
+ cp += 3;
+ hlen -= 3;
+ break;
+ }
+ case TCPOPT_EOL:
+ (void)printf("eol");
+ break;
+ case TCPOPT_NOP:
+ (void)printf("nop");
+ break;
+ case TCPOPT_WSCALE:
+ (void)printf("wscale %d", cp[1]);
+ if (*cp != 3)
+ (void)printf("[len %d]", *cp);
+ cp += 2;
+ hlen -= 2;
+ break;
+ case TCPOPT_SACKOK:
+ (void)printf("sackOK");
+ if (*cp != 2)
+ (void)printf("[len %d]", *cp);
+ cp += 1;
+ hlen -= 1;
+ break;
+ case TCPOPT_ECHO:
+ {
+ u_long v;
+#ifdef TCPDUMP_ALIGN
+ bcopy((char *)cp + 1, (char *)&v,
+ sizeof(v));
+#else
+ v = *(u_long *)(cp + 1);
+#endif
+ (void)printf("echo %lu", v);
+ if (*cp != 6)
+ (void)printf("[len %d]", *cp);
+ cp += 5;
+ hlen -= 5;
+ break;
+ }
+ case TCPOPT_ECHOREPLY:
+ {
+ u_long v;
+#ifdef TCPDUMP_ALIGN
+ bcopy((char *)cp + 1, (char *)&v,
+ sizeof(v));
+#else
+ v = *(u_long *)(cp + 1);
+#endif
+ (void)printf("echoreply %lu", v);
+ if (*cp != 6)
+ (void)printf("[len %d]", *cp);
+ cp += 5;
+ hlen -= 5;
+ break;
+ }
+ default:
+ (void)printf("opt-%d:", cp[-1]);
+ for (i = *cp++ - 2, hlen -= i + 1; i > 0; --i)
+ (void)printf("%02x", *cp++);
+ break;
+ }
+ ch = ',';
+ }
+ putchar('>');
+ }
+}
+
diff --git a/usr.sbin/tcpdump/tcpdump/print-tftp.c b/usr.sbin/tcpdump/tcpdump/print-tftp.c
new file mode 100644
index 000000000000..3f8f079a6106
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-tftp.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Format and print trivial file transfer protocol packets.
+ */
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: print-tftp.c,v 1.13 91/04/19 10:46:57 mccanne Exp $ (LBL)";
+#endif
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <arpa/tftp.h>
+
+#include "interface.h"
+#include <strings.h>
+#include <ctype.h>
+
+struct int2str {
+ int code;
+ char *str;
+};
+
+/* op code to string mapping */
+static struct int2str op2str[] = {
+ RRQ, "RRQ", /* read request */
+ WRQ, "WRQ", /* write request */
+ DATA, "DATA", /* data packet */
+ ACK, "ACK", /* acknowledgement */
+ ERROR, "ERROR", /* error code */
+ 0, 0
+};
+
+/* error code to string mapping */
+static struct int2str err2str[] = {
+ EUNDEF, "EUNDEF", /* not defined */
+ ENOTFOUND, "ENOTFOUND", /* file not found */
+ EACCESS, "EACCESS", /* access violation */
+ ENOSPACE, "ENOSPACE", /* disk full or allocation exceeded *?
+ EBADOP, "EBADOP", /* illegal TFTP operation */
+ EBADID, "EBADID", /* unknown transfer ID */
+ EEXISTS, "EEXISTS", /* file already exists */
+ ENOUSER, "ENOUSER", /* no such user */
+ 0, 0
+};
+
+/*
+ * Print trivial file transfer program requests
+ */
+void
+tftp_print(tp, length)
+ register struct tftphdr *tp;
+ int length;
+{
+ register struct int2str *ts;
+ register u_char *ep;
+#define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc
+ static char tstr[] = " [|tftp]";
+
+ /* 'ep' points to the end of avaible data. */
+ ep = (u_char *)snapend;
+
+ /* Print length */
+ printf(" %d", length);
+
+ /* Print tftp request type */
+ TCHECK(tp->th_opcode, sizeof(tp->th_opcode));
+ NTOHS(tp->th_opcode);
+ putchar(' ');
+ for (ts = op2str; ts->str; ++ts)
+ if (ts->code == tp->th_opcode) {
+ fputs(ts->str, stdout);
+ break;
+ }
+ if (ts->str == 0) {
+ /* Bail if bogus opcode */
+ printf("tftp-#%d", tp->th_opcode);
+ return;
+ }
+
+ switch (tp->th_opcode) {
+
+ case RRQ:
+ case WRQ:
+ putchar(' ');
+ if (printfn((u_char *)tp->th_stuff, ep)) {
+ fputs(&tstr[1], stdout);
+ return;
+ }
+ break;
+
+ case DATA:
+ TCHECK(tp->th_block, sizeof(tp->th_block));
+ NTOHS(tp->th_block);
+ printf(" block %d", tp->th_block);
+ break;
+
+ case ACK:
+ break;
+
+ case ERROR:
+ /* Print error code string */
+ TCHECK(tp->th_code, sizeof(tp->th_code));
+ NTOHS(tp->th_code);
+ putchar(' ');
+ for (ts = err2str; ts->str; ++ts)
+ if (ts->code == tp->th_code) {
+ fputs(ts->str, stdout);
+ break;
+ }
+ if (ts->str == 0)
+ printf("tftp-err-#%d", tp->th_code);
+
+ /* Print error message string */
+ putchar(' ');
+ if (printfn((u_char *)tp->th_data, ep)) {
+ fputs(&tstr[1], stdout);
+ return;
+ }
+ break;
+
+ default:
+ /* We shouldn't get here */
+ printf("(unknown #%d)", tp->th_opcode);
+ break;
+ }
+ return;
+trunc:
+ fputs(tstr, stdout);
+#undef TCHECK
+}
diff --git a/usr.sbin/tcpdump/tcpdump/print-udp.c b/usr.sbin/tcpdump/tcpdump/print-udp.c
new file mode 100644
index 000000000000..cd5180890219
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-udp.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: print-udp.c,v 1.26 92/05/22 19:43:17 leres Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+#include <arpa/nameser.h>
+#include <arpa/tftp.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <rpc/types.h>
+#include <rpc/auth.h>
+#include <rpc/auth_unix.h>
+#include <rpc/svc.h>
+#include <rpc/xdr.h>
+#include <rpc/rpc_msg.h>
+
+#include "interface.h"
+/* These must come after interface.h for BSD. */
+#if BSD >= 199006
+#include <sys/ucred.h>
+#include <nfs/nfsv2.h>
+#endif
+#include <nfs/nfs.h>
+
+#include "addrtoname.h"
+#include "appletalk.h"
+
+#include "bootp.h"
+
+/* XXX probably should use getservbyname() and cache answers */
+#define TFTP_PORT 69 /*XXX*/
+#define SUNRPC_PORT 111 /*XXX*/
+#define SNMP_PORT 161 /*XXX*/
+#define NTP_PORT 123 /*XXX*/
+#define SNMPTRAP_PORT 162 /*XXX*/
+#define RIP_PORT 520 /*XXX*/
+
+void
+udp_print(up, length, ip)
+ register struct udphdr *up;
+ int length;
+ register struct ip *ip;
+{
+ register u_char *cp = (u_char *)(up + 1);
+
+ if (cp > snapend) {
+ printf("[|udp]");
+ return;
+ }
+ if (length < sizeof(struct udphdr)) {
+ (void)printf(" truncated-udp %d", length);
+ return;
+ }
+ length -= sizeof(struct udphdr);
+
+ NTOHS(up->uh_sport);
+ NTOHS(up->uh_dport);
+ NTOHS(up->uh_ulen);
+
+ if (! qflag) {
+ register struct rpc_msg *rp;
+ enum msg_type direction;
+
+ rp = (struct rpc_msg *)(up + 1);
+ direction = (enum msg_type)ntohl(rp->rm_direction);
+ if (up->uh_dport == NFS_PORT && direction == CALL) {
+ nfsreq_print(rp, length, ip);
+ return;
+ }
+ else if (up->uh_sport == NFS_PORT && direction == REPLY) {
+ nfsreply_print(rp, length, ip);
+ return;
+ }
+#ifdef notdef
+ else if (up->uh_dport == SUNRPC_PORT && direction == CALL) {
+ sunrpcrequest_print(rp, length, ip);
+ return;
+ }
+#endif
+ else if (cp[2] == 2 && (atalk_port(up->uh_sport) ||
+ atalk_port(up->uh_dport))) {
+ ddp_print((struct atDDP *)(&cp[3]), length - 3);
+ return;
+ }
+ }
+ (void)printf("%s.%s > %s.%s:",
+ ipaddr_string(&ip->ip_src), udpport_string(up->uh_sport),
+ ipaddr_string(&ip->ip_dst), udpport_string(up->uh_dport));
+
+ if (!qflag) {
+#define ISPORT(p) (up->uh_dport == (p) || up->uh_sport == (p))
+ if (ISPORT(NAMESERVER_PORT))
+ ns_print((HEADER *)(up + 1), length);
+ else if (ISPORT(TFTP_PORT))
+ tftp_print((struct tftphdr *)(up + 1), length);
+ else if (ISPORT(IPPORT_BOOTPC) || ISPORT(IPPORT_BOOTPS))
+ bootp_print((struct bootp *)(up + 1), length,
+ up->uh_sport, up->uh_dport);
+ else if (up->uh_dport == RIP_PORT)
+ rip_print((u_char *)(up + 1), length);
+ else if (ISPORT(SNMP_PORT) || ISPORT(SNMPTRAP_PORT))
+ snmp_print((u_char *)(up + 1), length);
+ else if (ISPORT(NTP_PORT))
+ ntp_print((struct ntpdata *)(up + 1), length);
+ else
+ (void)printf(" udp %d", up->uh_ulen - sizeof(*up));
+#undef ISPORT
+ } else
+ (void)printf(" udp %d", up->uh_ulen - sizeof(*up));
+}
diff --git a/usr.sbin/tcpdump/tcpdump/savefile.c b/usr.sbin/tcpdump/tcpdump/savefile.c
new file mode 100644
index 000000000000..79bb9e8afc68
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/savefile.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 1990,1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static char rcsid[] =
+ "@(#)$Header: savefile.c,v 1.27 92/01/26 21:29:26 mccanne Exp $ (LBL)";
+#endif
+
+/*
+ * savefile.c - supports offline use of tcpdump
+ * Extraction/creation by Jeffrey Mogul, DECWRL
+ * Modified by Steve McCanne, LBL.
+ *
+ * Used to save the received packet headers, after filtering, to
+ * a file, and then read them later.
+ * The first record in the file contains saved values for the machine
+ * dependent values so we can print the dump file on any architecture.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <net/bpf.h>
+
+#include "version.h"
+#include "savefile.h"
+
+#define TCPDUMP_MAGIC 0xa1b2c3d4
+
+/*
+ * The first record in the file contains saved values for some
+ * of the flags used in the printout phases of tcpdump.
+ * Many fields here are longs so compilers won't insert unwanted
+ * padding; these files need to be interchangeable across architectures.
+ */
+struct file_header {
+ u_long magic;
+ u_short version_major;
+ u_short version_minor;
+ long thiszone; /* gmt to local correction */
+ u_long sigfigs; /* accuracy of timestamps */
+ u_long snaplen; /* max length saved portion of each pkt */
+ u_long linktype;
+};
+
+int sf_swapped;
+
+FILE *sf_readfile;
+FILE *sf_writefile;
+
+static int
+sf_write_header(fp, linktype, thiszone, snaplen, precision)
+ FILE *fp;
+ int linktype;
+ int thiszone;
+ int snaplen;
+ int precision;
+{
+ struct file_header hdr;
+
+ hdr.magic = TCPDUMP_MAGIC;
+ hdr.version_major = VERSION_MAJOR;
+ hdr.version_minor = VERSION_MINOR;
+
+ hdr.thiszone = thiszone;
+ hdr.snaplen = snaplen;
+ hdr.sigfigs = precision;
+ hdr.linktype = linktype;
+
+ if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1)
+ return -1;
+
+ return 0;
+}
+
+static void
+swap_hdr(hp)
+ struct file_header *hp;
+{
+ hp->version_major = SWAPSHORT(hp->version_major);
+ hp->version_minor = SWAPSHORT(hp->version_minor);
+ hp->thiszone = SWAPLONG(hp->thiszone);
+ hp->sigfigs = SWAPLONG(hp->sigfigs);
+ hp->snaplen = SWAPLONG(hp->snaplen);
+ hp->linktype = SWAPLONG(hp->linktype);
+}
+
+int
+sf_read_init(fname, linktypep, thiszonep, snaplenp, precision)
+ char *fname;
+ int *linktypep, *thiszonep, *snaplenp, *precision;
+{
+ register FILE *fp;
+ struct file_header hdr;
+
+ if (fname[0] == '-' && fname[1] == '\0')
+ fp = stdin;
+ else {
+ fp = fopen(fname, "r");
+ if (fp == 0) {
+ (void) fprintf(stderr, "tcpdump: fopen: ");
+ perror(fname);
+ exit(1);
+ }
+ }
+ if (fread((char *)&hdr, sizeof(hdr), 1, fp) != 1) {
+ (void) fprintf(stderr, "tcpdump: fread: ");
+ perror(fname);
+ exit(1);
+ }
+ if (hdr.magic != TCPDUMP_MAGIC) {
+ if (SWAPLONG(hdr.magic) != TCPDUMP_MAGIC)
+ return SFERR_BADF;
+ sf_swapped = 1;
+ swap_hdr(&hdr);
+ }
+ if (hdr.version_major < VERSION_MAJOR)
+ return SFERR_BADVERSION;
+
+ *thiszonep = hdr.thiszone;
+ *snaplenp = hdr.snaplen;
+ *linktypep = hdr.linktype;
+ *precision = hdr.sigfigs;
+
+ sf_readfile = fp;
+
+ return 0;
+}
+
+/*
+ * Print out packets stored in the file initilized by sf_read_init().
+ * If cnt >= 0, return after 'cnt' packets, otherwise continue until eof.
+ */
+int
+sf_read(filtp, cnt, snaplen, printit)
+ struct bpf_program *filtp;
+ int cnt, snaplen;
+ void (*printit)();
+{
+ struct packet_header h;
+ u_char *buf;
+ struct bpf_insn *fcode = filtp->bf_insns;
+ int status = 0;
+
+ buf = (u_char *)malloc(snaplen);
+
+ while (status == 0) {
+ status = sf_next_packet(&h, buf, snaplen);
+
+ if (status)
+ break;
+ /*
+ * XXX It's possible (and likely) for us to screw up the
+ * network layer alignment when we pass down packets from
+ * this point (ip_print deals by copying the ip header
+ * to an aligned buffer). There doesn't seem to be a
+ * clean way to fix this. We could compute an offset
+ * from the link type (which would have to be passed in),
+ * but that only works for fixed size headers.
+ */
+ if (bpf_filter(fcode, buf, h.len, h.caplen)) {
+ if (cnt >= 0 && --cnt < 0)
+ break;
+ (*printit)(buf, &h.ts, h.len, h.caplen);
+ }
+ }
+
+ if (status == SFERR_EOF)
+ /* treat EOF's as okay status */
+ status = 0;
+
+ free((char *)buf);
+ return status;
+}
+
+/*
+ * Read sf_readfile and return the next packet. Return the header in hdr
+ * and the contents in buf. Return 0 on success, SFERR_EOF if there were
+ * no more packets, and SFERR_TRUNC if a partial packet was encountered.
+ */
+int
+sf_next_packet(hdr, buf, buflen)
+ struct packet_header *hdr;
+ u_char *buf;
+ int buflen;
+{
+ FILE *fp = sf_readfile;
+
+ /* read the stamp */
+ if (fread((char *)hdr, sizeof(struct packet_header), 1, fp) != 1) {
+ /* probably an EOF, though could be a truncated packet */
+ return SFERR_EOF;
+ }
+
+ if (sf_swapped) {
+ /* these were written in opposite byte order */
+ hdr->caplen = SWAPLONG(hdr->caplen);
+ hdr->len = SWAPLONG(hdr->len);
+ hdr->ts.tv_sec = SWAPLONG(hdr->ts.tv_sec);
+ hdr->ts.tv_usec = SWAPLONG(hdr->ts.tv_usec);
+ }
+
+ if (hdr->caplen > buflen)
+ return SFERR_BADF;
+
+ /* read the packet itself */
+
+ if (fread((char *)buf, hdr->caplen, 1, fp) != 1)
+ return SFERR_TRUNC;
+
+ return 0;
+}
+
+/*
+ * Initialize so that sf_write() will output to the file named 'fname'.
+ */
+void
+sf_write_init(fname, linktype, thiszone, snaplen, precision)
+ char *fname;
+ int linktype;
+ int thiszone;
+ int snaplen;
+ int precision;
+{
+ if (fname[0] == '-' && fname[1] == '\0')
+ sf_writefile = stdout;
+ else {
+ sf_writefile = fopen(fname, "w");
+ if (sf_writefile == 0) {
+ (void) fprintf(stderr, "tcpdump: fopen: ");
+ perror(fname);
+ exit(1);
+ }
+ }
+ (void)sf_write_header(sf_writefile,
+ linktype, thiszone, snaplen, precision);
+}
+
+/*
+ * Output a packet to the intialized dump file.
+ */
+void
+sf_write(sp, tvp, length, caplen)
+ u_char *sp;
+ struct timeval *tvp;
+ int length;
+ int caplen;
+{
+ struct packet_header h;
+
+ h.ts.tv_sec = tvp->tv_sec;
+ h.ts.tv_usec = tvp->tv_usec;
+ h.len = length;
+ h.caplen = caplen;
+
+ (void)fwrite((char *)&h, sizeof h, 1, sf_writefile);
+ (void)fwrite((char *)sp, caplen, 1, sf_writefile);
+}
+
+void
+sf_err(code)
+ int code;
+{
+ switch (code) {
+ case SFERR_BADVERSION:
+ error("archaic file format");
+ /* NOTREACHED */
+
+ case SFERR_BADF:
+ error("bad dump file format");
+ /* NOTREACHED */
+
+ case SFERR_TRUNC:
+ error("truncated dump file");
+ /* NOTREACHED */
+
+ case SFERR_EOF:
+ error("EOF reading dump file");
+ /* NOTREACHED */
+
+ default:
+ error("unknown dump file error code in sf_err()");
+ /* NOTREACHED */
+ }
+ abort();
+}
diff --git a/usr.sbin/tcpdump/tcpdump/savefile.h b/usr.sbin/tcpdump/tcpdump/savefile.h
new file mode 100644
index 000000000000..a5082f9fb276
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/savefile.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Header: savefile.h,v 1.10 90/12/17 13:48:58 mccanne Exp $
+ *
+ * Header for offline storage info.
+ * Extraction/creation by Jeffrey Mogul, DECWRL.
+ *
+ * Used to save the received packet headers, after filtering, to
+ * a file, and then read them later.
+ */
+
+/*
+ * Each packet in the dump file is prepended with this generic header.
+ * This gets around the problem of different headers for different
+ * packet interfaces.
+ */
+struct packet_header {
+ struct timeval ts; /* time stamp */
+ u_long len; /* length this packet (off wire) */
+ u_long caplen; /* length of portion present */
+};
+
+/* true if the contents of the savefile being read are byte-swapped */
+extern int sf_swapped;
+
+/* macros for when sf_swapped is true: */
+/*
+ * We use the "receiver-makes-right" approach to byte order,
+ * because time is at a premium when we are writing the file.
+ * In other words, the file_header and packet_header records
+ * are written in host byte order.
+ * Note that the packets are always written in network byte order.
+ *
+ * ntoh[ls] aren't sufficient because we might need to swap on a big-endian
+ * machine (if the file was written in little-end order).
+ */
+#define SWAPLONG(y) \
+((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
+#define SWAPSHORT(y) \
+ ( (((y)&0xff)<<8) | (((y)&0xff00)>>8) )
+
+
+extern FILE *sf_readfile; /* dump file being read from */
+extern FILE *sf_writefile; /* dump file being written to */
+
+int sf_read_init();
+int sf_read();
+int sf_next_packet();
+void sf_write_init();
+void sf_write();
+void sf_err();
+
+#define SFERR_TRUNC 1
+#define SFERR_BADVERSION 2
+#define SFERR_BADF 3
+#define SFERR_EOF 4 /* not really an error, just a status */
+
diff --git a/usr.sbin/tcpdump/tcpdump/tcpdump.1 b/usr.sbin/tcpdump/tcpdump/tcpdump.1
new file mode 100644
index 000000000000..2406319e0ffc
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/tcpdump.1
@@ -0,0 +1,1067 @@
+.\" @(#) $Header: tcpdump.1,v 1.40 92/01/29 16:56:02 mccanne Exp $ (LBL)
+.\"
+.\" Copyright (c) 1988, 1989, 1990, 1991, 1992
+.\" The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH TCPDUMP 1 "4 Jan 1992"
+.SH NAME
+tcpdump \- dump traffic on a network
+.SH SYNOPSIS
+.na
+.B tcpdump
+[
+.B \-deflnNOpqStvx
+] [
+.B \-c
+.I count
+] [
+.B \-F
+.I file
+]
+.br
+.ti +8
+[
+.B \-i
+.I interface
+] [
+.B \-r
+.I file
+]
+[
+.B \-s
+.I snaplen
+]
+.br
+.ti +8
+[
+.B \-w
+.I file
+]
+.I expression
+.br
+.ad
+.SH DESCRIPTION
+.LP
+\fITcpdump\fP prints out the headers of packets on a network interface
+that match the boolean \fIexpression\fP.
+.B Under SunOS:
+You must be root to invoke \fItcpdump\fP or it must be installed
+setuid to root.
+.B Under Ultrix:
+Any user can invoke \fItcpdump\fP once the super-user has enabled
+promiscuous-mode operation using
+.IR pfconfig (8).
+.B Under BSD:
+Access is controlled by the permissions on
+.I /dev/bpf0,
+etc.
+.SH OPTIONS
+.TP
+.B \-c
+Exit after receiving \fIcount\fP packets.
+.TP
+.B \-d
+Dump the compiled packet-matching code to standard output and stop.
+.TP
+.B \-e
+Print the link-level header on each dump line.
+.TP
+.B \-f
+Print `foreign' internet addresses numerically rather than symbolically
+(this option is intended to get around serious brain damage in
+Sun's yp server \(em usually it hangs forever translating non-local
+internet numbers).
+.TP
+.B \-F
+Use \fIfile\fP as input for the filter expression.
+An additional expression given on the command line is ignored.
+.TP
+.B \-i
+Listen on \fIinterface\fP.
+If unspecified, \fItcpdump\fP searches the system interface list for the
+lowest numbered, configured up interface (excluding loopback).
+Ties are broken by choosing the earliest match.
+.TP
+.B \-l
+Make stdout line buffered. Useful if you want to see the data
+while capturing it. E.g.,
+.br
+``tcpdump\ \ \-l\ \ |\ \ tee dat'' or
+``tcpdump\ \ \-l \ \ > dat\ \ &\ \ tail\ \ \-f\ \ dat''.
+.TP
+.B \-n
+Don't convert addresses (i.e., host addresses, port numbers, etc.) to names.
+.TP
+.B \-N
+Don't print domain name qualification of host names. E.g.,
+if you give this flag then \fItcpdump\fP will print ``nic''
+instead of ``nic.ddn.mil''.
+.TP
+.B \-O
+Do not run the packet-matching code optimizer. This is useful only
+if you suspect a bug in the optimizer.
+.TP
+.B \-p
+\fIDon't\fP put the interface
+into promiscuous mode. Note that the interface might be in promiscuous
+for some other reason; hence, `-p' cannot be used as an abbreviation for
+`ether host {localhost} or broadcast'.
+.TP
+.B \-q
+Quick (quiet?) output. Print less protocol information so output
+lines are shorter.
+.TP
+.B \-r
+Read packets from \fIfile\fR (which was created with the -w option).
+Standard input is used if \fIfile\fR is ``-''.
+.TP
+.B \-s
+Snarf \fIsnaplen\fP bytes of data from each packet rather than the
+default of 68 (with NIT, the minimum is actually 96).
+68 bytes is adequate for IP, ICMP, TCP
+and UDP but may truncate protocol information from name server and NFS
+packets (see below). Packets truncated because of a limited snapshot
+are indicated in the output with ``[|\fIproto\fP]'', where \fIproto\fP
+is the name of the protocol level at which the truncation has occured.
+Note that taking larger snapshots both increases
+the amount of time it takes to process packets and, effectively,
+decreases the amount of packet buffering. This may cause packets to be
+lost. You should limit \fIsnaplen\fP to the smallest number that will
+capture the protocol information you're interested in.
+.TP
+.B \-S
+Print absolute, rather than relative, TCP sequence numbers.
+.TP
+.B \-t
+\fIDon't\fP print a timestamp on each dump line.
+.TP
+.B \-tt
+Print an unformatted timestamp on each dump line.
+.TP
+.B \-v
+(Slightly more) verbose output. For example, the time to live
+and type of service information in an IP packet is printed.
+.TP
+.B \-w
+Write the raw packets to \fIfile\fR rather than parsing and printing
+them out. They can later be printed with the \-r option.
+Standard output is used if \fIfile\fR is ``-''.
+.TP
+.B \-x
+Print each packet (minus its link level header) in hex.
+The smaller of the entire packet or
+.I snaplen
+bytes will be printed.
+.IP "\fI expression\fP"
+.RS
+selects which packets will be dumped. If no \fIexpression\fP
+is given, all packets on the net will be dumped. Otherwise,
+only packets for which \fIexpression\fP is `true' will be dumped.
+.LP
+The \fIexpression\fP consists of one or more
+.I primitives.
+Primitives usually consist of an
+.I id
+(name or number) preceded by one or more qualifiers. There are three
+different kinds of qualifier:
+.IP \fItype\fP
+qualifiers say what kind of thing the id name or number refers to.
+Possible types are
+.BR host ,
+.B net
+and
+.BR port .
+E.g., `host foo', `net 128.3', `port 20'. If there is no type
+qualifier,
+.B host
+is assumed.
+.IP \fIdir\fP
+qualifiers specify a particular tranfer direction to and/or from
+.I id.
+Possible directions are
+.BR src ,
+.BR dst ,
+.B "src or dst"
+and
+.BR "src and dst" .
+E.g., `src foo', `dst net 128.3', `src or dst port ftp-data'. If
+there is no dir qualifier,
+.B "src or dst"
+is assumed.
+.IP \fIproto\fP
+qualifiers restrict the match to a particular protocol. Possible
+protos are:
+.BR ether ,
+.BR ip ,
+.BR arp ,
+.BR rarp ,
+.B tcp
+and
+.BR udp .
+E.g., `ether src foo', `arp net 128.3', `tcp port 21'. If there is
+no proto qualifier, all protocols consistent with the type are
+assumed. E.g., `src foo' means `(ip or arp or rarp) src foo'
+(except the latter is not legal syntax), `net bar' means `(ip or
+arp or rarp) net bar' and `port 53' means `(tcp or udp) port 53'.
+.LP
+In addition to the above, there are some special `primitive' keywords
+that don't follow the pattern:
+.BR gateway ,
+.BR broadcast ,
+.BR less ,
+.B greater
+and arithmetic expressions. All of these are described below.
+.LP
+More complex filter expressions are built up by using the words
+.BR and ,
+.B or
+and
+.B not
+to combine primitives. E.g., `host foo and not port ftp and not port ftp-data'.
+To save typing, identical qualifier lists can be omitted. E.g.,
+`tcp dst port ftp or ftp-data or domain' is exactly the same as
+`tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain'.
+.LP
+Allowable primitives are:
+.IP "\fBdst host \fIhost\fR"
+True if the IP destination field of the packet is \fIhost\fP,
+which may be either an address or a name.
+.IP "\fBsrc host \fIhost\fR"
+True if the IP source field of the packet is \fIhost\fP.
+.IP "\fBhost \fIhost\fP
+True if either the IP source or destination of the packet is \fIhost\fP.
+Any of the above host expressions can be prepended with the keywords,
+\fBip\fP, \fBarp\fP, or \fBrarp\fP as in:
+.in +.5i
+.nf
+\fBip host \fIhost\fR
+.fi
+.in -.5i
+which is equivalent to:
+.in +.5i
+.nf
+\fBether proto \fI\\ip\fB and host \fIhost\fR
+.fi
+.in -.5i
+If \fIhost\fR is a name with multiple IP addresses, each address will
+be checked for a match.
+.IP "\fBether dst \fIehost\fP
+True if the ethernet destination address is \fIehost\fP. \fIEhost\fP
+may be either a name from /etc/ethers or a number (see
+.IR ethers (3N)
+for numeric format).
+.IP "\fBether src \fIehost\fP
+True if the ethernet source address is \fIehost\fP.
+.IP "\fBether host \fIehost\fP
+True if either the ethernet source or destination address is \fIehost\fP.
+.IP "\fBgateway\fP \fIhost\fP
+True if the packet used \fIhost\fP as a gateway. I.e., the ethernet
+source or destination address was \fIhost\fP but neither the IP source
+nor the IP destination was \fIhost\fP. \fIHost\fP must be a name and
+must be found in both /etc/hosts and /etc/ethers. (An equivalent
+expression is
+.in +.5i
+.nf
+\fBether host \fIehost \fBand not host \fIhost\fR
+.fi
+.in -.5i
+which can be used with either names or numbers for \fIhost / ehost\fP.)
+.IP "\fBdst net \fInet\fR"
+True if the IP destination address of the packet has a network
+number of \fInet\fP, which may be either an address or a name.
+.IP "\fBsrc net \fInet\fR"
+True if the IP source address of the packet has a network
+number of \fInet\fP.
+.IP "\fBnet \fInet\fR"
+True if either the IP source or destination address of the packet has a network
+number of \fInet\fP.
+.IP "\fBdst port \fIport\fR"
+True if the packet is ip/tcp or ip/udp and has a
+destination port value of \fIport\fP.
+The \fIport\fP can be a number or a name used in /etc/services (see
+.IR tcp (4P)
+and
+.IR udp (4P)).
+If a name is used, both the port
+number and protocol are checked. If a number or ambiguous name is used,
+only the port number is checked (e.g., \fBdst port 513\fR will print both
+tcp/login traffic and udp/who traffic, and \fBport domain\fR will print
+both tcp/domain and udp/domain traffic).
+.IP "\fBsrc port \fIport\fR"
+True if the packet has a source port value of \fIport\fP.
+.IP "\fBport \fIport\fR"
+True if either the source or destination port of the packet is \fIport\fP.
+Any of the above port expressions can be prepended with the keywords,
+\fBtcp\fP or \fBudp\fP, as in:
+.in +.5i
+.nf
+\fBtcp src port \fIport\fR
+.fi
+.in -.5i
+which matches only tcp packets.
+.IP "\fBless \fIlength\fR"
+True if the packet has a length less than or equal to \fIlength\fP.
+This is equivalent to:
+.in +.5i
+.nf
+\fBlen <= \fIlength\fP.
+.fi
+.in -.5i
+.IP "\fBgreater \fIlength\fR"
+True if the packet has a length greater than or equal to \fIlength\fP.
+This is equivalent to:
+.in +.5i
+.nf
+\fBlen >= \fIlength\fP.
+.fi
+.in -.5i
+.IP "\fBip proto \fIprotocol\fR"
+True if the packet is an ip packet (see
+.IR ip (4P))
+of protocol type \fIprotocol\fP.
+\fIProtocol\fP can be a number or one of the names
+\fIicmp\fP, \fIudp\fP, \fInd\fP, or \fItcp\fP.
+Note that the identifiers \fItcp\fP, \fIudp\fP, and \fIicmp\fP are also
+keywords and must be escaped via backslash (\\), which is \\\\ in the C-shell.
+.IP "\fBether broadcast\fR"
+True if the packet is an ethernet broadcast packet. The \fIether\fP
+keyword is optional.
+.IP "\fBip broadcast\fR"
+True if the packet is an IP broadcast packet. It checks for both
+the all-zeroes and all-ones broadcast conventions, and looks up
+the local subnet mask.
+.IP "\fBether multicast\fR"
+True if the packet is an ethernet multicast packet. The \fIether\fP
+keyword is optional.
+This is shorthand for `\fBether[0] & 1 != 0\fP'.
+.IP "\fBip multicast\fR"
+True if the packet is an IP multicast packet.
+.IP "\fBether proto \fIprotocol\fR"
+True if the packet is of ether type \fIprotocol\fR.
+\fIProtocol\fP can be a number or a name like
+\fIip\fP, \fIarp\fP, or \fIrarp\fP.
+Note these identifiers are also keywords
+and must be escaped via backslash (\\).
+.IP "\fBip\fR, \fBarp\fR, \fBrarp\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBether proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBtcp\fR, \fBudp\fR, \fBicmp\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBip proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fIexpr relop expr\fR"
+True if the relation holds, where \fIrelop\fR is one of >, <, >=, <=, =, !=,
+and \fIexpr\fR is an arithmetic expression composed of integer constants
+(expressed in standard C syntax), the normal binary operators
+[+, -, *, /, &, |], a length operator, and special packet data accessors.
+To access
+data inside the packet, use the following syntax:
+.in +.5i
+.nf
+\fIproto\fB [ \fIexpr\fB : \fIsize\fB ]\fR
+.fi
+.in -.5i
+\fIProto\fR is one of \fBether, ip, arp, rarp, tcp, udp, \fRor \fBicmp\fR, and
+indicates the protocol layer for the index operation.
+The byte offset, relative to the indicated protocol layer, is
+given by \fIexpr\fR.
+\fISize\fR is optional and indicates the number of bytes in the
+field of interest; it can be either one, two, or four, and defaults to one.
+The length operator, indicated by the keyword \fBlen\fP, gives the
+length of the packet.
+
+For example, `\fBether[0] & 1 != 0\fP' catches all multicast traffic.
+The expression `\fBip[0] & 0xf != 5\fP'
+catches all IP packets with options. The expression
+`\fBip[2:2] & 0x1fff = 0\fP'
+catches only unfragmented datagrams and frag zero of fragmented datagrams.
+This check is implicitly applied to the \fBtcp\fP and \fBudp\fP
+index opertations.
+For instance, \fBtcp[0]\fP always means the first
+byte of the TCP \fIheader\fP, and never means the first byte of an
+intervening fragment.
+.LP
+Primitives may be combined using:
+.IP
+A parenthesized group of primitives and operators
+(parentheses are special to the Shell and must be escaped).
+.IP
+Negation (`\fB!\fP' or `\fBnot\fP').
+.IP
+Concatenation (`\fBand\fP').
+.IP
+Alternation (`\fBor\fP').
+.LP
+Negation has highest precedence.
+Alternation and concatenation have equal precedence and associate
+left to right. Note that explicit \fBand\fR tokens, not juxtaposition,
+are now required for concatenation.
+.LP
+If an identifier is given without a keyword, the most recent keyword
+is assumed.
+For example,
+.in +.5i
+.nf
+\fBnot host vs and ace\fR
+.fi
+.in -.5i
+is short for
+.in +.5i
+.nf
+\fBnot host vs and host ace\fR
+.fi
+.in -.5i
+which should not be confused with
+.in +.5i
+.nf
+\fBnot ( host vs or ace )\fR
+.fi
+.in -.5i
+.LP
+Expression arguments can be passed to tcpdump as either a single argument
+or as multiple arguments, whichever is more convenient.
+Generally, if the expression contains Shell metacharacters, it is
+easier to pass it as a single, quoted argument.
+Multiple arguments are concatenated with spaces before being parsed.
+.SH EXAMPLES
+.LP
+To print all packets arriving at or departing from \fIsundown\fP:
+.RS
+.nf
+\fBtcpdump host sundown\fP
+.fi
+.RE
+.LP
+To print traffic between \fIhelios\fR and either \fIhot\fR or \fIace\fR:
+.RS
+.nf
+\fBtcpdump host helios and \\( hot or ace \\)\fP
+.fi
+.RE
+.LP
+To print all IP packets between \fIace\fR and any host except \fIhelios\fR:
+.RS
+.nf
+\fBtcpdump ip host ace and not helios\fP
+.fi
+.RE
+.LP
+To print all traffic between local hosts and hosts at Berkeley:
+.RS
+.nf
+.B
+tcpdump net ucb-ether
+.fi
+.RE
+.LP
+To print all ftp traffic through internet gateway \fIsnup\fP:
+(note that the expression is quoted to prevent the shell from
+(mis-)interpreting the parentheses):
+.RS
+.nf
+.B
+tcpdump 'gateway snup and (port ftp or ftp-data)'
+.fi
+.RE
+.LP
+To print traffic neither sourced from nor destined for local hosts
+(if you gateway to one other net, this stuff should never make it
+onto your local net).
+.RS
+.nf
+.B
+tcpdump ip and not net \fIlocalnet\fP
+.fi
+.RE
+.LP
+To print the start and end packets (the SYN and FIN packets) of each
+TCP conversation that involves a non-local host.
+.RS
+.nf
+.B
+tcpdump 'tcp[13] & 3 != 0 and not src and dst net \fIlocalnet\fP'
+.fi
+.RE
+.LP
+To print IP packets longer than 576 bytes sent through gateway \fIsnup\fP:
+.RS
+.nf
+.B
+tcpdump 'gateway snup and ip[2:2] > 576'
+.fi
+.RE
+.LP
+To print IP broadcast or multicast packets that were
+.I not
+sent via ethernet broadcast or multicast:
+.RS
+.nf
+.B
+tcpdump 'ether[0] & 1 = 0 and ip[16] >= 224'
+.fi
+.RE
+.LP
+To print all ICMP packets that are not echo requests/replies (i.e., not
+ping packets):
+.RS
+.nf
+.B
+tcpdump 'icmp[0] != 8 and icmp[0] != 0"
+.fi
+.RE
+.SH OUTPUT FORMAT
+.LP
+The output of \fItcpdump\fP is protocol dependent. The following
+gives a brief description and examples of most of the formats.
+.de HD
+.sp 1.5
+.B
+..
+.HD
+Link Level Headers
+.LP
+If the '-e' option is given, the link level header is printed out.
+On ethernets, the source and destination addresses, protocol,
+and packet length are printed.
+.LP
+\fI(N.B.: The following description assumes familiarity with
+the SLIP compression algorithm described in RFC-1144.)\fP
+.LP
+On SLIP links, a direction indicator (``I'' for inbound, ``O'' for outbound),
+packet type, and compression information are printed out.
+The packet type is printed first.
+The three types are \fIip\fP, \fIutcp\fP, and \fIctcp\fP.
+No further link information is printed for \fIip\fR packets.
+For TCP packets, the connection identifier is printed following the type.
+If the packet is compressed, its encoded header is printed out.
+The special cases are printed out as
+\fB*S+\fIn\fR and \fB*SA+\fIn\fR, where \fIn\fR is the amount by which
+the sequence number (or sequence number and ack) has changed.
+If it is not a special case,
+zero or more changes are printed.
+A change is indicated by U (urgent pointer), W (window), A (ack),
+S (sequence number), and I (packet ID), followed by a delta (+n or -n),
+or a new value (=n).
+Finally, the amount of data in the packet and compressed header length
+are printed.
+.LP
+For example, the following line shows an outbound compressed TCP packet,
+with an implicit connection identifier; the ack has changed by 6,
+the sequence number by 49, and the packet ID by 6; there are 3 bytes of
+data and 6 bytes of compressed header:
+.RS
+.nf
+\fBO ctcp * A+6 S+49 I+6 3 (6)\fP
+.fi
+.RE
+.HD
+ARP/RARP Packets
+.LP
+Arp/rarp output shows the type of request and its arguments. The
+format is intended to be self explanatory.
+Here is a short sample taken from the start of an `rlogin' from
+host \fIrtsg\fP to host \fIcsam\fP:
+.RS
+.nf
+.sp .5
+\f(CWarp who-has csam tell rtsg
+arp reply csam is-at CSAM\fP
+.sp .5
+.fi
+.RE
+The first line says that rtsg sent an arp packet asking
+for the ethernet address of internet host csam. Csam
+replies with its ethernet address (in this example, ethernet addresses
+are in caps and internet addresses in lower case).
+.LP
+This would look less redundant if we had done \fBtcpdump \-n\fP:
+.RS
+.nf
+.sp .5
+\f(CWarp who-has 128.3.254.6 tell 128.3.254.68
+arp reply 128.3.254.6 is-at 02:07:01:00:01:c4\fP
+.fi
+.RE
+.LP
+If we had done \fBtcpdump \-e\fP, the fact that the first packet is
+broadcast and the second is point-to-point would be visible:
+.RS
+.nf
+.sp .5
+\f(CWRTSG Broadcast 0806 64: arp who-has csam tell rtsg
+CSAM RTSG 0806 64: arp reply csam is-at CSAM\fP
+.sp .5
+.fi
+.RE
+For the first packet this says the ethernet source address is RTSG, the
+destination is the broadcast address, the type field
+contained hex 0806 (type ETHER_ARP) and the total length was 64 bytes.
+.HD
+TCP Packets
+.LP
+\fI(N.B.:The following description assumes familiarity with
+the TCP protocol described in RFC-793. If you are not familiar
+with the protocol, neither this description nor tcpdump will
+be of much use to you.)\fP
+.LP
+The general format of a tcp protocol line is:
+.RS
+.nf
+.sp .5
+\fIsrc > dst: flags data-seqno ack window urgent options\fP
+.sp .5
+.fi
+.RE
+\fISrc\fP and \fIdst\fP are the source and destination IP
+addresses and ports. \fIFlags\fP are some combination of S (SYN),
+F (FIN), P (PUSH) or R (RST) or a single `.' (no flags).
+\fIData-seqno\fP describes the portion of sequence space covered
+by the data in this packet (see example below).
+\fIAck\fP is sequence number of the next data expected the other
+direction on this connection.
+\fIWindow\fP is the number of bytes of receive buffer space available
+the other direction on this connection.
+\fIUrg\fP indicates there is `urgent' data in the packet.
+\fIOptions\fP are tcp options enclosed in angle brackets (e.g., <mss 1024>).
+.LP
+\fISrc, dst\fP and \fIflags\fP are always present. The other fields
+depend on the contents of the packet's tcp protocol header and
+are output only if appropriate.
+.LP
+Here is the opening portion of an rlogin from host \fIrtsg\fP to
+host \fIcsam\fP.
+.RS
+.nf
+.sp .5
+\s-2\f(CWrtsg.1023 > csam.login: S 768512:768512(0) win 4096 <mss 1024>
+csam.login > rtsg.1023: S 947648:947648(0) ack 768513 win 4096 <mss 1024>
+rtsg.1023 > csam.login: . ack 1 win 4096
+rtsg.1023 > csam.login: P 1:2(1) ack 1 win 4096
+csam.login > rtsg.1023: . ack 2 win 4096
+rtsg.1023 > csam.login: P 2:21(19) ack 1 win 4096
+csam.login > rtsg.1023: P 1:2(1) ack 21 win 4077
+csam.login > rtsg.1023: P 2:3(1) ack 21 win 4077 urg 1
+csam.login > rtsg.1023: P 3:4(1) ack 21 win 4077 urg 1\fP\s+2
+.sp .5
+.fi
+.RE
+The first line says that tcp port 1023 on rtsg sent a packet
+to port \fIlogin\fP
+on csam. The \fBS\fP indicates that the \fISYN\fP flag was set.
+The packet sequence number was 768512 and it contained no data.
+(The notation is `first:last(nbytes)' which means `sequence
+numbers \fIfirst\fP
+up to but not including \fIlast\fP which is \fInbytes\fP bytes of user data'.)
+There was no piggy-backed ack, the available receive window was 4096
+bytes and there was a max-segment-size option requesting an mss of
+1024 bytes.
+.LP
+Csam replies with a similar packet except it includes a piggy-backed
+ack for rtsg's SYN. Rtsg then acks csam's SYN. The `.' means no
+flags were set.
+The packet contained no data so there is no data sequence number.
+Note that the ack sequence
+number is a small integer (1). The first time \fBtcpdump\fP sees a
+tcp `conversation', it prints the sequence number from the packet.
+On subsequent packets of the conversation, the difference between
+the current packet's sequence number and this initial sequence number
+is printed. This means that sequence numbers after the
+first can be interpreted
+as relative byte positions in the conversation's data stream (with the
+first data byte each direction being `1'). `-S' will override this
+feature, causing the original sequence numbers to be output.
+.LP
+On the 6th line, rtsg sends csam 19 bytes of data (bytes 2 through 20
+in the rtsg \(-> csam side of the conversation).
+The PUSH flag is set in the packet.
+On the 7th line, csam says it's received data sent by rtsg up to
+but not including byte 21. Most of this data is apparently sitting in the
+socket buffer since csam's receive window has gotten 19 bytes smaller.
+Csam also sends one byte of data to rtsg in this packet.
+On the 8th and 9th lines,
+csam sends two bytes of urgent, pushed data to rtsg.
+.HD
+.B
+UDP Packets
+.LP
+UDP format is illustrated by this rwho packet:
+.RS
+.nf
+.sp .5
+\f(CWactinide.who > broadcast.who: udp 84\fP
+.sp .5
+.fi
+.RE
+This says that port \fIwho\fP on host \fIactinide\fP sent a udp
+datagram to port \fIwho\fP on host \fIbroadcast\fP, the Internet
+broadcast address. The packet contained 84 bytes of user data.
+.LP
+Some UDP services are recognized (from the source or destination
+port number) and the higher level protocol information printed.
+In particular, Domain Name service requests (RFC-1034/1035) and Sun
+RPC calls (RFC-1050) to NFS.
+.HD
+UDP Name Server Requests
+.LP
+\fI(N.B.:The following description assumes familiarity with
+the Domain Service protocol described in RFC-1035. If you are not familiar
+with the protocol, the following description will appear to be written
+in greek.)\fP
+.LP
+Name server requests are formatted as
+.RS
+.nf
+.sp .5
+\fIsrc > dst: id op? flags qtype qclass name (len)\fP
+.sp .5
+\f(CWh2opolo.1538 > helios.domain: 3+ A? ucbvax.berkeley.edu. (37)\fP
+.sp .5
+.fi
+.RE
+Host \fIh2opolo\fP asked the domain server on \fIhelios\fP for an
+address record (qtype=A) associated with the name \fIucbvax.berkeley.edu.\fP
+The query id was `3'. The `+' indicates the \fIrecursion desired\fP flag
+was set. The query length was 37 bytes, not including the UDP and
+IP protocol headers. The query operation was the normal one, \fIQuery\fP,
+so the op field was omitted. If the op had been anything else, it would
+have been printed between the `3' and the `+'.
+Similarly, the qclass was the normal one,
+\fIC_IN\fP, and omitted. Any other qclass would have been printed
+immediately after the `A'.
+.LP
+A few anomalies are checked and may result in extra fields enclosed in
+square brackets: If a query contains an answer, name server or
+authority section,
+.IR ancount ,
+.IR nscount ,
+or
+.I arcount
+are printed as `[\fIn\fPa]', `[\fIn\fPn]' or `[\fIn\fPau]' where \fIn\fP
+is the appropriate count.
+If any of the response bits are set (AA, RA or rcode) or any of the
+`must be zero' bits are set in bytes two and three, `[b2&3=\fIx\fP]'
+is printed, where \fIx\fP is the hex value of header bytes two and three.
+.HD
+UDP Name Server Responses
+.LP
+Name server responses are formatted as
+.RS
+.nf
+.sp .5
+\fIsrc > dst: id op rcode flags a/n/au type class data (len)\fP
+.sp .5
+\f(CWhelios.domain > h2opolo.1538: 3 3/3/7 A 128.32.137.3 (273)
+helios.domain > h2opolo.1537: 2 NXDomain* 0/1/0 (97)\fP
+.sp .5
+.fi
+.RE
+In the first example, \fIhelios\fP responds to query id 3 from \fIh2opolo\fP
+with 3 answer records, 3 name server records and 7 authority records.
+The first answer record is type A (address) and its data is internet
+address 128.32.137.3. The total size of the response was 273 bytes,
+excluding UDP and IP headers. The op (Query) and response code
+(NoError) were omitted, as was the class (C_IN) of the A record.
+.LP
+In the second example, \fIhelios\fP responds to query 2 with a
+response code of non-existent domain (NXDomain) with no answers,
+one name server and no authority records. The `*' indicates that
+the \fIauthoritative answer\fP bit was set. Since there were no
+answers, no type, class or data were printed.
+.LP
+Other flag characters that might appear are `\-' (recursion available,
+RA, \fInot\fP set) and `|' (truncated message, TC, set). If the
+`question' section doesn't contain exactly one entry, `[\fIn\fPq]'
+is printed.
+.LP
+Note that name server requests and responses tend to be large and the
+default \fIsnaplen\fP of 96 bytes may not capture enough of the packet
+to print. Use the \fB\-s\fP flag to increase the snaplen if you
+need to seriously investigate name server traffic. `\fB\-s 128\fP'
+has worked well for me.
+
+.HD
+NFS Requests
+.LP
+Sun NFS (Network File System) requests and replies are printed as:
+.RS
+.nf
+.sp .5
+\fIsrc.xid > dst.nfs: len op args\fP
+\fIsrc.nfs > dst.xid: reply stat len\fP
+.sp .5
+\f(CWvs.e2766 > helios.nfs: 136 readdir fh 6.5197 8192 bytes @ 0
+helios.nfs > vs.e2766: reply ok 384
+vs.e2767 > helios.nfs: 136 lookup fh 6.5197 `RCS'\fP
+.sp .5
+.fi
+.RE
+In the first line, host \fIvs\fP sends a transaction with id \fIe2766\fP
+to \fIhelios\fP (note that the number following the src host is a
+transaction id, \fInot\fP the source port). The request was 136 bytes,
+excluding the UDP and IP headers. The operation was a \fIreaddir\fP
+(read directory) on file handle (\fIfh\fP) 6.5197. 8192 bytes are
+read, starting at offset 0. \fIHelios\fP replies `ok' with 384
+bytes of data. (The design of Sun's RPC protocol makes it difficult to
+interpret replies. I don't bother.)
+.LP
+In the third line, \fIvs\fP asks \fIhelios\fP to lookup the name
+`\fIRCS\fP' in directory file 6.5197. Note that the data printed
+depends on the operation type. The format is intended to be self
+explanatory (at least, to me) if read in conjunction with
+an NFS protocol spec.
+.LP
+Note that NFS requests are very large and the above won't be printed
+unless \fIsnaplen\fP is increased. I use `\fB\-s 192\fP' to watch
+NFS traffic.
+
+.HD
+KIP Appletalk (DDP in UDP)
+.LP
+Appletalk DDP packets encapsulated in UDP datagrams are de-encapsulated
+and dumped as DDP packets (i.e., all the UDP header information is
+discarded). The file
+.I /etc/atalk.names
+is used to translate appletalk net and node numbers to names.
+Lines in this file have the form
+.RS
+.nf
+.sp .5
+\fInumber name\fP
+
+\f(CW1.254 ether
+16.1 icsd-net
+1.254.110 ace\fP
+.sp .5
+.fi
+.RE
+The first two lines give the names of appletalk networks. The third
+line gives the name of a particular host (a host is distinguished
+from a net by the 3rd octet in the number \-
+a net number \fImust\fP have two octets and a host number \fImust\fP
+have three octets.) The number and name should be separated by
+whitespace (blanks or tabs).
+The
+.I /etc/atalk.names
+file may contain blank lines or comment lines (lines starting with
+a `#').
+.LP
+Appletalk addresses are printed in the form
+.RS
+.nf
+.sp .5
+\fInet.host.port\fP
+
+\f(CW144.1.209.2 > icsd-net.112.220
+office.2 > icsd-net.112.220
+jssmag.149.235 > icsd-net.2\fP
+.sp .5
+.fi
+.RE
+(If the
+.I /etc/atalk.names
+doesn't exist or doesn't contain an entry for some appletalk
+host/net number, addresses are printed in numeric form.)
+In the first example, NBP (DDP port 2) on net 144.1 node 209
+is sending to whatever is listening on port 220 of net icsd node 112.
+The second line is the same except the full name of the source node
+is known (`office'). The third line is a send from port 235 on
+net jssmag node 149 to broadcast on the icsd-net NBP port (note that
+the broadcast address (255) is indicated by a net name with no host
+number \- for this reason it's a good idea to keep node names and
+net names distinct in /etc/atalk.names).
+.LP
+NBP (name binding protocol) and ATP (Appletalk transaction protocol)
+packets have their contents interpreted. Other protocols just dump
+the protocol name (or number if no name is registered for the
+protocol) and packet size.
+
+\fBNBP packets\fP are formatted like the following examples:
+.RS
+.nf
+.sp .5
+\s-2\f(CWicsd-net.112.220 > jssmag.2: nbp-lkup 190: "=:LaserWriter@*"
+jssmag.209.2 > icsd-net.112.220: nbp-reply 190: "RM1140:LaserWriter@*" 250
+techpit.2 > icsd-net.112.220: nbp-reply 190: "techpit:LaserWriter@*" 186\fP\s+2
+.sp .5
+.fi
+.RE
+The first line is a name lookup request for laserwriters sent by net icsd host
+112 and broadcast on net jssmag. The nbp id for the lookup is 190.
+The second line shows a reply for this request (note that it has the
+same id) from host jssmag.209 saying that it has a laserwriter
+resource named "RM1140" registered on port 250. The third line is
+another reply to the same request saying host techpit has laserwriter
+"techpit" registered on port 186.
+
+\fBATP packet\fP formatting is demonstrated by the following example:
+.RS
+.nf
+.sp .5
+\s-2\f(CWjssmag.209.165 > helios.132: atp-req 12266<0-7> 0xae030001
+helios.132 > jssmag.209.165: atp-resp 12266:0 (512) 0xae040000
+helios.132 > jssmag.209.165: atp-resp 12266:1 (512) 0xae040000
+helios.132 > jssmag.209.165: atp-resp 12266:2 (512) 0xae040000
+helios.132 > jssmag.209.165: atp-resp 12266:3 (512) 0xae040000
+helios.132 > jssmag.209.165: atp-resp 12266:4 (512) 0xae040000
+helios.132 > jssmag.209.165: atp-resp 12266:5 (512) 0xae040000
+helios.132 > jssmag.209.165: atp-resp 12266:6 (512) 0xae040000
+helios.132 > jssmag.209.165: atp-resp*12266:7 (512) 0xae040000
+jssmag.209.165 > helios.132: atp-req 12266<3,5> 0xae030001
+helios.132 > jssmag.209.165: atp-resp 12266:3 (512) 0xae040000
+helios.132 > jssmag.209.165: atp-resp 12266:5 (512) 0xae040000
+jssmag.209.165 > helios.132: atp-rel 12266<0-7> 0xae030001
+jssmag.209.133 > helios.132: atp-req* 12267<0-7> 0xae030002\fP\s+2
+.sp .5
+.fi
+.RE
+Jssmag.209 initiates transaction id 12266 with host helios by requesting
+up to 8 packets (the `<0-7>'). The hex number at the end of the line
+is the value of the `userdata' field in the request.
+.LP
+Helios responds with 8 512-byte packets. The `:digit' following the
+transaction id gives the packet sequence number in the transaction
+and the number in parens is the amount of data in the packet,
+excluding the atp header. The `*' on packet 7 indicates that the
+EOM bit was set.
+.LP
+Jssmag.209 then requests that packets 3 & 5 be retransmitted. Helios
+resends them then jssmag.209 releases the transaction. Finally,
+jssmag.209 initiates the next request. The `*' on the request
+indicates that XO (`exactly once') was \fInot\fP set.
+
+.HD
+IP Fragmentation
+.LP
+Fragmented Internet datagrams are printed as
+.RS
+.nf
+.sp .5
+\fB(frag \fIid\fB:\fIsize\fB@\fIoffset\fB+)\fR
+\fB(frag \fIid\fB:\fIsize\fB@\fIoffset\fB)\fR
+.sp .5
+.fi
+.RE
+(The first form indicates there are more fragments. The second
+indicates this is the last fragment.)
+.LP
+\fIId\fP is the fragment id. \fISize\fP is the fragment
+size (in bytes) excluding the IP header. \fIOffset\fP is this
+fragment's offset (in bytes) in the original datagram.
+.LP
+The fragment information is output for each fragment. The first
+fragment contains the higher level protocol header and the frag
+info is printed after the protocol info. Fragments
+after the first contain no higher level protocol header and the
+frag info is printed after the source and destination addresses.
+For example, here is part of an ftp from arizona.edu to lbl-rtsg.arpa
+over a CSNET connection that doesn't appear to handle 576 byte datagrams:
+.RS
+.nf
+.sp .5
+\s-2\f(CWarizona.ftp-data > rtsg.1170: . 1024:1332(308) ack 1 win 4096 (frag 595a:328@0+)
+arizona > rtsg: (frag 595a:204@328)
+rtsg.1170 > arizona.ftp-data: . ack 1536 win 2560\fP\s+2
+.sp .5
+.fi
+.RE
+There are a couple of things to note here: First, addresses in the
+2nd line don't include port numbers. This is because the TCP
+protocol information is all in the first fragment and we have no idea
+what the port or sequence numbers are when we print the later fragments.
+Second, the tcp sequence information in the first line is printed as if there
+were 308 bytes of user data when, in fact, there are 512 bytes (308 in
+the first frag and 204 in the second). If you are looking for holes
+in the sequence space or trying to match up acks
+with packets, this can fool you.
+.LP
+A packet with the IP \fIdon't fragment\fP flag is marked with a
+trailing \fB(DF)\fP.
+.HD
+Timestamps
+.LP
+By default, all output lines are preceded by a timestamp. The timestamp
+is the current clock time in the form
+.RS
+.nf
+\fIhh:mm:ss.frac\fP
+.fi
+.RE
+and is as accurate as the kernel's clock (e.g., \(+-10ms on a Sun-3).
+The timestamp reflects the time the kernel first saw the packet. No attempt
+is made to account for the time lag between when the
+ethernet interface removed the packet from the wire and when the kernel
+serviced the `new packet' interrupt (of course,
+with Sun's lousy clock resolution this time lag is negligible.)
+.SH "SEE ALSO"
+traffic(1C), nit(4P), bpf(4)
+.SH AUTHORS
+Van Jacobson (van@helios.ee.lbl.gov),
+Craig Leres (leres@helios.ee.lbl.gov) and
+Steven McCanne (mccanne@helios.ee.lbl.gov), all of
+Lawrence Berkeley Laboratory, University of California, Berkeley, CA.
+.SH BUGS
+The clock resolution on most Suns is pathetic (20ms).
+If you want to use the timestamp to generate some of the important
+performance distributions (like packet interarrival time) it's best
+to watch something that generates packets slowly (like an Arpanet
+gateway or a MicroVax running VMS).
+.LP
+NIT doesn't let you watch your own outbound traffic, BPF will.
+We recommend that you use the latter.
+.LP
+\fItcpdump\fP for Ultrix requires Ultrix version 4.0 or later; the kernel
+has to have been built with the \fIpacketfilter\fP pseudo-device driver
+(see
+.IR packetfilter (4)).
+As of this writing, Ultrix does not let you
+watch either your own outbound or inbound traffic.
+.LP
+Under SunOS 4.1, the packet capture code (or Streams NIT) is not what
+you'd call efficient. Don't plan on doing much with your Sun while
+you're monitoring a busy network.
+.LP
+On Sun systems prior to release 3.2, NIT is very buggy.
+If run on an old system, tcpdump may crash the machine.
+.LP
+Some attempt should be made to reassemble IP fragments or, at least
+to compute the right length for the higher level protocol.
+.LP
+Name server inverse queries are not dumped correctly: The (empty)
+question section is printed rather than real query in the answer
+section. Some believe that inverse queries are themselves a bug and
+prefer to fix the program generating them rather than tcpdump.
+.LP
+Apple Ethertalk DDP packets could be dumped as easily as KIP DDP
+packets but aren't.
+Even if we were inclined to do anything to promote the use of
+Ethertalk (we aren't), LBL doesn't allow Ethertalk on any of its
+networks so we'd would have no way of testing this code.
+.LP
+A packet trace that crosses a daylight savings time change will give
+skewed time stamps (the time change is ignored).
diff --git a/usr.sbin/tcpdump/tcpdump/tcpdump.c b/usr.sbin/tcpdump/tcpdump/tcpdump.c
new file mode 100644
index 000000000000..9a0ccc4bbd63
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/tcpdump.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 1987-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+char copyright[] =
+ "@(#) Copyright (c) 1987-1990 The Regents of the University of California.\nAll rights reserved.\n";
+static char rcsid[] =
+ "@(#)$Header: tcpdump.c,v 1.68 92/06/02 17:57:41 mccanne Exp $ (LBL)";
+#endif
+
+/*
+ * tcpdump - monitor tcp/ip traffic on an ethernet.
+ *
+ * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory.
+ * Mercilessly hacked and occasionally improved since then via the
+ * combined efforts of Van, Steve McCanne and Craig Leres of LBL.
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <netinet/in.h>
+
+#include <net/bpf.h>
+
+#include "interface.h"
+#include "savefile.h"
+#include "addrtoname.h"
+
+int fflag; /* don't translate "foreign" IP address */
+int nflag; /* leave addresses as numbers */
+int Nflag; /* remove domains from printed host names */
+int pflag; /* don't go promiscuous */
+int qflag; /* quick (shorter) output */
+int tflag = 1; /* print packet arrival time */
+int eflag; /* print ethernet header */
+int vflag; /* verbose */
+int xflag; /* print packet in hex */
+int Oflag = 1; /* run filter code optimizer */
+int Sflag; /* print raw TCP sequence numbers */
+
+int dflag; /* print filter code */
+
+char *program_name;
+
+long thiszone; /* gmt to local correction */
+
+static void cleanup();
+
+/* Length of saved portion of packet. */
+int snaplen = DEFAULT_SNAPLEN;
+
+static int if_fd = -1;
+
+struct printer {
+ void (*f)();
+ int type;
+};
+
+static struct printer printers[] = {
+ { ether_if_print, DLT_EN10MB },
+ { sl_if_print, DLT_SLIP },
+ { ppp_if_print, DLT_PPP },
+ { fddi_if_print, DLT_FDDI },
+ { null_if_print, DLT_NULL },
+ { 0, 0 },
+};
+
+void
+(*lookup_printer(type))()
+ int type;
+{
+ struct printer *p;
+
+ for (p = printers; p->f; ++p)
+ if (type == p->type)
+ return p->f;
+
+ error("unknown data link type 0x%x", type);
+ /* NOTREACHED */
+}
+
+void
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ struct bpf_program *parse();
+ void bpf_dump();
+
+ int cnt = -1, i;
+ struct timeb zt;
+ struct bpf_program *fcode;
+ int op;
+ void (*printit)();
+ char *infile = 0;
+ char *cmdbuf;
+ int linktype;
+ int err;
+ u_long localnet;
+ u_long netmask;
+
+ char *RFileName = 0; /* -r argument */
+ char *WFileName = 0; /* -w argument */
+
+ char *device = 0;
+
+ int precision = clock_sigfigs();
+
+ extern char *optarg;
+ extern int optind, opterr;
+
+ program_name = argv[0];
+
+ opterr = 0;
+ while ((op = getopt(argc, argv, "c:defF:i:lnNOpqr:s:Stvw:xY")) != EOF)
+ switch (op) {
+ case 'c':
+ cnt = atoi(optarg);
+ break;
+
+ case 'd':
+ ++dflag;
+ break;
+
+ case 'e':
+ ++eflag;
+ break;
+
+ case 'f':
+ ++fflag;
+ break;
+
+ case 'F':
+ infile = optarg;
+ break;
+
+ case 'i':
+ device = optarg;
+ break;
+
+ case 'l':
+ setlinebuf(stdout);
+ break;
+
+ case 'n':
+ ++nflag;
+ break;
+
+ case 'N':
+ ++Nflag;
+ break;
+
+ case 'O':
+ Oflag = 0;
+ break;
+
+ case 'p':
+ ++pflag;
+ break;
+
+ case 'q':
+ ++qflag;
+ break;
+
+ case 'r':
+ RFileName = optarg;
+ break;
+
+ case 's':
+ snaplen = atoi(optarg);
+ break;
+
+ case 'S':
+ ++Sflag;
+ break;
+
+ case 't':
+ --tflag;
+ break;
+
+ case 'v':
+ ++vflag;
+ break;
+
+ case 'w':
+ WFileName = optarg;
+ break;
+#ifdef YYDEBUG
+ case 'Y':
+ {
+ extern int yydebug;
+ yydebug = 1;
+ }
+ break;
+#endif
+ case 'x':
+ ++xflag;
+ break;
+
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+
+ if (tflag > 0) {
+ struct timeval now;
+ struct timezone tz;
+
+ if (gettimeofday(&now, &tz) < 0) {
+ perror("tcpdump: gettimeofday");
+ exit(1);
+ }
+ thiszone = tz.tz_minuteswest * -60;
+ if (localtime((time_t *)&now.tv_sec)->tm_isdst)
+ thiszone += 3600;
+ }
+
+ if (RFileName) {
+ /*
+ * We don't need network access, so set it back to the user id.
+ * Also, this prevents the user from reading anyone's
+ * trace file.
+ */
+ setuid(getuid());
+
+ err = sf_read_init(RFileName, &linktype, &thiszone, &snaplen,
+ &precision);
+ if (err)
+ sf_err(err);
+ localnet = 0;
+ netmask = 0;
+ if (fflag != 0)
+ error("-f and -r options are incompatible");
+ } else {
+ if (device == 0) {
+ device = lookup_device();
+ if (device == 0)
+ error("can't find any interfaces");
+ }
+ if_fd = initdevice(device, pflag, &linktype);
+ lookup_net(device, &localnet, &netmask);
+ /*
+ * Let user own process after socket has been opened.
+ */
+ setuid(getuid());
+ }
+
+ if (infile)
+ cmdbuf = read_infile(infile);
+ else
+ cmdbuf = copy_argv(&argv[optind]);
+
+ fcode = parse(cmdbuf, Oflag, linktype, netmask);
+ if (dflag) {
+ bpf_dump(fcode, dflag);
+ exit(0);
+ }
+ init_addrtoname(fflag, localnet, netmask);
+
+ (void)signal(SIGTERM, cleanup);
+ (void)signal(SIGINT, cleanup);
+ (void)signal(SIGHUP, cleanup);
+
+ printit = lookup_printer(linktype);
+
+ if (WFileName) {
+ sf_write_init(WFileName, linktype, thiszone, snaplen,
+ precision);
+ printit = sf_write;
+ }
+ if (RFileName) {
+ err = sf_read(fcode, cnt, snaplen, printit);
+ if (err)
+ sf_err(err);
+ } else {
+ fprintf(stderr, "%s: listening on %s\n", program_name, device);
+ fflush(stderr);
+ readloop(cnt, if_fd, fcode, printit);
+ }
+ exit(0);
+}
+
+/* make a clean exit on interrupts */
+static void
+cleanup()
+{
+ if (if_fd >= 0) {
+ putc('\n', stderr);
+ wrapup(if_fd);
+ }
+ exit(0);
+}
+
+void
+default_print(sp, length)
+ register u_short *sp;
+ register int length;
+{
+ register u_int i;
+ register int nshorts;
+
+ nshorts = (unsigned) length / sizeof(u_short);
+ i = 0;
+ while (--nshorts >= 0) {
+ if ((i++ % 8) == 0)
+ (void)printf("\n\t\t\t");
+ (void)printf(" %04x", ntohs(*sp++));
+ }
+ if (length & 1) {
+ if ((i % 8) == 0)
+ (void)printf("\n\t\t\t");
+ (void)printf(" %02x", *(u_char *)sp);
+ }
+}
+
+void
+usage()
+{
+ extern char version[];
+
+ (void)fprintf(stderr, "Version %s\n", version);
+ (void)fprintf(stderr,
+"Usage: tcpdump [-deflnOpqtvx] [-c count] [-i interface]\n");
+ (void)fprintf(stderr,
+"\t\t[-r filename] [-w filename] [expr]\n");
+ exit(-1);
+}
diff --git a/usr.sbin/tcpdump/tcpdump/tcpgram.y b/usr.sbin/tcpdump/tcpdump/tcpgram.y
new file mode 100644
index 000000000000..da235d0b1068
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/tcpgram.y
@@ -0,0 +1,232 @@
+%{
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Grammar for tcpdump.
+ */
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: tcpgram.y,v 1.29 92/03/17 13:45:08 mccanne Exp $ (LBL)";
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include "interface.h"
+
+#include <sys/time.h>
+#include <net/bpf.h>
+
+#include "gencode.h"
+
+#define QSET(q, p, d, a) (q).proto = (p),\
+ (q).dir = (d),\
+ (q).addr = (a)
+
+int n_errors = 0;
+
+static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
+
+static void
+yyerror()
+{
+ ++n_errors;
+}
+
+%}
+
+%union {
+ int i;
+ u_long h;
+ u_char *e;
+ char *s;
+ struct stmt *stmt;
+ struct arth *a;
+ struct {
+ struct qual q;
+ struct block *b;
+ } blk;
+ struct block *rblk;
+}
+
+%type <blk> expr id nid pid term rterm qid
+%type <blk> head
+%type <i> pqual dqual aqual ndaqual
+%type <a> arth narth
+%type <i> byteop pname pnum relop irelop
+%type <blk> and or paren not null prog
+%type <rblk> other
+
+%token DST SRC HOST GATEWAY
+%token NET PORT LESS GREATER PROTO BYTE
+%token ARP RARP IP TCP UDP ICMP
+%token TK_BROADCAST TK_MULTICAST
+%token NUM
+%token LINK
+%token GEQ LEQ NEQ
+%token ID EID HID
+%token LSH RSH
+%token LEN
+
+%type <s> ID
+%type <e> EID
+%type <h> HID
+%type <i> NUM
+
+%left OR AND
+%nonassoc '!'
+%left '|'
+%left '&'
+%left LSH RSH
+%left '+' '-'
+%left '*' '/'
+%nonassoc UMINUS
+%%
+prog: null expr
+{
+ finish_parse($2.b);
+}
+ | null
+ ;
+null: /* null */ { $$.q = qerr; }
+ ;
+expr: term
+ | expr and term { gen_and($1.b, $3.b); $$ = $3; }
+ | expr and id { gen_and($1.b, $3.b); $$ = $3; }
+ | expr or term { gen_or($1.b, $3.b); $$ = $3; }
+ | expr or id { gen_or($1.b, $3.b); $$ = $3; }
+ ;
+and: AND { $$ = $<blk>0; }
+ ;
+or: OR { $$ = $<blk>0; }
+ ;
+id: nid
+ | pnum { $$.b = gen_ncode((u_long)$1,
+ $$.q = $<blk>0.q); }
+ | paren pid ')' { $$ = $2; }
+ ;
+nid: ID { $$.b = gen_scode($1, $$.q = $<blk>0.q); }
+ | HID { $$.b = gen_ncode($1, $$.q = $<blk>0.q); }
+ | EID { $$.b = gen_ecode($1, $$.q = $<blk>0.q); }
+ | not id { gen_not($2.b); $$ = $2; }
+ ;
+not: '!' { $$ = $<blk>0; }
+ ;
+paren: '(' { $$ = $<blk>0; }
+ ;
+pid: nid
+ | qid and id { gen_and($1.b, $3.b); $$ = $3; }
+ | qid or id { gen_or($1.b, $3.b); $$ = $3; }
+ ;
+qid: pnum { $$.b = gen_ncode((u_long)$1,
+ $$.q = $<blk>0.q); }
+ | pid
+ ;
+term: rterm
+ | not term { gen_not($2.b); $$ = $2; }
+ ;
+head: pqual dqual aqual { QSET($$.q, $1, $2, $3); }
+ | pqual dqual { QSET($$.q, $1, $2, Q_DEFAULT); }
+ | pqual aqual { QSET($$.q, $1, Q_DEFAULT, $2); }
+ | pqual PROTO { QSET($$.q, $1, Q_DEFAULT, Q_PROTO); }
+ | pqual ndaqual { QSET($$.q, $1, Q_DEFAULT, $2); }
+ ;
+rterm: head id { $$ = $2; }
+ | paren expr ')' { $$.b = $2.b; $$.q = $1.q; }
+ | pname { $$.b = gen_proto_abbrev($1); $$.q = qerr; }
+ | arth relop arth { $$.b = gen_relation($2, $1, $3, 0);
+ $$.q = qerr; }
+ | arth irelop arth { $$.b = gen_relation($2, $1, $3, 1);
+ $$.q = qerr; }
+ | other { $$.b = $1; $$.q = qerr; }
+ ;
+/* protocol level qualifiers */
+pqual: pname
+ | { $$ = Q_DEFAULT; }
+ ;
+/* 'direction' qualifiers */
+dqual: SRC { $$ = Q_SRC; }
+ | DST { $$ = Q_DST; }
+ | SRC OR DST { $$ = Q_OR; }
+ | DST OR SRC { $$ = Q_OR; }
+ | SRC AND DST { $$ = Q_AND; }
+ | DST AND SRC { $$ = Q_AND; }
+ ;
+/* address type qualifiers */
+aqual: HOST { $$ = Q_HOST; }
+ | NET { $$ = Q_NET; }
+ | PORT { $$ = Q_PORT; }
+ ;
+/* non-directional address type qualifiers */
+ndaqual: GATEWAY { $$ = Q_GATEWAY; }
+ ;
+pname: LINK { $$ = Q_LINK; }
+ | IP { $$ = Q_IP; }
+ | ARP { $$ = Q_ARP; }
+ | RARP { $$ = Q_RARP; }
+ | TCP { $$ = Q_TCP; }
+ | UDP { $$ = Q_UDP; }
+ | ICMP { $$ = Q_ICMP; }
+ ;
+other: pqual TK_BROADCAST { $$ = gen_broadcast($1); }
+ | pqual TK_MULTICAST { $$ = gen_multicast($1); }
+ | LESS NUM { $$ = gen_less($2); }
+ | GREATER NUM { $$ = gen_greater($2); }
+ | BYTE NUM byteop NUM { $$ = gen_byteop($3, $2, $4); }
+ ;
+relop: '>' { $$ = BPF_JGT; }
+ | GEQ { $$ = BPF_JGE; }
+ | '=' { $$ = BPF_JEQ; }
+ ;
+irelop: LEQ { $$ = BPF_JGT; }
+ | '<' { $$ = BPF_JGE; }
+ | NEQ { $$ = BPF_JEQ; }
+ ;
+arth: pnum { $$ = gen_loadi($1); }
+ | narth
+ ;
+narth: pname '[' arth ']' { $$ = gen_load($1, $3, 1); }
+ | pname '[' arth ':' NUM ']' { $$ = gen_load($1, $3, $5); }
+ | arth '+' arth { $$ = gen_arth(BPF_ADD, $1, $3); }
+ | arth '-' arth { $$ = gen_arth(BPF_SUB, $1, $3); }
+ | arth '*' arth { $$ = gen_arth(BPF_MUL, $1, $3); }
+ | arth '/' arth { $$ = gen_arth(BPF_DIV, $1, $3); }
+ | arth '&' arth { $$ = gen_arth(BPF_AND, $1, $3); }
+ | arth '|' arth { $$ = gen_arth(BPF_OR, $1, $3); }
+ | arth LSH arth { $$ = gen_arth(BPF_LSH, $1, $3); }
+ | arth RSH arth { $$ = gen_arth(BPF_RSH, $1, $3); }
+ | '-' arth %prec UMINUS { $$ = gen_neg($2); }
+ | paren narth ')' { $$ = $2; }
+ | LEN { $$ = gen_loadlen(); }
+ ;
+byteop: '&' { $$ = '&'; }
+ | '|' { $$ = '|'; }
+ | '<' { $$ = '<'; }
+ | '>' { $$ = '>'; }
+ | '=' { $$ = '='; }
+ ;
+pnum: NUM
+ | paren pnum ')' { $$ = $2; }
+ ;
+%%
diff --git a/usr.sbin/tcpdump/tcpdump/tcplex.l b/usr.sbin/tcpdump/tcpdump/tcplex.l
new file mode 100644
index 000000000000..840590addcd3
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/tcplex.l
@@ -0,0 +1,146 @@
+%{
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: tcplex.l,v 1.26 92/02/14 15:16:35 mccanne Exp $ (LBL)";
+#endif
+
+/*
+ * Compiling with gcc under SunOS will cause problems unless we have this
+ * cruft here. The flex skeleton includes stddef.h which defines these types
+ * (under gcc). They will conflict with Sun's definitions in sys/types.h.
+ */
+#define size_t xxxsize_t
+#define ptrdiff_t xxxptrdiff_t
+#define wchar_t xxxwchar_t
+#include <sys/types.h>
+#undef size_t
+#undef ptrdiff_t
+#undef wchar_t
+
+#include "nametoaddr.h"
+
+/*
+ * We need bpf since enum bpf_code is in YYSTYPE.
+ */
+#include <sys/time.h>
+#include <net/bpf.h>
+
+#include "gencode.h"
+#include "y.tab.h" /* "tokdefs.h" */
+
+#ifdef FLEX_SCANNER
+#undef YY_INPUT
+#define YY_INPUT(buf, result, max)\
+ {\
+ char *src = in_buffer;\
+ int i;\
+\
+ if (*src == 0)\
+ result = YY_NULL;\
+ else {\
+ for (i = 0; *src && i < max; ++i)\
+ buf[i] = *src++;\
+ in_buffer += i;\
+ result = i;\
+ }\
+ }
+#else
+#undef getc
+#define getc(fp) (*in_buffer == 0 ? EOF : *in_buffer++)
+#endif
+
+extern YYSTYPE yylval;
+static char *in_buffer;
+
+%}
+
+N ([0-9]+|(0X|0x)[0-9A-Fa-f]+)
+B ([0-9A-Fa-f][0-9A-Fa-f]?)
+
+%a 3000
+
+%%
+dst return DST;
+src return SRC;
+
+link|ether|ppp|slip return LINK;
+arp return ARP;
+rarp return RARP;
+ip return IP;
+tcp return TCP;
+udp return UDP;
+icmp return ICMP;
+
+host return HOST;
+net return NET;
+port return PORT;
+proto return PROTO;
+
+gateway return GATEWAY;
+
+less return LESS;
+greater return GREATER;
+byte return BYTE;
+broadcast return TK_BROADCAST;
+multicast return TK_MULTICAST;
+
+and return AND;
+or return OR;
+not return '!';
+
+len return LEN;
+
+[ \n\t] ;
+[+\-*/:\[\]!<>()&|=] return yytext[0];
+">=" return GEQ;
+"<=" return LEQ;
+"!=" return NEQ;
+"==" return '=';
+"<<" return LSH;
+">>" return RSH;
+{N} { yylval.i = stoi(yytext); return NUM; }
+({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N}) {
+ yylval.h = atoin(yytext); return HID;
+}
+{B}:{B}:{B}:{B}:{B}:{B} { yylval.e = ETHER_aton(yytext); return EID; }
+{B}:+({B}:+)+ { error("bogus ethernet address %s", yytext); }
+[A-Za-z][-_.A-Za-z0-9]* { yylval.s = yytext; return ID; }
+"\\"[^ !()\n\t]+ { yylval.s = yytext + 1; return ID; }
+[^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+ { error("illegal token: %s\n", yytext); }
+. { error("illegal char '%c'", *yytext); }
+%%
+void
+lex_init(buf)
+ char *buf;
+{
+ in_buffer = buf;
+}
+#ifndef FLEX_SCANNER
+int
+yywrap()
+/* so we don't need -ll */
+{
+ return 1;
+}
+#endif
diff --git a/usr.sbin/tcpdump/tcpdump/util.c b/usr.sbin/tcpdump/tcpdump/util.c
new file mode 100644
index 000000000000..ec58c3f56cb1
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/util.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 1988-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#) $Header: util.c,v 1.12 91/10/28 22:09:31 mccanne Exp $ (LBL)";
+#endif
+
+#include <stdio.h>
+#ifdef __STDC__
+#include <stdlib.h>
+#endif
+#include <sys/types.h>
+#include <sys/time.h>
+#include <ctype.h>
+#include <varargs.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include "interface.h"
+
+/* Hex digit to integer. */
+static inline int
+xdtoi(c)
+{
+ if (isdigit(c))
+ return c - '0';
+ else if (islower(c))
+ return c - 'a' + 10;
+ else
+ return c - 'A' + 10;
+}
+
+/*
+ * Convert string to integer. Just like atoi(), but checks for
+ * preceding 0x or 0 and uses hex or octal instead of decimal.
+ */
+int
+stoi(s)
+ char *s;
+{
+ int base = 10;
+ int n = 0;
+
+ if (*s == '0') {
+ if (s[1] == 'x' || s[1] == 'X') {
+ s += 2;
+ base = 16;
+ }
+ else {
+ base = 8;
+ s += 1;
+ }
+ }
+ while (*s)
+ n = n * base + xdtoi(*s++);
+
+ return n;
+}
+
+/*
+ * Print out a filename (or other ascii string).
+ * Return true if truncated.
+ */
+int
+printfn(s, ep)
+ register u_char *s, *ep;
+{
+ register u_char c;
+
+ putchar('"');
+ while (c = *s++) {
+ if (s > ep) {
+ putchar('"');
+ return(1);
+ }
+ if (!isascii(c)) {
+ c = toascii(c);
+ putchar('M');
+ putchar('-');
+ }
+ if (!isprint(c)) {
+ c ^= 0x40; /* DEL to ?, others to alpha */
+ putchar('^');
+ }
+ putchar(c);
+ }
+ putchar('"');
+ return(0);
+}
+
+/*
+ * Print the timestamp
+ */
+void
+ts_print(tvp)
+ register struct timeval *tvp;
+{
+ register int i;
+
+ if (tflag > 0) {
+ /* Default */
+ i = (tvp->tv_sec + thiszone) % 86400;
+ (void)printf("%02d:%02d:%02d.%06d ",
+ i / 3600, (i % 3600) / 60, i % 60, tvp->tv_usec);
+ } else if (tflag < 0) {
+ /* Unix timeval style */
+ (void)printf("%d.%06d ", tvp->tv_sec, tvp->tv_usec);
+ }
+}
+
+#ifdef NOVFPRINTF
+/*
+ * Stock 4.3 doesn't have vfprintf.
+ * This routine is due to Chris Torek.
+ */
+vfprintf(f, fmt, args)
+ FILE *f;
+ char *fmt;
+ va_list args;
+{
+ int ret;
+
+ if ((f->_flag & _IOWRT) == 0) {
+ if (f->_flag & _IORW)
+ f->_flag |= _IOWRT;
+ else
+ return EOF;
+ }
+ ret = _doprnt(fmt, args, f);
+ return ferror(f) ? EOF : ret;
+}
+#endif
+
+static char *
+stripdir(s)
+ register char *s;
+{
+ register char *cp;
+ char *rindex();
+
+ cp = rindex(s, '/');
+ return (cp != 0) ? cp + 1 : s;
+}
+
+/* VARARGS */
+void
+error(va_alist)
+ va_dcl
+{
+ register char *cp;
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: ", stripdir(program_name));
+
+ va_start(ap);
+ cp = va_arg(ap, char *);
+ (void)vfprintf(stderr, cp, ap);
+ va_end(ap);
+ if (*cp) {
+ cp += strlen(cp);
+ if (cp[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+ exit(1);
+ /* NOTREACHED */
+}
+
+/* VARARGS */
+void
+warning(va_alist)
+ va_dcl
+{
+ register char *cp;
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: warning: ", stripdir(program_name));
+
+ va_start(ap);
+ cp = va_arg(ap, char *);
+ (void)vfprintf(stderr, cp, ap);
+ va_end(ap);
+ if (*cp) {
+ cp += strlen(cp);
+ if (cp[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+}
+
+
+/*
+ * Copy arg vector into a new buffer, concatenating arguments with spaces.
+ */
+char *
+copy_argv(argv)
+ register char **argv;
+{
+ register char **p;
+ register int len = 0;
+ char *buf;
+ char *src, *dst;
+
+ p = argv;
+ if (*p == 0)
+ return 0;
+
+ while (*p)
+ len += strlen(*p++) + 1;
+
+ buf = malloc(len);
+
+ p = argv;
+ dst = buf;
+ while (src = *p++) {
+ while (*dst++ = *src++)
+ ;
+ dst[-1] = ' ';
+ }
+ dst[-1] = '\0';
+
+ return buf;
+}
+
+char *
+read_infile(fname)
+ char *fname;
+{
+ struct stat buf;
+ int fd;
+ char *p;
+
+ fd = open(fname, O_RDONLY);
+ if (fd < 0)
+ error("can't open '%s'", fname);
+
+ if (fstat(fd, &buf) < 0)
+ error("can't state '%s'", fname);
+
+ p = malloc((unsigned)buf.st_size);
+ if (read(fd, p, (int)buf.st_size) != buf.st_size)
+ error("problem reading '%s'", fname);
+
+ return p;
+}
+
+/*
+ * Left justify 'addr' and return its resulting network mask.
+ */
+u_long
+net_mask(addr)
+ u_long *addr;
+{
+ register u_long m = 0xffffffff;
+
+ if (*addr)
+ while ((*addr & 0xff000000) == 0)
+ *addr <<= 8, m <<= 8;
+
+ return m;
+}
diff --git a/usr.sbin/tcpdump/tcpslice/Makefile b/usr.sbin/tcpdump/tcpslice/Makefile
new file mode 100644
index 000000000000..d1cd63b19ff4
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpslice/Makefile
@@ -0,0 +1,18 @@
+# @(#)Makefile 0.1 (RWGrimes) 3/24/93
+
+PROG= tcpslice
+CFLAGS+=-DCSLIP -I. -I$(.CURDIR)/../tcpdump
+MAN1= tcpslice.0
+SRCS= version.c tcpslice.c gwtm2secs.c search.c \
+ savefile.c bpf_filter.c md.c util.c
+.PATH: ${.CURDIR}/../tcpdump /sys/net
+CLEANFILES+= version.c version.h
+
+version.c version.h: $(.CURDIR)/../tcpdump/VERSION
+ rm -f version.c ; \
+ sed 's/.*/char version[] = "&";/' $(.CURDIR)/../tcpdump/VERSION > version.c
+ set `sed 's/\([0-9]*\)\.\([0-9]*\).*/\1 \2/' $(.CURDIR)/../tcpdump/VERSION` ; \
+ { echo '#define VERSION_MAJOR' $$1 ; \
+ echo '#define VERSION_MINOR' $$2 ; } > version.h
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/tcpdump/tcpslice/gwtm2secs.c b/usr.sbin/tcpdump/tcpslice/gwtm2secs.c
new file mode 100644
index 000000000000..aeb377fd932d
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpslice/gwtm2secs.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static char rcsid[] =
+ "@(#)$Header: gwtm2secs.c,v 1.1 92/06/02 11:35:19 mccanne Exp $ (LBL)";
+#endif
+
+/*
+ * gwtm2secs.c - convert "tm" structs for Greenwich time to Unix timestamp
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <time.h>
+
+static int days_in_month[] =
+ /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+#define IS_LEAP_YEAR(year) \
+ (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
+
+time_t gwtm2secs( tm )
+struct tm *tm;
+ {
+ int i, days, year;
+
+ year = tm->tm_year;
+
+ /* Allow for year being specified with either 2 digits or 4 digits.
+ * 2-digit years are either 19xx or 20xx - a simple heuristic
+ * distinguishes them, since we can't represent any time < 1970.
+ */
+ if ( year < 100 )
+ if ( year >= 70 )
+ year += 1900;
+ else
+ year += 2000;
+
+ days = 0;
+ for ( i = 1970; i < year; ++i )
+ {
+ days += 365;
+ if ( IS_LEAP_YEAR(i) )
+ ++days;
+ }
+
+ for ( i = 0; i < tm->tm_mon; ++i )
+ days += days_in_month[i];
+
+ if ( IS_LEAP_YEAR(year) && tm->tm_mon > 1 ) /* 1 is February */
+ ++days;
+
+ days += tm->tm_mday - 1; /* -1 since days are numbered starting at 1 */
+
+ return days * 86400 + tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec;
+ }
diff --git a/usr.sbin/tcpdump/tcpslice/search.c b/usr.sbin/tcpdump/tcpslice/search.c
new file mode 100644
index 000000000000..8bea0d2fabf1
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpslice/search.c
@@ -0,0 +1,563 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static char rcsid[] =
+ "@(#)$Header: search.c,v 1.3 92/05/01 15:14:45 vern Exp $ (LBL)";
+#endif
+
+/*
+ * search.c - supports fast searching through tcpdump files for timestamps
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include "interface.h"
+#include "savefile.h"
+
+
+/* Maximum number of seconds that we can conceive of a dump file spanning. */
+#define MAX_REASONABLE_FILE_SPAN (3600*24*366) /* one year */
+
+/* Maximum packet length we ever expect to see. */
+#define MAX_REASONABLE_PACKET_LENGTH 65535
+
+/* Size of a packet header in bytes; easier than typing the sizeof() all
+ * the time ...
+ */
+#define PACKET_HDR_LEN (sizeof( struct packet_header ))
+
+/* The maximum size of a packet, including its header. */
+#define MAX_PACKET_SIZE (PACKET_HDR_LEN + snaplen)
+
+/* Number of contiguous bytes from a dumpfile in which there's guaranteed
+ * to be enough information to find a "definite" header if one exists
+ * therein. This takes 3 full packets - the first to be just misaligned
+ * (one byte short of a full packet), missing its timestamp; the second
+ * to have the legitimate timestamp; and the third to provide confirmation
+ * that the second is legit, making it a "definite" header. We could
+ * scrimp a bit here since not the entire third packet is required, but
+ * it doesn't seem worth it
+ */
+#define MAX_BYTES_FOR_DEFINITE_HEADER (3 * MAX_PACKET_SIZE)
+
+/* Maximum number of seconds that might reasonably separate two headers. */
+#define MAX_REASONABLE_HDR_SEPARATION (3600 * 24 * 7) /* one week */
+
+/* When searching a file for a packet, if we think we're within this many
+ * bytes of the packet we just search linearly. Since linear searches are
+ * probably much faster than random ones (random ones require searching for
+ * the beginning of the packet, which may be unaligned in memory), we make
+ * this value pretty hefty.
+ */
+#define STRAIGHT_SCAN_THRESHOLD (100 * MAX_PACKET_SIZE)
+
+/* Extracts a long integer from a possibly unaligned buffer containing
+ * unsigned characters.
+ */
+#define EXTRACT_LONG(buf) (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3])
+
+
+/* Given a header and an acceptable first and last time stamp, returns non-zero
+ * if the header looks reasonable and zero otherwise.
+ */
+static int reasonable_header( hdr, first_time, last_time )
+struct packet_header *hdr;
+long first_time, last_time;
+ {
+ if ( last_time == 0 )
+ last_time = first_time + MAX_REASONABLE_FILE_SPAN;
+
+ return hdr->ts.tv_sec >= first_time &&
+ hdr->ts.tv_sec <= last_time &&
+ hdr->len > 0 &&
+ hdr->len <= MAX_REASONABLE_PACKET_LENGTH &&
+ hdr->caplen > 0 &&
+ hdr->caplen <= MAX_REASONABLE_PACKET_LENGTH;
+ }
+
+
+/* Given a buffer, extracts a (properly aligned) packet header from it. */
+
+static void extract_header( buf, hdr )
+u_char *buf;
+struct packet_header *hdr;
+ {
+ hdr->ts.tv_sec = EXTRACT_LONG(buf);
+ buf += sizeof( long );
+ hdr->ts.tv_usec = EXTRACT_LONG(buf);
+ buf += sizeof( long );
+ hdr->len = EXTRACT_LONG(buf);
+ buf += sizeof( long );
+ hdr->caplen = EXTRACT_LONG(buf);
+
+ if ( sf_swapped )
+ {
+ hdr->ts.tv_sec = SWAPLONG(hdr->ts.tv_sec);
+ hdr->ts.tv_usec = SWAPLONG(hdr->ts.tv_usec);
+ hdr->len = SWAPLONG(hdr->len);
+ hdr->caplen = SWAPLONG(hdr->caplen);
+ }
+ }
+
+
+/* Search a buffer to locate the first header within it. Return values
+ * are HEADER_NONE, HEADER_CLASH, HEADER_PERHAPS, and HEADER_DEFINITELY.
+ * The first indicates that no evidence of a header was found; the second
+ * that two or more possible headers were found, neither more convincing
+ * than the other(s); the third that exactly one "possible" header was
+ * found; and the fourth that exactly one "definite" header was found.
+ *
+ * Headers are detected by looking for positions in the buffer which have
+ * reasonable timestamps and lengths. If there is enough room in the buffer
+ * for another header to follow a candidate header, a check is made for
+ * that following header. If it is present then the header is *definite*
+ * (unless another "perhaps" or "definite" header is found); if not, then
+ * the header is discarded. If there is not enough room in the buffer for
+ * another header then the candidate is *perhaps* (unless another header
+ * is subsequently found). A "tie" between a "definite" header and a
+ * "perhaps" header is resolved in favor of the definite header. Any
+ * other tie leads to HEADER_CLASH.
+ *
+ * The buffer position of the header is returned in hdrpos_addr and
+ * for convenience the corresponding header in return_hdr.
+ *
+ * first_time is the earliest possible acceptable timestamp in the
+ * header. last_time, if non-zero, is the last such timestamp. If
+ * zero, then up to MAX_REASONABLE_FILE_SPAN seconds after first_time
+ * is acceptable.
+ */
+
+#define HEADER_NONE 0
+#define HEADER_CLASH 1
+#define HEADER_PERHAPS 2
+#define HEADER_DEFINITELY 3
+
+static int find_header( buf, buf_len, first_time, last_time,
+ hdrpos_addr, return_hdr )
+u_char *buf;
+unsigned buf_len;
+long first_time, last_time;
+u_char **hdrpos_addr;
+struct packet_header *return_hdr;
+ {
+ u_char *bufptr, *bufend, *last_pos_to_try;
+ struct packet_header hdr, hdr2;
+ int status = HEADER_NONE;
+ int saw_PERHAPS_clash = 0;
+
+ /* Initially, try each buffer position to see whether it looks like
+ * a valid packet header. We may later restrict the positions we look
+ * at to avoid seeing a sequence of legitimate headers as conflicting
+ * with one another.
+ */
+ bufend = buf + buf_len;
+ last_pos_to_try = bufend - PACKET_HDR_LEN;
+
+ for ( bufptr = buf; bufptr < last_pos_to_try; ++bufptr )
+ {
+ extract_header( bufptr, &hdr );
+
+ if ( reasonable_header( &hdr, first_time, last_time ) )
+ {
+ u_char *next_header = bufptr + PACKET_HDR_LEN + hdr.caplen;
+
+ if ( next_header + PACKET_HDR_LEN < bufend )
+ { /* check for another good header */
+ extract_header( next_header, &hdr2 );
+
+ if ( reasonable_header( &hdr2, hdr.ts.tv_sec,
+ hdr.ts.tv_sec + MAX_REASONABLE_HDR_SEPARATION ) )
+ { /* a confirmed header */
+ switch ( status )
+ {
+ case HEADER_NONE:
+ case HEADER_PERHAPS:
+ status = HEADER_DEFINITELY;
+ *hdrpos_addr = bufptr;
+ *return_hdr = hdr;
+
+ /* Make sure we don't demote this "definite"
+ * to a "clash" if we stumble across its
+ * successor.
+ */
+ last_pos_to_try = next_header - PACKET_HDR_LEN;
+ break;
+
+ case HEADER_DEFINITELY:
+ return HEADER_CLASH;
+
+ default:
+ error( "bad status in find_header()" );
+ }
+ }
+
+ /* ... else the header is bogus - we've verified that it's
+ * not followed by a reasonable header.
+ */
+ }
+
+ else
+ { /* can't check for another good header */
+ switch ( status )
+ {
+ case HEADER_NONE:
+ status = HEADER_PERHAPS;
+ *hdrpos_addr = bufptr;
+ *return_hdr = hdr;
+ break;
+
+ case HEADER_PERHAPS:
+ /* We don't immediately turn this into a
+ * clash because perhaps we'll later see a
+ * "definite" which will save us ...
+ */
+ saw_PERHAPS_clash = 1;
+ break;
+
+ case HEADER_DEFINITELY:
+ /* Keep the definite in preference to this one. */
+ break;
+
+ default:
+ error( "bad status in find_header()" );
+ }
+ }
+ }
+ }
+
+ if ( status == HEADER_PERHAPS && saw_PERHAPS_clash )
+ status = HEADER_CLASH;
+
+ return status;
+ }
+
+
+/* Positions the sf_readfile stream such that the next sf_read() will
+ * read the final full packet in the file. Returns non-zero if
+ * successful, zero if unsuccessful. If successful, returns the
+ * timestamp of the last packet in last_timestamp.
+ *
+ * Note that this routine is a special case of sf_find_packet(). In
+ * order to use sf_find_packet(), one first must use this routine in
+ * order to give sf_find_packet() an upper bound on the timestamps
+ * present in the dump file.
+ */
+int sf_find_end( first_timestamp, last_timestamp )
+struct timeval *first_timestamp;
+struct timeval *last_timestamp;
+ {
+ long first_time = first_timestamp->tv_sec;
+ unsigned num_bytes;
+ u_char *buf, *bufpos, *bufend;
+ u_char *hdrpos;
+ struct packet_header hdr, successor_hdr;
+ int status;
+
+ /* Allow enough room for at least two full (untruncated) packets,
+ * perhaps followed by a truncated packet, so we have a shot at
+ * finding a "definite" header and following its chain to the
+ * end of the file.
+ */
+ num_bytes = MAX_BYTES_FOR_DEFINITE_HEADER;
+ if ( fseek( sf_readfile, (long) -num_bytes, 2 ) < 0 )
+ return 0;
+
+ buf = (u_char *)malloc((unsigned) num_bytes);
+ if ( ! buf )
+ return 0;
+
+ status = 0;
+ bufpos = buf;
+ bufend = buf + num_bytes;
+
+ if ( fread( (char *) bufpos, num_bytes, 1, sf_readfile ) != 1 )
+ goto done;
+
+ if ( find_header( bufpos, num_bytes, first_time, 0L, &hdrpos, &hdr ) !=
+ HEADER_DEFINITELY )
+ goto done;
+
+ /* Okay, we have a definite header in our hands. Follow its
+ * chain till we find the last valid packet in the file ...
+ */
+ for ( ; ; )
+ {
+ /* move to the next header position */
+ bufpos = hdrpos + PACKET_HDR_LEN + hdr.caplen;
+
+ /* bufpos now points to a candidate packet, which if valid
+ * should replace the current packet pointed to by hdrpos as
+ * the last valid packet ...
+ */
+ if ( bufpos >= bufend - PACKET_HDR_LEN )
+ /* not enough room for another header */
+ break;
+
+ extract_header( bufpos, &successor_hdr );
+
+ first_time = hdr.ts.tv_sec;
+ if ( ! reasonable_header( &successor_hdr, first_time, 0L ) )
+ /* this bodes ill - it means bufpos is perhaps a
+ * bogus packet header after all ...
+ */
+ break;
+
+ /* Note that the following test is for whether the next
+ * packet starts at a position > bufend, *not* for a
+ * position >= bufend. If this is the last packet in the
+ * file and there isn't a subsequent partial packet, then
+ * we expect the first buffer position beyond this packet
+ * to be just beyond the end of the buffer, i.e., at bufend
+ * itself.
+ */
+ if ( bufpos + PACKET_HDR_LEN + successor_hdr.caplen > bufend )
+ /* the packet is truncated */
+ break;
+
+ /* Accept this packet as fully legit. */
+ hdrpos = bufpos;
+ hdr = successor_hdr;
+ }
+
+ /* Success! Last valid packet is at hdrpos. */
+ *last_timestamp = hdr.ts;
+ status = 1;
+
+ /* Seek so that the next read will start at last valid packet. */
+ if ( fseek( sf_readfile, (long) -(bufend - hdrpos), 2 ) < 0 )
+ error( "final fseek() failed in sf_find_end()" );
+
+ done:
+ free( (char *) buf );
+
+ return status;
+ }
+
+
+/* Takes two timeval's and returns the difference, tv2 - tv1, as a double. */
+
+static double timeval_diff( tv1, tv2 )
+struct timeval *tv1, *tv2;
+ {
+ double result = (tv2->tv_sec - tv1->tv_sec);
+ result += (tv2->tv_usec - tv1->tv_usec) / 1000000.0;
+
+ return result;
+ }
+
+
+/* Returns true if timestamp t1 is chronologically less than timestamp t2. */
+
+int sf_timestamp_less_than( t1, t2 )
+struct timeval *t1, *t2;
+ {
+ return t1->tv_sec < t2->tv_sec ||
+ (t1->tv_sec == t2->tv_sec &&
+ t1->tv_usec < t2->tv_usec);
+ }
+
+
+/* Given two timestamps on either side of desired_time and their positions,
+ * returns the interpolated position of the desired_time packet. Returns a
+ * negative value if the desired_time is outside the given range.
+ */
+
+static
+long interpolated_position( min_time, min_pos, max_time, max_pos, desired_time )
+struct timeval *min_time, *max_time, *desired_time;
+long min_pos, max_pos;
+ {
+ double full_span = timeval_diff( max_time, min_time );
+ double desired_span = timeval_diff( desired_time, min_time );
+ long full_span_pos = max_pos - min_pos;
+ double fractional_offset = desired_span / full_span;
+
+ if ( fractional_offset < 0.0 || fractional_offset > 1.0 )
+ return -1;
+
+ return min_pos + (long) (fractional_offset * (double) full_span_pos);
+ }
+
+
+/* Reads packets linearly until one with a time >= the given desired time
+ * is found; positions the dump file so that the next read will start
+ * at the given packet. Returns non-zero on success, 0 if an EOF was
+ * first encountered.
+ */
+
+static int read_up_to( desired_time )
+struct timeval *desired_time;
+ {
+ int status = 1;
+ struct packet_header hdr;
+ u_char *buf;
+ long pos;
+
+ buf = (u_char *) malloc( (unsigned) snaplen );
+
+ for ( ; ; )
+ {
+ struct timeval *timestamp;
+
+ pos = ftell( sf_readfile );
+ status = sf_next_packet( &hdr, buf, snaplen );
+
+ if ( status )
+ {
+ if ( status == SFERR_EOF )
+ {
+ status = 0;
+ break;
+ }
+
+ error( "bad status %d in read_up_to()", status );
+ }
+
+ timestamp = &hdr.ts;
+
+ if ( ! sf_timestamp_less_than( timestamp, desired_time ) )
+ break;
+ }
+
+ if ( fseek( sf_readfile, pos, 0 ) < 0 )
+ error( "fseek() failed in read_up_to()" );
+
+ free( (char *) buf );
+
+ return status;
+ }
+
+
+/* Positions the sf_readfile stream so that the next sf_read() will
+ * return the first packet with a time greater than or equal to
+ * desired_time. desired_time must be greater than min_time and less
+ * than max_time, which should correspond to actual packets in the
+ * file. min_pos is the file position (byte offset) corresponding to
+ * the min_time packet and max_pos is the same for the max_time packet.
+ *
+ * Returns non-zero on success, 0 if the given position is beyond max_pos.
+ *
+ * NOTE: when calling this routine, the sf_readfile stream *must* be
+ * already aligned so that the next call to sf_next_packet() will yield
+ * a valid packet.
+ */
+
+int sf_find_packet( min_time, min_pos, max_time, max_pos, desired_time )
+struct timeval *min_time, *max_time;
+long min_pos, max_pos;
+struct timeval *desired_time;
+ {
+ int status = 1;
+ struct timeval min_time_copy, max_time_copy;
+ unsigned num_bytes = MAX_BYTES_FOR_DEFINITE_HEADER;
+ int num_bytes_read;
+ long desired_pos, present_pos;
+ u_char *buf, *hdrpos;
+ struct packet_header hdr;
+
+ buf = (u_char *) malloc( num_bytes );
+ if ( ! buf )
+ error( "malloc() failured in sf_find_packet()" );
+
+ min_time_copy = *min_time;
+ min_time = &min_time_copy;
+
+ max_time_copy = *max_time;
+ max_time = &max_time_copy;
+
+ for ( ; ; ) /* loop until positioned correctly */
+ {
+ desired_pos =
+ interpolated_position( min_time, min_pos,
+ max_time, max_pos,
+ desired_time );
+
+ if ( desired_pos < 0 )
+ {
+ status = 0;
+ break;
+ }
+
+ present_pos = ftell( sf_readfile );
+
+ if ( present_pos <= desired_pos &&
+ desired_pos - present_pos < STRAIGHT_SCAN_THRESHOLD )
+ { /* we're close enough to just blindly read ahead */
+ status = read_up_to( desired_time );
+ break;
+ }
+
+ /* Undershoot the target a little bit - it's much easier to
+ * then scan straight forward than to try to read backwards ...
+ */
+ desired_pos -= STRAIGHT_SCAN_THRESHOLD / 2;
+ if ( desired_pos < min_pos )
+ desired_pos = min_pos;
+
+ if ( fseek( sf_readfile, desired_pos, 0 ) < 0 )
+ error( "fseek() failed in sf_find_packet()" );
+
+ num_bytes_read =
+ fread( (char *) buf, 1, num_bytes, sf_readfile );
+
+ if ( num_bytes_read == 0 )
+ /* This shouldn't ever happen because we try to
+ * undershoot, unless the dump file has only a
+ * couple packets in it ...
+ */
+ error( "fread() failed in sf_find_packet()" );
+
+ if ( find_header( buf, num_bytes, min_time->tv_sec,
+ max_time->tv_sec, &hdrpos, &hdr ) !=
+ HEADER_DEFINITELY )
+ error( "can't find header at position %ld in dump file",
+ desired_pos );
+
+ /* Correct desired_pos to reflect beginning of packet. */
+ desired_pos += (hdrpos - buf);
+
+ /* Seek to the beginning of the header. */
+ if ( fseek( sf_readfile, desired_pos, 0 ) < 0 )
+ error( "fseek() failed in sf_find_packet()" );
+
+ if ( sf_timestamp_less_than( &hdr.ts, desired_time ) )
+ { /* too early in the file */
+ *min_time = hdr.ts;
+ min_pos = desired_pos;
+ }
+
+ else if ( sf_timestamp_less_than( desired_time, &hdr.ts ) )
+ { /* too late in the file */
+ *max_time = hdr.ts;
+ max_pos = desired_pos;
+ }
+
+ else
+ /* got it! */
+ break;
+ }
+
+ free( (char *) buf );
+
+ return status;
+ }
diff --git a/usr.sbin/tcpdump/tcpslice/tcpslice.1 b/usr.sbin/tcpdump/tcpslice/tcpslice.1
new file mode 100644
index 000000000000..b130f2c22a7e
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpslice/tcpslice.1
@@ -0,0 +1,260 @@
+.\" @(#) $Header: tcpslice.1,v 1.2 91/10/16 11:42:46 vern Exp $ (LBL)
+.\"
+.\" Copyright (c) 1988-1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH TCPSLICE 1 "14 Oct 1991"
+.SH NAME
+tcpslice \- extract pieces of and/or glue together tcpdump files
+.SH SYNOPSIS
+.na
+.B tcpslice
+[
+.B \-dRrt
+] [
+.B \-w
+.I file
+]
+.br
+.ti +9
+[
+.I start-time
+[
+.I end-time
+] ]
+.I file ...
+.br
+.ad
+.SH DESCRIPTION
+.LP
+.I Tcpslice
+is a program for extracting portions of packet-trace files generated using
+\fItcpdump(l)\fP's
+.B \-w
+flag.
+It can also be used to glue together several such files, as discussed
+below.
+.LP
+The basic operation of
+.I tcpslice
+is to copy to
+.I stdout
+all packets from its input file(s) whose timestamps fall
+within a given range. The starting and ending times of the range
+may be specified on the command line. All ranges are inclusive.
+The starting time defaults
+to the time of the first packet in the first input file; we call
+this the
+.I first time.
+The ending time defaults to ten years after the starting time.
+Thus, the command
+.I tcpslice trace-file
+simply copies
+.I trace-file
+to \fIstdout\fP (assuming the file does not include more than
+ten years' worth of data).
+.LP
+There are a number of ways to specify times. The first is using
+Unix timestamps of the form
+.I sssssssss.uuuuuu
+(this is the format specified by \fItcpdump\fP's
+.B \-tt
+flag).
+For example,
+.B 654321098.7654
+specifies 38 seconds and 765,400 microseconds
+after 8:51PM PDT, Sept. 25, 1990.
+.LP
+All examples in this manual are given
+for PDT times, but when displaying times and interpreting times symbolically
+as discussed below,
+.I tcpslice
+uses the local timezone, regardless of the timezone in which the \fItcpdump\fP
+file was generated. The daylight-savings setting used is that which is
+appropriate for the local timezone at the date in question. For example,
+times associated with summer months will usually include daylight-savings
+effects, and those with winter months will not.
+.LP
+Times may also be specified relative
+to either the
+.I first time
+(when specifying a starting time)
+or the starting time (when specifying an ending time)
+by preceding a numeric value in seconds with a `+'.
+For example, a starting time of
+.B +200
+indicates 200 seconds after the
+.I first time,
+and the two arguments
+.B +200 +300
+indicate from 200 seconds after the
+.I first time
+through 500 seconds after the
+.I first time.
+.LP
+Times may also be specified in terms of years (y), months (m), days (d),
+hours (h), minutes (m), seconds (s), and microseconds(u). For example,
+the Unix timestamp 654321098.7654 discussed above could also be expressed
+as
+.B 90y9m25d20h51m38s765400u.
+.LP
+When specifying times using this style, fields that are omitted default
+as follows. If the omitted field is a unit
+.I greater
+than that of the first specified field, then its value defaults to
+the corresponding value taken from either
+.I first time
+(if the starting time is being specified) or the starting time
+(if the ending time is being specified).
+If the omitted field is a unit
+.I less
+than that of the first specified field, then it defaults to zero.
+For example, suppose that the input file has a
+.I first time
+of the Unix timestamp mentioned above, i.e., 38 seconds and 765,400 microseconds
+after 8:51PM PDT, Sept. 25, 1990. To specify 9:36PM PDT (exactly) on the
+same date we could use
+.B 21h36m.
+To specify a range from 9:36PM PDT through 1:54AM PDT the next day we
+could use
+.B 21h36m 26d1h54m.
+.LP
+Relative times can also be specified when using the
+.I ymdhmsu
+format. Omitted fields then default to 0 if the unit of the field is
+.I greater
+than that of the first specified field, and to the corresponding value
+taken from either the
+.I first time
+or the starting time if the omitted field's unit is
+.I less
+than that of the first specified field. Given a
+.I first time
+of the Unix timestamp mentioned above,
+.B 22h +1h10m
+specifies a range from 10:00PM PDT on that date through 11:10PM PDT, and
+.B +1h +1h10m
+specifies a range from 38.7654 seconds after 9:51PM PDT through 38.7654
+seconds after 11:01PM PDT. The first hour of the file could be extracted
+using
+.B +0 +1h.
+.LP
+Note that with the
+.I ymdhmsu
+format there is an ambiguity between using
+.I m
+for `month' or for `minute'. The ambiguity is resolved as follows: if an
+.I m
+field is followed by a
+.I d
+field then it is interpreted as specifying months; otherwise it
+specifies minutes.
+.LP
+If more than one input file is specified then
+.I tcpslice
+first copies packets lying in the given range from the first file; it
+then increases the starting time of the range to lie just beyond the
+timestamp of the last packet in the first file, repeats the process
+with the second file, and so on. Thus files with interleaved packets
+are
+.I not
+merged. For a given file, only packets that are newer than any in the
+preceding files will be considered. This mechanism avoids any possibility
+of a packet occurring more than once in the output.
+.SH OPTIONS
+.LP
+If any of
+.B \-R,
+.B \-r
+or
+.B \-t
+are specified then
+.I tcpslice
+reports the timestamps of the first and last packets in each input file
+and exits. Only one of these three options may be specified.
+.TP
+.B \-d
+Dump the start and end times specified by the given range and
+exit. This option is useful for checking that the given range actually
+specifies the times you think it does. If one of
+.B \-R,
+.B \-r
+or
+.B \-t
+has been specified then the times are dumped in the corresponding
+format; otherwise, raw format (\fB \-R\fP) is used.
+.TP
+.B \-R
+Dump the timestamps of the first and last packets in each input file
+as raw timestamps (i.e., in the form \fI sssssssss.uuuuuu\fP).
+.TP
+.B \-r
+Same as
+.B \-R
+except the timestamps are dumped in human-readable format, similar
+to that used by \fI date(1)\fP.
+.TP
+.B \-t
+Same as
+.B \-R
+except the timestamps are dumped in
+.I tcpslice
+format, i.e., in the
+.I ymdhmsu
+format discussed above.
+.TP
+.B \-w
+Direct the output to \fIfile\fR rather than \fIstdout\fP.
+.SH "SEE ALSO"
+tcpdump(l)
+.SH AUTHOR
+Vern Paxson (vern@ee.lbl.gov), of
+Lawrence Berkeley Laboratory, University of California, Berkeley, CA.
+.SH BUGS
+An input filename that beings with a digit or a `+' can be confused
+with a start/end time. Such filenames can be specified with a
+leading `./'; for example, specify the file `04Jul76.trace' as
+`./04Jul76.trace'.
+.LP
+.I tcpslice
+cannot read its input from \fIstdin\fP, since it uses random-access
+to rummage through its input files.
+.LP
+.I tcpslice
+refuses to write to its output if it is a terminal
+(as indicated by \fIisatty(3)\fP). This is not a bug but a feature,
+to prevent it from spraying binary data to the user's terminal.
+Note that this means you must either redirect \fIstdout\fP or specify an
+output file via \fB\-w\fP.
+.LP
+.I tcpslice
+will not work properly on \fItcpdump\fP files spanning more than one year;
+with files containing portions of packets whose original length was
+more than 65,535 bytes; nor with files containing fewer than three packets.
+Such files result in
+the error message: `couldn't find final packet in file'. These problems
+are due to the interpolation scheme used by
+.I tcpslice
+to greatly speed up its processing when dealing with large trace files.
+Note that
+.I tcpslice
+can efficiently extract slices from the middle of trace files of any
+size, and can also work with truncated trace files (i.e., the final packet
+in the file is only partially present, typically due to \fItcpdump\fP
+being ungracefully killed).
diff --git a/usr.sbin/tcpdump/tcpslice/tcpslice.c b/usr.sbin/tcpdump/tcpslice/tcpslice.c
new file mode 100644
index 000000000000..b5b6eeafb527
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpslice/tcpslice.c
@@ -0,0 +1,645 @@
+/*
+ * Copyright (c) 1987-1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+char copyright[] =
+ "@(#) Copyright (c) 1987-1990 The Regents of the University of California.\nAll rights reserved.\n";
+static char rcsid[] =
+ "@(#)$Header: tcpslice.c,v 1.10 92/06/02 17:57:44 mccanne Exp $ (LBL)";
+#endif
+
+/*
+ * tcpslice - extract pieces of and/or glue together tcpdump files
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <netinet/in.h>
+#include <varargs.h>
+
+#include "savefile.h"
+#include "version.h"
+
+
+int tflag = 0; /* global that util routines are sensitive to */
+
+char *program_name;
+
+long thiszone; /* gmt to local correction in trace file */
+
+/* Length of saved portion of packet. */
+int snaplen;
+
+/* Length of saved portion of data past link level protocol. */
+int snapdlen;
+
+/* Precision of clock used to generate trace file. */
+int precision;
+
+static int linkinfo;
+
+/* Style in which to print timestamps; RAW is "secs.usecs"; READABLE is
+ * ala the Unix "date" tool; and PARSEABLE is tcpslice's custom format,
+ * designed to be easy to parse. The default is RAW.
+ */
+enum stamp_styles { TIMESTAMP_RAW, TIMESTAMP_READABLE, TIMESTAMP_PARSEABLE };
+enum stamp_styles timestamp_style = TIMESTAMP_RAW;
+
+
+time_t gwtm2secs( /* struct tm *tmp */ );
+
+
+long local_time_zone( /* timestamp */ );
+struct timeval parse_time(/* time_string, base_time*/);
+void fill_tm(/* time_string, is_delta, t, usecs_addr */);
+void get_file_range( /* filename, first_time, last_time */ );
+struct timeval first_packet_time(/* filename */);
+void extract_slice(/* filename, start_time, stop_time */);
+char *timestamp_to_string( /* timestamp */ );
+void dump_times(/* filename */);
+void usage();
+
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int op;
+ int dump_flag = 0;
+ int report_times = 0;
+ char *start_time_string = 0;
+ char *stop_time_string = 0;
+ char *write_file_name = "-"; /* default is stdout */
+ struct timeval first_time, start_time, stop_time;
+
+ extern char *optarg;
+ extern int optind, opterr;
+
+ program_name = argv[0];
+
+ opterr = 0;
+ while ((op = getopt(argc, argv, "dRrtw:")) != EOF)
+ switch (op) {
+
+ case 'd':
+ dump_flag = 1;
+ break;
+
+ case 'R':
+ ++report_times;
+ timestamp_style = TIMESTAMP_RAW;
+ break;
+
+ case 'r':
+ ++report_times;
+ timestamp_style = TIMESTAMP_READABLE;
+ break;
+
+ case 't':
+ ++report_times;
+ timestamp_style = TIMESTAMP_PARSEABLE;
+ break;
+
+ case 'w':
+ write_file_name = optarg;
+ break;
+
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+
+ if ( report_times > 1 )
+ error( "only one of -R, -r, or -t can be specified" );
+
+
+ if (optind < argc)
+ /* See if the next argument looks like a possible
+ * start time, and if so assume it is one.
+ */
+ if (isdigit(argv[optind][0]) || argv[optind][0] == '+')
+ start_time_string = argv[optind++];
+
+ if (optind < argc)
+ if (isdigit(argv[optind][0]) || argv[optind][0] == '+')
+ stop_time_string = argv[optind++];
+
+
+ if (optind >= argc)
+ error("at least one input file must be given");
+
+
+ first_time = first_packet_time(argv[optind]);
+ fclose( sf_readfile );
+
+
+ if (start_time_string)
+ start_time = parse_time(start_time_string, first_time);
+ else
+ start_time = first_time;
+
+ if (stop_time_string)
+ stop_time = parse_time(stop_time_string, start_time);
+
+ else
+ {
+ stop_time = start_time;
+ stop_time.tv_sec += 86400*3660; /* + 10 years; "forever" */
+ }
+
+
+ if (report_times) {
+ for (; optind < argc; ++optind)
+ dump_times(argv[optind]);
+ }
+
+ if (dump_flag) {
+ printf( "start\t%s\nstop\t%s\n",
+ timestamp_to_string( &start_time ),
+ timestamp_to_string( &stop_time ) );
+ }
+
+ if (! report_times && ! dump_flag) {
+ if ( ! strcmp( write_file_name, "-" ) &&
+ isatty( fileno(stdout) ) )
+ error("stdout is a terminal; redirect or use -w");
+
+ sf_write_init(write_file_name, linkinfo, thiszone, snaplen,
+ precision);
+
+ for (; optind < argc; ++optind)
+ extract_slice(argv[optind], &start_time, &stop_time);
+
+ fclose( sf_writefile );
+ }
+
+ return 0;
+}
+
+
+/* Returns non-zero if a string matches the format for a timestamp,
+ * 0 otherwise.
+ */
+int is_timestamp( str )
+char *str;
+ {
+ while ( isdigit(*str) || *str == '.' )
+ ++str;
+
+ return *str == '\0';
+ }
+
+
+/* Return the correction in seconds for the local time zone with respect
+ * to Greenwich time.
+ */
+long local_time_zone(timestamp)
+long timestamp;
+{
+ struct timeval now;
+ struct timezone tz;
+ long localzone;
+
+ if (gettimeofday(&now, &tz) < 0) {
+ perror("tcpslice: gettimeofday");
+ exit(1);
+ }
+ localzone = tz.tz_minuteswest * -60;
+
+ if (localtime((time_t *) &timestamp)->tm_isdst)
+ localzone += 3600;
+
+ return localzone;
+}
+
+/* Given a string specifying a time (or a time offset) and a "base time"
+ * from which to compute offsets and fill in defaults, returns a timeval
+ * containing the specified time.
+ */
+
+struct timeval
+parse_time(time_string, base_time)
+ char *time_string;
+ struct timeval base_time;
+{
+ struct tm *bt = localtime((time_t *) &base_time.tv_sec);
+ struct tm t;
+ struct timeval result;
+ time_t usecs = 0;
+ int is_delta = (time_string[0] == '+');
+
+ if ( is_delta )
+ ++time_string; /* skip over '+' sign */
+
+ if ( is_timestamp( time_string ) )
+ { /* interpret as a raw timestamp or timestamp offset */
+ char *time_ptr;
+
+ result.tv_sec = atoi( time_string );
+ time_ptr = strchr( time_string, '.' );
+
+ if ( time_ptr )
+ { /* microseconds are specified, too */
+ int num_digits = strlen( time_ptr + 1 );
+ result.tv_usec = atoi( time_ptr + 1 );
+
+ /* turn 123.456 into 123 seconds plus 456000 usec */
+ while ( num_digits++ < 6 )
+ result.tv_usec *= 10;
+ }
+
+ else
+ result.tv_usec = 0;
+
+ if ( is_delta )
+ {
+ result.tv_sec += base_time.tv_sec;
+ result.tv_usec += base_time.tv_usec;
+
+ if ( result.tv_usec > 1000000 )
+ {
+ result.tv_usec -= 1000000;
+ ++result.tv_sec;
+ }
+ }
+
+ return result;
+ }
+
+ if (is_delta) {
+ t = *bt;
+ usecs = base_time.tv_usec;
+ } else {
+ /* Zero struct (easy way around lack of tm_gmtoff/tm_zone
+ * under older systems) */
+ bzero((char *)&t, sizeof(t));
+
+ /* Set values to "not set" flag so we can later identify
+ * and default them.
+ */
+ t.tm_sec = t.tm_min = t.tm_hour = t.tm_mday = t.tm_mon =
+ t.tm_year = -1;
+ }
+
+ fill_tm(time_string, is_delta, &t, &usecs);
+
+ /* Now until we reach a field that was specified, fill in the
+ * missing fields from the base time.
+ */
+#define CHECK_FIELD(field_name) \
+ if (t.field_name < 0) \
+ t.field_name = bt->field_name; \
+ else \
+ break
+
+ do { /* bogus do-while loop so "break" in CHECK_FIELD will work */
+ CHECK_FIELD(tm_year);
+ CHECK_FIELD(tm_mon);
+ CHECK_FIELD(tm_mday);
+ CHECK_FIELD(tm_hour);
+ CHECK_FIELD(tm_min);
+ CHECK_FIELD(tm_sec);
+ } while ( 0 );
+
+ /* Set remaining unspecified fields to 0. */
+#define ZERO_FIELD_IF_NOT_SET(field_name,zero_val) \
+ if (t.field_name < 0) \
+ t.field_name = zero_val
+
+ if (! is_delta) {
+ ZERO_FIELD_IF_NOT_SET(tm_year,90); /* should never happen */
+ ZERO_FIELD_IF_NOT_SET(tm_mon,0);
+ ZERO_FIELD_IF_NOT_SET(tm_mday,1);
+ ZERO_FIELD_IF_NOT_SET(tm_hour,0);
+ ZERO_FIELD_IF_NOT_SET(tm_min,0);
+ ZERO_FIELD_IF_NOT_SET(tm_sec,0);
+ }
+
+ result.tv_sec = gwtm2secs(&t);
+ result.tv_sec -= local_time_zone(result.tv_sec);
+ result.tv_usec = usecs;
+
+ return result;
+}
+
+
+/* Fill in (or add to, if is_delta is true) the time values in the
+ * tm struct "t" as specified by the time specified in the string
+ * "time_string". "usecs_addr" is updated with the specified number
+ * of microseconds, if any.
+ */
+void
+fill_tm(time_string, is_delta, t, usecs_addr)
+ char *time_string;
+ int is_delta; /* if true, add times in instead of replacing */
+ struct tm *t; /* tm struct to be filled from time_string */
+ time_t *usecs_addr;
+{
+ char *t_start, *t_stop, format_ch;
+ int val;
+
+#define SET_VAL(lhs,rhs) \
+ if (is_delta) \
+ lhs += rhs; \
+ else \
+ lhs = rhs
+
+ /* Loop through the time string parsing one specification at
+ * a time. Each specification has the form <number><letter>
+ * where <number> indicates the amount of time and <letter>
+ * the units.
+ */
+ for (t_stop = t_start = time_string; *t_start; t_start = ++t_stop) {
+ if (! isdigit(*t_start))
+ error("bad date format %s, problem starting at %s",
+ time_string, t_start);
+
+ while (isdigit(*t_stop))
+ ++t_stop;
+ if (! t_stop)
+ error("bad date format %s, problem starting at %s",
+ time_string, t_start);
+
+ val = atoi(t_start);
+
+ format_ch = *t_stop;
+ if ( isupper( format_ch ) )
+ format_ch = tolower( format_ch );
+
+ switch (format_ch) {
+ case 'y':
+ if ( val > 1900 )
+ val -= 1900;
+ SET_VAL(t->tm_year, val);
+ break;
+
+ case 'm':
+ if (strchr(t_stop+1, 'D') ||
+ strchr(t_stop+1, 'd'))
+ /* it's months */
+ SET_VAL(t->tm_mon, val - 1);
+ else /* it's minutes */
+ SET_VAL(t->tm_min, val);
+ break;
+
+ case 'd':
+ SET_VAL(t->tm_mday, val);
+ break;
+
+ case 'h':
+ SET_VAL(t->tm_hour, val);
+ break;
+
+ case 's':
+ SET_VAL(t->tm_sec, val);
+ break;
+
+ case 'u':
+ SET_VAL(*usecs_addr, val);
+ break;
+
+ default:
+ error(
+ "bad date format %s, problem starting at %s",
+ time_string, t_start);
+ }
+ }
+}
+
+
+/* Return in first_time and last_time the timestamps of the first and
+ * last packets in the given file.
+ */
+void
+get_file_range( filename, first_time, last_time )
+ char filename[];
+ struct timeval *first_time;
+ struct timeval *last_time;
+{
+ *first_time = first_packet_time( filename );
+
+ if ( ! sf_find_end( first_time, last_time ) )
+ error( "couldn't find final packet in file %s", filename );
+}
+
+
+/* Returns the timestamp of the first packet in the given tcpdump save
+ * file, which as a side-effect is initialized for further save-file
+ * reading.
+ */
+
+struct timeval
+first_packet_time(filename)
+ char filename[];
+{
+ struct packet_header hdr;
+ u_char *buf;
+
+ if (sf_read_init(filename, &linkinfo, &thiszone, &snaplen, &precision))
+ error( "bad tcpdump file %s", filename );
+
+ buf = (u_char *)malloc((unsigned)snaplen);
+
+ if (sf_next_packet(&hdr, buf, snaplen))
+ error( "bad status reading first packet in %s", filename );
+
+ free((char *)buf);
+
+ return hdr.ts;
+}
+
+
+/* Extract from the given file all packets with timestamps between
+ * the two time values given (inclusive). These packets are written
+ * to the save file output set up by a previous call to sf_write_init().
+ * Upon return, start_time is adjusted to reflect a time just after
+ * that of the last packet written to the output.
+ */
+
+void
+extract_slice(filename, start_time, stop_time)
+ char filename[];
+ struct timeval *start_time;
+ struct timeval *stop_time;
+{
+ long start_pos, stop_pos;
+ struct timeval file_start_time, file_stop_time;
+ int status;
+ struct packet_header hdr;
+ u_char *buf;
+
+
+ if (sf_read_init(filename, &linkinfo, &thiszone, &snaplen, &precision))
+ error( "bad tcpdump file %s", filename );
+
+ buf = (u_char *)malloc((unsigned)snaplen);
+
+ start_pos = ftell( sf_readfile );
+
+
+ if ( (status = sf_next_packet( &hdr, buf, snaplen )) )
+ error( "bad status %d reading packet in %s",
+ status, filename );
+
+ file_start_time = hdr.ts;
+
+
+ if ( ! sf_find_end( &file_start_time, &file_stop_time ) )
+ error( "problems finding end packet of file %s",
+ filename );
+
+ stop_pos = ftell( sf_readfile );
+
+
+ /* sf_find_packet() requires that the time it's passed as its last
+ * argument be in the range [min_time, max_time], so we enforce
+ * that constraint here.
+ */
+ if ( sf_timestamp_less_than( start_time, &file_start_time ) )
+ *start_time = file_start_time;
+
+ if ( sf_timestamp_less_than( &file_stop_time, start_time ) )
+ return; /* there aren't any packets of interest in the file */
+
+
+ sf_find_packet( &file_start_time, start_pos,
+ &file_stop_time, stop_pos,
+ start_time );
+
+ for ( ; ; )
+ {
+ struct timeval *timestamp;
+ status = sf_next_packet( &hdr, buf, snaplen );
+
+ if ( status )
+ {
+ if ( status != SFERR_EOF )
+ error( "bad status %d reading packet in %s",
+ status, filename );
+ break;
+ }
+
+ timestamp = &hdr.ts;
+
+ if ( ! sf_timestamp_less_than( timestamp, start_time ) )
+ { /* packet is recent enough */
+ if ( sf_timestamp_less_than( stop_time, timestamp ) )
+ /* We've gone beyond the end of the region
+ * of interest ... We're done with this file.
+ */
+ break;
+
+ sf_write( buf, timestamp, (int) hdr.len,
+ (int) hdr.caplen );
+ *start_time = *timestamp;
+
+ /* We know that each packet is guaranteed to have
+ * a unique timestamp, so we push forward the
+ * allowed minimum time to weed out duplicate
+ * packets.
+ */
+ ++start_time->tv_usec;
+ }
+ }
+
+ fclose( sf_readfile );
+ free( (char *) buf );
+}
+
+
+/* Translates a timestamp to the time format specified by the user.
+ * Returns a pointer to the translation residing in a static buffer.
+ * There are two such buffers, which are alternated on subseqeuent
+ * calls, so two calls may be made to this routine without worrying
+ * about the results of the first call being overwritten by the
+ * results of the second.
+ */
+
+char *
+timestamp_to_string(timestamp)
+ struct timeval *timestamp;
+{
+ struct tm *t;
+#define NUM_BUFFERS 2
+ static char buffers[NUM_BUFFERS][128];
+ static int buffer_to_use = 0;
+ char *buf;
+
+ buf = buffers[buffer_to_use];
+ buffer_to_use = (buffer_to_use + 1) % NUM_BUFFERS;
+
+ switch ( timestamp_style )
+ {
+ case TIMESTAMP_RAW:
+ sprintf( buf, "%d.%d", timestamp->tv_sec, timestamp->tv_usec );
+ break;
+
+ case TIMESTAMP_READABLE:
+ t = localtime((time_t *) &timestamp->tv_sec);
+ strcpy( buf, asctime( t ) );
+ buf[24] = '\0'; /* nuke final newline */
+ break;
+
+ case TIMESTAMP_PARSEABLE:
+ t = localtime((time_t *) &timestamp->tv_sec);
+ sprintf( buf, "%02dy%02dm%02dd%02dh%02dm%02ds%06du",
+ t->tm_year, t->tm_mon + 1, t->tm_mday, t->tm_hour,
+ t->tm_min, t->tm_sec, timestamp->tv_usec );
+ break;
+
+ }
+
+ return buf;
+}
+
+
+/* Given a tcpdump save filename, reports on the times of the first
+ * and last packets in the file.
+ */
+
+void
+dump_times(filename)
+ char filename[];
+{
+ struct timeval first_time, last_time;
+
+ get_file_range( filename, &first_time, &last_time );
+
+ printf( "%s\t%s\t%s\n",
+ filename,
+ timestamp_to_string( &first_time ),
+ timestamp_to_string( &last_time ) );
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr, "tcpslice for tcpdump version %d.%d\n",
+ VERSION_MAJOR, VERSION_MINOR);
+ (void)fprintf(stderr,
+"Usage: tcpslice [-dRrt] [-w file] [start-time [end-time]] file ... \n");
+
+ exit(-1);
+}