texlive[49537] Build/source/texk/web2c: move direct %s fixes to

commits+karl at tug.org commits+karl at tug.org
Sun Dec 30 19:59:26 CET 2018


Revision: 49537
          http://tug.org/svn/texlive?view=revision&revision=49537
Author:   karl
Date:     2018-12-30 19:59:26 +0100 (Sun, 30 Dec 2018)
Log Message:
-----------
move direct %s fixes to change files (from andreas)

Modified Paths:
--------------
    trunk/Build/source/texk/web2c/cwebboot.cin
    trunk/Build/source/texk/web2c/cwebboot.hin
    trunk/Build/source/texk/web2c/cwebdir/ChangeLog
    trunk/Build/source/texk/web2c/cwebdir/comm-w2c.ch
    trunk/Build/source/texk/web2c/cwebdir/common.c
    trunk/Build/source/texk/web2c/cwebdir/common.w
    trunk/Build/source/texk/web2c/cwebdir/cweav-w2c.ch
    trunk/Build/source/texk/web2c/cwebdir/cweave.w

Added Paths:
-----------
    trunk/Build/source/texk/web2c/cwebdir/examples/
    trunk/Build/source/texk/web2c/cwebdir/examples/Makefile
    trunk/Build/source/texk/web2c/cwebdir/examples/README
    trunk/Build/source/texk/web2c/cwebdir/examples/extex.ch
    trunk/Build/source/texk/web2c/cwebdir/examples/extex.w
    trunk/Build/source/texk/web2c/cwebdir/examples/kspell.el
    trunk/Build/source/texk/web2c/cwebdir/examples/oemacs.el
    trunk/Build/source/texk/web2c/cwebdir/examples/oemacs.w
    trunk/Build/source/texk/web2c/cwebdir/examples/treeprint.w
    trunk/Build/source/texk/web2c/cwebdir/examples/wc-dos.ch
    trunk/Build/source/texk/web2c/cwebdir/examples/wc.w
    trunk/Build/source/texk/web2c/cwebdir/examples/wmer-os2.ch
    trunk/Build/source/texk/web2c/cwebdir/examples/wmerg-pc.ch
    trunk/Build/source/texk/web2c/cwebdir/examples/wmerge.w
    trunk/Build/source/texk/web2c/cwebdir/examples/wordtest.w
    trunk/Build/source/texk/web2c/cwebdir/examples/xlib_types.w
    trunk/Build/source/texk/web2c/cwebdir/examples/xview_types.w

Modified: trunk/Build/source/texk/web2c/cwebboot.cin
===================================================================
--- trunk/Build/source/texk/web2c/cwebboot.cin	2018-12-30 17:39:13 UTC (rev 49536)
+++ trunk/Build/source/texk/web2c/cwebboot.cin	2018-12-30 18:59:26 UTC (rev 49537)
@@ -250,7 +250,7 @@
 FILE*tex_file;
 FILE*idx_file;
 FILE*scn_file;
-#line 730 "cwebdir/comm-w2c.ch"
+#line 736 "cwebdir/comm-w2c.ch"
 FILE*active_file;
 char*found_filename;
 #line 1376 "cwebdir/common.w"
@@ -283,7 +283,7 @@
 /*:55*//*71:*/
 #line 1251 "cwebdir/common.w"
 
-#line 647 "cwebdir/comm-w2c.ch"
+#line 653 "cwebdir/comm-w2c.ch"
 static void scan_args(void);
 #line 1253 "cwebdir/common.w"
 
@@ -334,7 +334,7 @@
 /*70:*/
 #line 1233 "cwebdir/common.w"
 
-#line 639 "cwebdir/comm-w2c.ch"
+#line 645 "cwebdir/comm-w2c.ch"
 show_banner= show_happiness= show_progress= 1;
 #line 1235 "cwebdir/common.w"
 
@@ -346,7 +346,7 @@
 
 scan_args();
 if(program==ctangle){
-#line 739 "cwebdir/comm-w2c.ch"
+#line 745 "cwebdir/comm-w2c.ch"
 if((C_file= fopen(C_file_name,"wb"))==NULL)
 #line 1381 "cwebdir/common.w"
 fatal("! Cannot open output file ",C_file_name);
@@ -353,7 +353,7 @@
 
 }
 else{
-#line 745 "cwebdir/comm-w2c.ch"
+#line 751 "cwebdir/comm-w2c.ch"
 if((tex_file= fopen(tex_file_name,"wb"))==NULL)
 #line 1386 "cwebdir/common.w"
 fatal("! Cannot open output file ",tex_file_name);
@@ -1098,7 +1098,9 @@
  fatal(const char*s,const char*t)
 #line 1182 "cwebdir/common.w"
 {
+#line 595 "cwebdir/comm-w2c.ch"
 if(*s)printf("%s",s);
+#line 1184 "cwebdir/common.w"
 err_print(t);
 history= fatal_message;exit(wrap_up());
 }
@@ -1106,7 +1108,7 @@
 /*:66*//*67:*/
 #line 1190 "cwebdir/common.w"
 void
-#line 598 "cwebdir/comm-w2c.ch"
+#line 604 "cwebdir/comm-w2c.ch"
  overflow(const char*t)
 #line 1193 "cwebdir/common.w"
 {
@@ -1117,7 +1119,7 @@
 /*:67*//*72:*/
 #line 1254 "cwebdir/common.w"
 
-#line 657 "cwebdir/comm-w2c.ch"
+#line 663 "cwebdir/comm-w2c.ch"
 static void
 scan_args(void)
 #line 1257 "cwebdir/common.w"
@@ -1131,22 +1133,22 @@
 
 while(--argc> 0){
 if((**(++argv)=='-'||**argv=='+')&&*(*argv+1))/*76:*/
-#line 682 "cwebdir/comm-w2c.ch"
+#line 688 "cwebdir/comm-w2c.ch"
 
 {
 if(strcmp("-help",*argv)==0||strcmp("--help",*argv)==0)
 /*86:*/
-#line 797 "cwebdir/comm-w2c.ch"
+#line 803 "cwebdir/comm-w2c.ch"
 
 usagehelp(program==ctangle?CTANGLEHELP:CWEAVEHELP,NULL);
 
 
 /*:86*/
-#line 685 "cwebdir/comm-w2c.ch"
+#line 691 "cwebdir/comm-w2c.ch"
 ;
 if(strcmp("-version",*argv)==0||strcmp("--version",*argv)==0)
 /*87:*/
-#line 806 "cwebdir/comm-w2c.ch"
+#line 812 "cwebdir/comm-w2c.ch"
 
 printversionandexit((program==ctangle?ctangle_banner:cweave_banner),
 "Silvio Levy and Donald E. Knuth",NULL,NULL);
@@ -1153,11 +1155,11 @@
 
 
 /*:87*/
-#line 687 "cwebdir/comm-w2c.ch"
+#line 693 "cwebdir/comm-w2c.ch"
 ;
 #line 1346 "cwebdir/common.w"
 if(**argv=='-')flag_change= 0;
-#line 693 "cwebdir/comm-w2c.ch"
+#line 699 "cwebdir/comm-w2c.ch"
 else flag_change= 1;
 if(*(*argv+1)=='d')
 if(sscanf(*argv+2,"%u",&kpathsea_debug)!=1)/*77:*/
@@ -1164,7 +1166,7 @@
 #line 1352 "cwebdir/common.w"
 
 {
-#line 716 "cwebdir/comm-w2c.ch"
+#line 722 "cwebdir/comm-w2c.ch"
 if(program==ctangle){
 fprintf(stderr,"ctangle: Need one to three file arguments.\n");
 usage("ctangle");
@@ -1176,11 +1178,11 @@
 }
 
 /*:77*/
-#line 695 "cwebdir/comm-w2c.ch"
+#line 701 "cwebdir/comm-w2c.ch"
 ;
 #line 1348 "cwebdir/common.w"
 for(dot_pos= *argv+1;*dot_pos> '\0';dot_pos++)
-#line 701 "cwebdir/comm-w2c.ch"
+#line 707 "cwebdir/comm-w2c.ch"
 flags[(unsigned char)*dot_pos]= flag_change;
 #line 1350 "cwebdir/common.w"
 }
@@ -1280,7 +1282,7 @@
 found_out= 1;
 }
 
-#line 682 "cwebdir/comm-w2c.ch"
+#line 688 "cwebdir/comm-w2c.ch"
 /*:75*/
 #line 1277 "cwebdir/common.w"
 
@@ -1288,7 +1290,7 @@
 #line 1352 "cwebdir/common.w"
 
 {
-#line 716 "cwebdir/comm-w2c.ch"
+#line 722 "cwebdir/comm-w2c.ch"
 if(program==ctangle){
 fprintf(stderr,"ctangle: Need one to three file arguments.\n");
 usage("ctangle");
@@ -1308,7 +1310,7 @@
 #line 1352 "cwebdir/common.w"
 
 {
-#line 716 "cwebdir/comm-w2c.ch"
+#line 722 "cwebdir/comm-w2c.ch"
 if(program==ctangle){
 fprintf(stderr,"ctangle: Need one to three file arguments.\n");
 usage("ctangle");
@@ -1322,7 +1324,7 @@
 /*:77*/
 #line 1281 "cwebdir/common.w"
 ;
-#line 667 "cwebdir/comm-w2c.ch"
+#line 673 "cwebdir/comm-w2c.ch"
 if(found_change<=0)strcpy(change_file_name,DEV_NULL);
 #line 1283 "cwebdir/common.w"
 }

Modified: trunk/Build/source/texk/web2c/cwebboot.hin
===================================================================
--- trunk/Build/source/texk/web2c/cwebboot.hin	2018-12-30 17:39:13 UTC (rev 49536)
+++ trunk/Build/source/texk/web2c/cwebboot.hin	2018-12-30 18:59:26 UTC (rev 49537)
@@ -1,5 +1,5 @@
 /*84:*/
-#line 786 "cwebdir/comm-w2c.ch"
+#line 792 "cwebdir/comm-w2c.ch"
 
 /* Prototypes for functions, either
  * declared in common.w and used in ctangle.w and cweave.w, or
@@ -43,7 +43,7 @@
 #line 1175 "cwebdir/common.w"
 
 /*:65*//*83:*/
-#line 767 "cwebdir/comm-w2c.ch"
+#line 773 "cwebdir/comm-w2c.ch"
 
 extern void common_init(void);
 extern int input_ln(FILE*fp);
@@ -56,9 +56,9 @@
 extern name_pointer section_lookup(char*first,char*last,int ispref);
 #line 1417 "cwebdir/common.w"
 
-#line 782 "cwebdir/comm-w2c.ch"
+#line 788 "cwebdir/comm-w2c.ch"
 /*:83*/
-#line 790 "cwebdir/comm-w2c.ch"
+#line 796 "cwebdir/comm-w2c.ch"
 
 extern const char*versionstring;
 

Modified: trunk/Build/source/texk/web2c/cwebdir/ChangeLog
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/ChangeLog	2018-12-30 17:39:13 UTC (rev 49536)
+++ trunk/Build/source/texk/web2c/cwebdir/ChangeLog	2018-12-30 18:59:26 UTC (rev 49537)
@@ -1,3 +1,12 @@
+2018-12-30  Andreas Scherer  <https://ascherer.github.io>
+
+	* cweave.w,
+	* common.w,
+	* common.c,
+	* ../cwebboot.cin: do not change the CWEB sources, use
+	changefile entries instead.
+	* examples: add directory (unchanged) from cweb-3.64c.tar.gz.
+
 2018-11-02  Andreas Scherer  <https://ascherer.github.io>
 
 	* ctang-w2c.ch,

Modified: trunk/Build/source/texk/web2c/cwebdir/comm-w2c.ch
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/comm-w2c.ch	2018-12-30 17:39:13 UTC (rev 49536)
+++ trunk/Build/source/texk/web2c/cwebdir/comm-w2c.ch	2018-12-30 18:59:26 UTC (rev 49537)
@@ -589,6 +589,12 @@
 fatal (const char *s, const char *t)
 @z
 
+ at x l.1183
+  if (*s) printf(s);
+ at y
+  if (*s) printf("%s",s);
+ at z
+
 Section 65.
 
 @x l.1191

Modified: trunk/Build/source/texk/web2c/cwebdir/common.c
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/common.c	2018-12-30 17:39:13 UTC (rev 49536)
+++ trunk/Build/source/texk/web2c/cwebdir/common.c	2018-12-30 18:59:26 UTC (rev 49537)
@@ -1063,7 +1063,7 @@
 fatal(s,t)
 char*s,*t;
 {
-if(*s)printf("%s",s);
+if(*s)printf(s);
 err_print(t);
 history= fatal_message;exit(wrap_up());
 }

Modified: trunk/Build/source/texk/web2c/cwebdir/common.w
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/common.w	2018-12-30 17:39:13 UTC (rev 49536)
+++ trunk/Build/source/texk/web2c/cwebdir/common.w	2018-12-30 18:59:26 UTC (rev 49537)
@@ -1180,7 +1180,7 @@
 fatal(s,t)
   char *s,*t;
 {
-  if (*s) printf("%s",s);
+  if (*s) printf(s);
   err_print(t);
   history=fatal_message; exit(wrap_up());
 }

Modified: trunk/Build/source/texk/web2c/cwebdir/cweav-w2c.ch
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/cweav-w2c.ch	2018-12-30 17:39:13 UTC (rev 49536)
+++ trunk/Build/source/texk/web2c/cwebdir/cweav-w2c.ch	2018-12-30 18:59:26 UTC (rev 49537)
@@ -599,6 +599,12 @@
 print_cat (eight_bits c)
 @z
 
+ at x l.1788
+  printf(cat_name[c]);
+ at y
+  printf("%s",cat_name[c]);
+ at z
+
 Section 106.
 
 @x l.2138

Modified: trunk/Build/source/texk/web2c/cwebdir/cweave.w
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/cweave.w	2018-12-30 17:39:13 UTC (rev 49536)
+++ trunk/Build/source/texk/web2c/cwebdir/cweave.w	2018-12-30 18:59:26 UTC (rev 49537)
@@ -1785,7 +1785,7 @@
 print_cat(c) /* symbolic printout of a category */
 eight_bits c;
 {
-  printf("%s",cat_name[c]);
+  printf(cat_name[c]);
 }
 
 @ The token lists for translated \TEX/ output contain some special control

Added: trunk/Build/source/texk/web2c/cwebdir/examples/Makefile
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/examples/Makefile	                        (rev 0)
+++ trunk/Build/source/texk/web2c/cwebdir/examples/Makefile	2018-12-30 18:59:26 UTC (rev 49537)
@@ -0,0 +1,57 @@
+#
+# generic Makefile to use when you've got CWEB
+# (add it to, or add to it, whatever you like)
+#
+#======================================================================
+
+CFLAGS = -g
+MLIB = -lm
+RM = /bin/rm -f
+WFILES = extex.w treeprint.w wc.w wmerge.w wordtest.w oemacs.w
+
+#======================================================================
+
+.SUFFIXES: .tex .dvi .w
+
+.w.tex:
+	cweave $*
+
+.tex.dvi:	
+	tex $<
+
+.w.dvi:
+	make $*.tex
+	make $*.dvi
+
+.w.c:
+	ctangle $*
+
+.w.o:
+	make $*.c
+	make $*.o
+
+.c.o:
+	cc $(CFLAGS) -c $*.c
+
+.w:
+	make $*.c
+	cc $(CFLAGS) $*.c -o $*
+
+#======================================================================
+
+all: $(WFILES:.w=) excweb
+
+excweb: extex
+	ln extex excweb
+
+oemacs: oemacs.c
+	cc $(CFLAGS) -I/usr/openwin/include oemacs.c \
+             -o oemacs -lxview -lolgx -lX11
+
+doc: $(WFILES:.w=.dvi)
+
+clean:
+	$(RM) *~ \#~ .\#* *.o *.log *.dvi *.toc core a.out
+
+clobber: clean
+	$(RM) $(WFILES:.w=) $(WFILES:.w=.c) $(WFILES:.w=.tex)


Property changes on: trunk/Build/source/texk/web2c/cwebdir/examples/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/texk/web2c/cwebdir/examples/README
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/examples/README	                        (rev 0)
+++ trunk/Build/source/texk/web2c/cwebdir/examples/README	2018-12-30 18:59:26 UTC (rev 49537)
@@ -0,0 +1,55 @@
+This directory contains several files for programs that are tutorial
+and/or useful. If you are new to CWEB, read "wc.w" first; it's a
+typical example of CWEB applied to system programming.
+
+The Makefile on this directory is a generic way to build applications
+written in CWEB. Say, for example, "make wc" to get an executable
+program "wc" from wc.w. Say "make wc.dvi" to get a printable listing
+of its documentation. The program "wc" is a slight improvement over
+UNIX's standard word-count utility. (Try it, for example, with "wc *".)
+
+The treeprint program, by Norman Ramsey, generates tree-structured
+representations of file hierarchies. To use it, say "make treeprint.run"
+and then
+   find dir -type p -print | sort | treeprint
+(on a UNIX system), where dir is a directory with interesting subdirectories.
+
+The wmerge program, by Silvio Levy, produces a single CWEB file from a
+given CWEB file and a change file. It expands any "web include" (@i)
+specifications in the original CWEB file. To use it, say "make wmerge.run"
+and then, e.g., "wmerge foo.w bar.ch > foobar.w". Both CTANGLE and
+CWEAVE already accept change files, so you need not merge anything yourself
+in normal day-to-day operations; but wmerge can be useful in connection with
+the spelling checker described below.
+
+If you intend to read the source code of CTANGLE and CWEAVE, you may
+well wish to read wmerge.w first, or the hardcopy version obtained from
+"make wmerge.dvi"; it is similar but much simpler.
+
+The extex and wordtest programs, by Don Knuth, are useful spellcheckers.
+After "make extex.run" say also "ln extex excweb"; this gives
+you two filter programs, extex and excweb, that remove extraneous
+material from TeX and CWEB source files, respectively. To use them,
+you can say for example
+   cat foo.w | excweb | spell
+(or replace "cat foo.w" with "wmerge foo.w bar.ch"). A similar pipeline
+for TeX files would be
+   cat foo.tex | extex | spell
+Even better is to replace "spell" by "wordtest /usr/local/lib/dict/words",
+if you have a suitable dictionary. One such dictionary in the public domain
+can be found in directory ~ftp/pub/dict at ftp.cs.stanford.edu, available
+via anonymous ftp. To make your own dictionary from given ones,
+   cat dict1 dict2 dict3 dict4 | wordtest > words
+is quick and effective. See the documentation of wordtest for more info.
+
+A file kspell.el that provides an emacs user interface to extex+excweb+wordtest
+also appears in this directory. (Somebody should write ELWEB...)
+
+The files xview_types.w and xlib_types.w are examples of @i (include) files
+that can be used when writing XView programs. They are based on the header
+files in OpenWindows Version 3.0.
+
+An example XView application appears in Knuth's program oemacs.w, which
+he uses for heavy emacsing. It's not very portable, but if you have
+OpenWindows3 and a Sun Type-4 keyboard you may like it as much as he does.
+(It replaces "emacstool".) The file oemacs.el goes with it.


Property changes on: trunk/Build/source/texk/web2c/cwebdir/examples/README
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/texk/web2c/cwebdir/examples/extex.ch
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/examples/extex.ch	                        (rev 0)
+++ trunk/Build/source/texk/web2c/cwebdir/examples/extex.ch	2018-12-30 18:59:26 UTC (rev 49537)
@@ -0,0 +1,23 @@
+ at x In my work (mainly TAOCP) I use \: (not \.) for the dot accent
+'&`&\relax\^&"&\relax\~&=&.&u&v\cr
+ at y
+'&`&\relax\^&"&\relax\~&=&:&u&v\cr
+ at z
+ at x
+  1,1,1,1,1,0,0,1, /* \.{\\-} and \.{\\.} */
+  1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1, /* \.{\\=} */
+ at y
+  1,1,1,1,1,0,1,1, /* \.{\\-} */
+  1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1, /* \.{:} and \.{\\=} */
+ at z
+ at x and I use |...xref-tag...| for cross-references
+case '|': if (web>1) {
+     save_skipping=skipping;
+     goto skip_C_prime;
+   }
+ at y
+case '|': if (web>1) {
+     save_skipping=skipping;
+     goto skip_C_prime;
+   } else discard_to('|');
+ at z


Property changes on: trunk/Build/source/texk/web2c/cwebdir/examples/extex.ch
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/texk/web2c/cwebdir/examples/extex.w
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/examples/extex.w	                        (rev 0)
+++ trunk/Build/source/texk/web2c/cwebdir/examples/extex.w	2018-12-30 18:59:26 UTC (rev 49537)
@@ -0,0 +1,366 @@
+\datethis
+@* Introduction. This program is a simple filter that inputs \TEX/ or \.{CWEB}
+files and outputs its best guess at the ``words'' they contain. The word
+list can then be passed to a spelling check routine such as {\tt wordtest}.
+
+If this program is invoked with the name `{\tt excweb}', it will apply
+special rules based on the syntax of \.{CWEB} files. Otherwise it will
+use only the \TEX/ conventions. (Note that \UNIX/'s {\tt ln} command
+allows a program to be invoked with more than one name although it
+appears only once in the computer's memory.)
+
+The \TEX/ conventions adopted here say that words are what remain
+after you remove nonletters, control sequences,
+comments triggered by \.\% marks, and material enclosed
+within \.{\$...\$} or \.{\$\$...\$\$}. However, an apostrophe within
+a word will be retained. The plain \TEX/ control
+sequences for accented characters and special text characters, namely
+$$\vbox{\halign{&\.{\\#}\hfil\qquad\cr
+'&`&\relax\^&"&\relax\~&=&.&u&v\cr
+H&t&c&d&b&oe&OE&ae&AE\cr
+aa&AA&o&O&l&L&ss&i&j\cr}}$$
+will also be retained, so that users can treat them as parts of words.
+A blank space
+following any of the alphabetic control sequences in this list will be carried
+along too. If any of these control sequences is followed by \.\{, everything
+up to the next \.\} will also be retained. Thus, for example, the
+construction `\.{m\\=\{\\i\}n\\u\ us}' will be considered a single word,
+in spite of the control sequences and the space between the two u's.
+Discretionary hyphens `\.{\char`\\-}' are treated in the same way as accents.
+
+The \.{CWEB} conventions are essentially the same as the \TEX/ conventions,
+in the \TEX/ parts of a \.{CWEB} file. The \CEE/ parts of the file
+are blanked out.
+
+No attempt is made to reach a high level of artificial intelligence,
+which would be able to truly understand the input file. Tricky users can
+ confuse us. But we claim that devious tricks are their problem, not ours.
+
+@ So here goes. The main idea is to keep a one-character lookahead
+buffer, called |c|, which is set to zero when the character has been
+processed. A giant switch to various cases, depending on the value of~|c|,
+keeps everything moving.
+
+If you don't like |goto| statements, don't read this. (And don't read
+any other programs that simulate finite-state automata.)
+
+ at c
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+extern void exit(); /* system routine that terminates execution */
+@#
+@<Global variables@>@;
+@<Procedures@>@;
+@#
+int main(argc,argv)
+  int argc; /* the number of arguments (should be 1, but this isn't checked) */
+  char *argv[]; /* the arguments (|*argv| is the program name) */
+{
+  @<Local variables@>;
+  if (strlen(*argv)>=6 && strcmp(*argv+strlen(*argv)-6,"excweb")==0) {
+    web=1;
+    @<Adjust tables for \.{CWEB} mode@>;
+  } else web=0;
+  comment=skipping=c=0;
+  main_cycle: if (c) goto big_switch;
+  restart: c=get();
+  big_switch: switch(c) {
+     @<Special cases of the giant switch where we don't just discard |c|@>@;
+    case EOF: exit(0);
+    default: goto restart;
+    }
+    @<Labeled code segments, which exit by explicit |goto|@>;
+}
+
+@ @<Global variables@>=
+int c; /* one-character look-see buffer */
+
+@ @<Local variables@>=
+int web; /* are we looking for \.{CWEB} constructs? */
+int comment; /* are we inside a \CEE/ comment in a \.{CWEB} document? */
+int skipping; /* are we skipping \CEE/ code in a \.{CWEB} document? */
+int save_skipping; /* value of |skipping| outside current \CEE/ mode */
+register int cc; /* temporary buffer */
+
+@* Simple cases.
+Let's do some of the easiest things first, in order to get the hang of
+this program. Several special characters will cause us to ignore everything
+until the first appearance of something else.
+
+ at d discard_to(x) {@+while (get()!=x) ;@+}
+ at d discard_to_dol {@+for (cc=c,c=get();c!='$' || cc=='\\';cc=c,c=get())
+     if (cc=='\\' && c==cc) c='\0';@+}
+
+@<Special cases...@>=
+case '%': discard_to('\n');@+goto restart;
+case '$': c=getchar();
+  if (c!='$') discard_to_dol@;
+  else { /* after \.{\$\$} we discard everything to the next \.{\$\$} */
+    do discard_to_dol@;
+    while (getchar()!='$');
+  }
+  goto restart;
+
+@ The `|get|' procedure in the code above is like \Cee's standard
+`|getchar|', except that it immediately terminates execution at the end of
+the input file. Otherwise malformed input files could lead to
+infinite loops.
+
+@<Procedures@>=
+int get()
+{@+register int x;
+  x=getchar();
+  if (x==EOF) exit(0);
+  return x;
+}
+ 
+@ More complex behavior is handled by jumping out of the |switch| statement
+to one of the routines following it. None of the cases say |break|, so
+the code following the switch statement is accessible only via |goto|.
+
+@<Special cases...@>=
+case 'a': case 'A':
+case 'b': case 'B':
+case 'c': case 'C':
+case 'd': case 'D':
+case 'e': case 'E':
+case 'f': case 'F':
+case 'g': case 'G':
+case 'h': case 'H':
+case 'i': case 'I':
+case 'j': case 'J':
+case 'k': case 'K':
+case 'l': case 'L':
+case 'm': case 'M':
+case 'n': case 'N':
+case 'o': case 'O':
+case 'p': case 'P':
+case 'q': case 'Q':
+case 'r': case 'R':
+case 's': case 'S':
+case 't': case 'T':
+case 'u': case 'U':
+case 'v': case 'V':
+case 'w': case 'W':
+case 'x': case 'X':
+case 'y': case 'Y':
+case 'z': case 'Z':
+goto out_word;
+
+@ When letters appear in |stdin|, we pass them immediately through to |stdout|
+with little further ado.
+An apostrophe is rejected unless it is immediately followed by a letter.
+
+@<Labeled code...@>=
+out_word: putchar(c);
+continue_word: c=getchar();
+checkout_word:
+if (isalpha(c)) goto out_word;
+if (c=='\'') {
+  c=getchar();
+  if (isalpha(c)) {
+    putchar('\'');@+goto out_word;
+  }
+  goto end_word;
+}
+if (c=='\\' && controlseq()) goto control_seq_in_word;
+end_word: putchar('\n');
+  goto main_cycle;
+
+@* Control sequences.  The |controlseq()| function is the only
+delicate part of this program.  After a backslash has been scanned,
+|controlseq| looks to see if the next characters define one of the
+special plain \TEX/ macros listed above. If so, the control sequence
+and its immediately following argument (if any) are output and
+|controlseq| returns a nonzero value. If not, nothing is output and
+|controlseq| returns zero. In both cases the value of |c| will be
+nonzero if and only if |controlseq| has had to look ahead at a
+character it decided not to process.
+
+@ @<Labeled code...@>=
+control_seq_in_word: if (!c) goto continue_word;
+goto checkout_word;
+
+@ @<Special cases...@>=
+case '\\': if (controlseq()) goto control_seq_in_word;
+goto main_cycle;
+
+@ @<Procedures@>=
+int controlseq()
+{
+  int l; /* number of letters in the control sequence */
+  char a,b; /* the first two characters after `\.\\' */
+  l=0;
+  a=c=getchar();
+  while (isalpha(c)) {
+    l++;
+    c=getchar();
+    if (l==1) b=c;
+  }
+  if (l==0) c=getchar();
+  @<Check for special plain \TEX/ control sequences;
+    output them and |return 1| if found@>;
+  return 0;
+}
+
+@ @d pair(x,y) (a==x && b==y)
+
+@<Check for special...@>=
+if ((a>='"' && a<='~' && ptab[a-'"']==l) ||
+ (l==2 && (pair('a','e') || pair('A','E')@|
+           || pair('o','e') || pair('O','E')@|
+           || pair('a','a') || pair('A','A') || pair('s','s')))) {
+  putchar('\\');
+  putchar(a);
+  if (l==2) putchar(b);
+  if (l && c==' ') {
+    putchar(' '); /* optional space after alphabetic control sequence */
+    c=getchar();
+  }
+  if (c=='{') {
+    do at +{putchar(c);
+      c=get();
+    }@+while (c!='}'); /* optional argument after special control sequence */
+    putchar(c);
+    c=0;
+  }
+  return 1;
+}
+
+@ The |ptab| entries for nonletters are 0 when the control sequence is
+special, otherwise~1; the conventions for letters are reversed.
+
+@<Global...@>=
+char ptab[]={0,1,1,1,1,0, /* \.{\\"} and \.{\\'} */
+  1,1,1,1,1,0,0,1, /* \.{\\-} and \.{\\.} */
+  1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1, /* \.{\\=} */
+  1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1, /* \.{\\H}, \.{\\L}, \.{\\O} */
+  0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1, /* \.{\\\^} */
+  0,0,1,1,1,0,0,0, /* \.{\\`}, \.{\\b}, \.{\\c}, \.{\\d} */
+  0,1,1,0,1,0,0,1, /* \.{\\i}, \.{\\j}, \.{\\l}, \.{\\o} */
+  0,0,0,0,1,1,1,0, /* \.{\\t}, \.{\\u}, \.{\\v} */
+  0,0,0,1,1,1,0}; /* \.{\\\~} */
+
+@ In \.{CWEB} the \TEX/ control sequence `\.{\\.}' denotes the typewriter
+font used for strings, not the dot-over accent. We must modify
+|ptab| to reflect this unfortunate (but too-late-too-change) design decision.
+
+@<Adjust tables for \.{CWEB} mode@>=
+ptab[12]=1;
+
+@* CWEB considerations.
+We're finished now with all that would be needed if we only wanted to
+handle \TEX/. For \.{CWEB} a bit more should be done.
+
+The \.{CWEB} escape character is \.{@@}, and the character following
+it tells us what mode we should enter. In \TEX/ mode we should not
+only do what we normally do for \TEX/ files, we should also ignore
+material delimited by \.{\char"7C...\char"7C}, being careful to recognize when
+|'|'| is part of a string (as it just was). And we should stop \TEX/
+mode if we scan \.{*/} while in a \CEE/ comment.
+
+@<Special cases...@>=
+case '@@': if (web) goto do_web;
+  goto restart;
+case '|': if (web>1) {
+     save_skipping=skipping;
+     goto skip_C_prime;
+   }
+   goto restart;
+case '*': if (!comment) goto restart;
+  c=getchar();
+  if (c=='/') {
+    comment=0;
+    goto skip_C;
+  }
+  goto big_switch;
+
+@ The characters that follow \.@@ in a \.{CWEB} file can be classified into
+a few types that have distinct implications for {\tt excweb}.
+
+ at d nop 0 /* control code that doesn't matter to us */
+ at d start_section 1 /* control code that begins a \.{CWEB} section */
+ at d start_C 2 /* control code that begins \CEE/ code */
+ at d start_name 3 /* control code that begins a section name */
+ at d start_index 4 /* control code for \.{CWEB} index entry */
+ at d start_insert 5 /* control code for \CEE/ material ended by `\.{@@>}' */
+ at d end_item 6 /* `\.{@@>}' */
+ at d ignore_line 7 /* `\.{@@i}' or `\.{@@l}' */
+
+@<Global...@>=
+char wtab[]={start_section,nop,nop,nop,nop,nop,nop,nop, /* \.{\ !"\#\$\%\&'} */
+ start_name,nop,start_section,nop,nop,nop,start_index,nop, /* \.{()*+,-./} */
+ nop,nop,nop,nop,nop,nop,nop,nop, /* \.{01234567} */
+ nop,nop,start_index,nop,start_name,start_insert,end_item,nop,
+    /* \.{89:;<=>?} */
+ nop,nop,nop,start_C,start_C,nop,start_C,nop, /* \.{@@ABCDEFG} */
+ nop,ignore_line,nop,nop,ignore_line,nop,nop,nop, /* \.{HIJKLMNO} */
+ start_C,start_insert,nop,start_C,start_insert,nop,nop,nop, /* \.{PQRSTUVW} */
+ nop,nop,nop,nop,nop,nop,start_index,nop, /* \.{XYZ[\\]\^\_} */
+ nop,nop,nop,start_C,start_C,nop,start_C,nop, /* \.{`abcdefg} */
+ nop,ignore_line,nop,nop,ignore_line,nop,nop,nop, /* \.{hijklmno} */
+ start_C,start_insert,nop,start_C,start_insert}; /* \.{pqrst} */
+
+@ We do not leave \TEX/ mode until the first \.{WEB} section has begun.
+
+@<Labeled code...@>=
+do_web: c=getchar();
+  if (c<' ' || c>'t') goto restart;
+  switch(wtab[c-' ']){
+ case nop: case start_index: goto restart;
+ case start_section: web++; /* out of ``limbo'' */
+  comment=skipping=0;@+goto restart;
+ case start_C: if (web>1) goto skip_C;
+  goto restart;
+ case start_name: case start_insert: if (web>1) skipping=1;
+  goto restart;
+ case end_item: if (skipping) goto skip_C;
+   goto restart;
+ case ignore_line: discard_to('\n');
+   goto restart;
+  }
+
+@ The final piece of program we need is a sub-automaton to pass over
+the \CEE/ parts of a \.{CWEB} document. The main subtlety here is that
+we don't want to get out of synch while scanning over a supposed
+string constant or verbatim insert.
+
+@<Labeled code...@>=
+skip_C: save_skipping=2;
+skip_C_prime: skipping=1;
+  while (1) {
+    c=get();
+  C_switch: switch(c) {
+   case '/': c=get();
+     if (c!='*') goto C_switch;
+     comment=1; /* fall through to the next case, returning to \TEX/ mode */
+   case '|': if (save_skipping==2) continue; /* |'|'| as \CEE/ operator */
+     skipping=save_skipping;@+goto restart; /* |'|'| as \.{CWEB} delimiter */
+   case '@@': c=getchar();
+    inner_switch: if (c<' ' || c>'t') continue;
+     switch(wtab[c-' ']) {
+    case nop: case start_C: case end_item: continue;
+    case start_section: web++;
+     comment=skipping=0;@+goto restart;
+    case start_name: case start_index: goto restart;
+    case start_insert: do at +discard_to('@@')@;@+while ((c=getchar())=='@@');
+      goto inner_switch; /* now |c| should equal |'>'| */
+    case ignore_line: discard_to('\n');
+     continue;
+     }
+   case '\'': case '"':    
+     while ((cc=get())!=c && cc!='\n')
+       if (cc=='\\') getchar();
+       else if (cc=='@@') {
+         cc=getchar();
+         if (cc!='@@') { /* syntax error, we try to recover */
+           c=cc; goto inner_switch;
+         }
+       };
+     continue; /* \.{CWEB} strings do not extend past one line */
+    default: continue;
+    }
+  }
+
+@* Index.


Property changes on: trunk/Build/source/texk/web2c/cwebdir/examples/extex.w
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/texk/web2c/cwebdir/examples/kspell.el
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/examples/kspell.el	                        (rev 0)
+++ trunk/Build/source/texk/web2c/cwebdir/examples/kspell.el	2018-12-30 18:59:26 UTC (rev 49537)
@@ -0,0 +1,228 @@
+;; Alternative spelling enterface for Emacs, contributed by Don Knuth
+;; (Uses the wordtest and extex programs, which are
+;;  supplied as examples with the CWEB distribution,
+;;  available by anonymous ftp from ftp.cs.stanford.edu)
+
+;; Based in part on "spell.el" from GNU Emacs; redistributed under
+;; the terms of the GNU General Public License; NO WARRANTY implied.
+
+;; To install this, using the default directories defined below,
+;; install wordtest and extex in /usr/local/bin, then say
+;; "ln /usr/local/bin/extex /usr/local/bin/excweb", then install
+;; a suitable dictionary in /usr/local/lib/dict/words; one such
+;; dictionary can be found in ~ftp/pub/dict/words at ftp.cs.stanford.edu.
+;; Also create an empty file called .words in your home directory.
+;; Finally, add (load-library "kspell") to your .emacs file, or
+;; include such a line in site-init.el if kspell is to be used by everybody.
+;; If you get a message like "Checking spelling of buffer...not correct"
+;; and nothing else, the probable cause is that the wordtest program
+;; could not open /usr/local/lib/dict/words or ~/.words for reading.
+
+;; Note (10 Feb 1998): The spell-check logic failed to catch "obso1ete"
+;; as a scanner-typo for "obsolete". The reason is that, although "obso"
+;; and "ete" are non-words, they couldn't be found in query-replace
+;; for the regexps "\bobso\b" and "\bete\b".
+
+(provide 'kspell)
+
+(defvar wordtest-command "wordtest" ;; maybe "/usr/local/bin/wordtest" better?
+  "*Command to run the wordtest program; can include command-line options.")
+
+;; "wordtest [options] [dictionaries] <infile >outfile" outputs all
+;; lines of infile that don't appear in the dictionaries. The options
+;; can define arbitrary character code mappings of 8-bit characters.
+;; The default mapping takes a-z into A-Z, otherwise is ASCII.
+
+(defvar wordtest-filter "extex" ;; maybe "/usr/local/bin/extex" is better?
+  "*Command to run the filter needed by wordtest.")
+(make-variable-buffer-local 'wordtest-filter)
+
+;; The extex filter extracts words from its input and outputs them on
+;; separate lines as required by wordtest. It removes TeX control
+;; sequences except those used to make accents and special characters.
+;; There's a companion filter excweb that also removes C code from CWEBs.
+(setq cweb-mode-hook '(lambda () (setq wordtest-filter "excweb")))
+
+(defvar wordtest-system-dictionary "/usr/local/lib/dict/words"
+  "*Sorted dictionary containing all \"correct\" words,
+including all variant forms obtained by prefix and suffix transformations.")
+;; The standard UNIX dictionary /usr/dict/words is NOT satisfactory.
+
+(defvar wordtest-personal-dictionary "~/.words"
+  "*Default dictionary to supplement the words in the system dictionary.
+If nil, no supplementary dictionary will be used.
+This dictionary must be in alphabetic order as defined by wordtest.
+Inserting any word with the + option to kspell-region will sort the file.")
+(make-variable-buffer-local 'wordtest-personal-dictionary)
+
+(defun set-personal-dictionary (filename)
+  "Defines the supplementary personal dictionary for kspell to use in the
+current buffer, overriding the default value of wordtest-personal-dictionary."
+  (interactive "FPersonal dictionary file name: ")
+  (setq wordtest-personal-dictionary filename))
+
+(defun unset-personal-dictionary ()
+  "Tells kspell not to use personal spelling dictionary with current buffer."
+  (interactive)
+  (setq wordtest-personal-dictionary nil))
+
+(defun insert-into-personal-dictionary (word)
+  "Put WORD into user's dictionary and sort that dictionary."
+  (interactive "sword: ")
+  (let ((xword (concat word "\n")))
+    (if (null wordtest-personal-dictionary)
+        (setq wordtest-personal-dictionary
+              (read-string "Personal dictionary file name: " "~/.words")))
+    (set-buffer (find-file-noselect wordtest-personal-dictionary))
+    (goto-char (point-min))
+    (insert xword)
+    (call-process-region (point-min) (point-max) shell-file-name
+                         t t nil "-c" wordtest-command)
+    (search-backward xword (point-min) 1) ;; in case the user is watching
+    (while (not (bolp)) (search-backward xword (point-min) 1))
+    (save-buffer)))
+    
+(defun kspell-buffer ()
+  "Check spelling of every word in the buffer.
+For each incorrect word, you are asked for the correct spelling
+and then put into a query-replace to fix some or all occurrences.
+
+If you do not want to change a word, just give the same word
+as its \"incorrect\" spelling; then the query replace is skipped.
+Words are given in lowercase, but they will be Capitalized when
+replacing Capitalized words, ALL_CAPS when replacing ALL_CAPS words.
+If you type ? after a replacement, your correction will first be
+looked up in the dictionary, and the query-replace will occur
+only if the replacement is found. If you type + after a replacement,
+your replacement will be inserted into the current personal dictionary.
+
+You can leave the minibuffer to do some other editing and then come
+back again to the query-replace loop by typing \\[other-window]."
+  (interactive)
+  (save-excursion (kspell-region (point-min) (point-max) "buffer")))
+
+(defun kspell-word ()
+  "Check spelling of the word at or before point.
+If it is not correct, ask user for the correct spelling and
+query-replace the entire buffer to substitute it as with kspell-buffer."
+  (interactive)
+  (let (beg end wordtest-filter)
+    (save-excursion
+     (if (not (looking-at "\\<"))
+         (forward-word -1))
+     (setq beg (point))
+     (forward-word 1)
+     (setq end (point))
+     (kspell-region beg end (buffer-substring beg end)))))
+
+(defun kspell-region (start end &optional description)
+  "Like kspell-buffer but checks only words in the current region.
+Used in a program, applies from START to END.
+DESCRIPTION is an optional string naming the unit being checked:
+for example, \"buffer\"."
+  (interactive "r")
+  (let (correct
+        (filter wordtest-filter)
+        (buf (get-buffer-create " *kspell*")) ;; hidden by list-buffers
+        (dicts wordtest-system-dictionary))
+    (if wordtest-personal-dictionary
+        (setq dicts (concat dicts " " wordtest-personal-dictionary)))        
+    (save-excursion
+      (save-excursion
+        (set-buffer buf)
+        (widen)
+        (erase-buffer))
+      (message "Checking spelling of %s..." (or description "region"))
+      (if (and (null filter)
+               (< end (point-max))
+               (= ?\n (char-after end)))
+          (call-process-region start (1+ end) shell-file-name
+                               nil buf nil "-c"
+                               (concat wordtest-command " " dicts))
+        (let ((oldbuf (current-buffer)))
+          (save-excursion
+            (set-buffer buf)
+            (insert-buffer-substring oldbuf start end)
+            (or (bolp) (insert ?\n))
+            (if filter
+                (call-process-region (point-min) (point-max) shell-file-name
+                                     t t nil "-c" filter))
+            (call-process-region (point-min) (point-max) shell-file-name
+                                 t t nil "-c"
+                                 (concat wordtest-command " " dicts)))))
+      (setq correct (save-excursion (set-buffer buf) (= (buffer-size) 0)))
+      (message "Checking spelling of %s...%scorrect"
+               (or description "region")
+               (if correct "" "not "))
+      (if correct t
+        (let (word newword qtext lastchar
+                   (case-fold-search t)
+                   (case-replace t))
+          (while (save-excursion
+                   (set-buffer buf)
+                   (> (buffer-size) 0))
+            (save-excursion
+              (set-buffer buf)
+              (goto-char (point-min))
+              (setq word (downcase
+                          (buffer-substring (point)
+                                            (progn (end-of-line) (point)))))
+              (forward-char 1) ;; pass the newline
+              (delete-region (point-min) (point))
+              (setq qtext (concat "\\b" (regexp-quote word) "\\b")))
+            (goto-char (point-min))
+            (setq lastchar nil)
+            (if (re-search-forward qtext nil t)
+                (while (null lastchar)
+                  (setq newword
+                        (read-string
+                         (concat "edit a replacement for `" word "': ")
+                         word))
+                  (if (null newword) (setq lastchar 0)
+                    (setq lastchar (string-to-char (substring newword -1)))
+                    (if (memq lastchar '(?? ?+))
+                        (setq newword (substring newword 0 -1))))
+                  (cond ((= lastchar ??)
+                         (cond ((or (string= word newword) (string= "" newword))
+                                (describe-function 'kspell-buffer)
+                                (setq lastchar nil))
+                               ((not (kspelt-right newword))
+                                (setq lastchar nil))))
+                        ((= lastchar ?+)
+                         (save-excursion
+                           (insert-into-personal-dictionary newword))))
+                  (cond ((string= word newword))
+                        ((null lastchar))
+                        (t
+                         (goto-char (point-min))
+                         (if (or (equal word newword) (null lastchar)) t
+                           (query-replace-regexp qtext newword))))))))))))
+
+(defun kspelt-right (word)
+  "T if WORD is in the system dictionary or user's personal dictionary."
+  (let ((buf (get-buffer-create " *temp*"))
+        (pdict wordtest-personal-dictionary))
+    (message "Checking spelling of %s..." word)
+    (save-excursion
+     (set-buffer buf)
+     (widen)
+     (erase-buffer)
+     (insert word "\n")
+     (if pdict
+         (call-process-region (point-min) (point-max) shell-file-name
+                              t t nil "-c"
+                              (concat wordtest-command " "
+                                      wordtest-system-dictionary " "
+                                      pdict))
+       (call-process-region (point-min) (point-max) shell-file-name
+                            t t nil "-c"
+                            (concat wordtest-command " "
+                                    wordtest-system-dictionary)))
+     (= 0 (buffer-size)))))
+
+(defun kspell-string (string)
+  "Check spelling of string supplied as argument."
+  (interactive "sSpell string: ")
+  (message "%s is %scorrect" string
+           (if (kspelt-right string) "" "in")))
+


Property changes on: trunk/Build/source/texk/web2c/cwebdir/examples/kspell.el
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/texk/web2c/cwebdir/examples/oemacs.el
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/examples/oemacs.el	                        (rev 0)
+++ trunk/Build/source/texk/web2c/cwebdir/examples/oemacs.el	2018-12-30 18:59:26 UTC (rev 49537)
@@ -0,0 +1,176 @@
+;; macros to go with oemacs
+
+; suntool-map is the map for "\C-x*", the oemacs prefix for function keys
+; commented-out lines agree with the settings in $(EMACS)/lisp/term/sun.el
+
+(setq suntool-map-hooks '(			; not your usual hook list
+; (define-key suntool-map "al" 'keyboard-quit)		; Stop
+; (define-key suntool-map "bl" 'redraw-display)		; Again	L2
+; (define-key suntool-map "b\M-l" 'repeat-complex-command); M-Again = C-X ESC
+; (define-key repeat-complex-command-map "\C-x*b\M-l"
+;                   'previous-complex-command)		; M-Again M-Again...
+  (define-key suntool-map "bL" 'rerun-prev-command)	; AGAIN (no confirm)
+; (define-key suntool-map "b\M-L" 'rerun-prev-command)	; M-AGAIN
+; (define-key suntool-map "cl" 'buffer-menu)		; Props
+; (define-key suntool-map "dl" 'undo)			; Undo
+; (define-key suntool-map "el" 'ignore-key)		; Front
+; (define-key suntool-map "fl" 'sun-select-region)	; Copy
+; (define-key suntool-map "f," 'copy-region-as-kill)	; C-Copy
+; (define-key suntool-map "gl" 'ignore-key)		; Open
+; (define-key suntool-map "hl" 'sun-yank-selection)	; Paste
+; (define-key suntool-map "h," 'yank)			; C-Paste
+; (define-key suntool-map "il" 'research-forward)	; Find (with default)
+; (define-key suntool-map "i\M-l" 'research-backward)	; M-Find
+; (define-key suntool-map "iL" 'isearch-forward-regexp)	; FIND (incremental)
+; (define-key suntool-map "i\M-L" 'isearch-backward-regexp); M-FIND
+; (define-key suntool-map "i," 're-search-forward)	; C-Find (ordinary)
+; (define-key suntool-map "i\M-," 're-search-backward)	; C-M-Find
+  (define-key suntool-map "jl" 'sun-cut-region)		; Cut
+  (define-key suntool-map "j," 'kill-region-and-unmark) ; C-Cut
+  (define-key suntool-map "jL" 'pop-the-mark)		; CUT
+; (define-key suntool-map "j\M-l" 'exchange-point-and-mark); M-Cut
+
+  (define-key suntool-map "at" 'bury-buffer)			; F1
+; (define-key suntool-map "bt" 'toggle-selective-display) 	; F2
+; (define-key suntool-map "ct" 'scroll-down-in-place)		; F3
+; (define-key suntool-map "cT" '(lambda(n) (interactive "p") (scroll-down n)))
+; (define-key suntool-map "dt" 'scroll-up-in-place)		; F4
+; (define-key suntool-map "dT" '(lambda(n) (interactive "p") (scroll-up n)))
+  (define-key suntool-map "et" 'jumpup)				; F5
+; (define-key suntool-map "ft" 'shrink-window)			; F6
+; (define-key suntool-map "fT" 'shrink-window-horizontally)	; Shift-F6
+; (define-key suntool-map "gt" 'enlarge-window)			; F7
+; (define-key suntool-map "gT" 'enlarge-window-horizontally)	; Shift-F7
+  (define-key suntool-map "ht" 'tags-search)			; F8
+  (define-key suntool-map "it" 'tags-query-replace)		; F9
+  (define-key suntool-map "jt" 'narrow-to-region)		; F10
+  (define-key suntool-map "j\M-t" 'narrow-to-page)		; M-F10
+  (define-key suntool-map "kt" 'revert-buffer)  		; F11
+  (define-key suntool-map "k\M-t" 'quick-revert-other-buffer)	; M-F11
+  (define-key suntool-map "lt" 'goto-line)			; F12
+  (define-key suntool-map "l\M-t" 'goto-line)			; M-F12
+
+  (define-key suntool-map "ar" 'redraw-display)			; Pause, R1
+  (define-key suntool-map "br" 'call-secondlast-kbd-macro)	; PrSc, R2
+  (define-key suntool-map "cr" 'ignore-key)		; Scroll Lock Break, R3
+  (define-key suntool-map "dr" 'unbound-key)			; KP=, R4
+  (define-key suntool-map "d\M-r" 'bind-last-kbd-macro-to-KP=)	; M-KP=, M-R4
+  (define-key suntool-map "er" 'unbound-key)			; KP/, R5
+  (define-key suntool-map "e\M-r" 'bind-last-kbd-macro-to-KP/)	; M-KP/, M-R5
+  (define-key suntool-map "fr" 'unbound-key)			; KP*, R6
+  (define-key suntool-map "f\M-r" 'bind-last-kbd-macro-to-KP*)	; M-KP*, M-R6
+; (define-key suntool-map "gr" 'beginning-of-buffer)		; Home, R7
+
+; (define-key suntool-map "hr" 'previous-line)			; Up, R8
+; (define-key suntool-map "ir" 'scroll-down)			; PgUp, R9
+; (define-key suntool-map "iR" 'backward-page)			; Shift-PGUP
+; (define-key suntool-map "jr" 'backward-char)			; Lft, R10
+  (define-key suntool-map "kr" "\C-u\C-l")			; KP5, R11
+; (define-key suntool-map "lr" 'forward-char)			; Rt, R12
+; (define-key suntool-map "mr" 'end-of-buffer)			; End, R13
+; (define-key suntool-map "nr" 'next-line)			; Dn, R14
+; (define-key suntool-map "or" 'scroll-up)			; PgDn, R15
+; (define-key suntool-map "oR" 'forward-page)			; Shift-PGUP
+
+  (define-key suntool-map "ab" 'apropos) 		; Help
+  (define-key suntool-map "a\M-b" 'mouse-help)	 	; M-Help
+  (define-key suntool-map "aB" 'describe-bindings) 	; HELP
+  (define-key suntool-map "a\M-B" 'describe-mouse-bindings); M-HELP
+  (define-key suntool-map "a\"" 'command-apropos)	; C-Help
+  (define-key suntool-map "a\C-B" 'apropos)		; C-HELP
+  (define-key suntool-map "a\M-\C-B" 'help-for-dummies)	; M-C-HELP
+  (define-key suntool-map "bb" 'ignore-key)		; Alt
+  (define-key suntool-map "cb" 'ignore-key)		; AltGraph
+  (define-key suntool-map "db" 'auto-fill-mode)		; Keypad Ins
+  (define-key suntool-map "eb" 'overwrite-mode)		; Keypad Del
+  (define-key suntool-map "fb" 'call-last-kbd-macro)	; Keypad Enter
+  (define-key suntool-map "gb" 'forward-paragraph)	; Keypad +
+  (define-key suntool-map "hb" 'backward-paragraph)	; Keypad -
+  ))
+
+
+; redefinition of emacs functions
+(defun end-of-buffer ()
+  "Move point to the end of the buffer; leave a mark at previous position.
+Scroll so that point is at the bottom of the window, if possible."
+  (interactive)
+  (push-mark)
+  (goto-char (point-max))
+  (recenter -1))
+
+; new functions
+(defun jumpup ()
+  "Scroll so that point is at the top of the window."
+  (interactive)(recenter 0))
+
+(defun quick-revert-buffer ()
+  "Revert the buffer without asking for confirmation."
+  (interactive)
+  (revert-buffer t t))
+
+(defun quick-revert-other-buffer (n)
+  "Revert the Nth other buffer without asking for confirmation."
+  (interactive "p")
+  (other-window n)
+  (revert-buffer t t)
+  (other-window (- n)))
+
+(defun bind-last-kbd-macro-to-KP= ()
+  "Assign the last keyboard macro to the = key on the numeric keypad."
+  (interactive)
+  (define-key suntool-map "dr" last-kbd-macro))
+
+(defun bind-last-kbd-macro-to-KP/ ()
+  "Assign the last keyboard macro to the / key on the numeric keypad."
+  (interactive)
+  (define-key suntool-map "er" last-kbd-macro))
+
+(defun bind-last-kbd-macro-to-KP* ()
+  "Assign the last keyboard macro to the * key on the numeric keypad."
+  (interactive)
+  (define-key suntool-map "fr" last-kbd-macro))
+
+(defvar secondlast-kbd-macro nil)
+(defun pre-end-kbd-macro ()
+  "Preserve last-kbd-macro as secondlast-kbd-macro, then end-kbd-macro."
+  (interactive)
+  (setq secondlast-kbd-macro last-kbd-macro)
+  (end-kbd-macro))
+(substitute-key-definition 'end-kbd-macro 'pre-end-kbd-macro global-map)
+(substitute-key-definition 'end-kbd-macro 'pre-end-kbd-macro esc-map)
+(substitute-key-definition 'end-kbd-macro 'pre-end-kbd-macro ctl-x-map)
+
+(defun call-secondlast-kbd-macro (n)
+  "Like call-last-kbd-macro, but uses the macro defined before that."
+  (interactive "p")
+  (let ((last-kbd-macro secondlast-kbd-macro))
+    (call-last-kbd-macro n)))
+
+; The turn-numlock-on/off commands are created automatically by oemacs
+; when the NumLock light changes state.
+(defun turn-numlock-on () ; numlock is always off when oemacs starts
+  "Bind keys in keypad area to numeric interpretations."
+  (interactive)
+  (setq hb-binding (lookup-key suntool-map "hb"))
+  (setq gb-binding (lookup-key suntool-map "gb"))
+  (setq fb-binding (lookup-key suntool-map "fb"))
+  (setq eb-binding (lookup-key suntool-map "eb"))
+  (setq db-binding (lookup-key suntool-map "db"))
+  (define-key suntool-map "hb" "-")
+  (define-key suntool-map "gb" "+")
+  (define-key suntool-map "fb" "\C-j")
+  (define-key suntool-map "eb" ".")
+  (define-key suntool-map "db" "0"))
+(defun turn-numlock-off ()
+  "Rebind keys in keypad area to function-key interpretations."
+  (interactive)
+  (define-key suntool-map "hb" hb-binding)
+  (define-key suntool-map "gb" gb-binding)
+  (define-key suntool-map "fb" fb-binding)
+  (define-key suntool-map "eb" eb-binding)
+  (define-key suntool-map "db" db-binding))
+(defvar hb-binding nil)
+(defvar gb-binding nil)
+(defvar fb-binding nil)
+(defvar eb-binding nil)
+(defvar db-binding nil)


Property changes on: trunk/Build/source/texk/web2c/cwebdir/examples/oemacs.el
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/texk/web2c/cwebdir/examples/oemacs.w
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/examples/oemacs.w	                        (rev 0)
+++ trunk/Build/source/texk/web2c/cwebdir/examples/oemacs.w	2018-12-30 18:59:26 UTC (rev 49537)
@@ -0,0 +1,896 @@
+\datethis
+ at i xview_types.w
+
+@* Introduction.
+This program provides an interface between the GNU Emacs editor and the
+OpenWindows environment, using the XView toolkit for interactive graphics.
+It is based on \.{emacstool}, a SunView interface written by Jeff Peck
+of Sun Microsystems in 1986 and adapted by him in 1988 to \.{xvetool},
+an early XView interface. The present code, by Don Knuth, is designed to work
+with OpenWindows Version~3 as distributed in 1992, using a Sun Type~4
+keyboard.
+
+GNU Emacs is a highly portable and versatile program, which does most
+of the hard work involved in editing files. Our job is simply twofold:
+To get \.{emacs} started in an appropriate window, and to transmit
+keyboard and mouse events as sequences of characters that \.{emacs}
+can happily consume.  These simple tasks do, however, require us to
+get a lot of fussy details right. In fact, this program could not have been
+written without a good deal more knowledge about XView than can be found
+in the manuals. Fortunately Jeff Peck works for Sun, and his
+inside knowledge has provided the necessary clues. (All complaints below
+about the XView documentation are based on the reference manuals and
+programming manuals available from Sun and from O'Reilly \AM\ Associates, in
+the summer of 1992. Let us hope that such problems will not persist;
+computer programming should be fun, but some of the code below was
+written only after a bitter struggle!)
+
+The command-line arguments to \.{oemacs} are either standard XView
+arguments, which specify the font and the size and position of the window,
+the icon, the colors, etc.; or they are standard arguments of \.{emacs},
+which typically specify the file to be edited and a position in that file.
+If I decide later to make certain things in \.{oemacs} less hardwired,
+I will look for options in the X resource database instead of on the
+command line.
+
+An important note about using \.{xmodmap} to change the behavior of
+certain keys appears below. It makes \.{emacs} more powerful, unless you
+have other good uses for those keys. (See the entry for \.{xmodmap}
+in the index.)
+
+Before using \.{oemacs}, you must compile \.{emacs} with the
+\.{sunfns} module (which the \.{Makefile} will do for you if you've
+configured it correctly), and you should include the lines
+$$\vbox{\halign{\.{#}\hfil\cr
+(load-library "sun-mouse")\cr
+(load-library "sun-fns")\cr}}$$
+in Emacs's file \.{lisp/site-init.el}.
+
+Caution: This program was developed and tested with Peck's improved
+versions of sun-mouse and sun-fns; these are available from
+\.{peck@@sun.com} if not yet part of the GNU distribution.
+
+@ We follow the traditional structure of XView applications. The |exit|
+statement at the end is important, because \.{oemacs} can be invoked by
+the \.{system} command in \TEX/ (when the user has typed \.e in response
+to an error message); without |exit(0)|, \TEX/ would complain of trouble
+executing this program, although we would simply be terminating the program
+without returning any particular value.
+
+ at c
+@<Include header files@>@;
+@#
+Frame frame; /* the base frame where we will live */
+@<Global variables@>@; /* additional globals besides |frame| */
+@#
+@<Event-handling procedures@>@;
+@#
+main(argc,argv)
+  int argc;@+char *argv[]; /* typical \UNIX/ setup */
+{
+  @<Special initialization@>;
+  @<Install the components and controls of |frame|@>;
+  xv_main_loop(frame);
+  exit(0);
+}
+
+@ Including the header file \.{<xview/xview.h>} also causes other
+basic header files like \.{<xview/frame.h>}, \.{<xview/icon.h>}, etc.,
+to be loaded. We must call the \CEE/ compiler with the flag
+\.{-I\$(OPENWINHOME)/include} so that the \CEE/ preprocessor will
+find the OpenWindows header files.
+
+Some \UNIX/ systems define string functions in \.{<string.h>}, some in
+\.{<strings.h>}; the Sun documentation calls for \.{<string.h>}. My
+experiments indicate that Sun's compiler and loader work perfectly
+well with string functions even when no header files are given, so the
+programmer doesn't really have to remember the right name. Similarly,
+\.{<stdio.h>} isn't really needed with Sun's \CEE/, unless certain macros
+are used. I'll include \.{<string.h>} and \.{<stdio.h>} anyway, in the
+spirit of being obedient to the stated rules.
+
+@<Include...@>=
+#include <string.h>
+#include <stdio.h>
+#include <xview/xview.h>
+
+@* The icon and frame.
+First we attach an icon that will appear if the user closes the \.{oemacs}
+window later.
+
+There are two reasons for doing this first. One is that we might as well
+begin with an easy task, in order to get warmed up. The other is that
+if we specify the icon {\it after\/} creating the frame, we will unconditionally
+override an icon that the user may have specified with the \.{-WI}
+option on the command line. (This is one of the little things a
+programmer has to turn by trial and error, since the XView documentation
+leaves much unsaid.)
+
+The colors used in the icon will be inherited from the frame, so they will
+be reversed if the user asks for reverse video. I~prefer to have the icon
+always in black on a yellow background, so I'm making the color explicit.
+(I hope this will work on monochrome displays; it works fine on my
+grayscale monitor.)
+
+@<Create a frame with the gnu icon@>=
+{@+Server_image icon_image=(Server_image)xv_create(NULL,SERVER_IMAGE,@|
+       XV_WIDTH,64,XV_HEIGHT,64,SERVER_IMAGE_BITS,icon_bits,NULL);
+  Server_image mask_image=(Server_image)xv_create(NULL,SERVER_IMAGE,@|
+       XV_WIDTH,64,XV_HEIGHT,64,SERVER_IMAGE_BITS,mask_bits,NULL);
+  Cms cms=(Cms)xv_create(NULL,CMS,CMS_SIZE,2,@|
+        CMS_NAMED_COLORS,"yellow","black",NULL,NULL);
+  Icon icon=(Icon)xv_create(NULL,ICON,@|
+       ICON_IMAGE,icon_image,ICON_MASK_IMAGE,mask_image,@|
+       WIN_CMS,cms,NULL);
+  frame=xv_create(NULL,FRAME,FRAME_ICON,icon,NULL);
+}
+
+@ @<Include...@>=
+#include <xview/cms.h>
+
+@ If the user hasn't specified a label with the \.{-Wl} option, we turn off
+the header line at the top of the frame. That gives us a chance to see
+two more lines of the file \.{emacs} is editing. However, we add a
+label of our own; it will show up in the virtual window manager display.
+
+@<Remove the frame header, unless the user has specifically requested it@>=
+if (xv_get(frame,XV_LABEL)==NULL) /* no label specified */
+  xv_set(frame,FRAME_SHOW_HEADER,FALSE,XV_LABEL,"OEMACS",NULL);
+
+@ The following icon and mask are derived from the ``what's gnu'' image on the
+back cover of the GNU Emacs manual. (This accounts for my black-on-yellow
+preference.)
+
+@<Global...@>=
+unsigned short icon_bits[]={@|
+	0x0000,	0x0000,	0x0000,	0x1E00,
+	0x0000,	0x0000,	0x0000,	0x0900,@|
+	0x001E,	0x0000,	0x0000,	0x0880,
+	0x0064,	0x0000,	0x0000,	0x0440,@|
+	0x0088,	0x0000,	0x0000,	0x0420,
+	0x0110,	0x0000,	0x0000,	0x0210,@|
+	0x0220,	0x0000,	0x0000,	0x0210,
+	0x0420,	0x0FCF,	0x01C0,	0x0108,@|
+	0x0840,	0x1030,	0x8620,	0x0088,
+	0x1080,	0x00C0,	0x5810,	0x0084,@|
+	0x1080,	0x1F00,	0x2008,	0x0044,
+	0x2100,	0xE200,	0x1004,	0x0044,@|
+	0x4103,	0x0400,	0x0002,	0x0042,
+	0x4204,	0x080E,	0x0001,	0x0042,@|
+	0x8200,	0x7830,	0x0020,	0x8082,
+	0x8203,	0x9040,	0x0018,	0x4102,@|
+	0x8204,	0x2080,	0x07C6,	0x3E04,
+	0x8108,	0x410C,	0x0021,	0x8004,@|
+	0x8080,	0x8210,	0x03D0,	0x6008,
+	0x4041,	0x0420,	0x0008,	0x1810,@|
+	0x403E,	0x0820,	0x0FFC,	0x0620,
+	0x2000,	0x1040,	0x0002,	0x01C0,@|
+	0x1000,	0x608C,	0x0FFF,	0x0060,
+	0x0801,	0x8110,	0x0080,	0x8118,@|
+	0x0406,	0x0220,	0x1FFF,	0x66E0,
+	0x0238,	0x044F,	0x0000,	0xD800,@|
+	0x01C0,	0x0890,	0x8FFF,	0x4000,
+	0x0300,	0x10A6,	0x4041,	0x6000,@|
+	0x1C00,	0x2026,	0x4FFF,	0x6000,
+	0x60CC,	0x4026,	0x4001,	0x6000,@|
+	0x1F33,	0x8010,	0x8FFF,	0x4000,
+	0x0012,	0x000F,	0x0040,	0xC000,@|
+	0x0022,	0x4000,	0x07FF,	0x4000,
+	0x0024,	0x4000,	0x0000,	0x2000,@|
+	0x0024,	0x4818,	0x8FFF,	0xE000,
+	0x0024,	0x4907,	0x0040,	0x2000,@|
+	0x0044,	0x4900,	0x1FFF,	0xE000,
+	0x0044,	0x4900,	0x0000,	0x2000,@|
+	0x0044,	0x4900,	0x07FF,	0xE000,
+	0x0044,	0x4880,	0x0020,	0x2000,@|
+	0x0044,	0x4880,	0x07FF,	0xE000,
+	0x0044,	0x4840,	0x0000,	0x2000,@|
+	0x0044,	0x2A20,	0x07FF,	0xE000,
+	0x0044,	0x2410,	0x0020,	0x2000,@|
+	0x0042,	0x2448,	0x0FFF,	0xE000,
+	0x0042,	0x2948,	0x0000,	0x2000,@|
+	0x0041,	0x1144,	0x07FF,	0xA000,
+	0x0041,	0x1144,	0x2010,	0x1000,@|
+	0x0021,	0x1126,	0x20FA,	0x1000,
+	0x0024,	0x8925,	0x2600,	0x1000,@|
+	0x0014,	0x8924,	0xA138,	0x7000,
+	0x0016,	0x88A4,	0x9090,	0x6000,@|
+	0x000A,	0x44A4,	0x4880,	0xA000,
+	0x0002,	0x44A2,	0x4401,	0x2000,@|
+	0x0003,	0x4492,	0x2001,	0x4000,
+	0x0001,	0x2451,	0x3002,	0x8000,@|
+	0x0000,	0xA251,	0x1E05,	0x0000,
+	0x0000,	0x2248,	0xA1F9,	0x8000,@|
+	0x0000,	0x1648,	0x9002,	0x8000,
+	0x0000,	0x1A28,	0x4C02,	0x8000,@|
+	0x0000,	0x1220,	0x43FC,	0x8000,
+	0x0000,	0x0120,	0x2000,	0x8000,@|
+	0x0000,	0x0120,	0x2003,	0x0000,
+	0x0000,	0x0150,	0x1FFC,	0x0000
+};
+unsigned short mask_bits[]={@|
+	0x0000,	0x0000,	0x0000,	0x1E00,
+	0x0000,	0x0000,	0x0000,	0x0F00,@|
+	0x001E,	0x0000,	0x0000,	0x0F80,
+	0x007C,	0x0000,	0x0000,	0x07C0,@|
+	0x00F8,	0x0000,	0x0000,	0x07E0,
+	0x01F0,	0x0000,	0x0000,	0x03F0,@|
+	0x03E0,	0x0000,	0x0000,	0x03F0,
+	0x07E0,	0x0FCF,	0x01C0,	0x01F8,@|
+	0x0FC0,	0x103F,	0x87F0,	0x00F8,
+	0x1F80,	0x00FF,	0xDFF0,	0x00FC,@|
+	0x1F80,	0x1FFF,	0xFFF8,	0x007C,
+	0x3F00,	0xE3FF,	0xFFFC,	0x007C,@|
+	0x7F03,	0x07FF,	0xFFFE,	0x007E,
+	0x7E04,	0x0FFF,	0xFFFF,	0x007E,@|
+	0xFE00,	0x7FFF,	0xFFFF,	0x80FE,
+	0xFE03,	0x9FFF,	0xFFFF,	0xC1FE,@|
+	0xFE04,	0x3FFF,	0xFFFF,	0xFFFC,
+	0xFF08,	0x7FFF,	0xFFFF,	0xFFFC,@|
+	0xFF80,	0xFFFF,	0xFFFF,	0xFFF8,
+	0x7FC1,	0xFFFF,	0xFFFF,	0xFFF0,@|
+	0x7FFF,	0xFFFF,	0xFFFF,	0xFFE0,
+	0x3FFF,	0xFFFF,	0xFFFF,	0xFFC0,@|
+	0x1FFF,	0xFFFF,	0xFFFF,	0xFFE0,
+	0x0FFF,	0xFFFF,	0xFFFF,	0xFFF8,@|
+	0x07FF,	0xFFFF,	0xFFFF,	0xFEE0,
+	0x03FF,	0xFFFF,	0xFFFF,	0xF800,@|
+	0x01FF,	0xFFFF,	0xFFFF,	0xE000,
+	0x03FF,	0xFFFF,	0xFFFF,	0xE000,@|
+	0x1FFF,	0xFFFF,	0xFFFF,	0xE000,
+	0x7FFF,	0xFFFF,	0xFFFF,	0xE000,@|
+	0x1F7F,	0xFFFF,	0xFFFF,	0xC000,
+	0x001F,	0xFFFF,	0xFFFF,	0xC000,@|
+	0x003F,	0xFFFF,	0xFFFF,	0xC000,
+	0x003F,	0xFFFF,	0xFFFF,	0xE000,@|
+	0x003F,	0xFFFF,	0xFFFF,	0xE000,
+	0x003F,	0xFFFF,	0xFFFF,	0xE000,@|
+	0x007F,	0xFFFF,	0xFFFF,	0xE000,
+	0x007F,	0xFFFF,	0xFFFF,	0xE000,@|
+	0x007F,	0xFFFF,	0xFFFF,	0xE000,
+	0x007F,	0xFFFF,	0xFFFF,	0xE000,@|
+	0x007F,	0xFFFF,	0xFFFF,	0xE000,
+	0x007F,	0xFFFF,	0xFFFF,	0xE000,@|
+	0x007F,	0xFFFF,	0xFFFF,	0xE000,
+	0x007F,	0xFFFF,	0xFFFF,	0xE000,@|
+	0x007F,	0xFFFF,	0xFFFF,	0xE000,
+	0x007F,	0xFFFF,	0xFFFF,	0xE000,@|
+	0x007F,	0xFFFF,	0xFFFF,	0xE000,
+	0x007F,	0xFFFF,	0xFFFF,	0xF000,@|
+	0x003F,	0xFFFF,	0xFFFF,	0xF000,
+	0x003F,	0xFFFF,	0xFFFF,	0xF000,@|
+	0x001F,	0xFFFF,	0xFFFF,	0xF000,
+	0x001F,	0xFFFF,	0xFFFF,	0xE000,@|
+	0x000B,	0xFFFF,	0xFFFF,	0xE000,
+	0x0003,	0xFFFF,	0xFFFF,	0xE000,@|
+	0x0003,	0xFFFF,	0xFFFF,	0xC000,
+	0x0001,	0xFFFF,	0xFFFF,	0x8000,@|
+	0x0000,	0xBFF1,	0xFFFF,	0x0000,
+	0x0000,	0x3FF8,	0xFFFF,	0x8000,@|
+	0x0000,	0x1FF8,	0xFFFF,	0x8000,
+	0x0000,	0x1FF8,	0x7FFF,	0x8000,@|
+	0x0000,	0x13E0,	0x7FFF,	0x8000,
+	0x0000,	0x01E0,	0x3FFF,	0x8000,@|
+	0x0000,	0x01E0,	0x3FFF,	0x0000,
+	0x0000,	0x0150,	0x1FFC,	0x0000
+};
+
+@* Emulating a terminal.
+We will run \.{emacs} in a ``tty subwindow,'' named after the teletype
+terminals of ancient yore.
+
+The |argv| array will be a command line that invokes
+\.{emacs} with all arguments not removed by |xv_init|, i.e., all arguments
+that remain after generic XView arguments have been removed.
+
+We have to say |WIN_IS_CLIENT_PANE|, otherwise fonts specified on the
+command line will be ignored. (This cryptic instruction is mentioned briefly
+in the XView reference manual, but not in the XView programming manual;
+I~would never have discovered it without Jeff Peck's help.)
+
+We also have to set |TTY_QUIT_ON_CHILD_DEATH| to |TRUE|. Otherwise when
+\.{emacs} exits (via control-X, control-C) there still will be a terminal
+window (into which we can type but not access the shell).
+
+Before starting \.{emacs} we set the environment variable
+\.{TERM} equal to \.{sun}.
+This will tell \.{emacs} to initialize itself with the
+programs in its source file \.{lisp/term/sun.el}, where special
+adaptations for Sun-style terminals have been recorded.
+
+@<Put a tty subwindow into the frame@>=
+argv[0]="emacs";
+putenv("TERM=sun");
+tty=(Tty)xv_create(frame,TTY,WIN_IS_CLIENT_PANE,@|
+      TTY_QUIT_ON_CHILD_DEATH,TRUE,@|
+      TTY_ARGV,argv,NULL);
+
+@ @<Global...@>=
+Tty tty;
+
+@ @<Include...@>=
+#include <xview/tty.h>
+
+@ The XView manual doesn't tell us that tty subwindows have a view part
+and a pseudo-terminal part. (The manual does mention briefly that text
+subwindows have views---at the beginning of section 6.3, and indirectly in
+one of the examples in the chapter on color.)
+
+The view window of an emulated tty will receive keyboard and
+mouse events. We need to know its ``handle,'' because we want to
+modify XView's default interpretation of many of those events.
+
+For example, we want to grab the keyboard focus (i.e., to begin receiving
+keyboard input) as soon as the user moves the mouse into the \.{emacs}
+window. The normal OpenLook default requires a user to click in the window
+first, but that is inefficient in a production book-writing environment.
+Us \.{emacs} users would rather type than point.
+
+A secret incantation makes the view window accessible. Dear reader,
+would you have guessed how to do this, from reading the manuals only,
+without looking at Jeff Peck's code? Be honest now.
+
+We don't have to enable the notification of other kinds of events;
+tty subwindows already do that.
+
+@<Prepare to be notified when the mouse enters the window@>=
+window=(Xv_window)xv_get(tty,OPENWIN_NTH_VIEW,0);
+xv_set(window,WIN_CONSUME_EVENT,LOC_WINENTER,NULL);
+
+@ @<Global...@>=
+Xv_window window; /* the view window of |tty| */
+
+@ If the user has specified reverse video with the \.{-rv} option,
+we will reverse black and white in the mouse cursor. This will make it
+more visible against a black background.
+
+Changing the cursor is another undocumented reason why we need to know
+about the tty's view window; nothing changes if we try to attach
+the new cursor to |frame| or to |tty| instead of to |window|.
+
+@<Change the cursor, to avoid black-on-black@>=
+if (rv) {Xv_singlecolor white,black;
+  Xv_cursor cursor;
+  white.red=white.green=white.blue=255;
+  black.red=black.green=black.blue=0;
+  cursor=(Xv_cursor)xv_create(NULL,CURSOR,@|
+    CURSOR_SRC_CHAR,OLC_BASIC_PTR,CURSOR_MASK_CHAR,OLC_BASIC_MASK_PTR,@|
+    CURSOR_FOREGROUND_COLOR,&white,CURSOR_BACKGROUND_COLOR,&black,NULL);
+  xv_set(window,WIN_CURSOR,cursor,NULL);
+}
+
+@ @<Include...@>=
+#include <xview/cursor.h> /* we're using the cursor package */
+
+@ What is the variable |rv| that was tested in the code above? Good question.
+We have to scan for \.{-rv} before |xv_init| looks at the command arguments.
+
+@<Scan the command line, setting |rv| nonzero if \.{-rv} is present@>=
+rv=0;
+{@+int k=argc;
+  while (--k>0) if (strcmp(argv[k],"-rv")==0 ||
+                     strcmp(argv[k],"-reverse")==0) rv=1;
+}
+
+@ @<Global...@>=
+int rv;
+
+@ We need to know the height and width of characters in the font, in order
+to convert mouse positions into coordinates that \.{emacs} will like.
+If the user has specified a font explicitly, the font will presumably have
+a fixed width for all characters; we can learn the relevant dimensions
+by calling |xv_get|. But if the user has not specified a font, the
+situation is trickier; |xv_get| will report the width of the default
+{\it non\/}-fixed-width font, and this will probably differ from the width of
+the actual fixed-width font the tty subwindow will choose.
+
+Curiously, if we call |xv_find(NULL,FONT,FONT_FAMILY,
+FONT_FAMILY_DEFAULT_FIXEDWIDTH,NULL)| {\it before\/} calling |xv_init|,
+without even doing anything with the result returned by |xv_find|,
+|xv_init| will not install any fonts specified on the command line.
+The trick we used for icons---installing the default gnu icon on the first
+call to |xv_create|---will therefore fail.
+
+Thus, we have to work around two distinct bugs in XView. The solution
+is to discover the effects of the user's command line after |xv_init|
+has acted and the frame has been set up; we can determine by brute force what
+font will go into the tty window. The program below works correctly
+even if the command line specifies \.{-scale} \.{large}, say, instead of
+specifying a new font explicitly by something like \.{-font} \.{9x15}.
+
+While we are cataloguing peculiarities of XView, we might as well mention
+that the default character dimensions of the default font (Lucida) are
+reported to be $8\times13$ in the 12-point (medium) size, $8\times15$ in the
+14-point (large) size, and $12\times20$ in the 19-point (extralarge) size.
+The actual character dimensions in the window come, however, from the
+default fixed-width font (Lucida typewriter), and they are $7\times13$,
+$9\times15$, and $11\times23$ in the same three sizes. No logical progression
+is evident in either the variable-width or the fixed-width dimensions,
+although Lucida is a ``scalable font family.''
+
+@<Compute the height and width of characters in the font@>=
+{
+  Xv_font font=(Xv_font)xv_get(frame,XV_FONT);
+  Xv_font dfont=(Xv_font)xv_find(NULL,FONT,FONT_FAMILY,
+     FONT_FAMILY_DEFAULT,NULL);
+  if (strcmp((char*)xv_get(font,FONT_NAME),
+             (char*)xv_get(dfont,FONT_NAME))==0) {
+    /* the user didn't specify a new font by name */
+    dfont=(Xv_font)xv_find(NULL,FONT,FONT_FAMILY,
+      FONT_FAMILY_DEFAULT_FIXEDWIDTH,NULL);
+        /* this one will be used by the tty window */
+  } else dfont=font;
+  char_width=(int)xv_get(dfont,FONT_DEFAULT_CHAR_WIDTH);
+  char_height=(int)xv_get(dfont,FONT_DEFAULT_CHAR_HEIGHT);
+}
+
+@ @<Global...@>=
+int char_width, char_height; /* character dimensions in the font */
+
+@ @<Include...@>=
+#include <xview/font.h> /* header for the font package */
+
+@ OK, we've figured out how to install a tty subwindow with the right
+event mask and the right cursor, and how to calculate the sizes of the
+characters it will contain. All that remains is for us to do these
+operations in the proper order, and to specify a filter routine that
+will monitor and edit all communications between the keyboard and the
+Emacs processor in the window.
+
+The new ingredient is the filter specification. We tell the XView
+notifier to call |filter| when a window event occurs, instead of
+letting it call the tty subroutine event handler directly. The parameter
+|NOTIFY_SAFE| implies that the window's event handler is
+part of XView, not an alien routine.
+
+@<Install the components...@>=
+@<Scan the command line, setting |rv| nonzero if \.{-rv} is present@>;
+xv_init(XV_INIT_ARGC_PTR_ARGV,&argc,argv,NULL);
+      /* start XViewing; strip and remember the OpenWin arguments */
+@<Create a frame with the gnu icon@>;
+@<Remove the frame header...@>;
+@<Put a tty subwindow into the frame@>;
+@<Prepare to be notified when the mouse enters the window@>;
+@<Change the cursor, to avoid black-on-black@>;
+@<Compute the height and width of characters in the font@>;
+notify_interpose_event_func(window,filter,NOTIFY_SAFE);
+
+@* Keyboard events.
+The job of an interposed filter function is to look at an event and
+either process it ourselves or pass it through (possibly modified)
+to its normal recipient. In the first case we return the code
+value |NOTIFY_DONE|, since we aren't reporting any errors;
+in the second case we call the normal event handler and return the value
+it returns to us.
+
+An XView event is a data structure that has been partially
+interpreted by the XView routines, which add semantic sugar to
+the complex union type of X~Window events. We need not look
+too far inside an event structure to do the things that concern us.
+
+And what is our job? We are looking for three different kinds of events:
+
+\smallskip
+\itemitem{(1)} When the mouse enters the window,
+we want to grab the keyboard focus.
+
+\itemitem{(2)} When a mouse button goes up or down, and we have the keyboard
+focus, we want to send a coded sequence of characters to \.{emacs}.
+
+\itemitem{(3)} When a key goes down, and we have the keyboard focus, we
+want to send an appropriate sequence of characters to \.{emacs}.
+
+\itemitem{(4)} When the status of the Num Lock indicator light changes, we
+will send emacs the command {\tt turn-numlock-on} or {\tt turn-numlock-off},
+for reasons described below.
+
+\smallskip\noindent Other events, like instructions to repaint or
+resize the window, will be passed through without change to the tty window.
+
+@<Event-handling...@>=
+Notify_value filter(window,event,arg,type)
+  Xv_window window; /* the ``client'' on whom we interposed */
+  Event *event; /* the data we are filtering */
+  Notify_arg arg; /* optional communication parameter between clients */
+  Notify_event_type type; /* |NOTIFY_SAFE| or |NOTIFY_IMMEDIATE| */
+{@+register int id=event_id(event);
+#ifdef DEBUG
+  printf("event %d%s, action %d, shift %x, mouse(%d,%d)\n",
+    event_id(event),event_is_up(event)?"UP":"DOWN",event->action,
+         event_shiftmask(event),event_x(event),event_y(event));
+#endif
+  @<Update the Num Lock status@>;
+  if (id==LOC_WINENTER) @<Grab the keyboard focus and return@>;
+  if (event_is_button(event)) @<Translate a mouse event and return@>;
+  if (event_is_up(event)) return NOTIFY_DONE; /* key has been released */
+  @<Translate a function key into a special escape sequence@>;
+  @<Sanitize a keypress event so that unusual semantic actions are removed@>;
+  return notify_next_event_func(window,event,arg,type); /* pass it through */
+}
+
+@ It's easy to take charge of the keyboard and mouse, as soon as the mouse
+enters our territory.
+
+@<Grab...@>=
+{
+  win_set_kbd_focus(window,xv_get(window,XV_XID));
+  return NOTIFY_DONE;
+}
+
+@ If the event is not related to mouse buttons or special function keys,
+we want to pass it on unchanged, unless its |event_id| is less than 128.
+In that case, it represents a character code, and we want to nuke any
+semantic ``keyboard acceleration'' actions it might have been assigned
+by OpenWindows.
+
+We also make the Meta key add 128 here. An undocumented macro
+called |event_set_id|, found in \.{<xview/win\_input.h>},
+clears the |action| code as desired.
+
+@<Sanitize...@>=
+if (id<128)
+  if (event_meta_is_down(event)) event_set_id(event,id+128);
+  else event_set_action(event,ACTION_NULL_EVENT);
+
+@* Function keys.
+The Sun Type 4 keyboard has lots of keys, and these can be bound to lots
+of useful functions when we are \.{emacs}ing to the max. Besides the
+letters and punctuation marks of a normal typewriter, there are ten
+``left'' function keys, L1--L10; twelve ``top'' function keys, F1--F12;
+fifteen ``right'' function keys, R1--R15; and eight additional keys
+labeled Help, Alt, AltGraph, Ins, Del, Enter, $+$, $-$, which we will
+pretend have been labeled B1--B8.
+
+The L5 key, also known as Front, is controlled by the Open Look
+window manager; it makes a window rise above any that might overlap it,
+or shoves the window underneath in case it already was on top.
+
+The L7 key, aka Open, is likewise preempted by the
+window manager. It closes a frame to an icon, or opens an icon.
+
+The window manager traps the R2 key and calls it the ``language'' key;
+but I have no use for that feature. So I have remapped R2 to the comparatively
+useless character $3\over4$, and I will translate it back to R2 below. (The
+\.{xmodmap} program allows users to reassign the interpretation of key codes.)
+I could have recovered the L5 and L7 keys in the same way, but I like
+their functions as they stand. (L5 and L7 still come through if a
+Shift, Control, and/or Meta key is down.)
+
+I can never remember the difference between Delete and BackSpace, so I
+have mapped them both into control-?, ASCII code 127.
+
+There are two Shift keys, one at the left and one at the right, which
+are best kept indistinguishable from each other. Similarly, the left
+and right Meta keys (`\.{\char27}') are essentially identical. There's a
+Control key too. These three types of modifier keys generate keypress
+events, but we ignore them; the only thing that matters to us is whether
+they are currently up or down, when other keys are pressed.
+
+\font\ttit=cmitt10
+There also are three special keys that do not generate events, so we
+never see them. The CapsLock key toggles the Caps Lock light and
+changes lowercase letters to uppercase when the light is on. The
+NumLock key toggles the Num Lock light and changes the interpretation
+of R4--R15 and B4--B8 when that light is on. The Compose key turns the
+Compose light on until you type two characters, then it produces a
+special symbol if those two characters match a pattern. For example,
+when Compose is followed by either \.{a"} or \.{"a} you get the 8-bit
+ISO code for {\tt \"a}; when Compose is followed by either \.{th} or
+\.{ht} you get the Icelandic thorn; when it's followed by \.{??} you get {\tt
+?`}; \.{c/} and \.{L-} give \rlap{\./}\.c and {\ttit\char`\$}
+and so on. (A list of all composition patterns
+appears in \.{<X11/Suncompose.h>}, but not in any of the manuals
+I've seen.) The light goes off after two characters have been
+typed, or if your first character is not composable, or if
+you hit Compose again prematurely. If no proper two-character pattern
+was specified, only ``up'' events (key releases) are transmitted, and
+nothing will pass through to \.{emacs}.
+
+One other feature is worth noting: The key between F12 and Delete
+produces a backslash `\.\\', or a vertical line `\.{\char125}' when
+shifted.  Everybody knows that, but even more is true. If you hold the
+AltGraph key down and press this key, it turns out that you get the
+broken-bar character `{\tt\hbox to1em{\hss\vbox{\hrule width 1pt height
+3pt\vskip1.5pt\hrule height2pt depth1pt}\hss}}'.  This is the only key that the
+engineers chose to endow with three different graphic symbols.
+
+A few other anomalies occur; for example, AltGraph-R1 gives ASCII null,
+while AltGraph does not affect R4. But I didn't discover any additional
+combinations that are either useful or harmful.
+
+Once upon a time the Caps Lock key might have affected the |event_shiftmask|
+field of an event, but it has no effect now. The shiftmask is always an
+even number, contrary to the implications of \.{<xview/win\_input.h>}.
+
+@ The function keys will be translated into a four-character code.
+First comes control-X; then an asterisk; then a letter, \.{a}--\.{o}
+for function numbers 1--15, respectively; and then another letter,
+identifying left, right, top, or bottom. The final letter is
+ordinarily `\.l', `\.r', `\.t', or `\.b', respectively. But it is `\.L', `\.R',
+`\.T', or `\.B' if a Shift key is down. Furthermore the Control key
+subtracts 64 from the ASCII code, so you get `\.,', `\.2', `\.4', or
+`\."' with Control and no Shift. With both Control and Shift you get
+\.{\\C-L}, \.{\\C-R}, \.{\\C-T}, \.{\\C-B}. A Meta key adds another 128
+to the code.  Thus, each function key leads to eight possibilities.
+
+For example, if F4 is pressed when Control and Shift are down, but not
+Meta, the four-letter code is \.{\\C-X*d\\C-T}. The user could type
+that sequence of four characters and get the same effect.
+
+Shifted function keys sometimes have a nice mnemonic significance.
+For example, key R14, also labeled PgDn, is usually bound to the Emacs
+operation `\.{scroll-up}', which moves the window down [sic] by one
+screenful; we can then bind Shift-R14 to \.{forward-page}, which advances
+down to the next page boundary. In \.{cweb-mode}, the next page boundary
+is the next \.{@@*}, beginning a major part of the program. Similarly,
+it's convenient to bind B7, the keypad `\.+' key, to \.{forward-paragraph}.
+Then in \.{cweb-mode}, Shift-B7 goes to the next module (the next
+\.{@@\ } or \.{@@*}).
+
+A Composed character will be preceded by \.{\\C-Q}, the Emacs `quote'
+character, to distinguish it from a character that was generated with the
+Meta key down. This also applies to the broken-bar character, which
+will incidentally be preceded by AltGraph, which is B3; you'll probably
+want to bind B3 to a no-op if broken bars are important to you.
+
+@ This program assumes that several key codes have been rebound from
+their normal values. Namely, the commands
+$$\vbox{\halign{\.{#}\hfil\cr
+keysym R2 = threequarters\cr
+keysym KP\_Subtract = onehalf\cr
+keysym KP\_Add = onequarter\cr
+keysym KP\_Enter = threesuperior\cr
+keysym KP\_Decimal = twosuperior\cr
+keysym KP\_0 = onesuperior\cr}}$$
+should be executed by \.{xmodmap}, preferably in the user's \.{.xinitrc} file.
+This makes the keys act as $3\over4$, $1\over2$, $1\over4$, $^3$, $^2$, and
+$^1$, respectively. The corresponding 8-bit codes are respectively
+190, 189, 188, 179, 178, 185. (By the way, can anybody explain why the ISO
+LATIN-1 code has $^0$, $^2$, and $^3$ in the positions of meta-0, meta-2,
+and meta-3, while $^1$ is in the position of meta-9?)
+ at .xmodmap@>
+
+We haven't actually bound the keys this way to use them in editing.
+We did it to provide linguistically unimportant codes that OpenWindows
+wouldn't mess up; its normal conventions make those valuable keys
+unusable for editing, except as duplicates for other existing keys.
+
+We send \.{turn-numlock-on/off} commands so that \.{emacs} can keep in
+synch with the keyboard state. Namely, it will rebind the function
+keys B4--B8 to their numeric-keypad equivalents while the Num Lock light is on.
+
+On the other hand, our remapping does make the Num Lock
+feature useless in other (non-Emacs) applications.  If you don't
+rebind the keys as stated, you lose the functionality of R2 and B4--B8,
+but \.{oemacs} will still work.
+
+The Help key is another special case. We don't want to remap it,
+because it gives useful help information with other OpenWindows
+applications.  If Help is pressed without the shift or control key,
+the |event_id| is zero and the |event_action| is |ACTION_HELP|.
+Control-Help is similar, but with |ACTION_TEXT_HELP|. Shift-Help is
+more complicated; it invokes `helpopen: starting new Viewer', after
+generating an event that has |event_action=WIN_VISIBILITY_NOTIFY|. The
+program below considers the Help key B1 to be characterized by any
+event with |event_id=0| and either |event_action!=0| or
+|event_shiftmask!=CTRLMASK|.
+
+@<Translate a function key into a special escape sequence@>=
+{@+register int bank='b'; /* |'l'|, |'r'|, |'t'|, or |'b'| */
+  register int n; /* function key serial number, |1<=n<=15| */
+  if (id>=KEY_LEFT(1)) @<Translate an ordinary function key@>@;
+  else if (id>=256) @<Look for Alt or AltGraph@>@;
+  else if (id>=128)
+    @<Translate a special function key or composed character@>@;
+  else if (id>0 ||
+          (event_action(event)==0 && event_shiftmask(event)==CTRLMASK))
+    goto non_function;
+  else n=1; /* Help key */
+emit_function_key:@<Emit the code for a function key and |return|@>;
+non_function:;
+}
+
+@ I'm assuming here that the event id codes occur in the order left, right,
+top, bottom, and that no higher event codes exist.
+
+@<Translate an ordinary function key@>=
+{
+  if (id<KEY_RIGHT(1)) { /* on the left bank */
+    bank='l';@+n=id-KEY_LEFT(0);
+  } else if (id<KEY_TOP(1)) { /* on the right bank */
+    bank='r';@+n=id-KEY_RIGHT(0);
+  } else if (id<KEY_BOTTOM(1)) {
+    bank='t';@+n=id-KEY_TOP(0);
+  } else n=id-KEY_BOTTOM(0);
+  goto emit_function_key;
+}
+
+@ The event codes examined here appear in \.{<xview/win\_event.h>}
+but not in the XView reference manual.
+
+@<Look for Alt or AltGraph@>=
+if (id==SHIFT_ALT) {
+  n=2;@+goto emit_function_key;
+} else if (id==SHIFT_ALTG) {
+  n=3;@+goto emit_function_key;
+} else goto non_function;
+
+@ The |ttysw_input| routine sends text to a tty's view window.
+The second parameter is a string, not necessarily terminated by
+|'\0'| or anything else; the third parameter is the string length.
+
+@<Emit the code for a function key and |return|@>=
+{
+  if (event_shift_is_down(event)) bank-=32;
+  if (event_ctrl_is_down(event)) bank-=64;
+  if (event_meta_is_down(event)) bank+=128;
+  buf[2]=n+'a'-1;
+  buf[3]=bank;
+  ttysw_input(window,buf,4);
+  return NOTIFY_DONE;
+}
+
+@ @<Global...@>=
+char buf[]="\030*??\021"; /* |030| and |021| give control-X, control-Q */
+
+@ @<Translate a special function key or composed character@>=
+switch (id) {
+case 190: bank='r';@+n=2;@+goto emit_function_key;
+case 189: n=8;@+goto emit_function_key;
+case 188: n=7;@+goto emit_function_key;
+case 179: n=6;@+goto emit_function_key;
+case 178: n=5;@+goto emit_function_key;
+case 185: n=4;@+goto emit_function_key;
+default: buf[5]=id; /* composed character or broken-bar */
+  ttysw_input(window,buf+4,2);
+  return NOTIFY_DONE;
+}
+
+@* The NumLock key.
+The global variable |num_lock_state| will be 0 if the Num Lock indicator
+light is off, 1 if it is on. Whenever an event occurs, we check to see
+if |num_lock_state| should change; if so, we change it and send an
+appropriate command to \.{emacs}.
+
+To read the state of the keyboard LED indicator lights, we need an I/O
+control command called the |KIOCGLED| ioctl, described on the
+man page for \.{kb(4m)}.
+
+@<Global...@>=
+int num_lock_state;
+char turnon[]="\370turn-numlock-on\r", turnoff[]="\370turn-numlock-off\r";
+int keyboard; /* file descriptor of \.{/dev/kbd} */
+
+@ @<Include...@>=
+#include <sys/file.h> /* definition of |O_RDWR| for |open| */
+#include <sundev/kbio.h> /* definition of |KIOCGLED| for |ioctl| */
+
+@ @d LED_NUM_LOCK 0x1 /* the official definition is in \.{<server/sunevq.h>},
+    but that header file includes huge gobs of other stuff */
+
+@<Update the Num Lock status@>=
+{@+char leds; /* binary encoding of LED lights */
+  ioctl(keyboard,KIOCGLED,&leds);
+  if ((leds&LED_NUM_LOCK)!=num_lock_state) {
+    num_lock_state=leds&LED_NUM_LOCK;
+    if (num_lock_state) ttysw_input(window,turnon,17);
+    else ttysw_input(window,turnoff,18);
+  }
+}
+
+@ Any ordinary user can apparently open the keyboard as a file. I would
+have tried read-only access if read-write had failed; but read-write access
+gives a sense of power even though I won't be writing anything.
+
+@<Special initialization@>=
+keyboard=open("/dev/kbd",O_RDWR);
+if (keyboard<0) {
+  fprintf(stderr,"%s: Can't open /dev/kbd!\n",argv[0]);
+  exit(1);
+}
+
+@* Mouse events.
+When a mouse button is pressed or released, we send \.{emacs} the
+codes control-X and ASCII null, followed by a parenthesized list
+of four numbers and carriage-return.
+For example, as I was typing this paragraph, I
+clicked the left mouse button on the screen just for fun; \.{emacs}
+received the characters
+$$\.{\\030\\0(1 18 28 9999)\\r\\030\\0(129 18 28 141)\\r}$$
+as a result (according to `\.{view-lossage}'). I would have received
+the same response if I had typed these characters myself, instead
+of clicking the mouse.
+
+The first of the four numbers identifies the mouse button itself
+as the code number 1, 2, or 4 (for left, middle, right), plus 8 if
+a Shift key is down, plus 16 if the Control key is down, plus 32
+if a Meta key is down, plus 128 if the mouse key is being released
+instead of pressed.
+
+The second number is the row number in the frame, the top row being
+considered row~0.
+
+The third number is the column number in the frame, the left column being
+considered column~0.
+
+The fourth number is the elapsed time between this mouse event and the
+previous one, in milliseconds. If the elapsed time was 10 seconds or
+more, 9999 is substituted.
+
+Macros inside \.{emacs} can use the second and third numbers to
+position the cursor. The fourth number can be used to determine if the
+user is ``double clicking'' or using ``chords.'' Examples of such
+macros appear in the Emacs source file \.{lisp/sun-mouse.el}.
+
+Incidentally, the ASCII null character in mouse sequence makes us happy that
+the string parameter to |ttysw_input| is not null-terminated.
+
+@<Translate a mouse event...@>=
+{@+register int button_code,elapsed_time;
+  button_code=(id==MS_LEFT? 1: id==MS_MIDDLE? 2: 4);
+  if (event_shift_is_down(event)) button_code += 8;
+  if (event_ctrl_is_down(event)) button_code += 16;
+  if (event_meta_is_down(event)) button_code += 32;
+  if (event_is_up(event)) button_code += 128;
+  @<Compute the time elapsed since the previous mouse event@>;
+  sprintf(mouse_buf+2,"(%d %d %d %d)\r",button_code,@|
+      event_x(event)/char_width, event_y(event)/char_height,@|
+      elapsed_time);
+  ttysw_input(window,mouse_buf,12+strlen(mouse_buf+12)); /* length is at least 12 */
+  return NOTIFY_DONE;
+}
+
+@ @<Global...@>=
+char mouse_buf[24]="\030";
+
+@ XView's event structure includes |event_time(event)|, which has
+type |struct timeval|; this data type is declared in \.{<sys/time.h>},
+which is one of the files included automatically as a result of
+including \.{<xview/xview.h>}.
+A |timeval| structure consists of two |long| integers, |tv_sec| and |tv_usec|,
+denoting clock time in seconds and microseconds, respectively.
+
+@<Compute the time...@>=
+{@+struct timeval now; /* current time */
+  long delta_sec, delta_usec; /* difference between current and
+                                 previous time */
+  now=event_time(event);
+  delta_sec=now.tv_sec-prev_mouse_time.tv_sec;
+  delta_usec=now.tv_usec-prev_mouse_time.tv_usec;
+  if (delta_usec<0) delta_usec+=1000000,delta_sec--;
+  if (delta_sec>=10) elapsed_time=9999; /* infinity (or close enough) */
+  else elapsed_time=(delta_sec*1000)+(delta_usec/1000);
+  prev_mouse_time=now;
+}
+
+@ @<Global...@>=
+struct timeval prev_mouse_time;
+
+@* Remaining problems. There's a terribly unfortunate bug in the
+present implementation of XView, causing characters of tty subwindows
+to be badly painted at crucial times; the rightmost column of pixels
+in a character is often clobbered. If I could figure out how to
+generate repaint events for the tty subwindow, I might build a mechanism
+into \.{oemacs} that does this after the keyboard has been idle for 10
+seconds, say.  This would blink the screen; maybe I'll get used to that,
+or maybe I'll prefer to refresh the window manually by binding
+\.{redraw-display} to the L2 and R1 keys.  In any case a lot of screen
+refreshing is necessary at the moment, alas.
+
+(Note added later: I doubt if I'll get used to blinking, and the present
+method of manual refresh is tolerable so I won't pursue the 10-second
+timer idea. I have meanwhile noticed a procedure |wmgr_refreshwindow(window)|
+mentioned in \.{<xview/wmgr.h>}; it will presumably refresh any
+given window.
+
+Another bug, much less serious, occurs when the window is resized.
+If the window gets smaller, \.{emacs} isn't told to correct its
+assumptions; so it puts information in strange places or offscreen.
+(Internally, emacs uses the \.{TIOCGWINSZ} or \.{TIOCSWINSZ} ioctl,
+described in the man page for \.{termio}.)
+You can work around this by first making the window very small, then
+making it large.
+
+@* Index.
+
+


Property changes on: trunk/Build/source/texk/web2c/cwebdir/examples/oemacs.w
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/texk/web2c/cwebdir/examples/treeprint.w
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/examples/treeprint.w	                        (rev 0)
+++ trunk/Build/source/texk/web2c/cwebdir/examples/treeprint.w	2018-12-30 18:59:26 UTC (rev 49537)
@@ -0,0 +1,248 @@
+\def\covernote{Copyright 1987 Norman Ramsey -- Princeton University}
+
+\def\vbar{\.{|}}
+@*Directory Trees.
+Our object is to print out a directory hierarchy in some pleasant way.
+The program takes output from {\tt find * -type d -print \vbar\ sort}
+@^system dependencies@>
+and produces a nicer-looking listing.
+More precisely, our input, which is the output of {\tt find} followed
+by {\tt sort}, is a list of fully qualified directory names (parent
+and child separated by slashes |'/'|); everything has already been
+sorted nicely into lexicographic order.
+
+The {\tt treeprint} routine takes one option, |"-p"|, which tells it
+to use the printer's line-drawing set, rather than the terminal's.
+
+ at c
+@<Global definitions@>@;
+@<Global include files@>@;
+@<Global declarations@>@;
+
+@#
+main(argc, argv)
+     int argc;
+     char **argv;
+{
+@<|main| variable declarations@>;
+@<Search for options and set special characters on |"-p"|@>;
+@<Read output from find and enter into tree@>;
+@<Write tree on standard output@>@;
+exit(0);
+}
+
+@
+We make all the siblings of a directory a linked list off of its left child, 
+and the offspring a linked list off the right side.
+Data are just directory names.
+ at d sibling left
+ at d child right
+
+@<Global decl...@>=
+typedef struct tnode {
+  struct tnode *left, *right;
+  char *data;
+} TNODE;
+@ @<|main| variable...@>=
+struct tnode *root=NULL;
+
+
+
+@*Input.
+Reading the tree is simple---we read one line at a time, and call on the 
+recursive |add_tree| procedure.
+
+ at c
+read_tree (fp, rootptr)
+   FILE *fp;
+   struct tnode **rootptr;
+{
+   char buf[255], *p;
+
+   while ((fgets(buf, 255, fp))!=NULL) {
+     @<If |buf| contains a newline, make it end there@>;
+     add_tree(rootptr, buf);
+   }
+ }
+@ @<Global include...@>=
+#include <stdio.h>
+
+@ Depending what system you're on, you may or may not get a newline in |buf|.
+@<If |buf| contains a newline...@>=
+     p=buf; while (*p!='\0'&&*p!='\n') p++;
+@^system dependencies@>
+     *p='\0';
+
+@ 
+To add a string, we split off the first part of the name and insert it into 
+the sibling list. We then do the rest of the string as a child of the new node.
+
+ at c
+add_tree(rootptr, p)
+     struct tnode **rootptr;
+     char *p;
+{
+     char *s;
+     int slashed;
+
+     if (*p=='\0') return;
+
+@<Break up the string so |p| is the first word,
+     |s| points at null-begun remainder,
+    and |slashed| tells whether |*s=='/'| on entry@>;
+
+     if (*rootptr==NULL) {
+@<Allocate new node to hold string of size |strlen(p)|@>;
+       strcpy((*rootptr)->data,p);
+     } 
+     if (strcmp((*rootptr)->data,p)==0) {
+           if (slashed) ++s;
+           add_tree(&((*rootptr)->child),s);
+	 }
+       else {
+           if (slashed) *s='/';
+           add_tree(&((*rootptr)->sibling),p);
+	 }
+   }
+
+@ We perform some nonsense to cut off the string |p| so that |p| just
+holds the first word of a multiword name. Variable |s| points at what
+was either the end of |p| or a slash delimiting names. In either case
+|*s| is made |'\0'|.  Later, depending on whether we want to pass the
+whole string or the last piece, we will restore the slash or advance
+|s| one character to the right.
+
+@<Break up...@>=
+     for (s=p;*s!='\0'&&*s!='/';) s++;
+     if (*s=='/') {
+       slashed=1;
+       *s='\0';
+     } else slashed=0;
+
+@ Node allocation is perfectly standard \dots
+@<Allocate new node...@>=
+       *rootptr=(struct tnode *) malloc (sizeof(struct tnode));
+       (*rootptr)->left = (*rootptr)->right = NULL;
+       (*rootptr)->data = malloc (strlen(p)+1);
+
+@
+@<Global decl...@>= char *malloc();
+
+@ In this simple implementation, we just read from standard input.
+@<Read...@>= read_tree(stdin,&root);
+
+@*Output.
+We begin by defining some lines, tees, and corners.
+The |s| stands for screen and the |p| for printer.
+You will have to change this for your line-drawing set.
+@^system dependencies@>
+
+@<Global definitions@>=
+#define svert '|'
+#define shoriz '-'
+#define scross '+'
+#define scorner '\\' /* lower left corner */
+
+#define pvert '|'
+#define phoriz '-'
+#define pcross '+'
+#define pcorner '\\' /* lower left corner */
+
+@ The default is to use the terminal's line drawing set.
+@<Global declarations@>=
+char vert=svert;
+char horiz=shoriz;
+char cross=scross;
+char corner=scorner;
+
+@ With option |"-p"| use the printer character set.
+@<Search for options...@>=
+while (--argc>0) {
+  if (**++argv=='-') {
+    switch (*++(*argv)) {
+      case 'p': 
+        vert=pvert;
+        horiz=phoriz;
+        cross=pcross;
+        corner=pcorner;
+	break;
+      default:
+        fprintf(stderr,"treeprint: bad option -%c\n",**argv);
+	break;
+      }
+  }
+}
+
+@ We play games with a character stack to figure out when to put in vertical
+bars.
+A vertical bar connects every sibling with its successor, but the last sibling
+in a list is followed by blanks, not by vertical bars. The state of 
+bar-ness or space-ness for each preceding sibling is recorded in the 
+|indent_string| variable, one character (bar or blank) per sibling.
+
+@<Global decl...@>=
+char indent_string[100]="";
+
+@  Children get printed 
+before siblings.
+We don't bother trying to bring children up to the same line as their parents,
+because the \UNIX/ filenames are so long.
+
+We define a predicate telling us when a sibling is the last in a series.
+ at d is_last(S) (S->sibling==NULL)
+
+ at c
+print_node(fp, indent_string, node)
+     FILE *fp;
+     char *indent_string;
+     struct tnode *node;
+{
+  char string[255];
+     int i;
+     char *p, *is;
+
+  if (node==NULL) {
+  }
+  else {
+    *string='\0';
+    for (i=strlen(indent_string); i>0; i--) 
+      strcat(string,@,      " |  ");
+    strcat(string, at t\ \ @>  " +--");
+@<Replace chars in |string| with chars from 
+         line-drawing set and from |indent_string|@>;
+    fprintf(fp,"%s%s\n",string,node->data);
+
+@#
+    /* Add vertical bar or space for this sibling (claim |*is=='\0'|) */
+    *is++ = (is_last(node) ? ' ' : vert);
+    *is='\0';
+   
+    print_node(fp, indent_string, node->child); /* extended |indent_string| */
+    *--is='\0';
+    print_node(fp, indent_string, node->sibling); /* original |indent_string| */
+  }
+
+}
+@ For simplicity, we originally wrote connecting lines with |'|'|, |'+'|, and
+|'-'|.
+Now we replace those characters with appropriate characters from the 
+line-drawing set. 
+We take the early vertical bars and replace them with characters from
+|indent_string|, and we replace the other characters appropriately.
+We are sure to put a |corner|, not a |cross|, on the last sibling in 
+a group.
+@<Replace chars...@>=
+    is=indent_string;
+    for (p=string; *p!='\0'; p++) switch(*p) {
+       case '|': *p=*is++; break;
+       case '+': *p=(is_last(node) ? corner : cross); break;
+       case '-': *p=horiz; break;
+       default: break;
+	       }
+
+
+@ For this simple implementation, we just write on standard output.
+
+@<Write...@>= print_node(stdout, indent_string, root);
+
+@*Index.


Property changes on: trunk/Build/source/texk/web2c/cwebdir/examples/treeprint.w
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/texk/web2c/cwebdir/examples/wc-dos.ch
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/examples/wc-dos.ch	                        (rev 0)
+++ trunk/Build/source/texk/web2c/cwebdir/examples/wc-dos.ch	2018-12-30 18:59:26 UTC (rev 49537)
@@ -0,0 +1,8 @@
+% from j.fitzsimons at genie.geis.com who compiled with Top Speed C
+% April 1995
+
+ at x
+ at d buf_size BUFSIZ /* \.{stdio.h}'s |BUFSIZ| is chosen for efficiency*/
+ at y
+ at d buf_size 2048 /* \.{stdio.h}'s |BUFSIZ| breaks DOS */
+ at z


Property changes on: trunk/Build/source/texk/web2c/cwebdir/examples/wc-dos.ch
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/texk/web2c/cwebdir/examples/wc.w
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/examples/wc.w	                        (rev 0)
+++ trunk/Build/source/texk/web2c/cwebdir/examples/wc.w	2018-12-30 18:59:26 UTC (rev 49537)
@@ -0,0 +1,254 @@
+% wc: An example of CWEB by Silvio Levy and Donald E. Knuth
+
+\nocon % omit table of contents
+\datethis % print date on listing
+\def\SPARC{SPARC\-\kern.1em station}
+
+@* An example of {\tt CWEB}.  This example, based on a program by
+Klaus Guntermann and Joachim Schrod [{\sl TUGboat\/ \bf7} (1986),
+134--137] presents the ``word count'' program from \UNIX/, rewritten in
+\.{CWEB} to demonstrate literate programming in \CEE/.  The level of
+detail in this document is intentionally high, for didactic purposes;
+many of the things spelled out here don't need to be explained in
+other programs.
+
+The purpose of \.{wc} is to count lines, words, and/or characters in a
+list of files. The number of lines in a file is the number of newline
+characters it contains. The number of characters is the file length in bytes.
+A ``word'' is a maximal sequence of consecutive characters other than
+newline, space, or tab, containing at least one visible ASCII code.
+(We assume that the standard ASCII code is in use.)
+
+This version of \.{wc} has a nonstandard ``silent'' option (\.{-s}),
+which suppresses printing except for the grand totals over all files.
+
+@ Most \.{CWEB} programs share a common structure.  It's probably a
+good idea to state the overall structure explicitly at the outset,
+even though the various parts could all be introduced in unnamed
+sections of the code if we wanted to add them piecemeal.
+
+Here, then, is an overview of the file \.{wc.c} that is defined
+by this \.{CWEB} program \.{wc.w}:
+
+ at c
+@<Header files to include@>@/
+@<Global variables@>@/
+@<Functions@>@/
+@<The main program@>
+
+@ We must include the standard I/O definitions, since we want to send
+formatted output to |stdout| and |stderr|.
+
+@<Header files...@>=
+#include <stdio.h>
+
+@  The |status| variable will tell the operating system if the run was
+successful or not, and |prog_name| is used in case there's an error message to
+be printed.
+
+ at d OK 0 /* |status| code for successful run */
+ at d usage_error 1 /* |status| code for improper syntax */
+ at d cannot_open_file 2 /* |status| code for file access error */
+
+@<Global variables@>=
+int status=OK; /* exit status of command, initially |OK| */
+char *prog_name; /* who we are */
+
+@ Now we come to the general layout of the |main| function. 
+
+@<The main...@>=
+main (argc,argv)
+    int argc; /* the number of arguments on the \UNIX/ command line */
+    char **argv; /* the arguments themselves, an array of strings */
+{
+  @<Variables local to |main|@>@;
+  prog_name=argv[0];
+  @<Set up option selection@>;
+  @<Process all the files@>;
+  @<Print the grand totals if there were multiple files @>;
+  exit(status);
+}
+
+@ If the first argument begins with a `\.{-}', the user is choosing
+the desired counts and specifying the order in which they should be
+displayed.  Each selection is given by the initial character
+(lines, words, or characters).  For example, `\.{-cl}' would cause
+just the number of characters and the number of lines to be printed,
+in that order. The default, if no special argument is given, is `\.{-lwc}'.
+
+We do not process this string now; we simply remember where it is.
+It will be used to control the formatting at output time.
+
+If the `\.{-}' is immediately followed by `\.{s}', only summary totals
+are printed.
+
+@<Var...@>=
+int file_count; /* how many files there are */
+char *which; /* which counts to print */
+int silent=0; /* nonzero if the silent option was selected */
+
+@ @<Set up o...@>=
+which="lwc"; /* if no option is given, print all three values */
+if (argc>1 && *argv[1] == '-') {
+  argv[1]++;
+  if (*argv[1]=='s') silent=1,argv[1]++;
+  if (*argv[1]) which=argv[1];
+  argc--; argv++;
+}
+file_count=argc-1;
+
+@ Now we scan the remaining arguments and try to open a file, if
+possible.  The file is processed and its statistics are given.
+We use a |do|~\dots~|while| loop because we should read from the
+standard input if no file name is given.
+
+@<Process...@>=
+argc--;
+do at +{
+  @<If a file is given, try to open |*(++argv)|; |continue| if unsuccessful@>;
+  @<Initialize pointers and counters@>;
+  @<Scan file@>;
+  @<Write statistics for file@>;
+  @<Close file@>;
+  @<Update grand totals@>; /* even if there is only one file */
+}@+while (--argc>0);
+
+@ Here's the code to open the file.  A special trick allows us to
+handle input from |stdin| when no name is given.
+Recall that the file descriptor to |stdin| is~0; that's what we
+use as the default initial value.
+
+@<Variabl...@>=
+int fd=0; /* file descriptor, initialized to |stdin| */
+
+@ @d READ_ONLY 0 /* read access code for system |open| routine */
+
+@<If a file...@>=
+if (file_count>0 && (fd=open(*(++argv),READ_ONLY))<0) {
+  fprintf (stderr, "%s: cannot open file %s\n", prog_name, *argv);
+ at .cannot open file@>
+  status|=cannot_open_file;
+  file_count--;
+  continue;
+}
+
+@ @<Close file@>=
+close(fd);
+
+@ We will do some homemade buffering in order to speed things up: Characters
+will be read into the |buffer| array before we process them.
+To do this we set up appropriate pointers and counters.
+
+ at d buf_size BUFSIZ /* \.{stdio.h}'s |BUFSIZ| is chosen for efficiency*/
+
+@<Var...@>=
+char buffer[buf_size]; /* we read the input into this array */
+register char *ptr; /* the first unprocessed character in |buffer| */
+register char *buf_end; /* the first unused position in |buffer| */
+register int c; /* current character, or number of characters just read */
+int in_word; /* are we within a word? */
+long word_count, line_count, char_count; /* number of words, lines, 
+    and characters found in the file so far */
+
+@ @<Init...@>=
+ptr=buf_end=buffer; line_count=word_count=char_count=0; in_word=0;
+
+@ The grand totals must be initialized to zero at the beginning of the
+program. If we made these variables local to |main|, we would have to
+do this initialization explicitly; however, \CEE/'s globals are automatically
+zeroed. (Or rather, ``statically zeroed.'') (Get it?)
+@^Joke@>
+
+@<Global var...@>=
+long tot_word_count, tot_line_count, tot_char_count;
+ /* total number of words, lines, and chars */
+
+@ The present section, which does the counting that is \.{wc}'s {\it raison
+d'\^etre}, was actually one of the simplest to write. We look at each
+character and change state if it begins or ends a word.
+
+@<Scan...@>=
+while (1) {
+  @<Fill |buffer| if it is empty; |break| at end of file@>;
+  c=*ptr++;
+  if (c>' ' && c<0177) { /* visible ASCII codes */
+    if (!in_word) {word_count++; in_word=1;}
+    continue;
+  }
+  if (c=='\n') line_count++;
+  else if (c!=' ' && c!='\t') continue;
+  in_word=0; /* |c| is newline, space, or tab */
+}
+
+@ Buffered I/O allows us to count the number of characters almost for free.
+
+@<Fill |buff...@>=
+if (ptr>=buf_end) {
+  ptr=buffer; c=read(fd,ptr,buf_size);
+  if (c<=0) break;
+  char_count+=c; buf_end=buffer+c;
+}
+
+@ It's convenient to output the statistics by defining a new function
+|wc_print|; then the same function can be used for the totals.
+Additionally we must decide here if we know the name of the file
+we have processed or if it was just |stdin|.
+
+@<Write...@>=
+if (!silent) {
+  wc_print(which, char_count, word_count, line_count);
+  if (file_count) printf (" %s\n", *argv); /* not |stdin| */
+  else printf ("\n"); /* |stdin| */
+}
+
+@ @<Upda...@>=
+tot_line_count+=line_count;
+tot_word_count+=word_count;
+tot_char_count+=char_count;
+
+@ We might as well improve a bit on \UNIX/'s \.{wc} by displaying the
+number of files too.
+
+@<Print the...@>=
+if (file_count>1 || silent) {
+  wc_print(which, tot_char_count, tot_word_count, tot_line_count);
+  if (!file_count) printf("\n");
+  else printf(" total in %d file%s\n",file_count,file_count>1?"s":"");
+}
+
+@ Here now is the function that prints the values according to the
+specified options.  The calling routine is supposed to supply a
+newline. If an invalid option character is found we inform
+the user about proper usage of the command. Counts are printed in
+8-digit fields so that they will line up in columns.
+
+ at d print_count(n) printf("%8ld",n)
+
+@<Fun...@>=
+wc_print(which, char_count, word_count, line_count)
+char *which; /* which counts to print */
+long char_count, word_count, line_count; /* given totals */
+{
+  while (*which) 
+    switch (*which++) {
+    case 'l': print_count(line_count); break;
+    case 'w': print_count(word_count); break;
+    case 'c': print_count(char_count); break;
+    default: if ((status & usage_error)==0) {
+        fprintf (stderr, "\nUsage: %s [-lwc] [filename ...]\n", prog_name);
+ at .Usage: ...@>
+        status|=usage_error;
+      }
+    }
+}
+
+@ Incidentally, a test of this program against the system \.{wc}
+command on a \SPARC\ showed that the ``official'' \.{wc} was slightly
+slower. Furthermore, although that \.{wc} gave an appropriate error
+message for the options `\.{-abc}', it made no complaints about the
+options `\.{-labc}'! Dare we suggest that the system routine might have been
+better if its programmer had used a more literate approach?
+
+@* Index.
+Here is a list of the identifiers used, and where they appear. Underlined
+entries indicate the place of definition. Error messages are also shown.


Property changes on: trunk/Build/source/texk/web2c/cwebdir/examples/wc.w
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/texk/web2c/cwebdir/examples/wmer-os2.ch
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/examples/wmer-os2.ch	                        (rev 0)
+++ trunk/Build/source/texk/web2c/cwebdir/examples/wmer-os2.ch	2018-12-30 18:59:26 UTC (rev 49537)
@@ -0,0 +1,21 @@
+Change file for wmerge, for OS/2 and WinNT and MSVC++ 2.2
+contributed May 1996 by Andreas Scherer, Aaxen University of TeXnology
+(scherer at physik.rwth-aachen.de)
+
+ at x Line 594
+An omitted change file argument means that |'/dev/null'| should be used,
+ at y
+An omitted change file argument means that |'NUL'| should be used,
+ at z
+
+ at x Line 620
+        else if (*s=='/') dot_pos=NULL,++s;
+ at y
+        else if (*s==':' || *s=='\\' || *s=='/') dot_pos=NULL,++s;
+ at z
+
+ at x Line 630
+  if (!found_change) strcpy(change_file_name,"/dev/null");
+ at y
+  if (!found_change) strcpy(change_file_name,"NUL");
+ at z


Property changes on: trunk/Build/source/texk/web2c/cwebdir/examples/wmer-os2.ch
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/texk/web2c/cwebdir/examples/wmerg-pc.ch
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/examples/wmerg-pc.ch	                        (rev 0)
+++ trunk/Build/source/texk/web2c/cwebdir/examples/wmerg-pc.ch	2018-12-30 18:59:26 UTC (rev 49537)
@@ -0,0 +1,22 @@
+Change file for wmerge, for MSDOS and Borland C++ 3.1.
+To compile the C file:  bcc -w-pro wmerge.c
+
+(This file contributed by Barry Schwartz, trashman at crud.mn.org, 28 Jun 94.)
+(Updated 17 Jul 06 by Don Knuth.)
+
+ at x Section 19.
+    cur_file_name[l]='/'; /* \UNIX/ pathname separator */
+ at y
+    cur_file_name[l]='/'; /* A valid {\mc MSDOS} pathname separator */
+ at z
+
+
+ at x Section 33.
+        if (*s=='.') dot_pos=s++;
+        else if (*s=='/') dot_pos=NULL,++s;
+        else s++;
+ at y
+        if (*s=='.') dot_pos=s++;
+        else if (*s==':' || *s=='\\' || *s=='/') dot_pos=NULL,++s;
+        else s++;
+ at z


Property changes on: trunk/Build/source/texk/web2c/cwebdir/examples/wmerg-pc.ch
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/texk/web2c/cwebdir/examples/wmerge.w
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/examples/wmerge.w	                        (rev 0)
+++ trunk/Build/source/texk/web2c/cwebdir/examples/wmerge.w	2018-12-30 18:59:26 UTC (rev 49537)
@@ -0,0 +1,717 @@
+% Modified 16 Jan 2002 to agree with COMMON version 3.64
+
+\def\9#1{} % this hack is explained in CWEB manual Appendix F11
+
+@* Introduction.  This file contains the program \.{wmerge},
+which takes two or more files and merges them according
+to the conventions of \.{CWEB}. Namely, it takes an ordinary \.{.w}
+file and and optional \.{.ch} file and sends the corresponding
+\.{.w}-style file to standard output (or to a named file),
+expanding all ``includes''
+that might be specified by \.{@@i} in the original \.{.w} file.
+(A more precise description appears in the section on ``command line
+arguments'' below.)
+
+ at c
+#include <stdio.h>
+#include <stdlib.h> /* declaration of |getenv| */
+#include <ctype.h> /* definition of |isalpha|, |isdigit| and so on */
+@<Definitions@>@;
+@<Predeclarations of functions@>@;
+@<Functions@>@;
+main (ac,av)
+int ac; char **av;
+{
+  argc=ac; argv=av;
+  @<Set the default options@>;
+  @<Scan arguments and open output file@>;
+  reset_input();
+  while (get_line())
+    put_line();
+  fflush(out_file);
+  check_complete();
+  fflush(out_file);
+  return wrap_up();
+}
+
+@ @<Definitions@>=
+typedef short boolean;
+typedef unsigned char eight_bits;
+typedef char ASCII; /* type of characters inside \.{WEB} */
+
+@ We predeclare some standard string-handling functions here instead of
+including their system header files, because the names of the header files
+are not as standard as the names of the functions. (There's confusion
+between \.{<string.h>} and \.{<strings.h>}.)
+
+@<Predecl...@>=
+extern size_t strlen(); /* length of string */
+extern char* strcpy(); /* copy one string to another */
+extern int strncmp(); /* compare up to $n$ string characters */
+extern char* strncpy(); /* copy up to $n$ string characters */
+
+@ @<Predec...@>=
+
+@ The lowest level of input to the \.{WEB} programs
+is performed by |input_ln|, which must be told which file to read from.
+The return value of |input_ln| is 1 if the read is successful and 0 if
+not (generally this means the file has ended).
+The characters of the next line of the file
+are copied into the |buffer| array,
+and the global variable |limit| is set to the first unoccupied position.
+Trailing blanks are ignored. The value of |limit| must be strictly less
+than |buf_size|, so that |buffer[buf_size-1]| is never filled.
+
+Some of the routines use the fact that it is safe to refer to
+|*(limit+2)| without overstepping the bounds of the array.
+
+ at d buf_size 4096
+
+@<Definitions...@>=
+ASCII buffer[buf_size]; /* where each line of input goes */
+ASCII *buffer_end=buffer+buf_size-2; /* end of |buffer| */
+ASCII *limit; /* points to the last character in the buffer */
+ASCII *loc; /* points to the next character to be read from the buffer */
+
+@ In the unlikely event that your standard I/O library does not
+support |feof|, |getc| and |ungetc|, you may have to change things here.
+@^system dependencies@>
+
+Incidentally, here's a curious fact about \.{CWEB} for those of you
+who are reading this file as an example of \.{CWEB} programming.
+The file \.{stdio.h} includes a typedef for
+the identifier |FILE|, which is not, strictly speaking, part of \CEE/.
+It turns out \.{CWEAVE} knows that |FILE| is a reserved word (after all,
+|FILE| is almost as common as |int|); indeed, \.{CWEAVE} knows all
+the types of the ISO standard \CEE/ library. But
+if you're using other types like {\bf caddr\_t},
+@:caddr_t}{\bf caddr_t@>
+which is defined in \.{/usr/include/sys/types.h}, you should let
+\.{WEAVE} know that this is a type, either by including the \.{.h} file
+at \.{WEB} time (saying \.{@@i /usr/include/sys/types.h}), or by
+using \.{WEB}'s format command (saying \.{@@f caddr\_t int}).  Either of
+these will make {\bf caddr\_t} be treated in the same way as |int|.
+
+@<Func...@>=
+input_ln(fp) /* copies a line into |buffer| or returns 0 */
+FILE *fp; /* what file to read from */
+{
+  register int  c=EOF; /* character read; initialized so some compilers won't complain */
+  register char *k;  /* where next character goes */
+  if (feof(fp)) return(0);  /* we have hit end-of-file */
+  limit = k = buffer;  /* beginning of buffer */
+  while (k<=buffer_end && (c=getc(fp)) != EOF && c!='\n')
+    if ((*(k++) = c) != ' ') limit = k;
+  if (k>buffer_end)
+    if ((c=getc(fp))!=EOF && c!='\n') {
+      ungetc(c,fp); loc=buffer; err_print("! Input line too long");
+ at .Input line too long@>
+  }
+  if (c==EOF && limit==buffer) return(0);  /* there was nothing after
+    the last newline */
+  return(1);
+}
+
+@ Now comes the problem of deciding which file to read from next.
+Recall that the actual text that \.{CWEB} should process comes from two
+streams: a |web_file|, which can contain possibly nested include
+commands \.{@@i}, and a |change_file|, which might also contain
+includes.  The |web_file| together with the currently open include
+files form a stack |file|, whose names are stored in a parallel stack
+|file_name|.  The boolean |changing| tells whether or not we're reading
+from the |change_file|.
+
+The line number of each open file is also kept for error reporting.
+
+ at f line x /* make |line| an unreserved word */
+ at d max_include_depth 10 /* maximum number of source files open
+  simultaneously, not counting the change file */
+ at d max_file_name_length 60
+ at d cur_file file[include_depth] /* current file */
+ at d cur_file_name file_name[include_depth] /* current file name */
+ at d cur_line line[include_depth] /* number of current line in current file */
+ at d web_file file[0] /* main source file */
+ at d web_file_name file_name[0] /* main source file name */
+
+@<Definitions...@>=
+int include_depth; /* current level of nesting */
+FILE *file[max_include_depth]; /* stack of non-change files */
+FILE *change_file; /* change file */
+char file_name[max_include_depth][max_file_name_length];
+  /* stack of non-change file names */
+char change_file_name[max_file_name_length]; /* name of change file */
+char alt_web_file_name[max_file_name_length]; /* alternate name to try */
+int line[max_include_depth]; /* number of current line in the stacked files */
+int change_line; /* number of current line in change file */
+int change_depth; /* where \.{@@y} originated during a change */
+boolean input_has_ended; /* if there is no more input */
+boolean changing; /* if the current line is from |change_file| */
+boolean web_file_open=0; /* if the web file is being read */
+
+@ When |changing=0|, the next line of |change_file| is kept in
+|change_buffer|, for purposes of comparison with the next
+line of |cur_file|. After the change file has been completely input, we
+set |change_limit=change_buffer|,
+so that no further matches will be made.
+
+Here's a shorthand expression for inequality between the two lines:
+
+ at d lines_dont_match (change_limit-change_buffer != limit-buffer ||
+  strncmp(buffer, change_buffer, limit-buffer))
+
+@<Def...@>=
+char change_buffer[buf_size]; /* next line of |change_file| */
+char *change_limit; /* points to the last character in |change_buffer| */
+
+@ Procedure |prime_the_change_buffer| sets |change_buffer| in
+preparation for the next matching operation. Since blank lines in the change
+file are not used for matching, we have
+|(change_limit==change_buffer && !changing)| if and only if
+the change file is exhausted. This procedure is called only when
+|changing| is 1; hence error messages will be reported correctly.
+
+@<Func...@>=
+void
+prime_the_change_buffer()
+{
+  change_limit=change_buffer; /* this value is used if the change file ends */
+  @<Skip over comment lines in the change file; |return| if end of file@>;
+  @<Skip to the next nonblank line; |return| if end of file@>;
+  @<Move |buffer| and |limit| to |change_buffer| and |change_limit|@>;
+}
+
+@ While looking for a line that begins with \.{@@x} in the change file, we
+allow lines that begin with \.{@@}, as long as they don't begin with \.{@@y},
+\.{@@z} or \.{@@i} (which would probably mean that the change file is fouled up).
+
+@<Skip over comment lines in the change file...@>=
+while(1) {
+  change_line++;
+  if (!input_ln(change_file)) return;
+  if (limit<buffer+2) continue;
+  if (buffer[0]!='@@') continue;
+  if (isupper(buffer[1])) buffer[1]=tolower(buffer[1]);
+  if (buffer[1]=='x') break;
+  if (buffer[1]=='y' || buffer[1]=='z' || buffer[1]=='i') {
+    loc=buffer+2;
+    err_print("! Missing @@x in change file");
+ at .Missing @@x...@>
+  }
+}
+
+@ Here we are looking at lines following the \.{@@x}.
+
+@<Skip to the next nonblank line...@>=
+do {
+  change_line++;
+  if (!input_ln(change_file)) {
+    err_print("! Change file ended after @@x");
+ at .Change file ended...@>
+    return;
+  }
+} while (limit==buffer);
+
+@ @<Move |buffer| and |limit| to |change_buffer| and |change_limit|@>=
+{
+  change_limit=change_buffer+(limit-buffer);
+  strncpy(change_buffer,buffer,limit-buffer+1);
+}
+
+@ The following procedure is used to see if the next change entry should
+go into effect; it is called only when |changing| is 0.
+The idea is to test whether or not the current
+contents of |buffer| matches the current contents of |change_buffer|.
+If not, there's nothing more to do; but if so, a change is called for:
+All of the text down to the \.{@@y} is supposed to match. An error
+message is issued if any discrepancy is found. Then the procedure
+prepares to read the next line from |change_file|.
+
+This procedure is called only when |buffer<limit|, i.e., when the
+current line is nonempty.
+
+@<Func...@>=
+void
+check_change() /* switches to |change_file| if the buffers match */
+{
+  int n=0; /* the number of discrepancies found */
+  if (lines_dont_match) return;
+  while (1) {
+    changing=1; change_line++;
+    if (!input_ln(change_file)) {
+      err_print("! Change file ended before @@y");
+ at .Change file ended...@>
+      change_limit=change_buffer; changing=0;
+      return;
+    }
+    if (limit>buffer+1 && buffer[0]=='@@') {
+      char xyz_code=isupper(buffer[1])? tolower(buffer[1]): buffer[1];
+      @<If the current line starts with \.{@@y},
+        report any discrepancies and |return|@>;
+    }
+    @<Move |buffer| and |limit|...@>;
+    changing=0; cur_line++;
+    while (!input_ln(cur_file)) { /* pop the stack or quit */
+      if (include_depth==0) {
+        err_print("! CWEB file ended during a change");
+ at .CWEB file ended...@>
+        input_has_ended=1; return;
+      }
+      include_depth--; cur_line++;
+    }
+    if (lines_dont_match) n++;
+  }
+}
+
+@ @<If the current line starts with \.{@@y}...@>=
+if (xyz_code=='x' || xyz_code=='z') {
+  loc=buffer+2; err_print("! Where is the matching @@y?");
+ at .Where is the match...@>
+  }
+else if (xyz_code=='y') {
+  if (n>0) {
+    loc=buffer+2;
+    fprintf(stderr,"\n! Hmm... %d ",n);
+    err_print("of the preceding lines failed to match");
+ at .Hmm... n of the preceding...@>
+  }
+  change_depth=include_depth;
+  return;
+}
+
+@ The |reset_input| procedure gets the program ready to read the
+user's \.{WEB} input.
+
+@<Func...@>=
+void
+reset_input()
+{
+  limit=buffer; loc=buffer+1; buffer[0]=' ';
+  @<Open input files@>;
+  include_depth=0; cur_line=0; change_line=0;
+  change_depth=include_depth;
+  changing=1; prime_the_change_buffer(); changing=!changing;
+  limit=buffer; loc=buffer+1; buffer[0]=' '; input_has_ended=0;
+}
+
+@ The following code opens the input files.
+@^system dependencies@>
+
+@<Open input files@>=
+if ((web_file=fopen(web_file_name,"r"))==NULL) {
+  strcpy(web_file_name,alt_web_file_name);
+  if ((web_file=fopen(web_file_name,"r"))==NULL)
+       fatal("! Cannot open input file ", web_file_name);
+}
+ at .Cannot open input file@>
+ at .Cannot open change file@>
+web_file_open=1;
+if ((change_file=fopen(change_file_name,"r"))==NULL)
+       fatal("! Cannot open change file ", change_file_name);
+
+@ The |get_line| procedure is called when |loc>limit|; it puts the next
+line of merged input into the buffer and updates the other variables
+appropriately. A space is placed at the right end of the line.
+This procedure returns |!input_has_ended| because we often want to
+check the value of that variable after calling the procedure.
+
+@<Fun...@>=
+int get_line() /* inputs the next line */
+{
+  restart:
+  if (changing && include_depth==change_depth)
+   @<Read from |change_file| and maybe turn off |changing|@>;
+  if (! changing || include_depth>change_depth) {
+    @<Read from |cur_file| and maybe turn on |changing|@>;
+    if (changing && include_depth==change_depth) goto restart;
+  }
+  if (input_has_ended) return 0;
+  loc=buffer; *limit=' ';
+  if (buffer[0]=='@@' && (buffer[1]=='i' || buffer[1]=='I')) {
+    loc=buffer+2; *limit='"';
+    while (*loc==' '||*loc=='\t') loc++;
+    if (loc>=limit) {
+      err_print("! Include file name not given");
+ at .Include file name ...@>
+      goto restart;
+    }
+    if (include_depth>=max_include_depth-1) {
+      err_print("! Too many nested includes");
+ at .Too many nested includes@>
+      goto restart;
+    }
+    include_depth++; /* push input stack */
+    @<Try to open include file, abort push if unsuccessful, go to |restart|@>;
+  }
+  return 1;
+}
+
+void put_line()
+{
+  char *ptr=buffer;
+  while (ptr<limit) putc(*ptr++,out_file);
+  putc('\n',out_file);
+}
+
+@ When an \.{@@i} line is found in the |cur_file|, we must temporarily
+stop reading it and start reading from the named include file.  The
+\.{@@i} line should give a complete file name with or without
+double quotes.
+If the environment variable \.{CWEBINPUTS} is set, or if the compiler flag
+of the same name was defined at compile time,
+\.{CWEB} will look for include files in the directory thus named, if
+it cannot find them in the current directory.
+(Colon-separated paths are not supported.)
+The remainder of the \.{@@i} line after the file name is ignored.
+
+ at d too_long() {include_depth--;
+        err_print("! Include file name too long"); goto restart;}
+
+@ @<Try to open...@>= {
+  char temp_file_name[max_file_name_length];
+  char *cur_file_name_end=cur_file_name+max_file_name_length-1;
+  char *k=cur_file_name, *kk;
+  int l; /* length of file name */
+
+  if (*loc=='"') {
+    loc++;
+    while (*loc!='"' && k<=cur_file_name_end) *k++=*loc++;
+    if (loc==limit) k=cur_file_name_end+1; /* unmatched quote is `too long' */
+  } else
+    while (*loc!=' '&&*loc!='\t'&&*loc!='"'&&k<=cur_file_name_end) *k++=*loc++;
+  if (k>cur_file_name_end) too_long();
+ at .Include file name ...@>
+  *k='\0';
+  if ((cur_file=fopen(cur_file_name,"r"))!=NULL) {
+    cur_line=0;
+    goto restart; /* success */
+  }
+  kk=getenv("CWEBINPUTS");
+  if (kk!=NULL) {
+    if ((l=strlen(kk))>max_file_name_length-2) too_long();
+    strcpy(temp_file_name,kk);
+  }
+  else {
+#ifdef CWEBINPUTS
+    if ((l=strlen(CWEBINPUTS))>max_file_name_length-2) too_long();
+    strcpy(temp_file_name,CWEBINPUTS);
+#else
+    l=0;
+#endif /* |CWEBINPUTS| */
+  }
+  if (l>0) {
+    if (k+l+2>=cur_file_name_end)  too_long();
+ at .Include file name ...@>
+    for (; k>= cur_file_name; k--) *(k+l+1)=*k;
+    strcpy(cur_file_name,temp_file_name);
+    cur_file_name[l]='/'; /* \UNIX/ pathname separator */
+    if ((cur_file=fopen(cur_file_name,"r"))!=NULL) {
+      cur_line=0;
+      goto restart; /* success */
+    }
+  }
+  include_depth--; err_print("! Cannot open include file"); goto restart;
+}
+
+@ @<Read from |cur_file|...@>= {
+  cur_line++;
+  while (!input_ln(cur_file)) { /* pop the stack or quit */
+    if (include_depth==0) {input_has_ended=1; break;}
+    else {
+      fclose(cur_file); include_depth--;
+      if (changing && include_depth==change_depth) break;
+      cur_line++;
+    }
+  }
+  if (!changing && !input_has_ended)
+   if (limit-buffer==change_limit-change_buffer)
+    if (buffer[0]==change_buffer[0])
+      if (change_limit>change_buffer) check_change();
+}
+
+@ @<Read from |change_file|...@>= {
+  change_line++;
+  if (!input_ln(change_file)) {
+    err_print("! Change file ended without @@z");
+ at .Change file ended...@>
+    buffer[0]='@@'; buffer[1]='z'; limit=buffer+2;
+  }
+  if (limit>buffer) { /* check if the change has ended */
+    *limit=' ';
+    if (buffer[0]=='@@') {
+      if (isupper(buffer[1])) buffer[1]=tolower(buffer[1]);
+      if (buffer[1]=='x' || buffer[1]=='y') {
+        loc=buffer+2;
+        err_print("! Where is the matching @@z?");
+ at .Where is the match...@>
+      }
+      else if (buffer[1]=='z') {
+        prime_the_change_buffer(); changing=!changing;
+      }
+    }
+  }
+}
+
+@ At the end of the program, we will tell the user if the change file
+had a line that didn't match any relevant line in |web_file|.
+
+@<Funct...@>=
+void
+check_complete(){
+  if (change_limit!=change_buffer) { /* |changing| is 0 */
+    strncpy(buffer,change_buffer,change_limit-change_buffer+1);
+    limit=buffer+(int)(change_limit-change_buffer);
+    changing=1; change_depth=include_depth; loc=buffer;
+    err_print("! Change file entry did not match");
+  @.Change file entry did not match@>
+  }
+}
+
+@* Reporting errors to the user.
+A global variable called |history| will contain one of four values
+at the end of every run: |spotless| means that no unusual messages were
+printed; |harmless_message| means that a message of possible interest
+was printed but no serious errors were detected; |error_message| means that
+at least one error was found; |fatal_message| means that the program
+terminated abnormally. The value of |history| does not influence the
+behavior of the program; it is simply computed for the convenience
+of systems that might want to use such information.
+
+ at d spotless 0 /* |history| value for normal jobs */
+ at d harmless_message 1 /* |history| value when non-serious info was printed */
+ at d error_message 2 /* |history| value when an error was noted */
+ at d fatal_message 3 /* |history| value when we had to stop prematurely */
+ at d mark_harmless {if (history==spotless) history=harmless_message;}
+ at d mark_error history=error_message
+
+@<Definit...@>=
+int history=spotless; /* indicates how bad this run was */
+
+@ The command `|err_print("! Error message")|' will report a syntax error to
+the user, by printing the error message at the beginning of a new line and
+then giving an indication of where the error was spotted in the source file.
+Note that no period follows the error message, since the error routine
+will automatically supply a period. A newline is automatically supplied
+if the string begins with |"!"|.
+
+The actual error indications are provided by a procedure called |error|.
+
+@<Predecl...@>=
+void  err_print();
+
+@
+@<Functions...@>=
+void
+err_print(s) /* prints `\..' and location of error message */
+char *s;
+{
+  char *k,*l; /* pointers into |buffer| */
+  fprintf(stderr,*s=='!'? "\n%s" : "%s",s);
+  if(web_file_open) @<Print error location based on input buffer@>@;
+  else putc('\n',stderr);
+  update_terminal; mark_error;
+}
+
+@ The error locations can be indicated by using the global variables
+|loc|, |cur_line|, |cur_file_name| and |changing|,
+which tell respectively the first
+unlooked-at position in |buffer|, the current line number, the current
+file, and whether the current line is from |change_file| or |cur_file|.
+This routine should be modified on systems whose standard text editor
+has special line-numbering conventions.
+@^system dependencies@>
+
+@<Print error location based on input buffer@>=
+{if (changing && include_depth==change_depth)
+  fprintf(stderr,". (l. %d of change file)\n", change_line);
+else if (include_depth==0) fprintf(stderr,". (l. %d)\n", cur_line);
+  else fprintf(stderr,". (l. %d of include file %s)\n", cur_line, cur_file_name);
+l= (loc>=limit? limit: loc);
+if (l>buffer) {
+  for (k=buffer; k<l; k++)
+    if (*k=='\t') putc(' ',stderr);
+    else putc(*k,stderr); /* print the characters already read */
+  putc('\n',stderr);
+  for (k=buffer; k<l; k++) putc(' ',stderr); /* space out the next line */
+}
+for (k=l; k<limit; k++) putc(*k,stderr); /* print the part not yet read */
+  putc('\n',stderr);
+}
+
+@ When no recovery from some error has been provided, we have to wrap
+up and quit as graciously as possible.  This is done by calling the
+function |wrap_up| at the end of the code.
+
+ at d fatal(s,t) {
+  fprintf(stderr,s); err_print(t);
+  history=fatal_message; exit(wrap_up());
+}
+
+@ Some implementations may wish to pass the |history| value to the
+operating system so that it can be used to govern whether or not other
+programs are started. Here, for instance, we pass the operating system
+a status of 0 if and only if only harmless messages were printed.
+@^system dependencies@>
+
+@<Func...@>=
+wrap_up() {
+  @<Print the job |history|@>;
+  if (history > harmless_message) return(1);
+  else return(0);
+}
+
+@ @<Print the job |history|@>=
+switch (history) {
+case spotless: if (show_happiness) fprintf(stderr,"(No errors were found.)\n"); break;
+case harmless_message:
+  fprintf(stderr,"(Did you see the warning message above?)\n"); break;
+case error_message:
+  fprintf(stderr,"(Pardon me, but I think I spotted something wrong.)\n"); break;
+case fatal_message: fprintf(stderr,"(That was a fatal error, my friend.)\n");
+} /* there are no other cases */
+
+@* Command line arguments.
+The user calls \.{wmerge} with arguments on the command line.
+These are either file names or flags to be turned off (beginning with |"-"|)
+or flags to be turned on (beginning with |"+"|.
+The following globals are for communicating the user's desires to the rest
+of the program. The various file name variables contain strings with
+the names of those files. Most of the 128 flags are undefined but available
+for future extensions.
+
+ at d show_banner flags['b'] /* should the banner line be printed? */
+ at d show_happiness flags['h'] /* should lack of errors be announced? */
+
+@<Defin...@>=
+int argc; /* copy of |ac| parameter to |main| */
+char **argv; /* copy of |av| parameter to |main| */
+char out_file_name[max_file_name_length]; /* name of |out_file| */
+boolean flags[128]; /* an option for each 7-bit code */
+
+@ The |flags| will be initially 1.
+
+@<Set the default options@>=
+show_banner=show_happiness=1;
+
+@ We now must look at the command line arguments and set the file names
+accordingly.  At least one file name must be present: the \.{WEB}
+file.  It may have an extension, or it may omit it to get |'.w'|
+added.
+
+If there is another file name present among the arguments, it is the
+change file, again either with an extension or without one to get |'.ch'|
+An omitted change file argument means that |'/dev/null'| should be used,
+when no changes are desired.
+@^system dependencies@>
+
+If there's a third file name, it will be the output file.
+
+@<Pred...@>=
+void scan_args();
+
+@
+@<Function...@>=
+void
+scan_args()
+{
+  char *dot_pos; /* position of |'.'| in the argument */
+  register char *s; /* register for scanning strings */
+  boolean found_web=0,found_change=0,found_out=0;
+             /* have these names have been seen? */
+  boolean flag_change;
+
+  while (--argc > 0) {
+    if (**(++argv)=='-' || **argv=='+') @<Handle flag argument@>@;
+    else {
+      s=*argv;@+dot_pos=NULL;
+      while (*s) {
+        if (*s=='.') dot_pos=s++;
+        else if (*s=='/') dot_pos=NULL,++s;
+        else s++;
+      }
+      if (!found_web) @<Make |web_file_name|@>@;
+      else if (!found_change) @<Make |change_file_name| from |fname|@>@;
+      else if (!found_out) @<Override output file name@>@;
+        else @<Print usage error message and quit@>;
+    }
+  }
+  if (!found_web) @<Print usage error message and quit@>;
+  if (!found_change) strcpy(change_file_name,"/dev/null");
+}
+
+@ We use all of |*argv| for the |web_file_name| if there is a |'.'| in it,
+otherwise we add |".w"|. If this file can't be opened, we prepare an
+|alt_web_file_name| by adding |"web"| after the dot.
+The other file names come from adding other things
+after the dot.  We must check that there is enough room in
+|web_file_name| and the other arrays for the argument.
+
+@<Make |web_file_name|...@>=
+{
+  if (s-*argv > max_file_name_length-5)
+    @<Complain about argument length@>;
+  if (dot_pos==NULL)
+    sprintf(web_file_name,"%s.w",*argv);
+  else {
+    strcpy(web_file_name,*argv);
+    *dot_pos=0; /* string now ends where the dot was */
+  }
+  sprintf(alt_web_file_name,"%s.web",*argv);
+  *out_file_name='\0'; /* this will print to stdout */
+  found_web=1;
+}
+
+@ @<Make |change_file_name|...@>=
+{
+  if (s-*argv > max_file_name_length-4)
+    @<Complain about argument length@>;
+  if (dot_pos==NULL)
+    sprintf(change_file_name,"%s.ch",*argv);
+  else strcpy(change_file_name,*argv);
+  found_change=1;
+}
+
+@ @<Override...@>=
+{
+  if (s-*argv > max_file_name_length-5)
+    @<Complain about argument length@>;
+  if (dot_pos==NULL) sprintf(out_file_name,"%s.out",*argv);
+  else strcpy(out_file_name,*argv);
+  found_out=1;
+}
+
+@ @<Handle flag...@>=
+{
+  if (**argv=='-') flag_change=0;
+  else flag_change=1;
+  for(dot_pos=*argv+1;*dot_pos>'\0';dot_pos++)
+    flags[*dot_pos]=flag_change;
+}
+
+@ @<Print usage error message and quit@>=
+{
+  fatal("! Usage: wmerge webfile[.w] [changefile[.ch] [outfile[.out]]]\n","")@;
+}
+
+@ @<Complain about arg...@>= fatal("! Filename too long\n", *argv);
+
+@* Output. Here is the code that opens the output file:
+@^system dependencies@>
+
+@<Defin...@>=
+FILE *out_file; /* where output goes */
+
+@ @<Scan arguments and open output file@>=
+scan_args();
+if (out_file_name[0]=='\0') out_file=stdout;
+else if ((out_file=fopen(out_file_name,"w"))==NULL)
+    fatal("! Cannot open output file ", out_file_name);
+ at .Cannot open output file@>
+
+@ The |update_terminal| procedure is called when we want
+to make sure that everything we have output to the terminal so far has
+actually left the computer's internal buffers and been sent.
+@^system dependencies@>
+
+ at d update_terminal fflush(stderr) /* empty the terminal output buffer */
+
+@* Index.


Property changes on: trunk/Build/source/texk/web2c/cwebdir/examples/wmerge.w
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/texk/web2c/cwebdir/examples/wordtest.w
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/examples/wordtest.w	                        (rev 0)
+++ trunk/Build/source/texk/web2c/cwebdir/examples/wordtest.w	2018-12-30 18:59:26 UTC (rev 49537)
@@ -0,0 +1,540 @@
+\datethis
+@* Introduction. This program is a simple filter that sorts and outputs all
+lines of input that do not appear in a given set of sorted files. It is called
+{\tt wordtest} because each line of input is considered to be a `word' and
+each of the sorted files is considered to be a 'dictionary'. Words are
+output when they don't appear in any given dictionary.
+
+The character set and alphabetic order are flexible. Every 8-bit
+character is mapped into an integer called its {\it ord}. A character
+is called a {\it null\/} if its ord is zero; such characters are
+discarded from the input. A character is called a {\it break\/} if
+its ord is negative; such characters break the input into so-called words.
+Otherwise a character's ord is positive, and the character is called a
+{\it letter}. One letter precedes another in alphabetic order if and only
+if it has a smaller ord. Two letters are considered identical, for
+purposes of sorting, if their ords are the same.
+
+The null character |'\n'| must have ord~0; thus, it must remain null.
+Otherwise the ord mapping is arbitrary. If the user doesn't specify
+any special mapping, the default ord table simply maps every 8-bit
+character code into itself, considering characters to be unsigned char
+values in the range 0--255, except that ASCII codes {\tt a-z} are
+mapped into the corresponding codes for {\tt A-Z}, and newline is a
+break character. Optional command-line arguments, described below, can
+change this default mapping to any other desired scheme.
+
+A word is any nonempty sequence of letters that is immediately preceded
+and followed by break characters, when nulls are ignored. Technically
+speaking, we pretend that a break character is present at the beginning of a
+file but not at the end; thus, all letters following the final break character
+of a file are ignored, if any such letters are present. Two words are
+{\it equivalent\/} to each other if their letters have the same sequence
+of ord values. If two or more words of the input are equivalent, only
+the first will be output, and it will be output only if it is not
+equivalent to any word in the given dictionary files. Words in each
+dictionary are assumed to be in lexicographic order and to contain no
+nulls. Words in the output file will satisfy these conditions; therefore
+{\tt wordtest} can be used to generate and update the dictionaries it needs.
+Notice that if no dictionaries are given, {\tt wordtest} will act as a
+sorting routine that simply discards nulls and duplicate lines.
+
+@ The \UNIX/ command line `{\tt wordtest} {\tt [options]} {\tt [dictionaries]}'
+is interpreted by executing option commands from left to right and then by
+regarding any remaining arguments as the names of dictionary files.
+
+Most of the option commands are designed to specify the |ord| table.
+Initially |ord[c]=c| for each unsigned char code~|c|. The command
+$$\line{\hskip5em\tt-b\it string\hfil}$$
+makes every character in the string a break character. If the string is
+empty, {\tt-b} makes every nonnull character a break (i.e., it sets
+|ord[c]=-1| for |1<=c<=255|). The command
+$$\line{\hskip5em\tt-n\it string\hfil}$$
+makes every character in the string a null character. If the string is
+empty, {\tt-n} makes every character null. The command
+$$\line{\hskip5em\tt-a\it string\hfil}$$
+sets the ord of the $k$th element of the string equal to $\delta+k$,
+where $\delta$ is an offset value (normally zero). The command
+$$\line{\hskip5em\tt-d\it offset\hfil}$$
+sets the value of $\delta$; the offset should be a decimal integer between
+0 and 255.
+
+There is also an option that has no effect on the |ord| table:
+$$\line{\hskip5em\tt-m\it length\hfil}$$
+defines the length of the longest word. If any word of a file has
+more than this many characters, a break is artificially inserted
+so that a word of this maximum length is obtained. The default value is 50.
+The maximum legal value is 1000.
+
+If the given options do not specify at least one break character,
+{\tt wordtest} applies the option commands
+$$\vbox{\line{\hskip5em\.{-b"\\}\hfil}
+\line{\.{" -d64 -a"abcdefghijklmnopqrstuvwxyz"}\hfil}}$$
+which generate the default mapping mentioned above (unless other ords were
+changed).
+
+The program is designed to run fastest when there are at most two
+dictionary files (usually one large system dictionary and another
+personalized one), although it places no limit on the actual number of
+dictionaries that can be mentioned on the command line. Users who want
+to specify a multitude of dictionaries should ask themselves why they
+wouldn't prefer to merge their dictionaries together first (using
+{\tt wordtest}).
+
+ at d MAX_LENGTH_DEFAULT 50
+ at d MAX_LENGTH_LIMIT 1000
+
+@ The general organization of {\tt wordtest} is typical of applications
+written in \CEE/, and its approach is quite simple. If any errors are
+detected, an indication of the error is sent to the |stderr| file and
+a nonzero value is returned.
+
+ at p
+#include <stdio.h>
+#include <stdlib.h>
+@#
+@<Typedefs@>@;
+int main(argc,argv)
+  int argc; /* the number of command-line arguments */
+  char *argv[]; /* the arguments themselves */
+{
+  @<Local variables@>;
+  @<Scan the command line arguments@>;
+  @<Sort the input into memory@>;
+  @<Output all input words that aren't in dictionaries@>;
+  return 0;
+}
+
+@ @<Typedefs@>=
+typedef unsigned char byte; /* our bytes will range from 0 to 255 */
+
+@ @<Local variables@>=
+int targc; /* temporary modifications to |argc| */
+byte **targv; /* pointer to the current argument of interest */
+unsigned delta; /* the offset used in the \.{-a} and \.{-d} options */
+unsigned max_length=MAX_LENGTH_DEFAULT; /* longest allowable word */
+byte breakchar; /* break character to use in the output */
+int ord[256]; /* table of ord values */
+register int c; /* an all-purpose index */
+register byte *u,*v; /* pointer to current string characters */
+
+@ We try to use newline as the output break character, if possible.
+
+@<Scan the command line arguments@>=
+for (c=0;c<256;c++) ord[c]=c;
+delta=0;
+targc=argc-1;@+targv=(byte**)argv+1;
+while (targc && **targv=='-') {
+  @<Execute the option command |targv|@>;
+  targc--;@+targv++;
+}
+if (ord['\n']<0) breakchar='\n';
+else {
+  breakchar='\0';
+  for (c=255;c;c--) if (ord[c]<0) breakchar=c;
+  if (!breakchar) @<Set up the default ords@>;
+}
+@<Allocate data structures for a total of |targc| files@>;
+for (;targc;targc--,targv++) @<Open the dictionary file named |*targv|@>;
+
+@ @<Execute the option...@>=
+switch((*targv)[1]) {
+case 'a': for (c=delta,u=*targv+2;*u;u++) ord[*u]=++c;@+break;
+case 'b': if ((*targv)[2]) for (u=*targv+2;*u;u++) ord[*u]=-1;
+  else for (c=1;c<256;c++) ord[c]=-1;
+  break;
+case 'n': if ((*targv)[2]) for (u=*targv+2;*u;u++) ord[*u]=0;
+  else for (c=1;c<256;c++) ord[c]=0;
+  break;
+case 'd': if (sscanf((char*)*targv+2,"%u",&delta)==1 && delta<256) break;
+  goto print_usage;
+case 'm': if (sscanf((char*)*targv+2,"%u",&max_length)==1 &&
+    max_length<=MAX_LENGTH_LIMIT) break;
+  goto print_usage;
+default: print_usage: fprintf(stderr,
+  "Usage: %s {-{{a|b|n}string|{d|m}number}}* dictionaryname*\n",*argv);
+  return-1;
+}
+
+@ @<Set up the default ords@>=
+{
+  ord['\n']=-1; /* newline is break character */
+  breakchar='\n';
+  for (c=1;c<=26;c++) ord['a'-1+c]='A'-1+c;
+}
+
+@*Treaps. The most interesting part of this program is its sorting algorithm,
+which is based on the ``treap'' data structure of Aragon and Seidel
+[{\sl 30th IEEE Symposium on Foundations of Computer Science\/} (1989),
+540--546].
+@^Aragon, Cecilia Rodriguez@>@^Seidel, Raimund@>
+A treap is a binary tree whose nodes have two key fields. The primary
+key, which in our application is a word from the input, obeys
+tree-search order: All descendants of the left child of node~$p$ have
+a primary key that is less than the primary key of~$p$, and all descendants
+of its right child have a primary key that is greater. The secondary key,
+which in our application is a unique pseudorandom integer attached to
+each input word, obeys heap order: The secondary key of~$p$'s children
+is greater than $p$'s own secondary key.
+
+A given set of nodes with distinct primary keys and distinct secondary
+keys can be made into a treap in exactly one way. This unique treap
+can be obtained, for example, by using ordinary tree insertion with
+respect to primary keys while inserting nodes in order of their
+secondary keys. It follows that, if the secondary keys are random,
+the binary tree will almost always be quite well balanced.
+
+We will compute secondary keys as unsigned long integers, assigning
+the key $(cn)\bmod 2^{32}$ to the $n$th node, where $c$ is an odd
+number. This will guarantee that the secondary keys are distinct.
+By choosing $c$ close to $2^{32}/\phi$, where $\phi$ is the golden
+ratio $(1+\sqrt5\,)/2$, we also spread the values out in a fashion that
+is unlikely to match any existing order in the data.
+
+ at d PHICLONE 2654435769 /* $\approx 2^{32}/\phi$ */
+
+@<Typedefs@>=
+typedef struct node_struct {
+  struct node_struct *left,*right; /* children */
+  byte *keyword; /* primary key */
+  unsigned long rank; /* secondary key */
+} node; /* node of a treap */
+
+@ We want to be able to compare two strings rapidly with respect to
+lexicographic order, as defined by the |ord| table. This can be done
+if one string is delimited by |'\0'| as usual, while the other is
+delimited by a break character. Then we are sure to have an unequal
+comparison, and the inner loop is fast.
+
+Here is a routine that checks to see if a word is already present in the
+treap.  The word is assumed to be in |buffer|, terminated by |breakchar|.
+The words in the treap are terminated by nulls. The
+treap is accessed by means of |root|, a pointer to its root node.
+
+@<Search for |buffer| in the treap; |goto found| if it's there@>=
+{@+register node *p=root;
+  while (p) {
+    for (u=buffer,v=p->keyword;ord[*u]==ord[*v];u++,v++) ;
+    if (*v=='\0' && *u==breakchar) goto found;
+    if (ord[*u]<ord[*v]) p=p->left;
+    else p=p->right;
+  }
+}
+
+@ We don't need to insert nodes into the treap as often as we need to
+look words up, so we don't mind repeating the comparisons already made
+when we discover that insertion is necessary. (Actually a more comprehensive
+study of this tradeoff ought to be done. But not today; I am trying
+here to keep the program short and sweet.)
+
+The insertion algorithm proceeds just as the lookup algorithm until
+we come to a node whose rank is larger than the rank of the node
+to be inserted. We insert the new node in its place, then split the
+old node and its descendants into two subtrees that will become the
+left and right subtrees of the new node.
+
+@<Insert the |buffer| word into the treap@>=
+{@+register node *p,**q,**qq,*r;
+  current_rank += PHICLONE; /* unsigned addition mod $2^{32}$ */
+  p=root;@+q=&root;
+  while (p) {
+    if (p->rank>current_rank) break; /* end of the first phase */
+    for (u=buffer,v=p->keyword;ord[*u]==ord[*v];u++,v++) ;
+    if (ord[*u]<ord[*v]) q=&(p->left), p=*q;
+    else q=&(p->right), p=*q;
+  }
+  @<Set |r| to the address of a new node, and move |buffer| into it@>;
+  r->rank=current_rank;
+  *q=r; /* link the new node into the tree */
+  @<Split subtree |p| and attach it below node |r|@>;
+}
+
+@ @<Local...@>=
+unsigned long current_rank=0; /* pseudorandom number */
+
+@ At this point |p| may already be empty. If not, we can hook its
+parts together easily.  (A formal proof is a bit tricky, but the computer
+doesn't slow down like people do when they get to a conceptually harder
+part of an algorithm.)
+
+@<Split subtree |p| and attach it below node |r|@>=
+q=&(r->left);@+qq=&(r->right); /* slots to fill in as we split the subtree */
+while (p) {
+  for (u=buffer,v=p->keyword;ord[*u]==ord[*v];u++,v++) ;
+  if (ord[*u]<ord[*v]) {
+    *qq=p;
+    qq=&(p->left);
+    p=*qq;
+  } else {
+    *q=p;
+    q=&(p->right);
+    p=*q;
+  }
+}
+*q=*qq=NULL;
+
+@ We allocate node memory dynamically, in blocks of 100 nodes at a time.
+We also allocate string memory dynamically, 1000 characters at once
+(in addition to space for the current string).
+The variable |l| will be set to the length of the word in |buffer|.
+
+ at d NODES_PER_BLOCK 100
+ at d CHARS_PER_BLOCK 1000
+ at d out_of_mem(x) {@+fprintf(stderr,"%s: Memory exhausted!\n",*argv);
+                    return x;@+}
+
+@<Set |r| to the address of a new node, and move |buffer| into it@>=
+if (next_node==bad_node) {
+  next_node=(node*)calloc(NODES_PER_BLOCK,sizeof(node));
+  if (next_node==NULL) out_of_mem(-2);
+  bad_node=next_node+NODES_PER_BLOCK;
+}
+r=next_node++;
+@<Move |buffer| to a new place in the string memory, and make
+  |r->keyword| point to it@>;
+
+@ @<Move |buffer| to a new place...@>=
+if (next_string+l+1>=bad_string) {@+int block_size=CHARS_PER_BLOCK+l+1;
+  next_string=(byte*)malloc(block_size);
+  if (next_string==NULL) out_of_mem(-3);
+  bad_string=next_string+block_size;
+}
+r->keyword=next_string;
+for (u=buffer,v=next_string;ord[*u]>0;u++,v++) *v=*u;
+*v='\0';
+next_string=v+1;
+
+@ We had better define the variables we've been assuming in these
+storage allocation routines.
+
+@<Local variables@>=
+node *next_node=NULL, *bad_node=NULL;
+byte *next_string=NULL, *bad_string=NULL;
+node *root=NULL;
+byte *buffer;
+int l; /* length of current string in |buffer| */
+
+@ The mechanisms for sorting the input words are now all in place.
+We merely need to invoke them at the right times.
+
+@<Sort the input into memory@>=
+buffer=(byte*)malloc(max_length+1);
+if (buffer==NULL) out_of_mem(-5);
+while (1) {
+  @<Set |buffer| to the next word from |stdin|; |goto done| if file ends@>;
+  if (l) {
+   @<Search for |buffer| in the treap; |goto found| if it's there@>;
+   @<Insert the |buffer| word into the treap@>;
+ found:;    
+  }
+}
+done:;
+
+@ @<Set |buffer| to the next word from |stdin|...@>=
+u=buffer;@+l=0;
+while (l<max_length) {
+  c=getchar();
+  if (c==EOF) {
+    if (ferror(stdin)) {
+      fprintf(stderr,"%s: File read error on standard input!\n",*argv);
+      return -6;
+    }
+    goto done; /* end of file; the current word, if any, is discarded */
+  }
+  if (ord[c]<=0) {
+    if (ord[c]<0) break;
+  } else {
+    *u++=(byte)c;
+    l++;
+  }
+}
+*u=breakchar;
+
+@ At the end we want to traverse the treap in symmetric order, so that
+we see its words in alphabetic order. We might as well destroy the
+treap structure as we do this. During this phase, |root| will point
+to a stack of nodes that remain to be visited (followed by traversal
+of their right subtrees).
+
+@<Output all input words that aren't in dictionaries@>=
+if (root!=NULL) {@+register node *p,*q;
+  p=root;
+  root=NULL;
+  while (1) {
+    while (p->left!=NULL) {
+      q=p->left;
+      p->left=root; /* |left| links are now used for the stack */
+      root=p;
+      p=q;
+    }
+visit: @<Output |p->keyword|, if it's not in the dictionaries@>;
+    if (p->right==NULL) {
+      if (root==NULL) break; /* the stack is empty, we're done */
+      p=root;
+      root=root->left; /* pop the stack */
+      goto visit;
+    } else p=p->right;
+  }
+}
+
+@* The dictionaries. So now all we have to do is provide a mechanism
+for reading the words in the dictionaries. The dictionaries are sorted,
+and by now the input words have been sorted too.
+So we need only scan through the
+dictionaries once; we'll try to zoom through as quickly as possible.
+
+First we need data structures. There will be an array of pointers to filenodes,
+for all dictionary files currently open. Each filenode will contain
+a buffer of size |BUFSIZ+1| for raw input bytes not yet scanned,
+as well as a buffer of size |MAX_LENGTH_LIMIT+1| for the current word
+being considered.
+
+@<Typedefs@>=
+typedef struct filenode_struct {
+  struct filenode_struct *link; /* pointer to next open file */
+  FILE *dfile; /* dictionary file */
+  byte buf[BUFSIZ+1], curword[MAX_LENGTH_LIMIT+1];
+  byte *pos; /* current position in |buf| */
+  byte *limit; /* end of input bytes in |buf| */
+  byte *endword; /* the first break character in |curword| */
+} filenode;
+
+@ @<Allocate data structures...@>=
+if (targc) {
+  curfile=(filenode*)calloc(targc,sizeof(filenode));
+  if (curfile==NULL) out_of_mem(-7);
+  for (f=curfile;f<curfile+targc-1;f++) f->link=f+1;
+  f->link=curfile; /* circular linking */
+} else curfile=NULL;
+
+@ @<Local...@>=
+filenode *curfile; /* current filenode of interest */
+filenode *f; /* temporary register for filenode list processing */
+
+@ @<Open the dictionary file named |*targv|@>=
+{
+  curfile->dfile=fopen((char*)*targv,"r");
+  if (curfile->dfile==NULL) {
+    fprintf(stderr,"%s: Can't open dictionary file %s!\n",*argv,(char*)*targv);
+    return -8;
+  }
+  curfile->pos=curfile->limit=curfile->buf; /* |buf| is empty */
+  curfile->buf[0]='\0';
+  curfile->endword=curfile->curword; /* |curword| is empty too */
+  curfile->curword[0]=breakchar;
+  curfile=curfile->link; /* move to next filenode */
+}
+
+@ We will implicitly merge the dictionaries together by using a brute force
+scheme that works fine when there are only a few of them. Namely,
+|curfile| will point to a file having the currently smallest
+current word. To get to the next word of the merge, we advance to the
+next word in that file, comparing it with the current words of the
+other files to see if |curfile| should switch to one of them.
+When we get to the end of a file, its filenode simply leaves the circular
+list. Eventually the list will be empty, and we will set |curfile| to
+|NULL|; we will then have seen all the dictionary words in order.
+
+@ @<Output |p->keyword|, if it's not in the dictionaries@>=
+while (curfile!=NULL) {
+  for (u=p->keyword,v=curfile->curword;ord[*u]==ord[*v];u++,v++) ;
+  if (*u=='\0' && *v==breakchar) goto word_done;
+    /* we found it in the dictionary */
+  if (ord[*u]<ord[*v]) break; /* we didn't find it */
+  @<Advance to the next dictionary word@>;
+}
+@<Print |p->keyword| and |breakchar| on |stdout|@>@;
+word_done:;
+
+@ @<Print |p->keyword| and |breakchar| on |stdout|@>=
+for (u=p->keyword;*u;u++) putchar(*u);
+putchar(breakchar);
+
+@ @<Advance...@>=
+@<Read a new word into |curfile->curword|, as fast as you can@>;
+@<Adjust |curfile|, if necessary, to point to a file with minimal
+  |curword|@>;
+
+@ The dictionaries are supposed to be in order, and they shouldn't
+contain nulls. But if they fail to meet these criteria, we don't want
+{\tt wordtest} to crash; it should just run more slowly and/or more
+peculiarly.
+
+The logic of the code here removes null characters, at the cost of speed.
+If the dictionary contains words out of order, say $\alpha>\beta$ where
+$\alpha$ precedes $\beta$ in the file, the effect will be as if $\beta$
+were not present. (In particular, if the dictionary would happen to have a null
+word because of a break character inserted by our |max_length| logic,
+that null word would cause no harm, because a null word is always less than
+any nonnull word.)
+
+A null character always appears in |curfile->limit|.
+
+@<Read a new word into |curfile->curword|...@>=
+v=curfile->curword;
+l=max_length; /* here |l| represents max characters to put in |curword| */
+while (1) {@+register byte *w=curfile->limit;
+  u=curfile->pos;
+  if (u+l>=w)
+    while (ord[*u]>0) *v++=*u++; /* this is the inner loop */
+  else {
+    w=u+l;
+    c=*w;
+    *w='\0'; /* temporarily store a null to avoid overlong string */
+    while (ord[*u]>0) *v++=*u++; /* this too is the inner loop */
+    *w=c; /* restore the damaged byte */
+  }
+  if (ord[*u]<0) {
+    curfile->pos=u+1; /* good, we found the next break character */
+    break;
+  }
+  l-=u-curfile->pos;
+  if (l==0) { /* |max_length| reached */
+    curfile->pos=u;
+    break;
+  }
+  if (u==w) { /* we're at |curfile->limit| */
+    @<Refill |curfile->buf|; or remove the current file from the
+      circular list and |goto update_done|, if it has ended@>;
+  } else curfile->pos=u+1; /* bypass a null character in the dictionary */
+}
+curfile->endword=v;
+*v=breakchar;
+update_done:;
+
+@ @<Refill |curfile->buf|...@>=
+if (ferror(curfile->dfile)) {
+  fprintf(stderr,"%s: File read error on dictionary file!\n",*argv);
+  return -9;
+}
+if (feof(curfile->dfile)) {
+  f=curfile->link;
+  if (f==curfile) curfile=NULL; /* the last dictionary file has ended */
+  else {
+    while (f->link!=curfile) f=f->link;
+    f->link=curfile->link; /* remove a filenode from the circular list */
+    curfile=f; /* and point to one of the remaining filenodes */
+  }
+  goto update_done;
+}
+curfile->limit=curfile->buf+fread(curfile->buf,1,BUFSIZ,curfile->dfile);
+*curfile->limit='\0';
+curfile->pos=curfile->buf;
+
+@ @<Adjust |curfile|, if necessary...@>=
+if (curfile!=NULL) {@+filenode *sentinel=curfile;
+  for (f=curfile->link;f!=sentinel;f=f->link)
+    @<Change |curfile| to |f| if |f->curword<curfile->curword|@>;    
+}
+
+@ @<Change |curfile| to |f| if |f->curword<curfile->curword|@>=
+{
+  *f->endword='\0';
+  for (u=f->curword,v=curfile->curword;ord[*u]==ord[*v];u++,v++) ;
+  if (ord[*u]<ord[*v]) curfile=f;
+  *f->endword=breakchar;
+}
+
+@* Index. Here is a list of the identifiers used by {\tt wordtest},
+showing the sections in which they appear, underlined at points
+of definition.


Property changes on: trunk/Build/source/texk/web2c/cwebdir/examples/wordtest.w
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/texk/web2c/cwebdir/examples/xlib_types.w
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/examples/xlib_types.w	                        (rev 0)
+++ trunk/Build/source/texk/web2c/cwebdir/examples/xlib_types.w	2018-12-30 18:59:26 UTC (rev 49537)
@@ -0,0 +1,92 @@
+ at q This file tells CWEAVE to treat X11/Xlib types as reserved words. @>
+
+ at s XExtData int
+ at s XExtCodes int
+ at s _XExtension int
+ at s XPixmapFormatValues int
+ at s XGCValues int
+ at s GC int
+ at s Visual int
+ at s Depth int
+ at s Screen int
+ at s ScreenFormat int
+ at s XSetWindowAttributes int
+ at s XWindowAttributes int
+ at s XHostAddress int
+ at s XImage int
+ at s XWindowChanges int
+ at s XColor int
+ at s XSegment int
+ at s XPoint int
+ at s XRectangle int
+ at s XArc int
+ at s XKeyboardControl int
+ at s XKeyboardState int
+ at s XTimeCoord int
+ at s XModifierKeymap int
+ at s Display int
+ at s XKeyEvent int
+ at s XKeyPressedEvent int
+ at s XKeyReleasedEvent int
+ at s XButtonEvent int
+ at s XButtonPressedEvent int
+ at s XButtonReleasedEvent int
+ at s XMotionEvent int
+ at s XPointerMovedEvent int
+ at s XCrossingEvent int
+ at s XEnterWindowEvent int
+ at s XLeaveWindowEvent int
+ at s XFocusChangeEvent int
+ at s XFocusInEvent int
+ at s XFocusOutEvent int
+ at s XKeymapEvent int
+ at s XExposeEvent int
+ at s XGraphicsExposeEvent int
+ at s XNoExposeEvent int
+ at s XVisibilityEvent int
+ at s XCreateWindowEvent int
+ at s XDestroyWindowEvent int
+ at s XUnmapEvent int
+ at s XMapEvent int
+ at s XMapRequestEvent int
+ at s XReparentEvent int
+ at s XConfigureEvent int
+ at s XGravityEvent int
+ at s XResizeRequestEvent int
+ at s XConfigureRequestEvent int
+ at s XCirculateEvent int
+ at s XCirculateRequestEvent int
+ at s XPropertyEvent int
+ at s XSelectionClearEvent int
+ at s XSelectionRequestEvent int
+ at s XSelectionEvent int
+ at s XColormapEvent int
+ at s XClientMessageEvent int
+ at s XMappingEvent int
+ at s XErrorEvent int
+ at s XAnyEvent int
+ at s XEvent int
+ at s _XQEvent int
+ at s XCharStruct int
+ at s XFontProp int
+ at s XFontStruct int
+ at s XTextItem int
+ at s XChar2b int
+ at s XTextItem16 int
+ at s XEDataObject int
+ at s XErrorHandler int
+ at s XIOErrorHandler int
+ at s XID int
+ at s Window int
+ at s Drawable int
+ at s Font int
+ at s Pixmap int
+ at s Cursor int
+ at s Colormap int
+ at s GContext int
+ at s KeySym int
+ at s Mask int
+ at s Atom int
+ at s VisualID int
+ at s Time int
+ at s KeyCode int


Property changes on: trunk/Build/source/texk/web2c/cwebdir/examples/xlib_types.w
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/texk/web2c/cwebdir/examples/xview_types.w
===================================================================
--- trunk/Build/source/texk/web2c/cwebdir/examples/xview_types.w	                        (rev 0)
+++ trunk/Build/source/texk/web2c/cwebdir/examples/xview_types.w	2018-12-30 18:59:26 UTC (rev 49537)
@@ -0,0 +1,274 @@
+ at q This file tells CWEAVE to treat XView types as reserved words. @>
+
+ at s Attr_attribute int
+ at s Attr_avlist int
+ at s Attr_base_cardinality int
+ at s Attr_base_type int
+ at s Attr_cu_type int
+ at s Attr_generic int
+ at s Attr_list_ptr_type int
+ at s Attr_list_type int
+ at s Attr_pkg int
+ at s Attr_union int
+ at s Canvas int
+ at s Canvas_attribute int
+ at s Canvas_paint_attribute int
+ at s Canvas_paint_window int
+ at s Canvas_view int
+ at s Canvas_view_attribute int
+ at s Cms int
+ at s Cms_attribute int
+ at s Cms_type int
+ at s Cursor_attribute int
+ at s Cursor_drag_state int
+ at s Cursor_drag_type int
+ at s Defaults_pairs int
+ at s Destroy_status int
+ at s Dnd int
+ at s DndDragType int
+ at s Dnd_attribute int
+ at s Drag_drop int
+ at s Drawable_attr int
+ at s Drawable_attribute int
+ at s Drop_site_item int
+ at s Enumerator int
+ at s Error_attr int
+ at s Error_attribute int
+ at s Error_layer int
+ at s Error_severity int
+ at s Event int
+ at s Firm_event int
+ at s Font_attribute int
+ at s Font_string_dims int
+ at s Font_type int
+ at s Frame int
+ at s Frame_accelerator int
+ at s Frame_attribute int
+ at s Frame_cmd int
+ at s Frame_cmd_pin_state int
+ at s Frame_focus_direction int
+ at s Frame_help int
+ at s Frame_props int
+ at s Fullscreen int
+ at s Fullscreen_attr int
+ at s Fullscreen_attribute int
+ at s Fullscreen_grab_mode int
+ at s Icon int
+ at s Icon_attribute int
+ at s Inputmask int
+ at s Kbd_cmds_value int
+ at s Menu int
+ at s Menu_attribute int
+ at s Menu_class int
+ at s Menu_feedback int
+ at s Menu_generate int
+ at s Menu_item int
+ at s Notice_attribute int
+ at s Notify_arg int
+ at s Notify_client int
+ at s Notify_copy int
+ at s Notify_dump_type int
+ at s Notify_error int
+ at s Notify_event int
+ at s Notify_event_type int
+ at s Notify_func int
+ at s Notify_release int
+ at s Notify_signal_mode int
+ at s Notify_value int
+ at s Openwin int
+ at s Openwin_attribute int
+ at s Openwin_split_direction int
+ at s Panel int
+ at s Panel_abbrev_menu_button_item int
+ at s Panel_attr int
+ at s Panel_attribute int
+ at s Panel_attribute_value int
+ at s Panel_button_item int
+ at s Panel_choice_item int
+ at s Panel_drop_target_item int
+ at s Panel_gauge_item int
+ at s Panel_item int
+ at s Panel_item_type int
+ at s Panel_list_item int
+ at s Panel_list_mode int
+ at s Panel_list_op int
+ at s Panel_message_item  int
+ at s Panel_multiline_text_item int
+ at s Panel_numeric_text_item int
+ at s Panel_ops int
+ at s Panel_paint_window int
+ at s Panel_setting int
+ at s Panel_slider_item int
+ at s Panel_status int
+ at s Panel_text_item int
+ at s Panel_view int
+ at s Pixwin int
+ at s Pw_pixel_cache int
+ at s Rect int
+ at s Rectlist int
+ at s Rectnode int
+ at s Screen_attr int
+ at s Screen_attribute int
+ at s Scroll_motion int
+ at s Scrollable_panel int
+ at s Scrollbar int
+ at s Scrollbar_attr int
+ at s Scrollbar_attribute int
+ at s Scrollbar_motion int
+ at s Scrollbar_setting int
+ at s Sel_cmpat_info int
+ at s Sel_prop_info int
+ at s Selection int
+ at s Selection_attr int
+ at s Selection_attribute int
+ at s Selection_item int
+ at s Selection_owner int
+ at s Selection_requestor int
+ at s Seln_access int
+ at s Seln_attribute int
+ at s Seln_client int
+ at s Seln_file_info int
+ at s Seln_function int
+ at s Seln_function_buffer int
+ at s Seln_functions_state int
+ at s Seln_holder int
+ at s Seln_holders_all int
+ at s Seln_inform_args int
+ at s Seln_level int
+ at s Seln_rank int
+ at s Seln_replier_data int
+ at s Seln_request int
+ at s Seln_requester int
+ at s Seln_response int
+ at s Seln_result int
+ at s Seln_state int
+ at s Server_attr int
+ at s Server_attribute int
+ at s Server_image int
+ at s Server_image_attribute int
+ at s Termsw int
+ at s Termsw_attribute int
+ at s Termsw_mode int
+ at s Termsw_view int
+ at s Text int
+ at s Textsw int
+ at s Textsw_action int
+ at s Textsw_attribute int
+ at s Textsw_enum int
+ at s Textsw_expand_status int
+ at s Textsw_filter_attribute int
+ at s Textsw_filter_command int
+ at s Textsw_index int
+ at s Textsw_mark int
+ at s Textsw_menu_cmd int
+ at s Textsw_opaque int
+ at s Textsw_status int
+ at s Textsw_view int
+ at s Tty int
+ at s Tty_attribute int
+ at s Tty_view int
+ at s Ttysubwindow int
+ at s Vuid_addr_probe int
+ at s Vuid_device int
+ at s WM_Direction int
+ at s Win_enum_node int
+ at s Win_enum_result int
+ at s Win_tree_layer int
+ at s Window_attr int
+ at s Window_attribute int
+ at s Window_handle int
+ at s Window_input_event int
+ at s Window_layout_op int
+ at s Window_rescale_rect_obj int
+ at s Window_rescale_state int
+ at s Window_type int
+ at s Ws_scale int
+ at s Ws_scale_list int
+ at s Xv_Color_info int
+ at s Xv_Cursor int
+ at s Xv_Drawable int
+ at s Xv_Font int
+ at s Xv_Notice int
+ at s Xv_Screen int
+ at s Xv_Server int
+ at s Xv_Window int
+ at s Xv_attr int
+ at s Xv_attribute int
+ at s Xv_base int
+ at s Xv_canvas int
+ at s Xv_canvas_pw int
+ at s Xv_canvas_view int
+ at s Xv_cms_struct int
+ at s Xv_cmsdata int
+ at s Xv_cursor int
+ at s Xv_cursor_struct int
+ at s Xv_dnd_struct int
+ at s Xv_drag_drop int
+ at s Xv_drawable int
+ at s Xv_drawable_struct int
+ at s Xv_drop_site int
+ at s Xv_drop_site_struct int
+ at s Xv_embedding int
+ at s Xv_focus_rank int
+ at s Xv_font int
+ at s Xv_font_struct int
+ at s Xv_frame_base int
+ at s Xv_frame_class int
+ at s Xv_frame_cmd int
+ at s Xv_frame_help int
+ at s Xv_frame_props int
+ at s Xv_fullscreen int
+ at s Xv_generic_attr int
+ at s Xv_generic_attribute int
+ at s Xv_generic_struct int
+ at s Xv_icon int
+ at s Xv_icon_header_info int
+ at s Xv_item int
+ at s Xv_menu int
+ at s Xv_menu_item int
+ at s Xv_Notice int
+ at s Xv_notice int
+ at s Xv_notice_struct int
+ at s Xv_object int
+ at s Xv_opaque int
+ at s Xv_openwin int
+ at s Xv_panel int
+ at s Xv_panel_ambtn int
+ at s Xv_panel_button int
+ at s Xv_panel_choice int
+ at s Xv_panel_drop int
+ at s Xv_panel_extension_item int
+ at s Xv_panel_gauge int
+ at s Xv_panel_list int
+ at s Xv_panel_message int
+ at s Xv_panel_multiline_text int
+ at s Xv_panel_num_text int
+ at s Xv_panel_or_item int
+ at s Xv_panel_slider int
+ at s Xv_panel_text int
+ at s Xv_panel_view int
+ at s Xv_pkg int
+ at s Xv_Screen int
+ at s Xv_screen int
+ at s Xv_screen_struct int
+ at s Xv_scrollbar int
+ at s Xv_sel int
+ at s Xv_sel_item int
+ at s Xv_sel_owner int
+ at s Xv_sel_requestor int
+ at s Xv_Server int
+ at s Xv_server int
+ at s Xv_server_image int
+ at s Xv_server_struct int
+ at s Xv_singlecolor int
+ at s Xv_termsw int
+ at s Xv_termsw_view int
+ at s Xv_textsw int
+ at s Xv_textsw_view int
+ at s Xv_tty int
+ at s Xv_tty_view int
+ at s Xv_window int
+ at s Xv_window_struct int
+ at s Xv_xrectlist int
+ at s icon_header_handle int
+ at s icon_header_object int


Property changes on: trunk/Build/source/texk/web2c/cwebdir/examples/xview_types.w
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property


More information about the tex-live-commits mailing list