summaryrefslogtreecommitdiff
path: root/web/c_cpp/c2cweb
diff options
context:
space:
mode:
Diffstat (limited to 'web/c_cpp/c2cweb')
-rw-r--r--web/c_cpp/c2cweb/COPYING339
-rw-r--r--web/c_cpp/c2cweb/Makefile146
-rw-r--r--web/c_cpp/c2cweb/c2cweb.c1195
-rw-r--r--web/c_cpp/c2cweb/c2cweb.def3
-rw-r--r--web/c_cpp/c2cweb/c2cweb.dvibin0 -> 73904 bytes
-rw-r--r--web/c_cpp/c2cweb/c2cweb.ger17
-rw-r--r--web/c_cpp/c2cweb/c2cweb.txt479
-rw-r--r--web/c_cpp/c2cweb/c2cweb.w1406
-rw-r--r--web/c_cpp/c2cweb/compiler.w71
-rw-r--r--web/c_cpp/c2cweb/cweb/Makefile106
-rw-r--r--web/c_cpp/c2cweb/cweb/common.c1280
-rw-r--r--web/c_cpp/c2cweb/cweb/common.ch83
-rw-r--r--web/c_cpp/c2cweb/cweb/common.h201
-rw-r--r--web/c_cpp/c2cweb/cweb/common.w1415
-rw-r--r--web/c_cpp/c2cweb/cweb/cweave.c4543
-rw-r--r--web/c_cpp/c2cweb/cweb/cweave.ch1095
-rw-r--r--web/c_cpp/c2cweb/cweb/cweave.def3
-rw-r--r--web/c_cpp/c2cweb/cweb/cweave.w4505
-rw-r--r--web/c_cpp/c2cweb/cweb/cwebmac.ori346
-rw-r--r--web/c_cpp/c2cweb/cweb/cwebmac.tex375
-rw-r--r--web/c_cpp/c2cweb/cweb/cwebmaca.tex381
-rw-r--r--web/c_cpp/c2cweb/cweb/prod-alt.w303
-rw-r--r--web/c_cpp/c2cweb/example.c98
-rw-r--r--web/c_cpp/c2cweb/example.h20
-rw-r--r--web/c_cpp/c2cweb/history.txt122
25 files changed, 18532 insertions, 0 deletions
diff --git a/web/c_cpp/c2cweb/COPYING b/web/c_cpp/c2cweb/COPYING
new file mode 100644
index 0000000000..a43ea2126f
--- /dev/null
+++ b/web/c_cpp/c2cweb/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/web/c_cpp/c2cweb/Makefile b/web/c_cpp/c2cweb/Makefile
new file mode 100644
index 0000000000..616b2af16e
--- /dev/null
+++ b/web/c_cpp/c2cweb/Makefile
@@ -0,0 +1,146 @@
+# This file is part of the c2cweb package Version 1.5 (10-Nov-1996)
+
+# GNU Makefile for c2cweb
+
+# you should use the CWEAVE program of this package
+
+.PHONY: default all debug documentation clean \
+ do_all cweb
+.CAUTIOUS: c2cweb.c
+
+
+default:
+ @echo " say "
+ @echo ". "
+ @echo " make <TARGET> OS=<SYSTEM> "
+ @echo ". "
+ @echo " SYSTEM can be one of the following:"
+ @echo ". "
+ @echo " unix (gcc) "
+ @echo " os2 bound (emx) "
+ @echo " dos (djgpp) "
+ @echo ". "
+ @echo " TARGET can be one of the following:"
+ @echo ". "
+ @echo " all debug "
+ @echo " documentation "
+ @echo " clean "
+
+
+ifdef OS
+
+ ifeq ($(OS),unix)
+ CC = gcc -Wall -O
+ O = .o
+ LIB =
+ EXE =
+ CP = cp
+ RM = rm -f
+ endif
+
+ ifeq ($(OS),os2)
+ CC = gcc -Wall -Zomf -Zmtd -O
+ O = .obj
+ LIB = c2cweb.def
+ EXE = .exe
+ CP = copy
+ RM = del
+ endif
+
+ ifeq ($(OS),dos)
+ CC = gcc -Wall -O
+ O = .o
+ LIB =
+ EXE = .exe
+ CP = copy
+ RM = del
+ endif
+
+ ifeq ($(OS),bound)
+ CC = gcc -Wall -O
+ O = .o
+ LIB =
+ EXE = .exe
+ CP = copy
+ RM = del
+ endif
+
+
+ ifeq ($(OS),unix)
+ define sub_make
+ cd cweb; make $@
+ endef
+ else
+ define sub_make
+ cd cweb
+ make $@
+ cd ..
+ endef
+ endif
+
+
+ OBJ = c2cweb$O
+ OUR_CWEAVE = cweb/cweave
+
+ %$O: %.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+ %.c: %.w %.ch
+ $(CTANGLE) $^ $@
+ %.c: %.w
+ $(CTANGLE) $<
+
+ %.tex: %.w %.ch
+ $(OUR_CWEAVE) +ai $^ $@
+ %.tex: %.w
+ $(OUR_CWEAVE) +ai $<
+
+
+ all:
+ $(MAKE) do_all CFLAGS=-s
+
+ debug:
+ $(MAKE) do_all CFLAGS=-g
+
+ # this builds a .dvi-file
+ # for .dvi files of cweave etc. please get the original CWEB package
+ documentation: c2cweb.dvi
+
+ # remove the unnecessary files.
+ clean:
+ $(sub_make)
+ -$(RM) *$O
+ -$(RM) *.tex
+ -$(RM) *.scn
+ -$(RM) *.toc
+ -$(RM) *.idx
+ -$(RM) *.log
+
+
+ do_all: cweb c2cweb$(EXE)
+
+ cweb:
+ $(sub_make)
+
+ c2cweb$(EXE): $(OBJ)
+ ifeq ($(OS),dos)
+ $(CC) $(CFLAGS) -o $(basename $@) $^
+ strip $(basename $@)
+ coff2exe $(basename $@)
+ -$(RM) $(basename $@)
+ else
+ $(CC) $(CFLAGS) -o $@ $^ $(LIB)
+ endif
+
+ c2cweb.dvi: c2cweb.tex cweb/cwebmaca.tex
+ -$(RM) cwebmaca.tex
+ $(CP) cweb/cwebmaca.tex .
+ $(TEX) c2cweb
+
+else # ifdef OS
+
+ all debug documentation clean: default
+
+endif
+
+# end of Makefile
diff --git a/web/c_cpp/c2cweb/c2cweb.c b/web/c_cpp/c2cweb/c2cweb.c
new file mode 100644
index 0000000000..f5869cf8b5
--- /dev/null
+++ b/web/c_cpp/c2cweb/c2cweb.c
@@ -0,0 +1,1195 @@
+#define banner "\nThis is c2cweb Version 1.5 (c) 1996 by Werner Lemberg\n\n" \
+ \
+
+#define FALSE 0
+#define TRUE 1
+#define DONE 2
+#define WAIT 3 \
+
+#define DIR_LENGTH 80
+#define TITLE_LENGTH 100
+#define PATH_SEPARATOR '/' \
+
+#define FILE_NAME_LENGTH 80 \
+
+#define BUFFER_LENGTH 500 \
+
+#define xisspace(c) (isspace(c) &&((unsigned char) c<0200) ) \
+
+/*4:*/
+#line 120 "c2cweb.w"
+
+/*5:*/
+#line 155 "c2cweb.w"
+
+#include <ctype.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/*:5*/
+#line 121 "c2cweb.w"
+;
+/*11:*/
+#line 370 "c2cweb.w"
+
+void open_files(char*);
+
+/*:11*//*14:*/
+#line 464 "c2cweb.w"
+
+void handle_input(void);
+
+
+/*:14*//*33:*/
+#line 1145 "c2cweb.w"
+
+void usage(void);
+
+/*:33*//*35:*/
+#line 1171 "c2cweb.w"
+
+void modify_filename(char*);
+
+
+/*:35*//*38:*/
+#line 1211 "c2cweb.w"
+
+char*get_line(void);
+
+
+/*:38*//*41:*/
+#line 1250 "c2cweb.w"
+
+char*protect_underlines(char*);
+
+
+/*:41*//*43:*/
+#line 1276 "c2cweb.w"
+
+#ifndef __EMX__
+char*_getname(char*);
+#endif
+
+
+/*:43*/
+#line 122 "c2cweb.w"
+;
+/*8:*/
+#line 249 "c2cweb.w"
+
+int tab_length= 4;
+int verbatim= FALSE;
+int user_linefeed= FALSE;
+int one_side= FALSE;
+char outdir[DIR_LENGTH+1];
+char include_file[FILE_NAME_LENGTH+1];
+char title[TITLE_LENGTH+1];
+
+#ifdef __EMX__
+char optchar[]= "-/";
+char pathsepchar[]= "\\/";
+#else
+char optchar[]= "-";
+char pathsepchar[]= "/";
+#endif
+
+char at_nmb[]= "@#";
+
+
+
+/*:8*//*10:*/
+#line 365 "c2cweb.w"
+
+FILE*in,*out;
+
+
+/*:10*//*15:*/
+#line 471 "c2cweb.w"
+
+char buffer[BUFFER_LENGTH+1];
+
+/*:15*//*37:*/
+#line 1205 "c2cweb.w"
+
+int line_number= 0;
+int column;
+
+
+/*:37*//*40:*/
+#line 1245 "c2cweb.w"
+
+char tempbuf[2*FILE_NAME_LENGTH+1];
+
+
+/*:40*/
+#line 123 "c2cweb.w"
+;
+
+void main(argc,argv)
+int argc;
+char*argv[];
+
+{int i;
+char buffer[DIR_LENGTH+FILE_NAME_LENGTH+1];
+char*p,*q;
+
+
+printf(banner);
+
+#ifdef __EMX__
+_response(&argc,&argv);
+_wildcard(&argc,&argv);
+#endif
+
+/*9:*/
+#line 271 "c2cweb.w"
+
+{char c;
+int i;
+
+
+outdir[0]= '\0';
+include_file[0]= '\0';
+title[0]= '\0';
+
+#ifdef __EMX__
+optswchar= optchar;
+#endif
+
+strcpy(title,"c2cweb output");
+
+while((c= getopt(argc,argv,"b:f:lo:t:v1"))!=EOF)
+{switch(c)
+{case'b':
+if(strchr(optchar,optarg[0]))
+
+usage();
+
+if(strlen(optarg)>=TITLE_LENGTH)
+fprintf(stderr,
+"\nTitle too long. Will use \"c2cweb output\".\n");
+else
+strcpy(title,optarg);
+break;
+case'f':
+if(strchr(optchar,optarg[0]))
+usage();
+
+if(strlen(optarg)>=FILE_NAME_LENGTH)
+fprintf(stderr,
+"\nInclude file name too long. Will be ignored.\n");
+else
+strcpy(include_file,optarg);
+break;
+case'l':
+user_linefeed= TRUE;
+break;
+case'o':
+if(strchr(optchar,optarg[0]))
+usage();
+
+if((i= strlen(optarg))>=DIR_LENGTH)
+fprintf(stderr,
+"\nOutput directory name too long. Will be ignored.\n");
+else
+{strcpy(outdir,optarg);
+if(!strchr(pathsepchar,outdir[i-1]))
+
+{outdir[i]= PATH_SEPARATOR;
+outdir[i+1]= '\0';
+}
+}
+break;
+case't':
+if(strchr(optchar,optarg[0]))
+usage();
+
+tab_length= atoi(optarg);
+if(tab_length==0||tab_length>8)
+tab_length= 4;
+break;
+case'v':
+verbatim= TRUE;
+break;
+case'1':
+one_side= TRUE;
+break;
+default:
+usage();
+break;
+}
+}
+
+if(optind==argc)
+usage();
+}
+
+
+/*:9*/
+#line 141 "c2cweb.w"
+;
+
+/*6:*/
+#line 164 "c2cweb.w"
+
+for(i= optind;i<argc-1;i++)
+{printf(" processing %s\n",argv[i]);
+
+open_files(argv[i]);
+q= protect_underlines(_getname(argv[i]));
+if((p= strrchr(q,'.'))!=NULL)
+
+
+fprintf(out,
+"@*{%s\\ZZZ{\\setbox0=\\hbox{%s}\\hskip-\\wd0}}.\n"
+"\\ind=2\n\n",q,p);
+else
+fprintf(out,"@*{%s}.\n"
+"\\ind=2\n\n",q);
+
+handle_input();
+fclose(in);
+fclose(out);
+}
+
+
+/*:6*/
+#line 143 "c2cweb.w"
+;
+/*7:*/
+#line 190 "c2cweb.w"
+
+printf(" processing %s\n",argv[i]);
+
+open_files(argv[i]);
+/*13:*/
+#line 418 "c2cweb.w"
+
+fprintf(out,
+"\\font\\symb=cmsy10\n"
+"\\font\\math=cmmi10\n"
+"\\def\\ob"
+"{\\parskip=0pt\\parindent=0pt%%\n"
+"\\let\\\\=\\BS\\let\\{=\\LB\\let\\}=\\RB\\let\\~=\\TL%%\n"
+"\\let\\ =\\SP\\let\\_=\\UL\\let\\&=\\AM\\let\\^=\\CF%%\n"
+"\\obeyspaces\\frenchspacing\\tt}\n"
+"\n"
+"\\def\\e{\\hfill\\break\\hbox{}}\n"
+"\\def\\{{\\relax\\ifmmode\\lbrace\\else$\\lbrace$\\fi}\n"
+"\\def\\}{\\relax\\ifmmode\\rbrace\\else$\\rbrace$\\fi}\n"
+"\\def\\takenone#1{\\hskip-0.1em}\n"
+"\\let\\ZZZ=\\relax\n"
+"\n"
+"%s"
+"\n"
+"\\pageno=\\contentspagenumber \\advance\\pageno by 1\n"
+"\\let\\maybe=\\iftrue\n"
+"\n"
+"\\def\\title{%s}\n"
+"\n"
+"@i compiler.w\n"
+"\n",one_side?"\\let\\lheader=\\rheader\n":"",title);
+
+if(*include_file)
+fprintf(out,
+"@i %s\n"
+"\n",include_file);
+
+for(i= optind;i<argc-1;i++)
+{strcpy(buffer,argv[i]);
+modify_filename(buffer);
+
+fprintf(out,"@i %s\n",_getname(buffer));
+}
+
+fputc('\n',out);
+
+
+
+/*:13*/
+#line 194 "c2cweb.w"
+;
+q= protect_underlines(_getname(argv[i]));
+if((p= strrchr(q,'.'))!=NULL)
+fprintf(out,
+"@*{%s\\ZZZ{\\setbox0=\\hbox{%s}\\hskip-\\wd0}}.\n"
+"\\ind=2\n\n",q,p);
+else
+fprintf(out,"@*{%s}.\n"
+"\\ind=2\n\n",q);
+
+handle_input();
+/*32:*/
+#line 1137 "c2cweb.w"
+
+fprintf(out,
+"\n"
+"@*Index.\n"
+"\\let\\ZZZ=\\takenone\n");
+
+
+/*:32*/
+#line 205 "c2cweb.w"
+;
+
+strcpy(buffer,argv[argc-1]);
+modify_filename(buffer);
+
+printf(
+"\n You must now call CWEAVE with %s%s\n"
+" as the argument to get a TeX output",outdir,_getname(buffer));
+if(optind<argc-1)
+printf(" of all processed files");
+printf("\n");
+
+
+
+/*:7*/
+#line 144 "c2cweb.w"
+;
+
+fclose(in);
+fclose(out);
+}
+
+
+/*:4*//*12:*/
+#line 374 "c2cweb.w"
+
+void open_files(filename)
+char*filename;
+{char buffer[DIR_LENGTH+FILE_NAME_LENGTH+1];
+
+
+if(strlen(filename)>FILE_NAME_LENGTH-2)
+{fprintf(stderr,"\n File name too long.\n");
+exit(-1);
+}
+
+if((in= fopen(filename,"rt"))==NULL)
+{fprintf(stderr,"\n Can't open input file %s\n",filename);
+exit(-1);
+}
+
+strcpy(buffer,outdir);
+strcat(buffer,filename);
+modify_filename(buffer);
+
+if((out= fopen(buffer,"wt"))==NULL)
+{fprintf(stderr,"\n Can't open output file %s\n",buffer);
+exit(-1);
+}
+}
+
+
+
+/*:12*//*16:*/
+#line 480 "c2cweb.w"
+
+void handle_input(void)
+{char*buf_p;
+char ch;
+/*17:*/
+#line 571 "c2cweb.w"
+
+int any_input= FALSE;
+
+int brace_count= 0;
+int blank_count= 0;
+
+int in_comment= FALSE;
+int in_C= FALSE;
+int in_string= FALSE;
+int short_comment= FALSE;
+int leading_blanks= TRUE;
+int double_linefeed= FALSE;
+int linefeed_comment= FALSE;
+
+int comment_slash= FALSE;
+int comment_star= FALSE;
+int escape_state= FALSE;
+
+
+int before_TeX_text= FALSE;
+
+int function_blocks= FALSE;
+
+
+/*:17*/
+#line 484 "c2cweb.w"
+;
+
+line_number= 0;
+while(get_line())
+{buf_p= buffer;
+
+do
+{ch= *buf_p;
+
+/*18:*/
+#line 598 "c2cweb.w"
+
+/*19:*/
+#line 690 "c2cweb.w"
+
+if(buf_p==buffer)
+{if(!(in_comment||in_string))
+{if(!strncmp(buf_p,"/""*@@*""/",6))
+{in_C= FALSE;
+before_TeX_text= TRUE;
+function_blocks= WAIT;
+brace_count= 0;
+
+if(any_input)
+fputs("\n@\n"
+"\\ind=2\n\n",out);
+
+
+any_input= FALSE;
+*(buf_p--)= '\n';
+
+goto end;
+}
+else if(!strncmp(buf_p,"/""*@*""/",5))
+{in_C= FALSE;
+before_TeX_text= TRUE;
+function_blocks= FALSE;
+
+if(any_input)
+fputs("\n@\n"
+"\\ind=2\n\n",out);
+
+any_input= FALSE;
+*(buf_p--)= '\n';
+goto end;
+}
+else if(!strncmp(buf_p,"/""*{*""/",5))
+{brace_count++;
+fputs("@{\n",out);
+
+ch= '\n';
+goto end;
+}
+else if(!strncmp(buf_p,"/""*}*""/",5))
+{brace_count--;
+fputs("@}\n",out);
+
+if(!brace_count&&function_blocks)
+
+{in_C= FALSE;
+before_TeX_text= TRUE;
+
+break;
+}
+
+ch= '\n';
+goto end;
+}
+else if(!strncmp(buf_p,"/""*{}*""/",6))
+{fputs("@{@}\n",out);
+
+ch= '\n';
+goto end;
+}
+}
+}
+
+
+/*:19*/
+#line 599 "c2cweb.w"
+;
+
+if(double_linefeed&&ch=='/')
+linefeed_comment= TRUE;
+
+if(double_linefeed&&(ch==' '||ch=='\t'))
+leading_blanks= TRUE;
+
+if(ch!='\n')
+double_linefeed= FALSE;
+
+if(!xisspace(ch))
+{any_input= TRUE;
+
+if(before_TeX_text&&function_blocks)
+{before_TeX_text= FALSE;
+
+if(function_blocks==WAIT)
+function_blocks= TRUE;
+
+else
+{fputs("@\n"
+"\\ind=2\n\n",out);
+
+
+if(leading_blanks)
+{leading_blanks= FALSE;
+
+while(blank_count--)
+fputc(' ',out);
+blank_count= 0;
+}
+}
+}
+
+if(in_comment&&leading_blanks)
+{leading_blanks= FALSE;
+
+while(blank_count--)
+fputc(' ',out);
+blank_count= 0;
+}
+}
+
+if(!(ch=='/'||xisspace(ch)))
+
+{if(!(in_comment||in_C||comment_slash))
+
+{in_C= TRUE;
+
+fputs("@c\n",out);
+
+if(leading_blanks)
+{leading_blanks= FALSE;
+
+while(blank_count--)
+fputc(' ',out);
+blank_count= 0;
+}
+}
+
+if(!(in_comment||comment_slash)&&leading_blanks)
+{leading_blanks= FALSE;
+
+while(blank_count--)
+fputc(' ',out);
+blank_count= 0;
+}
+}
+
+if(comment_slash&&!(ch=='*'||ch=='/'))
+
+{comment_slash= FALSE;
+if(!in_comment)
+linefeed_comment= FALSE;
+
+fputc('/',out);
+}
+
+if(comment_star&&ch!='/')
+{comment_star= FALSE;
+
+fputc('*',out);
+}
+
+if(escape_state&&!(ch=='\"'||ch=='\n'||ch=='\\'))
+
+escape_state= FALSE;
+
+
+/*:18*/
+#line 493 "c2cweb.w"
+;
+
+switch(ch)
+{case' ':
+if(leading_blanks)
+{blank_count++;
+goto end;
+}
+break;
+
+case'\t':
+{int i= tab_length-(column%tab_length);
+
+column+= i-1;
+
+if(leading_blanks)
+{blank_count+= i;
+goto end;
+}
+
+while(i--)
+fputc(' ',out);
+goto end;
+}
+break;
+
+case'{':
+/*20:*/
+#line 755 "c2cweb.w"
+
+if(in_comment)
+fputc('\\',out);
+else if(in_string)
+break;
+else if(function_blocks)
+{brace_count++;
+in_C= TRUE;
+}
+
+/*:20*/
+#line 520 "c2cweb.w"
+;
+break;
+
+case'}':
+/*25:*/
+#line 802 "c2cweb.w"
+
+if(in_comment)
+fputc('\\',out);
+else if(in_string)
+break;
+else if(function_blocks)
+{brace_count--;
+if(!brace_count)
+{in_C= FALSE;
+
+before_TeX_text= TRUE;
+break;
+}
+}
+
+/*:25*/
+#line 524 "c2cweb.w"
+;
+break;
+
+case'/':
+/*26:*/
+#line 818 "c2cweb.w"
+
+if(comment_star)
+{/*27:*/
+#line 832 "c2cweb.w"
+
+comment_star= FALSE;
+leading_blanks= FALSE;
+
+if(!short_comment)
+{in_comment= FALSE;
+
+if(!in_C)
+{linefeed_comment= FALSE;
+
+if(verbatim)
+fputs("*""/}",out);
+
+if(*(buf_p+1)=='\n')
+fputs("\\e{}%",out);
+
+goto end;
+}
+
+if(in_C&&verbatim)
+{if(linefeed_comment)
+{linefeed_comment= FALSE;
+
+fputs("*""/@>",out);
+if(*(buf_p+1)=='\n'&&!user_linefeed)
+fputs("@/",out);
+goto end;
+}
+else
+fputc('}',out);
+}
+
+linefeed_comment= FALSE;
+
+if(in_C||verbatim)
+fputc('*',out);
+else
+goto end;
+}
+else
+fputc('*',out);
+
+/*:27*/
+#line 820 "c2cweb.w"
+;
+}
+else if(comment_slash)
+{/*28:*/
+#line 875 "c2cweb.w"
+
+comment_slash= FALSE;
+
+if(!short_comment)
+{in_comment= TRUE;
+short_comment= TRUE;
+
+if(!in_C&&verbatim)
+{fputs("{\\ob{}",out);
+if(leading_blanks)
+{leading_blanks= FALSE;
+
+while(blank_count--)
+fputc(' ',out);
+blank_count= 0;
+}
+fputs("//",out);
+
+goto end;
+}
+
+if(in_C&&verbatim)
+{if(leading_blanks||linefeed_comment)
+{linefeed_comment= TRUE;
+
+if(!user_linefeed)
+fputs("@/",out);
+fputs("@t}\\8{\\ob{}",out);
+
+
+if(leading_blanks)
+{leading_blanks= FALSE;
+
+while(blank_count--)
+fputc(' ',out);
+blank_count= 0;
+}
+fputs("//",out);
+}
+else
+fputs("//{\\ob{}",out);
+
+goto end;
+}
+
+if(in_C||verbatim)
+fputc('/',out);
+else
+goto end;
+}
+else
+fputc('/',out);
+
+
+/*:28*/
+#line 823 "c2cweb.w"
+;
+}
+else
+{comment_slash= TRUE;
+
+goto end;
+}
+
+/*:26*/
+#line 528 "c2cweb.w"
+;
+break;
+
+case'*':
+/*29:*/
+#line 930 "c2cweb.w"
+
+if(comment_slash)
+{comment_slash= FALSE;
+
+if(in_comment&&!short_comment)
+
+
+
+
+
+
+
+{fprintf(stderr,
+" Error line %d: Nested comments not supported\n",
+line_number);
+exit(-1);
+}
+
+if(!short_comment)
+{in_comment= TRUE;
+
+if(!in_C&&verbatim)
+{fputs("{\\ob{}",out);
+if(leading_blanks)
+{leading_blanks= FALSE;
+
+while(blank_count--)
+fputc(' ',out);
+blank_count= 0;
+}
+fputs("/""*",out);
+
+goto end;
+}
+
+if(in_C&&verbatim)
+{if(leading_blanks||linefeed_comment)
+{linefeed_comment= TRUE;
+
+if(!user_linefeed)
+fputs("@/",out);
+fputs("@t}\\8{\\ob{}",out);
+if(leading_blanks)
+{leading_blanks= FALSE;
+
+while(blank_count--)
+fputc(' ',out);
+blank_count= 0;
+}
+fputs("/""*",out);
+}
+else
+fputs("/""*{\\ob{}",out);
+
+goto end;
+}
+
+if(in_C||verbatim)
+fputc('/',out);
+else
+{fputs(" ",out);
+
+goto end;
+}
+}
+else
+fputc('/',out);
+}
+else
+{comment_star= TRUE;
+
+goto end;
+}
+
+
+/*:29*/
+#line 532 "c2cweb.w"
+;
+break;
+
+case'\n':
+/*30:*/
+#line 1006 "c2cweb.w"
+
+blank_count= 0;
+
+if(!in_comment&&in_C)
+{if(double_linefeed==FALSE)
+{double_linefeed= TRUE;
+if(escape_state)
+{escape_state= FALSE;
+
+leading_blanks= TRUE;
+
+if(in_string)
+fputc('\n',out);
+else
+fputs("\n@/",out);
+goto end;
+}
+
+if(!leading_blanks&&user_linefeed)
+fputs("@/",out);
+}
+else if(double_linefeed==TRUE)
+{double_linefeed= DONE;
+
+
+fputs(at_nmb,out);
+}
+}
+
+leading_blanks= TRUE;
+
+if(short_comment)
+{short_comment= FALSE;
+in_comment= FALSE;
+double_linefeed= TRUE;
+
+if(verbatim)
+{if(linefeed_comment&&in_C)
+fputs("@>",out);
+else
+fputc('}',out);
+}
+
+if(!in_C)
+fputs("\\e{}%",out);
+else if(linefeed_comment&&verbatim)
+fputs("@/",out);
+
+linefeed_comment= FALSE;
+}
+
+if(in_comment&&in_C&&verbatim&&linefeed_comment)
+{
+fputs("@>@/\n@t}\\8{\\ob{}",out);
+
+goto end;
+}
+
+if(in_comment&&verbatim)
+
+
+
+{fputs("\n\\e{}",out);
+goto end;
+}
+
+
+/*:30*/
+#line 536 "c2cweb.w"
+;
+break;
+
+case'@':
+/*21:*/
+#line 766 "c2cweb.w"
+
+if(in_comment)
+{fputs("{\\char64}",out);
+goto end;
+}
+else
+fputc('@',out);
+
+/*:21*/
+#line 540 "c2cweb.w"
+;
+break;
+
+case'\'':
+/*22:*/
+#line 775 "c2cweb.w"
+
+if(!in_comment)
+{if(*(buf_p+1)=='\"'&&*(buf_p+2)=='\'')
+escape_state= TRUE;
+}
+
+/*:22*/
+#line 544 "c2cweb.w"
+;
+break;
+
+case'\"':
+/*23:*/
+#line 782 "c2cweb.w"
+
+if(!in_comment)
+{if(escape_state)
+escape_state= FALSE;
+else
+in_string= TRUE-in_string;
+}
+
+/*:23*/
+#line 548 "c2cweb.w"
+;
+break;
+
+case'\\':
+/*24:*/
+#line 791 "c2cweb.w"
+
+if(in_comment)
+{fputs("{\\symb\\char110}",out);
+goto end;
+}
+else
+escape_state= TRUE-escape_state;
+
+
+
+/*:24*/
+#line 552 "c2cweb.w"
+;
+break;
+
+default:
+/*31:*/
+#line 1077 "c2cweb.w"
+
+if(in_comment)
+{switch(ch)
+{case'#':
+fputs("{\\#}",out);
+break;
+
+case'$':
+fputs("{\\$}",out);
+break;
+
+case'%':
+fputs("{\\%}",out);
+break;
+
+case'&':
+fputs("{\\AM}",out);
+break;
+
+case'_':
+fputs("{\\_}",out);
+break;
+
+case'^':
+fputs("{\\^{}}",out);
+break;
+
+case'\\':
+fputs("{\\symb\\char110}",out);
+break;
+
+case'~':
+fputs("{\\~{}}",out);
+break;
+
+case'|':
+fputs("{\\symb\\char106}",out);
+break;
+
+case'<':
+fputs("{\\math\\char60}",out);
+break;
+
+case'>':
+fputs("{\\math\\char62}",out);
+break;
+
+default:
+fputc(ch,out);
+break;
+}
+
+goto end;
+}
+
+
+/*:31*/
+#line 556 "c2cweb.w"
+;
+break;
+}
+
+fputc(ch,out);
+
+end:
+buf_p++;
+column++;
+}while(ch!='\n');
+}
+}
+
+
+/*:16*//*34:*/
+#line 1149 "c2cweb.w"
+
+void usage(void)
+{fprintf(stderr,
+"Usage: c2cweb [switches] csourcefile(s) | @responsefile(s)"
+"\n"
+"\n possible switches:"
+"\n"
+"\n -b \"title\" set title"
+"\n -l use input linefeeds"
+"\n -o dirname set output directory (must already exist)"
+"\n -f filename use this file as a format file"
+"\n -t tablength set tabulator length (default 4)"
+"\n -v verbatim mode"
+"\n -1 one-sided output"
+"\n"
+"\n");
+
+exit(-1);
+}
+
+
+/*:34*//*36:*/
+#line 1180 "c2cweb.w"
+
+void modify_filename(name)
+char*name;
+{char*p;
+
+
+if((p= strrchr(name,'.'))!=NULL)
+{p++;
+if(*p&&*p!=' ')
+p++;
+if(*p&&*p!=' ')
+p++;
+if(*p!='w')
+*p= 'w';
+else
+*p= 'x';
+p++;
+*p= '\0';
+}
+else
+strcat(name,".w");
+}
+
+
+/*:36*//*39:*/
+#line 1218 "c2cweb.w"
+
+char*get_line(void)
+{char*p;
+int i= BUFFER_LENGTH;
+
+
+if((p= fgets(buffer,BUFFER_LENGTH+1,in))!=NULL)
+{while(i--)
+{if(*(p++)=='\n')
+break;
+}
+
+p--;
+p--;
+while((*p==' '||*p=='\t')&&p>=buffer)
+p--;
+*(p+1)= '\n';
+*(p+2)= '\0';
+
+line_number++;
+column= 0;
+}
+return(p);
+}
+
+
+/*:39*//*42:*/
+#line 1257 "c2cweb.w"
+
+char*protect_underlines(p)
+char*p;
+{char*q;
+
+
+q= tempbuf;
+
+do
+{if(*p=='_')
+*(q++)= '\\';
+*(q++)= *p;
+}while(*(p++));
+
+return tempbuf;
+}
+
+
+/*:42*//*44:*/
+#line 1287 "c2cweb.w"
+
+#ifndef __EMX__
+char*_getname(char*path)
+{char*p;
+
+p= strrchr(path,'/');
+return p==NULL?path:(p+1);
+}
+#endif
+
+
+
+/*:44*/
diff --git a/web/c_cpp/c2cweb/c2cweb.def b/web/c_cpp/c2cweb/c2cweb.def
new file mode 100644
index 0000000000..9fdd016403
--- /dev/null
+++ b/web/c_cpp/c2cweb/c2cweb.def
@@ -0,0 +1,3 @@
+NAME C2CWEB WINDOWCOMPAT
+DESCRIPTION 'C2CWEB 1.5'
+STACKSIZE 0x80000
diff --git a/web/c_cpp/c2cweb/c2cweb.dvi b/web/c_cpp/c2cweb/c2cweb.dvi
new file mode 100644
index 0000000000..f0b0fcd989
--- /dev/null
+++ b/web/c_cpp/c2cweb/c2cweb.dvi
Binary files differ
diff --git a/web/c_cpp/c2cweb/c2cweb.ger b/web/c_cpp/c2cweb/c2cweb.ger
new file mode 100644
index 0000000000..895137a5f3
--- /dev/null
+++ b/web/c_cpp/c2cweb/c2cweb.ger
@@ -0,0 +1,17 @@
+% This file is part of the c2cweb package Version 1.5
+
+% this is a small german `package' for c2cweb
+% written by Werner Lemberg (a7971428@unet.univie.ac.at) 10-Nov-1996
+
+\catcode`^^8e=\active \def ^^8e{\"A}
+\catcode`^^99=\active \def ^^99{\"O}
+\catcode`^^9a=\active \def ^^9a{\"U}
+\catcode`^^84=\active \def ^^84{\"a}
+\catcode`^^94=\active \def ^^94{\"o}
+\catcode`^^81=\active \def ^^81{\"u}
+\catcode`^^e1=\active \def ^^e1{\ss{}}
+
+\font\tentex=cmtt10
+
+
+% end of c2cweb.ger
diff --git a/web/c_cpp/c2cweb/c2cweb.txt b/web/c_cpp/c2cweb/c2cweb.txt
new file mode 100644
index 0000000000..9a7b64eb62
--- /dev/null
+++ b/web/c_cpp/c2cweb/c2cweb.txt
@@ -0,0 +1,479 @@
+
+This is the c2cweb package Version 1.5 (10-Nov-1996)
+=====================================================
+
+Copyright (C) 1996 Werner Lemberg
+
+[see below for a German introduction]
+
+
+c2cweb will transform plain C or C++ code into a CWEB file to get a pretty
+formatted output. A modified CWEAVE (which transforms the CWEB file into a
+TeX file, see below) is included also.
+
+Some c2cweb highlights:
+
+ variables and function names in italics
+ reserved words (int, char, return etc.) in bold face
+ strings in typewriter type
+ comments in typwriter type or roman
+ an index(!) of all variables, constants, function names etc.
+ each function gets a section
+
+ and more
+
+
+The c2cweb package contains the following files:
+
+ c2cweb.txt this file
+ history.txt the history file
+ Makefile a makefile to compile c2cweb for UNIX, OS/2, and DOS
+ c2cweb.def definition file (needed for compiling under OS/2
+ only)
+ COPYING the GNU Copying License
+ c2cweb.w a CWEB file of the program
+ you should say
+ make documentation (using this package's CWEAVE)
+ to produce a TeX-output
+ c2cweb.c extracted with CTANGLE from c2cweb.w
+ c2cweb.dvi the final .dvi-file
+ c2cweb.exe an executable for DOS and OS/2
+ compiler.w compiler dependent formatting commands
+ (an output of c2cweb reads this file)
+ c2cweb.ger a small german `package' to demonstrate national
+ language support
+ example.h
+ example.c a C code example with inserted c2cweb control
+ commands
+ cweb/cweave.exe a modified executable (for DOS and OS/2) of CWEAVE
+ Ver. 3.2 with three important new features:
+
+ o the switch +a causes CWEAVE to produce a
+ different output format, basically
+
+ if(a)
+ {bla bla bla...
+ }
+
+ instead of
+
+ if(a) {
+ bla bla bla...
+ }
+
+ o the switch +i causes CWEAVE to append () after a
+ function name in the index (this makes only
+ sense if all names are unique)
+ o the #define statement handling was basically
+ enhanced to allow macros with parameters
+ cweb/cweave.w this is the original CWEAVE source file of Levy's
+ CWEB package ver 3.2 (July 1994)
+ cweb/cweave.ch the change file for cweave.w
+ cweb/cweave.c extracted with CTANGLE from cweave.{w,ch}
+ cweb/common.h this is needed to build CWEAVE
+ (slightly different from the original)
+ cweb/common.w taken unaltered from CWEB 3.2
+ cweb/common.ch change file for common.w
+ cweb/common.c extracted with CTANGLE from common.{w,ch}
+ cweb/Makefile Makefile for CWEAVE (UNIX, OS/2, and DOS)
+ cweb/cweave.def definition file (needed for compiling under OS/2
+ only)
+ cweb/cwebmac.ori the standard cwebmac.tex file (slightly modified)
+ cweb/cwebmac.tex alternative format file
+ cweb/cwebmaca.tex this alternative format file is read by TeX if you
+ use the +a switch; similar to cwebmac.tex
+ cweb/prod-alt.w this file is an include file of cweave.ch; it
+ contains the alternative syntax rules of CWEAVE if
+ the switch a is on
+
+You should get the original CWEB package for further documentation; it
+contains change files for different operating systems also.
+
+
+Copying
+-------
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 as published by
+the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 675 Mass
+Ave, Cambridge, MA 02139, USA.
+
+
+Installation
+------------
+
+The c2cweb executable should be in the path.
+
+The CWEAVE executable should also be in the path; it needs the file
+compiler.w (use the environment variable CWEBINPUTS to set the path).
+
+c2cweb.ger, cwebmac.tex and cwebmaca.tex must be found by TeX (the path is
+usually controlled by the TEXINPUT environment variable).
+
+DOS and WINDOWS users must assure that emx.exe and rsx.exe can be found
+(either in the path or set with the EMX and RSX environment variables).
+
+OS/2 users must assure that emx.dll and rsx.exe can be found (either in the
+path or set with the EMX and RSX environment variables).
+
+[emx.exe, emx.dll, and rsx.exe can be found in the the emxrsx.zip package of
+ the emTeX distribution.]
+
+
+Remarks for UNIX systems users
+------------------------------
+
+Because of the many different UNIX implementations, no executables are
+included. The programs should compile without great problems if you use the
+gcc compiler, the GNU C library and gnumake; you should say
+
+ make all OS=unix
+
+in the c2cweb directory to build the binaries.
+
+Included in the package you will already find .c files extracted with
+CTANGLE which can be directly used to compile.
+
+
+How to use
+----------
+
+The only change the user has to do normally is to insert /*@@*/, starting an
+empty line outside of a comment or string before the first function block
+(normally main(){ ... }) in the C code. After this command c2cweb writes
+each function block into a section. Before /*@@*/ all stuff is written into
+a (possibly large) section. If you want to structure this further or if you
+have structure definitions between functions, use /*@*/ to start a new
+section without starting the function block algorithm (and of course /*@@*/
+before the next function). The function algorithm simply counts paired
+braces; if none are open, a new section will begin. The file example.c has
+these control codes inserted already.
+
+
+The syntax is
+
+ c2cweb [switches] csourcefile(s) | @responsefile(s)
+
+The possible switches are:
+
+-v:
+ all comments are written in typewriter type. You will need this if you
+ have already formatted your comments, for example
+
+ /********************/
+ /* example.c */
+ /********************/.
+
+-t value:
+ all tabs will be expanded, and the -t switch defines the tab length
+ (default value is 4).
+
+-l:
+ causes all linefeeds inside of C text to be output explicitly by inserting
+ @/ (a CWEB control code) at the end of each code line.
+
+-o directory:
+ sets the output directory which must exist already.
+
+-f format_file:
+ include a format file (additionally to compiler.w).
+
+-b "titlestring":
+ defines a title with the titlestring enclosed in double quotes. This
+ string will be passed directly to \TeX.
+
+-1:
+ one-sided output (i.e. left header is the same as right header).
+
+
+The last steps are calling CWEAVE with the transformed master file and then
+calling TeX to get a printable .dvi-file.
+
+
+An example:
+
+ your input files are
+ header1.h, header2.h, file1.c, file2.c, file3.c
+
+ you must call then
+ c2cweb [options] header*.h file*.c
+
+ to get the *.*w files. c2cweb will now process your files and tells you
+ which file is the input file for CWEAVE (we'll assume file3.cw).
+
+ After calling
+ cweave [options] file3.cw
+
+ you get a .tex file (and some additional auxiliary files) which should
+ be processed further by PLAIN TeX (LaTeX is not supported):
+
+ tex file3[.tex]
+
+
+Please read the `Hints and Tricks' section about enhancements and
+limitations of c2cweb in the file c2cweb.w (say `make documentation' to
+build the .dvi file).
+
+
+Author
+------
+
+Werner Lemberg (a7971428@unet.univie.ac.at)
+
+Please report any errors, comments or suggestions to this email-address.
+
+ Werner Lemberg
+ Goldschlagstr. 52/14
+ A-1150 Vienna/Austria
+
+
+
+--------------------------------------------------------------------------------
+
+
+
+c2cweb Paket Version 1.5 (10-Nov-1996)
+=======================================
+
+Copyright (C) 1996 Werner Lemberg
+
+
+c2cweb verwandelt gewoehnlichen C - oder C++ - Quellcode in eine CWEB-Datei,
+um einen gut formatierten Ausdruck zu erhalten. Dieses Paket enthaelt
+ausserdem eine modifizierte Version von CWEAVE (welche die CWEB-Datei in
+eine TeX-Datei transformiert).
+
+Besonderheiten u.a.:
+
+ Variablen und Funktionsnamen in Kursivschrift
+ reservierte Woerter (int, char, return etc.) in Fettschrift
+ Strings in Schreibmaschinenschrift
+ Kommentare in Normal- oder Schreibmaschinenschrift
+ ein Index(!) aller Variablen, Konstanten, Funktionsnamen etc.
+ jede Funktion fuellt einen eigenen Abschnitt
+
+
+Das c2cweb-Paket enthaelt folgende Dateien:
+
+ c2cweb.txt diese Datei
+ history.txt Entstehungsgeschichte von c2cweb
+ Makefile ein Makefile fuer c2cweb (UNIX, OS/2 und DOS)
+ c2cweb.def Definitionsdatei (wird nur fuer die Kompilation
+ unter OS/2 gebraucht)
+ COPYING GNU Kopierlizenz
+ c2cweb.w die CWEB-Realisation dieses Programms
+ Um eine TeX .dvi-Datei zu erhalten sollte man
+ make documentation
+ eingeben (mit der CWEAVE-Version dieses Pakets)
+ c2cweb.c extrahiert mittels CTANGLE aus c2cweb.w
+ c2cweb.dvi die finale .dvi-Datei
+ c2cweb.exe ausfuehrbares Programm fuer DOS und OS/2
+ compiler.w Compiler-abhaengige Formatierbefehle (von c2cweb
+ erzeugte Dateien inkludieren diese Datei)
+ c2cweb.ger ein kleines Deutsch-`Paket', um die Unterstuetzung
+ von nichtenglischen Sprachen zu demonstrieren.
+ example.h
+ example.c ein C-Code-Beispiel mit bereits eingefuegten
+ c2cweb-Kontrollbefehlen
+ cweb/cweave.exe eine modifizierte Version von CWEAVE Version 3.2
+ (fuer DOS und OS/2) mit drei wichtigen neuen
+ Eigenschaften:
+
+ o mit der Option +a formatiert CWEAVE den
+ Quellcode anders, und zwar im Prinzip
+
+ if(a)
+ {bla bla bla...
+ }
+
+ anstelle von
+
+ if(a) {
+ bla bla bla...
+ }
+
+ o die Option +i veranlasst CWEAVE, jedem
+ Funktionsnamen () im Index anzuhaengen (nur
+ sinnvoll, wenn alle Namen eindeutig sind)
+ o die Behandlung von Praeprozessorbefehlen
+ (#define etc.) wurde entscheidend verbessert, um
+ Makros mit Parametern zu ermoeglichen
+ cweb/cweave.w die originale CWEAVE Quelldatei aus Levy's
+ CWEB-Paket Version 3.2 (Juli 1994)
+ cweb/cweave.ch Change-Datei fuer cweave.w
+ cweb/cweave.c extrahiert aus cweave.{w,ch} mittels CTANGLE
+ cweb/common.h wird benoetigt fuer die Kompilation von cweave.exe
+ (Original wurde etwas modifiziert)
+ cweb/common.w unveraendert von CWEB 3.2 uebernommen
+ cweb/common.ch Change-Datei fuer common.w
+ cweb/common.c extrahiert aus common.{w,ch} mittels CTANGLE
+ cweb/Makefile Make-Datei fuer CWEAVE (UNIX, OS/2 und DOS)
+ cweb/cweave.def Definitionsfile (wird nur fuer die Kompilation unter
+ OS/2 gebraucht)
+ cweb/cwebmac.ori urspruengliche cwebmac.tex-Datei (leicht veraendert)
+ cweb/cwebmac.tex alternative Formatdatei
+ cweb/cwebmaca.tex diese alternative Formatdatei wird von TeX gelesen,
+ wenn die +a-Option angegeben ist; sonst gleich zu
+ cwebmac.tex
+ cweb/prod-alt.w diese Datei ist eine Include-Datei von cweave.ch;
+ sie enthaelt die alternativen Syntaxregeln, falls
+ Option +a verwendet wird
+
+Es ist empfehlenswert, sich das originale CWEB-Paket zu besorgen, welches
+weitere Dokumentation enthaelt. Ausserdem sind Change-Dateien fuer andere
+Betriebssysteme enthalten.
+
+
+Installation
+------------
+
+c2cweb (c2cweb.exe fuer DOS und OS/2 Benutzer) sollte im Pfad sein.
+
+CWEAVE (cweave.exe fuer DOS und OS/2 Benutzer) sollte auch im Pfad sein; es
+braucht die Datei compiler.w (die Umgebungsvariable CWEBINPUTS setzt den
+Pfad).
+
+TeX muss die Dateien c2cweb.ger, cwebmac.tex und cwebmaca.tex finden koennen
+(der Pfad wird normalerweise von der TEXINPUT-Umgebungsvariablen
+kontrolliert).
+
+DOS und WINDOWS Benuetzer muessen sicherstellen, dass emx.exe und rsx.exe
+gefunden werden koennen (entweder im Pfad oder durch die Umgebungsvariablen
+EMX und RSX bestimmt).
+
+OS/2 Benuetzer muessen sicherstellen, dass emx.dll und rsx.exe gefunden
+werden koennen (entweder im Pfad oder durch die Umgebungsvariablen EMX und
+RSX bestimmt).
+
+[emx.dll, emx.exe und rsx.exe koennen im Paket exmrsx.zip gefunden werden,
+ das Bestandteil von emTeX ist.]
+
+
+Bemerkungen fuer UNIX Benutzer
+------------------------------
+
+Aufgrund der vielen verschiedenen UNIX-Systeme sind keine ausfuehrbaren
+Dateien inkludiert. Die Programme sollten ohne groessere Probleme
+kompilierbar sein, wenn gcc, die GNU C-Bibliothek und gnumake verwendet
+wird.
+
+ make all OS=unix
+
+im c2cweb- und cweb-Verzeichnis erstellt die ausfuehrbaren Dateien.
+
+In diesem Paket befinden sich bereits mittels CTANGLE extrahiert .c Dateien,
+die man direkt kompilieren kann.
+
+
+Verwendung
+----------
+
+Die einzige Veraenderung, die der Anwender normalerweise machen muss, ist
+das Einfuegen von /*@@*/ am Anfang einer leeren Zeile ausserhalb eines
+Kommentars oder Strings vor dem ersten Funktionsblock (das ist in der Regel
+main(){ ...}) im C-Quellcode. Nach diesem Befehl erzeugt c2cweb fuer jede
+Funktion einen eigenen Abschnitt. Vor /*@@*/ wird alles in eine einzige
+(u.U. grosse) Sektion geschrieben. Will man solche Abschnitte zusaetzlich
+strukturieren oder hat man Struktur-Definitionen zwischen Funktionen, sollte
+man /*@*/ verwenden, um einen neuen Abschnitt zu beginnen, ohne den
+Funktionsalgorithmus einzuschalten (und natuerlich /*@@*/ vor der naechsten
+Funktion einfuegen). Der Funktionsalgorithmus zaehlt einfach paarweise
+geschwungene Klammern; falls keine mehr offen, wird ein neuer Abschnitt
+begonnen. In der Beispieldatei example.c sind diese Kontrollcodes bereits
+enthalten.
+
+
+Aufruf:
+
+ c2cweb [Optionen] C-Quelldatei(en) | @Response-Datei(en)
+
+Folgende Optionen sind moeglich:
+
+-v:
+ alle Kommentare werden in Schreibmaschinenschrift ausgegeben. Dieser
+ Schalter ist notwendig, falls die Kommentare bereits formatiert sind, zum
+ Beispiel
+
+ /********************/
+ /* example.c */
+ /********************/.
+
+-t Wert:
+ all Tabulator-Stopps werden expandiert; -t Wert definiert die
+ Tabulatorweite (Grundeinstellung: Wert=4).
+
+-l:
+ Zeilenumbrueche in der Eingabe innerhalb von C-Text bleiben in der Ausgabe
+ erhalten durch explizites Anhaengen von @/ (einem CWEB Kontrollcode) an
+ jede Code-Zeile.
+
+-o Verzeichnis
+ definiert das Ausgabeverzeichis (muss bereits existieren).
+
+-o Format-Datei
+ Inkludiert (zusaetzlich zu compiler.w) eine Format-Datei
+
+-b "Titel":
+
+definiert einen Titel (in doppelten Anfuehrungszeichen). Dieser String wird
+direkt an TeX weitergegeben.
+
+-1:
+ einseitige Ausgabe (d.h., linker Seitenkopf wird dem rechten Seitenkopf
+ gleichgesetzt).
+
+
+Die letzten Schritte sind das Aufrufen von CWEAVE mit der transformierten
+Hauptdatei und danach der Aufruf von TeX, um eine druckfaehige .dvi-Datei zu
+erhalten.
+
+
+Ein Beispiel:
+
+ die Eingabedateien:
+ header1.h, header2.h, file1.c, file2.c, file3.c
+
+ Man muss jetzt
+ c2cweb [Optionen] header*.h file*.c
+
+ aufrufen, um die *.*w-Dateien zu erhalten. c2cweb bearbeitet jetzt alle
+ Eingabedateien und teilt mit, welche Datei die Eingabedatei fuer CWEAVE
+ ist (hier im Beispiel sei es file3.cw).
+
+ Nach dem Aufruf
+ cweave [Optionen] file3.cw
+
+ erhaelt man eine .tex-Datei (und einige zusaetzliche Hilfsdateien), die
+ mit PLAIN TeX weiterverarbeitet werden muss (LaTeX wird nicht
+ unterstuetzt):
+
+ tex file3[.tex]
+
+
+Im Abschnitt `Hints and Tricks' in der Datei c2cweb.w werden weitere
+Verbesserungen und Beschraenkungen von c2cweb beschrieben (der Aufruf `make
+documentation' erzeugt die .dvi-Datei).
+
+
+Autor
+-----
+
+Werner Lemberg (a7971428@unet.univie.ac.at)
+
+Bitte alle Fehler, Kommentare oder Bemerkungen an obige email-Adresse
+schicken.
+
+ Werner Lemberg
+ Goldschlagstr. 52/14
+ A-1150 Vienna/Austria
+
+
+--- end of c2cweb.txt ---
diff --git a/web/c_cpp/c2cweb/c2cweb.w b/web/c_cpp/c2cweb/c2cweb.w
new file mode 100644
index 0000000000..eb3b0e7691
--- /dev/null
+++ b/web/c_cpp/c2cweb/c2cweb.w
@@ -0,0 +1,1406 @@
+% This is the cweb file c2cweb Version 1.5 10-Nov-1996
+%
+% You should process this file with
+%
+% cweave +ai c2cweb.w
+
+\pageno=\contentspagenumber \advance\pageno by 1
+\let\maybe=\iftrue
+\fullpageheight=240mm
+\pageheight=223mm
+\pagewidth=158mm
+\setpage
+\frenchspacing
+\def\in{\leavevmode\vrule width 0pt\nobreak\hskip 2em\hskip 0pt} % indentation
+\font\sixrm=cmr6
+\def\tm{$^{\hbox{\sixrm TM}}$} % trademark
+
+\def\title{c2cweb (Version 1.5)}
+
+\def\topofcontents{%
+ \null\vfill
+ \centerline{\titlefont The {\ttitlefont c2cweb} program}
+ \vskip 20pt
+ \centerline{(Version 1.5)}
+ \vfill}
+
+\def\botofcontents{%
+ \vfill
+ \noindent
+ Copyright \copyright\ 1996 by Werner Lemberg
+ \bigskip\noindent
+ Permission is granted to make and distribute verbatim copies of this
+ document provided that the copyright notice and this permission notice are
+ preserved on all copies.
+
+ \smallskip\noindent
+ Permission is granted to copy and distribute modified versions of this
+ document under the conditions for verbatim copying, provided that the
+ entire resulting derived work is distributed under the terms of a
+ permission notice identical to this one.}
+
+
+
+@* Introduction.
+This is the \.{c2cweb} program by Werner Lemberg
+(\.{a7971428@@unet.univie.ac.at}).
+
+The ``banner line'' defined here should be changed whenever \.{c2cweb} is
+modified.
+
+@d banner "\nThis is c2cweb Version 1.5 (c) 1996 by Werner Lemberg\n\n"
+
+
+@
+\.{c2cweb} will transform ordinary \CEE/ or \CPLUSPLUS/ source code into
+\.{CWEB} formatted code. Three primary functions are performed: inserting
+\.{@@}-commands between code blocks, transforming comments into \TeX-text,
+and replacing offending characters like \.{\\}, \.{\_}, \.{\&} etc. with
+commands \TeX\ (and \.{CWEB}) can understand.
+
+The only changes the user has to do normally is to insert `\.{/*@@@@*/}' or
+`\.{/*@@*/}' \\{starting a line} outside of a comment or string (the rest of
+these lines will be ignored):
+
+\advance\leftskip by 3em
+
+ \item{$\bullet$} \.{/*@@@@*/} starts a new section and switches the
+ function block algorithm on (see below).
+
+ \item{$\bullet$} \.{/*@@*/} starts a new section and switches the
+ function block algorithm off. This is the default when \.{c2cweb}
+ begins to scan a file.
+
+\advance\leftskip by -3em
+
+Both `commands' will be suppressed in the output (two additional commands
+are described in the `Hints and Tricks'-section).
+
+
+@
+Normal \CEE/ code consists of two parts: the code before function blocks
+(\.{\#include} and \.{\#define} statements, prototypes, structure
+definitions, global variables, etc.) and the function blocks (i.e.
+\.{foo()\{ ... \}}) itselves (possibly mixed with global definitions of
+variables, structures etc.). The main reason to separate them are memory
+constraints of \.{CWEAVE}; inserting \.{/*@@@@*/} causes each function block
+to be written into an own section.
+
+In header files, nothing is to do because there are no function blocks. In
+\CEE/ code files, it's usually sufficient to insert \.{/*@@@@*/} once, but
+you can structure your code further by inserting \.{/*@@*/} (and
+\.{/*@@@@*/} if necessary). See also the example file delivered with this
+package.
+
+You will need a special \.{CWEAVE} executable which has among others two
+additional control codes sometimes needed. See also the section `Hints and
+Tricks'.
+
+From now on, the words \.{CWEB} and \.{CWEAVE} will be used mutually in
+spite of the fact that \.{CWEB} consists of both the programs \.{CWEAVE} and
+\.{CTANGLE}---\.{c2cweb} is intended to create a well printed listing, and
+the use of \.{CTANGLE} is of course possible but senseless.
+
+
+
+@* The program.
+The use of |_response()|, |_wildcard()|, and |_getname()| is compiler
+specific. If you don't use emx-gcc, it's likely that you have to use
+different functions. If you use this program under DOS, consider the
+\UNIX/-like behavior of the ``|*|''-wildcard character.
+
+After processing the options, the global variable |optind| (defined in
+\.{getopt.h}) is the index to the first file name.
+
+@d FALSE 0
+@d TRUE 1
+@d DONE 2
+@d WAIT 3
+
+@c
+@<Include files@>;
+@<Prototypes@>;
+@<Global variables@>;@#
+
+void main(argc, argv)
+ int argc;
+ char *argv[];
+
+ {int i;
+ char buffer[DIR_LENGTH + FILE_NAME_LENGTH + 1];
+ char *p, *q;
+
+
+ printf(banner);@#
+
+#ifdef __EMX__
+ _response(&argc, &argv); /* to expand response files */
+ _wildcard(&argc, &argv); /* to expand wildcards */
+#endif@#
+
+ @<Get command switches@>;@#
+
+ @<Processing all files except the last one@>;
+ @<Processing the last file@>;@#
+
+ fclose(in);
+ fclose(out);
+ }
+
+
+@
+\.{getopt.h} contains the \UNIX/-specific |getopt()|. If your system doesn't
+support this function, get the GNU \CEE/-library for an implementation.
+
+@<Include files@>=
+#include <ctype.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+@
+@<Processing all files except the last one@>=
+ for (i = optind; i < argc - 1; i++)
+ {printf(" processing %s\n", argv[i]);@#
+
+ open_files(argv[i]);
+ q = protect_underlines(_getname(argv[i]));
+ if ((p = strrchr(q, '.')) != NULL)
+ /* the macro \.{\\ZZZ} suppresses the final dot after
+ the section title if the filename contains a dot */
+ fprintf(out,@/
+ "@@*{%s\\ZZZ{\\setbox0=\\hbox{%s}\\hskip-\\wd0}}.\n"@/
+ "\\ind=2\n\n", q, p);
+ else
+ fprintf(out, "@@*{%s}.\n"@/
+ "\\ind=2\n\n", q);@#
+
+ handle_input();
+ fclose(in);
+ fclose(out);
+ }
+
+
+@
+The last file will be the `master' file; you have to call \.{CWEAVE} with
+this file as the argument; all other files will be included.
+
+@<Processing the last file@>=
+ printf(" processing %s\n", argv[i]);@#
+
+ open_files(argv[i]);
+ @<Write limbo@>;
+ q = protect_underlines(_getname(argv[i]));
+ if ((p = strrchr(q, '.')) != NULL)
+ fprintf(out,@/
+ "@@*{%s\\ZZZ{\\setbox0=\\hbox{%s}\\hskip-\\wd0}}.\n"@/
+ "\\ind=2\n\n", q, p);
+ else
+ fprintf(out, "@@*{%s}.\n"@/
+ "\\ind=2\n\n", q);@#
+
+ handle_input();
+ @<Write index section@>;@#
+
+ strcpy(buffer, argv[argc - 1]);
+ modify_filename(buffer);@#
+
+ printf(@/
+ "\n You must now call CWEAVE with %s%s\n"@/
+ " as the argument to get a TeX output", outdir, _getname(buffer));
+ if (optind < argc - 1)
+ printf(" of all processed files");
+ printf("\n");
+
+
+
+@*1 The input switches.
+If the switch \.{-v} is set, all comments are written in typewriter type;
+comments starting a line will also start a line in the output.
+
+All tabs will be expanded, and the \.{-t} switch defines the tab length
+(default value is 4).
+
+The switch \.{-l} causes all linefeeds inside of \CEE/-text to be output
+explicitly by inserting a \.{@@/} command at the end of each code line.
+
+The output directory will be set with the \.{-o} option; this directory must
+already exist. Probably you have to adjust |PATH_SEPARATOR| and
+|pathsepchar[]| to make it work correctly under your operating system.
+
+To get a title, use the \.{-b} switch with the titlestring enclosed in
+double quotes; this string will be passed directly to \TeX.
+
+To include a format file (additionally to \.{compiler.w}), use the \.{-f}
+switch.
+
+One-sided output is enabled with the option \.{-1} set.
+
+The global variable |optarg| (defined in \.{getopt.h}) points to the option
+argument; the string |optswchar[]| is modified to allow |'-'| and |'/'| as
+characters which start options (not under \UNIX/).
+
+@d DIR_LENGTH 80
+@d TITLE_LENGTH 100
+@d PATH_SEPARATOR '/'
+
+@<Global...@>=
+int tab_length = 4;
+int verbatim = FALSE;
+int user_linefeed = FALSE;
+int one_side = FALSE;
+char outdir[DIR_LENGTH + 1];
+char include_file[FILE_NAME_LENGTH + 1];
+char title[TITLE_LENGTH + 1];@#
+
+#ifdef __EMX__
+char optchar[] = "-/";
+char pathsepchar[] = "\\/";
+#else
+char optchar[] = "-";
+char pathsepchar[] = "/";
+#endif@#
+
+char at_nmb[] = "@@#";
+ /* the \.{CWEB} command for inserting vertical space */
+
+
+@
+@<Get command switches@>=
+ {int c;
+ int i;
+
+
+ outdir[0] = '\0';
+ include_file[0] = '\0';
+ title[0] = '\0';@#
+
+#ifdef __EMX__
+ optswchar = optchar;
+#endif@#
+
+ strcpy(title, "c2cweb output"); /* the default title */@#
+
+ while ((c = getopt(argc, argv, "b:f:lo:t:v1")) != EOF)
+ {switch (c)
+ {case 'b':
+ if (strchr(optchar, optarg[0]))
+ /* check if argument is an option */
+ usage();@#
+
+ if (strlen(optarg) >= TITLE_LENGTH)
+ fprintf(stderr,@/
+ "\nTitle too long. Will use \"c2cweb output\".\n");
+ else
+ strcpy(title, optarg);
+ break;
+ case 'f':
+ if (strchr(optchar, optarg[0]))
+ usage();@#
+
+ if (strlen(optarg) >= FILE_NAME_LENGTH)
+ fprintf(stderr,@/
+ "\nInclude file name too long. Will be ignored.\n");
+ else
+ strcpy(include_file, optarg);
+ break;
+ case 'l':
+ user_linefeed = TRUE;
+ break;
+ case 'o':
+ if (strchr(optchar, optarg[0]))
+ usage();@#
+
+ if ((i = strlen(optarg)) >= DIR_LENGTH)
+ fprintf(stderr,@/
+ "\nOutput directory name too long. Will be ignored.\n");
+ else
+ {strcpy(outdir, optarg);
+ if (!strchr(pathsepchar, outdir[i - 1]))
+ /* check if last character is a path separator */
+ {outdir[i] = PATH_SEPARATOR;
+ outdir[i + 1] = '\0';
+ }
+ }
+ break;
+ case 't':
+ if (strchr(optchar, optarg[0]))
+ usage();@#
+
+ tab_length = atoi(optarg);
+ if (tab_length == 0 || tab_length > 8)
+ tab_length = 4; /* default value */
+ break;
+ case 'v':
+ verbatim = TRUE;
+ break;
+ case '1':
+ one_side = TRUE;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }@#
+
+ if (optind == argc)
+ usage();
+ }
+
+
+@
+The output file has the same name as the input file but a different
+extension: it will append a \.{w} or, if the extension is three characters
+long, substitute the third character with a \.{w}, i.e. \.{.c} becomes
+\.{.cw}, \.{.h} becomes \.{.hw}, \.{.cpp} will be replaced by \.{.cpw} and
+so on (notice that for example \.{.cppp} also becomes \.{.cpw}). If the
+character to be changed is a \.{w}, an \.{x} is used instead of. This will
+be done by the function |modify_filename()|. No checking for overwriting
+existing files is done.
+
+@d FILE_NAME_LENGTH 80
+
+@<Global...@>=
+ FILE *in, *out;
+
+
+@
+@<Prototypes@>=
+void open_files(char *);
+
+@
+@c
+void open_files(filename)
+ char *filename;
+ {char buffer[DIR_LENGTH + FILE_NAME_LENGTH + 1];
+
+
+ if (strlen(filename) > FILE_NAME_LENGTH - 2)
+ {fprintf(stderr, "\n File name too long.\n");
+ exit(-1);
+ }@#
+
+ if ((in = fopen(filename, "rt")) == NULL)
+ {fprintf(stderr, "\n Can't open input file %s\n", filename);
+ exit(-1);
+ }@#
+
+ strcpy(buffer, outdir);
+ strcat(buffer, filename);
+ modify_filename(buffer);@#
+
+ if ((out = fopen(buffer, "wt")) == NULL)
+ {fprintf(stderr, "\n Can't open output file %s\n", buffer);
+ exit(-1);
+ }
+ }
+
+
+
+@*1 The output header.
+This is the header of the last output file. You must call \.{CWEAVE} with
+this file as an argument---all other processed files will be included.
+
+Additionally this `master' file will include the file \.{compiler.w}, which
+should contain all system dependent definitions (like \.{va\_decl} or
+\.{va\_arg}) not contained in the \.{CWEAVE} program. The syntax of
+\.{compiler.w} is \.{CWEB} syntax; please read the documentation if you have
+questions. You should set the environment variable |CWEBINPUTS| used by
+\.{CWEAVE} (and \.{CTANGLE}) to the directory where \.{compiler.w} resides.
+
+The function |_getname()| will accept forward and backward slashes as path
+separators if you compile under emx. However, options can be introduced with
+|'-'| and |'/'|, therefore paths starting with a forward slash must be
+enclosed in double quotes (not under \UNIX/).
+
+@<Write limbo@>=
+ fprintf(out,@/
+ "\\font\\symb=cmsy10\n"@/
+ "\\font\\math=cmmi10\n"@/
+ "\\def\\ob"@/
+ "{\\parskip=0pt\\parindent=0pt%%\n"@/
+ "\\let\\\\=\\BS\\let\\{=\\LB\\let\\}=\\RB\\let\\~=\\TL%%\n"@/
+ "\\let\\ =\\SP\\let\\_=\\UL\\let\\&=\\AM\\let\\^=\\CF%%\n"@/
+ "\\obeyspaces\\frenchspacing\\tt}\n"@/
+ "\n"@/
+ "\\def\\e{\\hfill\\break\\hbox{}}\n"@/
+ "\\def\\{{\\relax\\ifmmode\\lbrace\\else$\\lbrace$\\fi}\n"@/
+ "\\def\\}{\\relax\\ifmmode\\rbrace\\else$\\rbrace$\\fi}\n"@/
+ "\\def\\takenone#1{\\hskip-0.1em}\n"@/
+ "\\let\\ZZZ=\\relax\n"@/
+ "\n"@/
+ "%s"@/
+ "\n"@/
+ "\\pageno=\\contentspagenumber \\advance\\pageno by 1\n"@/
+ "\\let\\maybe=\\iftrue\n"@/
+ "\n"@/
+ "\\def\\title{%s}\n"@/
+ "\n"@/
+ "@@i compiler.w\n"@/
+ "\n", one_side ? "\\let\\lheader=\\rheader\n" : "", title);@#
+
+ if (*include_file)
+ fprintf(out,@/
+ "@@i %s\n"@/
+ "\n", include_file);@#
+
+ for (i = optind; i < argc - 1; i++)
+ {strcpy(buffer, argv[i]);
+ modify_filename(buffer);@#
+
+ fprintf(out, "@@i %s\n", _getname(buffer));
+ }@#
+
+ fputc('\n', out);@#
+
+
+
+@*1 Input Handling.
+
+@d BUFFER_LENGTH 500
+
+@<Prototypes@>=
+void handle_input(void);
+
+
+@
+This is a wild hack. Perhaps in a future version I will improve it.
+
+@<Global...@>=
+char buffer[BUFFER_LENGTH + 1];
+
+@
+The main routine. Characters which will be treated in a special way by
+\.{CWEB} and \TeX\ are handled within a great switch.
+
+@d xisspace(c) (isspace(c) && ((unsigned char)c < 0200))
+
+@c
+void handle_input(void)
+ {char *buf_p;
+ char ch;
+ @<Control flags@>;
+
+ line_number = 0;
+ while (get_line())
+ {buf_p = buffer;@#
+
+ do
+ {ch = *buf_p;@#
+
+ @<Special cases@>;@#
+
+ switch (ch)
+ {case ' ':
+ if (leading_blanks)
+ {blank_count++;
+ goto end;
+ }
+ break;@#
+
+ case '\t':
+ {int i = tab_length - (column % tab_length);
+
+ column += i - 1; /* we'll say later |column++| */@#
+
+ if (leading_blanks)
+ {blank_count += i;
+ goto end;
+ }@#
+
+ while (i--)
+ fputc(' ', out);
+ goto end;
+ }
+ break;@#
+
+ case '{':
+ @<Cases for |'{'|@>;
+ break;@#
+
+ case '}':
+ @<Cases for |'}'|@>;
+ break;@#
+
+ case '/':
+ @<Cases for |'/'|@>;
+ break;@#
+
+ case '*':
+ @<Cases for |'*'|@>;
+ break;@#
+
+ case '\n':
+ @<Cases for |'\n'|@>;
+ break;@#
+
+ case '@@':
+ @<Cases for |'@@'|@>;
+ break;@#
+
+ case '\'':
+ @<Cases for |'\''|@>;
+ break;@#
+
+ case '\"':
+ @<Cases for |'\"'|@>;
+ break;@#
+
+ case '\\':
+ @<Cases for |'\\'|@>;
+ break;@#
+
+ default:
+ @<Cases for |default|@>;
+ break;
+ }@#
+
+ fputc(ch, out);@#
+
+end:
+ buf_p++;
+ column++;
+ } while(ch != '\n');
+ }
+ }
+
+
+@
+@<Control flags@>=
+ int any_input = FALSE;
+ /* set after the first non blank character in a new section */
+ int brace_count = 0;
+ int blank_count = 0;@#
+
+ int in_comment = FALSE;
+ int in_C = FALSE;
+ int in_string = FALSE;
+ int short_comment = FALSE;
+ int leading_blanks = TRUE;
+ int double_linefeed = FALSE; /* set if last character was a linefeed */
+ int linefeed_comment = FALSE;
+ /* set if a comment follows a linefeed immediately */
+ int comment_slash = FALSE; /* set if last character was a slash */
+ int comment_star = FALSE; /* set if last character was a star */
+ int escape_state = FALSE;
+ /* needed to check whether in string or
+ at the end of a preprocessor line */
+ int before_TeX_text = FALSE;
+ /* the state after leaving a function block */
+ int function_blocks = FALSE; /* set if function block algorithm is on */
+
+
+@
+Here comes a bunch of |if|-statements.
+
+@<Special cases@>=
+ @<Check conditions while at start of a line@>;@#
+
+ if (double_linefeed && ch == '/')
+ linefeed_comment = TRUE;@#
+
+ if (double_linefeed && (ch == ' ' || ch == '\t'))
+ leading_blanks = TRUE;@#
+
+ if (ch != '\n') /* multiple linefeed ? */
+ double_linefeed = FALSE;@#
+
+ if (!xisspace(ch)) /* whitespaces ? */
+ {any_input = TRUE;@#
+
+ if (before_TeX_text && function_blocks)
+ {before_TeX_text = FALSE;@#
+
+ if (function_blocks == WAIT)
+ function_blocks = TRUE;
+ /* start at the second occurrence */
+ else
+ {fputs("@@\n"@/
+ "\\ind=2\n\n", out);
+ /* start a new text section */@#
+
+ if (leading_blanks)
+ {leading_blanks = FALSE;@#
+
+ while (blank_count--)
+ fputc(' ', out);
+ blank_count = 0;
+ }
+ }
+ }@#
+
+ if (in_comment && leading_blanks)
+ {leading_blanks = FALSE;@#
+
+ while (blank_count--)
+ fputc(' ', out);
+ blank_count = 0;
+ }
+ }@#
+
+ if (!(ch == '/' || xisspace(ch)))
+ /* whitespace or possible start of comment ? */
+ {if (!(in_comment || in_C || comment_slash))
+ /* outside of code ? */
+ {in_C = TRUE;@#
+
+ fputs("@@c\n", out); /* start of a new code section */@#
+
+ if (leading_blanks)
+ {leading_blanks = FALSE;@#
+
+ while (blank_count--)
+ fputc(' ', out);
+ blank_count = 0;
+ }
+ }@#
+
+ if (!(in_comment || comment_slash) && leading_blanks)
+ {leading_blanks = FALSE;@#
+
+ while (blank_count--)
+ fputc(' ', out);
+ blank_count = 0;
+ }
+ }@#
+
+ if (comment_slash && !(ch == '*' || ch == '/'))
+ /* start of a comment ? */
+ {comment_slash = FALSE;
+ if (!in_comment)
+ linefeed_comment = FALSE;@#
+
+ fputc('/', out);
+ }@#
+
+ if (comment_star && ch != '/') /* end of a comment ? */
+ {comment_star = FALSE;@#
+
+ fputc('*', out);
+ }@#
+
+ if (escape_state && !(ch == '\"' || ch == '\n' || ch == '\\'))
+ /* end of string or end of preprocessor line or backslash itself ? */
+ escape_state = FALSE;@#
+
+
+@
+@<Check conditions while at start of a line@>=
+ if (buf_p == buffer)
+ {if (!(in_comment || in_string))
+ {if (!strncmp(buf_p, "/""*@@@@*""/", 6))
+ {in_C = FALSE;
+ before_TeX_text = TRUE;
+ function_blocks = WAIT; /* switch on the algorithm */
+ brace_count = 0;@#
+
+ if (any_input)
+ fputs("\n@@\n"@/
+ "\\ind=2\n\n", out);
+ /* start a new section */@#
+
+ any_input = FALSE;
+ *(buf_p--) = '\n';
+ /* the rest of the line will be ignored */
+ goto end;
+ }
+ else if (!strncmp(buf_p, "/""*@@*""/", 5))
+ {in_C = FALSE;
+ before_TeX_text = TRUE;
+ function_blocks = FALSE; /* switch off the algorithm */@#
+
+ if (any_input)
+ fputs("\n@@\n"@/
+ "\\ind=2\n\n", out);@#
+
+ any_input = FALSE;
+ *(buf_p--) = '\n';
+ goto end;
+ }
+ else if (!strncmp(buf_p, "/""*{*""/", 5))
+ {brace_count++; /* a dummy opening brace */
+ fputs("@@{\n", out);@#
+
+ ch = '\n'; /* an end of line is simulated */
+ goto end;
+ }
+ else if (!strncmp(buf_p, "/""*}*""/", 5))
+ {brace_count--; /* a dummy closing brace */
+ fputs("@@}\n", out);@#
+
+ if (!brace_count && function_blocks)
+ /* end of function block reached ? */
+ {in_C = FALSE;
+ before_TeX_text = TRUE;@#
+
+ break;
+ }@#
+
+ ch = '\n';
+ goto end;
+ }
+ else if (!strncmp(buf_p, "/""*{}*""/", 6))
+ {fputs("@@{@@}\n", out);@# /* a dummy function body */
+
+ ch = '\n';
+ goto end;
+ }
+ }
+ }
+
+
+@
+@<Cases for |'{'|@>=
+ if (in_comment)
+ fputc('\\', out);
+ else if (in_string)
+ break;
+ else if (function_blocks)
+ {brace_count++;
+ in_C = TRUE;
+ }
+
+@
+@<Cases for |'@@'|@>=
+ if (in_comment)
+ {fputs("{\\char64}", out);
+ goto end;
+ }
+ else /* \.{CWEB} needs \.{@@@@} to output \.{@@} */
+ fputc('@@', out);
+
+@
+@<Cases for |'\''|@>=
+ if (!in_comment)
+ {if (*(buf_p + 1) == '\"' && *(buf_p + 2) == '\'')
+ escape_state = TRUE; /* this catches |'"'| */
+ }
+
+@
+@<Cases for |'\"'|@>=
+ if (!in_comment) /* start or end of a string ? */
+ {if (escape_state)
+ escape_state = FALSE;
+ else
+ in_string = TRUE - in_string;
+ }
+
+@
+@<Cases for |'\\'|@>=
+ if (in_comment)
+ {fputs("{\\symb\\char110}", out);
+ goto end;
+ }
+ else
+ escape_state = TRUE - escape_state;
+ /* continuation of preprocessor line or
+ an escape character */
+
+@
+@<Cases for |'}'|@>=
+ if (in_comment)
+ fputc('\\', out);
+ else if (in_string)
+ break;
+ else if (function_blocks)
+ {brace_count--;
+ if (!brace_count) /* end of function block reached ? */
+ {in_C = FALSE;@#
+
+ before_TeX_text = TRUE;
+ break;
+ }
+ }
+
+@
+@<Cases for |'/'|@>=
+ if (comment_star)
+ {@<Cases for |'*/'|@>;
+ }
+ else if (comment_slash)
+ {@<Cases for |'//'|@>;
+ }
+ else
+ {comment_slash = TRUE;@#
+
+ goto end;
+ }
+
+@
+@<Cases for |'*/'|@>=
+ comment_star = FALSE;
+ leading_blanks = FALSE;@#
+
+ if (!short_comment)
+ {in_comment = FALSE; /* end of comment */@#
+
+ if (!in_C)
+ {linefeed_comment = FALSE;@#
+
+ if (verbatim) @q { @>
+ fputs("*""/}", out);@#
+
+ if (*(buf_p + 1) == '\n') /* end of line ? */
+ fputs("\\e{}%", out);@#
+
+ goto end;
+ }
+
+ if (in_C && verbatim)
+ {if (linefeed_comment)
+ {linefeed_comment = FALSE;@#
+
+ fputs("*""/@@>", out);
+ if (*(buf_p + 1) == '\n' && !user_linefeed)
+ fputs("@@/", out);
+ goto end;
+ }
+ else @q { @>
+ fputc('}', out);@#
+ }@#
+
+ linefeed_comment = FALSE;@#
+
+ if (in_C || verbatim)
+ fputc('*', out);
+ else
+ goto end;
+ }
+ else
+ fputc('*', out);
+
+@
+@<Cases for |'//'|@>=
+ comment_slash = FALSE;@#
+
+ if (!short_comment)
+ {in_comment = TRUE;
+ short_comment = TRUE; /* start of a short comment */@#
+
+ if (!in_C && verbatim)
+ {fputs("{\\ob{}", out); @q } @>
+ if (leading_blanks)
+ {leading_blanks = FALSE;@#
+
+ while (blank_count--)
+ fputc(' ', out);
+ blank_count = 0;
+ }
+ fputs("//", out);@#
+
+ goto end;
+ }@#
+
+ if (in_C && verbatim)
+ {if (leading_blanks || linefeed_comment)
+ {linefeed_comment = TRUE;@#
+
+ if (!user_linefeed)
+ fputs("@@/", out); @q { @>
+ fputs("@@t}\\8{\\ob{}", out); @q } @>
+ /* this cryptic command starts a
+ comment line without indentation */
+ if (leading_blanks)
+ {leading_blanks = FALSE;@#
+
+ while (blank_count--)
+ fputc(' ', out);
+ blank_count = 0;
+ }
+ fputs("//", out);
+ }
+ else
+ fputs("//{\\ob{}", out);@# @q } @>
+
+ goto end;
+ }@#
+
+ if (in_C || verbatim)
+ fputc('/', out);
+ else
+ goto end;
+ }
+ else
+ fputc('/', out);
+
+
+@
+@<Cases for |'*'|@>=
+ if (comment_slash)
+ {comment_slash = FALSE;@#
+
+ if (in_comment && !short_comment)
+ /* uuh, ooh, for people who `comment
+ out' code with comments instead of
+ using \.{\#if 0} and \.{\#endif} for
+ example---this non-ANSI behaviour
+ would cause bad formatted code and is
+ therefore not supported; the program
+ exits */
+ {fprintf(stderr,
+ " Error line %d: Nested comments not supported\n",
+ line_number);
+ exit(-1);
+ }@#
+
+ if (!short_comment)
+ {in_comment = TRUE; /* start of comment */@#
+
+ if (!in_C && verbatim)
+ {fputs("{\\ob{}", out); @q } @>
+ if (leading_blanks)
+ {leading_blanks = FALSE;@#
+
+ while (blank_count--)
+ fputc(' ', out);
+ blank_count = 0;
+ }
+ fputs("/""*", out);@#
+
+ goto end;
+ }@#
+
+ if (in_C && verbatim)
+ {if (leading_blanks || linefeed_comment)
+ {linefeed_comment = TRUE;
+
+ if (!user_linefeed)
+ fputs("@@/", out); @q { @>
+ fputs("@@t}\\8{\\ob{}", out); @q } @>
+ if (leading_blanks)
+ {leading_blanks = FALSE;@#
+
+ while (blank_count--)
+ fputc(' ', out);
+ blank_count = 0;
+ }
+ fputs("/""*", out);
+ }
+ else
+ fputs("/""*{\\ob{}", out);@# @q } @>
+
+ goto end;
+ }@#
+
+ if (in_C || verbatim)
+ fputc('/', out);
+ else
+ {fputs(" ", out);@#
+
+ goto end;
+ }
+ }
+ else
+ fputc('/', out);
+ }
+ else
+ {comment_star = TRUE;@#
+
+ goto end;
+ }
+
+
+@
+@<Cases for |'\n'|@>=
+ blank_count = 0;@#
+
+ if (!in_comment && in_C)
+ {if (double_linefeed == FALSE)
+ {double_linefeed = TRUE;
+ if (escape_state)
+ {escape_state = FALSE;
+ /* continuation of a preprocessor line */
+ leading_blanks = TRUE;@#
+
+ if (in_string)
+ fputc('\n', out);
+ else
+ fputs("\n@@/", out);
+ goto end;
+ }@#
+
+ if (!leading_blanks && user_linefeed)
+ fputs("@@/", out);
+ }
+ else if (double_linefeed == TRUE)
+ {double_linefeed = DONE;
+ /* blank lines in the input will be output as
+ little white space between code lines */@#
+ fputs(at_nmb, out);
+ }
+ }@#
+
+ leading_blanks = TRUE;@#
+
+ if (short_comment)
+ {short_comment = FALSE;
+ in_comment = FALSE;
+ double_linefeed = TRUE;@#
+
+ if (verbatim)
+ {if (linefeed_comment && in_C)
+ fputs("@@>", out);
+ else @q { @>
+ fputc('}', out);
+ }@#
+
+ if (!in_C)
+ fputs("\\e{}%", out);
+ else if (linefeed_comment && verbatim)
+ fputs("@@/", out);@#
+
+ linefeed_comment = FALSE;
+ }@#
+
+ if (in_comment && in_C && verbatim && linefeed_comment)
+ { @q { @>
+ fputs("@@>@@/\n@@t}\\8{\\ob{}", out); @q } @>
+ /* continuation of a comment line without indentation */
+ goto end;
+ }@#
+
+ if (in_comment && verbatim)
+ /* Both \.{CWEAVE} and \TeX\ need an input at the beginning of a line
+ to prevent leading blanks be swallowed while in verbatim mode;
+ this will be the macro \.{\\e} which causes a linebreak */
+ {fputs("\n\\e{}", out);
+ goto end;
+ }
+
+
+@
+All other special characters will be substituted with proper sequences \TeX\
+can understand.
+
+@<Cases for |default|@>=
+ if (in_comment)
+ {switch (ch)
+ {case '#':
+ fputs("{\\#}", out);
+ break;@#
+
+ case '$':
+ fputs("{\\$}", out);
+ break;@#
+
+ case '%':
+ fputs("{\\%}", out);
+ break;@#
+
+ case '&':
+ fputs("{\\AM}", out);
+ break;@#
+
+ case '_':
+ fputs("{\\_}", out);
+ break;@#
+
+ case '^':
+ fputs("{\\^{}}", out);
+ break;@#
+
+ case '\\':
+ fputs("{\\symb\\char110}", out);
+ break;@#
+
+ case '~':
+ fputs("{\\~{}}", out);
+ break;@#
+
+ case '|':
+ fputs("{\\symb\\char106}", out);
+ break;@#
+
+ case '<':
+ fputs("{\\math\\char60}", out);
+ break;@#
+
+ case '>':
+ fputs("{\\math\\char62}", out);
+ break;@#
+
+ default:
+ fputc(ch, out);
+ break;
+ }@#
+
+ goto end;
+ }
+
+
+@
+Because the index macros defined in \.{cwebmac.tex} don't append a dot, we
+have to redefine \.{\\ZZZ}.
+
+@<Write index section@>=
+ fprintf(out,@/
+ "\n"@/
+ "@@*Index.\n"@/
+ "\\let\\ZZZ=\\takenone\n");
+
+
+@
+@<Prototypes@>=
+void usage(void);
+
+@
+@c
+void usage(void)
+ {fprintf(stderr,@/
+ "Usage: c2cweb [switches] csourcefile(s) | @@responsefile(s)"@/
+ "\n"@/
+ "\n possible switches:"@/
+ "\n"@/
+ "\n -b \"title\" set title"@/
+ "\n -l use input linefeeds"@/
+ "\n -o dirname set output directory (must already exist)"@/
+ "\n -f filename use this file as a format file"@/
+ "\n -t tablength set tabulator length (default 4)"@/
+ "\n -v verbatim mode"@/
+ "\n -1 one-sided output"@/
+ "\n"@/
+ "\n");@#
+
+ exit(-1);
+ }
+
+
+@
+@<Prototypes@>=
+void modify_filename(char *);
+
+
+@
+If a response file is expanded, trailing blanks can occur which will be
+ignored here. The same happens if a filename with trailing blanks is
+enclosed in quotes.
+
+@c
+void modify_filename(name)
+ char *name;
+ {char *p;
+
+
+ if ((p = strrchr(name, '.')) != NULL)
+ {p++;
+ if (*p && *p != ' ')
+ p++;
+ if (*p && *p != ' ')
+ p++;
+ if (*p != 'w')
+ *p = 'w';
+ else
+ *p = 'x';
+ p++;
+ *p = '\0';
+ }
+ else
+ strcat(name, ".w");
+ }
+
+
+@
+@<Global...@>=
+int line_number = 0;
+int column;
+
+
+@
+@<Prototypes@>=
+char *get_line(void);
+
+
+@
+|get_line()| gets the next line and removes all trailing blanks or tabs.
+
+@c
+char *get_line(void)
+ {char *p;
+ int i = BUFFER_LENGTH;
+
+
+ if ((p = fgets(buffer, BUFFER_LENGTH + 1, in)) != NULL)
+ {while (i--)
+ {if (*(p++) == '\n')
+ break;
+ }@#
+
+ p--;
+ p--;
+ while ((*p == ' ' || *p == '\t') && p >= buffer)
+ p--;
+ *(p + 1) = '\n';
+ *(p + 2) = '\0';@#
+
+ line_number++;
+ column = 0;
+ }
+ return(p);
+ }
+
+
+@
+@<Global...@>=
+char tempbuf[2 * FILE_NAME_LENGTH + 1];
+
+
+@
+@<Prototypes@>=
+char *protect_underlines(char *);
+
+
+@
+This function is needed for the names of named sections, i.e. file names.
+
+@c
+char *protect_underlines(p)
+ char *p;
+ {char *q;
+
+
+ q = tempbuf;@#
+
+ do
+ {if (*p == '_')
+ *(q++) = '\\';
+ *(q++) = *p;
+ } while (*(p++));@#
+
+ return tempbuf;
+ }
+
+
+@
+@<Prototypes@>=
+#ifndef __EMX__
+char *_getname(char *);
+#endif
+
+
+@
+For Linux and other \UNIX/-systems the function |_getname()| must be
+defined.
+
+
+@c
+#ifndef __EMX__
+char *_getname(char *path)
+ {char *p;
+
+ p = strrchr(path, '/');
+ return p == NULL ? path : (p + 1);
+ }
+#endif
+
+
+
+@* Hints and Tricks.
+Some words are reserved by \.{CWEAVE} you would like to use. Here is a small
+list of them (see the manual for a complete one):
+
+ \in \.{error}, \.{line}, \.{try}, $\ldots$
+
+To make a word unreserved write a line
+
+ \in \.{@@s} \\{ident} \\{x}
+
+into \.{compiler.w} where \\{ident} is the reserved word.
+
+Some words you would expect \.{CWEAVE} knows actually are not in its memory:
+
+ \in \.{va\_arg}, \.{va\_end}, \.{va\_start}, $\ldots$
+
+To make a word \\{ident1} reserved you should write
+
+ \in \.{@@s} \\{ident1} \\{ident2}
+
+into \.{compiler.w}. Now \\{ident1} will behave as \\{ident2}; for example
+
+ \in \.{@@s va\_decl va\_dcl}
+
+causes \.{CWEAVE} to treat \.{va\_decl} as it treats \.{va\_dcl}.
+
+Bear always in mind that \.{CWEAVE} has been developed for use with \UNIX/
+and not for DOS or OS/2. Weird non-ANSI constructions like
+
+ \in \&{void \_FAR} |*| \&{\_FARFUNC \_Cdecl} \\{memcpy} $\ldots$
+
+will cause some, hmmm, troubles if you use the original \.{CWEAVE} program.
+Until now it's also a bit difficult to program for Windows\tm\ or the
+Presentation Manager\tm, because you have to include every structure and
+constant you use in your program manually, which can be a tedious work.
+
+Do not use the same name for a structure and an instance of it. This means
+that you must avoid things like this:
+
+ \in \&{struct foo} \\{foo;}
+
+\.{CWEAVE} would be confused totally. The same applies to all identifiers
+which will be used as reserved and as unreserved words at the same time (This
+usually will not affect identical names of variables and functions. But in
+this case the reader of your program will get confused).
+
+Most of the \CEE/ constants are written in upper case, and \.{CWEAVE} writes
+them in typewriter type. But some constants like \.{\_Windows} or
+\.{\_\_cplusplus} are mixed or lower case, and \.{CWEAVE} will use italic
+type instead of. Look at \.{compiler.w} again to see a workaround how to get
+a correct output (Note: underline characters are converted to `x' in the
+\TeX\ control string).
+
+Nested comments are not supported; the program aborts with an error message.
+
+If you have unbalanced braces due to \.{\#ifdef foo} $\ldots$ \.{\#endif}
+constructions, you can keep \.{c2cweb} and your editor happy if you write a
+\.{/*\{*/} or \.{/*\}*/} command where needed; otherwise memory of \.{CWEAVE}
+can overflow. \.{c2cweb} replaces these commands with the equal \.{CWEB}
+constructions (only defined in this package's modified \.{CWEAVE} version!).
+
+Another trick with preprocessor conditionals:
+
+ \in \.{/*@@*/}
+
+ \in \&{\#ifdef} \.{foo}
+
+ \in\in \&{int} \\{func1} $\{\,\ldots\,\}$
+
+ \in \&{\#endif}
+
+ \in \.{/*@@@@*/}
+
+Without \.{/*@@*/} the \&{\#endif} instruction would be written into the next
+section.
+
+The \.{/*\{\}*/} command proved to be useful in cases like this:
+
+ \in \&{\#if} \.{\_\_STDC\_\_}
+
+ \in\in \&{void} \\{func1}(\&{int} \\{a})
+
+ \in \.{/*\{\}*/}
+
+ \in \&{\#else}
+
+ \in\in \&{void} \\{func1}(\\{a})
+
+ \in\in\in \&{int} \\{a};
+
+ \in \&{\#endif}
+
+ \in $\{\,\ldots\,\}$
+
+It is essentially the same as
+
+ \in \.{/*\{*/}
+
+ \in \.{/*\}*/}
+
+but will not start a new section (Thus it is not necessary to insert a
+\.{/*@@*/} before the actual function).
+
+
+@* Index.
+
+
+@q end of c2cweb.w @>
diff --git a/web/c_cpp/c2cweb/compiler.w b/web/c_cpp/c2cweb/compiler.w
new file mode 100644
index 0000000000..e03320c0f2
--- /dev/null
+++ b/web/c_cpp/c2cweb/compiler.w
@@ -0,0 +1,71 @@
+@q this file is part of the c2cweb package Version 1.5 @>
+
+@q this is the file compiler.w @>
+@q written by Werner Lemberg (a7971428@@unet.univie.ac.at) 10-Nov-1996 @>
+
+
+@q the format definitions below are just examples and not complete! @>
+
+@q definition strings @>
+
+% A4 paper format
+
+\fullpageheight=240mm
+\pageheight=223mm
+\pagewidth=158mm
+\setpage
+
+\def\botofcontents{
+ \vfill
+ \centerline{This document was produced with the \.{c2cweb}
+ program by Werner Lemberg}}
+
+\input c2cweb.ger @q uncomment this if not needed @>
+
+\def\xWindows{\.{\_Windows}}
+\def\xxcplusplus{\.{\_\_cplusplus}}
+
+
+@s error x @q if you use C++ 3.0, you must delete this line @>
+@s line x @q if you want to use the #line preprocessor command, delete this line @>
+
+
+@q most of the DOS C and C++ compilers need that stuff @>
+
+@s _cdecl const
+@s cdecl const
+@s _cs const
+@s _ds const
+@s _es const
+@s _export const
+@s _far const
+@s far const
+@s huge const
+@s interrupt const
+@s _loadds const
+@s _near const
+@s near const
+@s _pascal const
+@s pascal const
+@s _saveregs const
+@s _seg const
+@s _ss const
+
+@s _Windows TeX
+@s __cplusplus TeX
+
+
+@q some GNU C directives @>
+
+@s asm const
+@s inline const
+@s const const
+@s __asm__ const
+@s __inline__ const
+@s __const__ const
+@s __label__ int
+@s __attribute__ int
+@s __alignof__ sizeof
+
+
+@q end of compiler.w @>
diff --git a/web/c_cpp/c2cweb/cweb/Makefile b/web/c_cpp/c2cweb/cweb/Makefile
new file mode 100644
index 0000000000..68d0ca8e18
--- /dev/null
+++ b/web/c_cpp/c2cweb/cweb/Makefile
@@ -0,0 +1,106 @@
+# This file is part of the c2cweb package Version 1.5 (10-Nov-1996)
+
+# GNU Makefile for c2cweb's version of CWEAVE
+
+
+.PHONY: default all debug clean \
+ cweb
+.CAUTIOUS: common.c cweave.c
+
+
+default:
+ @echo " say "
+ @echo ". "
+ @echo " make <TARGET> OS=<SYSTEM> "
+ @echo ". "
+ @echo " SYSTEM can be one of the following: "
+ @echo ". "
+ @echo " unix (gcc) "
+ @echo " os2 bound (emx) "
+ @echo " dos (djgpp) "
+ @echo ". "
+ @echo " TARGET can be one of the following: "
+ @echo ". "
+ @echo " all debug clean "
+
+
+ifdef OS
+
+ ifeq ($(OS),unix)
+ CC = gcc -Wall -O
+ O = .o
+ LIB =
+ EXE =
+ RM = rm -f
+ endif
+
+ ifeq ($(OS),os2)
+ CC = gcc -Wall -Zomf -Zmtd -O
+ O = .obj
+ LIB = cweave.def
+ EXE = .exe
+ RM = del
+ endif
+
+ ifeq ($(OS),dos)
+ CC = gcc -Wall -O
+ O = .o
+ LIB =
+ EXE = .exe
+ RM = del
+ endif
+
+ ifeq ($(OS),bound)
+ CC = gcc -Wall -O
+ O = .o
+ LIB =
+ EXE = .exe
+ RM = del
+ endif
+
+
+ OBJ = common$O cweave$O
+
+
+ %$O: %.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+ %.c: %.w %.ch
+ $(CTANGLE) $^ $@
+ %.c: %.w
+ $(CTANGLE) $<
+
+
+ all:
+ $(MAKE) cweb CFLAGS=-s
+
+ debug:
+ $(MAKE) cweb CFLAGS=-g
+
+ # remove the unnecessary files.
+ clean:
+ -$(RM) *$O
+
+
+ cweb: cweave$(EXE)
+
+ cweave$(EXE): $(OBJ)
+ ifeq ($(OS),dos)
+ $(CC) $(CFLAGS) -o $(basename $@) $^
+ strip $(basename $@)
+ coff2exe $(basename $@)
+ -$(RM) $(basename $@)
+ else
+ $(CC) $(CFLAGS) -o $@ $^ $(LIB)
+ endif
+
+ cweave.w: common.h
+ cweave.ch: prod-alt.w
+
+else # ifdef OS
+
+ all debug clean: default
+
+endif
+
+# end of Makefile
diff --git a/web/c_cpp/c2cweb/cweb/common.c b/web/c_cpp/c2cweb/cweb/common.c
new file mode 100644
index 0000000000..963a20d9c1
--- /dev/null
+++ b/web/c_cpp/c2cweb/cweb/common.c
@@ -0,0 +1,1280 @@
+/*1:*/
+#line 57 "common.w"
+
+/*5:*/
+#line 101 "common.w"
+
+#include <ctype.h>
+
+/*:5*//*8:*/
+#line 163 "common.w"
+
+#include <stdio.h>
+
+/*:8*//*22:*/
+#line 468 "common.w"
+
+#include <stdlib.h>
+
+/*:22*/
+#line 58 "common.w"
+
+#define ctangle 0
+#define cweave 1 \
+
+#define and_and 04
+#define lt_lt 020
+#define gt_gt 021
+#define plus_plus 013
+#define minus_minus 01
+#define minus_gt 031
+#define not_eq 032
+#define lt_eq 034
+#define gt_eq 035
+#define eq_eq 036
+#define or_or 037
+#define dot_dot_dot 016
+#define colon_colon 06
+#define period_ast 026
+#define minus_gt_ast 027 \
+
+#define buf_size 400
+#define long_buf_size 500
+#define xisspace(c) (isspace(c) &&((unsigned char) c<0200) )
+#define xisupper(c) (isupper(c) &&((unsigned char) c<0200) ) \
+
+#define max_include_depth 10 \
+
+#define max_file_name_length 60
+#define cur_file file[include_depth]
+#define cur_file_name file_name[include_depth]
+#define cur_line line[include_depth]
+#define web_file file[0]
+#define web_file_name file_name[0] \
+
+#define lines_dont_match (change_limit-change_buffer!=limit-buffer|| \
+strncmp(buffer,change_buffer,limit-buffer) ) \
+
+#define if_section_start_make_pending(b) {*limit= '!'; \
+for(loc= buffer;xisspace(*loc) ;loc++) ; \
+*limit= ' '; \
+if(*loc=='@'&&(xisspace(*(loc+1) ) ||*(loc+1) =='*') ) change_pending= b; \
+} \
+
+#define max_sections 2000 \
+ \
+
+#define too_long() {include_depth--; \
+err_print("! Include file name too long") ;goto restart;} \
+
+#define max_bytes 225000 \
+
+#define max_names 10000 \
+ \
+
+#define length(c) (c+1) ->byte_start-(c) ->byte_start
+#define print_id(c) term_write((c) ->byte_start,length((c) ) ) \
+
+#define hash_size 353 \
+
+#define llink link
+#define rlink dummy.Rlink
+#define root name_dir->rlink \
+ \
+
+#define first_chunk(p) ((p) ->byte_start+2)
+#define prefix_length(p) (int) ((unsigned char) *((p) ->byte_start) *256+ \
+(unsigned char) *((p) ->byte_start+1) )
+#define set_prefix_length(p,m) (*((p) ->byte_start) = (m) /256, \
+*((p) ->byte_start+1) = (m) %256) \
+
+#define less 0
+#define equal 1
+#define greater 2
+#define prefix 3
+#define extension 4 \
+
+#define bad_extension 5 \
+
+#define spotless 0
+#define harmless_message 1
+#define error_message 2
+#define fatal_message 3
+#define mark_harmless {if(history==spotless) history= harmless_message;}
+#define mark_error history= error_message \
+
+#define confusion(s) fatal("! This can't happen: ",s) \
+ \
+
+#define show_banner flags['b']
+#define show_progress flags['p']
+#define show_stats flags['s']
+#define show_happiness flags['h'] \
+
+#define update_terminal fflush(stdout) \
+
+#define new_line putchar('\n')
+#define putxchar putchar
+#define term_write(a,b) fflush(stdout) ,fwrite(a,sizeof(char) ,b,stdout)
+#define C_printf(c,a) fprintf(C_file,c,a)
+#define C_putc(c) putc(c,C_file) \
+
+
+#line 59 "common.w"
+
+/*2:*/
+#line 72 "common.w"
+
+typedef short boolean;
+boolean program;
+
+/*:2*//*7:*/
+#line 157 "common.w"
+
+char buffer[long_buf_size];
+char*buffer_end= buffer+buf_size-2;
+char*limit= buffer;
+char*loc= buffer;
+
+/*:7*//*10:*/
+#line 212 "common.w"
+
+int include_depth;
+FILE*file[max_include_depth];
+FILE*change_file;
+char file_name[max_include_depth][max_file_name_length];
+
+char change_file_name[max_file_name_length];
+char alt_web_file_name[max_file_name_length];
+int line[max_include_depth];
+int change_line;
+int change_depth;
+boolean input_has_ended;
+boolean changing;
+boolean web_file_open= 0;
+
+/*:10*//*20:*/
+#line 416 "common.w"
+
+typedef unsigned short sixteen_bits;
+sixteen_bits section_count;
+boolean changed_section[max_sections];
+boolean change_pending;
+
+boolean print_where= 0;
+
+/*:20*//*27:*/
+#line 586 "common.w"
+
+typedef struct name_info{
+char*byte_start;
+/*31:*/
+#line 623 "common.w"
+
+struct name_info*link;
+
+/*:31*//*40:*/
+#line 722 "common.w"
+
+union{
+struct name_info*Rlink;
+
+#line 31 "common.ch"
+struct{
+char Ilk;
+boolean Func_flag;}dummy1;
+}dummy;
+#line 728 "common.w"
+
+/*:40*//*55:*/
+#line 1054 "common.w"
+
+char*equiv_or_xref;
+
+/*:55*/
+#line 589 "common.w"
+
+}name_info;
+typedef name_info*name_pointer;
+char byte_mem[max_bytes];
+char*byte_mem_end= byte_mem+max_bytes-1;
+name_info name_dir[max_names];
+name_pointer name_dir_end= name_dir+max_names-1;
+
+/*:27*//*29:*/
+#line 609 "common.w"
+
+name_pointer name_ptr;
+char*byte_ptr;
+
+/*:29*//*32:*/
+#line 636 "common.w"
+
+typedef name_pointer*hash_pointer;
+name_pointer hash[hash_size];
+hash_pointer hash_end= hash+hash_size-1;
+hash_pointer h;
+
+/*:32*//*56:*/
+#line 1074 "common.w"
+
+int history= spotless;
+
+/*:56*//*67:*/
+#line 1212 "common.w"
+
+int argc;
+char**argv;
+char C_file_name[max_file_name_length];
+char tex_file_name[max_file_name_length];
+char idx_file_name[max_file_name_length];
+char scn_file_name[max_file_name_length];
+boolean flags[128];
+
+/*:67*//*77:*/
+#line 1366 "common.w"
+
+FILE*C_file;
+FILE*tex_file;
+FILE*idx_file;
+FILE*scn_file;
+FILE*active_file;
+
+/*:77*/
+#line 60 "common.w"
+
+/*3:*/
+#line 82 "common.w"
+int phase;
+
+/*:3*//*11:*/
+#line 238 "common.w"
+
+char change_buffer[buf_size];
+char*change_limit;
+
+/*:11*/
+#line 61 "common.w"
+
+/*33:*/
+#line 642 "common.w"
+
+extern int names_match();
+
+/*:33*//*38:*/
+#line 695 "common.w"
+
+void init_p();
+
+/*:38*//*46:*/
+#line 844 "common.w"
+
+extern void init_node();
+
+/*:46*//*53:*/
+#line 1009 "common.w"
+
+int section_name_cmp();
+
+/*:53*//*57:*/
+#line 1084 "common.w"
+
+void err_print();
+
+/*:57*//*60:*/
+#line 1132 "common.w"
+
+int wrap_up();
+extern void print_stats();
+
+/*:60*//*63:*/
+#line 1165 "common.w"
+
+void fatal(),overflow();
+
+/*:63*//*69:*/
+#line 1243 "common.w"
+
+void scan_args();
+
+/*:69*//*81:*/
+#line 1407 "common.w"
+
+extern int strlen();
+extern int strcmp();
+extern char*strcpy();
+extern int strncmp();
+extern char*strncpy();
+
+/*:81*/
+#line 62 "common.w"
+
+
+/*:1*//*4:*/
+#line 88 "common.w"
+
+void
+common_init()
+{
+/*30:*/
+#line 613 "common.w"
+
+name_dir->byte_start= byte_ptr= byte_mem;
+name_ptr= name_dir+1;
+name_ptr->byte_start= byte_mem;
+
+/*:30*//*34:*/
+#line 647 "common.w"
+
+for(h= hash;h<=hash_end;*h++= NULL);
+
+/*:34*//*41:*/
+#line 729 "common.w"
+
+root= NULL;
+
+/*:41*/
+#line 92 "common.w"
+;
+/*68:*/
+#line 1225 "common.w"
+
+show_banner= show_happiness= show_progress= 1;
+
+/*:68*/
+#line 93 "common.w"
+;
+/*78:*/
+#line 1373 "common.w"
+
+scan_args();
+if(program==ctangle){
+if((C_file= fopen(C_file_name,"w"))==NULL)
+fatal("! Cannot open output file ",C_file_name);
+
+}
+else{
+if((tex_file= fopen(tex_file_name,"w"))==NULL)
+fatal("! Cannot open output file ",tex_file_name);
+}
+
+/*:78*/
+#line 94 "common.w"
+;
+}
+
+/*:4*//*9:*/
+#line 170 "common.w"
+
+int input_ln(fp)
+FILE*fp;
+{
+register int c= EOF;
+register char*k;
+if(feof(fp))return(0);
+limit= k= 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");
+
+}
+if(c==EOF&&limit==buffer)return(0);
+
+return(1);
+}
+
+/*:9*//*12:*/
+#line 249 "common.w"
+
+void
+prime_the_change_buffer()
+{
+change_limit= change_buffer;
+/*13:*/
+#line 263 "common.w"
+
+while(1){
+change_line++;
+if(!input_ln(change_file))return;
+if(limit<buffer+2)continue;
+if(buffer[0]!='@')continue;
+if(xisupper(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");
+
+}
+}
+
+/*:13*/
+#line 254 "common.w"
+;
+/*14:*/
+#line 280 "common.w"
+
+do{
+change_line++;
+if(!input_ln(change_file)){
+err_print("! Change file ended after @x");
+
+return;
+}
+}while(limit==buffer);
+
+/*:14*/
+#line 255 "common.w"
+;
+/*15:*/
+#line 290 "common.w"
+
+{
+change_limit= change_buffer-buffer+limit;
+strncpy(change_buffer,buffer,limit-buffer+1);
+}
+
+/*:15*/
+#line 256 "common.w"
+;
+}
+
+/*:12*//*16:*/
+#line 318 "common.w"
+
+void
+check_change()
+{
+int n= 0;
+if(lines_dont_match)return;
+change_pending= 0;
+if(!changed_section[section_count]){
+if_section_start_make_pending(1);
+if(!change_pending)changed_section[section_count]= 1;
+}
+while(1){
+changing= 1;print_where= 1;change_line++;
+if(!input_ln(change_file)){
+err_print("! Change file ended before @y");
+
+change_limit= change_buffer;changing= 0;
+return;
+}
+if(limit>buffer+1&&buffer[0]=='@'){
+if(xisupper(buffer[1]))buffer[1]= tolower(buffer[1]);
+/*17:*/
+#line 356 "common.w"
+
+if(buffer[1]=='x'||buffer[1]=='z'){
+loc= buffer+2;err_print("! Where is the matching @y?");
+
+}
+else if(buffer[1]=='y'){
+if(n>0){
+loc= buffer+2;
+printf("\n! Hmm... %d ",n);
+err_print("of the preceding lines failed to match");
+
+}
+change_depth= include_depth;
+return;
+}
+
+/*:17*/
+#line 340 "common.w"
+;
+}
+/*15:*/
+#line 290 "common.w"
+
+{
+change_limit= change_buffer-buffer+limit;
+strncpy(change_buffer,buffer,limit-buffer+1);
+}
+
+/*:15*/
+#line 342 "common.w"
+;
+changing= 0;cur_line++;
+while(!input_ln(cur_file)){
+if(include_depth==0){
+err_print("! CWEB file ended during a change");
+
+input_has_ended= 1;return;
+}
+include_depth--;cur_line++;
+}
+if(lines_dont_match)n++;
+}
+}
+
+/*:16*//*18:*/
+#line 376 "common.w"
+
+void
+reset_input()
+{
+limit= buffer;loc= buffer+1;buffer[0]= ' ';
+/*19:*/
+#line 391 "common.w"
+
+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);
+}
+
+
+web_file_open= 1;
+if((change_file= fopen(change_file_name,"r"))==NULL)
+fatal("! Cannot open change file ",change_file_name);
+
+/*:19*/
+#line 381 "common.w"
+;
+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;
+}
+
+/*:18*//*21:*/
+#line 424 "common.w"
+
+int get_line()
+{
+restart:
+if(changing&&include_depth==change_depth)
+/*25:*/
+#line 529 "common.w"
+{
+change_line++;
+if(!input_ln(change_file)){
+err_print("! Change file ended without @z");
+
+buffer[0]= '@';buffer[1]= 'z';limit= buffer+2;
+}
+if(limit>buffer){
+if(change_pending){
+if_section_start_make_pending(0);
+if(change_pending){
+changed_section[section_count]= 1;change_pending= 0;
+}
+}
+*limit= ' ';
+if(buffer[0]=='@'){
+if(xisupper(buffer[1]))buffer[1]= tolower(buffer[1]);
+if(buffer[1]=='x'||buffer[1]=='y'){
+loc= buffer+2;
+err_print("! Where is the matching @z?");
+
+}
+else if(buffer[1]=='z'){
+prime_the_change_buffer();changing= !changing;print_where= 1;
+}
+}
+}
+}
+
+/*:25*/
+#line 429 "common.w"
+;
+if(!changing||include_depth>change_depth){
+/*24:*/
+#line 512 "common.w"
+{
+cur_line++;
+while(!input_ln(cur_file)){
+print_where= 1;
+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();
+}
+
+/*:24*/
+#line 431 "common.w"
+;
+if(changing&&include_depth==change_depth)goto restart;
+}
+loc= buffer;*limit= ' ';
+if(*buffer=='@'&&(*(buffer+1)=='i'||*(buffer+1)=='I')){
+loc= buffer+2;
+while(loc<=limit&&(*loc==' '||*loc=='\t'||*loc=='"'))loc++;
+if(loc>=limit){
+err_print("! Include file name not given");
+
+goto restart;
+}
+if(include_depth>=max_include_depth-1){
+err_print("! Too many nested includes");
+
+goto restart;
+}
+include_depth++;
+/*23:*/
+#line 471 "common.w"
+{
+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;
+
+while(*loc!=' '&&*loc!='\t'&&*loc!='"'&&k<=cur_file_name_end)*k++= *loc++;
+if(k>cur_file_name_end)too_long();
+
+*k= '\0';
+if((cur_file= fopen(cur_file_name,"r"))!=NULL){
+cur_line= 0;print_where= 1;
+goto restart;
+}
+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
+}
+if(l>0){
+if(k+l+2>=cur_file_name_end)too_long();
+
+for(;k>=cur_file_name;k--)*(k+l+1)= *k;
+strcpy(cur_file_name,temp_file_name);
+cur_file_name[l]= '/';
+if((cur_file= fopen(cur_file_name,"r"))!=NULL){
+cur_line= 0;print_where= 1;
+goto restart;
+}
+}
+include_depth--;err_print("! Cannot open include file");goto restart;
+}
+
+/*:23*/
+#line 449 "common.w"
+;
+}
+return(!input_has_ended);
+}
+
+/*:21*//*26:*/
+#line 561 "common.w"
+
+void
+check_complete(){
+if(change_limit!=change_buffer){
+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");
+
+}
+}
+
+/*:26*//*35:*/
+#line 652 "common.w"
+
+name_pointer
+id_lookup(first,last,t)
+char*first;
+char*last;
+char t;
+{
+char*i= first;
+int h;
+int l;
+name_pointer p;
+if(last==NULL)for(last= first;*last!='\0';last++);
+l= last-first;
+/*36:*/
+#line 675 "common.w"
+
+h= (unsigned char)*i;
+while(++i<last)h= (h+h+(int)((unsigned char)*i))%hash_size;
+
+
+/*:36*/
+#line 665 "common.w"
+;
+/*37:*/
+#line 683 "common.w"
+
+p= hash[h];
+while(p&&!names_match(p,first,l,t))p= p->link;
+if(p==NULL){
+p= name_ptr;
+p->link= hash[h];hash[h]= p;
+}
+
+/*:37*/
+#line 666 "common.w"
+;
+if(p==name_ptr)/*39:*/
+#line 698 "common.w"
+{
+if(byte_ptr+l>byte_mem_end)overflow("byte memory");
+if(name_ptr>=name_dir_end)overflow("name");
+strncpy(byte_ptr,first,l);
+(++name_ptr)->byte_start= byte_ptr+= l;
+if(program==cweave)init_p(p,t);
+}
+
+/*:39*/
+#line 667 "common.w"
+;
+return(p);
+}
+
+/*:35*//*42:*/
+#line 756 "common.w"
+
+void
+print_section_name(p)
+name_pointer p;
+{
+char*ss,*s= first_chunk(p);
+name_pointer q= p+1;
+while(p!=name_dir){
+ss= (p+1)->byte_start-1;
+if(*ss==' '&&ss>=s){
+term_write(s,ss-s);p= q->link;q= p;
+}else{
+term_write(s,ss+1-s);p= name_dir;q= NULL;
+}
+s= p->byte_start;
+}
+if(q)term_write("...",3);
+}
+
+/*:42*//*43:*/
+#line 775 "common.w"
+
+void
+sprint_section_name(dest,p)
+char*dest;
+name_pointer p;
+{
+char*ss,*s= first_chunk(p);
+name_pointer q= p+1;
+while(p!=name_dir){
+ss= (p+1)->byte_start-1;
+if(*ss==' '&&ss>=s){
+p= q->link;q= p;
+}else{
+ss++;p= name_dir;
+}
+strncpy(dest,s,ss-s),dest+= ss-s;
+s= p->byte_start;
+}
+*dest= '\0';
+}
+
+/*:43*//*44:*/
+#line 796 "common.w"
+
+void
+print_prefix_name(p)
+name_pointer p;
+{
+char*s= first_chunk(p);
+int l= prefix_length(p);
+term_write(s,l);
+if(s+l<(p+1)->byte_start)term_write("...",3);
+}
+
+/*:44*//*45:*/
+#line 817 "common.w"
+
+int web_strcmp(j,j_len,k,k_len)
+char*j,*k;
+int j_len,k_len;
+{
+char*j1= j+j_len,*k1= k+k_len;
+while(k<k1&&j<j1&&*j==*k)k++,j++;
+if(k==k1)if(j==j1)return equal;
+else return extension;
+else if(j==j1)return prefix;
+else if(*j<*k)return less;
+else return greater;
+}
+
+/*:45*//*47:*/
+#line 847 "common.w"
+
+name_pointer
+add_section_name(par,c,first,last,ispref)
+name_pointer par;
+int c;
+char*first;
+char*last;
+int ispref;
+{
+name_pointer p= name_ptr;
+char*s= first_chunk(p);
+int name_len= last-first+ispref;
+if(s+name_len>byte_mem_end)overflow("byte memory");
+if(name_ptr+1>=name_dir_end)overflow("name");
+(++name_ptr)->byte_start= byte_ptr= s+name_len;
+if(ispref){
+*(byte_ptr-1)= ' ';
+name_len--;
+name_ptr->link= name_dir;
+(++name_ptr)->byte_start= byte_ptr;
+}
+set_prefix_length(p,name_len);
+strncpy(s,first,name_len);
+p->llink= NULL;
+p->rlink= NULL;
+init_node(p);
+return par==NULL?(root= p):c==less?(par->llink= p):(par->rlink= p);
+}
+
+/*:47*//*48:*/
+#line 876 "common.w"
+
+void
+extend_section_name(p,first,last,ispref)
+name_pointer p;
+char*first;
+char*last;
+int ispref;
+{
+char*s;
+name_pointer q= p+1;
+int name_len= last-first+ispref;
+if(name_ptr>=name_dir_end)overflow("name");
+while(q->link!=name_dir)q= q->link;
+q->link= name_ptr;
+s= name_ptr->byte_start;
+name_ptr->link= name_dir;
+if(s+name_len>byte_mem_end)overflow("byte memory");
+(++name_ptr)->byte_start= byte_ptr= s+name_len;
+strncpy(s,first,name_len);
+if(ispref)*(byte_ptr-1)= ' ';
+}
+
+/*:48*//*49:*/
+#line 904 "common.w"
+
+name_pointer
+section_lookup(first,last,ispref)
+char*first,*last;
+int ispref;
+{
+int c= 0;
+name_pointer p= root;
+name_pointer q= NULL;
+name_pointer r= NULL;
+name_pointer par= NULL;
+
+int name_len= last-first+1;
+/*50:*/
+#line 928 "common.w"
+
+while(p){
+c= web_strcmp(first,name_len,first_chunk(p),prefix_length(p));
+if(c==less||c==greater){
+if(r==NULL)
+par= p;
+p= (c==less?p->llink:p->rlink);
+}else{
+if(r!=NULL){
+printf("\n! Ambiguous prefix: matches <");
+
+print_prefix_name(p);
+printf(">\n and <");
+print_prefix_name(r);
+err_print(">");
+return name_dir;
+}
+r= p;
+p= p->llink;
+q= r->rlink;
+}
+if(p==NULL)
+p= q,q= NULL;
+}
+
+/*:50*/
+#line 918 "common.w"
+;
+/*51:*/
+#line 953 "common.w"
+
+if(r==NULL)
+return add_section_name(par,c,first,last+1,ispref);
+
+/*:51*/
+#line 919 "common.w"
+;
+/*52:*/
+#line 961 "common.w"
+
+switch(section_name_cmp(&first,name_len,r)){
+
+case prefix:
+if(!ispref){
+printf("\n! New name is a prefix of <");
+
+print_section_name(r);
+err_print(">");
+}
+else if(name_len<prefix_length(r))set_prefix_length(r,name_len);
+
+case equal:return r;
+case extension:if(!ispref||first<=last)
+extend_section_name(r,first,last+1,ispref);
+return r;
+case bad_extension:
+printf("\n! New name extends <");
+
+print_section_name(r);
+err_print(">");
+return r;
+default:
+printf("\n! Section name incompatible with <");
+
+print_prefix_name(r);
+printf(">,\n which abbreviates <");
+print_section_name(r);
+err_print(">");
+return r;
+}
+
+/*:52*/
+#line 920 "common.w"
+;
+}
+
+/*:49*//*54:*/
+#line 1012 "common.w"
+
+int section_name_cmp(pfirst,len,r)
+char**pfirst;
+int len;
+name_pointer r;
+{
+char*first= *pfirst;
+name_pointer q= r+1;
+char*ss,*s= first_chunk(r);
+int c;
+int ispref;
+while(1){
+ss= (r+1)->byte_start-1;
+if(*ss==' '&&ss>=r->byte_start)ispref= 1,q= q->link;
+else ispref= 0,ss++,q= name_dir;
+switch(c= web_strcmp(first,len,s,ss-s)){
+case equal:if(q==name_dir)
+if(ispref){
+*pfirst= first+(ss-s);
+return extension;
+}else return equal;
+else return(q->byte_start==(q+1)->byte_start)?equal:prefix;
+case extension:
+if(!ispref)return bad_extension;
+first+= ss-s;
+if(q!=name_dir){len-= ss-s;s= q->byte_start;r= q;continue;}
+*pfirst= first;return extension;
+default:return c;
+}
+}
+}
+
+/*:54*//*58:*/
+#line 1087 "common.w"
+
+void
+err_print(s)
+char*s;
+{
+char*k,*l;
+printf(*s=='!'?"\n%s":"%s",s);
+if(web_file_open)/*59:*/
+#line 1107 "common.w"
+
+{if(changing&&include_depth==change_depth)
+printf(". (l. %d of change file)\n",change_line);
+else if(include_depth==0)printf(". (l. %d)\n",cur_line);
+else printf(". (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')putchar(' ');
+else putchar(*k);
+putchar('\n');
+for(k= buffer;k<l;k++)putchar(' ');
+}
+for(k= l;k<limit;k++)putchar(*k);
+if(*limit=='|')putchar('|');
+putchar(' ');
+}
+
+/*:59*/
+#line 1094 "common.w"
+;
+update_terminal;mark_error;
+}
+
+/*:58*//*61:*/
+#line 1142 "common.w"
+
+int wrap_up(){
+putchar('\n');
+if(show_stats)
+print_stats();
+/*62:*/
+#line 1152 "common.w"
+
+switch(history){
+case spotless:if(show_happiness)printf("(No errors were found.)\n");break;
+case harmless_message:
+printf("(Did you see the warning message above?)\n");break;
+case error_message:
+printf("(Pardon me, but I think I spotted something wrong.)\n");break;
+case fatal_message:printf("(That was a fatal error, my friend.)\n");
+}
+
+/*:62*/
+#line 1147 "common.w"
+;
+if(history>harmless_message)return(1);
+else return(0);
+}
+
+/*:61*//*64:*/
+#line 1171 "common.w"
+void
+fatal(s,t)
+char*s,*t;
+{
+if(*s)printf(s);
+err_print(t);
+history= fatal_message;exit(wrap_up());
+}
+
+/*:64*//*65:*/
+#line 1182 "common.w"
+void
+overflow(t)
+char*t;
+{
+printf("\n! Sorry, %s capacity exceeded",t);fatal("","");
+}
+
+
+/*:65*//*70:*/
+#line 1246 "common.w"
+
+void
+scan_args()
+{
+char*dot_pos;
+char*name_pos;
+register char*s;
+boolean found_web= 0,found_change= 0,found_out= 0;
+
+boolean flag_change;
+
+while(--argc>0){
+if((**(++argv)=='-'||**argv=='+')&&*(*argv+1))/*74:*/
+#line 1340 "common.w"
+
+{
+if(**argv=='-')flag_change= 0;
+else flag_change= 1;
+for(dot_pos= *argv+1;*dot_pos>'\0';dot_pos++)
+flags[*dot_pos]= flag_change;
+}
+
+/*:74*/
+#line 1258 "common.w"
+
+else{
+s= name_pos= *argv;dot_pos= NULL;
+while(*s){
+if(*s=='.')dot_pos= s++;
+#line 47 "common.ch"
+#ifdef __EMX__
+else if(*s==':'||*s=='\\'||*s=='/')
+dot_pos= NULL,name_pos= ++s;
+#else
+else if(*s=='/')dot_pos= NULL,name_pos= ++s;
+#endif
+#line 1264 "common.w"
+ else s++;
+}
+if(!found_web)/*71:*/
+#line 1284 "common.w"
+
+{
+if(s-*argv>max_file_name_length-5)
+/*76:*/
+#line 1360 "common.w"
+fatal("! Filename too long\n",*argv);
+
+
+/*:76*/
+#line 1287 "common.w"
+;
+if(dot_pos==NULL)
+sprintf(web_file_name,"%s.w",*argv);
+else{
+strcpy(web_file_name,*argv);
+*dot_pos= 0;
+}
+sprintf(alt_web_file_name,"%s.web",*argv);
+sprintf(tex_file_name,"%s.tex",name_pos);
+sprintf(idx_file_name,"%s.idx",name_pos);
+sprintf(scn_file_name,"%s.scn",name_pos);
+sprintf(C_file_name,"%s.c",name_pos);
+found_web= 1;
+}
+
+/*:71*/
+#line 1267 "common.w"
+
+else if(!found_change)/*72:*/
+#line 1302 "common.w"
+
+{
+if(strcmp(*argv,"-")==0)found_change= -1;
+else{
+if(s-*argv>max_file_name_length-4)
+/*76:*/
+#line 1360 "common.w"
+fatal("! Filename too long\n",*argv);
+
+
+/*:76*/
+#line 1307 "common.w"
+;
+if(dot_pos==NULL)
+sprintf(change_file_name,"%s.ch",*argv);
+else strcpy(change_file_name,*argv);
+found_change= 1;
+}
+}
+
+/*:72*/
+#line 1268 "common.w"
+
+else if(!found_out)/*73:*/
+#line 1315 "common.w"
+
+{
+if(s-*argv>max_file_name_length-5)
+/*76:*/
+#line 1360 "common.w"
+fatal("! Filename too long\n",*argv);
+
+
+/*:76*/
+#line 1318 "common.w"
+;
+if(dot_pos==NULL){
+sprintf(tex_file_name,"%s.tex",*argv);
+sprintf(idx_file_name,"%s.idx",*argv);
+sprintf(scn_file_name,"%s.scn",*argv);
+sprintf(C_file_name,"%s.c",*argv);
+}else{
+strcpy(tex_file_name,*argv);
+if(flags['x']){
+if(program==cweave&&strcmp(*argv+strlen(*argv)-4,".tex")!=0)
+fatal("! Output file name should end with .tex\n",*argv);
+
+strcpy(idx_file_name,*argv);
+strcpy(idx_file_name+strlen(*argv)-4,".idx");
+strcpy(scn_file_name,*argv);
+strcpy(scn_file_name+strlen(*argv)-4,".scn");
+}
+strcpy(C_file_name,*argv);
+}
+found_out= 1;
+}
+
+/*:73*/
+#line 1269 "common.w"
+
+else/*75:*/
+#line 1348 "common.w"
+
+{
+if(program==ctangle)
+fatal(
+"! Usage: ctangle [options] webfile[.w] [{changefile[.ch]|-} [outfile[.c]]]\n"
+,"");
+
+else fatal(
+#line 69 "common.ch"
+"! Usage: cweave [options] webfile[.w] [{changefile[.ch]|-} [outfile[.tex]]]\n"
+"\n"
+" possible options: (default values shown)\n"
+"\n"
+" -a alternative output format\n"
+" +b show banner\n"
+" +f force line breaks after C statements\n"
+" +h print happy message if successful\n"
+" -i append () after functions in index\n"
+" +p give progress reports\n"
+" -s show memory statistics\n"
+" +x include indices and table of contents\n","");
+#line 1358 "common.w"
+}
+
+/*:75*/
+#line 1270 "common.w"
+;
+}
+}
+if(!found_web)/*75:*/
+#line 1348 "common.w"
+
+{
+if(program==ctangle)
+fatal(
+"! Usage: ctangle [options] webfile[.w] [{changefile[.ch]|-} [outfile[.c]]]\n"
+,"");
+
+else fatal(
+#line 69 "common.ch"
+"! Usage: cweave [options] webfile[.w] [{changefile[.ch]|-} [outfile[.tex]]]\n"
+"\n"
+" possible options: (default values shown)\n"
+"\n"
+" -a alternative output format\n"
+" +b show banner\n"
+" +f force line breaks after C statements\n"
+" +h print happy message if successful\n"
+" -i append () after functions in index\n"
+" +p give progress reports\n"
+" -s show memory statistics\n"
+" +x include indices and table of contents\n","");
+#line 1358 "common.w"
+}
+
+/*:75*/
+#line 1273 "common.w"
+;
+#line 58 "common.ch"
+#ifdef __EMX__
+if(found_change<=0)strcpy(change_file_name,"NUL");
+#else
+if(found_change<=0)strcpy(change_file_name,"/dev/null");
+#endif
+#line 1275 "common.w"
+}
+
+/*:70*/
diff --git a/web/c_cpp/c2cweb/cweb/common.ch b/web/c_cpp/c2cweb/cweb/common.ch
new file mode 100644
index 0000000000..f591d774bf
--- /dev/null
+++ b/web/c_cpp/c2cweb/cweb/common.ch
@@ -0,0 +1,83 @@
+This file is part of the c2cweb package Version 1.5
+
+This is the change file for CWEB's COMMON (Ver. 3.2 July 1994)
+
+modified by Werner Lemberg (a7971428@@unet.univie.ac.at) 10-Nov-1996
+
+===============================================================================
+
+@x section 7
+@d buf_size 100 /* for \.{CWEAVE} and \.{CTANGLE} */
+@y
+@d buf_size 400 /* for \.{CWEAVE} and \.{CTANGLE} */
+@z
+
+@x section 27
+@d max_bytes 90000 /* the number of bytes in identifiers,
+ index entries, and section names; must be less than $2^{24}$ */
+@d max_names 4000 /* number of identifiers, strings, section names;
+ must be less than 10240 */
+@y
+@d max_bytes 225000 /* the number of bytes in identifiers,
+ index entries, and section names; must be less than $2^{24}$ */
+@d max_names 10000 /* number of identifiers, strings, section names;
+ must be less than 10240 */
+@z
+
+@x section 40
+ char Ilk; /* used by identifiers in \.{CWEAVE} only */
+} dummy;
+@y
+ struct {
+ char Ilk; /* used by identifiers in \.{CWEAVE} only */
+ boolean Func_flag; } dummy1;
+} dummy;
+@z
+
+@x section 69
+An omitted change file argument means that |"/dev/null"| should be used,
+@y
+An omitted change file argument means that |"/dev/null"| (or |"NUL"| under DOS
+and OS/2) should be used,
+@z
+
+@x section 70
+ else if (*s=='/') dot_pos=NULL,name_pos=++s;
+@y
+#ifdef __EMX__
+ else if (*s == ':' || *s == '\\' || *s == '/')
+ dot_pos=NULL,name_pos=++s;
+#else
+ else if (*s=='/') dot_pos=NULL,name_pos=++s;
+#endif
+@z
+
+@x section 70
+ if (found_change<=0) strcpy(change_file_name,"/dev/null");
+@y
+#ifdef __EMX__
+ if (found_change<=0) strcpy(change_file_name,"NUL");
+#else
+ if (found_change<=0) strcpy(change_file_name,"/dev/null");
+#endif
+@z
+
+@x section 75
+"! Usage: cweave [options] webfile[.w] [{changefile[.ch]|-} [outfile[.tex]]]\n"
+ ,"");
+@y
+"! Usage: cweave [options] webfile[.w] [{changefile[.ch]|-} [outfile[.tex]]]\n"
+"\n"
+" possible options: (default values shown)\n"
+"\n"
+" -a alternative output format\n"
+" +b show banner\n"
+" +f force line breaks after C statements\n"
+" +h print happy message if successful\n"
+" -i append () after functions in index\n"
+" +p give progress reports\n"
+" -s show memory statistics\n"
+" +x include indices and table of contents\n", "");
+@z
+
+--- end of common.ch ---
diff --git a/web/c_cpp/c2cweb/cweb/common.h b/web/c_cpp/c2cweb/cweb/common.h
new file mode 100644
index 0000000000..200ec27358
--- /dev/null
+++ b/web/c_cpp/c2cweb/cweb/common.h
@@ -0,0 +1,201 @@
+% This file is part of CWEB.
+% This program by Silvio Levy and Donald E. Knuth
+% is based on a program by Knuth.
+% It is distributed WITHOUT ANY WARRANTY, express or implied.
+% Version 3.0 --- June 1993
+
+% Copyright (C) 1987,1990,1993 Silvio Levy and Donald E. Knuth
+
+% this file is part of the c2cweb package Version 1.5
+% modified by Werner Lemberg (a7971428@@unet.univie.ac.at) 10-Nov-1996
+
+% Permission is granted to make and distribute verbatim copies of this
+% document provided that the copyright notice and this permission notice
+% are preserved on all copies.
+
+% Permission is granted to copy and distribute modified versions of this
+% document under the conditions for verbatim copying, provided that the
+% entire resulting derived work is distributed under the terms of a
+% permission notice identical to this one.
+
+% Please send comments, suggestions, etc. to levy@@geom.umn.edu.
+
+% The next few sections contain stuff from the file |"common.w"| that has
+% to be included in both |"ctangle.w"| and |"cweave.w"|. It appears in this
+% file |"common.h"|, which needs to be updated when |"common.w"| changes.
+
+First comes general stuff:
+
+@d ctangle 0
+@d cweave 1
+
+@<Common code for \.{CWEAVE} and \.{CTANGLE}@>=
+typedef short boolean;
+typedef char unsigned eight_bits;
+extern boolean program; /* \.{CWEAVE} or \.{CTANGLE}? */
+extern int phase; /* which phase are we in? */
+
+@ @<Include files@>=
+#include <stdio.h>
+
+@ Code related to the character set:
+@^ASCII code dependencies@>
+
+@d and_and 04 /* `\.{\&\&}'\,; corresponds to MIT's {\tentex\char'4} */
+@d lt_lt 020 /* `\.{<<}'\,; corresponds to MIT's {\tentex\char'20} */
+@d gt_gt 021 /* `\.{>>}'\,; corresponds to MIT's {\tentex\char'21} */
+@d plus_plus 013 /* `\.{++}'\,; corresponds to MIT's {\tentex\char'13} */
+@d minus_minus 01 /* `\.{--}'\,; corresponds to MIT's {\tentex\char'1} */
+@d minus_gt 031 /* `\.{->}'\,; corresponds to MIT's {\tentex\char'31} */
+@d not_eq 032 /* `\.{!=}'\,; corresponds to MIT's {\tentex\char'32} */
+@d lt_eq 034 /* `\.{<=}'\,; corresponds to MIT's {\tentex\char'34} */
+@d gt_eq 035 /* `\.{>=}'\,; corresponds to MIT's {\tentex\char'35} */
+@d eq_eq 036 /* `\.{==}'\,; corresponds to MIT's {\tentex\char'36} */
+@d or_or 037 /* `\.{\v\v}'\,; corresponds to MIT's {\tentex\char'37} */
+@d dot_dot_dot 016 /* `\.{...}'\,; corresponds to MIT's {\tentex\char'16} */
+@d colon_colon 06 /* `\.{::}'\,; corresponds to MIT's {\tentex\char'6} */
+@d period_ast 026 /* `\.{.*}'\,; corresponds to MIT's {\tentex\char'26} */
+@d minus_gt_ast 027 /* `\.{->*}'\,; corresponds to MIT's {\tentex\char'27} */
+
+@<Common code...@>=
+char section_text[longest_name+1]; /* name being sought for */
+char *section_text_end = section_text+longest_name; /* end of |section_text| */
+char *id_first; /* where the current identifier begins in the buffer */
+char *id_loc; /* just after the current identifier in the buffer */
+
+@ Code related to input routines:
+
+@d xisalpha(c) (isalpha(c)&&((eight_bits)c<0200))
+@d xisdigit(c) (isdigit(c)&&((eight_bits)c<0200))
+@d xisspace(c) (isspace(c)&&((eight_bits)c<0200))
+@d xislower(c) (islower(c)&&((eight_bits)c<0200))
+@d xisupper(c) (isupper(c)&&((eight_bits)c<0200))
+@d xisxdigit(c) (isxdigit(c)&&((eight_bits)c<0200))
+
+@<Common code...@>=
+extern char buffer[]; /* where each line of input goes */
+extern char *buffer_end; /* end of |buffer| */
+extern char *loc; /* points to the next character to be read from the buffer*/
+extern char *limit; /* points to the last character in the buffer */
+
+@ Code related to identifier and section name storage:
+@d length(c) (c+1)->byte_start-(c)->byte_start /* the length of a name */
+@d print_id(c) term_write((c)->byte_start,length((c))) /* print identifier */
+@d llink link /* left link in binary search tree for section names */
+@d rlink dummy.Rlink /* right link in binary search tree for section names */
+@d root name_dir->rlink /* the root of the binary search tree
+ for section names */
+@d chunk_marker 0
+
+@<Common code...@>=
+typedef struct name_info {
+ char *byte_start; /* beginning of the name in |byte_mem| */
+ struct name_info *link;
+ union {
+ struct name_info *Rlink; /* right link in binary search tree for section
+ names */
+ struct {
+ char Ilk; /* used by identifiers in \.{CWEAVE} only */
+ boolean Func_flag;
+ } dummy1;
+ } dummy;
+ char *equiv_or_xref; /* info corresponding to names */
+} name_info; /* contains information about an identifier or section name */
+typedef name_info *name_pointer; /* pointer into array of \&{name\_info}s */
+typedef name_pointer *hash_pointer;
+extern char byte_mem[]; /* characters of names */
+extern char *byte_mem_end; /* end of |byte_mem| */
+extern name_info name_dir[]; /* information about names */
+extern name_pointer name_dir_end; /* end of |name_dir| */
+extern name_pointer name_ptr; /* first unused position in |byte_start| */
+extern char *byte_ptr; /* first unused position in |byte_mem| */
+extern name_pointer hash[]; /* heads of hash lists */
+extern hash_pointer hash_end; /* end of |hash| */
+extern hash_pointer h; /* index into hash-head array */
+extern name_pointer id_lookup(); /* looks up a string in the identifier table */
+extern name_pointer section_lookup(); /* finds section name */
+extern void print_section_name(), sprint_section_name();
+
+@ Code related to error handling:
+@d spotless 0 /* |history| value for normal jobs */
+@d harmless_message 1 /* |history| value when non-serious info was printed */
+@d error_message 2 /* |history| value when an error was noted */
+@d fatal_message 3 /* |history| value when we had to stop prematurely */
+@d mark_harmless {if (history==spotless) history=harmless_message;}
+@d mark_error history=error_message
+@d confusion(s) fatal("! This can't happen: ",s)
+
+@<Common...@>=
+extern history; /* indicates how bad this run was */
+extern err_print(); /* print error message and context */
+extern wrap_up(); /* indicate |history| and exit */
+extern void fatal(); /* issue error message and die */
+extern void overflow(); /* succumb because a table has overflowed */
+
+@ Code related to file handling:
+@f line x /* make |line| an unreserved word */
+@d max_file_name_length 60
+@d cur_file file[include_depth] /* current file */
+@d cur_file_name file_name[include_depth] /* current file name */
+@d web_file_name file_name[0] /* main source file name */
+@d cur_line line[include_depth] /* number of current line in current file */
+
+@<Common code...@>=
+extern include_depth; /* current level of nesting */
+extern FILE *file[]; /* stack of non-change files */
+extern FILE *change_file; /* change file */
+extern char C_file_name[]; /* name of |C_file| */
+extern char tex_file_name[]; /* name of |tex_file| */
+extern char idx_file_name[]; /* name of |idx_file| */
+extern char scn_file_name[]; /* name of |scn_file| */
+extern char file_name[][max_file_name_length];
+ /* stack of non-change file names */
+extern char change_file_name[]; /* name of change file */
+extern line[]; /* number of current line in the stacked files */
+extern change_line; /* number of current line in change file */
+extern boolean input_has_ended; /* if there is no more input */
+extern boolean changing; /* if the current line is from |change_file| */
+extern boolean web_file_open; /* if the web file is being read */
+extern reset_input(); /* initialize to read the web file and change file */
+extern get_line(); /* inputs the next line */
+extern check_complete(); /* checks that all changes were picked up */
+
+@ Code related to section numbers:
+@<Common code...@>=
+typedef unsigned short sixteen_bits;
+extern sixteen_bits section_count; /* the current section number */
+extern boolean changed_section[]; /* is the section changed? */
+extern boolean change_pending; /* is a decision about change still unclear? */
+extern boolean print_where; /* tells \.{CTANGLE} to print line and file info */
+
+@ Code related to command line arguments:
+@d show_banner flags['b'] /* should the banner line be printed? */
+@d show_progress flags['p'] /* should progress reports be printed? */
+@d show_happiness flags['h'] /* should lack of errors be announced? */
+
+@<Common code...@>=
+extern int argc; /* copy of |ac| parameter to |main| */
+extern char **argv; /* copy of |av| parameter to |main| */
+extern boolean flags[]; /* an option for each 7-bit code */
+
+@ Code relating to output:
+@d update_terminal fflush(stdout) /* empty the terminal output buffer */
+@d new_line putchar('\n') @d putxchar putchar
+@d term_write(a,b) fflush(stdout),fwrite(a,sizeof(char),b,stdout)
+@d C_printf(c,a) fprintf(C_file,c,a)
+@d C_putc(c) putc(c,C_file)
+
+@<Common code...@>=
+extern FILE *C_file; /* where output of \.{CTANGLE} goes */
+extern FILE *tex_file; /* where output of \.{CWEAVE} goes */
+extern FILE *idx_file; /* where index from \.{CWEAVE} goes */
+extern FILE *scn_file; /* where list of sections from \.{CWEAVE} goes */
+extern FILE *active_file; /* currently active file for \.{CWEAVE} output */
+
+@ The procedure that gets everything rolling:
+
+@<Common code...@>=
+extern void common_init();
+
+
+@q end of common.h @>
diff --git a/web/c_cpp/c2cweb/cweb/common.w b/web/c_cpp/c2cweb/cweb/common.w
new file mode 100644
index 0000000000..48caf68e24
--- /dev/null
+++ b/web/c_cpp/c2cweb/cweb/common.w
@@ -0,0 +1,1415 @@
+% This file is part of CWEB.
+% This program by Silvio Levy and Donald E. Knuth
+% is based on a program by Knuth.
+% It is distributed WITHOUT ANY WARRANTY, express or implied.
+% Version 3.3 --- December 1994 (works with later versions too)
+
+% Copyright (C) 1987,1990,1993 Silvio Levy and Donald E. Knuth
+
+% Permission is granted to make and distribute verbatim copies of this
+% document provided that the copyright notice and this permission notice
+% are preserved on all copies.
+
+% Permission is granted to copy and distribute modified versions of this
+% document under the conditions for verbatim copying, provided that the
+% entire resulting derived work is given a different name and distributed
+% under the terms of a permission notice identical to this one.
+
+\def\v{\char'174} % vertical (|) in typewriter font
+
+\def\title{Common code for CTANGLE and CWEAVE (Version 3.3)}
+\def\topofcontents{\null\vfill
+ \centerline{\titlefont Common code for {\ttitlefont CTANGLE} and
+ {\ttitlefont CWEAVE}}
+ \vskip 15pt
+ \centerline{(Version 3.3)}
+ \vfill}
+\def\botofcontents{\vfill
+\noindent
+Copyright \copyright\ 1987, 1990, 1993 Silvio Levy and Donald E. Knuth
+\bigskip\noindent
+Permission is granted to make and distribute verbatim copies of this
+document provided that the copyright notice and this permission notice
+are preserved on all copies.
+
+\smallskip\noindent
+Permission is granted to copy and distribute modified versions of this
+document under the conditions for verbatim copying, provided that the
+entire resulting derived work is given a different name and distributed
+under the terms of a permission notice identical to this one.
+}
+
+\pageno=\contentspagenumber \advance\pageno by 1
+\let\maybe=\iftrue
+
+@** Introduction. This file contains code common
+to both \.{CTANGLE} and \.{CWEAVE}, which roughly concerns the following
+problems: character uniformity, input routines, error handling and
+parsing of command line. We have tried to concentrate in this file
+all the system dependencies, so as to maximize portability.
+
+In the texts below we will
+sometimes use \.{CWEB} to refer to either of the two component
+programs, if no confusion can arise.
+
+The file begins with a few basic definitions.
+
+@c
+@<Include files@>@/
+@h
+@<Definitions that should agree with \.{CTANGLE} and \.{CWEAVE}@>@/
+@<Other definitions@>@/
+@<Predeclaration of procedures@>@/
+
+@ In certain cases \.{CTANGLE} and \.{CWEAVE} should do almost, but not
+quite, the same thing. In these cases we've written common code for
+both, differentiating between the two by means of the global variable
+|program|.
+
+@d ctangle 0
+@d cweave 1
+
+@<Definitions...@>=
+typedef short boolean;
+boolean program; /* \.{CWEAVE} or \.{CTANGLE}? */
+
+@ \.{CWEAVE} operates in three phases: first it inputs the source
+file and stores cross-reference data, then it inputs the source once again and
+produces the \TEX/ output file, and finally it sorts and outputs the index.
+Similarly, \.{CTANGLE} operates in two phases.
+The global variable |phase| tells which phase we are in.
+
+@<Other...@>= int phase; /* which phase are we in? */
+
+@ There's an initialization procedure that gets both \.{CTANGLE} and
+\.{CWEAVE} off to a good start. We will fill in the details of this
+procedure later.
+
+@c
+void
+common_init()
+{
+ @<Initialize pointers@>;
+ @<Set the default options common to \.{CTANGLE} and \.{CWEAVE}@>;
+ @<Scan arguments and open output files@>;
+}
+
+@*1 The character set.
+\.{CWEB} uses the conventions of \CEE/ programs found in the standard
+\.{ctype.h} header file.
+
+@<Include files@>=
+#include <ctype.h>
+
+@ A few character pairs are encoded internally as single characters,
+using the definitions below. These definitions are consistent with
+an extension of ASCII code originally developed at MIT and explained in
+Appendix~C of {\sl The \TEX/book\/}; thus, users who have such a
+character set can type things like \.{\char'32} and \.{\char'4} instead
+of \.{!=} and \.{\&\&}. (However, their files will not be too portable
+until more people adopt the extended code.)
+
+If the character set is not ASCII, the definitions given here may conflict
+with existing characters; in such cases, other arbitrary codes should be
+substituted. The indexes to \.{CTANGLE} and \.{CWEAVE} mention every
+case where similar codes may have to be changed in order to
+avoid character conflicts. Look for the entry ``ASCII code dependencies''
+in those indexes.
+
+@^ASCII code dependencies@>
+@^system dependencies@>
+
+@d and_and 04 /* `\.{\&\&}'\,; corresponds to MIT's {\tentex\char'4} */
+@d lt_lt 020 /* `\.{<<}'\,; corresponds to MIT's {\tentex\char'20} */
+@d gt_gt 021 /* `\.{>>}'\,; corresponds to MIT's {\tentex\char'21} */
+@d plus_plus 013 /* `\.{++}'\,; corresponds to MIT's {\tentex\char'13} */
+@d minus_minus 01 /* `\.{--}'\,; corresponds to MIT's {\tentex\char'1} */
+@d minus_gt 031 /* `\.{->}'\,; corresponds to MIT's {\tentex\char'31} */
+@d not_eq 032 /* `\.{!=}'\,; corresponds to MIT's {\tentex\char'32} */
+@d lt_eq 034 /* `\.{<=}'\,; corresponds to MIT's {\tentex\char'34} */
+@d gt_eq 035 /* `\.{>=}'\,; corresponds to MIT's {\tentex\char'35} */
+@d eq_eq 036 /* `\.{==}'\,; corresponds to MIT's {\tentex\char'36} */
+@d or_or 037 /* `\.{\v\v}'\,; corresponds to MIT's {\tentex\char'37} */
+@d dot_dot_dot 016 /* `\.{...}'\,; corresponds to MIT's {\tentex\char'16} */
+@d colon_colon 06 /* `\.{::}'\,; corresponds to MIT's {\tentex\char'6} */
+@d period_ast 026 /* `\.{.*}'\,; corresponds to MIT's {\tentex\char'26} */
+@d minus_gt_ast 027 /* `\.{->*}'\,; corresponds to MIT's {\tentex\char'27} */
+
+@** Input routines. The lowest level of input to the \.{CWEB} 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 conventions
+of \TEX/ are followed; i.e., 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.
+
+Since |buf_size| is strictly less than |long_buf_size|,
+some of \.{CWEB}'s routines use the fact that it is safe to refer to
+|*(limit+2)| without overstepping the bounds of the array.
+
+@d buf_size 100 /* for \.{CWEAVE} and \.{CTANGLE} */
+@d longest_name 1000
+@d long_buf_size (buf_size+longest_name) /* for \.{CWEAVE} */
+@d xisspace(c) (isspace(c)&&((unsigned char)c<0200))
+@d xisupper(c) (isupper(c)&&((unsigned char)c<0200))
+
+@<Definitions...@>=
+char buffer[long_buf_size]; /* where each line of input goes */
+char *buffer_end=buffer+buf_size-2; /* end of |buffer| */
+char *limit=buffer; /* points to the last character in the buffer */
+char *loc=buffer; /* points to the next character to be read from the buffer */
+
+@ @<Include files@>=
+#include <stdio.h>
+
+@ 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@>
+
+@c
+int 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");
+@.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 and
+for the benefit of \.{CTANGLE}.
+
+@f line x /* make |line| an unreserved word */
+@d max_include_depth 10 /* maximum number of source files open
+ simultaneously, not counting the change file */
+@d max_file_name_length 60
+@d cur_file file[include_depth] /* current file */
+@d cur_file_name file_name[include_depth] /* current file name */
+@d cur_line line[include_depth] /* number of current line in current file */
+@d web_file file[0] /* main source file */
+@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:
+
+@d lines_dont_match (change_limit-change_buffer != limit-buffer ||
+ strncmp(buffer, change_buffer, limit-buffer))
+
+@<Other...@>=
+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.
+
+@c
+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 (xisupper(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");
+@.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");
+@.Change file ended...@>
+ return;
+ }
+} while (limit==buffer);
+
+@ @<Move |buffer| and |limit| to |change_buffer| and |change_limit|@>=
+{
+ change_limit=change_buffer-buffer+limit;
+ 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|.
+
+When a match is found, the current section is marked as changed unless
+the first line after the \.{@@x} and after the \.{@@y} both start with
+either |'@@*'| or |'@@ '| (possibly preceded by whitespace).
+
+This procedure is called only when |buffer<limit|, i.e., when the
+current line is nonempty.
+
+@d if_section_start_make_pending(b) {@+*limit='!';
+ for (loc=buffer;xisspace(*loc);loc++) ;
+ *limit=' ';
+ if (*loc=='@@' && (xisspace(*(loc+1)) || *(loc+1)=='*')) change_pending=b;
+}
+
+@c
+void
+check_change() /* switches to |change_file| if the buffers match */
+{
+ int n=0; /* the number of discrepancies found */
+ if (lines_dont_match) return;
+ change_pending=0;
+ if (!changed_section[section_count]) {
+ if_section_start_make_pending(1);
+ if (!change_pending) changed_section[section_count]=1;
+ }
+ while (1) {
+ changing=1; print_where=1; change_line++;
+ if (!input_ln(change_file)) {
+ err_print("! Change file ended before @@y");
+@.Change file ended...@>
+ change_limit=change_buffer; changing=0;
+ return;
+ }
+ if (limit>buffer+1 && buffer[0]=='@@') {
+ if (xisupper(buffer[1])) buffer[1]=tolower(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");
+@.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 (buffer[1]=='x' || buffer[1]=='z') {
+ loc=buffer+2; err_print("! Where is the matching @@y?");
+@.Where is the match...@>
+ }
+else if (buffer[1]=='y') {
+ if (n>0) {
+ loc=buffer+2;
+ printf("\n! Hmm... %d ",n);
+ err_print("of the preceding lines failed to match");
+@.Hmm... n of the preceding...@>
+ }
+ change_depth=include_depth;
+ return;
+}
+
+@ The |reset_input| procedure, which gets \.{CWEB} ready to read the
+user's \.{CWEB} input, is used at the beginning of phase one of \.{CTANGLE},
+phases one and two of \.{CWEAVE}.
+
+@c
+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);
+}
+@.Cannot open input file@>
+@.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.
+
+If we've just changed from the |cur_file| to the |change_file|, or if
+the |cur_file| has changed, we tell \.{CTANGLE} to print this
+information in the \CEE/ file by means of the |print_where| flag.
+
+@d max_sections 2000 /* number of identifiers, strings, section names;
+ must be less than 10240 */
+
+@<Defin...@>=
+typedef unsigned short sixteen_bits;
+sixteen_bits section_count; /* the current section number */
+boolean changed_section[max_sections]; /* is the section changed? */
+boolean change_pending; /* if the current change is not yet recorded in
+ |changed_section[section_count]| */
+boolean print_where=0; /* should \.{CTANGLE} print line and file info? */
+
+@ @c
+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;
+ }
+ loc=buffer; *limit=' ';
+ if (*buffer=='@@' && (*(buffer+1)=='i' || *(buffer+1)=='I')) {
+ loc=buffer+2;
+ while (loc<=limit && (*loc==' '||*loc=='\t'||*loc=='"')) loc++;
+ if (loc>=limit) {
+ err_print("! Include file name not given");
+@.Include file name ...@>
+ goto restart;
+ }
+ if (include_depth>=max_include_depth-1) {
+ err_print("! Too many nested includes");
+@.Too many nested includes@>
+ goto restart;
+ }
+ include_depth++; /* push input stack */
+ @<Try to open include file, abort push if unsuccessful, go to |restart|@>;
+ }
+ return (!input_has_ended);
+}
+
+@ 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.
+
+@d too_long() {include_depth--;
+ err_print("! Include file name too long"); goto restart;}
+
+@<Include...@>=
+#include <stdlib.h> /* declaration of |getenv| and |exit| */
+
+@ @<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 */
+
+ while (*loc!=' '&&*loc!='\t'&&*loc!='"'&&k<=cur_file_name_end) *k++=*loc++;
+ if (k>cur_file_name_end) too_long();
+@.Include file name ...@>
+ *k='\0';
+ if ((cur_file=fopen(cur_file_name,"r"))!=NULL) {
+ cur_line=0; print_where=1;
+ 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();
+@.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; print_where=1;
+ 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 */
+ print_where=1;
+ 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");
+@.Change file ended...@>
+ buffer[0]='@@'; buffer[1]='z'; limit=buffer+2;
+ }
+ if (limit>buffer) { /* check if the change has ended */
+ if (change_pending) {
+ if_section_start_make_pending(0);
+ if (change_pending) {
+ changed_section[section_count]=1; change_pending=0;
+ }
+ }
+ *limit=' ';
+ if (buffer[0]=='@@') {
+ if (xisupper(buffer[1])) buffer[1]=tolower(buffer[1]);
+ if (buffer[1]=='x' || buffer[1]=='y') {
+ loc=buffer+2;
+ err_print("! Where is the matching @@z?");
+@.Where is the match...@>
+ }
+ else if (buffer[1]=='z') {
+ prime_the_change_buffer(); changing=!changing; print_where=1;
+ }
+ }
+ }
+}
+
+@ 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|.
+
+@c
+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@>
+ }
+}
+
+@** Storage of names and strings.
+Both \.{CWEAVE} and \.{CTANGLE} store identifiers, section names and
+other strings in a large array of |char|s, called |byte_mem|.
+Information about the names is kept in the array |name_dir|, whose
+elements are structures of type |name_info|, containing a pointer into
+the |byte_mem| array (the address where the name begins) and other data.
+A |name_pointer| variable is a pointer into |name_dir|.
+
+@d max_bytes 90000 /* the number of bytes in identifiers,
+ index entries, and section names; must be less than $2^{24}$ */
+@d max_names 4000 /* number of identifiers, strings, section names;
+ must be less than 10240 */
+
+@<Definitions that...@>=
+typedef struct name_info {
+ char *byte_start; /* beginning of the name in |byte_mem| */
+ @<More elements of |name_info| structure@>@;
+} name_info; /* contains information about an identifier or section name */
+typedef name_info *name_pointer; /* pointer into array of |name_info|s */
+char byte_mem[max_bytes]; /* characters of names */
+char *byte_mem_end = byte_mem+max_bytes-1; /* end of |byte_mem| */
+name_info name_dir[max_names]; /* information about names */
+name_pointer name_dir_end = name_dir+max_names-1; /* end of |name_dir| */
+
+@ The actual sequence of characters in the name pointed to by a |name_pointer
+p| appears in positions |p->byte_start| to |(p+1)->byte_start-1|, inclusive.
+The |print_id| macro prints this text on the user's terminal.
+
+@d length(c) (c+1)->byte_start-(c)->byte_start /* the length of a name */
+@d print_id(c) term_write((c)->byte_start,length((c))) /* print identifier */
+
+@ The first unused position in |byte_mem| and |name_dir| is
+kept in |byte_ptr| and |name_ptr|, respectively. Thus we
+usually have |name_ptr->byte_start==byte_ptr|, and certainly
+we want to keep |name_ptr<=name_dir_end| and |byte_ptr<=byte_mem_end|.
+
+@<Defini...@>=
+name_pointer name_ptr; /* first unused position in |byte_start| */
+char *byte_ptr; /* first unused position in |byte_mem| */
+
+@ @<Init...@>=
+name_dir->byte_start=byte_ptr=byte_mem; /* position zero in both arrays */
+name_ptr=name_dir+1; /* |name_dir[0]| will be used only for error recovery */
+name_ptr->byte_start=byte_mem; /* this makes name 0 of length zero */
+
+@ The names of identifiers are found by computing a hash address |h| and
+then looking at strings of bytes signified by the |name_pointer|s
+|hash[h]|, |hash[h]->link|, |hash[h]->link->link|, \dots,
+until either finding the desired name or encountering the null pointer.
+
+@<More elements of |name...@>=
+struct name_info *link;
+
+@ The hash table itself
+consists of |hash_size| entries of type |name_pointer|, and is
+updated by the |id_lookup| procedure, which finds a given identifier
+and returns the appropriate |name_pointer|. The matching is done by the
+function |names_match|, which is slightly different in
+\.{CWEAVE} and \.{CTANGLE}. If there is no match for the identifier,
+it is inserted into the table.
+
+@d hash_size 353 /* should be prime */
+
+@<Defini...@>=
+typedef name_pointer *hash_pointer;
+name_pointer hash[hash_size]; /* heads of hash lists */
+hash_pointer hash_end = hash+hash_size-1; /* end of |hash| */
+hash_pointer h; /* index into hash-head array */
+
+@ @<Predec...@>=
+extern int names_match();
+
+@ Initially all the hash lists are empty.
+
+@<Init...@>=
+for (h=hash; h<=hash_end; *h++=NULL) ;
+
+@ Here is the main procedure for finding identifiers:
+
+@c
+name_pointer
+id_lookup(first,last,t) /* looks up a string in the identifier table */
+char *first; /* first character of string */
+char *last; /* last character of string plus one */
+char t; /* the |ilk|; used by \.{CWEAVE} only */
+{
+ char *i=first; /* position in |buffer| */
+ int h; /* hash code */
+ int l; /* length of the given identifier */
+ name_pointer p; /* where the identifier is being sought */
+ if (last==NULL) for (last=first; *last!='\0'; last++);
+ l=last-first; /* compute the length */
+ @<Compute the hash code |h|@>;
+ @<Compute the name location |p|@>;
+ if (p==name_ptr) @<Enter a new name into the table at position |p|@>;
+ return(p);
+}
+
+@ A simple hash code is used: If the sequence of
+character codes is $c_1c_2\ldots c_n$, its hash value will be
+$$(2^{n-1}c_1+2^{n-2}c_2+\cdots+c_n)\,\bmod\,|hash_size|.$$
+
+@<Compute the hash...@>=
+h=(unsigned char)*i;
+while (++i<last) h=(h+h+(int)((unsigned char)*i)) % hash_size;
+@^high-bit character handling@>
+
+@ If the identifier is new, it will be placed in position |p=name_ptr|,
+otherwise |p| will point to its existing location.
+
+@<Compute the name location...@>=
+p=hash[h];
+while (p && !names_match(p,first,l,t)) p=p->link;
+if (p==NULL) {
+ p=name_ptr; /* the current identifier is new */
+ p->link=hash[h]; hash[h]=p; /* insert |p| at beginning of hash list */
+}
+
+@ The information associated with a new identifier must be initialized
+in a slightly different way in \.{CWEAVE} than in \.{CTANGLE}; hence the
+|init_p| procedure.
+
+@<Pred...@>=
+void init_p();
+
+@ @<Enter a new name...@>= {
+ if (byte_ptr+l>byte_mem_end) overflow("byte memory");
+ if (name_ptr>=name_dir_end) overflow("name");
+ strncpy(byte_ptr,first,l);
+ (++name_ptr)->byte_start=byte_ptr+=l;
+ if (program==cweave) init_p(p,t);
+}
+
+@ The names of sections are stored in |byte_mem| together
+with the identifier names, but a hash table is not used for them because
+\.{CTANGLE} needs to be able to recognize a section name when given a prefix of
+that name. A conventional binary search tree is used to retrieve section names,
+with fields called |llink| and |rlink| (where |llink| takes the place
+of |link|). The root of this tree is stored in |name_dir->rlink|;
+this will be the only information in |name_dir[0]|.
+
+Since the space used by |rlink| has a different function for
+identifiers than for section names, we declare it as a |union|.
+
+@d llink link /* left link in binary search tree for section names */
+@d rlink dummy.Rlink /* right link in binary search tree for section names */
+@d root name_dir->rlink /* the root of the binary search tree
+ for section names */
+
+@<More elements of |name...@>=
+union {
+ struct name_info *Rlink; /* right link in binary search tree for section
+ names */
+ char Ilk; /* used by identifiers in \.{CWEAVE} only */
+} dummy;
+
+@ @<Init...@>=
+root=NULL; /* the binary search tree starts out with nothing in it */
+
+@ If |p| is a |name_pointer| variable, as we have seen,
+|p->byte_start| is the beginning of the area where the name
+corresponding to |p| is stored. However, if |p| refers to a section
+name, the name may need to be stored in chunks, because it may
+``grow'': a prefix of the section name may be encountered before
+the full name. Furthermore we need to know the length of the shortest
+prefix of the name that was ever encountered.
+
+We solve this problem by inserting two extra bytes at |p->byte_start|,
+representing the length of the shortest prefix, when |p| is a
+section name. Furthermore, the last byte of the name will be a blank
+space if |p| is a prefix. In the latter case, the name pointer
+|p+1| will allow us to access additional chunks of the name:
+The second chunk will begin at the name pointer |(p+1)->link|,
+and if it too is a prefix (ending with blank) its |link| will point
+to additional chunks in the same way. Null links are represented by
+|name_dir|.
+
+@d first_chunk(p) ((p)->byte_start+2)
+@d prefix_length(p) (int)((unsigned char)*((p)->byte_start)*256 +
+ (unsigned char)*((p)->byte_start+1))
+@d set_prefix_length(p,m) (*((p)->byte_start)=(m)/256,
+ *((p)->byte_start+1)=(m)%256)
+
+@c
+void
+print_section_name(p)
+name_pointer p;
+{
+ char *ss, *s = first_chunk(p);
+ name_pointer q = p+1;
+ while (p!=name_dir) {
+ ss = (p+1)->byte_start-1;
+ if (*ss==' ' && ss>=s) {
+ term_write(s,ss-s); p=q->link; q=p;
+ } else {
+ term_write(s,ss+1-s); p=name_dir; q=NULL;
+ }
+ s = p->byte_start;
+ }
+ if (q) term_write("...",3); /* complete name not yet known */
+}
+
+@ @c
+void
+sprint_section_name(dest,p)
+ char*dest;
+ name_pointer p;
+{
+ char *ss, *s = first_chunk(p);
+ name_pointer q = p+1;
+ while (p!=name_dir) {
+ ss = (p+1)->byte_start-1;
+ if (*ss==' ' && ss>=s) {
+ p=q->link; q=p;
+ } else {
+ ss++; p=name_dir;
+ }
+ strncpy(dest,s,ss-s), dest+=ss-s;
+ s = p->byte_start;
+ }
+ *dest='\0';
+}
+
+@ @c
+void
+print_prefix_name(p)
+name_pointer p;
+{
+ char *s = first_chunk(p);
+ int l = prefix_length(p);
+ term_write(s,l);
+ if (s+l<(p+1)->byte_start) term_write("...",3);
+}
+
+@ When we compare two section names, we'll need a function analogous to
+|strcmp|. But we do not assume the strings
+are null-terminated, and we keep an eye open for prefixes and extensions.
+
+@d less 0 /* the first name is lexicographically less than the second */
+@d equal 1 /* the first name is equal to the second */
+@d greater 2 /* the first name is lexicographically greater than the second */
+@d prefix 3 /* the first name is a proper prefix of the second */
+@d extension 4 /* the first name is a proper extension of the second */
+
+@c
+int web_strcmp(j,j_len,k,k_len) /* fuller comparison than |strcmp| */
+ char *j, *k; /* beginning of first and second strings */
+ int j_len, k_len; /* length of strings */
+{
+ char *j1=j+j_len, *k1=k+k_len;
+ while (k<k1 && j<j1 && *j==*k) k++, j++;
+ if (k==k1) if (j==j1) return equal;
+ else return extension;
+ else if (j==j1) return prefix;
+ else if (*j<*k) return less;
+ else return greater;
+}
+
+@ Adding a section name to the tree is straightforward if we know its
+parent and whether it's the |rlink| or |llink| of the parent. As a
+special case, when the name is the first section being added, we set the
+``parent'' to |NULL|. When a section name is created, it has only one
+chunk, which however may be just a prefix: the full name will
+hopefully be unveiled later. Obviously, |prefix_length| starts
+out as the length of the first chunk, though it may decrease later.
+
+The information associated with a new node must be initialized
+differently in \.{CWEAVE} and \.{CTANGLE}; hence the
+|init_node| procedure, which is defined differently in \.{cweave.w}
+and \.{ctangle.w}.
+
+@<Prede...@>=
+extern void init_node();
+
+@ @c
+name_pointer
+add_section_name(par,c,first,last,ispref) /* install a new node in the tree */
+name_pointer par; /* parent of new node */
+int c; /* right or left? */
+char *first; /* first character of section name */
+char *last; /* last character of section name, plus one */
+int ispref; /* are we adding a prefix or a full name? */
+{
+ name_pointer p=name_ptr; /* new node */
+ char *s=first_chunk(p);
+ int name_len=last-first+ispref; /* length of section name */
+ if (s+name_len>byte_mem_end) overflow("byte memory");
+ if (name_ptr+1>=name_dir_end) overflow("name");
+ (++name_ptr)->byte_start=byte_ptr=s+name_len;
+ if (ispref) {
+ *(byte_ptr-1)=' ';
+ name_len--;
+ name_ptr->link=name_dir;
+ (++name_ptr)->byte_start=byte_ptr;
+ }
+ set_prefix_length(p,name_len);
+ strncpy(s,first,name_len);
+ p->llink=NULL;
+ p->rlink=NULL;
+ init_node(p);
+ return par==NULL ? (root=p) : c==less ? (par->llink=p) : (par->rlink=p);
+}
+
+@ @c
+void
+extend_section_name(p,first,last,ispref)
+name_pointer p; /* name to be extended */
+char *first; /* beginning of extension text */
+char *last; /* one beyond end of extension text */
+int ispref; /* are we adding a prefix or a full name? */
+{
+ char *s;
+ name_pointer q=p+1;
+ int name_len=last-first+ispref;
+ if (name_ptr>=name_dir_end) overflow("name");
+ while (q->link!=name_dir) q=q->link;
+ q->link=name_ptr;
+ s=name_ptr->byte_start;
+ name_ptr->link=name_dir;
+ if (s+name_len>byte_mem_end) overflow("byte memory");
+ (++name_ptr)->byte_start=byte_ptr=s+name_len;
+ strncpy(s,first,name_len);
+ if (ispref) *(byte_ptr-1)=' ';
+}
+
+@ The |section_lookup| procedure is supposed to find a
+section name that matches a new name, installing the new name if
+it doesn't match an existing one. The new name is the string
+between |first| and |last|; a ``match'' means that the new name
+exactly equals or is a prefix or extension of a name in the tree.
+
+@c
+name_pointer
+section_lookup(first,last,ispref) /* find or install section name in tree */
+char *first, *last; /* first and last characters of new name */
+int ispref; /* is the new name a prefix or a full name? */
+{
+ int c=0; /* comparison between two names; initialized so some compilers won't complain */
+ name_pointer p=root; /* current node of the search tree */
+ name_pointer q=NULL; /* another place to look in the tree */
+ name_pointer r=NULL; /* where a match has been found */
+ name_pointer par=NULL; /* parent of |p|, if |r| is |NULL|;
+ otherwise parent of |r| */
+ int name_len=last-first+1;
+ @<Look for matches for new name among shortest prefixes, complaining
+ if more than one is found@>;
+ @<If no match found, add new name to tree@>;
+ @<If one match found, check for compatibility and return match@>;
+}
+
+@ A legal new name matches an existing section name if and only if it
+matches the shortest prefix of that section name. Therefore we can
+limit our search for matches to shortest prefixes, which eliminates
+the need for chunk-chasing at this stage.
+
+@<Look for matches for new name among...@>=
+while (p) { /* compare shortest prefix of |p| with new name */
+ c=web_strcmp(first,name_len,first_chunk(p),prefix_length(p));
+ if (c==less || c==greater) { /* new name does not match |p| */
+ if (r==NULL) /* no previous matches have been found */
+ par=p;
+ p=(c==less?p->llink:p->rlink);
+ } else { /* new name matches |p| */
+ if (r!=NULL) { /* and also |r|: illegal */
+ printf("\n! Ambiguous prefix: matches <");
+@.Ambiguous prefix ... @>
+ print_prefix_name(p);
+ printf(">\n and <");
+ print_prefix_name(r);
+ err_print(">");
+ return name_dir; /* the unsection */
+ }
+ r=p; /* remember match */
+ p=p->llink; /* try another */
+ q=r->rlink; /* we'll get back here if the new |p| doesn't match */
+ }
+ if (p==NULL)
+ p=q, q=NULL; /* |q| held the other branch of |r| */
+}
+
+@ @<If no match ...@>=
+ if (r==NULL) /* no matches were found */
+ return add_section_name(par,c,first,last+1,ispref);
+
+@ Although error messages are given in anomalous cases, we do return the
+unique best match when a discrepancy is found, because users often
+change a title in one place while forgetting to change it elsewhere.
+
+@<If one match found, check for compatibility and return match@>=
+switch(section_name_cmp(&first,name_len,r)) {
+ /* compare all of |r| with new name */
+ case prefix:
+ if (!ispref) {
+ printf("\n! New name is a prefix of <");
+@.New name is a prefix...@>
+ print_section_name(r);
+ err_print(">");
+ }
+ else if (name_len<prefix_length(r)) set_prefix_length(r,name_len);
+ /* fall through */
+ case equal: return r;
+ case extension: if (!ispref || first<=last)
+ extend_section_name(r,first,last+1,ispref);
+ return r;
+ case bad_extension:
+ printf("\n! New name extends <");
+@.New name extends...@>
+ print_section_name(r);
+ err_print(">");
+ return r;
+ default: /* no match: illegal */
+ printf("\n! Section name incompatible with <");
+@.Section name incompatible...@>
+ print_prefix_name(r);
+ printf(">,\n which abbreviates <");
+ print_section_name(r);
+ err_print(">");
+ return r;
+}
+
+@ The return codes of |section_name_cmp|, which compares a string with
+the full name of a section, are those of |web_strcmp| plus
+|bad_extension|, used when the string is an extension of a
+supposedly already complete section name. This function has a side
+effect when the comparison string is an extension: it advances the
+address of the first character of the string by an amount equal to
+the length of the known part of the section name.
+
+The name \.{@@<foo...@@>} should be an acceptable ``abbreviation''
+for \.{@@<foo@@>}. If such an abbreviation comes after the complete
+name, there's no trouble recognizing it. If it comes before the
+complete name, we simply append a null chunk. This logic requires
+us to regard \.{@@<foo...@@>} as an ``extension'' of itself.
+
+@d bad_extension 5
+
+@<Predec...@>=
+int section_name_cmp();
+
+@ @c
+int section_name_cmp(pfirst,len,r)
+char **pfirst; /* pointer to beginning of comparison string */
+int len; /* length of string */
+name_pointer r; /* section name being compared */
+{
+ char *first=*pfirst; /* beginning of comparison string */
+ name_pointer q=r+1; /* access to subsequent chunks */
+ char *ss, *s=first_chunk(r);
+ int c; /* comparison */
+ int ispref; /* is chunk |r| a prefix? */
+ while (1) {
+ ss=(r+1)->byte_start-1;
+ if (*ss==' ' && ss>=r->byte_start) ispref=1,q=q->link;
+ else ispref=0,ss++,q=name_dir;
+ switch(c=web_strcmp(first,len,s,ss-s)) {
+ case equal: if (q==name_dir)
+ if (ispref) {
+ *pfirst=first+(ss-s);
+ return extension; /* null extension */
+ } else return equal;
+ else return (q->byte_start==(q+1)->byte_start)? equal: prefix;
+ case extension:
+ if (!ispref) return bad_extension;
+ first += ss-s;
+ if (q!=name_dir) {len -= ss-s; s=q->byte_start; r=q; continue;}
+ *pfirst=first; return extension;
+ default: return c;
+ }
+ }
+}
+
+@ The last component of |name_info| is different for \.{CTANGLE} and
+\.{CWEAVE}. In \.{CTANGLE}, if |p| is a pointer to a section name,
+|p->equiv| is a pointer to its replacement text, an element of the
+array |text_info|. In \.{CWEAVE}, on the other hand, if
+|p| points to an identifier, |p->xref| is a pointer to its
+list of cross-references, an element of the array |xmem|. The make-up
+of |text_info| and |xmem| is discussed in the \.{CTANGLE} and \.{CWEAVE}
+source files, respectively; here we just declare a common field
+|equiv_or_xref| as a pointer to a |char|.
+
+@<More elements of |name...@>=
+char *equiv_or_xref; /* info corresponding to names */
+
+@** 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.
+
+@d spotless 0 /* |history| value for normal jobs */
+@d harmless_message 1 /* |history| value when non-serious info was printed */
+@d error_message 2 /* |history| value when an error was noted */
+@d fatal_message 3 /* |history| value when we had to stop prematurely */
+@d mark_harmless {if (history==spotless) history=harmless_message;}
+@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 |"!"|.
+
+@<Predecl...@>=
+void err_print();
+
+@ @c
+void
+err_print(s) /* prints `\..' and location of error message */
+char *s;
+{
+ char *k,*l; /* pointers into |buffer| */
+ printf(*s=='!'? "\n%s" : "%s",s);
+ if(web_file_open) @<Print error location based on input buffer@>;
+ 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)
+ printf(". (l. %d of change file)\n", change_line);
+else if (include_depth==0) printf(". (l. %d)\n", cur_line);
+ else printf(". (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') putchar(' ');
+ else putchar(*k); /* print the characters already read */
+ putchar('\n');
+ for (k=buffer; k<l; k++) putchar(' '); /* space out the next line */
+}
+for (k=l; k<limit; k++) putchar(*k); /* print the part not yet read */
+if (*limit=='|') putchar('|'); /* end of \CEE/ text in section names */
+putchar(' '); /* to separate the message from future asterisks */
+}
+
+@ 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.
+
+\.{CTANGLE} and \.{CWEAVE} have their own notions about how to
+print the job statistics.
+
+@<Prede...@>=
+int wrap_up();
+extern void print_stats();
+
+@ 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@>
+
+@c
+int wrap_up() {
+ putchar('\n');
+ if (show_stats)
+ print_stats(); /* print statistics about memory usage */
+ @<Print the job |history|@>;
+ if (history > harmless_message) return(1);
+ else return(0);
+}
+
+@ @<Print the job |history|@>=
+switch (history) {
+case spotless: if (show_happiness) printf("(No errors were found.)\n"); break;
+case harmless_message:
+ printf("(Did you see the warning message above?)\n"); break;
+case error_message:
+ printf("(Pardon me, but I think I spotted something wrong.)\n"); break;
+case fatal_message: printf("(That was a fatal error, my friend.)\n");
+} /* there are no other cases */
+
+@ When there is no way to recover from an error, the |fatal| subroutine is
+invoked. This happens most often when |overflow| occurs.
+
+@<Predec...@>=
+void fatal(), overflow();
+
+@ The two parameters to |fatal| are strings that are essentially
+concatenated to print the final error message.
+
+@c void
+fatal(s,t)
+ char *s,*t;
+{
+ if (*s) printf(s);
+ err_print(t);
+ history=fatal_message; exit(wrap_up());
+}
+
+@ An overflow stop occurs if \.{CWEB}'s tables aren't large enough.
+
+@c void
+overflow(t)
+ char *t;
+{
+ printf("\n! Sorry, %s capacity exceeded",t); fatal("","");
+}
+@.Sorry, capacity exceeded@>
+
+@ Sometimes the program's behavior is far different from what it should be,
+and \.{CWEB} prints an error message that is really for the \.{CWEB}
+maintenance person, not the user. In such cases the program says
+|confusion("indication of where we are")|.
+
+@d confusion(s) fatal("! This can't happen: ",s)
+@.This can't happen@>
+
+@** Command line arguments.
+The user calls \.{CWEAVE} and \.{CTANGLE} 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.
+
+@d show_banner flags['b'] /* should the banner line be printed? */
+@d show_progress flags['p'] /* should progress reports be printed? */
+@d show_stats flags['s'] /* should statistics be printed at end of run? */
+@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 C_file_name[max_file_name_length]; /* name of |C_file| */
+char tex_file_name[max_file_name_length]; /* name of |tex_file| */
+char idx_file_name[max_file_name_length]; /* name of |idx_file| */
+char scn_file_name[max_file_name_length]; /* name of |scn_file| */
+boolean flags[128]; /* an option for each 7-bit code */
+
+@ The |flags| will be initially zero. Some of them are set to~1 before
+scanning the arguments; if additional flags are 1 by default they
+should be set before calling |common_init|.
+
+@<Set the default options common to \.{CTANGLE} and \.{CWEAVE}@>=
+show_banner=show_happiness=show_progress=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 \.{CWEB}
+file. It may have an extension, or it may omit the extension to get |".w"| or
+|".web"| added. The \TEX/ output file name is formed by replacing the \.{CWEB}
+file name extension by |".tex"|, and the \CEE/ file name by replacing
+the extension by |".c"|, after removing the directory name (if any).
+
+If there is a second 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();
+
+@ @c
+void
+scan_args()
+{
+ char *dot_pos; /* position of |'.'| in the argument */
+ char *name_pos; /* file name beginning, sans directory */
+ 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=='+')&&*(*argv+1)) @<Handle flag argument@>@;
+ else {
+ s=name_pos=*argv;@+dot_pos=NULL;
+ while (*s) {
+ if (*s=='.') dot_pos=s++;
+ else if (*s=='/') dot_pos=NULL,name_pos=++s;
+ else s++;
+ }
+ if (!found_web) @<Make
+ |web_file_name|, |tex_file_name| and |C_file_name|@>@;
+ else if (!found_change) @<Make |change_file_name| from |fname|@>@;
+ else if (!found_out) @<Override |tex_file_name| and |C_file_name|@>@;
+ else @<Print usage error message and quit@>;
+ }
+ }
+ if (!found_web) @<Print usage error message and quit@>;
+ if (found_change<=0) 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);
+ sprintf(tex_file_name,"%s.tex",name_pos); /* strip off directory name */
+ sprintf(idx_file_name,"%s.idx",name_pos);
+ sprintf(scn_file_name,"%s.scn",name_pos);
+ sprintf(C_file_name,"%s.c",name_pos);
+ found_web=1;
+}
+
+@ @<Make |change_file_name|...@>=
+{
+ if (strcmp(*argv,"-")==0) found_change=-1;
+ else {
+ 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(tex_file_name,"%s.tex",*argv);
+ sprintf(idx_file_name,"%s.idx",*argv);
+ sprintf(scn_file_name,"%s.scn",*argv);
+ sprintf(C_file_name,"%s.c",*argv);
+ } else {
+ strcpy(tex_file_name,*argv);
+ if (flags['x']) { /* indexes will be generated */
+ if (program==cweave && strcmp(*argv+strlen(*argv)-4,".tex")!=0)
+ fatal("! Output file name should end with .tex\n",*argv);
+@.Output file name...tex@>
+ strcpy(idx_file_name,*argv);
+ strcpy(idx_file_name+strlen(*argv)-4,".idx");
+ strcpy(scn_file_name,*argv);
+ strcpy(scn_file_name+strlen(*argv)-4,".scn");
+ }
+ strcpy(C_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@>=
+{
+if (program==ctangle)
+ fatal(
+"! Usage: ctangle [options] webfile[.w] [{changefile[.ch]|-} [outfile[.c]]]\n"
+ ,"");
+@.Usage:@>
+else fatal(
+"! Usage: cweave [options] webfile[.w] [{changefile[.ch]|-} [outfile[.tex]]]\n"
+ ,"");
+}
+
+@ @<Complain about arg...@>= fatal("! Filename too long\n", *argv);
+@.Filename too long@>
+
+@** Output. Here is the code that opens the output file:
+@^system dependencies@>
+
+@<Defin...@>=
+FILE *C_file; /* where output of \.{CTANGLE} goes */
+FILE *tex_file; /* where output of \.{CWEAVE} goes */
+FILE *idx_file; /* where index from \.{CWEAVE} goes */
+FILE *scn_file; /* where list of sections from \.{CWEAVE} goes */
+FILE *active_file; /* currently active file for \.{CWEAVE} output */
+
+@ @<Scan arguments and open output files@>=
+scan_args();
+if (program==ctangle) {
+ if ((C_file=fopen(C_file_name,"w"))==NULL)
+ fatal("! Cannot open output file ", C_file_name);
+@.Cannot open output file@>
+}
+else {
+ if ((tex_file=fopen(tex_file_name,"w"))==NULL)
+ fatal("! Cannot open output file ", tex_file_name);
+}
+
+@ 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@>
+
+@d update_terminal fflush(stdout) /* empty the terminal output buffer */
+
+@ Terminal output uses |putchar| and |putc| when we have to
+translate from \.{CWEB}'s code into the external character code,
+and |printf| when we just want to print strings.
+Several macros make other kinds of output convenient.
+@^system dependencies@>
+@d new_line putchar('\n') @d putxchar putchar
+@d term_write(a,b) fflush(stdout),fwrite(a,sizeof(char),b,stdout)
+@d C_printf(c,a) fprintf(C_file,c,a)
+@d C_putc(c) putc(c,C_file) /* isn't \CEE/ wonderfully consistent? */
+
+@ We predeclare several standard system 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. (For example, some \CEE/ environments
+have \.{<string.h>} where others have \.{<strings.h>}.)
+
+@<Predecl...@>=
+extern int strlen(); /* length of string */
+extern int strcmp(); /* compare strings lexicographically */
+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 */
+
+@** Index.
diff --git a/web/c_cpp/c2cweb/cweb/cweave.c b/web/c_cpp/c2cweb/cweb/cweave.c
new file mode 100644
index 0000000000..bff742feb7
--- /dev/null
+++ b/web/c_cpp/c2cweb/cweb/cweave.c
@@ -0,0 +1,4543 @@
+/*1:*/
+#line 66 "cweave.w"
+/*6:*/
+#line 38 "common.h"
+
+#include <stdio.h>
+
+/*:6*//*38:*/
+#line 644 "cweave.w"
+
+#include <ctype.h>
+#include <stdlib.h>
+
+/*:38*/
+#line 66 "cweave.w"
+
+#define banner "This is CWEAVE (Version 3.4) modified by Werner Lemberg (V1.5)\n" \
+
+#define max_bytes 225000 \
+
+#define max_names 10000 \
+
+#define max_sections 2000
+#define hash_size 353
+#define buf_size 400
+#define longest_name 1000
+#define long_buf_size (buf_size+longest_name)
+#define line_length 100 \
+
+#define max_refs 20000
+#define max_toks 65000 \
+
+#define max_texts 10200 \
+
+#define max_scraps 65000
+#define stack_size 10000 \
+
+#define ctangle 0
+#define cweave 1 \
+
+#define and_and 04
+#define lt_lt 020
+#define gt_gt 021
+#define plus_plus 013
+#define minus_minus 01
+#define minus_gt 031
+#define not_eq 032
+#define lt_eq 034
+#define gt_eq 035
+#define eq_eq 036
+#define or_or 037
+#define dot_dot_dot 016
+#define colon_colon 06
+#define period_ast 026
+#define minus_gt_ast 027 \
+
+#define xisalpha(c) (isalpha(c) &&((eight_bits) c<0200) )
+#define xisdigit(c) (isdigit(c) &&((eight_bits) c<0200) )
+#define xisspace(c) (isspace(c) &&((eight_bits) c<0200) )
+#define xislower(c) (islower(c) &&((eight_bits) c<0200) )
+#define xisupper(c) (isupper(c) &&((eight_bits) c<0200) )
+#define xisxdigit(c) (isxdigit(c) &&((eight_bits) c<0200) ) \
+
+#define length(c) (c+1) ->byte_start-(c) ->byte_start
+#define print_id(c) term_write((c) ->byte_start,length((c) ) )
+#define llink link
+#define rlink dummy.Rlink
+#define root name_dir->rlink \
+
+#define chunk_marker 0 \
+
+#define spotless 0
+#define harmless_message 1
+#define error_message 2
+#define fatal_message 3
+#define mark_harmless {if(history==spotless) history= harmless_message;}
+#define mark_error history= error_message
+#define confusion(s) fatal("! This can't happen: ",s) \
+
+#define max_file_name_length 60
+#define cur_file file[include_depth]
+#define cur_file_name file_name[include_depth]
+#define web_file_name file_name[0]
+#define cur_line line[include_depth] \
+
+#define show_banner flags['b']
+#define show_progress flags['p']
+#define show_happiness flags['h'] \
+
+#define update_terminal fflush(stdout)
+#define new_line putchar('\n')
+#define putxchar putchar
+#define term_write(a,b) fflush(stdout) ,fwrite(a,sizeof(char) ,b,stdout)
+#define C_printf(c,a) fprintf(C_file,c,a)
+#define C_putc(c) putc(c,C_file) \
+
+#define ilk dummy.dummy1.Ilk
+#define func_flag dummy.dummy1.Func_flag
+#define normal 0
+#define roman 1
+#define wildcard 2
+#define typewriter 3
+#define abnormal(a) (a->ilk>typewriter)
+#define custom 4
+#define unindexed(a) (a->ilk>custom)
+#define quoted 5
+#define else_like 26
+#define public_like 40
+#define operator_like 41
+#define new_like 42
+#define catch_like 43
+#define for_like 45
+#define do_like 46
+#define if_like 47
+#define raw_rpar 48
+#define raw_unorbin 49
+#define const_like 50
+#define raw_int 51
+#define int_like 52
+#define case_like 53
+#define sizeof_like 54
+#define struct_like 55
+#define typedef_like 56
+#define define_like 57 \
+
+#define file_flag (3*cite_flag)
+#define def_flag (2*cite_flag)
+#define cite_flag 10240
+#define xref equiv_or_xref \
+
+#define append_xref(c) if(xref_ptr==xmem_end) overflow("cross-reference") ; \
+else(++xref_ptr) ->num= c;
+#define no_xref (flags['x']==0)
+#define make_xrefs flags['x']
+#define is_tiny(p) ((p+1) ->byte_start==(p) ->byte_start+1) \
+
+#define ignore 00
+#define verbatim 02
+#define begin_short_comment 03
+#define begin_comment '\t'
+#define underline '\n'
+#define noop 0177
+#define xref_roman 0203
+#define xref_wildcard 0204
+#define xref_typewriter 0205
+#define TeX_string 0206
+#define ord 0207
+#define join 0210
+#define thin_space 0211
+#define math_break 0212
+#define line_break 0213
+#define big_line_break 0214
+#define no_line_break 0215
+#define pseudo_semi 0216
+#define macro_arg_open 0220
+#define macro_arg_close 0221
+#define trace 0222
+#define translit_code 0223
+#define output_defs_code 0224
+#define format_code 0225
+#define definition 0226
+#define begin_C 0227
+#define section_name 0230
+#define new_section 0231
+#define pseudo_lbrace 022
+#define pseudo_rbrace 023 \
+
+#define constant 0200
+#define string 0201
+#define identifier 0202 \
+
+#define isxalpha(c) ((c) =='_'||(c) =='$') \
+
+#define ishigh(c) ((eight_bits) (c) >0177) \
+ \
+
+#define left_preproc ord
+#define right_preproc 0217
+#define preproc_space '\b'
+#define numb_numb '\f' \
+
+#define compress(c) if(loc++<=limit) return(c) \
+
+#define c_line_write(c) fflush(active_file) ,fwrite(out_buf+1,sizeof(char) ,c,active_file)
+#define tex_putc(c) putc(c,active_file)
+#define tex_new_line putc('\n',active_file)
+#define tex_printf(c) fprintf(active_file,c) \
+
+#define app_tok(c) {if(tok_ptr+2>tok_mem_end) overflow("token") ;*(tok_ptr++) = c;} \
+
+#define exp 1
+#define unop 2
+#define binop 3
+#define unorbinop 4 \
+
+#define cast 5
+#define question 6
+#define lbrace 7
+#define rbrace 8
+#define decl_head 9
+#define comma 10
+#define lpar 11
+#define rpar 12
+#define prelangle 13
+#define prerangle 14
+#define langle 15
+#define colcol 18
+#define base 19
+#define decl 20
+#define struct_head 21
+#define stmt 23
+#define function 24
+#define fn_decl 25
+#define semi 27
+#define colon 28
+#define tag 29 \
+
+#define if_head 30
+#define else_head 31
+#define if_clause 32
+#define lproc 35
+#define rproc 36
+#define insert 37
+#define section_scrap 38
+#define dead 39
+#define begin_arg 58
+#define end_arg 59
+#define label 60
+#define do_head 61
+#define pp_space 62 \
+
+#define math_rel 0206
+#define big_cancel 0210
+#define cancel 0211
+#define indent 0212
+#define outdent 0213
+#define opt 0214
+#define backup 0215
+#define break_space 0216
+#define force 0217
+#define big_force 0220
+#define preproc_line 0221 \
+
+#define quoted_char 0222 \
+
+#define end_translation 0223
+#define inserted 0224 \
+
+#define trans trans_plus.Trans \
+
+#define id_flag 10240
+#define res_flag 2*id_flag
+#define section_flag 3*id_flag
+#define tok_flag 4*id_flag
+#define inner_tok_flag 5*id_flag \
+
+#define no_math 2
+#define yes_math 1
+#define maybe_math 0
+#define big_app2(a) big_app1(a) ;big_app1(a+1)
+#define big_app3(a) big_app2(a) ;big_app1(a+2)
+#define big_app4(a) big_app3(a) ;big_app1(a+3)
+#define app(a) *(tok_ptr++) = a
+#define app1(a) *(tok_ptr++) = tok_flag+(int) ((a) ->trans-tok_start) \
+
+#define cat1 (pp+1) ->cat
+#define cat2 (pp+2) ->cat
+#define cat3 (pp+3) ->cat
+#define lhs_not_simple (pp->cat!=semi&&pp->cat!=raw_int&&pp->cat!=raw_unorbin \
+&&pp->cat!=raw_rpar&&pp->cat!=const_like) \
+
+#define no_ident_found 0 \
+
+#define force_lines flags['f']
+#define freeze_text *(++text_ptr) = tok_ptr \
+
+#define safe_tok_incr 20
+#define safe_text_incr 10
+#define safe_scrap_incr 10 \
+
+#define app_scrap(c,b) { \
+(++scrap_ptr) ->cat= (c) ;scrap_ptr->trans= text_ptr; \
+scrap_ptr->mathness= 5*(b) ; \
+freeze_text; \
+} \
+
+#define alternative flags['a']
+#define func_index flags['i'] \
+ \
+
+#define inner 0
+#define outer 1 \
+
+#define cur_end cur_state.end_field
+#define cur_tok cur_state.tok_field
+#define cur_mode cur_state.mode_field
+#define init_stack stack_ptr= stack;cur_mode= outer \
+
+#define res_word 0201
+#define section_code 0200 \
+
+#define save_position save_line= out_line;save_place= out_ptr
+#define emit_space_if_needed if(save_line!=out_line||save_place!=out_ptr) \
+out_str("\\Y") ; \
+space_checked= 1 \
+ \
+
+#define depth cat
+#define head trans_plus.Head
+#define sort_pointer scrap_pointer
+#define sort_ptr scrap_ptr
+#define max_sorts max_scraps \
+
+#define infinity 255 \
+
+
+#line 67 "cweave.w"
+
+/*5:*/
+#line 32 "common.h"
+
+typedef short boolean;
+typedef char unsigned eight_bits;
+extern boolean program;
+extern int phase;
+
+/*:5*//*7:*/
+#line 60 "common.h"
+
+char section_text[longest_name+1];
+char*section_text_end= section_text+longest_name;
+char*id_first;
+char*id_loc;
+
+/*:7*//*8:*/
+#line 75 "common.h"
+
+extern char buffer[];
+extern char*buffer_end;
+extern char*loc;
+extern char*limit;
+
+/*:8*//*9:*/
+#line 90 "common.h"
+
+typedef struct name_info{
+char*byte_start;
+struct name_info*link;
+union{
+struct name_info*Rlink;
+
+struct{
+char Ilk;
+boolean Func_flag;
+}dummy1;
+}dummy;
+char*equiv_or_xref;
+}name_info;
+typedef name_info*name_pointer;
+typedef name_pointer*hash_pointer;
+extern char byte_mem[];
+extern char*byte_mem_end;
+extern name_info name_dir[];
+extern name_pointer name_dir_end;
+extern name_pointer name_ptr;
+extern char*byte_ptr;
+extern name_pointer hash[];
+extern hash_pointer hash_end;
+extern hash_pointer h;
+extern name_pointer id_lookup();
+extern name_pointer section_lookup();
+extern void print_section_name(),sprint_section_name();
+
+/*:9*//*10:*/
+#line 128 "common.h"
+
+extern history;
+extern err_print();
+extern wrap_up();
+extern void fatal();
+extern void overflow();
+
+/*:10*//*11:*/
+#line 143 "common.h"
+
+extern include_depth;
+extern FILE*file[];
+extern FILE*change_file;
+extern char C_file_name[];
+extern char tex_file_name[];
+extern char idx_file_name[];
+extern char scn_file_name[];
+extern char file_name[][max_file_name_length];
+
+extern char change_file_name[];
+extern line[];
+extern change_line;
+extern boolean input_has_ended;
+extern boolean changing;
+extern boolean web_file_open;
+extern reset_input();
+extern get_line();
+extern check_complete();
+
+/*:11*//*12:*/
+#line 164 "common.h"
+
+typedef unsigned short sixteen_bits;
+extern sixteen_bits section_count;
+extern boolean changed_section[];
+extern boolean change_pending;
+extern boolean print_where;
+
+/*:12*//*13:*/
+#line 176 "common.h"
+
+extern int argc;
+extern char**argv;
+extern boolean flags[];
+
+/*:13*//*14:*/
+#line 188 "common.h"
+
+extern FILE*C_file;
+extern FILE*tex_file;
+extern FILE*idx_file;
+extern FILE*scn_file;
+extern FILE*active_file;
+
+/*:14*//*15:*/
+#line 197 "common.h"
+
+extern void common_init();
+
+
+
+#line 140 "cweave.w"
+
+/*:15*/
+#line 68 "cweave.w"
+
+/*18:*/
+#line 222 "cweave.w"
+
+typedef struct xref_info{
+sixteen_bits num;
+struct xref_info*xlink;
+}xref_info;
+typedef xref_info*xref_pointer;
+
+/*:18*//*24:*/
+#line 332 "cweave.w"
+
+typedef sixteen_bits token;
+typedef token*token_pointer;
+typedef token_pointer*text_pointer;
+
+/*:24*//*103:*/
+#line 2012 "cweave.w"
+
+typedef struct{
+eight_bits cat;
+eight_bits mathness;
+union{
+text_pointer Trans;
+/*231:*/
+#line 4257 "cweave.w"
+
+name_pointer Head;
+
+/*:231*/
+#line 2018 "cweave.w"
+
+}trans_plus;
+}scrap;
+typedef scrap*scrap_pointer;
+
+/*:103*//*185:*/
+#line 3412 "cweave.w"
+typedef int mode;
+typedef struct{
+token_pointer end_field;
+token_pointer tok_field;
+boolean mode_field;
+}output_state;
+typedef output_state*stack_pointer;
+
+/*:185*/
+#line 69 "cweave.w"
+
+/*17:*/
+#line 197 "cweave.w"
+
+boolean change_exists;
+
+/*:17*//*19:*/
+#line 229 "cweave.w"
+
+xref_info xmem[max_refs];
+xref_pointer xmem_end= xmem+max_refs-1;
+xref_pointer xref_ptr;
+sixteen_bits xref_switch,section_xref_switch;
+
+/*:19*//*25:*/
+#line 342 "cweave.w"
+
+token tok_mem[max_toks];
+token_pointer tok_mem_end= tok_mem+max_toks-1;
+token_pointer tok_start[max_texts];
+token_pointer tok_ptr;
+text_pointer text_ptr;
+text_pointer tok_start_end= tok_start+max_texts-1;
+token_pointer max_tok_ptr;
+text_pointer max_text_ptr;
+
+/*:25*//*31:*/
+#line 521 "cweave.w"
+
+eight_bits ccode[256];
+
+/*:31*//*37:*/
+#line 640 "cweave.w"
+
+name_pointer cur_section;
+char cur_section_char;
+
+/*:37*//*41:*/
+#line 214 "cweave.ch"
+
+boolean preprocessing= 0;
+int define_pos= 0;
+
+#line 695 "cweave.w"
+
+/*:41*//*43:*/
+#line 706 "cweave.w"
+
+boolean sharp_include_line= 0;
+
+/*:43*//*58:*/
+#line 980 "cweave.w"
+
+eight_bits next_control;
+
+/*:58*//*68:*/
+#line 1136 "cweave.w"
+
+name_pointer lhs,rhs;
+
+/*:68*//*73:*/
+#line 1219 "cweave.w"
+
+xref_pointer cur_xref;
+boolean an_output;
+
+/*:73*//*77:*/
+#line 1261 "cweave.w"
+
+char out_buf[line_length+1];
+char*out_ptr;
+char*out_buf_end= out_buf+line_length;
+#line 268 "cweave.ch"
+int out_line;
+
+boolean in_math= 0;
+boolean escape= 0;
+int math_brace_count= 0;
+#line 1266 "cweave.w"
+
+/*:77*//*97:*/
+#line 1670 "cweave.w"
+
+char cat_name[256][12];
+eight_bits cat_index;
+
+/*:97*//*104:*/
+#line 2025 "cweave.w"
+
+scrap scrap_info[max_scraps];
+scrap_pointer scrap_info_end= scrap_info+max_scraps-1;
+scrap_pointer pp;
+scrap_pointer scrap_base;
+scrap_pointer scrap_ptr;
+scrap_pointer lo_ptr;
+scrap_pointer hi_ptr;
+scrap_pointer max_scr_ptr;
+
+/*:104*//*108:*/
+#line 2184 "cweave.w"
+
+int cur_mathness,init_mathness;
+
+/*:108*//*167:*/
+#line 2962 "cweave.w"
+
+int tracing;
+
+/*:167*//*186:*/
+#line 3425 "cweave.w"
+
+output_state cur_state;
+output_state stack[stack_size];
+stack_pointer stack_ptr;
+stack_pointer stack_end= stack+stack_size-1;
+stack_pointer max_stack_ptr;
+
+/*:186*//*190:*/
+#line 3475 "cweave.w"
+
+name_pointer cur_name;
+
+/*:190*//*206:*/
+#line 3831 "cweave.w"
+
+int save_line;
+char*save_place;
+int sec_depth;
+boolean space_checked;
+boolean format_visible;
+boolean doing_format= 0;
+boolean group_found= 0;
+
+/*:206*//*215:*/
+#line 4014 "cweave.w"
+
+name_pointer this_section;
+
+/*:215*//*226:*/
+#line 4198 "cweave.w"
+
+sixteen_bits k_section;
+
+/*:226*//*228:*/
+#line 4224 "cweave.w"
+
+name_pointer bucket[256];
+name_pointer next_name;
+name_pointer blink[max_names];
+
+/*:228*//*232:*/
+#line 4267 "cweave.w"
+
+eight_bits cur_depth;
+char*cur_byte;
+sixteen_bits cur_val;
+sort_pointer max_sort_ptr;
+
+/*:232*//*234:*/
+#line 4279 "cweave.w"
+
+eight_bits collate[102+128];
+
+
+/*:234*//*243:*/
+#line 4432 "cweave.w"
+
+xref_pointer next_xref,this_xref;
+
+
+/*:243*/
+#line 70 "cweave.w"
+
+/*2:*/
+#line 78 "cweave.w"
+
+extern int strlen();
+extern int strcmp();
+extern char*strcpy();
+extern int strncmp();
+extern char*strncpy();
+
+/*:2*//*34:*/
+#line 562 "cweave.w"
+
+void skip_limbo();
+
+/*:34*//*39:*/
+#line 655 "cweave.w"
+
+eight_bits get_next();
+
+/*:39*//*55:*/
+#line 933 "cweave.w"
+
+void skip_restricted();
+
+/*:55*//*59:*/
+#line 986 "cweave.w"
+
+void phase_one();
+
+/*:59*//*62:*/
+#line 1038 "cweave.w"
+
+void C_xref();
+
+/*:62*//*64:*/
+#line 1066 "cweave.w"
+
+void outer_xref();
+
+/*:64*//*74:*/
+#line 1227 "cweave.w"
+
+void section_check();
+
+/*:74*//*83:*/
+#line 1363 "cweave.w"
+
+void break_out();
+
+/*:83*//*91:*/
+#line 1506 "cweave.w"
+
+int copy_comment();
+
+/*:91*//*114:*/
+#line 2388 "cweave.w"
+
+void underline_xref();
+
+/*:114*//*180:*/
+#line 3289 "cweave.w"
+
+void app_cur_id();
+
+/*:180*//*193:*/
+#line 3544 "cweave.w"
+
+void make_output();
+
+/*:193*//*204:*/
+#line 3804 "cweave.w"
+
+void phase_two();
+
+/*:204*//*211:*/
+#line 3927 "cweave.w"
+
+void finish_C();
+
+/*:211*//*220:*/
+#line 4098 "cweave.w"
+
+void footnote();
+
+/*:220*//*224:*/
+#line 4147 "cweave.w"
+
+void phase_three();
+
+/*:224*//*236:*/
+#line 4327 "cweave.w"
+
+void unbucket();
+
+/*:236*//*245:*/
+#line 4447 "cweave.w"
+
+void section_print();
+
+/*:245*/
+#line 71 "cweave.w"
+
+
+/*:1*//*3:*/
+#line 93 "cweave.w"
+
+int main(ac,av)
+int ac;
+char**av;
+{
+argc= ac;argv= av;
+program= cweave;
+make_xrefs= force_lines= 1;
+common_init();
+/*20:*/
+#line 243 "cweave.w"
+
+xref_ptr= xmem;name_dir->xref= (char*)xmem;xref_switch= 0;section_xref_switch= 0;
+xmem->num= 0;
+
+/*:20*//*26:*/
+#line 352 "cweave.w"
+
+tok_ptr= tok_mem+1;text_ptr= tok_start+1;tok_start[0]= tok_mem+1;
+tok_start[1]= tok_mem+1;
+max_tok_ptr= tok_mem+1;max_text_ptr= tok_start+1;
+
+/*:26*//*32:*/
+#line 524 "cweave.w"
+
+{int c;for(c= 0;c<256;c++)ccode[c]= 0;}
+ccode[' ']= ccode['\t']= ccode['\n']= ccode['\v']= ccode['\r']= ccode['\f']
+= ccode['*']= new_section;
+ccode['@']= '@';
+ccode['=']= verbatim;
+ccode['d']= ccode['D']= definition;
+ccode['f']= ccode['F']= ccode['s']= ccode['S']= format_code;
+ccode['c']= ccode['C']= ccode['p']= ccode['P']= begin_C;
+ccode['t']= ccode['T']= TeX_string;
+ccode['l']= ccode['L']= translit_code;
+ccode['q']= ccode['Q']= noop;
+ccode['h']= ccode['H']= output_defs_code;
+ccode['&']= join;ccode['<']= ccode['(']= section_name;
+ccode['!']= underline;ccode['^']= xref_roman;
+ccode[':']= xref_wildcard;ccode['.']= xref_typewriter;ccode[',']= thin_space;
+ccode['|']= math_break;ccode['/']= line_break;ccode['#']= big_line_break;
+#line 117 "cweave.ch"
+ccode['+']= no_line_break;ccode[';']= pseudo_semi;
+ccode['{']= pseudo_lbrace;ccode['}']= pseudo_rbrace;
+ccode['[']= macro_arg_open;ccode[']']= macro_arg_close;
+#line 543 "cweave.w"
+ccode['\'']= ord;
+/*33:*/
+#line 550 "cweave.w"
+
+ccode['0']= ccode['1']= ccode['2']= trace;
+
+/*:33*/
+#line 544 "cweave.w"
+
+
+/*:32*//*52:*/
+#line 888 "cweave.w"
+section_text[0]= ' ';
+
+/*:52*//*80:*/
+#line 1330 "cweave.w"
+
+#line 281 "cweave.ch"
+out_ptr= out_buf+1;out_line= 1;active_file= tex_file;
+if(alternative){
+*out_ptr= 'a';
+tex_printf("\\input cwebmac");
+}else{
+*out_ptr= 'c';
+tex_printf("\\input cwebma");
+}
+#line 1333 "cweave.w"
+
+/*:80*//*82:*/
+#line 1356 "cweave.w"
+
+out_buf[0]= '\\';
+
+/*:82*//*98:*/
+#line 1674 "cweave.w"
+
+for(cat_index= 0;cat_index<255;cat_index++)
+strcpy(cat_name[cat_index],"UNKNOWN");
+strcpy(cat_name[exp],"exp");
+strcpy(cat_name[unop],"unop");
+strcpy(cat_name[binop],"binop");
+strcpy(cat_name[unorbinop],"unorbinop");
+strcpy(cat_name[cast],"cast");
+strcpy(cat_name[question],"?");
+strcpy(cat_name[lbrace],"{");
+strcpy(cat_name[rbrace],"}");
+strcpy(cat_name[decl_head],"decl_head");
+strcpy(cat_name[comma],",");
+strcpy(cat_name[lpar],"(");
+strcpy(cat_name[rpar],")");
+strcpy(cat_name[prelangle],"<");
+strcpy(cat_name[prerangle],">");
+strcpy(cat_name[langle],"\\<");
+strcpy(cat_name[colcol],"::");
+strcpy(cat_name[base],"\\:");
+strcpy(cat_name[decl],"decl");
+strcpy(cat_name[struct_head],"struct_head");
+strcpy(cat_name[stmt],"stmt");
+strcpy(cat_name[function],"function");
+strcpy(cat_name[fn_decl],"fn_decl");
+strcpy(cat_name[else_like],"else_like");
+strcpy(cat_name[semi],";");
+strcpy(cat_name[colon],":");
+strcpy(cat_name[tag],"tag");
+strcpy(cat_name[if_head],"if_head");
+strcpy(cat_name[else_head],"else_head");
+strcpy(cat_name[if_clause],"if()");
+strcpy(cat_name[lproc],"#{");
+strcpy(cat_name[rproc],"#}");
+strcpy(cat_name[insert],"insert");
+strcpy(cat_name[section_scrap],"section");
+strcpy(cat_name[dead],"@d");
+strcpy(cat_name[public_like],"public");
+strcpy(cat_name[operator_like],"operator");
+strcpy(cat_name[new_like],"new");
+strcpy(cat_name[catch_like],"catch");
+strcpy(cat_name[for_like],"for");
+strcpy(cat_name[do_like],"do");
+strcpy(cat_name[if_like],"if");
+strcpy(cat_name[raw_rpar],")?");
+strcpy(cat_name[raw_unorbin],"unorbinop?");
+strcpy(cat_name[const_like],"const");
+strcpy(cat_name[raw_int],"raw");
+strcpy(cat_name[int_like],"int");
+strcpy(cat_name[case_like],"case");
+strcpy(cat_name[sizeof_like],"sizeof");
+strcpy(cat_name[struct_like],"struct");
+strcpy(cat_name[typedef_like],"typedef");
+strcpy(cat_name[define_like],"define");
+strcpy(cat_name[begin_arg],"@[");
+#line 362 "cweave.ch"
+strcpy(cat_name[end_arg],"@]");
+strcpy(cat_name[label],"label");
+strcpy(cat_name[do_head],"do_head");
+strcpy(cat_name[pp_space],"#_");
+#line 1730 "cweave.w"
+strcpy(cat_name[0],"zero");
+
+/*:98*//*105:*/
+#line 2035 "cweave.w"
+
+scrap_base= scrap_info+1;
+max_scr_ptr= scrap_ptr= scrap_info;
+
+/*:105*//*187:*/
+#line 3432 "cweave.w"
+
+max_stack_ptr= stack;
+
+/*:187*//*233:*/
+#line 4273 "cweave.w"
+
+max_sort_ptr= scrap_info;
+
+/*:233*//*235:*/
+#line 4292 "cweave.w"
+
+collate[0]= 0;
+strcpy(collate+1," \1\2\3\4\5\6\7\10\11\12\13\14\15\16\17");
+
+strcpy(collate+17,"\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37");
+
+strcpy(collate+33,"!\42#$%&'()*+,-./:;<=>?@[\\]^`{|}~_");
+
+strcpy(collate+65,"abcdefghijklmnopqrstuvwxyz0123456789");
+
+strcpy(collate+101,"\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217");
+
+strcpy(collate+117,"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237");
+
+strcpy(collate+133,"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257");
+
+strcpy(collate+149,"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277");
+
+strcpy(collate+165,"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317");
+
+strcpy(collate+181,"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337");
+
+strcpy(collate+197,"\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357");
+
+strcpy(collate+213,"\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377");
+
+
+/*:235*/
+#line 102 "cweave.w"
+;
+if(show_banner)printf(banner);
+/*28:*/
+#line 392 "cweave.w"
+
+id_lookup("asm",NULL,sizeof_like);
+id_lookup("auto",NULL,int_like);
+id_lookup("break",NULL,case_like);
+id_lookup("case",NULL,case_like);
+id_lookup("catch",NULL,catch_like);
+id_lookup("char",NULL,raw_int);
+id_lookup("class",NULL,struct_like);
+id_lookup("clock_t",NULL,raw_int);
+id_lookup("const",NULL,const_like);
+id_lookup("continue",NULL,case_like);
+id_lookup("default",NULL,case_like);
+id_lookup("define",NULL,define_like);
+id_lookup("defined",NULL,sizeof_like);
+id_lookup("delete",NULL,sizeof_like);
+id_lookup("div_t",NULL,raw_int);
+id_lookup("do",NULL,do_like);
+id_lookup("double",NULL,raw_int);
+id_lookup("elif",NULL,if_like);
+id_lookup("else",NULL,else_like);
+id_lookup("endif",NULL,if_like);
+id_lookup("enum",NULL,struct_like);
+id_lookup("error",NULL,if_like);
+id_lookup("extern",NULL,int_like);
+id_lookup("FILE",NULL,raw_int);
+id_lookup("float",NULL,raw_int);
+id_lookup("for",NULL,for_like);
+id_lookup("fpos_t",NULL,raw_int);
+id_lookup("friend",NULL,int_like);
+id_lookup("goto",NULL,case_like);
+id_lookup("if",NULL,if_like);
+id_lookup("ifdef",NULL,if_like);
+id_lookup("ifndef",NULL,if_like);
+id_lookup("include",NULL,if_like);
+id_lookup("inline",NULL,int_like);
+id_lookup("int",NULL,raw_int);
+id_lookup("jmp_buf",NULL,raw_int);
+id_lookup("ldiv_t",NULL,raw_int);
+id_lookup("line",NULL,if_like);
+id_lookup("long",NULL,raw_int);
+id_lookup("new",NULL,new_like);
+id_lookup("NULL",NULL,quoted);
+id_lookup("offsetof",NULL,sizeof_like);
+id_lookup("operator",NULL,operator_like);
+id_lookup("pragma",NULL,if_like);
+id_lookup("private",NULL,public_like);
+id_lookup("protected",NULL,public_like);
+id_lookup("ptrdiff_t",NULL,raw_int);
+id_lookup("public",NULL,public_like);
+id_lookup("register",NULL,int_like);
+id_lookup("return",NULL,case_like);
+id_lookup("short",NULL,raw_int);
+id_lookup("sig_atomic_t",NULL,raw_int);
+id_lookup("signed",NULL,raw_int);
+id_lookup("size_t",NULL,raw_int);
+id_lookup("sizeof",NULL,sizeof_like);
+id_lookup("static",NULL,int_like);
+id_lookup("struct",NULL,struct_like);
+id_lookup("switch",NULL,for_like);
+id_lookup("template",NULL,int_like);
+id_lookup("TeX",NULL,custom);
+id_lookup("this",NULL,quoted);
+id_lookup("throw",NULL,case_like);
+id_lookup("time_t",NULL,raw_int);
+id_lookup("try",NULL,else_like);
+id_lookup("typedef",NULL,typedef_like);
+id_lookup("undef",NULL,if_like);
+id_lookup("union",NULL,struct_like);
+id_lookup("unsigned",NULL,raw_int);
+id_lookup("va_dcl",NULL,decl);
+id_lookup("va_list",NULL,raw_int);
+id_lookup("virtual",NULL,int_like);
+id_lookup("void",NULL,raw_int);
+id_lookup("volatile",NULL,const_like);
+id_lookup("wchar_t",NULL,raw_int);
+id_lookup("while",NULL,for_like);
+
+/*:28*/
+#line 104 "cweave.w"
+;
+phase_one();
+phase_two();
+phase_three();
+return wrap_up();
+}
+
+/*:3*//*21:*/
+#line 262 "cweave.w"
+
+void
+new_xref(p)
+name_pointer p;
+{
+xref_pointer q;
+sixteen_bits m,n;
+if(no_xref)return;
+if((unindexed(p)||is_tiny(p))&&xref_switch==0)return;
+m= section_count+xref_switch;xref_switch= 0;q= (xref_pointer)p->xref;
+if(q!=xmem){
+n= q->num;
+if(n==m||n==m+def_flag)return;
+else if(m==n+def_flag){
+q->num= m;return;
+}
+}
+append_xref(m);xref_ptr->xlink= q;p->xref= (char*)xref_ptr;
+}
+
+/*:21*//*22:*/
+#line 293 "cweave.w"
+
+void
+new_section_xref(p)
+name_pointer p;
+{
+xref_pointer q,r;
+q= (xref_pointer)p->xref;r= xmem;
+if(q>xmem)
+while(q->num>section_xref_switch){r= q;q= q->xlink;}
+if(r->num==section_count+section_xref_switch)
+return;
+append_xref(section_count+section_xref_switch);
+xref_ptr->xlink= q;section_xref_switch= 0;
+if(r==xmem)p->xref= (char*)xref_ptr;
+else r->xlink= xref_ptr;
+}
+
+/*:22*//*23:*/
+#line 313 "cweave.w"
+
+void
+set_file_flag(p)
+name_pointer p;
+{
+xref_pointer q;
+q= (xref_pointer)p->xref;
+if(q->num==file_flag)return;
+append_xref(file_flag);
+xref_ptr->xlink= q;
+p->xref= (char*)xref_ptr;
+}
+
+/*:23*//*27:*/
+#line 358 "cweave.w"
+
+int names_match(p,first,l,t)
+name_pointer p;
+char*first;
+int l;
+eight_bits t;
+{
+if(length(p)!=l)return 0;
+if(p->ilk!=t&&!(t==normal&&abnormal(p)))return 0;
+return!strncmp(first,p->byte_start,l);
+}
+
+void
+init_p(p,t)
+name_pointer p;
+eight_bits t;
+{
+p->ilk= t;p->xref= (char*)xmem;
+}
+
+void
+init_node(p)
+name_pointer p;
+{
+p->xref= (char*)xmem;
+}
+
+/*:27*//*35:*/
+#line 565 "cweave.w"
+
+void
+skip_limbo(){
+while(1){
+if(loc>limit&&get_line()==0)return;
+*(limit+1)= '@';
+while(*loc!='@')loc++;
+if(loc++<=limit){int c= ccode[(eight_bits)*loc++];
+if(c==new_section)return;
+if(c==noop)skip_restricted();
+else if(c==format_code)/*71:*/
+#line 1180 "cweave.w"
+
+{
+if(get_next()!=identifier)
+err_print("! Missing left identifier of @s");
+
+else{
+lhs= id_lookup(id_first,id_loc,normal);
+if(get_next()!=identifier)
+err_print("! Missing right identifier of @s");
+
+else{
+rhs= id_lookup(id_first,id_loc,normal);
+lhs->ilk= rhs->ilk;
+}
+}
+}
+
+/*:71*/
+#line 575 "cweave.w"
+;
+}
+}
+}
+
+/*:35*//*36:*/
+#line 587 "cweave.w"
+
+unsigned
+skip_TeX()
+{
+while(1){
+if(loc>limit&&get_line()==0)return(new_section);
+*(limit+1)= '@';
+while(*loc!='@'&&*loc!='|')loc++;
+if(*loc++=='|')return('|');
+if(loc<=limit)return(ccode[(eight_bits)*(loc++)]);
+}
+}
+
+/*:36*//*40:*/
+#line 658 "cweave.w"
+
+#line 155 "cweave.ch"
+eight_bits
+get_next()
+{eight_bits c;
+int blank_count= 0;
+
+if(loc<limit&&preprocessing&&(define_pos==2||define_pos==4)&&
+xisspace(*loc)){
+define_pos= 5;
+return(preproc_space);
+}
+
+while(1){
+/*45:*/
+#line 717 "cweave.w"
+
+while(loc==limit-1&&preprocessing&&*loc=='\\')
+if(get_line()==0)return(new_section);
+#line 228 "cweave.ch"
+if(loc>=limit&&preprocessing){
+preprocessing= sharp_include_line= define_pos= 0;
+return(right_preproc);
+}
+#line 724 "cweave.w"
+
+/*:45*/
+#line 167 "cweave.ch"
+;
+if(loc>limit&&get_line()==0)return(new_section);
+
+if(loc==buffer){
+blank_count= 0;
+while((*loc==' '||*loc=='\t')&&loc<limit){
+blank_count++;loc++;
+}
+}
+
+c= *(loc++);
+if(xisdigit(c)||c=='\\'||c=='.')/*48:*/
+#line 775 "cweave.w"
+{
+id_first= id_loc= section_text+1;
+if(*(loc-1)=='\\'){*id_loc++= '~';
+while(xisdigit(*loc))*id_loc++= *loc++;}
+else if(*(loc-1)=='0'){
+if(*loc=='x'||*loc=='X'){*id_loc++= '^';loc++;
+while(xisxdigit(*loc))*id_loc++= *loc++;}
+else if(xisdigit(*loc)){*id_loc++= '~';
+while(xisdigit(*loc))*id_loc++= *loc++;}
+else goto dec;
+}
+else{
+if(*(loc-1)=='.'&&!xisdigit(*loc))goto mistake;
+dec:*id_loc++= *(loc-1);
+while(xisdigit(*loc)||*loc=='.')*id_loc++= *loc++;
+if(*loc=='e'||*loc=='E'){
+*id_loc++= '_';loc++;
+if(*loc=='+'||*loc=='-')*id_loc++= *loc++;
+while(xisdigit(*loc))*id_loc++= *loc++;
+}
+}
+while(*loc=='u'||*loc=='U'||*loc=='l'||*loc=='L'
+||*loc=='f'||*loc=='F'){
+*id_loc++= '$';*id_loc++= toupper(*loc);loc++;
+}
+return(constant);
+}
+
+/*:48*/
+#line 178 "cweave.ch"
+
+else if(c=='\''||c=='"'||(c=='L'&&(*loc=='\''||*loc=='"'))
+||(c=='<'&&sharp_include_line==1))
+/*49:*/
+#line 808 "cweave.w"
+{
+char delim= c;
+id_first= section_text+1;
+id_loc= section_text;
+if(delim=='\''&&*(loc-2)=='@'){*++id_loc= '@';*++id_loc= '@';}
+*++id_loc= delim;
+if(delim=='L'){
+delim= *loc++;*++id_loc= delim;
+}
+if(delim=='<')delim= '>';
+while(1){
+if(loc>=limit){
+if(*(limit-1)!='\\'){
+err_print("! String didn't end");loc= limit;break;
+
+}
+if(get_line()==0){
+err_print("! Input ended in middle of string");loc= buffer;break;
+
+}
+}
+if((c= *loc++)==delim){
+if(++id_loc<=section_text_end)*id_loc= c;
+break;
+}
+if(c=='\\')if(loc>=limit)continue;
+else if(++id_loc<=section_text_end){
+*id_loc= '\\';c= *loc++;
+}
+if(++id_loc<=section_text_end)*id_loc= c;
+}
+if(id_loc>=section_text_end){
+printf("\n! String too long: ");
+
+term_write(section_text+1,25);
+printf("...");mark_error;
+}
+id_loc++;
+return(string);
+}
+
+/*:49*/
+#line 181 "cweave.ch"
+
+else if(xisalpha(c)||isxalpha(c)||ishigh(c))
+/*47:*/
+#line 758 "cweave.w"
+{
+#line 250 "cweave.ch"
+id_first= --loc;
+
+if(preprocessing){
+if(define_pos==1)
+define_pos= 2;
+else if(strncmp(loc,"define",6)==0&&xisspace(*(loc+6)))
+define_pos= 1;
+}
+
+while(isalpha(*++loc)||isdigit(*loc)||isxalpha(*loc)||ishigh(*loc));
+id_loc= loc;return(identifier);
+#line 762 "cweave.w"
+}
+
+/*:47*/
+#line 183 "cweave.ch"
+
+else if(c=='@')/*50:*/
+#line 852 "cweave.w"
+{
+c= *loc++;
+switch(ccode[(eight_bits)c]){
+case translit_code:err_print("! Use @l in limbo only");continue;
+
+case underline:xref_switch= def_flag;continue;
+case trace:tracing= c-'0';continue;
+case xref_roman:case xref_wildcard:case xref_typewriter:
+case noop:case TeX_string:c= ccode[c];skip_restricted();return(c);
+case section_name:
+/*51:*/
+#line 872 "cweave.w"
+{
+char*k;
+cur_section_char= *(loc-1);
+/*53:*/
+#line 890 "cweave.w"
+
+k= section_text;
+while(1){
+if(loc>limit&&get_line()==0){
+err_print("! Input ended in section name");
+
+loc= buffer+1;break;
+}
+c= *loc;
+/*54:*/
+#line 914 "cweave.w"
+
+if(c=='@'){
+c= *(loc+1);
+if(c=='>'){
+loc+= 2;break;
+}
+if(ccode[(eight_bits)c]==new_section){
+err_print("! Section name didn't end");break;
+
+}
+if(c!='@'){
+err_print("! Control codes are forbidden in section name");break;
+
+}
+*(++k)= '@';loc++;
+}
+
+/*:54*/
+#line 899 "cweave.w"
+;
+loc++;if(k<section_text_end)k++;
+if(xisspace(c)){
+c= ' ';if(*(k-1)==' ')k--;
+}
+*k= c;
+}
+if(k>=section_text_end){
+printf("\n! Section name too long: ");
+
+term_write(section_text+1,25);
+printf("...");mark_harmless;
+}
+if(*k==' '&&k>section_text)k--;
+
+/*:53*/
+#line 875 "cweave.w"
+;
+if(k-section_text>3&&strncmp(k-2,"...",3)==0)
+cur_section= section_lookup(section_text+1,k-3,1);
+else cur_section= section_lookup(section_text+1,k,0);
+xref_switch= 0;return(section_name);
+}
+
+/*:51*/
+#line 862 "cweave.w"
+;
+case verbatim:/*57:*/
+#line 961 "cweave.w"
+{
+id_first= loc++;*(limit+1)= '@';*(limit+2)= '>';
+while(*loc!='@'||*(loc+1)!='>')loc++;
+if(loc>=limit)err_print("! Verbatim string didn't end");
+
+id_loc= loc;loc+= 2;
+return(verbatim);
+}
+
+/*:57*/
+#line 863 "cweave.w"
+;
+case ord:/*49:*/
+#line 808 "cweave.w"
+{
+char delim= c;
+id_first= section_text+1;
+id_loc= section_text;
+if(delim=='\''&&*(loc-2)=='@'){*++id_loc= '@';*++id_loc= '@';}
+*++id_loc= delim;
+if(delim=='L'){
+delim= *loc++;*++id_loc= delim;
+}
+if(delim=='<')delim= '>';
+while(1){
+if(loc>=limit){
+if(*(limit-1)!='\\'){
+err_print("! String didn't end");loc= limit;break;
+
+}
+if(get_line()==0){
+err_print("! Input ended in middle of string");loc= buffer;break;
+
+}
+}
+if((c= *loc++)==delim){
+if(++id_loc<=section_text_end)*id_loc= c;
+break;
+}
+if(c=='\\')if(loc>=limit)continue;
+else if(++id_loc<=section_text_end){
+*id_loc= '\\';c= *loc++;
+}
+if(++id_loc<=section_text_end)*id_loc= c;
+}
+if(id_loc>=section_text_end){
+printf("\n! String too long: ");
+
+term_write(section_text+1,25);
+printf("...");mark_error;
+}
+id_loc++;
+return(string);
+}
+
+/*:49*/
+#line 864 "cweave.w"
+;
+default:return(ccode[(eight_bits)c]);
+}
+}
+
+/*:50*/
+#line 184 "cweave.ch"
+
+else if(xisspace(c))continue;
+if(c=='#'&&loc==buffer+1+blank_count&&!preprocessing)
+/*42:*/
+#line 696 "cweave.w"
+{
+preprocessing= 1;
+/*44:*/
+#line 709 "cweave.w"
+
+while(loc<=buffer_end-7&&xisspace(*loc))loc++;
+if(loc<=buffer_end-6&&strncmp(loc,"include",7)==0)sharp_include_line= 1;
+
+/*:44*/
+#line 698 "cweave.w"
+;
+return(left_preproc);
+}
+
+/*:42*/
+#line 187 "cweave.ch"
+;
+mistake:/*46:*/
+#line 734 "cweave.w"
+
+switch(c){
+case'/':if(*loc=='*'){compress(begin_comment);}
+else if(*loc=='/')compress(begin_short_comment);break;
+case'+':if(*loc=='+')compress(plus_plus);break;
+case'-':if(*loc=='-'){compress(minus_minus);}
+else if(*loc=='>')if(*(loc+1)=='*'){loc++;compress(minus_gt_ast);}
+else compress(minus_gt);break;
+case'.':if(*loc=='*'){compress(period_ast);}
+else if(*loc=='.'&&*(loc+1)=='.'){
+loc++;compress(dot_dot_dot);
+}
+break;
+case':':if(*loc==':')compress(colon_colon);break;
+case'=':if(*loc=='=')compress(eq_eq);break;
+case'>':if(*loc=='='){compress(gt_eq);}
+else if(*loc=='>')compress(gt_gt);break;
+case'<':if(*loc=='='){compress(lt_eq);}
+else if(*loc=='<')compress(lt_lt);break;
+case'&':if(*loc=='&')compress(and_and);break;
+case'|':if(*loc=='|')compress(or_or);break;
+#line 239 "cweave.ch"
+case'!':if(*loc=='=')compress(not_eq);break;
+case'#':if(*loc=='#')compress(numb_numb);break;
+#line 756 "cweave.w"
+}
+
+/*:46*/
+#line 188 "cweave.ch"
+
+if(preprocessing){
+if(c=='('&&define_pos==2&&!xisspace(*(loc-2)))
+define_pos= 3;
+else if(c==')'&&define_pos==3)
+define_pos= 4;
+}
+return(c);
+}
+}
+#line 679 "cweave.w"
+
+/*:40*//*56:*/
+#line 936 "cweave.w"
+
+void
+skip_restricted()
+{
+id_first= loc;*(limit+1)= '@';
+false_alarm:
+while(*loc!='@')loc++;
+id_loc= loc;
+if(loc++>limit){
+err_print("! Control text didn't end");loc= limit;
+
+}
+else{
+if(*loc=='@'&&loc<=limit){loc++;goto false_alarm;}
+if(*loc++!='>')
+err_print("! Control codes are forbidden in control text");
+
+}
+}
+
+/*:56*//*60:*/
+#line 989 "cweave.w"
+
+void
+phase_one(){
+phase= 1;reset_input();section_count= 0;
+skip_limbo();change_exists= 0;
+while(!input_has_ended)
+/*61:*/
+#line 1002 "cweave.w"
+
+{
+if(++section_count==max_sections)overflow("section number");
+changed_section[section_count]= changing;
+
+if(*(loc-1)=='*'&&show_progress){
+printf("*%d",section_count);
+update_terminal;
+}
+/*66:*/
+#line 1093 "cweave.w"
+
+while(1){
+switch(next_control= skip_TeX()){
+case translit_code:err_print("! Use @l in limbo only");continue;
+
+case underline:xref_switch= def_flag;continue;
+case trace:tracing= *(loc-1)-'0';continue;
+case'|':C_xref(section_name);break;
+case xref_roman:case xref_wildcard:case xref_typewriter:
+case noop:case section_name:
+loc-= 2;next_control= get_next();
+if(next_control>=xref_roman&&next_control<=xref_typewriter){
+/*67:*/
+#line 1113 "cweave.w"
+
+{
+char*src= id_first,*dst= id_first;
+while(src<id_loc){
+if(*src=='@')src++;
+*dst++= *src++;
+}
+id_loc= dst;
+while(dst<src)*dst++= ' ';
+}
+
+/*:67*/
+#line 1105 "cweave.w"
+
+new_xref(id_lookup(id_first,id_loc,next_control-identifier));
+}
+break;
+}
+if(next_control>=format_code)break;
+}
+
+/*:66*/
+#line 1011 "cweave.w"
+;
+/*69:*/
+#line 1141 "cweave.w"
+
+while(next_control<=definition){
+if(next_control==definition){
+xref_switch= def_flag;
+next_control= get_next();
+}else/*70:*/
+#line 1155 "cweave.w"
+{
+next_control= get_next();
+if(next_control==identifier){
+lhs= id_lookup(id_first,id_loc,normal);lhs->ilk= normal;
+if(xref_switch)new_xref(lhs);
+next_control= get_next();
+if(next_control==identifier){
+rhs= id_lookup(id_first,id_loc,normal);
+lhs->ilk= rhs->ilk;
+if(unindexed(lhs)){
+xref_pointer q,r= NULL;
+for(q= (xref_pointer)lhs->xref;q>xmem;q= q->xlink)
+if(q->num<def_flag)
+if(r)r->xlink= q->xlink;
+else lhs->xref= (char*)q->xlink;
+else r= q;
+}
+next_control= get_next();
+}
+}
+}
+
+/*:70*/
+#line 1146 "cweave.w"
+;
+outer_xref();
+}
+
+/*:69*/
+#line 1012 "cweave.w"
+;
+/*72:*/
+#line 1200 "cweave.w"
+
+if(next_control<=section_name){
+if(next_control==begin_C)section_xref_switch= 0;
+else{
+section_xref_switch= def_flag;
+if(cur_section_char=='('&&cur_section!=name_dir)
+set_file_flag(cur_section);
+}
+do{
+if(next_control==section_name&&cur_section!=name_dir)
+new_section_xref(cur_section);
+next_control= get_next();outer_xref();
+}while(next_control<=section_name);
+}
+
+/*:72*/
+#line 1013 "cweave.w"
+;
+if(changed_section[section_count])change_exists= 1;
+}
+
+/*:61*/
+#line 995 "cweave.w"
+;
+changed_section[section_count]= change_exists;
+
+phase= 2;
+/*76:*/
+#line 1253 "cweave.w"
+section_check(root)
+
+/*:76*/
+#line 999 "cweave.w"
+;
+}
+
+/*:60*//*63:*/
+#line 1041 "cweave.w"
+
+void
+C_xref(spec_ctrl)
+eight_bits spec_ctrl;
+{
+name_pointer p;
+while(next_control<format_code||next_control==spec_ctrl){
+if(next_control>=identifier&&next_control<=xref_typewriter){
+if(next_control>identifier)/*67:*/
+#line 1113 "cweave.w"
+
+{
+char*src= id_first,*dst= id_first;
+while(src<id_loc){
+if(*src=='@')src++;
+*dst++= *src++;
+}
+id_loc= dst;
+while(dst<src)*dst++= ' ';
+}
+
+/*:67*/
+#line 1049 "cweave.w"
+
+p= id_lookup(id_first,id_loc,next_control-identifier);new_xref(p);
+}
+if(next_control==section_name){
+section_xref_switch= cite_flag;
+new_section_xref(cur_section);
+}
+next_control= get_next();
+if(next_control=='|'||next_control==begin_comment||
+next_control==begin_short_comment)return;
+}
+}
+
+/*:63*//*65:*/
+#line 1069 "cweave.w"
+
+void
+outer_xref()
+{
+int bal;
+while(next_control<format_code)
+if(next_control!=begin_comment&&next_control!=begin_short_comment)
+C_xref(ignore);
+else{
+boolean is_long_comment= (next_control==begin_comment);
+bal= copy_comment(is_long_comment,1);next_control= '|';
+while(bal>0){
+C_xref(section_name);
+if(next_control=='|')bal= copy_comment(is_long_comment,bal);
+else bal= 0;
+}
+}
+}
+
+/*:65*//*75:*/
+#line 1230 "cweave.w"
+
+void
+section_check(p)
+name_pointer p;
+{
+if(p){
+section_check(p->llink);
+cur_xref= (xref_pointer)p->xref;
+if(cur_xref->num==file_flag){an_output= 1;cur_xref= cur_xref->xlink;}
+else an_output= 0;
+if(cur_xref->num<def_flag){
+printf("\n! Never defined: <");print_section_name(p);putchar('>');mark_harmless;
+
+}
+while(cur_xref->num>=cite_flag)cur_xref= cur_xref->xlink;
+if(cur_xref==xmem&&!an_output){
+printf("\n! Never used: <");print_section_name(p);putchar('>');mark_harmless;
+
+}
+section_check(p->rlink);
+}
+}
+
+/*:75*//*78:*/
+#line 1283 "cweave.w"
+
+void
+flush_buffer(b,per_cent,carryover)
+char*b;
+boolean per_cent,carryover;
+{
+char*j;j= b;
+if(!per_cent)
+while(j>out_buf&&*j==' ')j--;
+c_line_write(j-out_buf);
+if(per_cent)tex_putc('%');
+tex_new_line;out_line++;
+if(carryover)
+while(j>out_buf)
+if(*j--=='%'&&(j==out_buf||*j!='\\')){
+*b--= '%';break;
+}
+if(b<out_ptr)strncpy(out_buf+1,b+1,out_ptr-b);
+out_ptr-= b-out_buf;
+}
+
+/*:78*//*79:*/
+#line 1312 "cweave.w"
+
+void
+finish_line()
+{
+char*k;
+if(out_ptr>out_buf)flush_buffer(out_ptr,0,0);
+else{
+for(k= buffer;k<=limit;k++)
+if(!(xisspace(*k)))return;
+flush_buffer(out_buf,0,0);
+}
+}
+
+/*:79*//*81:*/
+#line 298 "cweave.ch"
+
+void
+out(c)
+char c;
+{
+if(out_ptr>=out_buf_end)
+break_out();
+
+if(!escape){
+if(in_math){
+if(c=='{')
+math_brace_count++;
+else if(c=='}'){
+math_brace_count--;
+if(math_brace_count<0){
+math_brace_count= 0;
+return;
+}
+}
+}
+if(c=='$'){
+while(math_brace_count>0){
+*(++out_ptr)= '}';
+math_brace_count--;
+}
+in_math= 1-in_math;
+}
+}
+
+if(c=='\\'&&!escape)
+escape= 1;
+else
+escape= 0;
+
+*(++out_ptr)= c;
+return;
+}
+#line 1345 "cweave.w"
+void
+out_str(s)
+char*s;
+{
+while(*s)out(*s++);
+}
+
+/*:81*//*84:*/
+#line 1366 "cweave.w"
+
+void
+break_out()
+{
+char*k= out_ptr;
+while(1){
+if(k==out_buf)/*85:*/
+#line 1387 "cweave.w"
+
+{
+printf("\n! Line had to be broken (output l. %d):\n",out_line);
+
+term_write(out_buf+1,out_ptr-out_buf-1);
+new_line;mark_harmless;
+flush_buffer(out_ptr-1,1,1);return;
+}
+
+/*:85*/
+#line 1372 "cweave.w"
+;
+if(*k==' '){
+flush_buffer(k,0,1);return;
+}
+if(*(k--)=='\\'&&*k!='\\'){
+flush_buffer(k,1,1);return;
+}
+}
+}
+
+/*:84*//*86:*/
+#line 1401 "cweave.w"
+
+void
+out_section(n)
+sixteen_bits n;
+{
+char s[6];
+sprintf(s,"%d",n);out_str(s);
+if(changed_section[n])out_str("\\*");
+
+}
+
+/*:86*//*87:*/
+#line 1415 "cweave.w"
+
+void
+out_name(p)
+name_pointer p;
+{
+char*k,*k_end= (p+1)->byte_start;
+out('{');
+for(k= p->byte_start;k<k_end;k++){
+if(isxalpha(*k))out('\\');
+out(*k);
+}
+out('}');
+}
+
+/*:87*//*88:*/
+#line 1442 "cweave.w"
+
+void
+copy_limbo()
+{
+char c;
+while(1){
+if(loc>limit&&(finish_line(),get_line()==0))return;
+*(limit+1)= '@';
+while(*loc!='@')out(*(loc++));
+if(loc++<=limit){
+c= *loc++;
+if(ccode[(eight_bits)c]==new_section)break;
+switch(ccode[(eight_bits)c]){
+case translit_code:out_str("\\ATL");break;
+
+case'@':out('@');break;
+case noop:skip_restricted();break;
+case format_code:if(get_next()==identifier)get_next();
+if(loc>=limit)get_line();
+break;
+default:err_print("! Double @ should be used in limbo");
+
+out('@');
+}
+}
+}
+}
+
+/*:88*//*90:*/
+#line 1477 "cweave.w"
+
+eight_bits
+copy_TeX()
+{
+char c;
+while(1){
+if(loc>limit&&(finish_line(),get_line()==0))return(new_section);
+*(limit+1)= '@';
+while((c= *(loc++))!='|'&&c!='@'){
+out(c);
+if(out_ptr==out_buf+1&&(xisspace(c)))out_ptr--;
+}
+if(c=='|')return('|');
+if(loc<=limit)return(ccode[(eight_bits)*(loc++)]);
+}
+}
+
+/*:90*//*92:*/
+#line 1509 "cweave.w"
+
+int copy_comment(is_long_comment,bal)
+boolean is_long_comment;
+int bal;
+{
+char c;
+while(1){
+if(loc>limit){
+if(is_long_comment){
+if(get_line()==0){
+err_print("! Input ended in mid-comment");
+
+loc= buffer+1;goto done;
+}
+}
+else{
+if(bal>1)err_print("! Missing } in comment");
+
+goto done;
+}
+}
+c= *(loc++);
+if(c=='|')return(bal);
+if(is_long_comment)/*93:*/
+#line 1550 "cweave.w"
+
+if(c=='*'&&*loc=='/'){
+loc++;
+if(bal>1)err_print("! Missing } in comment");
+
+goto done;
+}
+
+/*:93*/
+#line 1532 "cweave.w"
+;
+if(phase==2){
+if(ishigh(c))app_tok(quoted_char);
+app_tok(c);
+}
+/*94:*/
+#line 1558 "cweave.w"
+
+if(c=='@'){
+if(*(loc++)!='@'){
+err_print("! Illegal use of @ in comment");
+
+loc-= 2;if(phase==2)*(tok_ptr-1)= ' ';goto done;
+}
+}
+else if(c=='\\'&&*loc!='@')
+if(phase==2)app_tok(*(loc++))else loc++;
+
+/*:94*/
+#line 1537 "cweave.w"
+;
+if(c=='{')bal++;
+else if(c=='}'){
+if(bal>1)bal--;
+else{err_print("! Extra } in comment");
+
+if(phase==2)tok_ptr--;
+}
+}
+}
+done:/*95:*/
+#line 1572 "cweave.w"
+
+if(phase==2)while(bal-->0)app_tok('}');
+return(0);
+
+/*:95*/
+#line 1547 "cweave.w"
+;
+}
+
+/*:92*//*99:*/
+#line 1734 "cweave.w"
+
+void
+print_cat(c)
+eight_bits c;
+{
+printf(cat_name[c]);
+}
+
+/*:99*//*106:*/
+#line 2062 "cweave.w"
+
+void
+print_text(p)
+text_pointer p;
+{
+token_pointer j;
+sixteen_bits r;
+if(p>=text_ptr)printf("BAD");
+else for(j= *p;j<*(p+1);j++){
+r= *j%id_flag;
+switch(*j/id_flag){
+case 1:printf("\\\\{");print_id((name_dir+r));printf("}");
+break;
+case 2:printf("\\&{");print_id((name_dir+r));printf("}");
+break;
+case 3:printf("<");print_section_name((name_dir+r));printf(">");
+break;
+case 4:printf("[[%d]]",r);break;
+case 5:printf("|[[%d]]|",r);break;
+default:/*107:*/
+#line 2087 "cweave.w"
+
+switch(r){
+case math_rel:printf("\\mathrel{");break;
+case big_cancel:printf("[ccancel]");break;
+case cancel:printf("[cancel]");break;
+case indent:printf("[indent]");break;
+case outdent:printf("[outdent]");break;
+case backup:printf("[backup]");break;
+case opt:printf("[opt]");break;
+case break_space:printf("[break]");break;
+case force:printf("[force]");break;
+case big_force:printf("[fforce]");break;
+case preproc_line:printf("[preproc]");break;
+case quoted_char:j++;printf("[%o]",(unsigned)*j);break;
+case end_translation:printf("[quit]");break;
+case inserted:printf("[inserted]");break;
+default:putxchar(r);
+}
+
+/*:107*/
+#line 2081 "cweave.w"
+;
+}
+}
+fflush(stdout);
+}
+
+/*:106*//*109:*/
+#line 2187 "cweave.w"
+
+void
+app_str(s)
+char*s;
+{
+while(*s)app_tok(*(s++));
+}
+
+void
+big_app(a)
+token a;
+{
+if(a==' '||(a>=big_cancel&&a<=big_force)){
+if(cur_mathness==maybe_math)init_mathness= no_math;
+else if(cur_mathness==yes_math)app_str("{}$");
+cur_mathness= no_math;
+}
+else{
+if(cur_mathness==maybe_math)init_mathness= yes_math;
+else if(cur_mathness==no_math)app_str("${}");
+cur_mathness= yes_math;
+}
+app(a);
+}
+
+void
+big_app1(a)
+scrap_pointer a;
+{
+switch(a->mathness%4){
+case(no_math):
+if(cur_mathness==maybe_math)init_mathness= no_math;
+else if(cur_mathness==yes_math)app_str("{}$");
+cur_mathness= a->mathness/4;
+break;
+case(yes_math):
+if(cur_mathness==maybe_math)init_mathness= yes_math;
+else if(cur_mathness==no_math)app_str("${}");
+cur_mathness= a->mathness/4;
+break;
+case(maybe_math):break;
+}
+app(tok_flag+(int)((a)->trans-tok_start));
+}
+
+/*:109*//*111:*/
+#line 2312 "cweave.w"
+
+token_pointer
+find_first_ident(p)
+text_pointer p;
+{
+token_pointer q;
+token_pointer j;
+sixteen_bits r;
+if(p>=text_ptr)confusion("find_first_ident");
+for(j= *p;j<*(p+1);j++){
+r= *j%id_flag;
+switch(*j/id_flag){
+case 1:case 2:return j;
+case 4:case 5:
+if((q= find_first_ident(tok_start+r))!=no_ident_found)
+return q;
+default:;
+if(*j==inserted)return no_ident_found;
+}
+}
+return no_ident_found;
+}
+
+/*:111*//*112:*/
+#line 2339 "cweave.w"
+
+#line 421 "cweave.ch"
+void
+make_reserved(p,cat)
+scrap_pointer p;
+eight_bits cat;
+{
+sixteen_bits tok_value;
+token_pointer tok_loc;
+if((tok_loc= find_first_ident(p->trans))==no_ident_found)
+return;
+tok_value= *tok_loc;
+for(;p<=scrap_ptr;p==lo_ptr?p= hi_ptr:p++){
+if(p->cat==exp||p->cat==int_like||p->cat==const_like){
+if(**(p->trans)==tok_value){
+p->cat= cat;
+**(p->trans)= tok_value%id_flag+res_flag;
+}
+}
+}
+(name_dir+(sixteen_bits)(tok_value%id_flag))->ilk= cat;
+*tok_loc= tok_value%id_flag+res_flag;
+}
+#line 2360 "cweave.w"
+
+/*:112*//*113:*/
+#line 2370 "cweave.w"
+
+void
+make_underlined(p)
+
+scrap_pointer p;
+{
+token_pointer tok_loc;
+if((tok_loc= find_first_ident(p->trans))==no_ident_found)
+return;
+xref_switch= def_flag;
+underline_xref(*tok_loc%id_flag+name_dir);
+}
+
+/*:113*//*115:*/
+#line 2391 "cweave.w"
+
+void
+underline_xref(p)
+name_pointer p;
+{
+xref_pointer q= (xref_pointer)p->xref;
+xref_pointer r;
+sixteen_bits m;
+sixteen_bits n;
+if(no_xref)return;
+m= section_count+xref_switch;
+while(q!=xmem){
+n= q->num;
+if(n==m)return;
+else if(m==n+def_flag){
+q->num= m;return;
+}
+else if(n>=def_flag&&n<m)break;
+q= q->xlink;
+}
+/*116:*/
+#line 2421 "cweave.w"
+
+append_xref(0);
+xref_ptr->xlink= (xref_pointer)p->xref;r= xref_ptr;
+p->xref= (char*)xref_ptr;
+while(r->xlink!=q){r->num= r->xlink->num;r= r->xlink;}
+r->num= m;
+
+/*:116*/
+#line 2411 "cweave.w"
+;
+}
+
+/*:115*//*162:*/
+#line 2868 "cweave.w"
+
+void
+reduce(j,k,c,d,n)
+scrap_pointer j;
+eight_bits c;
+short k,d,n;
+{
+scrap_pointer i,i1;
+j->cat= c;j->trans= text_ptr;
+j->mathness= 4*cur_mathness+init_mathness;
+freeze_text;
+if(k>1){
+for(i= j+k,i1= j+1;i<=lo_ptr;i++,i1++){
+i1->cat= i->cat;i1->trans= i->trans;
+i1->mathness= i->mathness;
+}
+lo_ptr= lo_ptr-k+1;
+}
+/*163:*/
+#line 2891 "cweave.w"
+
+if(pp+d>=scrap_base)pp= pp+d;
+else pp= scrap_base;
+
+/*:163*/
+#line 2886 "cweave.w"
+;
+/*168:*/
+#line 2965 "cweave.w"
+
+{scrap_pointer k;
+#line 806 "cweave.ch"
+if(tracing==2){
+printf("\n%3d:",n);
+#line 2969 "cweave.w"
+for(k= scrap_base;k<=lo_ptr;k++){
+if(k==pp)putxchar('*');else putxchar(' ');
+if(k->mathness%4==yes_math)putchar('+');
+else if(k->mathness%4==no_math)putchar('-');
+print_cat(k->cat);
+if(k->mathness/4==yes_math)putchar('+');
+else if(k->mathness/4==no_math)putchar('-');
+}
+if(hi_ptr<=scrap_ptr)printf("...");
+}
+}
+
+/*:168*/
+#line 2887 "cweave.w"
+;
+pp--;
+}
+
+/*:162*//*164:*/
+#line 2898 "cweave.w"
+
+void
+squash(j,k,c,d,n)
+scrap_pointer j;
+eight_bits c;
+short k,d,n;
+{
+scrap_pointer i;
+if(k==1){
+j->cat= c;/*163:*/
+#line 2891 "cweave.w"
+
+if(pp+d>=scrap_base)pp= pp+d;
+else pp= scrap_base;
+
+/*:163*/
+#line 2907 "cweave.w"
+;
+/*168:*/
+#line 2965 "cweave.w"
+
+{scrap_pointer k;
+#line 806 "cweave.ch"
+if(tracing==2){
+printf("\n%3d:",n);
+#line 2969 "cweave.w"
+for(k= scrap_base;k<=lo_ptr;k++){
+if(k==pp)putxchar('*');else putxchar(' ');
+if(k->mathness%4==yes_math)putchar('+');
+else if(k->mathness%4==no_math)putchar('-');
+print_cat(k->cat);
+if(k->mathness/4==yes_math)putchar('+');
+else if(k->mathness/4==no_math)putchar('-');
+}
+if(hi_ptr<=scrap_ptr)printf("...");
+}
+}
+
+/*:168*/
+#line 2908 "cweave.w"
+;
+pp--;
+return;
+}
+for(i= j;i<j+k;i++)big_app1(i);
+reduce(j,k,c,d,n);
+}
+
+/*:164*//*169:*/
+#line 2994 "cweave.w"
+
+text_pointer
+translate()
+{
+scrap_pointer i,
+j;
+pp= scrap_base;lo_ptr= pp-1;hi_ptr= pp;
+/*172:*/
+#line 3033 "cweave.w"
+
+if(tracing==2){
+printf("\nTracing after l. %d:\n",cur_line);mark_harmless;
+
+if(loc>buffer+50){
+printf("...");
+term_write(loc-51,51);
+}
+else term_write(buffer,loc-buffer);
+}
+
+/*:172*/
+#line 3001 "cweave.w"
+;
+/*165:*/
+#line 2929 "cweave.w"
+
+while(1){
+/*166:*/
+#line 2948 "cweave.w"
+
+if(lo_ptr<pp+3){
+while(hi_ptr<=scrap_ptr&&lo_ptr!=pp+3){
+(++lo_ptr)->cat= hi_ptr->cat;lo_ptr->mathness= (hi_ptr)->mathness;
+lo_ptr->trans= (hi_ptr++)->trans;
+}
+for(i= lo_ptr+1;i<=pp+3;i++)i->cat= 0;
+}
+
+/*:166*/
+#line 2931 "cweave.w"
+;
+if(tok_ptr+safe_tok_incr>tok_mem_end){
+if(tok_ptr>max_tok_ptr)max_tok_ptr= tok_ptr;
+overflow("token");
+}
+if(text_ptr+safe_text_incr>tok_start_end){
+if(text_ptr>max_text_ptr)max_text_ptr= text_ptr;
+overflow("text");
+}
+if(pp>lo_ptr)break;
+init_mathness= cur_mathness= maybe_math;
+/*110:*/
+#line 2243 "cweave.w"
+{
+if(cat1==end_arg&&lhs_not_simple)
+if(pp->cat==begin_arg)squash(pp,2,exp,-2,110);
+else squash(pp,2,end_arg,-1,111);
+else if(cat1==insert)squash(pp,2,pp->cat,-2,0);
+else if(cat2==insert)squash(pp+1,2,(pp+1)->cat,-1,0);
+else if(cat3==insert)squash(pp+2,2,(pp+2)->cat,0,0);
+else
+switch(pp->cat){
+case exp:/*117:*/
+#line 2433 "cweave.w"
+
+if(cat1==lbrace||cat1==int_like||cat1==decl){
+make_underlined(pp);big_app1(pp);big_app(indent);app(indent);
+reduce(pp,1,fn_decl,0,1);
+}
+else if(cat1==unop)squash(pp,2,exp,-2,2);
+else if((cat1==binop||cat1==unorbinop)&&cat2==exp)
+squash(pp,3,exp,-2,3);
+else if(cat1==comma&&cat2==exp){
+big_app2(pp);
+app(opt);app('9');big_app1(pp+2);reduce(pp,3,exp,-2,4);
+}
+else if(cat1==exp||cat1==cast)squash(pp,2,exp,-2,5);
+else if(cat1==semi)squash(pp,2,stmt,-1,6);
+else if(cat1==colon){
+#line 449 "cweave.ch"
+make_underlined(pp);
+if(alternative)
+squash(pp,2,label,0,7);
+else
+squash(pp,2,tag,0,7);
+#line 2449 "cweave.w"
+}
+else if(cat1==base){
+if(cat2==int_like&&cat3==comma){
+big_app1(pp+1);big_app(' ');big_app2(pp+2);
+app(opt);app('9');reduce(pp+1,3,base,0,8);
+}
+else if(cat2==int_like&&cat3==lbrace){
+big_app1(pp);big_app(' ');big_app1(pp+1);big_app(' ');big_app1(pp+2);
+reduce(pp,3,exp,-1,9);
+}
+}
+else if(cat1==rbrace)squash(pp,1,stmt,-1,10);
+
+/*:117*/
+#line 2252 "cweave.w"
+;break;
+case lpar:/*118:*/
+#line 2462 "cweave.w"
+
+if((cat1==exp||cat1==unorbinop)&&cat2==rpar)squash(pp,3,exp,-2,11);
+else if(cat1==rpar){
+big_app1(pp);app('\\');app(',');big_app1(pp+1);
+
+reduce(pp,2,exp,-2,12);
+}
+else if(cat1==decl_head||cat1==int_like||cat1==exp){
+if(cat2==rpar)squash(pp,3,cast,-2,13);
+else if(cat2==comma){
+big_app3(pp);app(opt);app('9');reduce(pp,3,lpar,0,14);
+}
+}
+else if(cat1==stmt||cat1==decl){
+big_app2(pp);big_app(' ');reduce(pp,2,lpar,0,15);
+}
+
+/*:118*/
+#line 2253 "cweave.w"
+;break;
+case question:/*119:*/
+#line 2479 "cweave.w"
+
+if(cat1==exp&&cat2==colon)squash(pp,3,binop,-2,16);
+
+/*:119*/
+#line 2254 "cweave.w"
+;break;
+case unop:/*120:*/
+#line 2482 "cweave.w"
+
+if(cat1==exp||cat1==int_like)squash(pp,2,cat1,-2,17);
+
+/*:120*/
+#line 2255 "cweave.w"
+;break;
+case unorbinop:/*121:*/
+#line 2485 "cweave.w"
+
+if(cat1==exp||cat1==int_like){
+big_app('{');big_app1(pp);big_app('}');big_app1(pp+1);
+reduce(pp,2,cat1,-2,18);
+}
+else if(cat1==binop){
+big_app(math_rel);big_app1(pp);big_app('{');big_app1(pp+1);big_app('}');
+big_app('}');reduce(pp,2,binop,-1,19);
+}
+
+/*:121*/
+#line 2256 "cweave.w"
+;break;
+case binop:/*122:*/
+#line 2495 "cweave.w"
+
+if(cat1==binop){
+big_app(math_rel);big_app('{');big_app1(pp);big_app('}');
+big_app('{');big_app1(pp+1);big_app('}');
+big_app('}');reduce(pp,2,binop,-1,20);
+}
+
+/*:122*/
+#line 2257 "cweave.w"
+;break;
+case cast:/*123:*/
+#line 2502 "cweave.w"
+
+if(cat1==exp){
+big_app1(pp);big_app(' ');big_app1(pp+1);reduce(pp,2,exp,-2,21);
+}
+else if(cat1==semi)squash(pp,1,exp,-2,22);
+
+/*:123*/
+#line 2258 "cweave.w"
+;break;
+case sizeof_like:/*124:*/
+#line 2508 "cweave.w"
+
+if(cat1==cast)squash(pp,2,exp,-2,23);
+else if(cat1==exp){
+big_app1(pp);big_app(' ');big_app1(pp+1);reduce(pp,2,exp,-2,24);
+}
+
+/*:124*/
+#line 2259 "cweave.w"
+;break;
+case int_like:/*125:*/
+#line 2514 "cweave.w"
+
+if(cat1==int_like||cat1==struct_like){
+big_app1(pp);big_app(' ');big_app1(pp+1);reduce(pp,2,cat1,-2,25);
+}
+else if(cat1==exp&&(cat2==raw_int||cat2==struct_like))
+squash(pp,2,int_like,-2,26);
+else if(cat1==exp||cat1==unorbinop||cat1==semi){
+big_app1(pp);
+if(cat1!=semi)big_app(' ');
+reduce(pp,1,decl_head,-1,27);
+}
+else if(cat1==colon){
+big_app1(pp);big_app(' ');reduce(pp,1,decl_head,0,28);
+}
+else if(cat1==prelangle)squash(pp+1,1,langle,1,29);
+else if(cat1==colcol&&(cat2==exp||cat2==int_like))squash(pp,3,cat2,-2,30);
+else if(cat1==cast){
+if(cat2==lbrace){
+big_app2(pp);big_app(indent);big_app(indent);
+reduce(pp,2,fn_decl,1,31);
+}
+#line 462 "cweave.ch"
+else squash(pp,2,int_like,-2,32);
+}
+else if(cat1==binop&&cat2==exp)squash(pp,3,int_like,-2,117);
+#line 2537 "cweave.w"
+
+/*:125*/
+#line 2260 "cweave.w"
+;break;
+case decl_head:/*126:*/
+#line 2538 "cweave.w"
+
+if(cat1==comma){
+big_app2(pp);big_app(' ');reduce(pp,2,decl_head,-1,33);
+}
+else if(cat1==unorbinop){
+big_app1(pp);big_app('{');big_app1(pp+1);big_app('}');
+reduce(pp,2,decl_head,-1,34);
+}
+else if(cat1==exp&&cat2!=lpar&&cat2!=exp){
+make_underlined(pp+1);squash(pp,2,decl_head,-1,35);
+}
+else if((cat1==binop||cat1==colon)&&cat2==exp&&(cat3==comma||
+cat3==semi||cat3==rpar))
+squash(pp,3,decl_head,-1,36);
+else if(cat1==cast)squash(pp,2,decl_head,-1,37);
+else if(cat1==lbrace||(cat1==int_like&&cat2!=colcol)||cat1==decl){
+big_app1(pp);big_app(indent);app(indent);reduce(pp,1,fn_decl,0,38);
+}
+else if(cat1==semi)squash(pp,2,decl,-1,39);
+
+/*:126*/
+#line 2261 "cweave.w"
+;break;
+case decl:/*127:*/
+#line 2558 "cweave.w"
+
+if(cat1==decl){
+big_app1(pp);big_app(force);big_app1(pp+1);
+reduce(pp,2,decl,-1,40);
+}
+else if(cat1==stmt||cat1==function){
+big_app1(pp);big_app(big_force);
+big_app1(pp+1);reduce(pp,2,cat1,-1,41);
+}
+
+/*:127*/
+#line 2262 "cweave.w"
+;break;
+case typedef_like:/*128:*/
+#line 2568 "cweave.w"
+
+#line 479 "cweave.ch"
+if(cat1==decl_head){
+if((cat2==exp&&cat3!=lpar&&cat3!=exp)||cat2==int_like){
+make_underlined(pp+2);make_reserved(pp+2,raw_int);
+big_app2(pp+1);reduce(pp+1,2,decl_head,0,42);
+}
+else if(cat2==semi){
+big_app1(pp);big_app(' ');big_app2(pp+1);reduce(pp,3,decl,-1,43);
+}
+}
+else if(cat1==exp&&!preprocessing&&cat2!=lpar){
+make_reserved(pp+1,raw_int);
+squash(pp+1,1,raw_int,-2,116);
+}
+#line 2577 "cweave.w"
+
+/*:128*/
+#line 2263 "cweave.w"
+;break;
+case struct_like:/*129:*/
+#line 2578 "cweave.w"
+
+#line 515 "cweave.ch"
+if(cat1==lbrace){
+if(alternative){
+big_app1(pp);big_app(indent);big_app(force);big_app(backup);
+big_app1(pp+1);reduce(pp,2,struct_head,0,44);
+}else{
+big_app1(pp);big_app(' ');big_app1(pp+1);
+reduce(pp,2,struct_head,0,44);
+}
+}
+else if(cat1==exp||cat1==int_like){
+if(cat2==lbrace||cat2==semi){
+make_underlined(pp+1);make_reserved(pp+1,raw_int);
+big_app1(pp);big_app(' ');big_app1(pp+1);
+if(cat2==semi)reduce(pp,2,decl_head,-1,45);
+else{
+if(alternative){
+big_app(indent);big_app(force);big_app(backup);big_app1(pp+2);
+reduce(pp,3,struct_head,0,46);
+}else{
+big_app(' ');big_app1(pp+2);reduce(pp,3,struct_head,0,46);
+}
+}
+}
+else if(cat2==colon)squash(pp+2,1,base,-1,47);
+else if(!(cat2==base||cat2==raw_int||
+cat2==int_like||cat2==const_like)){
+big_app1(pp);big_app(' ');big_app1(pp+1);reduce(pp,2,int_like,-2,48);
+}
+}
+#line 2596 "cweave.w"
+
+/*:129*/
+#line 2264 "cweave.w"
+;break;
+case struct_head:/*130:*/
+#line 2597 "cweave.w"
+
+if((cat1==decl||cat1==stmt||cat1==function)&&cat2==rbrace){
+#line 553 "cweave.ch"
+if(alternative){
+big_app1(pp);big_app1(pp+1);
+big_app(force);big_app(backup);big_app1(pp+2);big_app(' ');
+big_app(outdent);reduce(pp,3,int_like,-2,49);
+}else{
+big_app1(pp);big_app(indent);big_app(force);big_app1(pp+1);
+big_app(outdent);big_app(force);big_app1(pp+2);
+reduce(pp,3,int_like,-2,49);
+}
+#line 2602 "cweave.w"
+}
+else if(cat1==rbrace){
+big_app1(pp);app_str("\\,");big_app1(pp+1);
+
+reduce(pp,2,int_like,-2,50);
+}
+
+/*:130*/
+#line 2265 "cweave.w"
+;break;
+case fn_decl:/*131:*/
+#line 2609 "cweave.w"
+
+if(cat1==decl){
+big_app1(pp);big_app(force);big_app1(pp+1);reduce(pp,2,fn_decl,0,51);
+}
+else if(cat1==stmt){
+big_app1(pp);app(outdent);app(outdent);big_app(force);
+big_app1(pp+1);reduce(pp,2,function,-1,52);
+}
+
+/*:131*/
+#line 2266 "cweave.w"
+;break;
+case function:/*132:*/
+#line 2618 "cweave.w"
+
+if(cat1==function||cat1==decl||cat1==stmt){
+big_app1(pp);big_app(big_force);big_app1(pp+1);reduce(pp,2,cat1,-1,53);
+}
+
+/*:132*/
+#line 2267 "cweave.w"
+;break;
+case lbrace:/*133:*/
+#line 2623 "cweave.w"
+
+if(cat1==rbrace){
+big_app1(pp);app('\\');app(',');big_app1(pp+1);
+
+reduce(pp,2,stmt,-1,54);
+}
+else if((cat1==stmt||cat1==decl||cat1==function)&&cat2==rbrace){
+#line 571 "cweave.ch"
+if(alternative){
+big_app(indent);big_app(force);big_app(backup);big_app1(pp);
+app(noop);big_app(cancel);big_app1(pp+1);big_app(force);big_app(backup);
+big_app1(pp+2);big_app(outdent);big_app(force);reduce(pp,3,stmt,-2,55);
+}else{
+big_app(force);big_app1(pp);big_app(indent);big_app(force);
+big_app1(pp+1);big_app(force);big_app(backup);big_app1(pp+2);
+big_app(outdent);big_app(force);reduce(pp,3,stmt,-1,55);
+}
+#line 2633 "cweave.w"
+}
+else if(cat1==exp){
+if(cat2==rbrace)squash(pp,3,exp,-2,56);
+else if(cat2==comma&&cat3==rbrace)squash(pp,4,exp,-2,56);
+}
+
+/*:133*/
+#line 2268 "cweave.w"
+;break;
+case do_like:/*140:*/
+#line 2689 "cweave.w"
+
+#line 669 "cweave.ch"
+if(alternative){
+if(cat1==lbrace)squash(pp,1,do_head,0,114);
+else if(cat1==stmt&&cat2==else_like&&cat3==semi){
+big_app(force);big_app1(pp);big_app(indent);big_app(force);
+big_app1(pp+1);big_app(cancel);app(noop);
+big_app(break_space);big_app2(pp+2);big_app(outdent);big_app(force);
+reduce(pp,4,stmt,-1,69);
+}
+}else{
+if(cat1==stmt&&cat2==else_like&&cat3==semi){
+big_app1(pp);big_app(break_space);app(noop);big_app(cancel);
+big_app1(pp+1);big_app(cancel);app(noop);big_app(break_space);
+big_app2(pp+2);reduce(pp,4,stmt,-1,69);
+}
+}
+#line 2695 "cweave.w"
+
+/*:140*/
+#line 2269 "cweave.w"
+;break;
+case if_like:/*134:*/
+#line 2639 "cweave.w"
+
+if(cat1==exp){
+big_app1(pp);big_app(' ');big_app1(pp+1);reduce(pp,2,if_clause,0,57);
+}
+
+/*:134*/
+#line 2270 "cweave.w"
+;break;
+case for_like:/*135:*/
+#line 2644 "cweave.w"
+
+if(cat1==exp){
+big_app1(pp);big_app(' ');big_app1(pp+1);reduce(pp,2,else_like,-2,58);
+}
+
+/*:135*/
+#line 2271 "cweave.w"
+;break;
+case else_like:/*136:*/
+#line 2649 "cweave.w"
+
+if(cat1==lbrace)squash(pp,1,else_head,0,59);
+else if(cat1==stmt){
+#line 589 "cweave.ch"
+if(alternative){
+big_app(force);big_app1(pp);big_app(indent);big_app(force);
+big_app1(pp+1);big_app(outdent);big_app(force);
+reduce(pp,2,stmt,-1,60);
+}else{
+big_app(force);big_app1(pp);big_app(indent);big_app(break_space);
+big_app1(pp+1);big_app(outdent);big_app(force);
+reduce(pp,2,stmt,-1,60);
+}
+#line 2655 "cweave.w"
+}
+
+/*:136*/
+#line 2272 "cweave.w"
+;break;
+case if_clause:/*138:*/
+#line 2664 "cweave.w"
+
+if(cat1==lbrace)squash(pp,1,if_head,0,62);
+else if(cat1==stmt){
+if(cat2==else_like){
+#line 627 "cweave.ch"
+if(alternative){
+big_app(force);big_app1(pp);big_app(indent);big_app(force);
+big_app1(pp+1);big_app(outdent);big_app(force);big_app1(pp+2);
+}else{
+big_app(force);big_app1(pp);big_app(indent);big_app(break_space);
+big_app1(pp+1);big_app(outdent);big_app(force);big_app1(pp+2);
+}
+if(cat3==if_like){
+big_app(' ');big_app1(pp+3);reduce(pp,4,if_like,0,63);
+}else reduce(pp,3,else_like,0,64);
+#line 2673 "cweave.w"
+}
+else squash(pp,1,else_like,0,65);
+}
+
+/*:138*/
+#line 2273 "cweave.w"
+;break;
+case if_head:/*139:*/
+#line 2677 "cweave.w"
+
+if(cat1==stmt||cat1==exp){
+if(cat2==else_like){
+#line 648 "cweave.ch"
+if(alternative){
+big_app(force);big_app1(pp);big_app(break_space);
+big_app1(pp+1);big_app(force);big_app1(pp+2);
+}else{
+big_app(force);big_app1(pp);big_app(break_space);app(noop);
+big_app(cancel);big_app1(pp+1);big_app(force);big_app1(pp+2);
+}
+if(cat3==if_like){
+big_app(' ');big_app1(pp+3);reduce(pp,4,if_like,0,66);
+}else reduce(pp,3,else_like,0,67);
+#line 2685 "cweave.w"
+}
+else squash(pp,1,else_head,0,68);
+}
+
+/*:139*/
+#line 2274 "cweave.w"
+;break;
+case else_head:/*137:*/
+#line 2657 "cweave.w"
+
+if(cat1==stmt||cat1==exp){
+#line 607 "cweave.ch"
+if(alternative){
+big_app(force);big_app1(pp);big_app(break_space);
+big_app1(pp+1);big_app(force);
+reduce(pp,2,stmt,-1,61);
+}else{
+big_app(force);big_app1(pp);big_app(break_space);app(noop);
+big_app(cancel);big_app1(pp+1);big_app(force);
+reduce(pp,2,stmt,-1,61);
+}
+#line 2662 "cweave.w"
+}
+
+/*:137*/
+#line 2275 "cweave.w"
+;break;
+case case_like:/*141:*/
+#line 2696 "cweave.w"
+
+#line 692 "cweave.ch"
+if(cat1==semi)squash(pp,2,stmt,-3,70);
+else if(cat1==colon)squash(pp,2,tag,-2,71);
+#line 2699 "cweave.w"
+else if(cat1==exp){
+if(cat2==semi){
+big_app1(pp);big_app(' ');big_app1(pp+1);big_app1(pp+2);
+reduce(pp,3,stmt,-1,72);
+}
+else if(cat2==colon){
+big_app1(pp);big_app(' ');big_app1(pp+1);big_app1(pp+2);
+#line 701 "cweave.ch"
+reduce(pp,3,tag,-2,73);
+#line 2707 "cweave.w"
+}
+}
+
+/*:141*/
+#line 2276 "cweave.w"
+;break;
+case stmt:/*143:*/
+#line 2723 "cweave.w"
+
+if(cat1==stmt||cat1==decl||cat1==function){
+big_app1(pp);
+if(cat1==function)big_app(big_force);
+else if(cat1==decl)big_app(big_force);
+else if(force_lines)big_app(force);
+else big_app(break_space);
+big_app1(pp+1);reduce(pp,2,cat1,-1,76);
+}
+
+/*:143*/
+#line 2277 "cweave.w"
+;break;
+case tag:/*142:*/
+#line 2710 "cweave.w"
+
+#line 715 "cweave.ch"
+if(alternative){
+if(cat1==tag){
+big_app1(pp);big_app(force);big_app1(pp+1);reduce(pp,2,tag,-1,74);
+}
+else if((cat1==stmt||cat1==decl||cat1==function)&&
+(cat2==rbrace||cat2==tag)){
+big_app(force);big_app1(pp);big_app(indent);big_app(force);
+big_app1(pp+1);big_app(outdent);reduce(pp,2,cat1,-1,75);
+}
+}else{
+if(cat1==tag){
+big_app1(pp);big_app(break_space);big_app1(pp+1);reduce(pp,2,tag,-1,74);
+}
+else if(cat1==stmt||cat1==decl||cat1==function){
+big_app(force);big_app(backup);big_app1(pp);big_app(break_space);
+big_app1(pp+1);reduce(pp,2,cat1,-1,75);
+}
+}
+#line 2718 "cweave.w"
+
+/*:142*/
+#line 2278 "cweave.w"
+;break;
+case semi:/*144:*/
+#line 2733 "cweave.w"
+
+big_app(' ');big_app1(pp);reduce(pp,1,stmt,-1,77);
+
+/*:144*/
+#line 2279 "cweave.w"
+;break;
+case lproc:/*145:*/
+#line 2736 "cweave.w"
+
+if(cat1==define_like)make_underlined(pp+2);
+if(cat1==else_like||cat1==if_like||cat1==define_like)
+squash(pp,2,lproc,0,78);
+else if(cat1==rproc){
+app(inserted);big_app2(pp);reduce(pp,2,insert,-1,79);
+#line 750 "cweave.ch"
+}else if((cat1==exp||cat1==function||cat1==int_like)&&cat2==rproc){
+app(inserted);big_app1(pp);big_app(' ');big_app2(pp+1);
+reduce(pp,3,insert,-1,80);
+}else if((cat1==exp||cat1==int_like||cat1==const_like)&&
+cat2==pp_space){
+if(cat3==int_like||cat3==const_like||cat3==raw_int)
+make_reserved(pp+1,(pp+3)->cat);
+big_app1(pp);big_app(' ');big_app1(pp+1);app_str(" \\5");
+
+reduce(pp,3,lproc,-1,119);
+}else if(cat1==exp&&cat2==exp&&cat3==pp_space){
+big_app1(pp);big_app(' ');big_app2(pp+1);app_str(" \\5");
+reduce(pp,4,lproc,-1,120);
+}
+#line 2753 "cweave.w"
+
+/*:145*/
+#line 2280 "cweave.w"
+;break;
+case section_scrap:/*146:*/
+#line 2754 "cweave.w"
+
+if(cat1==semi){
+big_app2(pp);big_app(force);reduce(pp,2,stmt,-2,81);
+}
+else squash(pp,1,exp,-2,82);
+
+/*:146*/
+#line 2281 "cweave.w"
+;break;
+case insert:/*147:*/
+#line 2760 "cweave.w"
+
+if(cat1)
+squash(pp,2,cat1,0,83);
+
+/*:147*/
+#line 2282 "cweave.w"
+;break;
+case prelangle:/*148:*/
+#line 2764 "cweave.w"
+
+init_mathness= cur_mathness= yes_math;
+app('<');reduce(pp,1,binop,-2,84);
+
+/*:148*/
+#line 2283 "cweave.w"
+;break;
+case prerangle:/*149:*/
+#line 2768 "cweave.w"
+
+init_mathness= cur_mathness= yes_math;
+app('>');reduce(pp,1,binop,-2,85);
+
+/*:149*/
+#line 2284 "cweave.w"
+;break;
+case langle:/*150:*/
+#line 2772 "cweave.w"
+
+if(cat1==exp&&cat2==prerangle)squash(pp,3,cast,-1,86);
+else if(cat1==prerangle){
+big_app1(pp);app('\\');app(',');big_app1(pp+1);
+
+reduce(pp,2,cast,-1,87);
+}
+else if(cat1==decl_head||cat1==int_like){
+if(cat2==prerangle)squash(pp,3,cast,-1,88);
+else if(cat2==comma){
+big_app3(pp);app(opt);app('9');reduce(pp,3,langle,0,89);
+}
+}
+
+/*:150*/
+#line 2285 "cweave.w"
+;break;
+case public_like:/*151:*/
+#line 2786 "cweave.w"
+
+#line 771 "cweave.ch"
+if(cat1==colon)squash(pp,2,tag,-2,90);
+#line 2788 "cweave.w"
+else squash(pp,1,int_like,-2,91);
+
+/*:151*/
+#line 2286 "cweave.w"
+;break;
+case colcol:/*152:*/
+#line 2790 "cweave.w"
+
+if(cat1==exp||cat1==int_like)squash(pp,2,cat1,-2,92);
+
+/*:152*/
+#line 2287 "cweave.w"
+;break;
+case new_like:/*153:*/
+#line 2793 "cweave.w"
+
+if(cat1==exp||(cat1==raw_int&&cat2!=prelangle&&cat2!=langle)){
+big_app1(pp);big_app(' ');big_app1(pp+1);reduce(pp,2,new_like,0,93);
+}
+else if(cat1==raw_unorbin||cat1==colcol)
+squash(pp,2,new_like,0,94);
+else if(cat1==cast)squash(pp,2,exp,-2,95);
+else if(cat1!=lpar&&cat1!=raw_int&&cat1!=struct_like)
+squash(pp,1,exp,-2,96);
+
+/*:153*/
+#line 2288 "cweave.w"
+;break;
+case operator_like:/*154:*/
+#line 2803 "cweave.w"
+
+#line 786 "cweave.ch"
+if(cat1==binop||cat1==unop||cat1==unorbinop||cat1==raw_unorbin){
+if(cat2==binop)break;
+big_app1(pp);big_app('{');big_app1(pp+1);big_app('}');
+reduce(pp,2,exp,-2,97);
+}
+else if(cat1==new_like||cat1==sizeof_like){
+big_app1(pp);big_app(' ');big_app1(pp+1);reduce(pp,2,exp,-2,98);
+}
+else if(cat1==raw_int||cat1==int_like||cat1==const_like){
+big_app1(pp);big_app(' ');big_app1(pp+1);
+reduce(pp,2,operator_like,-2,118);
+}
+#line 2812 "cweave.w"
+else squash(pp,1,new_like,0,99);
+
+/*:154*/
+#line 2289 "cweave.w"
+;break;
+case catch_like:/*155:*/
+#line 2814 "cweave.w"
+
+if(cat1==cast||cat1==exp){
+big_app2(pp);big_app(indent);big_app(indent);
+reduce(pp,2,fn_decl,0,100);
+}
+
+/*:155*/
+#line 2290 "cweave.w"
+;break;
+case base:/*156:*/
+#line 2820 "cweave.w"
+
+if(cat1==public_like&&cat2==exp){
+if(cat3==comma){
+big_app2(pp);big_app(' ');big_app2(pp+2);
+reduce(pp,4,base,0,101);
+}else{
+big_app1(pp+1);big_app(' ');big_app1(pp+2);
+reduce(pp+1,2,int_like,-1,102);
+}
+}
+
+/*:156*/
+#line 2291 "cweave.w"
+;break;
+case raw_rpar:/*157:*/
+#line 2831 "cweave.w"
+
+if(cat1==const_like&&
+(cat2==semi||cat2==lbrace||cat2==comma||cat2==binop
+||cat2==const_like)){
+big_app1(pp);big_app(' ');
+big_app1(pp+1);reduce(pp,2,raw_rpar,0,103);
+}else squash(pp,1,rpar,-3,104);
+
+/*:157*/
+#line 2292 "cweave.w"
+;break;
+case raw_unorbin:/*158:*/
+#line 2839 "cweave.w"
+
+if(cat1==const_like){
+big_app2(pp);app_str("\\ ");reduce(pp,2,raw_unorbin,0,105);
+
+}else squash(pp,1,unorbinop,-2,106);
+
+/*:158*/
+#line 2293 "cweave.w"
+;break;
+case const_like:/*159:*/
+#line 2845 "cweave.w"
+
+squash(pp,1,int_like,-2,107);
+
+/*:159*/
+#line 2294 "cweave.w"
+;break;
+#line 392 "cweave.ch"
+case raw_int:/*160:*/
+#line 2848 "cweave.w"
+
+if(cat1==lpar)squash(pp,1,exp,-2,108);
+else squash(pp,1,int_like,-3,109);
+
+/*:160*/
+#line 392 "cweave.ch"
+;break;
+case label:/*249:*/
+#line 1075 "cweave.ch"
+
+if(cat1==label){
+big_app1(pp);big_app(force);big_app1(pp+1);reduce(pp,2,label,-1,112);
+}
+else if(cat1==stmt||cat1==decl||cat1==function){
+big_app(cancel);app(noop);
+big_app(outdent);big_app(outdent);big_app(force);
+big_app1(pp);big_app(indent);big_app(indent);big_app(force);
+big_app1(pp+1);reduce(pp,2,cat1,-1,113);
+}
+
+/*:249*/
+#line 393 "cweave.ch"
+;break;
+case do_head:/*250:*/
+#line 1086 "cweave.ch"
+
+if(cat1==stmt&&cat2==else_like&&cat3==semi){
+big_app1(pp);big_app(break_space);big_app1(pp+1);big_app(cancel);
+app(noop);big_app(break_space);big_app2(pp+2);reduce(pp,4,stmt,-1,115);
+}
+
+/*:250*/
+#line 394 "cweave.ch"
+;break;
+#line 2296 "cweave.w"
+}
+pp++;
+}
+
+/*:110*/
+#line 2942 "cweave.w"
+;
+}
+
+/*:165*/
+#line 3002 "cweave.w"
+;
+/*170:*/
+#line 3011 "cweave.w"
+{
+/*171:*/
+#line 3023 "cweave.w"
+
+if(lo_ptr>scrap_base&&tracing==1){
+printf("\nIrreducible scrap sequence in section %d:",section_count);
+
+mark_harmless;
+for(j= scrap_base;j<=lo_ptr;j++){
+printf(" ");print_cat(j->cat);
+}
+}
+
+/*:171*/
+#line 3012 "cweave.w"
+;
+for(j= scrap_base;j<=lo_ptr;j++){
+if(j!=scrap_base)app(' ');
+if(j->mathness%4==yes_math)app('$');
+app1(j);
+if(j->mathness/4==yes_math)app('$');
+if(tok_ptr+6>tok_mem_end)overflow("token");
+}
+freeze_text;return(text_ptr-1);
+}
+
+/*:170*/
+#line 3003 "cweave.w"
+;
+}
+
+/*:169*//*173:*/
+#line 3059 "cweave.w"
+
+void
+C_parse(spec_ctrl)
+eight_bits spec_ctrl;
+{
+int count;
+while(next_control<format_code||next_control==spec_ctrl){
+/*175:*/
+#line 821 "cweave.ch"
+
+/*176:*/
+#line 3156 "cweave.w"
+
+if(scrap_ptr+safe_scrap_incr>scrap_info_end||
+tok_ptr+safe_tok_incr>tok_mem_end||
+text_ptr+safe_text_incr>tok_start_end){
+if(scrap_ptr>max_scr_ptr)max_scr_ptr= scrap_ptr;
+if(tok_ptr>max_tok_ptr)max_tok_ptr= tok_ptr;
+if(text_ptr>max_text_ptr)max_text_ptr= text_ptr;
+overflow("scrap/token/text");
+}
+
+/*:176*/
+#line 822 "cweave.ch"
+;
+#line 3084 "cweave.w"
+switch(next_control){
+case section_name:
+app(section_flag+(int)(cur_section-name_dir));
+app_scrap(section_scrap,maybe_math);
+app_scrap(exp,yes_math);break;
+case string:case constant:case verbatim:/*178:*/
+#line 3211 "cweave.w"
+
+count= -1;
+if(next_control==constant)app_str("\\T{");
+
+else if(next_control==string){
+count= 20;app_str("\\.{");
+}
+
+else app_str("\\vb{");
+
+while(id_first<id_loc){
+if(count==0){
+app_str("}\\)\\.{");count= 20;
+
+}
+
+if((eight_bits)(*id_first)>0177){
+app_tok(quoted_char);
+app_tok((eight_bits)(*id_first++));
+}
+else{
+switch(*id_first){
+case' ':case'\\':case'#':case'%':case'$':case'^':
+case'{':case'}':case'~':case'&':case'_':app('\\');break;
+
+
+
+#line 913 "cweave.ch"
+
+
+
+#line 3241 "cweave.w"
+
+
+
+
+
+case'@':if(*(id_first+1)=='@')id_first++;
+else err_print("! Double @ should be used in strings");
+
+}
+app_tok(*id_first++);
+}
+count--;
+}
+app('}');
+app_scrap(exp,maybe_math);
+
+/*:178*/
+#line 3089 "cweave.w"
+;
+break;
+case identifier:app_cur_id(1);break;
+case TeX_string:/*179:*/
+#line 3272 "cweave.w"
+
+app_str("\\hbox{");
+
+while(id_first<id_loc)
+if((eight_bits)(*id_first)>0177){
+app_tok(quoted_char);
+app_tok((eight_bits)(*id_first++));
+}
+else{
+if(*id_first=='@')id_first++;
+app_tok(*id_first++);
+}
+app('}');
+
+/*:179*/
+#line 3092 "cweave.w"
+;break;
+case'/':case'.':
+app(next_control);app_scrap(binop,yes_math);break;
+case'<':app_str("\\langle");app_scrap(prelangle,yes_math);break;
+
+case'>':app_str("\\rangle");app_scrap(prerangle,yes_math);break;
+
+case'=':app_str("\\K");app_scrap(binop,yes_math);break;
+
+case'|':app_str("\\OR");app_scrap(binop,yes_math);break;
+
+case'^':app_str("\\XOR");app_scrap(binop,yes_math);break;
+
+case'%':app_str("\\MOD");app_scrap(binop,yes_math);break;
+
+case'!':app_str("\\R");app_scrap(unop,yes_math);break;
+
+case'~':app_str("\\CM");app_scrap(unop,yes_math);break;
+
+case'+':case'-':app(next_control);app_scrap(unorbinop,yes_math);break;
+case'*':app(next_control);app_scrap(raw_unorbin,yes_math);break;
+case'&':app_str("\\AND");app_scrap(raw_unorbin,yes_math);break;
+
+case'?':app_str("\\?");app_scrap(question,yes_math);break;
+
+case'#':app_str("\\#");app_scrap(unorbinop,yes_math);break;
+
+case ignore:case xref_roman:case xref_wildcard:
+case xref_typewriter:case noop:break;
+#line 835 "cweave.ch"
+case'(':if(func_index)
+if(*(tok_ptr-1)>=id_flag&&*(tok_ptr-1)<res_flag)
+
+(name_dir+*(tok_ptr-1)%10240)->func_flag= 1;
+case'[':app(next_control);app_scrap(lpar,maybe_math);break;
+case')':case']':app(next_control);app_scrap(raw_rpar,maybe_math);break;
+case'{':if(alternative)
+app_str("\\LBR");
+else
+app_str("\\{");
+app_scrap(lbrace,yes_math);break;
+
+case'}':if(alternative)
+app_str("\\RBR");
+else
+app_str("\\}");
+app_scrap(rbrace,yes_math);break;
+
+#line 3127 "cweave.w"
+case',':app(',');app_scrap(comma,yes_math);break;
+case';':app(';');app_scrap(semi,maybe_math);break;
+case':':app(':');app_scrap(colon,maybe_math);break;
+/*177:*/
+#line 3170 "cweave.w"
+
+case not_eq:app_str("\\I");app_scrap(binop,yes_math);break;
+
+case lt_eq:app_str("\\Z");app_scrap(binop,yes_math);break;
+
+case gt_eq:app_str("\\G");app_scrap(binop,yes_math);break;
+
+case eq_eq:app_str("\\E");app_scrap(binop,yes_math);break;
+
+case and_and:app_str("\\W");app_scrap(binop,yes_math);break;
+
+case or_or:app_str("\\V");app_scrap(binop,yes_math);break;
+
+case plus_plus:app_str("\\PP");app_scrap(unop,yes_math);break;
+
+case minus_minus:app_str("\\MM");app_scrap(unop,yes_math);break;
+
+case minus_gt:app_str("\\MG");app_scrap(binop,yes_math);break;
+
+case gt_gt:app_str("\\GG");app_scrap(binop,yes_math);break;
+
+case lt_lt:app_str("\\LL");app_scrap(binop,yes_math);break;
+
+case dot_dot_dot:app_str("\\,\\ldots\\,");app_scrap(exp,yes_math);break;
+
+
+case colon_colon:app_str("\\DC");app_scrap(colcol,maybe_math);break;
+
+case period_ast:app_str("\\PA");app_scrap(binop,yes_math);break;
+
+#line 900 "cweave.ch"
+case minus_gt_ast:app_str("\\MGA");app_scrap(binop,yes_math);break;
+
+case numb_numb:app_str("\\NN");app_scrap(binop,yes_math);break;
+
+#line 3202 "cweave.w"
+
+/*:177*/
+#line 3130 "cweave.w"
+
+case thin_space:app_str("\\,");app_scrap(insert,maybe_math);break;
+
+case math_break:app(opt);app_str("0");
+app_scrap(insert,maybe_math);break;
+case line_break:app(force);app_scrap(insert,no_math);break;
+#line 863 "cweave.ch"
+case left_preproc:app(force);app(preproc_line);
+app_str("\\#");app_scrap(lproc,no_math);break;
+
+case preproc_space:app(' ');app_scrap(pp_space,maybe_math);break;
+case right_preproc:app(force);app_scrap(rproc,no_math);break;
+#line 3140 "cweave.w"
+case big_line_break:app(big_force);app_scrap(insert,no_math);break;
+case no_line_break:app(big_cancel);app(noop);app(break_space);
+app(noop);app(big_cancel);
+app_scrap(insert,no_math);break;
+#line 875 "cweave.ch"
+case pseudo_semi:app_scrap(semi,maybe_math);break;
+case pseudo_lbrace:app_str("\\phantom{");
+if(alternative)
+app_str("\\LBR");
+else
+app_str("\\{");
+app_str("}");
+app_scrap(lbrace,yes_math);
+break;
+case pseudo_rbrace:app_str("\\phantom{");
+if(alternative)
+app_str("\\RBR");
+else
+app_str("\\}");
+app_str("}");
+app_scrap(rbrace,yes_math);
+break;
+#line 3145 "cweave.w"
+case macro_arg_open:app_scrap(begin_arg,maybe_math);break;
+case macro_arg_close:app_scrap(end_arg,maybe_math);break;
+case join:app_str("\\J");app_scrap(insert,no_math);break;
+
+case output_defs_code:app(force);app_str("\\ATH");app(force);
+app_scrap(insert,no_math);break;
+
+default:app(inserted);app(next_control);
+app_scrap(insert,maybe_math);break;
+}
+
+/*:175*/
+#line 3066 "cweave.w"
+;
+next_control= get_next();
+if(next_control=='|'||next_control==begin_comment||
+next_control==begin_short_comment)return;
+}
+}
+
+/*:173*//*181:*/
+#line 3292 "cweave.w"
+
+void
+app_cur_id(scrapping)
+boolean scrapping;
+{
+name_pointer p= id_lookup(id_first,id_loc,normal);
+if(p->ilk<=quoted){
+app(id_flag+(int)(p-name_dir));
+if(scrapping)app_scrap(exp,p->ilk>=custom?yes_math:maybe_math);
+
+}else{
+app(res_flag+(int)(p-name_dir));
+if(scrapping)app_scrap(p->ilk,maybe_math);
+}
+}
+
+/*:181*//*182:*/
+#line 3313 "cweave.w"
+
+text_pointer
+C_translate()
+{
+text_pointer p;
+scrap_pointer save_base;
+save_base= scrap_base;scrap_base= scrap_ptr+1;
+C_parse(section_name);
+if(next_control!='|')err_print("! Missing '|' after C text");
+
+app_tok(cancel);app_scrap(insert,maybe_math);
+
+p= translate();
+if(scrap_ptr>max_scr_ptr)max_scr_ptr= scrap_ptr;
+scrap_ptr= scrap_base-1;scrap_base= save_base;
+return(p);
+}
+
+/*:182*//*183:*/
+#line 3335 "cweave.w"
+
+void
+outer_parse()
+{
+int bal;
+text_pointer p,q;
+while(next_control<format_code)
+if(next_control!=begin_comment&&next_control!=begin_short_comment)
+C_parse(ignore);
+else{
+boolean is_long_comment= (next_control==begin_comment);
+/*176:*/
+#line 3156 "cweave.w"
+
+if(scrap_ptr+safe_scrap_incr>scrap_info_end||
+tok_ptr+safe_tok_incr>tok_mem_end||
+text_ptr+safe_text_incr>tok_start_end){
+if(scrap_ptr>max_scr_ptr)max_scr_ptr= scrap_ptr;
+if(tok_ptr>max_tok_ptr)max_tok_ptr= tok_ptr;
+if(text_ptr>max_text_ptr)max_text_ptr= text_ptr;
+overflow("scrap/token/text");
+}
+
+/*:176*/
+#line 3346 "cweave.w"
+;
+app(cancel);app(inserted);
+if(is_long_comment)app_str("\\C{");
+
+else app_str("\\SHC{");
+
+bal= copy_comment(is_long_comment,1);next_control= ignore;
+while(bal>0){
+p= text_ptr;freeze_text;q= C_translate();
+
+app(tok_flag+(int)(p-tok_start));
+app_str("\\PB{");app(inner_tok_flag+(int)(q-tok_start));app_tok('}');
+
+if(next_control=='|'){
+bal= copy_comment(is_long_comment,bal);
+next_control= ignore;
+}
+else bal= 0;
+}
+app(force);app_scrap(insert,no_math);
+
+}
+}
+
+/*:183*//*188:*/
+#line 3439 "cweave.w"
+
+void
+push_level(p)
+text_pointer p;
+{
+if(stack_ptr==stack_end)overflow("stack");
+if(stack_ptr>stack){
+stack_ptr->end_field= cur_end;
+stack_ptr->tok_field= cur_tok;
+stack_ptr->mode_field= cur_mode;
+}
+stack_ptr++;
+if(stack_ptr>max_stack_ptr)max_stack_ptr= stack_ptr;
+cur_tok= *p;cur_end= *(p+1);
+}
+
+/*:188*//*189:*/
+#line 3459 "cweave.w"
+
+void
+pop_level()
+{
+cur_end= (--stack_ptr)->end_field;
+cur_tok= stack_ptr->tok_field;cur_mode= stack_ptr->mode_field;
+}
+
+/*:189*//*191:*/
+#line 3481 "cweave.w"
+
+eight_bits
+get_output()
+{
+sixteen_bits a;
+restart:while(cur_tok==cur_end)pop_level();
+a= *(cur_tok++);
+if(a>=0400){
+cur_name= a%id_flag+name_dir;
+switch(a/id_flag){
+case 2:return(res_word);
+case 3:return(section_code);
+case 4:push_level(a%id_flag+tok_start);goto restart;
+
+case 5:push_level(a%id_flag+tok_start);cur_mode= inner;goto restart;
+
+default:return(identifier);
+}
+}
+return(a);
+}
+
+/*:191*//*192:*/
+#line 3523 "cweave.w"
+
+void
+output_C()
+{
+token_pointer save_tok_ptr;
+text_pointer save_text_ptr;
+sixteen_bits save_next_control;
+text_pointer p;
+save_tok_ptr= tok_ptr;save_text_ptr= text_ptr;
+save_next_control= next_control;next_control= ignore;p= C_translate();
+app(inner_tok_flag+(int)(p-tok_start));
+out_str("\\PB{");make_output();out('}');
+
+if(text_ptr>max_text_ptr)max_text_ptr= text_ptr;
+if(tok_ptr>max_tok_ptr)max_tok_ptr= tok_ptr;
+text_ptr= save_text_ptr;tok_ptr= save_tok_ptr;
+next_control= save_next_control;
+}
+
+/*:192*//*194:*/
+#line 3547 "cweave.w"
+
+void
+make_output()
+{
+eight_bits a,
+b;
+int c;
+char scratch[longest_name];
+char*k,*k_limit;
+char*j;
+char*p;
+char delim;
+char*save_loc,*save_limit;
+name_pointer cur_section_name;
+boolean save_mode;
+app(end_translation);
+freeze_text;push_level(text_ptr-1);
+while(1){
+a= get_output();
+reswitch:switch(a){
+case end_translation:return;
+case identifier:case res_word:/*195:*/
+#line 3597 "cweave.w"
+
+out('\\');
+if(a==identifier){
+if(cur_name->ilk>=custom&&cur_name->ilk<=quoted&&!doing_format){
+for(p= cur_name->byte_start;p<(cur_name+1)->byte_start;p++)
+out(isxalpha(*p)?'x':*p);
+break;
+#line 923 "cweave.ch"
+}else if(is_tiny(cur_name))out('|');
+#line 3605 "cweave.w"
+
+else{delim= '.';
+for(p= cur_name->byte_start;p<(cur_name+1)->byte_start;p++)
+if(xislower(*p)){
+delim= '\\';break;
+}
+out(delim);
+}
+
+
+}
+#line 931 "cweave.ch"
+else out('&');
+#line 3617 "cweave.w"
+
+if(is_tiny(cur_name)){
+if(isxalpha((cur_name->byte_start)[0]))
+out('\\');
+out((cur_name->byte_start)[0]);
+}
+else out_name(cur_name);
+
+/*:195*/
+#line 3568 "cweave.w"
+;break;
+case section_code:/*199:*/
+#line 3695 "cweave.w"
+{
+out_str("\\X");
+
+cur_xref= (xref_pointer)cur_name->xref;
+if(cur_xref->num==file_flag){an_output= 1;cur_xref= cur_xref->xlink;}
+else an_output= 0;
+if(cur_xref->num>=def_flag){
+out_section(cur_xref->num-def_flag);
+if(phase==3){
+cur_xref= cur_xref->xlink;
+while(cur_xref->num>=def_flag){
+out_str(", ");
+out_section(cur_xref->num-def_flag);
+cur_xref= cur_xref->xlink;
+}
+}
+}
+else out('0');
+out(':');
+if(an_output)out_str("\\.{");
+
+/*200:*/
+#line 3721 "cweave.w"
+
+sprint_section_name(scratch,cur_name);
+k= scratch;
+k_limit= scratch+strlen(scratch);
+cur_section_name= cur_name;
+while(k<k_limit){
+b= *(k++);
+if(b=='@')/*201:*/
+#line 3756 "cweave.w"
+
+if(*k++!='@'){
+printf("\n! Illegal control code in section name: <");
+
+print_section_name(cur_section_name);printf("> ");mark_error;
+}
+
+/*:201*/
+#line 3728 "cweave.w"
+;
+if(an_output)
+switch(b){
+case' ':case'\\':case'#':case'%':case'$':case'^':
+case'{':case'}':case'~':case'&':case'_':
+out('\\');
+
+
+
+#line 949 "cweave.ch"
+
+
+
+#line 3740 "cweave.w"
+
+
+
+
+
+default:out(b);
+}
+#line 959 "cweave.ch"
+else if(b!='|')out(b);
+#line 3748 "cweave.w"
+else{
+/*202:*/
+#line 3769 "cweave.w"
+
+j= limit+1;*j= '|';delim= 0;
+while(1){
+if(k>=k_limit){
+printf("\n! C text in section name didn't end: <");
+
+print_section_name(cur_section_name);printf("> ");mark_error;break;
+}
+b= *(k++);
+if(b=='@'||(b=='\\'&&delim!=0))
+/*203:*/
+#line 3792 "cweave.w"
+{
+if(j>buffer+long_buf_size-4)overflow("buffer");
+*(++j)= b;*(++j)= *(k++);
+}
+
+/*:203*/
+#line 3779 "cweave.w"
+
+else{
+if(b=='\''||b=='"')
+if(delim==0)delim= b;
+else if(delim==b)delim= 0;
+if(b!='|'||delim!=0){
+if(j>buffer+long_buf_size-3)overflow("buffer");
+*(++j)= b;
+}
+else break;
+}
+}
+
+/*:202*/
+#line 3749 "cweave.w"
+;
+save_loc= loc;save_limit= limit;loc= limit+2;limit= j+1;
+*limit= '|';output_C();
+loc= save_loc;limit= save_limit;
+}
+}
+
+/*:200*/
+#line 3716 "cweave.w"
+;
+if(an_output)out_str(" }");
+out_str("\\X");
+}
+
+/*:199*/
+#line 3569 "cweave.w"
+;break;
+case math_rel:out_str("\\MRL{");
+
+case noop:case inserted:break;
+case cancel:case big_cancel:c= 0;b= a;
+while(1){
+a= get_output();
+if(a==inserted)continue;
+if((a<indent&&!(b==big_cancel&&a==' '))||a>big_force)break;
+if(a==indent)c++;else if(a==outdent)c--;
+else if(a==opt)a= get_output();
+}
+/*198:*/
+#line 3682 "cweave.w"
+
+for(;c>0;c--)out_str("\\1");
+
+for(;c<0;c++)out_str("\\2");
+
+
+/*:198*/
+#line 3581 "cweave.w"
+;
+goto reswitch;
+case indent:case outdent:case opt:case backup:case break_space:
+case force:case big_force:case preproc_line:/*196:*/
+#line 3628 "cweave.w"
+
+if(a<break_space||a==preproc_line){
+if(cur_mode==outer){
+out('\\');out(a-cancel+'0');
+
+
+
+
+
+if(a==opt){
+b= get_output();
+#line 939 "cweave.ch"
+if(b!='0'||force_lines==0)out(b);
+#line 3640 "cweave.w"
+else out_str("{-1}");
+}
+}else if(a==opt)b= get_output();
+}
+else/*197:*/
+#line 3652 "cweave.w"
+{
+b= a;save_mode= cur_mode;c= 0;
+while(1){
+a= get_output();
+if(a==inserted)continue;
+if(a==cancel||a==big_cancel){
+/*198:*/
+#line 3682 "cweave.w"
+
+for(;c>0;c--)out_str("\\1");
+
+for(;c<0;c++)out_str("\\2");
+
+
+/*:198*/
+#line 3658 "cweave.w"
+;
+goto reswitch;
+}
+if((a!=' '&&a<indent)||a==backup||a>big_force){
+if(save_mode==outer){
+if(out_ptr>out_buf+3&&strncmp(out_ptr-3,"\\Y\\B",4)==0)
+goto reswitch;
+/*198:*/
+#line 3682 "cweave.w"
+
+for(;c>0;c--)out_str("\\1");
+
+for(;c<0;c++)out_str("\\2");
+
+
+/*:198*/
+#line 3665 "cweave.w"
+;
+out('\\');out(b-cancel+'0');
+
+
+
+if(a!=end_translation)finish_line();
+}
+else if(a!=end_translation&&cur_mode==inner)out(' ');
+goto reswitch;
+}
+if(a==indent)c++;
+else if(a==outdent)c--;
+else if(a==opt)a= get_output();
+else if(a>b)b= a;
+}
+}
+
+/*:197*/
+#line 3644 "cweave.w"
+
+
+/*:196*/
+#line 3585 "cweave.w"
+;break;
+case quoted_char:out(*(cur_tok++));break;
+default:out(a);
+}
+}
+}
+
+/*:194*//*205:*/
+#line 3807 "cweave.w"
+
+void
+phase_two(){
+reset_input();if(show_progress)printf("\nWriting the output file...");
+
+section_count= 0;format_visible= 1;copy_limbo();
+finish_line();flush_buffer(out_buf,0,0);
+while(!input_has_ended)/*207:*/
+#line 3840 "cweave.w"
+{
+section_count++;
+/*208:*/
+#line 3858 "cweave.w"
+
+if(*(loc-1)!='*')out_str("\\M");
+
+else{
+while(*loc==' ')loc++;
+if(*loc=='*'){
+sec_depth= -1;
+loc++;
+}
+else{
+for(sec_depth= 0;xisdigit(*loc);loc++)
+sec_depth= sec_depth*10+(*loc)-'0';
+}
+while(*loc==' ')loc++;
+group_found= 1;
+out_str("\\N");
+
+{char s[32];sprintf(s,"{%d}",sec_depth+1);out_str(s);}
+if(show_progress)
+printf("*%d",section_count);update_terminal;
+}
+out_str("{");out_section(section_count);out_str("}");
+
+/*:208*/
+#line 3842 "cweave.w"
+;
+save_position;
+/*209:*/
+#line 3884 "cweave.w"
+do{
+next_control= copy_TeX();
+switch(next_control){
+case'|':init_stack;output_C();break;
+case'@':out('@');break;
+case TeX_string:case noop:
+case xref_roman:case xref_wildcard:case xref_typewriter:
+case section_name:loc-= 2;next_control= get_next();
+if(next_control==TeX_string)
+err_print("! TeX string should be in C text only");break;
+
+#line 972 "cweave.ch"
+case thin_space:case math_break:case ord:
+case line_break:case big_line_break:case no_line_break:case join:
+case pseudo_semi:case macro_arg_open:case macro_arg_close:
+case pseudo_lbrace:case pseudo_rbrace:
+case output_defs_code:
+err_print("! You can't do that in TeX text");break;
+
+#line 3901 "cweave.w"
+}
+}while(next_control<format_code);
+
+/*:209*/
+#line 3844 "cweave.w"
+;
+/*210:*/
+#line 3907 "cweave.w"
+
+space_checked= 0;
+while(next_control<=definition){
+init_stack;
+if(next_control==definition)/*213:*/
+#line 3965 "cweave.w"
+{
+if(save_line!=out_line||save_place!=out_ptr||space_checked)app(backup);
+if(!space_checked){emit_space_if_needed;save_position;}
+app_str("\\D");
+
+if((next_control= get_next())!=identifier)
+err_print("! Improper macro definition");
+
+else{
+app('$');app_cur_id(0);
+#line 992 "cweave.ch"
+if(*loc=='('){
+if(func_index)
+(name_dir+*(tok_ptr-1)%10240)->func_flag= 1;
+reswitch:switch(next_control= get_next()){
+case'(':case',':app(next_control);goto reswitch;
+case identifier:app_cur_id(0);goto reswitch;
+case')':app(next_control);next_control= get_next();break;
+default:err_print("! Improper macro definition");break;
+}
+}
+#line 3982 "cweave.w"
+else next_control= get_next();
+app_str("$ ");app(break_space);
+app_scrap(dead,no_math);
+}
+}
+
+/*:213*/
+#line 3911 "cweave.w"
+
+else/*214:*/
+#line 3988 "cweave.w"
+{
+doing_format= 1;
+if(*(loc-1)=='s'||*(loc-1)=='S')format_visible= 0;
+if(!space_checked){emit_space_if_needed;save_position;}
+app_str("\\F");
+
+next_control= get_next();
+if(next_control==identifier){
+app(id_flag+(int)(id_lookup(id_first,id_loc,normal)-name_dir));
+app(' ');
+app(break_space);
+next_control= get_next();
+if(next_control==identifier){
+app(id_flag+(int)(id_lookup(id_first,id_loc,normal)-name_dir));
+app_scrap(exp,maybe_math);app_scrap(semi,maybe_math);
+next_control= get_next();
+}
+}
+if(scrap_ptr!=scrap_info+2)err_print("! Improper format definition");
+
+}
+
+/*:214*/
+#line 3912 "cweave.w"
+;
+outer_parse();finish_C(format_visible);format_visible= 1;
+doing_format= 0;
+}
+
+/*:210*/
+#line 3845 "cweave.w"
+;
+/*216:*/
+#line 4017 "cweave.w"
+
+this_section= name_dir;
+if(next_control<=section_name){
+emit_space_if_needed;init_stack;
+if(next_control==begin_C)next_control= get_next();
+else{
+this_section= cur_section;
+/*217:*/
+#line 4037 "cweave.w"
+
+do next_control= get_next();
+while(next_control=='+');
+if(next_control!='='&&next_control!=eq_eq)
+err_print("! You need an = sign after the section name");
+
+else next_control= get_next();
+if(out_ptr>out_buf+1&&*out_ptr=='Y'&&*(out_ptr-1)=='\\')app(backup);
+
+
+app(section_flag+(int)(this_section-name_dir));
+cur_xref= (xref_pointer)this_section->xref;
+if(cur_xref->num==file_flag)cur_xref= cur_xref->xlink;
+app_str("${}");
+if(cur_xref->num!=section_count+def_flag){
+app_str("\\mathrel+");
+this_section= name_dir;
+}
+app_str("\\E");
+
+app_str("{}$");
+app(force);app_scrap(dead,no_math);
+
+
+/*:217*/
+#line 4025 "cweave.w"
+;
+}
+while(next_control<=section_name){
+outer_parse();
+/*218:*/
+#line 4061 "cweave.w"
+
+if(next_control<section_name){
+err_print("! You can't do that in C text");
+
+next_control= get_next();
+}
+else if(next_control==section_name){
+app(section_flag+(int)(cur_section-name_dir));
+app_scrap(section_scrap,maybe_math);
+next_control= get_next();
+}
+
+/*:218*/
+#line 4029 "cweave.w"
+;
+}
+finish_C(1);
+}
+
+/*:216*/
+#line 3846 "cweave.w"
+;
+/*219:*/
+#line 4076 "cweave.w"
+
+if(this_section>name_dir){
+cur_xref= (xref_pointer)this_section->xref;
+if(cur_xref->num==file_flag){an_output= 1;cur_xref= cur_xref->xlink;}
+else an_output= 0;
+if(cur_xref->num>def_flag)
+cur_xref= cur_xref->xlink;
+footnote(def_flag);footnote(cite_flag);footnote(0);
+}
+
+/*:219*/
+#line 3847 "cweave.w"
+;
+/*223:*/
+#line 4134 "cweave.w"
+
+out_str("\\fi");finish_line();
+
+flush_buffer(out_buf,0,0);
+
+/*:223*/
+#line 3848 "cweave.w"
+;
+}
+
+/*:207*/
+#line 3814 "cweave.w"
+;
+}
+
+/*:205*//*212:*/
+#line 3930 "cweave.w"
+
+void
+finish_C(visible)
+boolean visible;
+{
+text_pointer p;
+if(visible){
+out_str("\\B");app_tok(force);app_scrap(insert,no_math);
+p= translate();
+
+app(tok_flag+(int)(p-tok_start));make_output();
+if(out_ptr>out_buf+1)
+if(*(out_ptr-1)=='\\')
+
+
+
+if(*out_ptr=='6')out_ptr-= 2;
+else if(*out_ptr=='7')*out_ptr= 'Y';
+out_str("\\par");finish_line();
+}
+if(text_ptr>max_text_ptr)max_text_ptr= text_ptr;
+if(tok_ptr>max_tok_ptr)max_tok_ptr= tok_ptr;
+if(scrap_ptr>max_scr_ptr)max_scr_ptr= scrap_ptr;
+tok_ptr= tok_mem+1;text_ptr= tok_start+1;scrap_ptr= scrap_info;
+
+}
+
+/*:212*//*221:*/
+#line 4101 "cweave.w"
+
+void
+footnote(flag)
+sixteen_bits flag;
+{
+xref_pointer q;
+if(cur_xref->num<=flag)return;
+finish_line();out('\\');
+
+
+
+out(flag==0?'U':flag==cite_flag?'Q':'A');
+/*222:*/
+#line 4121 "cweave.w"
+
+q= cur_xref;if(q->xlink->num>flag)out('s');
+while(1){
+out_section(cur_xref->num-flag);
+cur_xref= cur_xref->xlink;
+if(cur_xref->num<=flag)break;
+if(cur_xref->xlink->num>flag)out_str(", ");
+else{out_str("\\ET");
+
+if(cur_xref!=q->xlink)out('s');
+}
+}
+
+/*:222*/
+#line 4113 "cweave.w"
+;
+out('.');
+}
+
+/*:221*//*225:*/
+#line 4150 "cweave.w"
+
+void
+phase_three(){
+if(no_xref){
+finish_line();
+out_str("\\end");
+
+finish_line();
+}
+else{
+phase= 3;if(show_progress)printf("\nWriting the index...");
+
+finish_line();
+if((idx_file= fopen(idx_file_name,"w"))==NULL)
+fatal("! Cannot open index file ",idx_file_name);
+
+if(change_exists){
+/*227:*/
+#line 4201 "cweave.w"
+{
+
+k_section= 0;
+while(!changed_section[++k_section]);
+out_str("\\ch ");
+
+out_section(k_section);
+while(k_section<section_count){
+while(!changed_section[++k_section]);
+out_str(", ");out_section(k_section);
+}
+out('.');
+}
+
+/*:227*/
+#line 4167 "cweave.w"
+;finish_line();finish_line();
+}
+out_str("\\inx");finish_line();
+
+active_file= idx_file;
+/*229:*/
+#line 4232 "cweave.w"
+{
+int c;
+for(c= 0;c<=255;c++)bucket[c]= NULL;
+for(h= hash;h<=hash_end;h++){
+next_name= *h;
+while(next_name){
+cur_name= next_name;next_name= cur_name->link;
+if(cur_name->xref!=(char*)xmem){
+c= (eight_bits)((cur_name->byte_start)[0]);
+if(xisupper(c))c= tolower(c);
+blink[cur_name-name_dir]= bucket[c];bucket[c]= cur_name;
+}
+}
+}
+}
+
+/*:229*/
+#line 4172 "cweave.w"
+;
+/*238:*/
+#line 4348 "cweave.w"
+
+sort_ptr= scrap_info;unbucket(1);
+while(sort_ptr>scrap_info){
+cur_depth= sort_ptr->depth;
+if(blink[sort_ptr->head-name_dir]==0||cur_depth==infinity)
+/*240:*/
+#line 4373 "cweave.w"
+{
+cur_name= sort_ptr->head;
+do{
+out_str("\\I");
+
+/*241:*/
+#line 4385 "cweave.w"
+
+#line 1036 "cweave.ch"
+switch(cur_name->ilk){
+case normal:
+if(is_tiny(cur_name)&&!cur_name->func_flag)
+out_str("\\|");
+else{char*j;
+for(j= cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
+if(xislower(*j))goto lowcase;
+out_str("\\.");break;
+lowcase:out_str("\\\\");
+}
+break;
+
+
+
+case roman:break;
+case wildcard:out_str("\\9");break;
+
+case typewriter:out_str("\\.");break;
+
+case custom:case quoted:{char*j;out_str("$\\");
+for(j= cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
+out(isxalpha(*j)?'x':*j);
+out('$');
+goto name_done;
+}
+default:out_str("\\&");
+
+}
+out_name(cur_name);
+name_done:
+if(cur_name->func_flag)
+out_str("(\\,)");
+#line 4414 "cweave.w"
+
+/*:241*/
+#line 4378 "cweave.w"
+;
+/*242:*/
+#line 4418 "cweave.w"
+
+/*244:*/
+#line 4436 "cweave.w"
+
+this_xref= (xref_pointer)cur_name->xref;cur_xref= xmem;
+do{
+next_xref= this_xref->xlink;this_xref->xlink= cur_xref;
+cur_xref= this_xref;this_xref= next_xref;
+}while(this_xref!=xmem);
+
+/*:244*/
+#line 4419 "cweave.w"
+;
+do{
+out_str(", ");cur_val= cur_xref->num;
+if(cur_val<def_flag)out_section(cur_val);
+else{out_str("\\[");out_section(cur_val-def_flag);out(']');}
+
+cur_xref= cur_xref->xlink;
+}while(cur_xref!=xmem);
+out('.');finish_line();
+
+/*:242*/
+#line 4379 "cweave.w"
+;
+cur_name= blink[cur_name-name_dir];
+}while(cur_name);
+--sort_ptr;
+}
+
+/*:240*/
+#line 4353 "cweave.w"
+
+else/*239:*/
+#line 4357 "cweave.w"
+{
+eight_bits c;
+next_name= sort_ptr->head;
+do{
+cur_name= next_name;next_name= blink[cur_name-name_dir];
+cur_byte= cur_name->byte_start+cur_depth;
+if(cur_byte==(cur_name+1)->byte_start)c= 0;
+else{
+c= (eight_bits)*cur_byte;
+if(xisupper(c))c= tolower(c);
+}
+blink[cur_name-name_dir]= bucket[c];bucket[c]= cur_name;
+}while(next_name);
+--sort_ptr;unbucket(cur_depth+1);
+}
+
+/*:239*/
+#line 4354 "cweave.w"
+;
+}
+
+/*:238*/
+#line 4173 "cweave.w"
+;
+finish_line();fclose(active_file);
+active_file= tex_file;
+out_str("\\fin");finish_line();
+
+if((scn_file= fopen(scn_file_name,"w"))==NULL)
+fatal("! Cannot open section file ",scn_file_name);
+
+active_file= scn_file;
+/*247:*/
+#line 4467 "cweave.w"
+section_print(root)
+
+/*:247*/
+#line 4182 "cweave.w"
+;
+finish_line();fclose(active_file);
+active_file= tex_file;
+if(group_found)out_str("\\con");else out_str("\\end");
+
+
+finish_line();
+fclose(active_file);
+}
+if(show_happiness)printf("\nDone.");
+check_complete();
+}
+
+/*:225*//*237:*/
+#line 4330 "cweave.w"
+
+void
+unbucket(d)
+eight_bits d;
+{
+int c;
+
+for(c= 100+128;c>=0;c--)if(bucket[collate[c]]){
+
+if(sort_ptr>=scrap_info_end)overflow("sorting");
+sort_ptr++;
+if(sort_ptr>max_sort_ptr)max_sort_ptr= sort_ptr;
+if(c==0)sort_ptr->depth= infinity;
+else sort_ptr->depth= d;
+sort_ptr->head= bucket[collate[c]];bucket[collate[c]]= NULL;
+}
+}
+
+/*:237*//*246:*/
+#line 4450 "cweave.w"
+
+void
+section_print(p)
+name_pointer p;
+{
+if(p){
+section_print(p->llink);out_str("\\I");
+
+tok_ptr= tok_mem+1;text_ptr= tok_start+1;scrap_ptr= scrap_info;init_stack;
+app(p-name_dir+section_flag);make_output();
+footnote(cite_flag);
+footnote(0);
+finish_line();
+section_print(p->rlink);
+}
+}
+
+/*:246*//*248:*/
+#line 4472 "cweave.w"
+
+void
+print_stats(){
+printf("\nMemory usage statistics:\n");
+
+printf("%ld names (out of %ld)\n",
+(long)(name_ptr-name_dir),(long)max_names);
+printf("%ld cross-references (out of %ld)\n",
+(long)(xref_ptr-xmem),(long)max_refs);
+printf("%ld bytes (out of %ld)\n",
+(long)(byte_ptr-byte_mem),(long)max_bytes);
+printf("Parsing:\n");
+printf("%ld scraps (out of %ld)\n",
+(long)(max_scr_ptr-scrap_info),(long)max_scraps);
+printf("%ld texts (out of %ld)\n",
+(long)(max_text_ptr-tok_start),(long)max_texts);
+printf("%ld tokens (out of %ld)\n",
+(long)(max_tok_ptr-tok_mem),(long)max_toks);
+printf("%ld levels (out of %ld)\n",
+(long)(max_stack_ptr-stack),(long)stack_size);
+printf("Sorting:\n");
+printf("%ld levels (out of %ld)\n",
+(long)(max_sort_ptr-scrap_info),(long)max_scraps);
+}
+
+#line 1075 "cweave.ch"
+/*:248*/
diff --git a/web/c_cpp/c2cweb/cweb/cweave.ch b/web/c_cpp/c2cweb/cweb/cweave.ch
new file mode 100644
index 0000000000..035de5a5e3
--- /dev/null
+++ b/web/c_cpp/c2cweb/cweb/cweave.ch
@@ -0,0 +1,1095 @@
+This file is part of the c2cweb package Version 1.5
+
+This is a change file for CWEB's CWEAVE (Ver. 3.4g June 1996)
+
+modified by Werner Lemberg (a7971428@@unet.univie.ac.at) 10-Nov-1996
+
+===============================================================================
+
+An exclamation mark (!) removes a bug in the original CWEAVE which caused
+unbalanced braces sometimes.
+
+One star (*) marks changes of the productions if switch a is set --
+please look at an output to see what. Additionally cwebmaca.tex will be used
+by TeX instead of cwebmac.tex .
+
+Two stars (**) mark changes to the index routines: function definitions will
+now have () after the identifier if the i switch is on (this will work properly
+only if you don't have function names identical to names of variables,
+structures etc.).
+
+Three stars (***) change the debugging output slightly.
+
+A (+) enables the dollar sign `$' in identifiers; some compilers allow it,
+and it doesn't harm in the output.
+
+Two plus (++) improve the processing of #define statements (weird things
+like '#define short int'). Two new control codes are introduced: @{ and @}
+(i.e. invisible braces). You will need this if you have unbalanced braces due
+to #ifdef ... #endif statements. The concatenation operator ## will be now
+recognized.
+
+Three plus (+++) implement exotic cases of C++ (look e.g. for "iostream.h").
+
+
+These changes are not perfect yet; if you don't like some things, remove the
+specified sections. (Or better, improve them and send the new change file(s)
+to me :-)
+
+
+@x in limbo
+\let\maybe=\iftrue
+@y
+\let\maybe=\iffalse
+@z
+
+@x section 1
+@d banner "This is CWEAVE (Version 3.4)\n"
+@y
+@d banner "This is CWEAVE (Version 3.4) modified by Werner Lemberg (V1.5)\n"
+@z
+
+@x section 4
+@d max_bytes 90000 /* the number of bytes in identifiers,
+ index entries, and section names */
+@d max_names 4000 /* number of identifiers, strings, section names;
+ must be less than 10240; used in |"common.w"| */
+@d max_sections 2000 /* greater than the total number of sections */
+@d hash_size 353 /* should be prime */
+@d buf_size 100 /* maximum length of input line, plus one */
+@d longest_name 1000 /* section names and strings shouldn't be longer than this */
+@d long_buf_size (buf_size+longest_name)
+@d line_length 80 /* lines of \TEX/ output have at most this many characters;
+ should be less than 256 */
+@d max_refs 20000 /* number of cross-references; must be less than 65536 */
+@d max_toks 20000 /* number of symbols in \CEE/ texts being parsed;
+ must be less than 65536 */
+@d max_texts 4000 /* number of phrases in \CEE/ texts being parsed;
+ must be less than 10240 */
+@d max_scraps 2000 /* number of tokens in \CEE/ texts being parsed */
+@d stack_size 400 /* number of simultaneous output levels */
+@y
+@d max_bytes 225000 /* the number of bytes in identifiers,
+ index entries, and section names */
+@d max_names 10000 /* number of identifiers, strings, section names;
+ must be less than 10240; used in |"common.w"| */
+@d max_sections 2000 /* greater than the total number of sections */
+@d hash_size 353 /* should be prime */
+@d buf_size 400 /* maximum length of input line, plus one */
+@d longest_name 1000 /* section names and strings shouldn't be longer than this */
+@d long_buf_size (buf_size+longest_name)
+@d line_length 100 /* lines of \TEX/ output have at most this many characters;
+ should be less than 256 */
+@d max_refs 20000 /* number of cross-references; must be less than 65536 */
+@d max_toks 65000 /* number of symbols in \CEE/ texts being parsed;
+ must be less than 65536 */
+@d max_texts 10200 /* number of phrases in \CEE/ texts being parsed;
+ must be less than 10240 */
+@d max_scraps 65000 /* number of tokens in \CEE/ texts being parsed */
+@d stack_size 10000 /* number of simultaneous output levels */
+@z
+
+**
+
+@x section 16
+@d ilk dummy.Ilk
+@y
+@d ilk dummy.dummy1.Ilk
+@d func_flag dummy.dummy1.Func_flag
+@z
+
+++
+
+@x section 30
+@d new_section 0231 /* control code for `\.{@@\ }' and `\.{@@*}' */
+@y
+@d new_section 0231 /* control code for `\.{@@\ }' and `\.{@@*}' */
+@d pseudo_lbrace 022 /* control code for `\.{@@\{}' */
+@d pseudo_rbrace 023 /* control code for `\.{@@\}}' */
+@z
+
+++
+
+@x section 32
+ccode['+']=no_line_break; ccode[';']=pseudo_semi;
+ccode['[']=macro_arg_open; ccode[']']=macro_arg_close;
+@y
+ccode['+']=no_line_break; ccode[';']=pseudo_semi;
+ccode['{']=pseudo_lbrace; ccode['}']=pseudo_rbrace;
+ccode['[']=macro_arg_open; ccode[']']=macro_arg_close;
+@z
+
++
+
+@x section 39
+@d isxalpha(c) ((c)=='_') /* non-alpha character allowed in identifier */
+@y
+@d isxalpha(c) ((c)=='_' || (c)=='$')
+ /* non-alpha characters allowed in identifier */
+@z
+
+++
+
+@x section 40
+eight_bits
+get_next() /* produces the next input token */
+{@+eight_bits c; /* the current character */
+ while (1) {
+ @<Check if we're at the end of a preprocessor command@>;
+ if (loc>limit && get_line()==0) return(new_section);
+ c=*(loc++);
+ if (xisdigit(c) || c=='\\' || c=='.') @<Get a constant@>@;
+ else if (c=='\'' || c=='"' || (c=='L'&&(*loc=='\'' || *loc=='"'))@|
+ || (c=='<' && sharp_include_line==1))
+ @<Get a string@>@;
+ else if (xisalpha(c) || isxalpha(c) || ishigh(c))
+ @<Get an identifier@>@;
+ else if (c=='@@') @<Get control code and possible section name@>@;
+ else if (xisspace(c)) continue; /* ignore spaces and tabs */
+ if (c=='#' && loc==buffer+1) @<Raise preprocessor flag@>;
+ mistake: @<Compress two-symbol operator@>@;
+ return(c);
+ }
+}
+@y
+eight_bits
+get_next() /* produces the next input token */
+{@+eight_bits c; /* the current character */
+ int blank_count=0; /* number of leading blanks */
+
+ if (loc<limit && preprocessing && (define_pos==2 || define_pos==4) &&
+ xisspace(*loc)) {
+ define_pos=5;
+ return(preproc_space);
+ }
+
+ while (1) {
+ @<Check if we're at the end of a preprocessor command@>;
+ if (loc>limit && get_line()==0) return(new_section);
+
+ if(loc==buffer) {
+ blank_count=0;
+ while((*loc==' ' || *loc=='\t') && loc<limit) {
+ blank_count++; loc++;
+ }
+ }
+
+ c=*(loc++);
+ if (xisdigit(c) || c=='\\' || c=='.') @<Get a constant@>@;
+ else if (c=='\'' || c=='"' || (c=='L'&&(*loc=='\'' || *loc=='"'))@|
+ || (c=='<' && sharp_include_line==1))
+ @<Get a string@>@;
+ else if (xisalpha(c) || isxalpha(c) || ishigh(c))
+ @<Get an identifier@>@;
+ else if (c=='@@') @<Get control code and possible section name@>@;
+ else if (xisspace(c)) continue; /* ignore spaces and tabs */
+ if (c=='#' && loc==buffer+1+blank_count && !preprocessing)
+ @<Raise preprocessor flag@>;
+ mistake: @<Compress two-symbol operator@>@;
+ if(preprocessing) {
+ if (c=='(' && define_pos==2 && !xisspace(*(loc-2)))
+ define_pos=3;
+ else if (c==')' && define_pos==3)
+ define_pos=4;
+ }
+ return(c);
+ }
+}
+@z
+
+++
+
+@x section 41
+@d left_preproc ord /* begins a preprocessor command */
+@d right_preproc 0217 /* ends a preprocessor command */
+
+@<Glob...@>=
+boolean preprocessing=0; /* are we scanning a preprocessor command? */
+@y
+@d left_preproc ord /* begins a preprocessor command */
+@d right_preproc 0217 /* ends a preprocessor command */
+@d preproc_space '\b' /* emitted before the macro sustitution */
+@d numb_numb '\f' /* `\.{\#\#}'\,; the concatenation operator */
+
+@<Glob...@>=
+boolean preprocessing=0; /* are we scanning a preprocessor command? */
+int define_pos=0;
+ /* at which position we are while scanning a macro definition */
+@z
+
+++
+
+@x section 45
+ if (loc>=limit && preprocessing) {
+ preprocessing=sharp_include_line=0;
+ return(right_preproc);
+ }
+@y
+ if (loc>=limit && preprocessing) {
+ preprocessing=sharp_include_line=define_pos=0;
+ return(right_preproc);
+ }
+@z
+
+++
+
+@x section 46
+ case '!': if (*loc=='=') compress(not_eq); break;
+@y
+ case '!': if (*loc=='=') compress(not_eq); break;
+ case '#': if (*loc=='#') compress(numb_numb); break;
+@z
+
+++
+
+@x section 47
+ id_first=--loc;
+ while (isalpha(*++loc) || isdigit(*loc) || isxalpha(*loc) || ishigh(*loc));
+ id_loc=loc; return(identifier);
+@y
+ id_first=--loc;
+
+ if (preprocessing) {
+ if (define_pos==1)
+ define_pos=2;
+ else if (strncmp(loc, "define", 6)==0 && xisspace(*(loc+6)))
+ define_pos=1;
+ }
+
+ while (isalpha(*++loc) || isdigit(*loc) || isxalpha(*loc) || ishigh(*loc));
+ id_loc=loc; return(identifier);
+@z
+
+!
+
+@x section 77
+int out_line; /* number of next line to be output */
+@y
+int out_line; /* number of next line to be output */
+
+boolean in_math = 0;
+boolean escape = 0;
+int math_brace_count = 0;
+@z
+
+*
+
+@x section 80
+out_ptr=out_buf+1; out_line=1; active_file=tex_file;
+*out_ptr='c'; tex_printf("\\input cwebma");
+@y
+out_ptr=out_buf+1; out_line=1; active_file=tex_file;
+if(alternative) {
+ *out_ptr='a';
+ tex_printf("\\input cwebmac");
+} else {
+ *out_ptr='c';
+ tex_printf("\\input cwebma");
+}
+@z
+
+!
+
+@x section 81
+@d out(c) {if (out_ptr>=out_buf_end) break_out(); *(++out_ptr)=c;}
+
+@c
+@y
+@c
+void
+out(c)
+char c;
+{
+ if (out_ptr >= out_buf_end)
+ break_out();
+
+ if(!escape) {
+ if(in_math) {
+ if(c == '{')
+ math_brace_count++;
+ else if(c == '}') {
+ math_brace_count--;
+ if(math_brace_count < 0) {
+ math_brace_count = 0;
+ return;
+ }
+ }
+ }
+ if(c == '$') {
+ while(math_brace_count > 0) {
+ *(++out_ptr) = '}';
+ math_brace_count--;
+ }
+ in_math = 1 - in_math;
+ }
+ }
+
+ if(c == '\\' && !escape)
+ escape = 1;
+ else
+ escape = 0;
+
+ *(++out_ptr) = c;
+ return;
+}
+@z
+
+*
+
+@x section 97
+@d tag 29 /* denotes a statement label */
+@y
+@d tag 29
+ /* denotes a statement label (if |alternative| is set, only a case label) */
+@z
+
+*, ++
+
+@x section 97
+@d end_arg 59 /* \.{@@]} */
+@y
+@d end_arg 59 /* \.{@@]} */
+@d label 60 /* denotes a label; used if |alternative| is set */
+@d do_head 61 /* used if |alternative| is set */
+@d pp_space 62 /* denotes the start point of a macro replacement text */
+@z
+
+*, ++
+
+@x section 98
+ strcpy(cat_name[end_arg],@q[@>"@@]");
+@y
+ strcpy(cat_name[end_arg],@q[@>"@@]");
+ strcpy(cat_name[label],"label"); /* used if |alternative| is set */
+ strcpy(cat_name[do_head], "do_head"); /* used if |alternative| is set */
+ strcpy(cat_name[pp_space], "#_");
+@z
+
+++ section 101
+
+@x
+\.:&|colon|: \.:&maybe\cr
+\.\# (within line)&|unorbinop|: \.{\\\#}&yes\cr
+@y
+\.:&|colon|: \.:&maybe\cr
+\.{\#\#}&|binop|: \.{\\NN}&yes\cr
+\.\# (within line)&|unorbinop|: \.{\\\#}&yes\cr
+@z
+
+*
+
+@x section 101
+@i prod.w
+@y
+@i prod-alt.w
+@z
+
+*
+
+@x section 110
+ case raw_int: @<Cases for |raw_int|@>; @+break;
+@y
+ case raw_int: @<Cases for |raw_int|@>; @+break;
+ case label: @<Cases for |label|@>; @+break;
+ case do_head: @<Cases for |do_head|@>; @+break;
+@z
+
+++
+
+@x section 112
+void
+make_reserved(p) /* make the first identifier in |p->trans| like |int| */
+scrap_pointer p;
+{
+ sixteen_bits tok_value; /* the name of this identifier, plus its flag*/
+ token_pointer tok_loc; /* pointer to |tok_value| */
+ if ((tok_loc=find_first_ident(p->trans))==no_ident_found)
+ return; /* this should not happen */
+ tok_value=*tok_loc;
+ for (;p<=scrap_ptr; p==lo_ptr? p=hi_ptr: p++) {
+ if (p->cat==exp) {
+ if (**(p->trans)==tok_value) {
+ p->cat=raw_int;
+ **(p->trans)=tok_value%id_flag+res_flag;
+ }
+ }
+ }
+ (name_dir+(sixteen_bits)(tok_value%id_flag))->ilk=raw_int;
+ *tok_loc=tok_value%id_flag+res_flag;
+}
+@y
+void
+make_reserved(p, cat) /* make the first identifier in |p->trans| like |cat| */
+scrap_pointer p;
+eight_bits cat;
+{
+ sixteen_bits tok_value; /* the name of this identifier, plus its flag*/
+ token_pointer tok_loc; /* pointer to |tok_value| */
+ if ((tok_loc=find_first_ident(p->trans))==no_ident_found)
+ return; /* this should not happen */
+ tok_value=*tok_loc;
+ for (;p<=scrap_ptr; p==lo_ptr? p=hi_ptr: p++) {
+ if (p->cat==exp || p->cat==int_like || p->cat==const_like) {
+ if (**(p->trans)==tok_value) {
+ p->cat=cat;
+ **(p->trans)=tok_value%id_flag+res_flag;
+ }
+ }
+ }
+ (name_dir+(sixteen_bits)(tok_value%id_flag))->ilk=cat;
+ *tok_loc=tok_value%id_flag+res_flag;
+}
+@z
+
+*
+
+@x section 117
+ make_underlined (pp); squash(pp,2,tag,0,7);
+@y
+ make_underlined (pp);
+ if(alternative)
+ squash(pp,2,label,0,7);
+ else
+ squash(pp,2,tag,0,7);
+@z
+
++++
+
+@x section 125
+ else squash(pp,2,int_like,-2,32);
+}
+@y
+ else squash(pp,2,int_like,-2,32);
+}
+else if (cat1==binop && cat2==exp) squash(pp,3,int_like,-2,117);
+@z
+
+++
+
+@x section 128
+if (cat1==decl_head)
+ if ((cat2==exp&&cat3!=lpar&&cat3!=exp)||cat2==int_like) {
+ make_underlined(pp+2); make_reserved(pp+2);
+ big_app2(pp+1); reduce(pp+1,2,decl_head,0,42);
+ }
+ else if (cat2==semi) {
+ big_app1(pp); big_app(' '); big_app2(pp+1); reduce(pp,3,decl,-1,43);
+ }
+@y
+if (cat1==decl_head) {
+ if ((cat2==exp&&cat3!=lpar&&cat3!=exp)||cat2==int_like) {
+ make_underlined(pp+2); make_reserved(pp+2, raw_int);
+ big_app2(pp+1); reduce(pp+1,2,decl_head,0,42);
+ }
+ else if (cat2==semi) {
+ big_app1(pp); big_app(' '); big_app2(pp+1); reduce(pp,3,decl,-1,43);
+ }
+}
+else if (cat1==exp && !preprocessing && cat2!=lpar) {
+ make_reserved(pp+1, raw_int);
+ squash(pp+1,1,raw_int,-2,116);
+}
+@z
+
+*
+
+@x section 129
+if (cat1==lbrace) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,struct_head,0,44);
+}
+else if (cat1==exp||cat1==int_like) {
+ if (cat2==lbrace || cat2==semi) {
+ make_underlined(pp+1); make_reserved(pp+1);
+ big_app1(pp); big_app(' '); big_app1(pp+1);
+ if (cat2==semi) reduce(pp,2,decl_head,0,45);
+ else {
+ big_app(' '); big_app1(pp+2);reduce(pp,3,struct_head,0,46);
+ }
+ }
+ else if (cat2==colon) squash(pp+2,1,base,-1,47);
+ else if (cat2!=base) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,int_like,-2,48);
+ }
+}
+@y
+if (cat1==lbrace) {
+ if(alternative) {
+ big_app1(pp); big_app(indent); big_app(force); big_app(backup);
+ big_app1(pp+1); reduce(pp,2,struct_head,0,44);
+ } else {
+ big_app1(pp); big_app(' '); big_app1(pp+1);
+ reduce(pp,2,struct_head,0,44);
+ }
+}
+else if (cat1==exp||cat1==int_like) {
+ if (cat2==lbrace || cat2==semi) {
+ make_underlined(pp+1); make_reserved(pp+1, raw_int);
+ big_app1(pp); big_app(' '); big_app1(pp+1);
+ if (cat2==semi) reduce(pp,2,decl_head,-1,45);
+ else {
+ if(alternative) {
+ big_app(indent); big_app(force); big_app(backup); big_app1(pp+2);
+ reduce(pp,3,struct_head,0,46);
+ } else {
+ big_app(' '); big_app1(pp+2); reduce(pp,3,struct_head,0,46);
+ }
+ }
+ }
+ else if (cat2==colon) squash(pp+2,1,base,-1,47);
+ else if (!(cat2==base || cat2==raw_int ||
+ cat2==int_like || cat2==const_like)) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,int_like,-2,48);
+ }
+}
+@z
+
+*
+
+@x section 130
+ big_app1(pp); big_app(indent); big_app(force); big_app1(pp+1);
+ big_app(outdent); big_app(force); big_app1(pp+2);
+ reduce(pp,3,int_like,-2,49);
+@y
+ if(alternative) {
+ big_app1(pp); big_app1(pp+1);
+ big_app(force); big_app(backup); big_app1(pp+2); big_app(' ');
+ big_app(outdent); reduce(pp,3,int_like,-2,49);
+ } else {
+ big_app1(pp); big_app(indent); big_app(force); big_app1(pp+1);
+ big_app(outdent); big_app(force); big_app1(pp+2);
+ reduce(pp,3,int_like,-2,49);
+ }
+@z
+
+*
+
+@x section 133
+ big_app(force); big_app1(pp); big_app(indent); big_app(force);
+ big_app1(pp+1); big_app(force); big_app(backup); big_app1(pp+2);
+ big_app(outdent); big_app(force); reduce(pp,3,stmt,-1,55);
+@y
+ if(alternative) {
+ big_app(indent); big_app(force); big_app(backup); big_app1(pp);
+ app(noop); big_app(cancel); big_app1(pp+1); big_app(force); big_app(backup);
+ big_app1(pp+2); big_app(outdent); big_app(force); reduce(pp,3,stmt,-2,55);
+ } else {
+ big_app(force); big_app1(pp); big_app(indent); big_app(force);
+ big_app1(pp+1); big_app(force); big_app(backup); big_app1(pp+2);
+ big_app(outdent); big_app(force); reduce(pp,3,stmt,-1,55);
+ }
+@z
+
+*
+
+@x section 136
+ big_app(force); big_app1(pp); big_app(indent); big_app(break_space);
+ big_app1(pp+1); big_app(outdent); big_app(force);
+ reduce(pp,2,stmt,-1,60);
+@y
+ if(alternative) {
+ big_app(force); big_app1(pp); big_app(indent); big_app(force);
+ big_app1(pp+1); big_app(outdent); big_app(force);
+ reduce(pp,2,stmt,-1,60);
+ } else {
+ big_app(force); big_app1(pp); big_app(indent); big_app(break_space);
+ big_app1(pp+1); big_app(outdent); big_app(force);
+ reduce(pp,2,stmt,-1,60);
+ }
+@z
+
+*
+
+@x section 137
+ big_app(force); big_app1(pp); big_app(break_space); app(noop);
+ big_app(cancel); big_app1(pp+1); big_app(force);
+ reduce(pp,2,stmt,-1,61);
+@y
+ if(alternative) {
+ big_app(force); big_app1(pp); big_app(break_space);
+ big_app1(pp+1); big_app(force);
+ reduce(pp,2,stmt,-1,61);
+ } else {
+ big_app(force); big_app1(pp); big_app(break_space); app(noop);
+ big_app(cancel); big_app1(pp+1); big_app(force);
+ reduce(pp,2,stmt,-1,61);
+ }
+@z
+
+*
+
+@x section 138
+ big_app(force); big_app1(pp); big_app(indent); big_app(break_space);
+ big_app1(pp+1); big_app(outdent); big_app(force); big_app1(pp+2);
+ if (cat3==if_like) {
+ big_app(' '); big_app1(pp+3); reduce(pp,4,if_like,0,63);
+ }@+else reduce(pp,3,else_like,0,64);
+@y
+ if(alternative) {
+ big_app(force); big_app1(pp); big_app(indent); big_app(force);
+ big_app1(pp+1); big_app(outdent); big_app(force); big_app1(pp+2);
+ } else {
+ big_app(force); big_app1(pp); big_app(indent); big_app(break_space);
+ big_app1(pp+1); big_app(outdent); big_app(force); big_app1(pp+2);
+ }
+ if (cat3==if_like) {
+ big_app(' '); big_app1(pp+3); reduce(pp,4,if_like,0,63);
+ }@+else reduce(pp,3,else_like,0,64);
+@z
+
+*
+
+@x section 139
+ big_app(force); big_app1(pp); big_app(break_space); app(noop);
+ big_app(cancel); big_app1(pp+1); big_app(force); big_app1(pp+2);
+ if (cat3==if_like) {
+ big_app(' '); big_app1(pp+3); reduce(pp,4,if_like,0,66);
+ }@+else reduce(pp,3,else_like,0,67);
+@y
+ if(alternative) {
+ big_app(force); big_app1(pp); big_app(break_space);
+ big_app1(pp+1); big_app(force); big_app1(pp+2);
+ } else {
+ big_app(force); big_app1(pp); big_app(break_space); app(noop);
+ big_app(cancel); big_app1(pp+1); big_app(force); big_app1(pp+2);
+ }
+ if (cat3==if_like) {
+ big_app(' '); big_app1(pp+3); reduce(pp,4,if_like,0,66);
+ }@+else reduce(pp,3,else_like,0,67);
+@z
+
+*
+
+@x section 140
+if (cat1==stmt && cat2==else_like && cat3==semi) {
+ big_app1(pp); big_app(break_space); app(noop); big_app(cancel);
+ big_app1(pp+1); big_app(cancel); app(noop); big_app(break_space);
+ big_app2(pp+2); reduce(pp,4,stmt,-1,69);
+}
+@y
+if(alternative) {
+ if (cat1==lbrace) squash(pp,1,do_head,0,114);
+ else if (cat1==stmt && cat2==else_like && cat3==semi) {
+ big_app(force); big_app1(pp); big_app(indent); big_app(force);
+ big_app1(pp+1); big_app(cancel); app(noop);
+ big_app(break_space); big_app2(pp+2); big_app(outdent); big_app(force);
+ reduce(pp,4,stmt,-1,69);
+ }
+} else {
+ if (cat1==stmt && cat2==else_like && cat3==semi) {
+ big_app1(pp); big_app(break_space); app(noop); big_app(cancel);
+ big_app1(pp+1); big_app(cancel); app(noop); big_app(break_space);
+ big_app2(pp+2); reduce(pp,4,stmt,-1,69);
+ }
+}
+@z
+
+*
+
+@x section 141
+if (cat1==semi) squash(pp,2,stmt,-1,70);
+else if (cat1==colon) squash(pp,2,tag,-1,71);
+@y
+if (cat1==semi) squash(pp,2,stmt,-3,70);
+else if (cat1==colon) squash(pp,2,tag,-2,71);
+@z
+
+*
+
+@x section 141
+ reduce(pp,3,tag,-1,73);
+@y
+ reduce(pp,3,tag,-2,73);
+@z
+
+*
+
+@x section 142
+if (cat1==tag) {
+ big_app1(pp); big_app(break_space); big_app1(pp+1); reduce(pp,2,tag,-1,74);
+}
+else if (cat1==stmt||cat1==decl||cat1==function) {
+ big_app(force); big_app(backup); big_app1(pp); big_app(break_space);
+ big_app1(pp+1); reduce(pp,2,cat1,-1,75);
+}
+@y
+if(alternative) {
+ if (cat1==tag) {
+ big_app1(pp); big_app(force); big_app1(pp+1); reduce(pp,2,tag,-1,74);
+ }
+ else if ((cat1==stmt||cat1==decl||cat1==function) &&
+ (cat2==rbrace||cat2==tag)) {
+ big_app(force); big_app1(pp); big_app(indent); big_app(force);
+ big_app1(pp+1); big_app(outdent); reduce(pp,2,cat1,-1,75);
+ }
+} else {
+ if (cat1==tag) {
+ big_app1(pp); big_app(break_space); big_app1(pp+1); reduce(pp,2,tag,-1,74);
+ }
+ else if (cat1==stmt||cat1==decl||cat1==function) {
+ big_app(force); big_app(backup); big_app1(pp); big_app(break_space);
+ big_app1(pp+1); reduce(pp,2,cat1,-1,75);
+ }
+}
+@z
+
+++
+
+@x section 145
+} else if (cat1==exp || cat1==function) {
+ if (cat2==rproc) {
+ app(inserted); big_app1(pp); big_app(' '); big_app2(pp+1);
+ reduce(pp,3,insert,-1,80);
+ }
+ else if (cat2==exp && cat3==rproc && cat1==exp) {
+ app(inserted); big_app1(pp); big_app(' '); big_app1(pp+1); app_str(" \\5");
+@.\\5@>
+ big_app2(pp+2); reduce(pp,4,insert,-1,80);
+ }
+}
+@y
+} else if ((cat1==exp || cat1==function || cat1==int_like) && cat2==rproc) {
+ app(inserted); big_app1(pp); big_app(' '); big_app2(pp+1);
+ reduce(pp,3,insert,-1,80);
+} else if ((cat1==exp || cat1==int_like || cat1==const_like) &&
+ cat2==pp_space) {
+ if(cat3==int_like || cat3==const_like || cat3==raw_int)
+ make_reserved(pp+1, (pp+3)->cat);
+ big_app1(pp); big_app(' '); big_app1(pp+1); app_str(" \\5");
+@.\\5@>
+ reduce(pp,3,lproc,-1,119);
+} else if (cat1==exp && cat2==exp && cat3==pp_space) {
+ big_app1(pp); big_app(' '); big_app2(pp+1); app_str(" \\5");
+ reduce(pp,4,lproc,-1,120);
+}
+@z
+
+*
+
+@x section 151
+if (cat1==colon) squash(pp,2,tag,-1,90);
+@y
+if (cat1==colon) squash(pp,2,tag,-2,90);
+@z
+
++++
+
+@x section 154
+if (cat1==binop || cat1==unop || cat1==unorbinop) {
+ if (cat2==binop) break;
+ big_app1(pp); big_app('{'); big_app1(pp+1); big_app('}');
+ reduce(pp,2,exp,-2,97);
+}
+else if (cat1==new_like || cat1==sizeof_like) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,exp,-2,98);
+}
+@y
+if (cat1==binop || cat1==unop || cat1==unorbinop || cat1==raw_unorbin) {
+ if (cat2==binop) break;
+ big_app1(pp); big_app('{'); big_app1(pp+1); big_app('}');
+ reduce(pp,2,exp,-2,97);
+}
+else if (cat1==new_like || cat1==sizeof_like) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,exp,-2,98);
+}
+else if (cat1==raw_int || cat1==int_like || cat1==const_like) {
+ big_app1(pp); big_app(' '); big_app1(pp+1);
+ reduce(pp,2,operator_like,-2,118);
+}
+@z
+
+*** This makes the tracing info looking smoother
+
+@x section 168
+ if (tracing==2) {
+ printf("\n%d:",n);
+@y
+ if (tracing==2) {
+ printf("\n%3d:",n);
+@z
+
+**, ++
+
+@x section 175
+@ @<Append the scr...@>=
+@<Make sure that there is room for the new scraps, tokens, and texts@>;
+@y
+@
+@d alternative flags['a'] /* if set, an alternative format is produced */
+@d func_index flags['i']
+ /* should functions in the index have |()| appended? */
+
+@<Append the scr...@>=
+@<Make sure that there is room for the new scraps, tokens, and texts@>;
+@z
+
+*, **
+
+@x section 175
+ case '(': case '[': app(next_control); app_scrap(lpar,maybe_math);@+break;
+ case ')': case ']': app(next_control); app_scrap(raw_rpar,maybe_math);@+break;
+ case '{': app_str("\\{"@q}@>); app_scrap(lbrace,yes_math);@+break;
+@.\\\{@>@q}@>
+ case '}': app_str(@q{@>"\\}"); app_scrap(rbrace,yes_math);@+break;
+@q{@>@.\\\}@>
+@y
+ case '(': if(func_index)
+ if(*(tok_ptr-1)>=id_flag && *(tok_ptr-1)<res_flag)
+ /* an identifier? */
+ (name_dir+ *(tok_ptr-1)%10240)->func_flag=1;
+ case '[': app(next_control); app_scrap(lpar,maybe_math);@+break;
+ case ')': case ']': app(next_control); app_scrap(raw_rpar,maybe_math);@+break;
+ case '{': if(alternative)
+ app_str("\\LBR");
+ else
+ app_str("\\{"@q}@>);
+ app_scrap(lbrace,yes_math);@+break;
+@.\\\{@>@q}@>
+ case '}': if(alternative)
+ app_str("\\RBR");
+ else
+ app_str(@q{@>"\\}");
+ app_scrap(rbrace,yes_math);@+break;
+@q{@>@.\\\}@>
+@z
+
+++
+
+@x section 175
+ case left_preproc: app(force); app(preproc_line);
+ app_str("\\#"); app_scrap(lproc,no_math);@+break;
+@.\\\#@>
+ case right_preproc: app(force); app_scrap(rproc,no_math);@+break;
+@y
+ case left_preproc: app(force); app(preproc_line);
+ app_str("\\#"); app_scrap(lproc,no_math);@+break;
+@.\\\#@>
+ case preproc_space: app(' '); app_scrap(pp_space, maybe_math);@+break;
+ case right_preproc: app(force); app_scrap(rproc,no_math);@+break;
+@z
+
+++
+
+@x section 175
+ case pseudo_semi: app_scrap(semi,maybe_math);@+break;
+@y
+ case pseudo_semi: app_scrap(semi,maybe_math);@+break;
+ case pseudo_lbrace: app_str("\\phantom{");
+ if(alternative)
+ app_str("\\LBR");
+ else
+ app_str("\\{"@q}@>);
+ app_str("}");
+ app_scrap(lbrace,yes_math);
+ break;
+ case pseudo_rbrace: app_str("\\phantom{");
+ if(alternative)
+ app_str("\\RBR");
+ else
+ app_str(@q{@>"\\}");
+ app_str("}");
+ app_scrap(rbrace,yes_math);
+ break;
+@z
+
+++
+
+@x section 177
+case minus_gt_ast: app_str("\\MGA");@+app_scrap(binop,yes_math);@+break;
+@.\\MGA@>
+@y
+case minus_gt_ast: app_str("\\MGA");@+app_scrap(binop,yes_math);@+break;
+@.\\MGA@>
+case numb_numb: app_str("\\NN");@+app_scrap(binop,yes_math);@+break;
+@.\\NN@>
+@z
+
+**
+
+@x section 178
+@.\\\%@>
+@.\\\$@>
+@.\\\^@>
+@y
+@.\\\%@>
+@.\\$@> @q CWEAVE quotes a dollar sign! @>
+@.\\\^@>
+@z
+
+!
+
+@x section 195
+ } else if (is_tiny(cur_name)) out('|')
+@y
+ } else if (is_tiny(cur_name)) out('|');
+@z
+
+!
+
+@x section 195
+else out('&') /* |a==res_word| */
+@y
+else out('&'); /* |a==res_word| */
+@z
+
+!
+
+@x section 196
+ if (b!='0' || force_lines==0) out(b)@;
+@y
+ if (b!='0' || force_lines==0) out(b);
+@z
+
+**
+
+@x section 200
+@.\\\%@>
+@.\\\$@>
+@.\\\^@>
+@y
+@.\\\%@>
+@.\\$@> @q CWEAVE quotes a dollar symbol! @>
+@.\\\^@>
+@z
+
+!
+
+@x section 200
+ else if (b!='|') out(b)
+@y
+ else if (b!='|') out(b);
+@z
+
+++
+
+@x section 209
+ case thin_space: case math_break: case ord:
+ case line_break: case big_line_break: case no_line_break: case join:
+ case pseudo_semi: case macro_arg_open: case macro_arg_close:
+ case output_defs_code:
+ err_print("! You can't do that in TeX text"); break;
+@.You can't do that...@>
+@y
+ case thin_space: case math_break: case ord:
+ case line_break: case big_line_break: case no_line_break: case join:
+ case pseudo_semi: case macro_arg_open: case macro_arg_close:
+ case pseudo_lbrace: case pseudo_rbrace:
+ case output_defs_code:
+ err_print("! You can't do that in TeX text"); break;
+@.You can't do that...@>
+@z
+
+**
+
+@x section 213
+ if (*loc=='(')
+ reswitch: switch (next_control=get_next()) {
+ case '(': case ',': app(next_control); goto reswitch;
+ case identifier: app_cur_id(0); goto reswitch;
+ case ')': app(next_control); next_control=get_next(); break;
+ default: err_print("! Improper macro definition"); break;
+ }
+@y
+ if (*loc=='(') {
+ if(func_index)
+ (name_dir+ *(tok_ptr-1)%10240)->func_flag=1;
+ reswitch: switch (next_control=get_next()) {
+ case '(': case ',': app(next_control); goto reswitch;
+ case identifier: app_cur_id(0); goto reswitch;
+ case ')': app(next_control); next_control=get_next(); break;
+ default: err_print("! Improper macro definition"); break;
+ }
+ }
+@z
+
+**
+
+@x section 241
+switch (cur_name->ilk) {
+ case normal: if (is_tiny(cur_name)) out_str("\\|");
+ else {char *j;
+ for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
+ if (xislower(*j)) goto lowcase;
+ out_str("\\."); break;
+lowcase: out_str("\\\\");
+ }
+ break;
+@.\\|@>
+@.\\.@>
+@.\\\\@>
+ case roman: break;
+ case wildcard: out_str("\\9"); break;
+@.\\9@>
+ case typewriter: out_str("\\."); break;
+@.\\.@>
+ case custom: case quoted: {char *j; out_str("$\\");
+ for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
+ out(isxalpha(*j)? 'x' : *j);
+ out('$');
+ goto name_done;
+ }
+ default: out_str("\\&");
+@.\\\&@>
+}
+out_name(cur_name);
+name_done:
+@y
+switch (cur_name->ilk) {
+ case normal:
+ if (is_tiny(cur_name) && !cur_name->func_flag)
+ out_str("\\|");
+ else {char *j;
+ for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
+ if (xislower(*j)) goto lowcase;
+ out_str("\\."); break;
+lowcase: out_str("\\\\");
+ }
+ break;
+@.\\|@>
+@.\\.@>
+@.\\\\@>
+ case roman: break;
+ case wildcard: out_str("\\9"); break;
+@.\\9@>
+ case typewriter: out_str("\\."); break;
+@.\\.@>
+ case custom: case quoted: {char *j; out_str("$\\");
+ for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
+ out(isxalpha(*j)? 'x' : *j);
+ out('$');
+ goto name_done;
+ }
+ default: out_str("\\&");
+@.\\\&@>
+}
+out_name(cur_name);
+name_done:
+ if(cur_name->func_flag)
+ out_str("(\\,)");
+@z
+
+*
+
+@x section 249
+@** Index.
+@y
+@ @<Cases for |label|@>=
+if (cat1==label) {
+ big_app1(pp); big_app(force); big_app1(pp+1); reduce(pp,2,label,-1,112);
+}
+else if (cat1==stmt||cat1==decl||cat1==function) {
+ big_app(cancel); app(noop);
+ big_app(outdent); big_app(outdent); big_app(force);
+ big_app1(pp); big_app(indent); big_app(indent); big_app(force);
+ big_app1(pp+1); reduce(pp,2,cat1,-1,113);
+}
+
+@ @<Cases for |do_head|@>=
+if (cat1==stmt && cat2==else_like && cat3==semi) {
+ big_app1(pp); big_app(break_space); big_app1(pp+1); big_app(cancel);
+ app(noop); big_app(break_space); big_app2(pp+2); reduce(pp,4,stmt,-1,115);
+}
+
+@** Index.
+@z
+
+--- end of cweave.ch ---
diff --git a/web/c_cpp/c2cweb/cweb/cweave.def b/web/c_cpp/c2cweb/cweb/cweave.def
new file mode 100644
index 0000000000..71fd302fae
--- /dev/null
+++ b/web/c_cpp/c2cweb/cweb/cweave.def
@@ -0,0 +1,3 @@
+NAME CWEAVE WINDOWCOMPAT
+DESCRIPTION 'CWEAVE 3.2'
+STACKSIZE 0x80000
diff --git a/web/c_cpp/c2cweb/cweb/cweave.w b/web/c_cpp/c2cweb/cweb/cweave.w
new file mode 100644
index 0000000000..6c08b6bc80
--- /dev/null
+++ b/web/c_cpp/c2cweb/cweb/cweave.w
@@ -0,0 +1,4505 @@
+% This file is part of CWEB.
+% This program by Silvio Levy and Donald E. Knuth
+% is based on a program by Knuth.
+% It is distributed WITHOUT ANY WARRANTY, express or implied.
+% Version 3.4 --- April 1995
+
+% Copyright (C) 1987,1990,1993 Silvio Levy and Donald E. Knuth
+
+% Permission is granted to make and distribute verbatim copies of this
+% document provided that the copyright notice and this permission notice
+% are preserved on all copies.
+
+% Permission is granted to copy and distribute modified versions of this
+% document under the conditions for verbatim copying, provided that the
+% entire resulting derived work is given a different name and distributed
+% under the terms of a permission notice identical to this one.
+
+% Here is TeX material that gets inserted after \input cwebmac
+\def\hang{\hangindent 3em\indent\ignorespaces}
+\def\pb{$\.|\ldots\.|$} % C brackets (|...|)
+\def\v{\char'174} % vertical (|) in typewriter font
+\def\dleft{[\![} \def\dright{]\!]} % double brackets
+\mathchardef\RA="3221 % right arrow
+\mathchardef\BA="3224 % double arrow
+\def\({} % ) kludge for alphabetizing certain section names
+\def\TeXxstring{\\{\TEX/\_string}}
+\def\skipxTeX{\\{skip\_\TEX/}}
+\def\copyxTeX{\\{copy\_\TEX/}}
+
+\def\title{CWEAVE (Version 3.4)}
+\def\topofcontents{\null\vfill
+ \centerline{\titlefont The {\ttitlefont CWEAVE} processor}
+ \vskip 15pt
+ \centerline{(Version 3.4)}
+ \vfill}
+\def\botofcontents{\vfill
+\noindent
+Copyright \copyright\ 1987, 1990, 1993 Silvio Levy and Donald E. Knuth
+\bigskip\noindent
+Permission is granted to make and distribute verbatim copies of this
+document provided that the copyright notice and this permission notice
+are preserved on all copies.
+
+\smallskip\noindent
+Permission is granted to copy and distribute modified versions of this
+document under the conditions for verbatim copying, provided that the
+entire resulting derived work is given a different name and distributed
+under the terms of a permission notice identical to this one.
+}
+\pageno=\contentspagenumber \advance\pageno by 1
+\let\maybe=\iftrue
+
+@** Introduction.
+This is the \.{CWEAVE} program by Silvio Levy and Donald E. Knuth,
+based on \.{WEAVE} by Knuth.
+We are thankful to Steve Avery,
+Nelson Beebe, Hans-Hermann Bode (to whom the \CPLUSPLUS/ adaptation is due),
+Klaus Guntermann, Norman Ramsey, Tomas Rokicki, Joachim Schnitter,
+Joachim Schrod, Lee Wittenberg, and others who have contributed improvements.
+
+The ``banner line'' defined here should be changed whenever \.{CWEAVE}
+is modified.
+
+@d banner "This is CWEAVE (Version 3.4)\n"
+
+@c @<Include files@>@/
+@h
+@<Common code for \.{CWEAVE} and \.{CTANGLE}@>@/
+@<Typedef declarations@>@/
+@<Global variables@>@/
+@<Predeclaration of procedures@>
+
+@ We predeclare several standard system 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. (For example, some \CEE/ environments
+have \.{<string.h>} where others have \.{<strings.h>}.)
+
+@<Predecl...@>=
+extern int strlen(); /* length of string */
+extern int strcmp(); /* compare strings lexicographically */
+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 */
+
+@ \.{CWEAVE} has a fairly straightforward outline. It operates in
+three phases: First it inputs the source file and stores cross-reference
+data, then it inputs the source once again and produces the \TEX/ output
+file, finally it sorts and outputs the index.
+
+Please read the documentation for \.{common}, the set of routines common
+to \.{CTANGLE} and \.{CWEAVE}, before proceeding further.
+
+@c
+int main (ac, av)
+int ac; /* argument count */
+char **av; /* argument values */
+{
+ argc=ac; argv=av;
+ program=cweave;
+ make_xrefs=force_lines=1; /* controlled by command-line options */
+ common_init();
+ @<Set initial values@>;
+ if (show_banner) printf(banner); /* print a ``banner line'' */
+ @<Store all the reserved words@>;
+ phase_one(); /* read all the user's text and store the cross-references */
+ phase_two(); /* read all the text again and translate it to \TEX/ form */
+ phase_three(); /* output the cross-reference index */
+ return wrap_up(); /* and exit gracefully */
+}
+
+@ The following parameters were sufficient in the original \.{WEAVE} to
+handle \TEX/, so they should be sufficient for most applications of \.{CWEAVE}.
+If you change |max_bytes|, |max_names|, |hash_size| or |buf_size|
+you have to change them also in the file |"common.w"|.
+
+@d max_bytes 90000 /* the number of bytes in identifiers,
+ index entries, and section names */
+@d max_names 4000 /* number of identifiers, strings, section names;
+ must be less than 10240; used in |"common.w"| */
+@d max_sections 2000 /* greater than the total number of sections */
+@d hash_size 353 /* should be prime */
+@d buf_size 100 /* maximum length of input line, plus one */
+@d longest_name 1000 /* section names and strings shouldn't be longer than this */
+@d long_buf_size (buf_size+longest_name)
+@d line_length 80 /* lines of \TEX/ output have at most this many characters;
+ should be less than 256 */
+@d max_refs 20000 /* number of cross-references; must be less than 65536 */
+@d max_toks 20000 /* number of symbols in \CEE/ texts being parsed;
+ must be less than 65536 */
+@d max_texts 4000 /* number of phrases in \CEE/ texts being parsed;
+ must be less than 10240 */
+@d max_scraps 2000 /* number of tokens in \CEE/ texts being parsed */
+@d stack_size 400 /* number of simultaneous output levels */
+
+@ The next few sections contain stuff from the file |"common.w"| that must
+be included in both |"ctangle.w"| and |"cweave.w"|. It appears in
+file |"common.h"|, which needs to be updated when |"common.w"| changes.
+
+@i common.h
+
+@* Data structures exclusive to {\tt CWEAVE}.
+As explained in \.{common.w}, the field of a |name_info| structure
+that contains the |rlink| of a section name is used for a completely
+different purpose in the case of identifiers. It is then called the
+|ilk| of the identifier, and it is used to
+distinguish between various types of identifiers, as follows:
+
+\yskip\hang |normal| identifiers are part of the \CEE/ program and
+will appear in italic type.
+
+\yskip\hang |roman| identifiers are index entries that appear after
+\.{@@\^} in the \.{CWEB} file.
+
+\yskip\hang |wildcard| identifiers are index entries that appear after
+\.{@@:} in the \.{CWEB} file.
+
+\yskip\hang |typewriter| identifiers are index entries that appear after
+\.{@@.} in the \.{CWEB} file.
+
+\yskip\hang |else_like|, \dots, |typedef_like|
+identifiers are \CEE/ reserved words whose |ilk| explains how they are
+to be treated when \CEE/ code is being formatted.
+
+@d ilk dummy.Ilk
+@d normal 0 /* ordinary identifiers have |normal| ilk */
+@d roman 1 /* normal index entries have |roman| ilk */
+@d wildcard 2 /* user-formatted index entries have |wildcard| ilk */
+@d typewriter 3 /* `typewriter type' entries have |typewriter| ilk */
+@d abnormal(a) (a->ilk>typewriter) /* tells if a name is special */
+@d custom 4 /* identifiers with user-given control sequence */
+@d unindexed(a) (a->ilk>custom) /* tells if uses of a name are to be indexed */
+@d quoted 5 /* \.{NULL} */
+@d else_like 26 /* \&{else} */
+@d public_like 40 /* \&{public}, \&{private}, \&{protected} */
+@d operator_like 41 /* \&{operator} */
+@d new_like 42 /* \&{new} */
+@d catch_like 43 /* \&{catch} */
+@d for_like 45 /* \.{for}, \&{switch}, \&{while} */
+@d do_like 46 /* \&{do} */
+@d if_like 47 /* \&{if}, \&{ifdef}, \&{endif}, \&{pragma}, \dots */
+@d raw_rpar 48 /* `\.)' or `\.]' when looking for \&{const} following */
+@d raw_unorbin 49 /* `\.\&' or `\.*' when looking for \&{const} following */
+@d const_like 50 /* \&{const}, \&{volatile} */
+@d raw_int 51 /* \&{int}, \&{char}, \&{extern}, \dots */
+@d int_like 52 /* same, when not followed by left parenthesis */
+@d case_like 53 /* \&{case}, \&{return}, \&{goto}, \&{break}, \&{continue} */
+@d sizeof_like 54 /* \&{sizeof} */
+@d struct_like 55 /* \&{struct}, \&{union}, \&{enum}, \&{class} */
+@d typedef_like 56 /* \&{typedef} */
+@d define_like 57 /* \&{define} */
+
+@ We keep track of the current section number in |section_count|, which
+is the total number of sections that have started. Sections which have
+been altered by a change file entry have their |changed_section| flag
+turned on during the first phase.
+
+@<Global...@>=
+boolean change_exists; /* has any section changed? */
+
+@ The other large memory area in \.{CWEAVE} keeps the cross-reference data.
+All uses of the name |p| are recorded in a linked list beginning at
+|p->xref|, which points into the |xmem| array. The elements of |xmem|
+are structures consisting of an integer, |num|, and a pointer |xlink|
+to another element of |xmem|. If |x=p->xref| is a pointer into |xmem|,
+the value of |x->num| is either a section number where |p| is used,
+or |cite_flag| plus a section number where |p| is mentioned,
+or |def_flag| plus a section number where |p| is defined;
+and |x->xlink| points to the next such cross-reference for |p|,
+if any. This list of cross-references is in decreasing order by
+section number. The next unused slot in |xmem| is |xref_ptr|.
+The linked list ends at |&xmem[0]|.
+
+The global variable |xref_switch| is set either to |def_flag| or to zero,
+depending on whether the next cross-reference to an identifier is to be
+underlined or not in the index. This switch is set to |def_flag| when
+\.{@@!} or \.{@@d} is scanned, and it is cleared to zero when
+the next identifier or index entry cross-reference has been made.
+Similarly, the global variable |section_xref_switch| is either
+|def_flag| or |cite_flag| or zero, depending
+on whether a section name is being defined, cited or used in \CEE/ text.
+
+@<Type...@>=
+typedef struct xref_info {
+ sixteen_bits num; /* section number plus zero or |def_flag| */
+ struct xref_info *xlink; /* pointer to the previous cross-reference */
+} xref_info;
+typedef xref_info *xref_pointer;
+
+@ @<Global...@>=
+xref_info xmem[max_refs]; /* contains cross-reference information */
+xref_pointer xmem_end = xmem+max_refs-1;
+xref_pointer xref_ptr; /* the largest occupied position in |xmem| */
+sixteen_bits xref_switch,section_xref_switch; /* either zero or |def_flag| */
+
+@ A section that is used for multi-file output (with the \.{@@(} feature)
+has a special first cross-reference whose |num| field is |file_flag|.
+
+@d file_flag (3*cite_flag)
+@d def_flag (2*cite_flag)
+@d cite_flag 10240 /* must be strictly larger than |max_sections| */
+@d xref equiv_or_xref
+
+@<Set init...@>=
+xref_ptr=xmem; name_dir->xref=(char*)xmem; xref_switch=0; section_xref_switch=0;
+xmem->num=0; /* sentinel value */
+
+@ A new cross-reference for an identifier is formed by calling |new_xref|,
+which discards duplicate entries and ignores non-underlined references
+to one-letter identifiers or \CEE/'s reserved words.
+
+If the user has sent the |no_xref| flag (the \.{-x} option of the command line),
+it is unnecessary to keep track of cross-references for identifiers.
+If one were careful, one could probably make more changes around section
+100 to avoid a lot of identifier looking up.
+
+@d append_xref(c) if (xref_ptr==xmem_end) overflow("cross-reference");
+ else (++xref_ptr)->num=c;
+@d no_xref (flags['x']==0)
+@d make_xrefs flags['x'] /* should cross references be output? */
+@d is_tiny(p) ((p+1)->byte_start==(p)->byte_start+1)
+
+@c
+void
+new_xref(p)
+name_pointer p;
+{
+ xref_pointer q; /* pointer to previous cross-reference */
+ sixteen_bits m, n; /* new and previous cross-reference value */
+ if (no_xref) return;
+ if ((unindexed(p) || is_tiny(p)) && xref_switch==0) return;
+ m=section_count+xref_switch; xref_switch=0; q=(xref_pointer)p->xref;
+ if (q != xmem) {
+ n=q->num;
+ if (n==m || n==m+def_flag) return;
+ else if (m==n+def_flag) {
+ q->num=m; return;
+ }
+ }
+ append_xref(m); xref_ptr->xlink=q; p->xref=(char*)xref_ptr;
+}
+
+@ The cross-reference lists for section names are slightly different.
+Suppose that a section name is defined in sections $m_1$, \dots,
+$m_k$, cited in sections $n_1$, \dots, $n_l$, and used in sections
+$p_1$, \dots, $p_j$. Then its list will contain $m_1+|def_flag|$,
+\dots, $m_k+|def_flag|$, $n_1+|cite_flag|$, \dots,
+$n_l+|cite_flag|$, $p_1$, \dots, $p_j$, in this order.
+
+Although this method of storage take quadratic time on the length of
+the list, under foreseeable uses of \.{CWEAVE} this inefficiency is
+insignificant.
+
+@c
+void
+new_section_xref(p)
+name_pointer p;
+{
+ xref_pointer q,r; /* pointers to previous cross-references */
+ q=(xref_pointer)p->xref; r=xmem;
+ if (q>xmem)
+ while (q->num>section_xref_switch) {r=q; q=q->xlink;}
+ if (r->num==section_count+section_xref_switch)
+ return; /* don't duplicate entries */
+ append_xref(section_count+section_xref_switch);
+ xref_ptr->xlink=q; section_xref_switch=0;
+ if (r==xmem) p->xref=(char*)xref_ptr;
+ else r->xlink=xref_ptr;
+}
+
+@ The cross-reference list for a section name may also begin with
+|file_flag|. Here's how that flag gets put~in.
+
+@c
+void
+set_file_flag(p)
+name_pointer p;
+{
+ xref_pointer q;
+ q=(xref_pointer)p->xref;
+ if (q->num==file_flag) return;
+ append_xref(file_flag);
+ xref_ptr->xlink = q;
+ p->xref = (char *)xref_ptr;
+}
+
+@ A third large area of memory is used for sixteen-bit `tokens', which appear
+in short lists similar to the strings of characters in |byte_mem|. Token lists
+are used to contain the result of \CEE/ code translated into \TEX/ form;
+further details about them will be explained later. A |text_pointer| variable
+is an index into |tok_start|.
+
+@<Typed...@>=
+typedef sixteen_bits token;
+typedef token *token_pointer;
+typedef token_pointer *text_pointer;
+
+@ The first position of |tok_mem|
+that is unoccupied by replacement text is called |tok_ptr|, and the first
+unused location of |tok_start| is called |text_ptr|.
+Thus, we usually have |*text_ptr==tok_ptr|.
+
+@<Global...@>=
+token tok_mem[max_toks]; /* tokens */
+token_pointer tok_mem_end = tok_mem+max_toks-1; /* end of |tok_mem| */
+token_pointer tok_start[max_texts]; /* directory into |tok_mem| */
+token_pointer tok_ptr; /* first unused position in |tok_mem| */
+text_pointer text_ptr; /* first unused position in |tok_start| */
+text_pointer tok_start_end = tok_start+max_texts-1; /* end of |tok_start| */
+token_pointer max_tok_ptr; /* largest value of |tok_ptr| */
+text_pointer max_text_ptr; /* largest value of |text_ptr| */
+
+@ @<Set init...@>=
+tok_ptr=tok_mem+1; text_ptr=tok_start+1; tok_start[0]=tok_mem+1;
+tok_start[1]=tok_mem+1;
+max_tok_ptr=tok_mem+1; max_text_ptr=tok_start+1;
+
+@ Here are the three procedures needed to complete |id_lookup|:
+@c
+int names_match(p,first,l,t)
+name_pointer p; /* points to the proposed match */
+char *first; /* position of first character of string */
+int l; /* length of identifier */
+eight_bits t; /* desired ilk */
+{
+ if (length(p)!=l) return 0;
+ if (p->ilk!=t && !(t==normal && abnormal(p))) return 0;
+ return !strncmp(first,p->byte_start,l);
+}
+
+void
+init_p(p,t)
+name_pointer p;
+eight_bits t;
+{
+ p->ilk=t; p->xref=(char*)xmem;
+}
+
+void
+init_node(p)
+name_pointer p;
+{
+ p->xref=(char*)xmem;
+}
+
+@ We have to get \CEE/'s
+reserved words into the hash table, and the simplest way to do this is
+to insert them every time \.{CWEAVE} is run. Fortunately there are relatively
+few reserved words. (Some of these are not strictly ``reserved,'' but
+are defined in header files of the ISO Standard \CEE/ Library.)
+@^reserved words@>
+
+@<Store all the reserved words@>=
+id_lookup("asm",NULL,sizeof_like);
+id_lookup("auto",NULL,int_like);
+id_lookup("break",NULL,case_like);
+id_lookup("case",NULL,case_like);
+id_lookup("catch",NULL,catch_like);
+id_lookup("char",NULL,raw_int);
+id_lookup("class",NULL,struct_like);
+id_lookup("clock_t",NULL,raw_int);
+id_lookup("const",NULL,const_like);
+id_lookup("continue",NULL,case_like);
+id_lookup("default",NULL,case_like);
+id_lookup("define",NULL,define_like);
+id_lookup("defined",NULL,sizeof_like);
+id_lookup("delete",NULL,sizeof_like);
+id_lookup("div_t",NULL,raw_int);
+id_lookup("do",NULL,do_like);
+id_lookup("double",NULL,raw_int);
+id_lookup("elif",NULL,if_like);
+id_lookup("else",NULL,else_like);
+id_lookup("endif",NULL,if_like);
+id_lookup("enum",NULL,struct_like);
+id_lookup("error",NULL,if_like);
+id_lookup("extern",NULL,int_like);
+id_lookup("FILE",NULL,raw_int);
+id_lookup("float",NULL,raw_int);
+id_lookup("for",NULL,for_like);
+id_lookup("fpos_t",NULL,raw_int);
+id_lookup("friend",NULL,int_like);
+id_lookup("goto",NULL,case_like);
+id_lookup("if",NULL,if_like);
+id_lookup("ifdef",NULL,if_like);
+id_lookup("ifndef",NULL,if_like);
+id_lookup("include",NULL,if_like);
+id_lookup("inline",NULL,int_like);
+id_lookup("int",NULL,raw_int);
+id_lookup("jmp_buf",NULL,raw_int);
+id_lookup("ldiv_t",NULL,raw_int);
+id_lookup("line",NULL,if_like);
+id_lookup("long",NULL,raw_int);
+id_lookup("new",NULL,new_like);
+id_lookup("NULL",NULL,quoted);
+id_lookup("offsetof",NULL,sizeof_like);
+id_lookup("operator",NULL,operator_like);
+id_lookup("pragma",NULL,if_like);
+id_lookup("private",NULL,public_like);
+id_lookup("protected",NULL,public_like);
+id_lookup("ptrdiff_t",NULL,raw_int);
+id_lookup("public",NULL,public_like);
+id_lookup("register",NULL,int_like);
+id_lookup("return",NULL,case_like);
+id_lookup("short",NULL,raw_int);
+id_lookup("sig_atomic_t",NULL,raw_int);
+id_lookup("signed",NULL,raw_int);
+id_lookup("size_t",NULL,raw_int);
+id_lookup("sizeof",NULL,sizeof_like);
+id_lookup("static",NULL,int_like);
+id_lookup("struct",NULL,struct_like);
+id_lookup("switch",NULL,for_like);
+id_lookup("template",NULL,int_like);
+id_lookup("TeX",NULL,custom);
+id_lookup("this",NULL,quoted);
+id_lookup("throw",NULL,case_like);
+id_lookup("time_t",NULL,raw_int);
+id_lookup("try",NULL,else_like);
+id_lookup("typedef",NULL,typedef_like);
+id_lookup("undef",NULL,if_like);
+id_lookup("union",NULL,struct_like);
+id_lookup("unsigned",NULL,raw_int);
+id_lookup("va_dcl",NULL,decl); /* Berkeley's variable-arg-list convention */
+id_lookup("va_list",NULL,raw_int); /* ditto */
+id_lookup("virtual",NULL,int_like);
+id_lookup("void",NULL,raw_int);
+id_lookup("volatile",NULL,const_like);
+id_lookup("wchar_t",NULL,raw_int);
+id_lookup("while",NULL,for_like);
+
+@* Lexical scanning.
+Let us now consider the subroutines that read the \.{CWEB} source file
+and break it into meaningful units. There are four such procedures:
+One simply skips to the next `\.{@@\ }' or `\.{@@*}' that begins a
+section; another passes over the \TEX/ text at the beginning of a
+section; the third passes over the \TEX/ text in a \CEE/ comment;
+and the last, which is the most interesting, gets the next token of
+a \CEE/ text. They all use the pointers |limit| and |loc| into
+the line of input currently being studied.
+
+@ Control codes in \.{CWEB}, which begin with `\.{@@}', are converted
+into a numeric code designed to simplify \.{CWEAVE}'s logic; for example,
+larger numbers are given to the control codes that denote more significant
+milestones, and the code of |new_section| should be the largest of
+all. Some of these numeric control codes take the place of |char|
+control codes that will not otherwise appear in the output of the
+scanning routines.
+@^ASCII code dependencies@>
+
+@d ignore 00 /* control code of no interest to \.{CWEAVE} */
+@d verbatim 02 /* takes the place of extended ASCII \.{\char2} */
+@d begin_short_comment 03 /* \CPLUSPLUS/ short comment */
+@d begin_comment '\t' /* tab marks will not appear */
+@d underline '\n' /* this code will be intercepted without confusion */
+@d noop 0177 /* takes the place of ASCII delete */
+@d xref_roman 0203 /* control code for `\.{@@\^}' */
+@d xref_wildcard 0204 /* control code for `\.{@@:}' */
+@d xref_typewriter 0205 /* control code for `\.{@@.}' */
+@d TeX_string 0206 /* control code for `\.{@@t}' */
+@f TeX_string TeX
+@d ord 0207 /* control code for `\.{@@'}' */
+@d join 0210 /* control code for `\.{@@\&}' */
+@d thin_space 0211 /* control code for `\.{@@,}' */
+@d math_break 0212 /* control code for `\.{@@\v}' */
+@d line_break 0213 /* control code for `\.{@@/}' */
+@d big_line_break 0214 /* control code for `\.{@@\#}' */
+@d no_line_break 0215 /* control code for `\.{@@+}' */
+@d pseudo_semi 0216 /* control code for `\.{@@;}' */
+@d macro_arg_open 0220 /* control code for `\.{@@[}' */
+@d macro_arg_close 0221 /* control code for `\.{@@]}' */
+@d trace 0222 /* control code for `\.{@@0}', `\.{@@1}' and `\.{@@2}' */
+@d translit_code 0223 /* control code for `\.{@@l}' */
+@d output_defs_code 0224 /* control code for `\.{@@h}' */
+@d format_code 0225 /* control code for `\.{@@f}' and `\.{@@s}' */
+@d definition 0226 /* control code for `\.{@@d}' */
+@d begin_C 0227 /* control code for `\.{@@c}' */
+@d section_name 0230 /* control code for `\.{@@<}' */
+@d new_section 0231 /* control code for `\.{@@\ }' and `\.{@@*}' */
+
+@ Control codes are converted to \.{CWEAVE}'s internal
+representation by means of the table |ccode|.
+
+@<Global...@>=
+eight_bits ccode[256]; /* meaning of a char following \.{@@} */
+
+@ @<Set ini...@>=
+{int c; for (c=0; c<256; c++) ccode[c]=0;}
+ccode[' ']=ccode['\t']=ccode['\n']=ccode['\v']=ccode['\r']=ccode['\f']
+ =ccode['*']=new_section;
+ccode['@@']='@@'; /* `quoted' at sign */
+ccode['=']=verbatim;
+ccode['d']=ccode['D']=definition;
+ccode['f']=ccode['F']=ccode['s']=ccode['S']=format_code;
+ccode['c']=ccode['C']=ccode['p']=ccode['P']=begin_C;
+ccode['t']=ccode['T']=TeX_string;
+ccode['l']=ccode['L']=translit_code;
+ccode['q']=ccode['Q']=noop;
+ccode['h']=ccode['H']=output_defs_code;
+ccode['&']=join; ccode['<']=ccode['(']=section_name;
+ccode['!']=underline; ccode['^']=xref_roman;
+ccode[':']=xref_wildcard; ccode['.']=xref_typewriter; ccode[',']=thin_space;
+ccode['|']=math_break; ccode['/']=line_break; ccode['#']=big_line_break;
+ccode['+']=no_line_break; ccode[';']=pseudo_semi;
+ccode['[']=macro_arg_open; ccode[']']=macro_arg_close;
+ccode['\'']=ord;
+@<Special control codes for debugging@>@;
+
+@ Users can write
+\.{@@2}, \.{@@1}, and \.{@@0} to turn tracing fully on, partly on,
+and off, respectively.
+
+@<Special control codes...@>=
+ccode['0']=ccode['1']=ccode['2']=trace;
+
+@ The |skip_limbo| routine is used on the first pass to skip through
+portions of the input that are not in any sections, i.e., that precede
+the first section. After this procedure has been called, the value of
+|input_has_ended| will tell whether or not a section has actually been found.
+
+There's a complication that we will postpone until later: If the \.{@@s}
+operation appears in limbo, we want to use it to adjust the default
+interpretation of identifiers.
+
+@<Predec...@>=
+void skip_limbo();
+
+@ @c
+void
+skip_limbo() {
+ while(1) {
+ if (loc>limit && get_line()==0) return;
+ *(limit+1)='@@';
+ while (*loc!='@@') loc++; /* look for '@@', then skip two chars */
+ if (loc++ <=limit) { int c=ccode[(eight_bits)*loc++];
+ if (c==new_section) return;
+ if (c==noop) skip_restricted();
+ else if (c==format_code) @<Process simple format in limbo@>;
+ }
+ }
+}
+
+@ The |skip_TeX| routine is used on the first pass to skip through
+the \TEX/ code at the beginning of a section. It returns the next
+control code or `\.{\v}' found in the input. A |new_section| is
+assumed to exist at the very end of the file.
+
+@f skip_TeX TeX
+
+@c
+unsigned
+skip_TeX() /* skip past pure \TEX/ code */
+{
+ while (1) {
+ if (loc>limit && get_line()==0) return(new_section);
+ *(limit+1)='@@';
+ while (*loc!='@@' && *loc!='|') loc++;
+ if (*loc++ =='|') return('|');
+ if (loc<=limit) return(ccode[(eight_bits)*(loc++)]);
+ }
+}
+
+@*1 Inputting the next token.
+As stated above, \.{CWEAVE}'s most interesting lexical scanning routine is the
+|get_next| function that inputs the next token of \CEE/ input. However,
+|get_next| is not especially complicated.
+
+The result of |get_next| is either a |char| code for some special character,
+or it is a special code representing a pair of characters (e.g., `\.{!=}'),
+or it is the numeric value computed by the |ccode|
+table, or it is one of the following special codes:
+
+\yskip\hang |identifier|: In this case the global variables |id_first| and
+|id_loc| will have been set to the beginning and ending-plus-one locations
+in the buffer, as required by the |id_lookup| routine.
+
+\yskip\hang |string|: The string will have been copied into the array
+|section_text|; |id_first| and |id_loc| are set as above (now they are
+pointers into |section_text|).
+
+\yskip\hang |constant|: The constant is copied into |section_text|, with
+slight modifications; |id_first| and |id_loc| are set.
+
+\yskip\noindent Furthermore, some of the control codes cause
+|get_next| to take additional actions:
+
+\yskip\hang |xref_roman|, |xref_wildcard|, |xref_typewriter|, |TeX_string|,
+|verbatim|: The values of |id_first| and |id_loc| will have been set to
+the beginning and ending-plus-one locations in the buffer.
+
+\yskip\hang |section_name|: In this case the global variable |cur_section| will
+point to the |byte_start| entry for the section name that has just been scanned.
+The value of |cur_section_char| will be |'('| if the section name was
+preceded by \.{@@(} instead of \.{@@<}.
+
+\yskip\noindent If |get_next| sees `\.{@@!}'
+it sets |xref_switch| to |def_flag| and goes on to the next token.
+
+@d constant 0200 /* \CEE/ constant */
+@d string 0201 /* \CEE/ string */
+@d identifier 0202 /* \CEE/ identifier or reserved word */
+
+@<Global...@>=
+name_pointer cur_section; /* name of section just scanned */
+char cur_section_char; /* the character just before that name */
+
+@ @<Include...@>=
+#include <ctype.h> /* definition of |isalpha|, |isdigit| and so on */
+#include <stdlib.h> /* definition of |exit| */
+
+@ As one might expect, |get_next| consists mostly of a big switch
+that branches to the various special cases that can arise.
+
+@d isxalpha(c) ((c)=='_') /* non-alpha character allowed in identifier */
+@d ishigh(c) ((eight_bits)(c)>0177)
+@^high-bit character handling@>
+
+@<Predecl...@>=
+eight_bits get_next();
+
+@ @c
+eight_bits
+get_next() /* produces the next input token */
+{@+eight_bits c; /* the current character */
+ while (1) {
+ @<Check if we're at the end of a preprocessor command@>;
+ if (loc>limit && get_line()==0) return(new_section);
+ c=*(loc++);
+ if (xisdigit(c) || c=='\\' || c=='.') @<Get a constant@>@;
+ else if (c=='\'' || c=='"' || (c=='L'&&(*loc=='\'' || *loc=='"'))@|
+ || (c=='<' && sharp_include_line==1))
+ @<Get a string@>@;
+ else if (xisalpha(c) || isxalpha(c) || ishigh(c))
+ @<Get an identifier@>@;
+ else if (c=='@@') @<Get control code and possible section name@>@;
+ else if (xisspace(c)) continue; /* ignore spaces and tabs */
+ if (c=='#' && loc==buffer+1) @<Raise preprocessor flag@>;
+ mistake: @<Compress two-symbol operator@>@;
+ return(c);
+ }
+}
+
+@ Because preprocessor commands do not fit in with the rest of the syntax
+of \CEE/,
+we have to deal with them separately. One solution is to enclose such
+commands between special markers. Thus, when a \.\# is seen as the
+first character of a line, |get_next| returns a special code
+|left_preproc| and raises a flag |preprocessing|.
+
+We can use the same internal code number for |left_preproc| as we do
+for |ord|, since |get_next| changes |ord| into a string.
+
+@d left_preproc ord /* begins a preprocessor command */
+@d right_preproc 0217 /* ends a preprocessor command */
+
+@<Glob...@>=
+boolean preprocessing=0; /* are we scanning a preprocessor command? */
+
+@ @<Raise prep...@>= {
+ preprocessing=1;
+ @<Check if next token is |include|@>;
+ return (left_preproc);
+}
+
+@ An additional complication is the freakish use of \.< and \.> to delimit
+a file name in lines that start with \.{\#include}. We must treat this file
+name as a string.
+
+@<Glob...@>=
+boolean sharp_include_line=0; /* are we scanning a |#include| line? */
+
+@ @<Check if next token is |include|@>=
+while (loc<=buffer_end-7 && xisspace(*loc)) loc++;
+if (loc<=buffer_end-6 && strncmp(loc,"include",7)==0) sharp_include_line=1;
+
+@ When we get to the end of a preprocessor line,
+we lower the flag and send a code |right_preproc|, unless
+the last character was a \.\\.
+
+@<Check if we're at...@>=
+ while (loc==limit-1 && preprocessing && *loc=='\\')
+ if (get_line()==0) return(new_section); /* still in preprocessor mode */
+ if (loc>=limit && preprocessing) {
+ preprocessing=sharp_include_line=0;
+ return(right_preproc);
+ }
+
+@ The following code assigns values to the combinations \.{++},
+\.{--}, \.{->}, \.{>=}, \.{<=}, \.{==}, \.{<<}, \.{>>}, \.{!=}, \.{\v\v}, and
+\.{\&\&}, and to the \CPLUSPLUS/
+combinations \.{...}, \.{::}, \.{.*} and \.{->*}.
+The compound assignment operators (e.g., \.{+=}) are
+treated as separate tokens.
+
+@d compress(c) if (loc++<=limit) return(c)
+
+@<Compress tw...@>=
+switch(c) {
+ case '/': if (*loc=='*') {compress(begin_comment);}
+ else if (*loc=='/') compress(begin_short_comment); break;
+ case '+': if (*loc=='+') compress(plus_plus); break;
+ case '-': if (*loc=='-') {compress(minus_minus);}
+ else if (*loc=='>') if (*(loc+1)=='*') {loc++; compress(minus_gt_ast);}
+ else compress(minus_gt); break;
+ case '.': if (*loc=='*') {compress(period_ast);}
+ else if (*loc=='.' && *(loc+1)=='.') {
+ loc++; compress(dot_dot_dot);
+ }
+ break;
+ case ':': if (*loc==':') compress(colon_colon); break;
+ case '=': if (*loc=='=') compress(eq_eq); break;
+ case '>': if (*loc=='=') {compress(gt_eq);}
+ else if (*loc=='>') compress(gt_gt); break;
+ case '<': if (*loc=='=') {compress(lt_eq);}
+ else if (*loc=='<') compress(lt_lt); break;
+ case '&': if (*loc=='&') compress(and_and); break;
+ case '|': if (*loc=='|') compress(or_or); break;
+ case '!': if (*loc=='=') compress(not_eq); break;
+}
+
+@ @<Get an identifier@>= {
+ id_first=--loc;
+ while (isalpha(*++loc) || isdigit(*loc) || isxalpha(*loc) || ishigh(*loc));
+ id_loc=loc; return(identifier);
+}
+
+@ Different conventions are followed by \TEX/ and \CEE/ to express octal
+and hexadecimal numbers; it is reasonable to stick to each convention
+within its realm. Thus the \CEE/ part of a \.{CWEB} file has octals
+introduced by \.0 and hexadecimals by \.{0x}, but \.{CWEAVE} will print
+in italics or typewriter font, respectively, and introduced by single
+or double quotes. In order to simplify the \TEX/ macro used to print
+such constants, we replace some of the characters.
+
+Notice that in this section and the next, |id_first| and |id_loc|
+are pointers into the array |section_text|, not into |buffer|.
+
+@<Get a constant@>= {
+ id_first=id_loc=section_text+1;
+ if (*(loc-1)=='\\') {*id_loc++='~';
+ while (xisdigit(*loc)) *id_loc++=*loc++;} /* octal constant */
+ else if (*(loc-1)=='0') {
+ if (*loc=='x' || *loc=='X') {*id_loc++='^'; loc++;
+ while (xisxdigit(*loc)) *id_loc++=*loc++;} /* hex constant */
+ else if (xisdigit(*loc)) {*id_loc++='~';
+ while (xisdigit(*loc)) *id_loc++=*loc++;} /* octal constant */
+ else goto dec; /* decimal constant */
+ }
+ else { /* decimal constant */
+ if (*(loc-1)=='.' && !xisdigit(*loc)) goto mistake; /* not a constant */
+ dec: *id_loc++=*(loc-1);
+ while (xisdigit(*loc) || *loc=='.') *id_loc++=*loc++;
+ if (*loc=='e' || *loc=='E') { /* float constant */
+ *id_loc++='_'; loc++;
+ if (*loc=='+' || *loc=='-') *id_loc++=*loc++;
+ while (xisdigit(*loc)) *id_loc++=*loc++;
+ }
+ }
+ while (*loc=='u' || *loc=='U' || *loc=='l' || *loc=='L'
+ || *loc=='f' || *loc=='F') {
+ *id_loc++='$'; *id_loc++=toupper(*loc); loc++;
+ }
+ return(constant);
+}
+
+@ \CEE/ strings and character constants, delimited by double and single
+quotes, respectively, can contain newlines or instances of their own
+delimiters if they are protected by a backslash. We follow this
+convention, but do not allow the string to be longer than |longest_name|.
+
+@<Get a string@>= {
+ char delim = c; /* what started the string */
+ id_first = section_text+1;
+ id_loc = section_text;
+ if (delim=='\'' && *(loc-2)=='@@') {*++id_loc='@@'; *++id_loc='@@';}
+ *++id_loc=delim;
+ if (delim=='L') { /* wide character constant */
+ delim=*loc++; *++id_loc=delim;
+ }
+ if (delim=='<') delim='>'; /* for file names in |#include| lines */
+ while (1) {
+ if (loc>=limit) {
+ if(*(limit-1)!='\\') {
+ err_print("! String didn't end"); loc=limit; break;
+@.String didn't end@>
+ }
+ if(get_line()==0) {
+ err_print("! Input ended in middle of string"); loc=buffer; break;
+@.Input ended in middle of string@>
+ }
+ }
+ if ((c=*loc++)==delim) {
+ if (++id_loc<=section_text_end) *id_loc=c;
+ break;
+ }
+ if (c=='\\') if (loc>=limit) continue;
+ else if (++id_loc<=section_text_end) {
+ *id_loc = '\\'; c=*loc++;
+ }
+ if (++id_loc<=section_text_end) *id_loc=c;
+ }
+ if (id_loc>=section_text_end) {
+ printf("\n! String too long: ");
+@.String too long@>
+ term_write(section_text+1,25);
+ printf("..."); mark_error;
+ }
+ id_loc++;
+ return(string);
+}
+
+@ After an \.{@@} sign has been scanned, the next character tells us
+whether there is more work to do.
+
+@<Get control code and possible section name@>= {
+ c=*loc++;
+ switch(ccode[(eight_bits)c]) {
+ case translit_code: err_print("! Use @@l in limbo only"); continue;
+@.Use @@l in limbo...@>
+ case underline: xref_switch=def_flag; continue;
+ case trace: tracing=c-'0'; continue;
+ case xref_roman: case xref_wildcard: case xref_typewriter:
+ case noop: case TeX_string: c=ccode[c]; skip_restricted(); return(c);
+ case section_name:
+ @<Scan the section name and make |cur_section| point to it@>;
+ case verbatim: @<Scan a verbatim string@>;
+ case ord: @<Get a string@>;
+ default: return(ccode[(eight_bits)c]);
+ }
+}
+
+@ The occurrence of a section name sets |xref_switch| to zero,
+because the section name might (for example) follow \&{int}.
+
+@<Scan the section name...@>= {
+ char *k; /* pointer into |section_text| */
+ cur_section_char=*(loc-1);
+ @<Put section name into |section_text|@>;
+ if (k-section_text>3 && strncmp(k-2,"...",3)==0)
+ cur_section=section_lookup(section_text+1,k-3,1); /* 1 indicates a prefix */
+ else cur_section=section_lookup(section_text+1,k,0);
+ xref_switch=0; return(section_name);
+}
+
+@ Section names are placed into the |section_text| array with consecutive spaces,
+tabs, and carriage-returns replaced by single spaces. There will be no
+spaces at the beginning or the end. (We set |section_text[0]=' '| to facilitate
+this, since the |section_lookup| routine uses |section_text[1]| as the first
+character of the name.)
+
+@<Set init...@>=section_text[0]=' ';
+
+@ @<Put section name...@>=
+k=section_text;
+while (1) {
+ if (loc>limit && get_line()==0) {
+ err_print("! Input ended in section name");
+@.Input ended in section name@>
+ loc=buffer+1; break;
+ }
+ c=*loc;
+ @<If end of name or erroneous control code, |break|@>;
+ loc++; if (k<section_text_end) k++;
+ if (xisspace(c)) {
+ c=' '; if (*(k-1)==' ') k--;
+ }
+*k=c;
+}
+if (k>=section_text_end) {
+ printf("\n! Section name too long: ");
+@.Section name too long@>
+ term_write(section_text+1,25);
+ printf("..."); mark_harmless;
+}
+if (*k==' ' && k>section_text) k--;
+
+@ @<If end of name...@>=
+if (c=='@@') {
+ c=*(loc+1);
+ if (c=='>') {
+ loc+=2; break;
+ }
+ if (ccode[(eight_bits)c]==new_section) {
+ err_print("! Section name didn't end"); break;
+@.Section name didn't end@>
+ }
+ if (c!='@@') {
+ err_print("! Control codes are forbidden in section name"); break;
+@.Control codes are forbidden...@>
+ }
+ *(++k)='@@'; loc++; /* now |c==*loc| again */
+}
+
+@ This function skips over a restricted context at relatively high speed.
+
+@<Predecl...@>=
+void skip_restricted();
+
+@ @c
+void
+skip_restricted()
+{
+ id_first=loc; *(limit+1)='@@';
+false_alarm:
+ while (*loc!='@@') loc++;
+ id_loc=loc;
+ if (loc++>limit) {
+ err_print("! Control text didn't end"); loc=limit;
+@.Control text didn't end@>
+ }
+ else {
+ if (*loc=='@@'&&loc<=limit) {loc++; goto false_alarm;}
+ if (*loc++!='>')
+ err_print("! Control codes are forbidden in control text");
+@.Control codes are forbidden...@>
+ }
+}
+
+@ At the present point in the program we
+have |*(loc-1)==verbatim|; we set |id_first| to the beginning
+of the string itself, and |id_loc| to its ending-plus-one location in the
+buffer. We also set |loc| to the position just after the ending delimiter.
+
+@<Scan a verbatim string@>= {
+ id_first=loc++; *(limit+1)='@@'; *(limit+2)='>';
+ while (*loc!='@@' || *(loc+1)!='>') loc++;
+ if (loc>=limit) err_print("! Verbatim string didn't end");
+@.Verbatim string didn't end@>
+ id_loc=loc; loc+=2;
+ return (verbatim);
+}
+
+@** Phase one processing.
+We now have accumulated enough subroutines to make it possible to carry out
+\.{CWEAVE}'s first pass over the source file. If everything works right,
+both phase one and phase two of \.{CWEAVE} will assign the same numbers to
+sections, and these numbers will agree with what \.{CTANGLE} does.
+
+The global variable |next_control| often contains the most recent output of
+|get_next|; in interesting cases, this will be the control code that
+ended a section or part of a section.
+
+@<Global...@>=
+eight_bits next_control; /* control code waiting to be acting upon */
+
+@ The overall processing strategy in phase one has the following
+straightforward outline.
+
+@<Predecl...@>=
+void phase_one();
+
+@ @c
+void
+phase_one() {
+ phase=1; reset_input(); section_count=0;
+ skip_limbo(); change_exists=0;
+ while (!input_has_ended)
+ @<Store cross-reference data for the current section@>;
+ changed_section[section_count]=change_exists;
+ /* the index changes if anything does */
+ phase=2; /* prepare for second phase */
+ @<Print error messages about unused or undefined section names@>;
+}
+
+@ @<Store cross-reference data...@>=
+{
+ if (++section_count==max_sections) overflow("section number");
+ changed_section[section_count]=changing;
+ /* it will become 1 if any line changes */
+ if (*(loc-1)=='*' && show_progress) {
+ printf("*%d",section_count);
+ update_terminal; /* print a progress report */
+ }
+ @<Store cross-references in the \TEX/ part of a section@>;
+ @<Store cross-references in the definition part of a section@>;
+ @<Store cross-references in the \CEE/ part of a section@>;
+ if (changed_section[section_count]) change_exists=1;
+}
+
+@ The |C_xref| subroutine stores references to identifiers in
+\CEE/ text material beginning with the current value of |next_control|
+and continuing until |next_control| is `\.\{' or `\.{\v}', or until the next
+``milestone'' is passed (i.e., |next_control>=format_code|). If
+|next_control>=format_code| when |C_xref| is called, nothing will happen;
+but if |next_control=='|'| upon entry, the procedure assumes that this is
+the `\.{\v}' preceding \CEE/ text that is to be processed.
+
+The parameter |spec_ctrl| is used to change this behavior. In most cases
+|C_xref| is called with |spec_ctrl==ignore|, which triggers the default
+processing described above. If |spec_ctrl==section_name|, section names will
+be gobbled. This is used when \CEE/ text in the \TEX/ part or inside comments
+is parsed: It allows for section names to appear in \pb, but these
+strings will not be entered into the cross reference lists since they are not
+definitions of section names.
+
+The program uses the fact that our internal code numbers satisfy
+the relations |xref_roman==identifier+roman| and |xref_wildcard==identifier
++wildcard| and |xref_typewriter==identifier+typewriter|,
+as well as |normal==0|.
+
+@<Predecl...@>=
+void C_xref();
+
+@ @c
+void
+C_xref( spec_ctrl ) /* makes cross-references for \CEE/ identifiers */
+ eight_bits spec_ctrl;
+{
+ name_pointer p; /* a referenced name */
+ while (next_control<format_code || next_control==spec_ctrl) {
+ if (next_control>=identifier && next_control<=xref_typewriter) {
+ if (next_control>identifier) @<Replace |"@@@@"| by |"@@"| @>@;
+ p=id_lookup(id_first, id_loc,next_control-identifier); new_xref(p);
+ }
+ if (next_control==section_name) {
+ section_xref_switch=cite_flag;
+ new_section_xref(cur_section);
+ }
+ next_control=get_next();
+ if (next_control=='|' || next_control==begin_comment ||
+ next_control==begin_short_comment) return;
+ }
+}
+
+@ The |outer_xref| subroutine is like |C_xref| except that it begins
+with |next_control!='|'| and ends with |next_control>=format_code|. Thus, it
+handles \CEE/ text with embedded comments.
+
+@<Predecl...@>=
+void outer_xref();
+
+@ @c
+void
+outer_xref() /* extension of |C_xref| */
+{
+ int bal; /* brace level in comment */
+ while (next_control<format_code)
+ if (next_control!=begin_comment && next_control!=begin_short_comment)
+ C_xref(ignore);
+ else {
+ boolean is_long_comment=(next_control==begin_comment);
+ bal=copy_comment(is_long_comment,1); next_control='|';
+ while (bal>0) {
+ C_xref(section_name); /* do not reference section names in comments */
+ if (next_control=='|') bal=copy_comment(is_long_comment,bal);
+ else bal=0; /* an error message will occur in phase two */
+ }
+ }
+}
+
+@ In the \TEX/ part of a section, cross-reference entries are made only for
+the identifiers in \CEE/ texts enclosed in \pb, or for control texts
+enclosed in \.{@@\^}$\,\ldots\,$\.{@@>} or \.{@@.}$\,\ldots\,$\.{@@>}
+or \.{@@:}$\,\ldots\,$\.{@@>}.
+
+@<Store cross-references in the \T...@>=
+while (1) {
+ switch (next_control=skip_TeX()) {
+ case translit_code: err_print("! Use @@l in limbo only"); continue;
+@.Use @@l in limbo...@>
+ case underline: xref_switch=def_flag; continue;
+ case trace: tracing=*(loc-1)-'0'; continue;
+ case '|': C_xref(section_name); break;
+ case xref_roman: case xref_wildcard: case xref_typewriter:
+ case noop: case section_name:
+ loc-=2; next_control=get_next(); /* scan to \.{@@>} */
+ if (next_control>=xref_roman && next_control<=xref_typewriter) {
+ @<Replace |"@@@@"| by |"@@"| @>@;
+ new_xref(id_lookup(id_first, id_loc,next_control-identifier));
+ }
+ break;
+ }
+ if (next_control>=format_code) break;
+}
+
+@ @<Replace |"@@@@"| by |"@@"| @>=
+{
+ char *src=id_first,*dst=id_first;
+ while(src<id_loc){
+ if(*src=='@@') src++;
+ *dst++=*src++;
+ }
+ id_loc=dst;
+ while (dst<src) *dst++=' '; /* clean up in case of error message display */
+}
+
+@ During the definition and \CEE/ parts of a section, cross-references
+are made for all identifiers except reserved words. However, the right
+identifier in a format definition is not referenced, and the left
+identifier is referenced only if it has been explicitly
+underlined (preceded by \.{@@!}).
+The \TEX/ code in comments is, of course, ignored, except for
+\CEE/ portions enclosed in \pb; the text of a section name is skipped
+entirely, even if it contains \pb\ constructions.
+
+The variables |lhs| and |rhs| point to the respective identifiers involved
+in a format definition.
+
+@<Global...@>=
+name_pointer lhs, rhs; /* pointers to |byte_start| for format identifiers */
+
+@ When we get to the following code we have |next_control>=format_code|.
+
+@<Store cross-references in the d...@>=
+while (next_control<=definition) { /* |format_code| or |definition| */
+ if (next_control==definition) {
+ xref_switch=def_flag; /* implied \.{@@!} */
+ next_control=get_next();
+ } else @<Process a format definition@>;
+ outer_xref();
+}
+
+@ Error messages for improper format definitions will be issued in phase
+two. Our job in phase one is to define the |ilk| of a properly formatted
+identifier, and to remove cross-references to identifiers that we now
+discover should be unindexed.
+
+@<Process a form...@>= {
+ next_control=get_next();
+ if (next_control==identifier) {
+ lhs=id_lookup(id_first, id_loc,normal); lhs->ilk=normal;
+ if (xref_switch) new_xref(lhs);
+ next_control=get_next();
+ if (next_control==identifier) {
+ rhs=id_lookup(id_first, id_loc,normal);
+ lhs->ilk=rhs->ilk;
+ if (unindexed(lhs)) { /* retain only underlined entries */
+ xref_pointer q,r=NULL;
+ for (q=(xref_pointer)lhs->xref;q>xmem;q=q->xlink)
+ if (q->num<def_flag)
+ if (r) r->xlink=q->xlink;
+ else lhs->xref=(char*)q->xlink;
+ else r=q;
+ }
+ next_control=get_next();
+ }
+ }
+}
+
+@ A much simpler processing of format definitions occurs when the
+definition is found in limbo.
+
+@<Process simple format in limbo@>=
+{
+ if (get_next()!=identifier)
+ err_print("! Missing left identifier of @@s");
+@.Missing left identifier...@>
+ else {
+ lhs=id_lookup(id_first,id_loc,normal);
+ if (get_next()!=identifier)
+ err_print("! Missing right identifier of @@s");
+@.Missing right identifier...@>
+ else {
+ rhs=id_lookup(id_first,id_loc,normal);
+ lhs->ilk=rhs->ilk;
+ }
+ }
+}
+
+@ Finally, when the \TEX/ and definition parts have been treated, we have
+|next_control>=begin_C|.
+
+@<Store cross-references in the \CEE/...@>=
+if (next_control<=section_name) { /* |begin_C| or |section_name| */
+ if (next_control==begin_C) section_xref_switch=0;
+ else {
+ section_xref_switch=def_flag;
+ if(cur_section_char=='(' && cur_section!=name_dir)
+ set_file_flag(cur_section);
+ }
+ do {
+ if (next_control==section_name && cur_section!=name_dir)
+ new_section_xref(cur_section);
+ next_control=get_next(); outer_xref();
+ } while ( next_control<=section_name);
+}
+
+@ After phase one has looked at everything, we want to check that each
+section name was both defined and used. The variable |cur_xref| will point
+to cross-references for the current section name of interest.
+
+@<Global...@>=
+xref_pointer cur_xref; /* temporary cross-reference pointer */
+boolean an_output; /* did |file_flag| precede |cur_xref|? */
+
+@ The following recursive procedure
+walks through the tree of section names and prints out anomalies.
+@^recursion@>
+
+@<Predecl...@>=
+void section_check();
+
+@ @c
+void
+section_check(p)
+name_pointer p; /* print anomalies in subtree |p| */
+{
+ if (p) {
+ section_check(p->llink);
+ cur_xref=(xref_pointer)p->xref;
+ if (cur_xref->num==file_flag) {an_output=1; cur_xref=cur_xref->xlink;}
+ else an_output=0;
+ if (cur_xref->num <def_flag) {
+ printf("\n! Never defined: <"); print_section_name(p); putchar('>'); mark_harmless;
+@.Never defined: <section name>@>
+ }
+ while (cur_xref->num >=cite_flag) cur_xref=cur_xref->xlink;
+ if (cur_xref==xmem && !an_output) {
+ printf("\n! Never used: <"); print_section_name(p); putchar('>'); mark_harmless;
+@.Never used: <section name>@>
+ }
+ section_check(p->rlink);
+ }
+}
+
+@ @<Print error messages about un...@>=section_check(root)
+
+@* Low-level output routines.
+The \TEX/ output is supposed to appear in lines at most |line_length|
+characters long, so we place it into an output buffer. During the output
+process, |out_line| will hold the current line number of the line about to
+be output.
+
+@<Global...@>=
+char out_buf[line_length+1]; /* assembled characters */
+char *out_ptr; /* just after last character in |out_buf| */
+char *out_buf_end = out_buf+line_length; /* end of |out_buf| */
+int out_line; /* number of next line to be output */
+
+@ The |flush_buffer| routine empties the buffer up to a given breakpoint,
+and moves any remaining characters to the beginning of the next line.
+If the |per_cent| parameter is 1 a |'%'| is appended to the line
+that is being output; in this case the breakpoint |b| should be strictly
+less than |out_buf_end|. If the |per_cent| parameter is |0|,
+trailing blanks are suppressed.
+The characters emptied from the buffer form a new line of output;
+if the |carryover| parameter is true, a |"%"| in that line will be
+carried over to the next line (so that \TEX/ will ignore the completion
+of commented-out text).
+
+@d c_line_write(c) fflush(active_file),fwrite(out_buf+1,sizeof(char),c,active_file)
+@d tex_putc(c) putc(c,active_file)
+@d tex_new_line putc('\n',active_file)
+@d tex_printf(c) fprintf(active_file,c)
+
+@c
+void
+flush_buffer(b,per_cent,carryover)
+char *b; /* outputs from |out_buf+1| to |b|,where |b<=out_ptr| */
+boolean per_cent,carryover;
+{
+ char *j; j=b; /* pointer into |out_buf| */
+ if (! per_cent) /* remove trailing blanks */
+ while (j>out_buf && *j==' ') j--;
+ c_line_write(j-out_buf);
+ if (per_cent) tex_putc('%');
+ tex_new_line; out_line++;
+ if (carryover)
+ while (j>out_buf)
+ if (*j--=='%' && (j==out_buf || *j!='\\')) {
+ *b--='%'; break;
+ }
+ if (b<out_ptr) strncpy(out_buf+1,b+1,out_ptr-b);
+ out_ptr-=b-out_buf;
+}
+
+@ When we are copying \TEX/ source material, we retain line breaks
+that occur in the input, except that an empty line is not
+output when the \TEX/ source line was nonempty. For example, a line
+of the \TEX/ file that contains only an index cross-reference entry
+will not be copied. The |finish_line| routine is called just before
+|get_line| inputs a new line, and just after a line break token has
+been emitted during the output of translated \CEE/ text.
+
+@c
+void
+finish_line() /* do this at the end of a line */
+{
+ char *k; /* pointer into |buffer| */
+ if (out_ptr>out_buf) flush_buffer(out_ptr,0,0);
+ else {
+ for (k=buffer; k<=limit; k++)
+ if (!(xisspace(*k))) return;
+ flush_buffer(out_buf,0,0);
+ }
+}
+
+@ In particular, the |finish_line| procedure is called near the very
+beginning of phase two. We initialize the output variables in a slightly
+tricky way so that the first line of the output file will be
+`\.{\\input cwebmac}'.
+
+@<Set init...@>=
+out_ptr=out_buf+1; out_line=1; active_file=tex_file;
+*out_ptr='c'; tex_printf("\\input cwebma");
+
+@ When we wish to append one character |c| to the output buffer, we write
+`|out(c)|'; this will cause the buffer to be emptied if it was already
+full. If we want to append more than one character at once, we say
+|out_str(s)|, where |s| is a string containing the characters.
+
+A line break will occur at a space or after a single-nonletter
+\TEX/ control sequence.
+
+@d out(c) {if (out_ptr>=out_buf_end) break_out(); *(++out_ptr)=c;}
+
+@c
+void
+out_str(s) /* output characters from |s| to end of string */
+char *s;
+{
+ while (*s) out(*s++);
+}
+
+@ The |break_out| routine is called just before the output buffer is about
+to overflow. To make this routine a little faster, we initialize position
+0 of the output buffer to `\.\\'; this character isn't really output.
+
+@<Set init...@>=
+out_buf[0]='\\';
+
+@ A long line is broken at a blank space or just before a backslash that isn't
+preceded by another backslash. In the latter case, a |'%'| is output at
+the break.
+
+@<Predecl...@>=
+void break_out();
+
+@ @c
+void
+break_out() /* finds a way to break the output line */
+{
+ char *k=out_ptr; /* pointer into |out_buf| */
+ while (1) {
+ if (k==out_buf) @<Print warning message, break the line, |return|@>;
+ if (*k==' ') {
+ flush_buffer(k,0,1); return;
+ }
+ if (*(k--)=='\\' && *k!='\\') { /* we've decreased |k| */
+ flush_buffer(k,1,1); return;
+ }
+ }
+}
+
+@ We get to this section only in the unusual case that the entire output line
+consists of a string of backslashes followed by a string of nonblank
+non-backslashes. In such cases it is almost always safe to break the
+line by putting a |'%'| just before the last character.
+
+@<Print warning message...@>=
+{
+ printf("\n! Line had to be broken (output l. %d):\n",out_line);
+@.Line had to be broken@>
+ term_write(out_buf+1, out_ptr-out_buf-1);
+ new_line; mark_harmless;
+ flush_buffer(out_ptr-1,1,1); return;
+}
+
+@ Here is a macro that outputs a section number in decimal notation.
+The number to be converted by |out_section| is known to be less than
+|def_flag|, so it cannot have more than five decimal digits. If
+the section is changed, we output `\.{\\*}' just after the number.
+
+@c
+void
+out_section(n)
+sixteen_bits n;
+{
+ char s[6];
+ sprintf(s,"%d",n); out_str(s);
+ if(changed_section[n]) out_str ("\\*");
+@.\\*@>
+}
+
+@ The |out_name| procedure is used to output an identifier or index
+entry, enclosing it in braces.
+
+@c
+void
+out_name(p)
+name_pointer p;
+{
+ char *k, *k_end=(p+1)->byte_start; /* pointers into |byte_mem| */
+ out('{');
+ for (k=p->byte_start; k<k_end; k++) {
+ if (isxalpha(*k)) out('\\');
+ out(*k);
+ }
+ out('}');
+}
+
+@* Routines that copy \TEX/ material.
+During phase two, we use subroutines |copy_limbo|, |copy_TeX|, and
+|copy_comment| in place of the analogous |skip_limbo|, |skip_TeX|, and
+|skip_comment| that were used in phase one. (Well, |copy_comment|
+was actually written in such a way that it functions as |skip_comment|
+in phase one.)
+
+The |copy_limbo| routine, for example, takes \TEX/ material that is not
+part of any section and transcribes it almost verbatim to the output file.
+The use of `\.{@@}' signs is severely restricted in such material:
+`\.{@@@@}' pairs are replaced by singletons; `\.{@@l}' and `\.{@@q}' and
+`\.{@@s}' are interpreted.
+
+@c
+void
+copy_limbo()
+{
+ char c;
+ while (1) {
+ if (loc>limit && (finish_line(), get_line()==0)) return;
+ *(limit+1)='@@';
+ while (*loc!='@@') out(*(loc++));
+ if (loc++<=limit) {
+ c=*loc++;
+ if (ccode[(eight_bits)c]==new_section) break;
+ switch (ccode[(eight_bits)c]) {
+ case translit_code: out_str("\\ATL"); break;
+@.\\ATL@>
+ case '@@': out('@@'); break;
+ case noop: skip_restricted(); break;
+ case format_code: if (get_next()==identifier) get_next();
+ if (loc>=limit) get_line(); /* avoid blank lines in output */
+ break; /* the operands of \.{@@s} are ignored on this pass */
+ default: err_print("! Double @@ should be used in limbo");
+@.Double @@ should be used...@>
+ out('@@');
+ }
+ }
+ }
+}
+
+@ The |copy_TeX| routine processes the \TEX/ code at the beginning of a
+section; for example, the words you are now reading were copied in this
+way. It returns the next control code or `\.{\v}' found in the input.
+We don't copy spaces or tab marks into the beginning of a line. This
+makes the test for empty lines in |finish_line| work.
+
+@ @f copy_TeX TeX
+@c
+eight_bits
+copy_TeX()
+{
+ char c; /* current character being copied */
+ while (1) {
+ if (loc>limit && (finish_line(), get_line()==0)) return(new_section);
+ *(limit+1)='@@';
+ while ((c=*(loc++))!='|' && c!='@@') {
+ out(c);
+ if (out_ptr==out_buf+1 && (xisspace(c))) out_ptr--;
+ }
+ if (c=='|') return('|');
+ if (loc<=limit) return(ccode[(eight_bits)*(loc++)]);
+ }
+}
+
+@ The |copy_comment| function issues a warning if more braces are opened than
+closed, and in the case of a more serious error it supplies enough
+braces to keep \TEX/ from complaining about unbalanced braces.
+Instead of copying the \TEX/ material
+into the output buffer, this function copies it into the token memory
+(in phase two only).
+The abbreviation |app_tok(t)| is used to append token |t| to the current
+token list, and it also makes sure that it is possible to append at least
+one further token without overflow.
+
+@d app_tok(c) {if (tok_ptr+2>tok_mem_end) overflow("token"); *(tok_ptr++)=c;}
+
+@<Predec...@>=
+int copy_comment();
+
+@ @c
+int copy_comment(is_long_comment,bal) /* copies \TEX/ code in comments */
+boolean is_long_comment; /* is this a traditional \CEE/ comment? */
+int bal; /* brace balance */
+{
+ char c; /* current character being copied */
+ while (1) {
+ if (loc>limit) {
+ if (is_long_comment) {
+ if (get_line()==0) {
+ err_print("! Input ended in mid-comment");
+@.Input ended in mid-comment@>
+ loc=buffer+1; goto done;
+ }
+ }
+ else {
+ if (bal>1) err_print("! Missing } in comment");
+@.Missing \} in comment@>
+ goto done;
+ }
+ }
+ c=*(loc++);
+ if (c=='|') return(bal);
+ if (is_long_comment) @<Check for end of comment@>;
+ if (phase==2) {
+ if (ishigh(c)) app_tok(quoted_char);
+ app_tok(c);
+ }
+ @<Copy special things when |c=='@@', '\\'|@>;
+ if (c=='{') bal++;
+ else if (c=='}') {
+ if(bal>1) bal--;
+ else {err_print("! Extra } in comment");
+@.Extra \} in comment@>
+ if (phase==2) tok_ptr--;
+ }
+ }
+ }
+done:@<Clear |bal| and |return|@>;
+}
+
+@ @<Check for end of comment@>=
+if (c=='*' && *loc=='/') {
+ loc++;
+ if (bal>1) err_print("! Missing } in comment");
+@.Missing \} in comment@>
+ goto done;
+}
+
+@ @<Copy special things when |c=='@@'...@>=
+if (c=='@@') {
+ if (*(loc++)!='@@') {
+ err_print("! Illegal use of @@ in comment");
+@.Illegal use of @@...@>
+ loc-=2; if (phase==2) *(tok_ptr-1)=' '; goto done;
+ }
+}
+else if (c=='\\' && *loc!='@@')
+ if (phase==2) app_tok(*(loc++)) else loc++;
+
+@ We output
+enough right braces to keep \TEX/ happy.
+
+@<Clear |bal|...@>=
+if (phase==2) while (bal-- >0) app_tok('}');
+return(0);
+
+@** Parsing.
+The most intricate part of \.{CWEAVE} is its mechanism for converting
+\CEE/-like code into \TEX/ code, and we might as well plunge into this
+aspect of the program now. A ``bottom up'' approach is used to parse the
+\CEE/-like material, since \.{CWEAVE} must deal with fragmentary
+constructions whose overall ``part of speech'' is not known.
+
+At the lowest level, the input is represented as a sequence of entities
+that we shall call {\it scraps}, where each scrap of information consists
+of two parts, its {\it category} and its {\it translation}. The category
+is essentially a syntactic class, and the translation is a token list that
+represents \TEX/ code. Rules of syntax and semantics tell us how to
+combine adjacent scraps into larger ones, and if we are lucky an entire
+\CEE/ text that starts out as hundreds of small scraps will join
+together into one gigantic scrap whose translation is the desired \TEX/
+code. If we are unlucky, we will be left with several scraps that don't
+combine; their translations will simply be output, one by one.
+
+The combination rules are given as context-sensitive productions that are
+applied from left to right. Suppose that we are currently working on the
+sequence of scraps $s_1\,s_2\ldots s_n$. We try first to find the longest
+production that applies to an initial substring $s_1\,s_2\ldots\,$; but if
+no such productions exist, we try to find the longest production
+applicable to the next substring $s_2\,s_3\ldots\,$; and if that fails, we
+try to match $s_3\,s_4\ldots\,$, etc.
+
+A production applies if the category codes have a given pattern. For
+example, one of the productions (see rule~3) is
+$$\hbox{|exp| }\left\{\matrix{\hbox{|binop|}\cr\hbox{|unorbinop|}}\right\}
+\hbox{ |exp| }\RA\hbox{ |exp|}$$
+and it means that three consecutive scraps whose respective categories are
+|exp|, |binop| (or |unorbinop|),
+and |exp| are converted to one scrap whose category
+is |exp|. The translations of the original
+scraps are simply concatenated. The case of
+$$\hbox{|exp| |comma| |exp| $\RA$ |exp|} \hskip4emE_1C\,\\{opt}9\,E_2$$
+(rule 4) is only slightly more complicated:
+Here the resulting |exp| translation
+consists not only of the three original translations, but also of the
+tokens |opt| and 9 between the translations of the
+|comma| and the following |exp|.
+In the \TEX/ file, this will specify an optional line break after the
+comma, with penalty 90.
+
+At each opportunity the longest possible production is applied. For
+example, if the current sequence of scraps is |int_like| |cast|
+|lbrace|, rule 31 is applied; but if the sequence is |int_like| |cast|
+followed by anything other than |lbrace|, rule 32 takes effect.
+
+Translation rules such as `$E_1C\,\\{opt}9\,E_2$' above use subscripts
+to distinguish between translations of scraps whose categories have the
+same initial letter; these subscripts are assigned from left to right.
+
+@ Here is a list of the category codes that scraps can have.
+(A few others, like |int_like|, have already been defined; the
+|cat_name| array contains a complete list.)
+
+@d exp 1 /* denotes an expression, including perhaps a single identifier */
+@d unop 2 /* denotes a unary operator */
+@d binop 3 /* denotes a binary operator */
+@d unorbinop 4
+ /* denotes an operator that can be unary or binary, depending on context */
+@d cast 5 /* denotes a cast */
+@d question 6 /* denotes a question mark and possibly the expressions flanking it */
+@d lbrace 7 /* denotes a left brace */
+@d rbrace 8 /* denotes a right brace */
+@d decl_head 9 /* denotes an incomplete declaration */
+@d comma 10 /* denotes a comma */
+@d lpar 11 /* denotes a left parenthesis or left bracket */
+@d rpar 12 /* denotes a right parenthesis or right bracket */
+@d prelangle 13 /* denotes `$<$' before we know what it is */
+@d prerangle 14 /* denotes `$>$' before we know what it is */
+@d langle 15 /* denotes `$<$' when it's used as angle bracket in a template */
+@d colcol 18 /* denotes `::' */
+@d base 19 /* denotes a colon that introduces a base specifier */
+@d decl 20 /* denotes a complete declaration */
+@d struct_head 21 /* denotes the beginning of a structure specifier */
+@d stmt 23 /* denotes a complete statement */
+@d function 24 /* denotes a complete function */
+@d fn_decl 25 /* denotes a function declarator */
+@d semi 27 /* denotes a semicolon */
+@d colon 28 /* denotes a colon */
+@d tag 29 /* denotes a statement label */
+@d if_head 30 /* denotes the beginning of a compound conditional */
+@d else_head 31 /* denotes a prefix for a compound statement */
+@d if_clause 32 /* pending \.{if} together with a condition */
+@d lproc 35 /* begins a preprocessor command */
+@d rproc 36 /* ends a preprocessor command */
+@d insert 37 /* a scrap that gets combined with its neighbor */
+@d section_scrap 38 /* section name */
+@d dead 39 /* scrap that won't combine */
+@d begin_arg 58 /* \.{@@[} */
+@d end_arg 59 /* \.{@@]} */
+
+@<Glo...@>=
+char cat_name[256][12];
+eight_bits cat_index;
+
+@ @<Set in...@>=
+ for (cat_index=0;cat_index<255;cat_index++)
+ strcpy(cat_name[cat_index],"UNKNOWN");
+ strcpy(cat_name[exp],"exp");
+ strcpy(cat_name[unop],"unop");
+ strcpy(cat_name[binop],"binop");
+ strcpy(cat_name[unorbinop],"unorbinop");
+ strcpy(cat_name[cast],"cast");
+ strcpy(cat_name[question],"?");
+ strcpy(cat_name[lbrace],"{"@q}@>);
+ strcpy(cat_name[rbrace],@q{@>"}");
+ strcpy(cat_name[decl_head],"decl_head");
+ strcpy(cat_name[comma],",");
+ strcpy(cat_name[lpar],"(");
+ strcpy(cat_name[rpar],")");
+ strcpy(cat_name[prelangle],"<");
+ strcpy(cat_name[prerangle],">");
+ strcpy(cat_name[langle],"\\<");
+ strcpy(cat_name[colcol],"::");
+ strcpy(cat_name[base],"\\:");
+ strcpy(cat_name[decl],"decl");
+ strcpy(cat_name[struct_head],"struct_head");
+ strcpy(cat_name[stmt],"stmt");
+ strcpy(cat_name[function],"function");
+ strcpy(cat_name[fn_decl],"fn_decl");
+ strcpy(cat_name[else_like],"else_like");
+ strcpy(cat_name[semi],";");
+ strcpy(cat_name[colon],":");
+ strcpy(cat_name[tag],"tag");
+ strcpy(cat_name[if_head],"if_head");
+ strcpy(cat_name[else_head],"else_head");
+ strcpy(cat_name[if_clause],"if()");
+ strcpy(cat_name[lproc],"#{"@q}@>);
+ strcpy(cat_name[rproc],@q{@>"#}");
+ strcpy(cat_name[insert],"insert");
+ strcpy(cat_name[section_scrap],"section");
+ strcpy(cat_name[dead],"@@d");
+ strcpy(cat_name[public_like],"public");
+ strcpy(cat_name[operator_like],"operator");
+ strcpy(cat_name[new_like],"new");
+ strcpy(cat_name[catch_like],"catch");
+ strcpy(cat_name[for_like],"for");
+ strcpy(cat_name[do_like],"do");
+ strcpy(cat_name[if_like],"if");
+ strcpy(cat_name[raw_rpar],")?");
+ strcpy(cat_name[raw_unorbin],"unorbinop?");
+ strcpy(cat_name[const_like],"const");
+ strcpy(cat_name[raw_int],"raw");
+ strcpy(cat_name[int_like],"int");
+ strcpy(cat_name[case_like],"case");
+ strcpy(cat_name[sizeof_like],"sizeof");
+ strcpy(cat_name[struct_like],"struct");
+ strcpy(cat_name[typedef_like],"typedef");
+ strcpy(cat_name[define_like],"define");
+ strcpy(cat_name[begin_arg],"@@["@q]@>);
+ strcpy(cat_name[end_arg],@q[@>"@@]");
+ strcpy(cat_name[0],"zero");
+
+@ This code allows \.{CWEAVE} to display its parsing steps.
+
+@c
+void
+print_cat(c) /* symbolic printout of a category */
+eight_bits c;
+{
+ printf(cat_name[c]);
+}
+
+@ The token lists for translated \TEX/ output contain some special control
+symbols as well as ordinary characters. These control symbols are
+interpreted by \.{CWEAVE} before they are written to the output file.
+
+\yskip\hang |break_space| denotes an optional line break or an en space;
+
+\yskip\hang |force| denotes a line break;
+
+\yskip\hang |big_force| denotes a line break with additional vertical space;
+
+\yskip\hang |preproc_line| denotes that the line will be printed flush left;
+
+\yskip\hang |opt| denotes an optional line break (with the continuation
+line indented two ems with respect to the normal starting position)---this
+code is followed by an integer |n|, and the break will occur with penalty
+$10n$;
+
+\yskip\hang |backup| denotes a backspace of one em;
+
+\yskip\hang |cancel| obliterates any |break_space|, |opt|, |force|, or
+|big_force| tokens that immediately precede or follow it and also cancels any
+|backup| tokens that follow it;
+
+\yskip\hang |indent| causes future lines to be indented one more em;
+
+\yskip\hang |outdent| causes future lines to be indented one less em.
+
+\yskip\noindent All of these tokens are removed from the \TEX/ output that
+comes from \CEE/ text between \pb\ signs; |break_space| and |force| and
+|big_force| become single spaces in this mode. The translation of other
+\CEE/ texts results in \TEX/ control sequences \.{\\1}, \.{\\2},
+\.{\\3}, \.{\\4}, \.{\\5}, \.{\\6}, \.{\\7}, \.{\\8}
+corresponding respectively to
+|indent|, |outdent|, |opt|, |backup|, |break_space|, |force|,
+|big_force| and |preproc_line|.
+However, a sequence of consecutive `\.\ ', |break_space|,
+|force|, and/or |big_force| tokens is first replaced by a single token
+(the maximum of the given ones).
+
+The token |math_rel| will be translated into
+\.{\\MRL\{}, and it will get a matching \.\} later.
+Other control sequences in the \TEX/ output will be
+`\.{\\\\\{}$\,\ldots\,$\.\}'
+surrounding identifiers, `\.{\\\&\{}$\,\ldots\,$\.\}' surrounding
+reserved words, `\.{\\.\{}$\,\ldots\,$\.\}' surrounding strings,
+`\.{\\C\{}$\,\ldots\,$\.\}$\,$|force|' surrounding comments, and
+`\.{\\X$n$:}$\,\ldots\,$\.{\\X}' surrounding section names, where
+|n| is the section number.
+
+@d math_rel 0206
+@d big_cancel 0210 /* like |cancel|, also overrides spaces */
+@d cancel 0211 /* overrides |backup|, |break_space|, |force|, |big_force| */
+@d indent 0212 /* one more tab (\.{\\1}) */
+@d outdent 0213 /* one less tab (\.{\\2}) */
+@d opt 0214 /* optional break in mid-statement (\.{\\3}) */
+@d backup 0215 /* stick out one unit to the left (\.{\\4}) */
+@d break_space 0216 /* optional break between statements (\.{\\5}) */
+@d force 0217 /* forced break between statements (\.{\\6}) */
+@d big_force 0220 /* forced break with additional space (\.{\\7}) */
+@d preproc_line 0221 /* begin line without indentation (\.{\\8}) */
+@^high-bit character handling@>
+@d quoted_char 0222
+ /* introduces a character token in the range |0200|--|0377| */
+@d end_translation 0223 /* special sentinel token at end of list */
+@d inserted 0224 /* sentinel to mark translations of inserts */
+
+@ The raw input is converted into scraps according to the following table,
+which gives category codes followed by the translations.
+\def\stars {\.{**}}%
+The symbol `\stars' stands for `\.{\\\&\{{\rm identifier}\}}',
+i.e., the identifier itself treated as a reserved word.
+The right-hand column is the so-called |mathness|, which is explained
+further below.
+
+An identifier |c| of length 1 is translated as \.{\\\v c} instead of
+as \.{\\\\\{c\}}. An identifier \.{CAPS} in all caps is translated as
+\.{\\.\{CAPS\}} instead of as \.{\\\\\{CAPS\}}. An identifier that has
+become a reserved word via |typedef| is translated with \.{\\\&} replacing
+\.{\\\\} and |raw_int| replacing |exp|.
+
+A string of length greater than 20 is broken into pieces of size at most~20
+with discretionary breaks in between.
+
+\yskip\halign{\quad#\hfil&\quad#\hfil&\quad\hfil#\hfil\cr
+\.{!=}&|binop|: \.{\\I}&yes\cr
+\.{<=}&|binop|: \.{\\Z}&yes\cr
+\.{>=}&|binop|: \.{\\G}&yes\cr
+\.{==}&|binop|: \.{\\E}&yes\cr
+\.{\&\&}&|binop|: \.{\\W}&yes\cr
+\.{\v\v}&|binop|: \.{\\V}&yes\cr
+\.{++}&|binop|: \.{\\PP}&yes\cr
+\.{--}&|binop|: \.{\\MM}&yes\cr
+\.{->}&|binop|: \.{\\MG}&yes\cr
+\.{>>}&|binop|: \.{\\GG}&yes\cr
+\.{<<}&|binop|: \.{\\LL}&yes\cr
+\.{::}&|colcol|: \.{\\DC}&maybe\cr
+\.{.*}&|binop|: \.{\\PA}&yes\cr
+\.{->*}&|binop|: \.{\\MGA}&yes\cr
+\.{...}&|exp|: \.{\\,\\ldots\\,}&yes\cr
+\."string\."&|exp|: \.{\\.\{}string with special characters quoted\.\}&maybe\cr
+\.{@@=}string\.{@@>}&|exp|: \.{\\vb\{}string with special characters
+ quoted\.\}&maybe\cr
+\.{@@'7'}&|exp|: \.{\\.\{@@'7'\}}&maybe\cr
+\.{077} or \.{\\77}&|exp|: \.{\\T\{\\\~77\}}&maybe\cr
+\.{0x7f}&|exp|: \.{\\T\{\\\^7f\}}&maybe\cr
+\.{77}&|exp|: \.{\\T\{77\}}&maybe\cr
+\.{77L}&|exp|: \.{\\T\{77\\\$L\}}&maybe\cr
+\.{0.1E5}&|exp|: \.{\\T\{0.1\\\_5\}}&maybe\cr
+\.+&|unorbinop|: \.+&yes\cr
+\.-&|unorbinop|: \.-&yes\cr
+\.*&|raw_unorbin|: \.*&yes\cr
+\./&|binop|: \./&yes\cr
+\.<&|prelangle|: \.{\\langle}&yes\cr
+\.=&|binop|: \.{\\K}&yes\cr
+\.>&|prerangle|: \.{\\rangle}&yes\cr
+\..&|binop|: \..&yes\cr
+\.{\v}&|binop|: \.{\\OR}&yes\cr
+\.\^&|binop|: \.{\\XOR}&yes\cr
+\.\%&|binop|: \.{\\MOD}&yes\cr
+\.?&|question|: \.{\\?}&yes\cr
+\.!&|unop|: \.{\\R}&yes\cr
+\.\~&|unop|: \.{\\CM}&yes\cr
+\.\&&|raw_unorbin|: \.{\\AND}&yes\cr
+\.(&|lpar|: \.(&maybe\cr
+\.[&|lpar|: \.[&maybe\cr
+\.)&|raw_rpar|: \.)&maybe\cr
+\.]&|raw_rpar|: \.]&maybe\cr
+\.\{&|lbrace|: \.\{&yes\cr
+\.\}&|lbrace|: \.\}&yes\cr
+\.,&|comma|: \.,&yes\cr
+\.;&|semi|: \.;&maybe\cr
+\.:&|colon|: \.:&maybe\cr
+\.\# (within line)&|unorbinop|: \.{\\\#}&yes\cr
+\.\# (at beginning)&|lproc|: |force| |preproc_line| \.{\\\#}&no\cr
+end of \.\# line&|rproc|: |force|&no\cr
+identifier&|exp|: \.{\\\\\{}identifier with underlines quoted\.\}&maybe\cr
+\.{asm}&|sizeof_like|: \stars&maybe\cr
+\.{auto}&|int_like|: \stars&maybe\cr
+\.{break}&|case_like|: \stars&maybe\cr
+\.{case}&|case_like|: \stars&maybe\cr
+\.{catch}&|catch_like|: \stars&maybe\cr
+\.{char}&|raw_int|: \stars&maybe\cr
+\.{class}&|struct_like|: \stars&maybe\cr
+\.{clock\_t}&|raw_int|: \stars&maybe\cr
+\.{const}&|const_like|: \stars&maybe\cr
+\.{continue}&|case_like|: \stars&maybe\cr
+\.{default}&|case_like|: \stars&maybe\cr
+\.{define}&|define_like|: \stars&maybe\cr
+\.{defined}&|sizeof_like|: \stars&maybe\cr
+\.{delete}&|sizeof_like|: \stars&maybe\cr
+\.{div\_t}&|raw_int|: \stars&maybe\cr
+\.{do}&|do_like|: \stars&maybe\cr
+\.{double}&|raw_int|: \stars&maybe\cr
+\.{elif}&|if_like|: \stars&maybe\cr
+\.{else}&|else_like|: \stars&maybe\cr
+\.{endif}&|if_like|: \stars&maybe\cr
+\.{enum}&|struct_like|: \stars&maybe\cr
+\.{error}&|if_like|: \stars&maybe\cr
+\.{extern}&|int_like|: \stars&maybe\cr
+\.{FILE}&|raw_int|: \stars&maybe\cr
+\.{float}&|raw_int|: \stars&maybe\cr
+\.{for}&|for_like|: \stars&maybe\cr
+\.{fpos\_t}&|raw_int|: \stars&maybe\cr
+\.{friend}&|int_like|: \stars&maybe\cr
+\.{goto}&|case_like|: \stars&maybe\cr
+\.{if}&|if_like|: \stars&maybe\cr
+\.{ifdef}&|if_like|: \stars&maybe\cr
+\.{ifndef}&|if_like|: \stars&maybe\cr
+\.{include}&|if_like|: \stars&maybe\cr
+\.{inline}&|int_like|: \stars&maybe\cr
+\.{int}&|raw_int|: \stars&maybe\cr
+\.{jmp\_buf}&|raw_int|: \stars&maybe\cr
+\.{ldiv\_t}&|raw_int|: \stars&maybe\cr
+\.{line}&|if_like|: \stars&maybe\cr
+\.{long}&|raw_int|: \stars&maybe\cr
+\.{new}&|new_like|: \stars&maybe\cr
+\.{NULL}&|exp|: \.{\\NULL}&yes\cr
+\.{offsetof}&|sizeof_like|: \stars&maybe\cr
+\.{operator}&|operator_like|: \stars&maybe\cr
+\.{pragma}&|if_like|: \stars&maybe\cr
+\.{private}&|public_like|: \stars&maybe\cr
+\.{protected}&|public_like|: \stars&maybe\cr
+\.{ptrdiff\_t}&|raw_int|: \stars&maybe\cr
+\.{public}&|public_like|: \stars&maybe\cr
+\.{register}&|int_like|: \stars&maybe\cr
+\.{return}&|case_like|: \stars&maybe\cr
+\.{short}&|raw_int|: \stars&maybe\cr
+\.{sig\_atomic\_t}&|raw_int|: \stars&maybe\cr
+\.{signed}&|raw_int|: \stars&maybe\cr
+\.{size\_t}&|raw_int|: \stars&maybe\cr
+\.{sizeof}&|sizeof_like|: \stars&maybe\cr
+\.{static}&|int_like|: \stars&maybe\cr
+\.{struct}&|struct_like|: \stars&maybe\cr
+\.{switch}&|if_like|: \stars&maybe\cr
+\.{template}&|int_like|: \stars&maybe\cr
+\.{TeX}&|exp|: \.{\\TeX}&yes\cr
+\.{this}&|exp|: \.{\\this}&yes\cr
+\.{throw}&|case_like|: \stars&maybe\cr
+\.{time\_t}&|raw_int|: \stars&maybe\cr
+\.{try}&|else_like|: \stars&maybe\cr
+\.{typedef}&|typedef_like|: \stars&maybe\cr
+\.{undef}&|if_like|: \stars&maybe\cr
+\.{union}&|struct_like|: \stars&maybe\cr
+\.{unsigned}&|raw_int|: \stars&maybe\cr
+\.{va\_dcl}&|decl|: \stars&maybe\cr
+\.{va\_list}&|raw_int|: \stars&maybe\cr
+\.{virtual}&|int_like|: \stars&maybe\cr
+\.{void}&|raw_int|: \stars&maybe\cr
+\.{volatile}&|const_like|: \stars&maybe\cr
+\.{wchar\_t}&|raw_int|: \stars&maybe\cr
+\.{while}&|if_like|: \stars&maybe\cr
+\.{@@,}&|insert|: \.{\\,}&maybe\cr
+\.{@@\v}&|insert|: |opt| \.0&maybe\cr
+\.{@@/}&|insert|: |force|&no\cr
+\.{@@\#}&|insert|: |big_force|&no\cr
+\.{@@+}&|insert|: |big_cancel| \.{\{\}} |break_space|
+ \.{\{\}} |big_cancel|&no\cr
+\.{@@;}&|semi|: &maybe\cr
+\.{@@[@q]@>}&|begin_arg|: &maybe\cr
+\.{@q[@>@@]}&|end_arg|: &maybe\cr
+\.{@@\&}&|insert|: \.{\\J}&maybe\cr
+\.{@@h}&|insert|: |force| \.{\\ATH} |force|&no\cr
+\.{@@<}\thinspace section name\thinspace\.{@@>}&|section_scrap|:
+ \.{\\X}$n$\.:translated section name\.{\\X}&maybe\cr
+\.{@@(@q)@>}\thinspace section name\thinspace\.{@@>}&|section_scrap|:
+ \.{\\X}$n$\.{:\\.\{}section name with special characters
+ quoted\.{\ \}\\X}&maybe\cr
+\.{/*}comment\.{*/}&|insert|: |cancel|
+ \.{\\C\{}translated comment\.\} |force|&no\cr
+\.{//}comment&|insert|: |cancel|
+ \.{\\SHC\{}translated comment\.\} |force|&no\cr
+}
+
+The construction \.{@@t}\thinspace stuff\/\thinspace\.{@@>} contributes
+\.{\\hbox\{}\thinspace stuff\/\thinspace\.\} to the following scrap.
+
+@i prod.w
+
+@* Implementing the productions.
+More specifically, a scrap is a structure consisting of a category
+|cat| and a |text_pointer| |trans|, which points to the translation in
+|tok_start|. When \CEE/ text is to be processed with the grammar above,
+we form an array |scrap_info| containing the initial scraps.
+Our production rules have the nice property that the right-hand side is never
+longer than the left-hand side. Therefore it is convenient to use sequential
+allocation for the current sequence of scraps. Five pointers are used to
+manage the parsing:
+
+\yskip\hang |pp| is a pointer into |scrap_info|. We will try to match
+the category codes |pp->cat,@,@,(pp+1)->cat|$,\,\,\ldots\,$
+to the left-hand sides of productions.
+
+\yskip\hang |scrap_base|, |lo_ptr|, |hi_ptr|, and |scrap_ptr| are such that
+the current sequence of scraps appears in positions |scrap_base| through
+|lo_ptr| and |hi_ptr| through |scrap_ptr|, inclusive, in the |cat| and
+|trans| arrays. Scraps located between |scrap_base| and |lo_ptr| have
+been examined, while those in positions |>=hi_ptr| have not yet been
+looked at by the parsing process.
+
+\yskip\noindent Initially |scrap_ptr| is set to the position of the final
+scrap to be parsed, and it doesn't change its value. The parsing process
+makes sure that |lo_ptr>=pp+3|, since productions have as many as four terms,
+by moving scraps from |hi_ptr| to |lo_ptr|. If there are
+fewer than |pp+3| scraps left, the positions up to |pp+3| are filled with
+blanks that will not match in any productions. Parsing stops when
+|pp==lo_ptr+1| and |hi_ptr==scrap_ptr+1|.
+
+Since the |scrap| structure will later be used for other purposes, we
+declare its second element as unions.
+
+@<Type...@>=
+typedef struct {
+ eight_bits cat;
+ eight_bits mathness;
+ union {
+ text_pointer Trans;
+ @<Rest of |trans_plus| union@>@;
+ } trans_plus;
+} scrap;
+typedef scrap *scrap_pointer;
+
+@ @d trans trans_plus.Trans /* translation texts of scraps */
+
+@<Global...@>=
+scrap scrap_info[max_scraps]; /* memory array for scraps */
+scrap_pointer scrap_info_end=scrap_info+max_scraps -1; /* end of |scrap_info| */
+scrap_pointer pp; /* current position for reducing productions */
+scrap_pointer scrap_base; /* beginning of the current scrap sequence */
+scrap_pointer scrap_ptr; /* ending of the current scrap sequence */
+scrap_pointer lo_ptr; /* last scrap that has been examined */
+scrap_pointer hi_ptr; /* first scrap that has not been examined */
+scrap_pointer max_scr_ptr; /* largest value assumed by |scrap_ptr| */
+
+@ @<Set init...@>=
+scrap_base=scrap_info+1;
+max_scr_ptr=scrap_ptr=scrap_info;
+
+@ Token lists in |@!tok_mem| are composed of the following kinds of
+items for \TEX/ output.
+
+\yskip\item{$\bullet$}Character codes and special codes like |force| and
+|math_rel| represent themselves;
+
+\item{$\bullet$}|id_flag+p| represents \.{\\\\\{{\rm identifier $p$}\}};
+
+\item{$\bullet$}|res_flag+p| represents \.{\\\&\{{\rm identifier $p$}\}};
+
+\item{$\bullet$}|section_flag+p| represents section name |p|;
+
+\item{$\bullet$}|tok_flag+p| represents token list number |p|;
+
+\item{$\bullet$}|inner_tok_flag+p| represents token list number |p|, to be
+translated without line-break controls.
+
+@d id_flag 10240 /* signifies an identifier */
+@d res_flag 2*id_flag /* signifies a reserved word */
+@d section_flag 3*id_flag /* signifies a section name */
+@d tok_flag 4*id_flag /* signifies a token list */
+@d inner_tok_flag 5*id_flag /* signifies a token list in `\pb' */
+
+@c
+void
+print_text(p) /* prints a token list for debugging; not used in |main| */
+text_pointer p;
+{
+ token_pointer j; /* index into |tok_mem| */
+ sixteen_bits r; /* remainder of token after the flag has been stripped off */
+ if (p>=text_ptr) printf("BAD");
+ else for (j=*p; j<*(p+1); j++) {
+ r=*j%id_flag;
+ switch (*j/id_flag) {
+ case 1: printf("\\\\{"@q}@>); print_id((name_dir+r)); printf(@q{@>"}");
+ break; /* |id_flag| */
+ case 2: printf("\\&{"@q}@>); print_id((name_dir+r)); printf(@q{@>"}");
+ break; /* |res_flag| */
+ case 3: printf("<"); print_section_name((name_dir+r)); printf(">");
+ break; /* |section_flag| */
+ case 4: printf("[[%d]]",r); break; /* |tok_flag| */
+ case 5: printf("|[[%d]]|",r); break; /* |inner_tok_flag| */
+ default: @<Print token |r| in symbolic form@>;
+ }
+ }
+ fflush(stdout);
+}
+
+@ @<Print token |r|...@>=
+switch (r) {
+ case math_rel: printf("\\mathrel{"@q}@>); break;
+ case big_cancel: printf("[ccancel]"); break;
+ case cancel: printf("[cancel]"); break;
+ case indent: printf("[indent]"); break;
+ case outdent: printf("[outdent]"); break;
+ case backup: printf("[backup]"); break;
+ case opt: printf("[opt]"); break;
+ case break_space: printf("[break]"); break;
+ case force: printf("[force]"); break;
+ case big_force: printf("[fforce]"); break;
+ case preproc_line: printf("[preproc]"); break;
+ case quoted_char: j++; printf("[%o]",(unsigned)*j); break;
+ case end_translation: printf("[quit]"); break;
+ case inserted: printf("[inserted]"); break;
+ default: putxchar(r);
+}
+
+@ The production rules listed above are embedded directly into \.{CWEAVE},
+since it is easier to do this than to write an interpretive system
+that would handle production systems in general. Several macros are defined
+here so that the program for each production is fairly short.
+
+All of our productions conform to the general notion that some |k|
+consecutive scraps starting at some position |j| are to be replaced by a
+single scrap of some category |c| whose translation is composed from the
+translations of the disappearing scraps. After this production has been
+applied, the production pointer |pp| should change by an amount |d|. Such
+a production can be represented by the quadruple |(j,k,c,d)|. For example,
+the production `|exp@,comma@,exp| $\RA$ |exp|' would be represented by
+`|(pp,3,exp,-2)|'; in this case the pointer |pp| should decrease by 2
+after the production has been applied, because some productions with
+|exp| in their second or third positions might now match,
+but no productions have
+|exp| in the fourth position of their left-hand sides. Note that
+the value of |d| is determined by the whole collection of productions, not
+by an individual one.
+The determination of |d| has been
+done by hand in each case, based on the full set of productions but not on
+the grammar of \CEE/ or on the rules for constructing the initial
+scraps.
+
+We also attach a serial number to each production, so that additional
+information is available when debugging. For example, the program below
+contains the statement `|reduce(pp,3,exp,-2,4)|' when it implements
+the production just mentioned.
+
+Before calling |reduce|, the program should have appended the tokens of
+the new translation to the |tok_mem| array. We commonly want to append
+copies of several existing translations, and macros are defined to
+simplify these common cases. For example, \\{app2}|(pp)| will append the
+translations of two consecutive scraps, |pp->trans| and |(pp+1)->trans|, to
+the current token list. If the entire new translation is formed in this
+way, we write `|squash(j,k,c,d,n)|' instead of `|reduce(j,k,c,d,n)|'. For
+example, `|squash(pp,3,exp,-2,3)|' is an abbreviation for `\\{app3}|(pp);
+reduce(pp,3,exp,-2,3)|'.
+
+A couple more words of explanation:
+Both |big_app| and |app| append a token (while |big_app1| to |big_app4|
+append the specified number of scrap translations) to the current token list.
+The difference between |big_app| and |app| is simply that |big_app|
+checks whether there can be a conflict between math and non-math
+tokens, and intercalates a `\.{\$}' token if necessary. When in
+doubt what to use, use |big_app|.
+
+The |mathness| is an attribute of scraps that says whether they are
+to be printed in a math mode context or not. It is separate from the
+``part of speech'' (the |cat|) because to make each |cat| have
+a fixed |mathness| (as in the original \.{WEAVE}) would multiply the
+number of necessary production rules.
+
+The low two bits (i.e. |mathness % 4|) control the left boundary.
+(We need two bits because we allow cases |yes_math|, |no_math| and
+|maybe_math|, which can go either way.)
+The next two bits (i.e. |mathness / 4|) control the right boundary.
+If we combine two scraps and the right boundary of the first has
+a different mathness from the left boundary of the second, we
+insert a \.{\$} in between. Similarly, if at printing time some
+irreducible scrap has a |yes_math| boundary the scrap gets preceded
+or followed by a \.{\$}. The left boundary is |maybe_math| if and
+only if the right boundary is.
+
+The code below is an exact translation of the production rules into
+\CEE/, using such macros, and the reader should have no difficulty
+understanding the format by comparing the code with the symbolic
+productions as they were listed earlier.
+
+@d no_math 2 /* should be in horizontal mode */
+@d yes_math 1 /* should be in math mode */
+@d maybe_math 0 /* works in either horizontal or math mode */
+@d big_app2(a) big_app1(a);big_app1(a+1)
+@d big_app3(a) big_app2(a);big_app1(a+2)
+@d big_app4(a) big_app3(a);big_app1(a+3)
+@d app(a) *(tok_ptr++)=a
+@d app1(a) *(tok_ptr++)=tok_flag+(int)((a)->trans-tok_start)
+
+@<Global...@>=
+int cur_mathness, init_mathness;
+
+@ @c
+void
+app_str(s)
+char *s;
+{
+ while (*s) app_tok(*(s++));
+}
+
+void
+big_app(a)
+token a;
+{
+ if (a==' ' || (a>=big_cancel && a<=big_force)) /* non-math token */ {
+ if (cur_mathness==maybe_math) init_mathness=no_math;
+ else if (cur_mathness==yes_math) app_str("{}$");
+ cur_mathness=no_math;
+ }
+ else {
+ if (cur_mathness==maybe_math) init_mathness=yes_math;
+ else if (cur_mathness==no_math) app_str("${}");
+ cur_mathness=yes_math;
+ }
+ app(a);
+}
+
+void
+big_app1(a)
+scrap_pointer a;
+{
+ switch (a->mathness % 4) { /* left boundary */
+ case (no_math):
+ if (cur_mathness==maybe_math) init_mathness=no_math;
+ else if (cur_mathness==yes_math) app_str("{}$");
+ cur_mathness=a->mathness / 4; /* right boundary */
+ break;
+ case (yes_math):
+ if (cur_mathness==maybe_math) init_mathness=yes_math;
+ else if (cur_mathness==no_math) app_str("${}");
+ cur_mathness=a->mathness / 4; /* right boundary */
+ break;
+ case (maybe_math): /* no changes */ break;
+ }
+ app(tok_flag+(int)((a)->trans-tok_start));
+}
+
+@ Let us consider the big switch for productions now, before looking
+at its context. We want to design the program so that this switch
+works, so we might as well not keep ourselves in suspense about exactly what
+code needs to be provided with a proper environment.
+
+@d cat1 (pp+1)->cat
+@d cat2 (pp+2)->cat
+@d cat3 (pp+3)->cat
+@d lhs_not_simple (pp->cat!=semi && pp->cat!=raw_int && pp->cat!=raw_unorbin
+ && pp->cat!=raw_rpar && pp->cat!=const_like)
+
+@<Match a production at |pp|, or increase |pp| if there is no match@>= {
+ if (cat1==end_arg && lhs_not_simple)
+ if (pp->cat==begin_arg) squash(pp,2,exp,-2,110);
+ else squash(pp,2,end_arg,-1,111);
+ else if (cat1==insert) squash(pp,2,pp->cat,-2,0);
+ else if (cat2==insert) squash(pp+1,2,(pp+1)->cat,-1,0);
+ else if (cat3==insert) squash(pp+2,2,(pp+2)->cat,0,0);
+ else
+ switch (pp->cat) {
+ case exp: @<Cases for |exp|@>; @+break;
+ case lpar: @<Cases for |lpar|@>; @+break;
+ case question: @<Cases for |question|@>; @+break;
+ case unop: @<Cases for |unop|@>; @+break;
+ case unorbinop: @<Cases for |unorbinop|@>; @+break;
+ case binop: @<Cases for |binop|@>; @+break;
+ case cast: @<Cases for |cast|@>; @+break;
+ case sizeof_like: @<Cases for |sizeof_like|@>; @+break;
+ case int_like: @<Cases for |int_like|@>; @+break;
+ case decl_head: @<Cases for |decl_head|@>; @+break;
+ case decl: @<Cases for |decl|@>; @+break;
+ case typedef_like: @<Cases for |typedef_like|@>; @+break;
+ case struct_like: @<Cases for |struct_like|@>; @+break;
+ case struct_head: @<Cases for |struct_head|@>; @+break;
+ case fn_decl: @<Cases for |fn_decl|@>; @+break;
+ case function: @<Cases for |function|@>; @+break;
+ case lbrace: @<Cases for |lbrace|@>; @+break;
+ case do_like: @<Cases for |do_like|@>; @+break;
+ case if_like: @<Cases for |if_like|@>; @+break;
+ case for_like: @<Cases for |for_like|@>; @+break;
+ case else_like: @<Cases for |else_like|@>; @+break;
+ case if_clause: @<Cases for |if_clause|@>; @+break;
+ case if_head: @<Cases for |if_head|@>; @+break;
+ case else_head: @<Cases for |else_head|@>; @+break;
+ case case_like: @<Cases for |case_like|@>; @+break;
+ case stmt: @<Cases for |stmt|@>; @+break;
+ case tag: @<Cases for |tag|@>; @+break;
+ case semi: @<Cases for |semi|@>; @+break;
+ case lproc: @<Cases for |lproc|@>; @+break;
+ case section_scrap: @<Cases for |section_scrap|@>; @+break;
+ case insert: @<Cases for |insert|@>; @+break;
+ case prelangle: @<Cases for |prelangle|@>; @+break;
+ case prerangle: @<Cases for |prerangle|@>; @+break;
+ case langle: @<Cases for |langle|@>; @+break;
+ case public_like: @<Cases for |public_like|@>; @+break;
+ case colcol: @<Cases for |colcol|@>; @+break;
+ case new_like: @<Cases for |new_like|@>; @+break;
+ case operator_like: @<Cases for |operator_like|@>; @+break;
+ case catch_like: @<Cases for |catch_like|@>; @+break;
+ case base: @<Cases for |base|@>; @+break;
+ case raw_rpar: @<Cases for |raw_rpar|@>; @+break;
+ case raw_unorbin: @<Cases for |raw_unorbin|@>; @+break;
+ case const_like: @<Cases for |const_like|@>; @+break;
+ case raw_int: @<Cases for |raw_int|@>; @+break;
+ }
+ pp++; /* if no match was found, we move to the right */
+}
+
+@ In \CEE/, new specifier names can be defined via |typedef|, and we want
+to make the parser recognize future occurrences of the identifier thus
+defined as specifiers. This is done by the procedure |make_reserved|,
+which changes the |ilk| of the relevant identifier.
+
+We first need a procedure to recursively seek the first
+identifier in a token list, because the identifier might
+be enclosed in parentheses, as when one defines a function
+returning a pointer.
+
+@d no_ident_found 0 /* distinct from any identifier token */
+
+@c
+token_pointer
+find_first_ident(p)
+text_pointer p;
+{
+ token_pointer q; /* token to be returned */
+ token_pointer j; /* token being looked at */
+ sixteen_bits r; /* remainder of token after the flag has been stripped off */
+ if (p>=text_ptr) confusion("find_first_ident");
+ for (j=*p; j<*(p+1); j++) {
+ r=*j%id_flag;
+ switch (*j/id_flag) {
+ case 1: case 2: return j;
+ case 4: case 5: /* |tok_flag| or |inner_tok_flag| */
+ if ((q=find_first_ident(tok_start+r))!=no_ident_found)
+ return q;
+ default: ; /* char, |section_flag|, fall thru: move on to next token */
+ if (*j==inserted) return no_ident_found; /* ignore inserts */
+ }
+ }
+ return no_ident_found;
+}
+
+@ The scraps currently being parsed must be inspected for any
+occurrence of the identifier that we're making reserved; hence
+the |for| loop below.
+
+@c
+void
+make_reserved(p) /* make the first identifier in |p->trans| like |int| */
+scrap_pointer p;
+{
+ sixteen_bits tok_value; /* the name of this identifier, plus its flag*/
+ token_pointer tok_loc; /* pointer to |tok_value| */
+ if ((tok_loc=find_first_ident(p->trans))==no_ident_found)
+ return; /* this should not happen */
+ tok_value=*tok_loc;
+ for (;p<=scrap_ptr; p==lo_ptr? p=hi_ptr: p++) {
+ if (p->cat==exp) {
+ if (**(p->trans)==tok_value) {
+ p->cat=raw_int;
+ **(p->trans)=tok_value%id_flag+res_flag;
+ }
+ }
+ }
+ (name_dir+(sixteen_bits)(tok_value%id_flag))->ilk=raw_int;
+ *tok_loc=tok_value%id_flag+res_flag;
+}
+
+@ In the following situations we want to mark the occurrence of
+an identifier as a definition: when |make_reserved| is just about to be
+used; after a specifier, as in |char **argv|;
+before a colon, as in \\{found}:; and in the declaration of a function,
+as in \\{main}()$\{\ldots;\}$. This is accomplished by the invocation
+of |make_underlined| at appropriate times. Notice that, in the declaration
+of a function, we only find out that the identifier is being defined after
+it has been swallowed up by an |exp|.
+
+@c
+void
+make_underlined(p)
+/* underline the entry for the first identifier in |p->trans| */
+scrap_pointer p;
+{
+ token_pointer tok_loc; /* where the first identifier appears */
+ if ((tok_loc=find_first_ident(p->trans))==no_ident_found)
+ return; /* this happens after parsing the |()| in |double f();| */
+ xref_switch=def_flag;
+ underline_xref(*tok_loc%id_flag+name_dir);
+}
+
+@ We cannot use |new_xref| to underline a cross-reference at this point
+because this would just make a new cross-reference at the end of the list.
+We actually have to search through the list for the existing
+cross-reference.
+
+@<Predecl...@>=
+void underline_xref();
+
+@ @c
+void
+underline_xref(p)
+name_pointer p;
+{
+ xref_pointer q=(xref_pointer)p->xref; /* pointer to cross-reference being examined */
+ xref_pointer r; /* temporary pointer for permuting cross-references */
+ sixteen_bits m; /* cross-reference value to be installed */
+ sixteen_bits n; /* cross-reference value being examined */
+ if (no_xref) return;
+ m=section_count+xref_switch;
+ while (q != xmem) {
+ n=q->num;
+ if (n==m) return;
+ else if (m==n+def_flag) {
+ q->num=m; return;
+ }
+ else if (n>=def_flag && n<m) break;
+ q=q->xlink;
+ }
+ @<Insert new cross-reference at |q|, not at beginning of list@>;
+}
+
+@ We get to this section only when the identifier is one letter long,
+so it didn't get a non-underlined entry during phase one. But it may
+have got some explicitly underlined entries in later sections, so in order
+to preserve the numerical order of the entries in the index, we have
+to insert the new cross-reference not at the beginning of the list
+(namely, at |p->xref|), but rather right before |q|.
+
+@<Insert new cross-reference at |q|...@>=
+ append_xref(0); /* this number doesn't matter */
+ xref_ptr->xlink=(xref_pointer)p->xref; r=xref_ptr;
+ p->xref=(char*)xref_ptr;
+ while (r->xlink!=q) {r->num=r->xlink->num; r=r->xlink;}
+ r->num=m; /* everything from |q| on is left undisturbed */
+
+@ Now comes the code that tries to match each production starting
+with a particular type of scrap. Whenever a match is discovered,
+the |squash| or |reduce| macro will cause the appropriate action
+to be performed, followed by |goto found|.
+
+@<Cases for |exp|@>=
+if (cat1==lbrace || cat1==int_like || cat1==decl) {
+ make_underlined(pp); big_app1(pp); big_app(indent); app(indent);
+ reduce(pp,1,fn_decl,0,1);
+}
+else if (cat1==unop) squash(pp,2,exp,-2,2);
+else if ((cat1==binop || cat1==unorbinop) && cat2==exp)
+ squash(pp,3,exp,-2,3);
+else if (cat1==comma && cat2==exp) {
+ big_app2(pp);
+ app(opt); app('9'); big_app1(pp+2); reduce(pp,3,exp,-2,4);
+}
+else if (cat1==exp || cat1==cast) squash(pp,2,exp,-2,5);
+else if (cat1==semi) squash(pp,2,stmt,-1,6);
+else if (cat1==colon) {
+ make_underlined (pp); squash(pp,2,tag,0,7);
+}
+else if (cat1==base) {
+ if (cat2==int_like && cat3==comma) {
+ big_app1(pp+1); big_app(' '); big_app2(pp+2);
+ app(opt); app('9'); reduce(pp+1,3,base,0,8);
+ }
+ else if (cat2==int_like && cat3==lbrace) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); big_app(' '); big_app1(pp+2);
+ reduce(pp,3,exp,-1,9);
+ }
+}
+else if (cat1==rbrace) squash(pp,1,stmt,-1,10);
+
+@ @<Cases for |lpar|@>=
+if ((cat1==exp||cat1==unorbinop) && cat2==rpar) squash(pp,3,exp,-2,11);
+else if (cat1==rpar) {
+ big_app1(pp); app('\\'); app(','); big_app1(pp+1);
+@.\\,@>
+ reduce(pp,2,exp,-2,12);
+}
+else if (cat1==decl_head || cat1==int_like || cat1==exp) {
+ if (cat2==rpar) squash(pp,3,cast,-2,13);
+ else if (cat2==comma) {
+ big_app3(pp); app(opt); app('9'); reduce(pp,3,lpar,0,14);
+ }
+}
+else if (cat1==stmt || cat1==decl) {
+ big_app2(pp); big_app(' '); reduce(pp,2,lpar,0,15);
+}
+
+@ @<Cases for |question|@>=
+if (cat1==exp && cat2==colon) squash(pp,3,binop,-2,16);
+
+@ @<Cases for |unop|@>=
+if (cat1==exp || cat1==int_like) squash(pp,2,cat1,-2,17);
+
+@ @<Cases for |unorbinop|@>=
+if (cat1==exp || cat1==int_like) {
+ big_app('{'); big_app1(pp); big_app('}'); big_app1(pp+1);
+ reduce(pp,2,cat1,-2,18);
+}
+else if (cat1==binop) {
+ big_app(math_rel); big_app1(pp); big_app('{'); big_app1(pp+1); big_app('}');
+ big_app('}'); reduce(pp,2,binop,-1,19);
+}
+
+@ @<Cases for |binop|@>=
+if (cat1==binop) {
+ big_app(math_rel); big_app('{'); big_app1(pp); big_app('}');
+ big_app('{'); big_app1(pp+1); big_app('}');
+ big_app('}'); reduce(pp,2,binop,-1,20);
+}
+
+@ @<Cases for |cast|@>=
+if (cat1==exp) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,exp,-2,21);
+}
+else if (cat1==semi) squash(pp,1,exp,-2,22);
+
+@ @<Cases for |sizeof_like|@>=
+if (cat1==cast) squash(pp,2,exp,-2,23);
+else if (cat1==exp) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,exp,-2,24);
+}
+
+@ @<Cases for |int_like|@>=
+if (cat1==int_like|| cat1==struct_like) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,cat1,-2,25);
+}
+else if (cat1==exp && (cat2==raw_int||cat2==struct_like))
+ squash(pp,2,int_like,-2,26);
+else if (cat1==exp || cat1==unorbinop || cat1==semi) {
+ big_app1(pp);
+ if (cat1!=semi) big_app(' ');
+ reduce(pp,1,decl_head,-1,27);
+}
+else if (cat1==colon) {
+ big_app1(pp); big_app(' '); reduce(pp,1,decl_head,0,28);
+}
+else if (cat1==prelangle) squash(pp+1,1,langle,1,29);
+else if (cat1==colcol && (cat2==exp||cat2==int_like)) squash(pp,3,cat2,-2,30);
+else if (cat1==cast) {
+ if (cat2==lbrace) {
+ big_app2(pp); big_app(indent); big_app(indent);
+ reduce(pp,2,fn_decl,1,31);
+ }
+ else squash(pp,2,int_like,-2,32);
+}
+
+@ @<Cases for |decl_head|@>=
+if (cat1==comma) {
+ big_app2(pp); big_app(' '); reduce(pp,2,decl_head,-1,33);
+}
+else if (cat1==unorbinop) {
+ big_app1(pp); big_app('{'); big_app1(pp+1); big_app('}');
+ reduce(pp,2,decl_head,-1,34);
+}
+else if (cat1==exp && cat2!=lpar && cat2!=exp) {
+ make_underlined(pp+1); squash(pp,2,decl_head,-1,35);
+}
+else if ((cat1==binop||cat1==colon) && cat2==exp && (cat3==comma ||
+ cat3==semi || cat3==rpar))
+ squash(pp,3,decl_head,-1,36);
+else if (cat1==cast) squash(pp,2,decl_head,-1,37);
+else if (cat1==lbrace || (cat1==int_like&&cat2!=colcol) || cat1==decl) {
+ big_app1(pp); big_app(indent); app(indent); reduce(pp,1,fn_decl,0,38);
+}
+else if (cat1==semi) squash(pp,2,decl,-1,39);
+
+@ @<Cases for |decl|@>=
+if (cat1==decl) {
+ big_app1(pp); big_app(force); big_app1(pp+1);
+ reduce(pp,2,decl,-1,40);
+}
+else if (cat1==stmt || cat1==function) {
+ big_app1(pp); big_app(big_force);
+ big_app1(pp+1); reduce(pp,2,cat1,-1,41);
+}
+
+@ @<Cases for |typedef_like|@>=
+if (cat1==decl_head)
+ if ((cat2==exp&&cat3!=lpar&&cat3!=exp)||cat2==int_like) {
+ make_underlined(pp+2); make_reserved(pp+2);
+ big_app2(pp+1); reduce(pp+1,2,decl_head,0,42);
+ }
+ else if (cat2==semi) {
+ big_app1(pp); big_app(' '); big_app2(pp+1); reduce(pp,3,decl,-1,43);
+ }
+
+@ @<Cases for |struct_like|@>=
+if (cat1==lbrace) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,struct_head,0,44);
+}
+else if (cat1==exp||cat1==int_like) {
+ if (cat2==lbrace || cat2==semi) {
+ make_underlined(pp+1); make_reserved(pp+1);
+ big_app1(pp); big_app(' '); big_app1(pp+1);
+ if (cat2==semi) reduce(pp,2,decl_head,0,45);
+ else {
+ big_app(' '); big_app1(pp+2);reduce(pp,3,struct_head,0,46);
+ }
+ }
+ else if (cat2==colon) squash(pp+2,1,base,-1,47);
+ else if (cat2!=base) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,int_like,-2,48);
+ }
+}
+
+@ @<Cases for |struct_head|@>=
+if ((cat1==decl || cat1==stmt || cat1==function) && cat2==rbrace) {
+ big_app1(pp); big_app(indent); big_app(force); big_app1(pp+1);
+ big_app(outdent); big_app(force); big_app1(pp+2);
+ reduce(pp,3,int_like,-2,49);
+}
+else if (cat1==rbrace) {
+ big_app1(pp); app_str("\\,"); big_app1(pp+1);
+@.\\,@>
+ reduce(pp,2,int_like,-2,50);
+}
+
+@ @<Cases for |fn_decl|@>=
+if (cat1==decl) {
+ big_app1(pp); big_app(force); big_app1(pp+1); reduce(pp,2,fn_decl,0,51);
+}
+else if (cat1==stmt) {
+ big_app1(pp); app(outdent); app(outdent); big_app(force);
+ big_app1(pp+1); reduce(pp,2,function,-1,52);
+}
+
+@ @<Cases for |function|@>=
+if (cat1==function || cat1==decl || cat1==stmt) {
+ big_app1(pp); big_app(big_force); big_app1(pp+1); reduce(pp,2,cat1,-1,53);
+}
+
+@ @<Cases for |lbrace|@>=
+if (cat1==rbrace) {
+ big_app1(pp); app('\\'); app(','); big_app1(pp+1);
+@.\\,@>
+ reduce(pp,2,stmt,-1,54);
+}
+else if ((cat1==stmt||cat1==decl||cat1==function) && cat2==rbrace) {
+ big_app(force); big_app1(pp); big_app(indent); big_app(force);
+ big_app1(pp+1); big_app(force); big_app(backup); big_app1(pp+2);
+ big_app(outdent); big_app(force); reduce(pp,3,stmt,-1,55);
+}
+else if (cat1==exp) {
+ if (cat2==rbrace) squash(pp,3,exp,-2,56);
+ else if (cat2==comma && cat3==rbrace) squash(pp,4,exp,-2,56);
+}
+
+@ @<Cases for |if_like|@>=
+if (cat1==exp) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,if_clause,0,57);
+}
+
+@ @<Cases for |for_like|@>=
+if (cat1==exp) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,else_like,-2,58);
+}
+
+@ @<Cases for |else_like|@>=
+if (cat1==lbrace) squash(pp,1,else_head,0,59);
+else if (cat1==stmt) {
+ big_app(force); big_app1(pp); big_app(indent); big_app(break_space);
+ big_app1(pp+1); big_app(outdent); big_app(force);
+ reduce(pp,2,stmt,-1,60);
+}
+
+@ @<Cases for |else_head|@>=
+if (cat1==stmt || cat1==exp) {
+ big_app(force); big_app1(pp); big_app(break_space); app(noop);
+ big_app(cancel); big_app1(pp+1); big_app(force);
+ reduce(pp,2,stmt,-1,61);
+}
+
+@ @<Cases for |if_clause|@>=
+if (cat1==lbrace) squash(pp,1,if_head,0,62);
+else if (cat1==stmt) {
+ if (cat2==else_like) {
+ big_app(force); big_app1(pp); big_app(indent); big_app(break_space);
+ big_app1(pp+1); big_app(outdent); big_app(force); big_app1(pp+2);
+ if (cat3==if_like) {
+ big_app(' '); big_app1(pp+3); reduce(pp,4,if_like,0,63);
+ }@+else reduce(pp,3,else_like,0,64);
+ }
+ else squash(pp,1,else_like,0,65);
+}
+
+@ @<Cases for |if_head|@>=
+if (cat1==stmt || cat1==exp) {
+ if (cat2==else_like) {
+ big_app(force); big_app1(pp); big_app(break_space); app(noop);
+ big_app(cancel); big_app1(pp+1); big_app(force); big_app1(pp+2);
+ if (cat3==if_like) {
+ big_app(' '); big_app1(pp+3); reduce(pp,4,if_like,0,66);
+ }@+else reduce(pp,3,else_like,0,67);
+ }
+ else squash(pp,1,else_head,0,68);
+}
+
+@ @<Cases for |do_like|@>=
+if (cat1==stmt && cat2==else_like && cat3==semi) {
+ big_app1(pp); big_app(break_space); app(noop); big_app(cancel);
+ big_app1(pp+1); big_app(cancel); app(noop); big_app(break_space);
+ big_app2(pp+2); reduce(pp,4,stmt,-1,69);
+}
+
+@ @<Cases for |case_like|@>=
+if (cat1==semi) squash(pp,2,stmt,-1,70);
+else if (cat1==colon) squash(pp,2,tag,-1,71);
+else if (cat1==exp) {
+ if (cat2==semi) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); big_app1(pp+2);
+ reduce(pp,3,stmt,-1,72);
+ }
+ else if (cat2==colon) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); big_app1(pp+2);
+ reduce(pp,3,tag,-1,73);
+ }
+}
+
+@ @<Cases for |tag|@>=
+if (cat1==tag) {
+ big_app1(pp); big_app(break_space); big_app1(pp+1); reduce(pp,2,tag,-1,74);
+}
+else if (cat1==stmt||cat1==decl||cat1==function) {
+ big_app(force); big_app(backup); big_app1(pp); big_app(break_space);
+ big_app1(pp+1); reduce(pp,2,cat1,-1,75);
+}
+
+@ The user can decide at run-time whether short statements should be
+grouped together on the same line.
+
+@d force_lines flags['f'] /* should each statement be on its own line? */
+@<Cases for |stmt|@>=
+if (cat1==stmt||cat1==decl||cat1==function) {
+ big_app1(pp);
+ if (cat1==function) big_app(big_force);
+ else if (cat1==decl) big_app(big_force);
+ else if (force_lines) big_app(force);
+ else big_app(break_space);
+ big_app1(pp+1); reduce(pp,2,cat1,-1,76);
+}
+
+@ @<Cases for |semi|@>=
+big_app(' '); big_app1(pp); reduce(pp,1,stmt,-1,77);
+
+@ @<Cases for |lproc|@>=
+if (cat1==define_like) make_underlined(pp+2);
+if (cat1==else_like || cat1==if_like ||cat1==define_like)
+ squash(pp,2,lproc,0,78);
+else if (cat1==rproc) {
+ app(inserted); big_app2(pp); reduce(pp,2,insert,-1,79);
+} else if (cat1==exp || cat1==function) {
+ if (cat2==rproc) {
+ app(inserted); big_app1(pp); big_app(' '); big_app2(pp+1);
+ reduce(pp,3,insert,-1,80);
+ }
+ else if (cat2==exp && cat3==rproc && cat1==exp) {
+ app(inserted); big_app1(pp); big_app(' '); big_app1(pp+1); app_str(" \\5");
+@.\\5@>
+ big_app2(pp+2); reduce(pp,4,insert,-1,80);
+ }
+}
+
+@ @<Cases for |section_scrap|@>=
+if (cat1==semi) {
+ big_app2(pp); big_app(force); reduce(pp,2,stmt,-2,81);
+}
+else squash(pp,1,exp,-2,82);
+
+@ @<Cases for |insert|@>=
+if (cat1)
+ squash(pp,2,cat1,0,83);
+
+@ @<Cases for |prelangle|@>=
+init_mathness=cur_mathness=yes_math;
+app('<'); reduce(pp,1,binop,-2,84);
+
+@ @<Cases for |prerangle|@>=
+init_mathness=cur_mathness=yes_math;
+app('>'); reduce(pp,1,binop,-2,85);
+
+@ @<Cases for |langle|@>=
+if (cat1==exp && cat2==prerangle) squash(pp,3,cast,-1,86);
+else if (cat1==prerangle) {
+ big_app1(pp); app('\\'); app(','); big_app1(pp+1);
+@.\\,@>
+ reduce(pp,2,cast,-1,87);
+}
+else if (cat1==decl_head || cat1==int_like) {
+ if (cat2==prerangle) squash(pp,3,cast,-1,88);
+ else if (cat2==comma) {
+ big_app3(pp); app(opt); app('9'); reduce(pp,3,langle,0,89);
+ }
+}
+
+@ @<Cases for |public_like|@>=
+if (cat1==colon) squash(pp,2,tag,-1,90);
+else squash(pp,1,int_like,-2,91);
+
+@ @<Cases for |colcol|@>=
+if (cat1==exp||cat1==int_like) squash(pp,2,cat1,-2,92);
+
+@ @<Cases for |new_like|@>=
+if (cat1==exp || (cat1==raw_int&&cat2!=prelangle&&cat2!=langle)) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,new_like,0,93);
+}
+else if (cat1==raw_unorbin || cat1==colcol)
+ squash(pp,2,new_like,0,94);
+else if (cat1==cast) squash(pp,2,exp,-2,95);
+else if (cat1!=lpar && cat1!=raw_int && cat1!=struct_like)
+ squash(pp,1,exp,-2,96);
+
+@ @<Cases for |operator_like|@>=
+if (cat1==binop || cat1==unop || cat1==unorbinop) {
+ if (cat2==binop) break;
+ big_app1(pp); big_app('{'); big_app1(pp+1); big_app('}');
+ reduce(pp,2,exp,-2,97);
+}
+else if (cat1==new_like || cat1==sizeof_like) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,exp,-2,98);
+}
+else squash(pp,1,new_like,0,99);
+
+@ @<Cases for |catch_like|@>=
+if (cat1==cast || cat1==exp) {
+ big_app2(pp); big_app(indent); big_app(indent);
+ reduce(pp,2,fn_decl,0,100);
+}
+
+@ @<Cases for |base|@>=
+if (cat1==public_like && cat2==exp) {
+ if (cat3==comma) {
+ big_app2(pp); big_app(' '); big_app2(pp+2);
+ reduce(pp,4,base,0,101);
+ } else {
+ big_app1(pp+1); big_app(' '); big_app1(pp+2);
+ reduce(pp+1,2,int_like,-1,102);
+ }
+}
+
+@ @<Cases for |raw_rpar|@>=
+if (cat1==const_like && @|
+ (cat2==semi || cat2==lbrace || cat2==comma || cat2==binop
+ || cat2==const_like)) {
+ big_app1(pp); big_app(' ');
+ big_app1(pp+1); reduce(pp,2,raw_rpar,0,103);
+} else squash(pp,1,rpar,-3,104);
+
+@ @<Cases for |raw_unorbin|@>=
+if (cat1==const_like) {
+ big_app2(pp); app_str("\\ "); reduce(pp,2,raw_unorbin,0,105);
+@.\\ @>
+} else squash(pp,1,unorbinop,-2,106);
+
+@ @<Cases for |const_like|@>=
+squash(pp,1,int_like,-2,107);
+
+@ @<Cases for |raw_int|@>=
+if (cat1==lpar) squash(pp,1,exp,-2,108);
+else squash(pp,1,int_like,-3,109);
+
+@ The `|freeze_text|' macro is used to give official status to a token list.
+Before saying |freeze_text|, items are appended to the current token list,
+and we know that the eventual number of this token list will be the current
+value of |text_ptr|. But no list of that number really exists as yet,
+because no ending point for the current list has been
+stored in the |tok_start| array. After saying |freeze_text|, the
+old current token list becomes legitimate, and its number is the current
+value of |text_ptr-1| since |text_ptr| has been increased. The new
+current token list is empty and ready to be appended to.
+Note that |freeze_text| does not check to see that |text_ptr| hasn't gotten
+too large, since it is assumed that this test was done beforehand.
+
+@d freeze_text *(++text_ptr)=tok_ptr
+
+@ Here's the |reduce| procedure used in our code for productions:
+
+@c
+void
+reduce(j,k,c,d,n)
+scrap_pointer j;
+eight_bits c;
+short k, d, n;
+{
+ scrap_pointer i, i1; /* pointers into scrap memory */
+ j->cat=c; j->trans=text_ptr;
+ j->mathness=4*cur_mathness+init_mathness;
+ freeze_text;
+ if (k>1) {
+ for (i=j+k, i1=j+1; i<=lo_ptr; i++, i1++) {
+ i1->cat=i->cat; i1->trans=i->trans;
+ i1->mathness=i->mathness;
+ }
+ lo_ptr=lo_ptr-k+1;
+ }
+ @<Change |pp| to $\max(|scrap_base|,|pp|+d)$@>;
+ @<Print a snapshot of the scrap list if debugging @>;
+ pp--; /* we next say |pp++| */
+}
+
+@ @<Change |pp| to $\max...@>=
+if (pp+d>=scrap_base) pp=pp+d;
+else pp=scrap_base;
+
+@ Here's the |squash| procedure, which
+takes advantage of the simplification that occurs when |k==1|.
+
+@c
+void
+squash(j,k,c,d,n)
+scrap_pointer j;
+eight_bits c;
+short k, d, n;
+{
+ scrap_pointer i; /* pointers into scrap memory */
+ if (k==1) {
+ j->cat=c; @<Change |pp|...@>;
+ @<Print a snapshot...@>;
+ pp--; /* we next say |pp++| */
+ return;
+ }
+ for (i=j; i<j+k; i++) big_app1(i);
+ reduce(j,k,c,d,n);
+}
+
+@ Here now is the code that applies productions as long as possible.
+Before applying the production mechanism, we must make sure
+it has good input (at least four scraps, the length of the lhs of the
+longest rules), and that there is enough room in the memory arrays
+to hold the appended tokens and texts. Here we use a very
+conservative test: it's more important to make sure the program
+will still work if we change the production rules (within reason)
+than to squeeze the last bit of space from the memory arrays.
+
+@d safe_tok_incr 20
+@d safe_text_incr 10
+@d safe_scrap_incr 10
+
+@<Reduce the scraps using the productions until no more rules apply@>=
+while (1) {
+ @<Make sure the entries |pp| through |pp+3| of |cat| are defined@>;
+ if (tok_ptr+safe_tok_incr>tok_mem_end) {
+ if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr;
+ overflow("token");
+ }
+ if (text_ptr+safe_text_incr>tok_start_end) {
+ if (text_ptr>max_text_ptr) max_text_ptr=text_ptr;
+ overflow("text");
+ }
+ if (pp>lo_ptr) break;
+ init_mathness=cur_mathness=maybe_math;
+ @<Match a production...@>;
+}
+
+@ If we get to the end of the scrap list, category codes equal to zero are
+stored, since zero does not match anything in a production.
+
+@<Make sure the entries...@>=
+if (lo_ptr<pp+3) {
+ while (hi_ptr<=scrap_ptr && lo_ptr!=pp+3) {
+ (++lo_ptr)->cat=hi_ptr->cat; lo_ptr->mathness=(hi_ptr)->mathness;
+ lo_ptr->trans=(hi_ptr++)->trans;
+ }
+ for (i=lo_ptr+1;i<=pp+3;i++) i->cat=0;
+}
+
+@ If \.{CWEAVE} is being run in debugging mode, the production numbers and
+current stack categories will be printed out when |tracing| is set to 2;
+a sequence of two or more irreducible scraps will be printed out when
+|tracing| is set to 1.
+
+@<Global...@>=
+int tracing; /* can be used to show parsing details */
+
+@ @<Print a snapsh...@>=
+{ scrap_pointer k; /* pointer into |scrap_info| */
+ if (tracing==2) {
+ printf("\n%d:",n);
+ for (k=scrap_base; k<=lo_ptr; k++) {
+ if (k==pp) putxchar('*'); else putxchar(' ');
+ if (k->mathness %4 == yes_math) putchar('+');
+ else if (k->mathness %4 == no_math) putchar('-');
+ print_cat(k->cat);
+ if (k->mathness /4 == yes_math) putchar('+');
+ else if (k->mathness /4 == no_math) putchar('-');
+ }
+ if (hi_ptr<=scrap_ptr) printf("..."); /* indicate that more is coming */
+ }
+}
+
+@ The |translate| function assumes that scraps have been stored in
+positions |scrap_base| through |scrap_ptr| of |cat| and |trans|. It
+applies productions as much as
+possible. The result is a token list containing the translation of
+the given sequence of scraps.
+
+After calling |translate|, we will have |text_ptr+3<=max_texts| and
+|tok_ptr+6<=max_toks|, so it will be possible to create up to three token
+lists with up to six tokens without checking for overflow. Before calling
+|translate|, we should have |text_ptr<max_texts| and |scrap_ptr<max_scraps|,
+since |translate| might add a new text and a new scrap before it checks
+for overflow.
+
+@c
+text_pointer
+translate() /* converts a sequence of scraps */
+{
+ scrap_pointer i, /* index into |cat| */
+ j; /* runs through final scraps */
+ pp=scrap_base; lo_ptr=pp-1; hi_ptr=pp;
+ @<If tracing, print an indication of where we are@>;
+ @<Reduce the scraps...@>;
+ @<Combine the irreducible scraps that remain@>;
+}
+
+@ If the initial sequence of scraps does not reduce to a single scrap,
+we concatenate the translations of all remaining scraps, separated by
+blank spaces, with dollar signs surrounding the translations of scraps
+where appropriate.
+
+@<Combine the irreducible...@>= {
+ @<If semi-tracing, show the irreducible scraps@>;
+ for (j=scrap_base; j<=lo_ptr; j++) {
+ if (j!=scrap_base) app(' ');
+ if (j->mathness % 4 == yes_math) app('$');
+ app1(j);
+ if (j->mathness / 4 == yes_math) app('$');
+ if (tok_ptr+6>tok_mem_end) overflow("token");
+ }
+ freeze_text; return(text_ptr-1);
+}
+
+@ @<If semi-tracing, show the irreducible scraps@>=
+if (lo_ptr>scrap_base && tracing==1) {
+ printf("\nIrreducible scrap sequence in section %d:",section_count);
+@.Irreducible scrap sequence...@>
+ mark_harmless;
+ for (j=scrap_base; j<=lo_ptr; j++) {
+ printf(" "); print_cat(j->cat);
+ }
+}
+
+@ @<If tracing,...@>=
+if (tracing==2) {
+ printf("\nTracing after l. %d:\n",cur_line); mark_harmless;
+@.Tracing after...@>
+ if (loc>buffer+50) {
+ printf("...");
+ term_write(loc-51,51);
+ }
+ else term_write(buffer,loc-buffer);
+}
+
+@* Initializing the scraps.
+If we are going to use the powerful production mechanism just developed, we
+must get the scraps set up in the first place, given a \CEE/ text. A table
+of the initial scraps corresponding to \CEE/ tokens appeared above in the
+section on parsing; our goal now is to implement that table. We shall do this
+by implementing a subroutine called |C_parse| that is analogous to the
+|C_xref| routine used during phase one.
+
+Like |C_xref|, the |C_parse| procedure starts with the current
+value of |next_control| and it uses the operation |next_control=get_next()|
+repeatedly to read \CEE/ text until encountering the next `\.{\v}' or
+`\.{/*}', or until |next_control>=format_code|. The scraps corresponding to
+what it reads are appended into the |cat| and |trans| arrays, and |scrap_ptr|
+is advanced.
+
+@c
+void
+C_parse(spec_ctrl) /* creates scraps from \CEE/ tokens */
+ eight_bits spec_ctrl;
+{
+ int count; /* characters remaining before string break */
+ while (next_control<format_code || next_control==spec_ctrl) {
+ @<Append the scrap appropriate to |next_control|@>;
+ next_control=get_next();
+ if (next_control=='|' || next_control==begin_comment ||
+ next_control==begin_short_comment) return;
+ }
+}
+
+@ The following macro is used to append a scrap whose tokens have just
+been appended:
+
+@d app_scrap(c,b) {
+ (++scrap_ptr)->cat=(c); scrap_ptr->trans=text_ptr;
+ scrap_ptr->mathness=5*(b); /* no no, yes yes, or maybe maybe */
+ freeze_text;
+}
+
+@ @<Append the scr...@>=
+@<Make sure that there is room for the new scraps, tokens, and texts@>;
+switch (next_control) {
+ case section_name:
+ app(section_flag+(int)(cur_section-name_dir));
+ app_scrap(section_scrap,maybe_math);
+ app_scrap(exp,yes_math);@+break;
+ case string: case constant: case verbatim: @<Append a string or constant@>;
+ @+break;
+ case identifier: app_cur_id(1);@+break;
+ case TeX_string: @<Append a \TEX/ string, without forming a scrap@>;@+break;
+ case '/': case '.':
+ app(next_control); app_scrap(binop,yes_math);@+break;
+ case '<': app_str("\\langle");@+app_scrap(prelangle,yes_math);@+break;
+@.\\langle@>
+ case '>': app_str("\\rangle");@+app_scrap(prerangle,yes_math);@+break;
+@.\\rangle@>
+ case '=': app_str("\\K"); app_scrap(binop,yes_math);@+break;
+@.\\K@>
+ case '|': app_str("\\OR"); app_scrap(binop,yes_math);@+break;
+@.\\OR@>
+ case '^': app_str("\\XOR"); app_scrap(binop,yes_math);@+break;
+@.\\XOR@>
+ case '%': app_str("\\MOD"); app_scrap(binop,yes_math);@+break;
+@.\\MOD@>
+ case '!': app_str("\\R"); app_scrap(unop,yes_math);@+break;
+@.\\R@>
+ case '~': app_str("\\CM"); app_scrap(unop,yes_math);@+break;
+@.\\CM@>
+ case '+': case '-': app(next_control); app_scrap(unorbinop,yes_math);@+break;
+ case '*': app(next_control); app_scrap(raw_unorbin,yes_math);@+break;
+ case '&': app_str("\\AND"); app_scrap(raw_unorbin,yes_math);@+break;
+@.\\AND@>
+ case '?': app_str("\\?"); app_scrap(question,yes_math);@+break;
+@.\\?@>
+ case '#': app_str("\\#"); app_scrap(unorbinop,yes_math);@+break;
+@.\\\#@>
+ case ignore: case xref_roman: case xref_wildcard:
+ case xref_typewriter: case noop:@+break;
+ case '(': case '[': app(next_control); app_scrap(lpar,maybe_math);@+break;
+ case ')': case ']': app(next_control); app_scrap(raw_rpar,maybe_math);@+break;
+ case '{': app_str("\\{"@q}@>); app_scrap(lbrace,yes_math);@+break;
+@.\\\{@>@q}@>
+ case '}': app_str(@q{@>"\\}"); app_scrap(rbrace,yes_math);@+break;
+@q{@>@.\\\}@>
+ case ',': app(','); app_scrap(comma,yes_math);@+break;
+ case ';': app(';'); app_scrap(semi,maybe_math);@+break;
+ case ':': app(':'); app_scrap(colon,maybe_math);@+break;@/
+ @t\4@> @<Cases involving nonstandard characters@>@;
+ case thin_space: app_str("\\,"); app_scrap(insert,maybe_math);@+break;
+@.\\,@>
+ case math_break: app(opt); app_str("0");
+ app_scrap(insert,maybe_math);@+break;
+ case line_break: app(force); app_scrap(insert,no_math);@+break;
+ case left_preproc: app(force); app(preproc_line);
+ app_str("\\#"); app_scrap(lproc,no_math);@+break;
+@.\\\#@>
+ case right_preproc: app(force); app_scrap(rproc,no_math);@+break;
+ case big_line_break: app(big_force); app_scrap(insert,no_math);@+break;
+ case no_line_break: app(big_cancel); app(noop); app(break_space);
+ app(noop); app(big_cancel);
+ app_scrap(insert,no_math);@+break;
+ case pseudo_semi: app_scrap(semi,maybe_math);@+break;
+ case macro_arg_open: app_scrap(begin_arg,maybe_math);@+break;
+ case macro_arg_close: app_scrap(end_arg,maybe_math);@+break;
+ case join: app_str("\\J"); app_scrap(insert,no_math);@+break;
+@.\\J@>
+ case output_defs_code: app(force); app_str("\\ATH"); app(force);
+ app_scrap(insert,no_math);@+break;
+@.\\ATH@>
+ default: app(inserted); app(next_control);
+ app_scrap(insert,maybe_math);@+break;
+}
+
+@ @<Make sure that there is room for the new...@>=
+if (scrap_ptr+safe_scrap_incr>scrap_info_end ||
+ tok_ptr+safe_tok_incr>tok_mem_end @| ||
+ text_ptr+safe_text_incr>tok_start_end) {
+ if (scrap_ptr>max_scr_ptr) max_scr_ptr=scrap_ptr;
+ if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr;
+ if (text_ptr>max_text_ptr) max_text_ptr=text_ptr;
+ overflow("scrap/token/text");
+}
+
+@ Some nonstandard characters may have entered \.{CWEAVE} by means of
+standard ones. They are converted to \TEX/ control sequences so that it is
+possible to keep \.{CWEAVE} from outputting unusual |char| codes.
+
+@<Cases involving nonstandard...@>=
+case not_eq: app_str("\\I");@+app_scrap(binop,yes_math);@+break;
+@.\\I@>
+case lt_eq: app_str("\\Z");@+app_scrap(binop,yes_math);@+break;
+@.\\Z@>
+case gt_eq: app_str("\\G");@+app_scrap(binop,yes_math);@+break;
+@.\\G@>
+case eq_eq: app_str("\\E");@+app_scrap(binop,yes_math);@+break;
+@.\\E@>
+case and_and: app_str("\\W");@+app_scrap(binop,yes_math);@+break;
+@.\\W@>
+case or_or: app_str("\\V");@+app_scrap(binop,yes_math);@+break;
+@.\\V@>
+case plus_plus: app_str("\\PP");@+app_scrap(unop,yes_math);@+break;
+@.\\PP@>
+case minus_minus: app_str("\\MM");@+app_scrap(unop,yes_math);@+break;
+@.\\MM@>
+case minus_gt: app_str("\\MG");@+app_scrap(binop,yes_math);@+break;
+@.\\MG@>
+case gt_gt: app_str("\\GG");@+app_scrap(binop,yes_math);@+break;
+@.\\GG@>
+case lt_lt: app_str("\\LL");@+app_scrap(binop,yes_math);@+break;
+@.\\LL@>
+case dot_dot_dot: app_str("\\,\\ldots\\,");@+app_scrap(exp,yes_math);@+break;
+@.\\,@>
+@.\\ldots@>
+case colon_colon: app_str("\\DC");@+app_scrap(colcol,maybe_math);@+break;
+@.\\DC@>
+case period_ast: app_str("\\PA");@+app_scrap(binop,yes_math);@+break;
+@.\\PA@>
+case minus_gt_ast: app_str("\\MGA");@+app_scrap(binop,yes_math);@+break;
+@.\\MGA@>
+
+@ The following code must use |app_tok| instead of |app| in order to
+protect against overflow. Note that |tok_ptr+1<=max_toks| after |app_tok|
+has been used, so another |app| is legitimate before testing again.
+
+Many of the special characters in a string must be prefixed by `\.\\' so that
+\TEX/ will print them properly.
+@^special string characters@>
+
+@<Append a string or...@>=
+count= -1;
+if (next_control==constant) app_str("\\T{"@q}@>);
+@.\\T@>
+else if (next_control==string) {
+ count=20; app_str("\\.{"@q}@>);
+}
+@.\\.@>
+else app_str("\\vb{"@q}@>);
+@.\\vb@>
+while (id_first<id_loc) {
+ if (count==0) { /* insert a discretionary break in a long string */
+ app_str(@q(@>@q{@>"}\\)\\.{"@q}@>); count=20;
+@q(@>@.\\)@>
+ }
+@^high-bit character handling@>
+ if((eight_bits)(*id_first)>0177) {
+ app_tok(quoted_char);
+ app_tok((eight_bits)(*id_first++));
+ }
+ else {
+ switch (*id_first) {
+ case ' ':case '\\':case '#':case '%':case '$':case '^':
+ case '{': case '}': case '~': case '&': case '_': app('\\'); break;
+@.\\\ @>
+@.\\\\@>
+@.\\\#@>
+@.\\\%@>
+@.\\\$@>
+@.\\\^@>
+@.\\\{@>@q}@>
+@q{@>@.\\\}@>
+@.\\\~@>
+@.\\\&@>
+@.\\_@> @q CWEAVE does quote an underscore! @>
+ case '@@': if (*(id_first+1)=='@@') id_first++;
+ else err_print("! Double @@ should be used in strings");
+@.Double @@ should be used...@>
+ }
+ app_tok(*id_first++);
+ }
+ count--;
+}
+app(@q{@>'}');
+app_scrap(exp,maybe_math);
+
+@ We do not make the \TEX/ string into a scrap, because there is no
+telling what the user will be putting into it; instead we leave it
+open, to be picked up by the next scrap. If it comes at the end of a
+section, it will be made into a scrap when |finish_C| is called.
+
+There's a known bug here, in cases where an adjacent scrap is
+|prelangle| or |prerangle|. Then the \TEX/ string can disappear
+when the \.{\\langle} or \.{\\rangle} becomes \.{<} or \.{>}.
+For example, if the user writes \.{\v x<@@ty@@>\v}, the \TEX/ string
+\.{\\hbox\{y\}} eventually becomes part of an |insert| scrap, which is combined
+with a |prelangle| scrap and eventually lost. The best way to work around
+this bug is probably to enclose the \.{@@t...@@>} in \.{@@[...@@]} so that
+the \TEX/ string is treated as an expression.
+@^bug, known@>
+
+@<Append a \TEX/ string, without forming a scrap@>=
+app_str("\\hbox{"@q}@>);
+@^high-bit character handling@>
+while (id_first<id_loc)
+ if((eight_bits)(*id_first)>0177) {
+ app_tok(quoted_char);
+ app_tok((eight_bits)(*id_first++));
+ }
+ else {
+ if (*id_first=='@@') id_first++;
+ app_tok(*id_first++);
+ }
+app(@q{@>'}');
+
+@ The function |app_cur_id| appends the current identifier to the
+token list; it also builds a new scrap if |scrapping==1|.
+
+@<Predec...@>=
+void app_cur_id();
+
+@ @c
+void
+app_cur_id(scrapping)
+boolean scrapping; /* are we making this into a scrap? */
+{
+ name_pointer p=id_lookup(id_first,id_loc,normal);
+ if (p->ilk<=quoted) { /* not a reserved word */
+ app(id_flag+(int)(p-name_dir));
+ if (scrapping) app_scrap(exp,p->ilk>=custom? yes_math: maybe_math);
+@.\\NULL@>
+ } else {
+ app(res_flag+(int)(p-name_dir));
+ if (scrapping) app_scrap(p->ilk,maybe_math);
+ }
+}
+
+@ When the `\.{\v}' that introduces \CEE/ text is sensed, a call on
+|C_translate| will return a pointer to the \TEX/ translation of
+that text. If scraps exist in |scrap_info|, they are
+unaffected by this translation process.
+
+@c
+text_pointer
+C_translate()
+{
+ text_pointer p; /* points to the translation */
+ scrap_pointer save_base; /* holds original value of |scrap_base| */
+ save_base=scrap_base; scrap_base=scrap_ptr+1;
+ C_parse(section_name); /* get the scraps together */
+ if (next_control!='|') err_print("! Missing '|' after C text");
+@.Missing '|'...@>
+ app_tok(cancel); app_scrap(insert,maybe_math);
+ /* place a |cancel| token as a final ``comment'' */
+ p=translate(); /* make the translation */
+ if (scrap_ptr>max_scr_ptr) max_scr_ptr=scrap_ptr;
+ scrap_ptr=scrap_base-1; scrap_base=save_base; /* scrap the scraps */
+ return(p);
+}
+
+@ The |outer_parse| routine is to |C_parse| as |outer_xref|
+is to |C_xref|: it constructs a sequence of scraps for \CEE/ text
+until |next_control>=format_code|. Thus, it takes care of embedded comments.
+
+@c
+void
+outer_parse() /* makes scraps from \CEE/ tokens and comments */
+{
+ int bal; /* brace level in comment */
+ text_pointer p, q; /* partial comments */
+ while (next_control<format_code)
+ if (next_control!=begin_comment && next_control!=begin_short_comment)
+ C_parse(ignore);
+ else {
+ boolean is_long_comment=(next_control==begin_comment);
+ @<Make sure that there is room for the new...@>;
+ app(cancel); app(inserted);
+ if (is_long_comment) app_str("\\C{"@q}@>);
+@.\\C@>
+ else app_str("\\SHC{"@q}@>);
+@.\\SHC@>
+ bal=copy_comment(is_long_comment,1); next_control=ignore;
+ while (bal>0) {
+ p=text_ptr; freeze_text; q=C_translate();
+ /* at this point we have |tok_ptr+6<=max_toks| */
+ app(tok_flag+(int)(p-tok_start));
+ app_str("\\PB{"); app(inner_tok_flag+(int)(q-tok_start)); app_tok('}');
+@.\\PB@>
+ if (next_control=='|') {
+ bal=copy_comment(is_long_comment,bal);
+ next_control=ignore;
+ }
+ else bal=0; /* an error has been reported */
+ }
+ app(force); app_scrap(insert,no_math);
+ /* the full comment becomes a scrap */
+ }
+}
+
+@* Output of tokens.
+So far our programs have only built up multi-layered token lists in
+\.{CWEAVE}'s internal memory; we have to figure out how to get them into
+the desired final form. The job of converting token lists to characters in
+the \TEX/ output file is not difficult, although it is an implicitly
+recursive process. Four main considerations had to be kept in mind when
+this part of \.{CWEAVE} was designed. (a) There are two modes of output:
+|outer| mode, which translates tokens like |force| into line-breaking
+control sequences, and |inner| mode, which ignores them except that blank
+spaces take the place of line breaks. (b) The |cancel| instruction applies
+to adjacent token or tokens that are output, and this cuts across levels
+of recursion since `|cancel|' occurs at the beginning or end of a token
+list on one level. (c) The \TEX/ output file will be semi-readable if line
+breaks are inserted after the result of tokens like |break_space| and
+|force|. (d) The final line break should be suppressed, and there should
+be no |force| token output immediately after `\.{\\Y\\B}'.
+
+@ The output process uses a stack to keep track of what is going on at
+different ``levels'' as the token lists are being written out. Entries on
+this stack have three parts:
+
+\yskip\hang |end_field| is the |tok_mem| location where the token list of a
+particular level will end;
+
+\yskip\hang |tok_field| is the |tok_mem| location from which the next token
+on a particular level will be read;
+
+\yskip\hang |mode_field| is the current mode, either |inner| or |outer|.
+
+\yskip\noindent The current values of these quantities are referred to
+quite frequently, so they are stored in a separate place instead of in the
+|stack| array. We call the current values |cur_end|, |cur_tok|, and
+|cur_mode|.
+
+The global variable |stack_ptr| tells how many levels of output are
+currently in progress. The end of output occurs when an |end_translation|
+token is found, so the stack is never empty except when we first begin the
+output process.
+
+@d inner 0 /* value of |mode| for \CEE/ texts within \TEX/ texts */
+@d outer 1 /* value of |mode| for \CEE/ texts in sections */
+
+@<Typed...@>= typedef int mode;
+typedef struct {
+ token_pointer end_field; /* ending location of token list */
+ token_pointer tok_field; /* present location within token list */
+ boolean mode_field; /* interpretation of control tokens */
+} output_state;
+typedef output_state *stack_pointer;
+
+@ @d cur_end cur_state.end_field /* current ending location in |tok_mem| */
+@d cur_tok cur_state.tok_field /* location of next output token in |tok_mem| */
+@d cur_mode cur_state.mode_field /* current mode of interpretation */
+@d init_stack stack_ptr=stack;cur_mode=outer /* initialize the stack */
+
+@<Global...@>=
+output_state cur_state; /* |cur_end|, |cur_tok|, |cur_mode| */
+output_state stack[stack_size]; /* info for non-current levels */
+stack_pointer stack_ptr; /* first unused location in the output state stack */
+stack_pointer stack_end=stack+stack_size-1; /* end of |stack| */
+stack_pointer max_stack_ptr; /* largest value assumed by |stack_ptr| */
+
+@ @<Set init...@>=
+max_stack_ptr=stack;
+
+@ To insert token-list |p| into the output, the |push_level| subroutine
+is called; it saves the old level of output and gets a new one going.
+The value of |cur_mode| is not changed.
+
+@c
+void
+push_level(p) /* suspends the current level */
+text_pointer p;
+{
+ if (stack_ptr==stack_end) overflow("stack");
+ if (stack_ptr>stack) { /* save current state */
+ stack_ptr->end_field=cur_end;
+ stack_ptr->tok_field=cur_tok;
+ stack_ptr->mode_field=cur_mode;
+ }
+ stack_ptr++;
+ if (stack_ptr>max_stack_ptr) max_stack_ptr=stack_ptr;
+ cur_tok=*p; cur_end=*(p+1);
+}
+
+@ Conversely, the |pop_level| routine restores the conditions that were in
+force when the current level was begun. This subroutine will never be
+called when |stack_ptr==1|.
+
+@c
+void
+pop_level()
+{
+ cur_end=(--stack_ptr)->end_field;
+ cur_tok=stack_ptr->tok_field; cur_mode=stack_ptr->mode_field;
+}
+
+@ The |get_output| function returns the next byte of output that is not a
+reference to a token list. It returns the values |identifier| or |res_word|
+or |section_code| if the next token is to be an identifier (typeset in
+italics), a reserved word (typeset in boldface) or a section name (typeset
+by a complex routine that might generate additional levels of output).
+In these cases |cur_name| points to the identifier or section name in
+question.
+
+@<Global...@>=
+name_pointer cur_name;
+
+@ @d res_word 0201 /* returned by |get_output| for reserved words */
+@d section_code 0200 /* returned by |get_output| for section names */
+
+@c
+eight_bits
+get_output() /* returns the next token of output */
+{
+ sixteen_bits a; /* current item read from |tok_mem| */
+ restart: while (cur_tok==cur_end) pop_level();
+ a=*(cur_tok++);
+ if (a>=0400) {
+ cur_name=a % id_flag + name_dir;
+ switch (a / id_flag) {
+ case 2: return(res_word); /* |a==res_flag+cur_name| */
+ case 3: return(section_code); /* |a==section_flag+cur_name| */
+ case 4: push_level(a % id_flag + tok_start); goto restart;
+ /* |a==tok_flag+cur_name| */
+ case 5: push_level(a % id_flag + tok_start); cur_mode=inner; goto restart;
+ /* |a==inner_tok_flag+cur_name| */
+ default: return(identifier); /* |a==id_flag+cur_name| */
+ }
+ }
+ return(a);
+}
+
+@ The real work associated with token output is done by |make_output|.
+This procedure appends an |end_translation| token to the current token list,
+and then it repeatedly calls |get_output| and feeds characters to the output
+buffer until reaching the |end_translation| sentinel. It is possible for
+|make_output| to be called recursively, since a section name may include
+embedded \CEE/ text; however, the depth of recursion never exceeds one
+level, since section names cannot be inside of section names.
+
+A procedure called |output_C| does the scanning, translation, and
+output of \CEE/ text within `\pb' brackets, and this procedure uses
+|make_output| to output the current token list. Thus, the recursive call
+of |make_output| actually occurs when |make_output| calls |output_C|
+while outputting the name of a section.
+@^recursion@>
+
+The token list created from within `\pb' brackets is output as an argument
+to \.{\\PB}. Although \.{cwebmac} ignores \.{\\PB}, other macro packages
+might use it to localize the special meaning of the macros that mark up
+program text.
+
+@c
+void
+output_C() /* outputs the current token list */
+{
+ token_pointer save_tok_ptr;
+ text_pointer save_text_ptr;
+ sixteen_bits save_next_control; /* values to be restored */
+ text_pointer p; /* translation of the \CEE/ text */
+ save_tok_ptr=tok_ptr; save_text_ptr=text_ptr;
+ save_next_control=next_control; next_control=ignore; p=C_translate();
+ app(inner_tok_flag+(int)(p-tok_start));
+ out_str("\\PB{"); make_output(); out('}'); /* output the list */
+@.\\PB@>
+ if (text_ptr>max_text_ptr) max_text_ptr=text_ptr;
+ if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr;
+ text_ptr=save_text_ptr; tok_ptr=save_tok_ptr; /* forget the tokens */
+ next_control=save_next_control; /* restore |next_control| to original state */
+}
+
+@ Here is \.{CWEAVE}'s major output handler.
+
+@<Predecl...@>=
+void make_output();
+
+@ @c
+void
+make_output() /* outputs the equivalents of tokens */
+{
+ eight_bits a, /* current output byte */
+ b; /* next output byte */
+ int c; /* count of |indent| and |outdent| tokens */
+ char scratch[longest_name]; /* scratch area for section names */
+ char *k, *k_limit; /* indices into |scratch| */
+ char *j; /* index into |buffer| */
+ char *p; /* index into |byte_mem| */
+ char delim; /* first and last character of string being copied */
+ char *save_loc, *save_limit; /* |loc| and |limit| to be restored */
+ name_pointer cur_section_name; /* name of section being output */
+ boolean save_mode; /* value of |cur_mode| before a sequence of breaks */
+ app(end_translation); /* append a sentinel */
+ freeze_text; push_level(text_ptr-1);
+ while (1) {
+ a=get_output();
+ reswitch: switch(a) {
+ case end_translation: return;
+ case identifier: case res_word: @<Output an identifier@>; break;
+ case section_code: @<Output a section name@>; break;
+ case math_rel: out_str("\\MRL{"@q}@>);
+@.\\MRL@>
+ case noop: case inserted: break;
+ case cancel: case big_cancel: c=0; b=a;
+ while (1) {
+ a=get_output();
+ if (a==inserted) continue;
+ if ((a<indent && !(b==big_cancel&&a==' ')) || a>big_force) break;
+ if (a==indent) c++; else if (a==outdent) c--;
+ else if (a==opt) a=get_output();
+ }
+ @<Output saved |indent| or |outdent| tokens@>;
+ goto reswitch;
+ case indent: case outdent: case opt: case backup: case break_space:
+ case force: case big_force: case preproc_line: @<Output a control,
+ look ahead in case of line breaks, possibly |goto reswitch|@>; break;
+ case quoted_char: out(*(cur_tok++)); break;
+ default: out(a); /* otherwise |a| is an ordinary character */
+ }
+ }
+}
+
+@ An identifier of length one does not have to be enclosed in braces, and it
+looks slightly better if set in a math-italic font instead of a (slightly
+narrower) text-italic font. Thus we output `\.{\\\v}\.{a}' but
+`\.{\\\\\{aa\}}'.
+
+@<Output an identifier@>=
+out('\\');
+if (a==identifier) {
+ if (cur_name->ilk>=custom && cur_name->ilk<=quoted && !doing_format) {
+ for (p=cur_name->byte_start;p<(cur_name+1)->byte_start;p++)
+ out(isxalpha(*p)? 'x':*p);
+ break;
+ } else if (is_tiny(cur_name)) out('|')
+@.\\|@>
+ else { delim='.';
+ for (p=cur_name->byte_start;p<(cur_name+1)->byte_start;p++)
+ if (xislower(*p)) { /* not entirely uppercase */
+ delim='\\'; break;
+ }
+ out(delim);
+ }
+@.\\\\@>
+@.\\.@>
+}
+else out('&') /* |a==res_word| */
+@.\\\&@>
+if (is_tiny(cur_name)) {
+ if (isxalpha((cur_name->byte_start)[0]))
+ out('\\');
+ out((cur_name->byte_start)[0]);
+}
+else out_name(cur_name);
+
+@ The current mode does not affect the behavior of \.{CWEAVE}'s output routine
+except when we are outputting control tokens.
+
+@<Output a control...@>=
+if (a<break_space || a==preproc_line) {
+ if (cur_mode==outer) {
+ out('\\'); out(a-cancel+'0');
+@.\\1@>
+@.\\2@>
+@.\\3@>
+@.\\4@>
+@.\\8@>
+ if (a==opt) {
+ b=get_output(); /* |opt| is followed by a digit */
+ if (b!='0' || force_lines==0) out(b)@;
+ else out_str("{-1}"); /* |force_lines| encourages more \.{@@\v} breaks */
+ }
+ } else if (a==opt) b=get_output(); /* ignore digit following |opt| */
+ }
+else @<Look ahead for strongest line break, |goto reswitch|@>
+
+@ If several of the tokens |break_space|, |force|, |big_force| occur in a
+row, possibly mixed with blank spaces (which are ignored),
+the largest one is used. A line break also occurs in the output file,
+except at the very end of the translation. The very first line break
+is suppressed (i.e., a line break that follows `\.{\\Y\\B}').
+
+@<Look ahead for st...@>= {
+ b=a; save_mode=cur_mode; c=0;
+ while (1) {
+ a=get_output();
+ if (a==inserted) continue;
+ if (a==cancel || a==big_cancel) {
+ @<Output saved |indent| or |outdent| tokens@>;
+ goto reswitch; /* |cancel| overrides everything */
+ }
+ if ((a!=' ' && a<indent) || a==backup || a>big_force) {
+ if (save_mode==outer) {
+ if (out_ptr>out_buf+3 && strncmp(out_ptr-3,"\\Y\\B",4)==0)
+ goto reswitch;
+ @<Output saved |indent| or |outdent| tokens@>;
+ out('\\'); out(b-cancel+'0');
+@.\\5@>
+@.\\6@>
+@.\\7@>
+ if (a!=end_translation) finish_line();
+ }
+ else if (a!=end_translation && cur_mode==inner) out(' ');
+ goto reswitch;
+ }
+ if (a==indent) c++;
+ else if (a==outdent) c--;
+ else if (a==opt) a=get_output();
+ else if (a>b) b=a; /* if |a==' '| we have |a<b| */
+ }
+}
+
+@ @<Output saved...@>=
+ for (;c>0;c--) out_str("\\1");
+@.\\1@>
+ for (;c<0;c++) out_str("\\2");
+@.\\2@>
+
+@ The remaining part of |make_output| is somewhat more complicated. When we
+output a section name, we may need to enter the parsing and translation
+routines, since the name may contain \CEE/ code embedded in
+\pb\ constructions. This \CEE/ code is placed at the end of the active
+input buffer and the translation process uses the end of the active
+|tok_mem| area.
+
+@<Output a section name@>= {
+ out_str("\\X");
+@.\\X@>
+ cur_xref=(xref_pointer)cur_name->xref;
+ if (cur_xref->num==file_flag) {an_output=1; cur_xref=cur_xref->xlink;}
+ else an_output=0;
+ if (cur_xref->num>=def_flag) {
+ out_section(cur_xref->num-def_flag);
+ if (phase==3) {
+ cur_xref=cur_xref->xlink;
+ while (cur_xref->num>=def_flag) {
+ out_str(", ");
+ out_section(cur_xref->num-def_flag);
+ cur_xref=cur_xref->xlink;
+ }
+ }
+ }
+ else out('0'); /* output the section number, or zero if it was undefined */
+ out(':');
+ if (an_output) out_str("\\.{"@q}@>);
+@.\\.@>
+ @<Output the text of the section name@>;
+ if (an_output) out_str(@q{@>" }");
+ out_str("\\X");
+}
+
+@ @<Output the text...@>=
+sprint_section_name(scratch,cur_name);
+k=scratch;
+k_limit=scratch+strlen(scratch);
+cur_section_name=cur_name;
+while (k<k_limit) {
+ b=*(k++);
+ if (b=='@@') @<Skip next character, give error if not `\.{@@}'@>;
+ if (an_output)
+ switch (b) {
+ case ' ':case '\\':case '#':case '%':case '$':case '^':
+ case '{': case '}': case '~': case '&': case '_':
+ out('\\'); /* falls through */
+@.\\\ @>
+@.\\\\@>
+@.\\\#@>
+@.\\\%@>
+@.\\\$@>
+@.\\\^@>
+@.\\\{@>@q}@>
+@q{@>@.\\\}@>
+@.\\\~@>
+@.\\\&@>
+@.\\_@> @q CWEAVE does quote an underscore! @>
+ default: out(b);
+ }
+ else if (b!='|') out(b)
+ else {
+ @<Copy the \CEE/ text into the |buffer| array@>;
+ save_loc=loc; save_limit=limit; loc=limit+2; limit=j+1;
+ *limit='|'; output_C();
+ loc=save_loc; limit=save_limit;
+ }
+}
+
+@ @<Skip next char...@>=
+if (*k++!='@@') {
+ printf("\n! Illegal control code in section name: <");
+@.Illegal control code...@>
+ print_section_name(cur_section_name); printf("> "); mark_error;
+}
+
+@ The \CEE/ text enclosed in \pb\ should not contain `\.{\v}' characters,
+except within strings. We put a `\.{\v}' at the front of the buffer, so that an
+error message that displays the whole buffer will look a little bit sensible.
+The variable |delim| is zero outside of strings, otherwise it
+equals the delimiter that began the string being copied.
+
+@<Copy the \CEE/ text into...@>=
+j=limit+1; *j='|'; delim=0;
+while (1) {
+ if (k>=k_limit) {
+ printf("\n! C text in section name didn't end: <");
+@.C text...didn't end@>
+ print_section_name(cur_section_name); printf("> "); mark_error; break;
+ }
+ b=*(k++);
+ if (b=='@@' || (b=='\\' && delim!=0))
+ @<Copy a quoted character into the buffer@>
+ else {
+ if (b=='\'' || b=='"')
+ if (delim==0) delim=b;
+ else if (delim==b) delim=0;
+ if (b!='|' || delim!=0) {
+ if (j>buffer+long_buf_size-3) overflow("buffer");
+ *(++j)=b;
+ }
+ else break;
+ }
+}
+
+@ @<Copy a quoted char...@>= {
+ if (j>buffer+long_buf_size-4) overflow("buffer");
+ *(++j)=b; *(++j)=*(k++);
+}
+
+@** Phase two processing.
+We have assembled enough pieces of the puzzle in order to be ready to specify
+the processing in \.{CWEAVE}'s main pass over the source file. Phase two
+is analogous to phase one, except that more work is involved because we must
+actually output the \TEX/ material instead of merely looking at the
+\.{CWEB} specifications.
+
+@<Predecl...@>=
+void phase_two();
+
+@ @c
+void
+phase_two() {
+reset_input(); if (show_progress) printf("\nWriting the output file...");
+@.Writing the output file...@>
+section_count=0; format_visible=1; copy_limbo();
+finish_line(); flush_buffer(out_buf,0,0); /* insert a blank line, it looks nice */
+while (!input_has_ended) @<Translate the current section@>;
+}
+
+@ The output file will contain the control sequence \.{\\Y} between non-null
+sections of a section, e.g., between the \TEX/ and definition parts if both
+are nonempty. This puts a little white space between the parts when they are
+printed. However, we don't want \.{\\Y} to occur between two definitions
+within a single section. The variables |out_line| or |out_ptr| will
+change if a section is non-null, so the following macros `|save_position|'
+and `|emit_space_if_needed|' are able to handle the situation:
+
+@d save_position save_line=out_line; save_place=out_ptr
+@d emit_space_if_needed if (save_line!=out_line || save_place!=out_ptr)
+ out_str("\\Y");
+ space_checked=1
+@.\\Y@>
+
+@<Global...@>=
+int save_line; /* former value of |out_line| */
+char *save_place; /* former value of |out_ptr| */
+int sec_depth; /* the integer, if any, following \.{@@*} */
+boolean space_checked; /* have we done |emit_space_if_needed|? */
+boolean format_visible; /* should the next format declaration be output? */
+boolean doing_format=0; /* are we outputting a format declaration? */
+boolean group_found=0; /* has a starred section occurred? */
+
+@ @<Translate the current section@>= {
+ section_count++;
+ @<Output the code for the beginning of a new section@>;
+ save_position;
+ @<Translate the \TEX/ part of the current section@>;
+ @<Translate the definition part of the current section@>;
+ @<Translate the \CEE/ part of the current section@>;
+ @<Show cross-references to this section@>;
+ @<Output the code for the end of a section@>;
+}
+
+@ Sections beginning with the \.{CWEB} control sequence `\.{@@\ }' start in the
+output with the \TEX/ control sequence `\.{\\M}', followed by the section
+number. Similarly, `\.{@@*}' sections lead to the control sequence `\.{\\N}'.
+In this case there's an additional parameter, representing one plus the
+specified depth, immediately after the \.{\\N}.
+If the section has changed, we put \.{\\*} just after the section number.
+
+@<Output the code for the beginning...@>=
+if (*(loc-1)!='*') out_str("\\M");
+@.\\M@>
+else {
+ while (*loc == ' ') loc++;
+ if (*loc=='*') { /* ``top'' level */
+ sec_depth = -1;
+ loc++;
+ }
+ else {
+ for (sec_depth=0; xisdigit(*loc);loc++)
+ sec_depth = sec_depth*10 + (*loc) -'0';
+ }
+ while (*loc == ' ') loc++; /* remove spaces before group title */
+ group_found=1;
+ out_str("\\N");
+@.\\N@>
+ {@+ char s[32];@+sprintf(s,"{%d}",sec_depth+1);@+out_str(s);@+}
+ if (show_progress)
+ printf("*%d",section_count); update_terminal; /* print a progress report */
+}
+out_str("{");out_section(section_count); out_str("}");
+
+@ In the \TEX/ part of a section, we simply copy the source text, except that
+index entries are not copied and \CEE/ text within \pb\ is translated.
+
+@<Translate the \T...@>= do {
+ next_control=copy_TeX();
+ switch (next_control) {
+ case '|': init_stack; output_C(); break;
+ case '@@': out('@@'); break;
+ case TeX_string: case noop:
+ case xref_roman: case xref_wildcard: case xref_typewriter:
+ case section_name: loc-=2; next_control=get_next(); /* skip to \.{@@>} */
+ if (next_control==TeX_string)
+ err_print("! TeX string should be in C text only"); break;
+@.TeX string should be...@>
+ case thin_space: case math_break: case ord:
+ case line_break: case big_line_break: case no_line_break: case join:
+ case pseudo_semi: case macro_arg_open: case macro_arg_close:
+ case output_defs_code:
+ err_print("! You can't do that in TeX text"); break;
+@.You can't do that...@>
+ }
+} while (next_control<format_code);
+
+@ When we get to the following code we have |next_control>=format_code|, and
+the token memory is in its initial empty state.
+
+@<Translate the d...@>=
+space_checked=0;
+while (next_control<=definition) { /* |format_code| or |definition| */
+ init_stack;
+ if (next_control==definition) @<Start a macro definition@>@;
+ else @<Start a format definition@>;
+ outer_parse(); finish_C(format_visible); format_visible=1;
+ doing_format=0;
+}
+
+@ The |finish_C| procedure outputs the translation of the current
+scraps, preceded by the control sequence `\.{\\B}' and followed by the
+control sequence `\.{\\par}'. It also restores the token and scrap
+memories to their initial empty state.
+
+A |force| token is appended to the current scraps before translation
+takes place, so that the translation will normally end with \.{\\6} or
+\.{\\7} (the \TEX/ macros for |force| and |big_force|). This \.{\\6} or
+\.{\\7} is replaced by the concluding \.{\\par} or by \.{\\Y\\par}.
+
+@<Predecl...@>=
+void finish_C();
+
+@ @c
+void
+finish_C(visible) /* finishes a definition or a \CEE/ part */
+ boolean visible; /* nonzero if we should produce \TEX/ output */
+{
+ text_pointer p; /* translation of the scraps */
+ if (visible) {
+ out_str("\\B"); app_tok(force); app_scrap(insert,no_math);
+ p=translate();
+@.\\B@>
+ app(tok_flag+(int)(p-tok_start)); make_output(); /* output the list */
+ if (out_ptr>out_buf+1)
+ if (*(out_ptr-1)=='\\')
+@.\\6@>
+@.\\7@>
+@.\\Y@>
+ if (*out_ptr=='6') out_ptr-=2;
+ else if (*out_ptr=='7') *out_ptr='Y';
+ out_str("\\par"); finish_line();
+ }
+ if (text_ptr>max_text_ptr) max_text_ptr=text_ptr;
+ if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr;
+ if (scrap_ptr>max_scr_ptr) max_scr_ptr=scrap_ptr;
+ tok_ptr=tok_mem+1; text_ptr=tok_start+1; scrap_ptr=scrap_info;
+ /* forget the tokens and the scraps */
+}
+
+@ Keeping in line with the conventions of the \CEE/ preprocessor (and
+otherwise contrary to the rules of \.{CWEB}) we distinguish here
+between the case that `\.(' immediately follows an identifier and the
+case that the two are separated by a space. In the latter case, and
+if the identifier is not followed by `\.(' at all, the replacement
+text starts immediately after the identifier. In the former case,
+it starts after we scan the matching `\.)'.
+
+@<Start a macro...@>= {
+ if (save_line!=out_line || save_place!=out_ptr || space_checked) app(backup);
+ if(!space_checked){emit_space_if_needed;save_position;}
+ app_str("\\D"); /* this will produce `\&{define }' */
+@.\\D@>
+ if ((next_control=get_next())!=identifier)
+ err_print("! Improper macro definition");
+@.Improper macro definition@>
+ else {
+ app('$'); app_cur_id(0);
+ if (*loc=='(')
+ reswitch: switch (next_control=get_next()) {
+ case '(': case ',': app(next_control); goto reswitch;
+ case identifier: app_cur_id(0); goto reswitch;
+ case ')': app(next_control); next_control=get_next(); break;
+ default: err_print("! Improper macro definition"); break;
+ }
+ else next_control=get_next();
+ app_str("$ "); app(break_space);
+ app_scrap(dead,no_math); /* scrap won't take part in the parsing */
+ }
+}
+
+@ @<Start a format...@>= {
+ doing_format=1;
+ if(*(loc-1)=='s' || *(loc-1)=='S') format_visible=0;
+ if(!space_checked){emit_space_if_needed;save_position;}
+ app_str("\\F"); /* this will produce `\&{format }' */
+@.\\F@>
+ next_control=get_next();
+ if (next_control==identifier) {
+ app(id_flag+(int)(id_lookup(id_first, id_loc,normal)-name_dir));
+ app(' ');
+ app(break_space); /* this is syntactically separate from what follows */
+ next_control=get_next();
+ if (next_control==identifier) {
+ app(id_flag+(int)(id_lookup(id_first, id_loc,normal)-name_dir));
+ app_scrap(exp,maybe_math); app_scrap(semi,maybe_math);
+ next_control=get_next();
+ }
+ }
+ if (scrap_ptr!=scrap_info+2) err_print("! Improper format definition");
+@.Improper format definition@>
+}
+
+@ Finally, when the \TEX/ and definition parts have been treated, we have
+|next_control>=begin_C|. We will make the global variable |this_section|
+point to the current section name, if it has a name.
+
+@<Global...@>=
+name_pointer this_section; /* the current section name, or zero */
+
+@ @<Translate the \CEE/...@>=
+this_section=name_dir;
+if (next_control<=section_name) {
+ emit_space_if_needed; init_stack;
+ if (next_control==begin_C) next_control=get_next();
+ else {
+ this_section=cur_section;
+ @<Check that '=' or '==' follows this section name, and
+ emit the scraps to start the section definition@>;
+ }
+ while (next_control<=section_name) {
+ outer_parse();
+ @<Emit the scrap for a section name if present@>;
+ }
+ finish_C(1);
+}
+
+@ The title of the section and an $\E$ or $\mathrel+\E$ are made
+into a scrap that should not take part in the parsing.
+
+@<Check that '='...@>=
+do next_control=get_next();
+ while (next_control=='+'); /* allow optional `\.{+=}' */
+if (next_control!='=' && next_control!=eq_eq)
+ err_print("! You need an = sign after the section name");
+@.You need an = sign...@>
+ else next_control=get_next();
+if (out_ptr>out_buf+1 && *out_ptr=='Y' && *(out_ptr-1)=='\\') app(backup);
+ /* the section name will be flush left */
+@.\\Y@>
+app(section_flag+(int)(this_section-name_dir));
+cur_xref=(xref_pointer)this_section->xref;
+if(cur_xref->num==file_flag) cur_xref=cur_xref->xlink;
+app_str("${}");
+if (cur_xref->num!=section_count+def_flag) {
+ app_str("\\mathrel+"); /*section name is multiply defined*/
+ this_section=name_dir; /*so we won't give cross-reference info here*/
+}
+app_str("\\E"); /* output an equivalence sign */
+@.\\E@>
+app_str("{}$");
+app(force); app_scrap(dead,no_math);
+ /* this forces a line break unless `\.{@@+}' follows */
+
+@ @<Emit the scrap...@>=
+if (next_control<section_name) {
+ err_print("! You can't do that in C text");
+@.You can't do that...@>
+ next_control=get_next();
+}
+else if (next_control==section_name) {
+ app(section_flag+(int)(cur_section-name_dir));
+ app_scrap(section_scrap,maybe_math);
+ next_control=get_next();
+}
+
+@ Cross references relating to a named section are given
+after the section ends.
+
+@<Show cross...@>=
+if (this_section>name_dir) {
+ cur_xref=(xref_pointer)this_section->xref;
+ if (cur_xref->num==file_flag){an_output=1;cur_xref=cur_xref->xlink;}
+ else an_output=0;
+ if (cur_xref->num>def_flag)
+ cur_xref=cur_xref->xlink; /* bypass current section number */
+ footnote(def_flag); footnote(cite_flag); footnote(0);
+}
+
+@ The |footnote| procedure gives cross-reference information about
+multiply defined section names (if the |flag| parameter is
+|def_flag|), or about references to a section name
+(if |flag==cite_flag|), or to its uses (if |flag==0|). It assumes that
+|cur_xref| points to the first cross-reference entry of interest, and it
+leaves |cur_xref| pointing to the first element not printed. Typical outputs:
+`\.{\\A101.}'; `\.{\\Us 370\\ET1009.}';
+`\.{\\As 8, 27\\*\\ETs64.}'.
+
+Note that the output of \.{CWEAVE} is not English-specific; users may
+supply new definitions for the macros \.{\\A}, \.{\\As}, etc.
+
+@<Predecl...@>=
+void footnote();
+
+@ @c
+void
+footnote(flag) /* outputs section cross-references */
+sixteen_bits flag;
+{
+ xref_pointer q; /* cross-reference pointer variable */
+ if (cur_xref->num<=flag) return;
+ finish_line(); out('\\');
+@.\\A@>
+@.\\Q@>
+@.\\U@>
+ out(flag==0? 'U': flag==cite_flag? 'Q': 'A');
+ @<Output all the section numbers on the reference list |cur_xref|@>;
+ out('.');
+}
+
+@ The following code distinguishes three cases, according as the number
+of cross-references is one, two, or more than two. Variable |q| points
+to the first cross-reference, and the last link is a zero.
+
+@<Output all the section numbers...@>=
+q=cur_xref; if (q->xlink->num>flag) out('s'); /* plural */
+while (1) {
+ out_section(cur_xref->num-flag);
+ cur_xref=cur_xref->xlink; /* point to the next cross-reference to output */
+ if (cur_xref->num<=flag) break;
+ if (cur_xref->xlink->num>flag) out_str(", "); /* not the last */
+ else {out_str("\\ET"); /* the last */
+@.\\ET@>
+ if (cur_xref != q->xlink) out('s'); /* the last of more than two */
+ }
+}
+
+@ @<Output the code for the end of a section@>=
+out_str("\\fi"); finish_line();
+@.\\fi@>
+flush_buffer(out_buf,0,0); /* insert a blank line, it looks nice */
+
+@** Phase three processing.
+We are nearly finished! \.{CWEAVE}'s only remaining task is to write out the
+index, after sorting the identifiers and index entries.
+
+If the user has set the |no_xref| flag (the \.{-x} option on the command line),
+just finish off the page, omitting the index, section name list, and table of
+contents.
+
+@<Predecl...@>=
+void phase_three();
+
+@ @c
+void
+phase_three() {
+if (no_xref) {
+ finish_line();
+ out_str("\\end");
+@.\\end@>
+ finish_line();
+}
+else {
+ phase=3; if (show_progress) printf("\nWriting the index...");
+@.Writing the index...@>
+ finish_line();
+ if ((idx_file=fopen(idx_file_name,"w"))==NULL)
+ fatal("! Cannot open index file ",idx_file_name);
+@.Cannot open index file@>
+ if (change_exists) {
+ @<Tell about changed sections@>; finish_line(); finish_line();
+ }
+ out_str("\\inx"); finish_line();
+@.\\inx@>
+ active_file=idx_file; /* change active file to the index file */
+ @<Do the first pass of sorting@>;
+ @<Sort and output the index@>;
+ finish_line(); fclose(active_file); /* finished with |idx_file| */
+ active_file=tex_file; /* switch back to |tex_file| for a tic */
+ out_str("\\fin"); finish_line();
+@.\\fin@>
+ if ((scn_file=fopen(scn_file_name,"w"))==NULL)
+ fatal("! Cannot open section file ",scn_file_name);
+@.Cannot open section file@>
+ active_file=scn_file; /* change active file to section listing file */
+ @<Output all the section names@>;
+ finish_line(); fclose(active_file); /* finished with |scn_file| */
+ active_file=tex_file;
+ if (group_found) out_str("\\con");@+else out_str("\\end");
+@.\\con@>
+@.\\end@>
+ finish_line();
+ fclose(active_file);
+}
+if (show_happiness) printf("\nDone.");
+check_complete(); /* was all of the change file used? */
+}
+
+@ Just before the index comes a list of all the changed sections, including
+the index section itself.
+
+@<Global...@>=
+sixteen_bits k_section; /* runs through the sections */
+
+@ @<Tell about changed sections@>= {
+ /* remember that the index is already marked as changed */
+ k_section=0;
+ while (!changed_section[++k_section]);
+ out_str("\\ch ");
+@.\\ch@>
+ out_section(k_section);
+ while (k_section<section_count) {
+ while (!changed_section[++k_section]);
+ out_str(", "); out_section(k_section);
+ }
+ out('.');
+}
+
+@ A left-to-right radix sorting method is used, since this makes it easy to
+adjust the collating sequence and since the running time will be at worst
+proportional to the total length of all entries in the index. We put the
+identifiers into 102 different lists based on their first characters.
+(Uppercase letters are put into the same list as the corresponding lowercase
+letters, since we want to have `$t<\\{TeX}<\&{to}$'.) The
+list for character |c| begins at location |bucket[c]| and continues through
+the |blink| array.
+
+@<Global...@>=
+name_pointer bucket[256];
+name_pointer next_name; /* successor of |cur_name| when sorting */
+name_pointer blink[max_names]; /* links in the buckets */
+
+@ To begin the sorting, we go through all the hash lists and put each entry
+having a nonempty cross-reference list into the proper bucket.
+
+@<Do the first pass...@>= {
+int c;
+for (c=0; c<=255; c++) bucket[c]=NULL;
+for (h=hash; h<=hash_end; h++) {
+ next_name=*h;
+ while (next_name) {
+ cur_name=next_name; next_name=cur_name->link;
+ if (cur_name->xref!=(char*)xmem) {
+ c=(eight_bits)((cur_name->byte_start)[0]);
+ if (xisupper(c)) c=tolower(c);
+ blink[cur_name-name_dir]=bucket[c]; bucket[c]=cur_name;
+ }
+ }
+}
+}
+
+@ During the sorting phase we shall use the |cat| and |trans| arrays from
+\.{CWEAVE}'s parsing algorithm and rename them |depth| and |head|. They now
+represent a stack of identifier lists for all the index entries that have
+not yet been output. The variable |sort_ptr| tells how many such lists are
+present; the lists are output in reverse order (first |sort_ptr|, then
+|sort_ptr-1|, etc.). The |j|th list starts at |head[j]|, and if the first
+|k| characters of all entries on this list are known to be equal we have
+|depth[j]==k|.
+
+@ @<Rest of |trans_plus| union@>=
+name_pointer Head;
+
+@ @d depth cat /* reclaims memory that is no longer needed for parsing */
+@d head trans_plus.Head /* ditto */
+@f sort_pointer int
+@d sort_pointer scrap_pointer /* ditto */
+@d sort_ptr scrap_ptr /* ditto */
+@d max_sorts max_scraps /* ditto */
+
+@<Global...@>=
+eight_bits cur_depth; /* depth of current buckets */
+char *cur_byte; /* index into |byte_mem| */
+sixteen_bits cur_val; /* current cross-reference number */
+sort_pointer max_sort_ptr; /* largest value of |sort_ptr| */
+
+@ @<Set init...@>=
+max_sort_ptr=scrap_info;
+
+@ The desired alphabetic order is specified by the |collate| array; namely,
+$|collate|[0]<|collate|[1]<\cdots<|collate|[100]$.
+
+@<Global...@>=
+eight_bits collate[102+128]; /* collation order */
+@^high-bit character handling@>
+
+@ We use the order $\hbox{null}<\.\ <\hbox{other characters}<{}$\.\_${}<
+\.A=\.a<\cdots<\.Z=\.z<\.0<\cdots<\.9.$ Warning: The collation mapping
+needs to be changed if ASCII code is not being used.
+@^ASCII code dependencies@>
+@^high-bit character handling@>
+
+We initialize |collate| by copying a few characters at a time, because
+some \CEE/ compilers choke on long strings.
+
+@<Set init...@>=
+collate[0]=0;
+strcpy(collate+1," \1\2\3\4\5\6\7\10\11\12\13\14\15\16\17");
+/* 16 characters + 1 = 17 */
+strcpy(collate+17,"\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37");
+/* 16 characters + 17 = 33 */
+strcpy(collate+33,"!\42#$%&'()*+,-./:;<=>?@@[\\]^`{|}~_");
+/* 32 characters + 33 = 65 */
+strcpy(collate+65,"abcdefghijklmnopqrstuvwxyz0123456789");
+/* (26 + 10) characters + 65 = 101 */
+strcpy(collate+101,"\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217");
+/* 16 characters + 101 = 117 */
+strcpy(collate+117,"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237");
+/* 16 characters + 117 = 133 */
+strcpy(collate+133,"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257");
+/* 16 characters + 133 = 149 */
+strcpy(collate+149,"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277");
+/* 16 characters + 149 = 165 */
+strcpy(collate+165,"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317");
+/* 16 characters + 165 = 181 */
+strcpy(collate+181,"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337");
+/* 16 characters + 181 = 197 */
+strcpy(collate+197,"\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357");
+/* 16 characters + 197 = 213 */
+strcpy(collate+213,"\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377");
+/* 16 characters + 213 = 229 */
+
+@ Procedure |unbucket| goes through the buckets and adds nonempty lists
+to the stack, using the collating sequence specified in the |collate| array.
+The parameter to |unbucket| tells the current depth in the buckets.
+Any two sequences that agree in their first 255 character positions are
+regarded as identical.
+
+@d infinity 255 /* $\infty$ (approximately) */
+
+@<Predecl...@>=
+void unbucket();
+
+@ @c
+void
+unbucket(d) /* empties buckets having depth |d| */
+eight_bits d;
+{
+ int c; /* index into |bucket|; cannot be a simple |char| because of sign
+ comparison below*/
+ for (c=100+128; c>= 0; c--) if (bucket[collate[c]]) {
+@^high-bit character handling@>
+ if (sort_ptr>=scrap_info_end) overflow("sorting");
+ sort_ptr++;
+ if (sort_ptr>max_sort_ptr) max_sort_ptr=sort_ptr;
+ if (c==0) sort_ptr->depth=infinity;
+ else sort_ptr->depth=d;
+ sort_ptr->head=bucket[collate[c]]; bucket[collate[c]]=NULL;
+ }
+}
+
+@ @<Sort and output...@>=
+sort_ptr=scrap_info; unbucket(1);
+while (sort_ptr>scrap_info) {
+ cur_depth=sort_ptr->depth;
+ if (blink[sort_ptr->head-name_dir]==0 || cur_depth==infinity)
+ @<Output index entries for the list at |sort_ptr|@>@;
+ else @<Split the list at |sort_ptr| into further lists@>;
+}
+
+@ @<Split the list...@>= {
+ eight_bits c;
+ next_name=sort_ptr->head;
+ do {
+ cur_name=next_name; next_name=blink[cur_name-name_dir];
+ cur_byte=cur_name->byte_start+cur_depth;
+ if (cur_byte==(cur_name+1)->byte_start) c=0; /* hit end of the name */
+ else {
+ c=(eight_bits) *cur_byte;
+ if (xisupper(c)) c=tolower(c);
+ }
+ blink[cur_name-name_dir]=bucket[c]; bucket[c]=cur_name;
+ } while (next_name);
+ --sort_ptr; unbucket(cur_depth+1);
+}
+
+@ @<Output index...@>= {
+ cur_name=sort_ptr->head;
+ do {
+ out_str("\\I");
+@.\\I@>
+ @<Output the name at |cur_name|@>;
+ @<Output the cross-references at |cur_name|@>;
+ cur_name=blink[cur_name-name_dir];
+ } while (cur_name);
+ --sort_ptr;
+}
+
+@ @<Output the name...@>=
+switch (cur_name->ilk) {
+ case normal: if (is_tiny(cur_name)) out_str("\\|");
+ else {char *j;
+ for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
+ if (xislower(*j)) goto lowcase;
+ out_str("\\."); break;
+lowcase: out_str("\\\\");
+ }
+ break;
+@.\\|@>
+@.\\.@>
+@.\\\\@>
+ case roman: break;
+ case wildcard: out_str("\\9"); break;
+@.\\9@>
+ case typewriter: out_str("\\."); break;
+@.\\.@>
+ case custom: case quoted: {char *j; out_str("$\\");
+ for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
+ out(isxalpha(*j)? 'x' : *j);
+ out('$');
+ goto name_done;
+ }
+ default: out_str("\\&");
+@.\\\&@>
+}
+out_name(cur_name);
+name_done:
+
+@ Section numbers that are to be underlined are enclosed in
+`\.{\\[}$\,\ldots\,$\.]'.
+
+@<Output the cross-references...@>=
+@<Invert the cross-reference list at |cur_name|, making |cur_xref| the head@>;
+do {
+ out_str(", "); cur_val=cur_xref->num;
+ if (cur_val<def_flag) out_section(cur_val);
+ else {out_str("\\["); out_section(cur_val-def_flag); out(']');}
+@.\\[@>
+ cur_xref=cur_xref->xlink;
+} while (cur_xref!=xmem);
+out('.'); finish_line();
+
+@ List inversion is best thought of as popping elements off one stack and
+pushing them onto another. In this case |cur_xref| will be the head of
+the stack that we push things onto.
+@<Global...@>=
+xref_pointer next_xref, this_xref;
+ /* pointer variables for rearranging a list */
+
+@ @<Invert the cross-reference list at |cur_name|, making |cur_xref| the head@>=
+this_xref=(xref_pointer)cur_name->xref; cur_xref=xmem;
+do {
+ next_xref=this_xref->xlink; this_xref->xlink=cur_xref;
+ cur_xref=this_xref; this_xref=next_xref;
+} while (this_xref!=xmem);
+
+@ The following recursive procedure walks through the tree of section names and
+prints them.
+@^recursion@>
+
+@<Predecl...@>=
+void section_print();
+
+@ @c
+void
+section_print(p) /* print all section names in subtree |p| */
+name_pointer p;
+{
+ if (p) {
+ section_print(p->llink); out_str("\\I");
+@.\\I@>
+ tok_ptr=tok_mem+1; text_ptr=tok_start+1; scrap_ptr=scrap_info; init_stack;
+ app(p-name_dir+section_flag); make_output();
+ footnote(cite_flag);
+ footnote(0); /* |cur_xref| was set by |make_output| */
+ finish_line();@/
+ section_print(p->rlink);
+ }
+}
+
+@ @<Output all the section names@>=section_print(root)
+
+@ Because on some systems the difference between two pointers is a |long|
+rather than an |int|, we use \.{\%ld} to print these quantities.
+
+@c
+void
+print_stats() {
+ printf("\nMemory usage statistics:\n");
+@.Memory usage statistics:@>
+ printf("%ld names (out of %ld)\n",
+ (long)(name_ptr-name_dir),(long)max_names);
+ printf("%ld cross-references (out of %ld)\n",
+ (long)(xref_ptr-xmem),(long)max_refs);
+ printf("%ld bytes (out of %ld)\n",
+ (long)(byte_ptr-byte_mem),(long)max_bytes);
+ printf("Parsing:\n");
+ printf("%ld scraps (out of %ld)\n",
+ (long)(max_scr_ptr-scrap_info),(long)max_scraps);
+ printf("%ld texts (out of %ld)\n",
+ (long)(max_text_ptr-tok_start),(long)max_texts);
+ printf("%ld tokens (out of %ld)\n",
+ (long)(max_tok_ptr-tok_mem),(long)max_toks);
+ printf("%ld levels (out of %ld)\n",
+ (long)(max_stack_ptr-stack),(long)stack_size);
+ printf("Sorting:\n");
+ printf("%ld levels (out of %ld)\n",
+ (long)(max_sort_ptr-scrap_info),(long)max_scraps);
+}
+
+@** Index.
+If you have read and understood the code for Phase III above, you know what
+is in this index and how it got here. All sections in which an identifier is
+used are listed with that identifier, except that reserved words are
+indexed only when they appear in format definitions, and the appearances
+of identifiers in section names are not indexed. Underlined entries
+correspond to where the identifier was declared. Error messages, control
+sequences put into the output, and a few
+other things like ``recursion'' are indexed here too.
diff --git a/web/c_cpp/c2cweb/cweb/cwebmac.ori b/web/c_cpp/c2cweb/cweb/cwebmac.ori
new file mode 100644
index 0000000000..331a2eff46
--- /dev/null
+++ b/web/c_cpp/c2cweb/cweb/cwebmac.ori
@@ -0,0 +1,346 @@
+% This file is part of c2cweb package Version 1.5
+
+% standard macros for CWEB listings (in addition to plain.tex)
+% Version 3.0 --- June 1993
+
+% modified by Werner Lemberg (a7971428@unet.univie.ac.at) 10-Nov-1996
+
+\ifx\documentstyle\undefined\else\endinput\fi % LaTeX will use other macros
+\xdef\fmtversion{\fmtversion+CWEB3.0}
+
+\let\:=\. % preserve a way to get the dot accent
+ % (all other accents will still work as usual)
+
+\parskip 0pt % no stretch between paragraphs
+\parindent 1em % for paragraphs and for the first line of C text
+
+\font\ninerm=cmr9
+\let\mc=\ninerm % medium caps
+\def\CEE/{{\mc C\spacefactor1000}}
+\def\UNIX/{{\mc U\kern-.05emNIX\spacefactor1000}}
+\def\TEX/{\TeX}
+\def\CPLUSPLUS/{{\mc C\PP\spacefactor1000}}
+\def\Cee{\CEE/} % for backward compatibility
+\def\9#1{}
+\font\eightrm=cmr8
+\let\sc=\eightrm % small caps (NOT a caps-and-small-caps font)
+\let\mainfont=\tenrm
+\let\cmntfont\tenrm
+%\font\tenss=cmss10 \let\cmntfont\tenss % alternative comment font
+\font\titlefont=cmr7 scaled\magstep4 % title on the contents page
+\font\ttitlefont=cmtt10 scaled\magstep2 % typewriter type in title
+\font\tentex=cmtex10 % TeX extended character set (used in strings)
+\fontdimen7\tentex=0pt % no double space after sentences
+
+\def\${\ifmmode \hbox{\sl \char`\$}
+ \else \hbox{\ifdim \fontdimen1\font > 0pt \sl \fi \char`\$}\fi}
+
+\def\\#1{\leavevmode\hbox{\it#1\/\kern.05em}} % italic type for identifiers
+\def\|#1{\leavevmode\hbox{$#1$}} % one-letter identifiers look better this way
+\def\&#1{\leavevmode\hbox{\bf
+ \def\_{\kern.04em\vbox{\hrule width.3em height .6pt}\kern.08em}%
+ #1\/\kern.05em}} % boldface type for reserved words
+\def\.#1{\leavevmode\hbox{\tentex % typewriter type for strings
+ \let\\=\BS % backslash in a string
+ \let\{=\LB % left brace in a string
+ \let\}=\RB % right brace in a string
+ \let\~=\TL % tilde in a string
+ \let\ =\SP % space in a string
+ \let\_=\UL % underline in a string
+ \let\&=\AM % ampersand in a string
+ \let\^=\CF % circumflex in a string
+ #1\kern.05em}}
+\def\){\discretionary{\hbox{\tentex\BS}}{}{}}
+\def\AT{@} % at sign for control text (not needed in versions >= 2.9)
+\def\ATL{\par\noindent\bgroup\catcode`\_=12 \postATL} % print @l in limbo
+\def\postATL#1 #2 {\bf letter \\{\uppercase{\char"#1}}
+ tangles as \tentex "#2"\egroup\par}
+\def\noATL#1 #2 {}
+\def\noatl{\let\ATL=\noATL} % suppress output from @l
+\def\ATH{\X\kern-.5em:Preprocessor definitions\X}
+\let\PB=\relax % hook for program brackets |...| in TeX part or section name
+
+\chardef\AM=`\& % ampersand character in a string
+\chardef\BS=`\\ % backslash in a string
+\chardef\LB=`\{ % left brace in a string
+\chardef\RB=`\} % right brace in a string
+\def\SP{{\tt\char`\ }} % (visible) space in a string
+\chardef\TL=`\~ % tilde in a string
+\chardef\UL=`\_ % underline character in a string
+\chardef\CF=`\^ % circumflex character in a string
+
+\newbox\PPbox % symbol for ++
+\setbox\PPbox=\hbox{\kern.5pt\raise1pt\hbox{\sevenrm+\kern-1pt+}\kern.5pt}
+\def\PP{\copy\PPbox}
+\newbox\MMbox \setbox\MMbox=\hbox{\kern.5pt\raise1pt\hbox{\sevensy\char0
+ \kern-1pt\char0}\kern.5pt}
+\def\MM{\copy\MMbox}
+\newbox\MGbox % symbol for ->
+\setbox\MGbox=\hbox{\kern-2pt\lower3pt\hbox{\teni\char'176}\kern1pt}
+\def\MG{\copy\MGbox}
+\newbox\NNbox % symbol for ##
+\setbox\NNbox=\hbox{\kern.5pt\raise2pt\hbox{\#}\kern-4pt
+ \lower2pt\hbox{\#}\kern.5pt}
+\def\NN{\copy\NNbox}
+\def\MRL#1{\mathrel{\let\K==#1}}
+%\def\MRL#1{\KK#1}\def\KK#1#2{\buildrel\;#1\over{#2}}
+\let\GG=\gg
+\let\LL=\ll
+\let\NULL=\Lambda
+\mathchardef\AND="2026 % bitwise and; also \& (unary operator)
+\let\OR=\mid % bitwise or
+\let\XOR=\oplus % bitwise exclusive or
+\def\CM{{\sim}} % bitwise complement
+\newbox\MODbox \setbox\MODbox=\hbox{\eightrm\%}
+\def\MOD{\mathbin{\copy\MODbox}}
+\def\DC{\kern.1em{::}\kern.1em} % symbol for ::
+\def\PA{\mathbin{.*}} % symbol for .*
+\def\MGA{\mathbin{\MG*}} % symbol for ->*
+\def\this{\&{this}}
+
+\newbox\bak \setbox\bak=\hbox to -1em{} % backspace one em
+\newbox\bakk\setbox\bakk=\hbox to -2em{} % backspace two ems
+
+\newcount\ind % current indentation in ems
+\def\1{\global\advance\ind by1\hangindent\ind em} % indent one more notch
+\def\2{\global\advance\ind by-1} % indent one less notch
+\def\3#1{\hfil\penalty#10\hfilneg} % optional break within a statement
+\def\4{\copy\bak} % backspace one notch
+\def\5{\hfil\penalty-1\hfilneg\kern2.5em\copy\bakk\ignorespaces}% optional break
+\def\6{\ifmmode\else\par % forced break
+ \hangindent\ind em\noindent\kern\ind em\copy\bakk\ignorespaces\fi}
+\def\7{\Y\6} % forced break and a little extra space
+\def\8{\hskip-\ind em\hskip 2em} % no indentation
+
+\newcount\gdepth % depth of current major group, plus one
+\newcount\secpagedepth
+\secpagedepth=3 % page breaks will occur for depths -1, 0, and 1
+\newtoks\gtitle % title of current major group
+\newskip\intersecskip \intersecskip=12pt minus 3pt % space between sections
+\let\yskip=\smallskip
+\def\?{\mathrel?}
+\def\note#1#2.{\Y\noindent{\hangindent2em\baselineskip10pt\eightrm#1~#2.\par}}
+\def\lapstar{\rlap{*}}
+\def\stsec{\rightskip=0pt % get out of C mode (cf. \B)
+ \sfcode`;=1500 \pretolerance 200 \hyphenpenalty 50 \exhyphenpenalty 50
+ \noindent{\let\*=\lapstar\bf\secstar.\quad}}
+\let\startsection=\stsec
+\def\defin#1{\global\advance\ind by 2 \1\&{#1 } } % begin `define' or `format'
+\def\A{\note{See also section}} % xref for doubly defined section name
+\def\As{\note{See also sections}} % xref for multiply defined section name
+\def\B{\rightskip=0pt plus 100pt minus 10pt % go into C mode
+ \sfcode`;=3000
+ \pretolerance 10000
+ \hyphenpenalty 9999 % so strings can be broken (discretionary \ is inserted)
+ \exhyphenpenalty 10000
+ \global\ind=2 \1\ \unskip}
+\def\C#1{\5\5\quad$/\ast\,${\cmntfont #1}$\,\ast/$}
+\let\SHC\C % "// short comments" treated like "/* ordinary comments */"
+%\def\C#1{\5\5\quad$\triangleright\,${\cmntfont#1}$\,\triangleleft$}
+%\def\SHC#1{\5\5\quad$\diamond\,${\cmntfont#1}}
+\def\D{\defin{\#define}} % macro definition
+\let\E=\equiv % equivalence sign
+\def\ET{ and~} % conjunction between two section numbers
+\def\ETs{, and~} % conjunction between the last two of several section numbers
+\def\F{\defin{format}} % format definition
+\let\G=\ge % greater than or equal sign
+% \H is long Hungarian umlaut accent
+\let\I=\ne % unequal sign
+\def\J{\.{@\&}} % TANGLE's join operation
+\let\K== % assignment operator
+%\let\K=\leftarrow % "honest" alternative to standard assignment operator
+% \L is Polish letter suppressed-L
+\outer\def\M#1{\MN{#1}\ifon\vfil\penalty-100\vfilneg % beginning of section
+ \vskip\intersecskip\startsection\ignorespaces}
+\outer\def\N#1#2#3.{\gdepth=#1\gtitle={#3}\MN{#2}% beginning of starred section
+ \ifon\ifnum#1<\secpagedepth \vfil\eject % force page break if depth is small
+ \else\vfil\penalty-100\vfilneg\vskip\intersecskip\fi\fi
+ \message{*\secno} % progress report
+ \edef\next{\write\cont{\ZZ{#3}{#1}{\secno}% write to contents file
+ {\noexpand\the\pageno}}}\next % \ZZ{title}{depth}{sec}{page}
+ \ifon\startsection{\bf#3.\quad}\ignorespaces}
+\def\MN#1{\par % common code for \M, \N
+ {\xdef\secstar{#1}\let\*=\empty\xdef\secno{#1}}% remove \* from section name
+ \ifx\secno\secstar \onmaybe \else\ontrue \fi
+ \mark{{{\tensy x}\secno}{\the\gdepth}{\the\gtitle}}}
+% each \mark is {section reference or null}{depth plus 1}{group title}
+% \O is Scandinavian letter O-with-slash
+% \P is paragraph sign
+\def\Q{\note{This code is cited in section}} % xref for mention of a section
+\def\Qs{\note{This code is cited in sections}} % xref for mentions of a section
+\let\R=\lnot % logical not
+% \S is section sign
+\def\T#1{\leavevmode % octal, hex or decimal constant
+ \hbox{$\def\?{\kern.2em}%
+ \def\$##1{\egroup_{\,\rm##1}\bgroup}% suffix to constant
+ \def\_{\cdot 10^{\aftergroup}}% power of ten (via dirty trick)
+ \let\~=\oct \let\^=\hex {#1}$}}
+\def\U{\note{This code is used in section}} % xref for use of a section
+\def\Us{\note{This code is used in sections}} % xref for uses of a section
+\let\V=\lor % logical or
+\let\W=\land % logical and
+\def\X#1:#2\X{\ifmmode\gdef\XX{\null$\null}\else\gdef\XX{}\fi % section name
+ \XX$\langle\,${#2\eightrm\kern.5em#1}$\,\rangle$\XX}
+\def\Y{\par\yskip}
+\let\Z=\le
+\let\ZZ=\let % now you can \write the control sequence \ZZ
+\let\*=*
+
+%\def\oct{\hbox{\rm\char'23\kern-.2em\it\aftergroup\?\aftergroup}} % WEB style
+%\def\hex{\hbox{\rm\char"7D\tt\aftergroup}} % WEB style
+\def\oct{\hbox{$^\circ$\kern-.1em\it\aftergroup\?\aftergroup}}% CWEB style
+\def\hex{\hbox{$^{\scriptscriptstyle\#}$\tt\aftergroup}} % CWEB style
+\def\vb#1{\leavevmode\hbox{\kern2pt\vrule\vtop{\vbox{\hrule
+ \hbox{\strut\kern2pt\.{#1}\kern2pt}}
+ \hrule}\vrule\kern2pt}} % verbatim string
+
+\def\onmaybe{\let\ifon=\maybe} \let\maybe=\iftrue
+\newif\ifon \newif\iftitle \newif\ifpagesaved
+
+\def\lheader{\mainfont\the\pageno\eightrm\qquad\grouptitle\hfill\title\qquad
+ \mainfont\topsecno} % top line on left-hand pages
+\def\rheader{\mainfont\topsecno\eightrm\qquad\title\hfill\grouptitle
+ \qquad\mainfont\the\pageno} % top line on right-hand pages
+\def\grouptitle{\let\i=I\let\j=J\uppercase\expandafter{\expandafter
+ \takethree\topmark}}
+\def\topsecno{\expandafter\takeone\topmark}
+\def\takeone#1#2#3{#1}
+\def\taketwo#1#2#3{#2}
+\def\takethree#1#2#3{#3}
+\def\nullsec{\eightrm\kern-2em} % the \kern-2em cancels \qquad in headers
+
+\let\page=\pagebody \raggedbottom
+% \def\page{\box255 }\normalbottom % faster, but loses plain TeX footnotes
+\def\normaloutput#1#2#3{\ifodd\pageno\hoffset=\pageshift\fi
+ \shipout\vbox{
+ \vbox to\fullpageheight{
+ \iftitle\global\titlefalse
+ \else\hbox to\pagewidth{\vbox to10pt{}\ifodd\pageno #3\else#2\fi}\fi
+ \vfill#1}} % parameter #1 is the page itself
+ \global\advance\pageno by1}
+
+\gtitle={\.{CWEB} output} % this running head is reset by starred sections
+\mark{\noexpand\nullsec0{\the\gtitle}}
+\def\title{\expandafter\uppercase\expandafter{\jobname}}
+\def\topofcontents{\centerline{\titlefont\title}\vskip.7in
+ \vfill} % this material will start the table of contents page
+\def\botofcontents{\vfill
+ \centerline{\covernote}} % this material will end the table of contents page
+\def\covernote{}
+\def\contentspagenumber{0} % default page number for table of contents
+\newdimen\pagewidth \pagewidth=6.5in % the width of each page
+\newdimen\pageheight \pageheight=8.7in % the height of each page
+\newdimen\fullpageheight \fullpageheight=9in % page height including headlines
+\newdimen\pageshift \pageshift=0in % shift righthand pages wrt lefthand ones
+\def\magnify#1{\mag=#1\pagewidth=6.5truein\pageheight=8.7truein
+ \fullpageheight=9truein\setpage}
+\def\setpage{\hsize\pagewidth\vsize\pageheight} % use after changing page size
+\def\contentsfile{\jobname.toc} % file that gets table of contents info
+\def\readcontents{\input \contentsfile}
+\def\readindex{\input \jobname.idx}
+\def\readsections{\input \jobname.scn}
+
+\newwrite\cont
+\output{\setbox0=\page % the first page is garbage
+ \openout\cont=\contentsfile
+ \write\cont{\catcode `\noexpand\@=11\relax} % \makeatletter
+ \global\output{\normaloutput\page\lheader\rheader}}
+\setpage
+\vbox to \vsize{} % the first \topmark won't be null
+
+\def\ch{\note{The following sections were changed by the change file:}
+ \let\*=\relax}
+\newbox\sbox % saved box preceding the index
+\newbox\lbox % lefthand column in the index
+\def\inx{\par\vskip6pt plus 1fil % we are beginning the index
+ \def\page{\box255 } \normalbottom
+ \write\cont{} % ensure that the contents file isn't empty
+ \write\cont{\catcode `\noexpand\@=12\relax} % \makeatother
+ \closeout\cont % the contents information has been fully gathered
+ \output{\ifpagesaved\normaloutput{\box\sbox}\lheader\rheader\fi
+ \global\setbox\sbox=\page \global\pagesavedtrue}
+ \pagesavedfalse \eject % eject the page-so-far and predecessors
+ \setbox\sbox\vbox{\unvbox\sbox} % take it out of its box
+ \vsize=\pageheight \advance\vsize by -\ht\sbox % the remaining height
+ \hsize=.5\pagewidth \advance\hsize by -10pt
+ % column width for the index (20pt between cols)
+ \parfillskip 0pt plus .6\hsize % try to avoid almost empty lines
+ \def\lr{L} % this tells whether the left or right column is next
+ \output{\if L\lr\global\setbox\lbox=\page \gdef\lr{R}
+ \else\normaloutput{\vbox to\pageheight{\box\sbox\vss
+ \hbox to\pagewidth{\box\lbox\hfil\page}}}\lheader\rheader
+ \global\vsize\pageheight\gdef\lr{L}\global\pagesavedfalse\fi}
+ \message{Index:}
+ \parskip 0pt plus .5pt
+ \outer\def\I##1, {\par\hangindent2em\noindent##1:\kern1em} % index entry
+ \def\[##1]{$\underline{##1}$} % underlined index item
+ \rm \rightskip0pt plus 2.5em \tolerance 10000 \let\*=\lapstar
+ \hyphenpenalty 10000 \parindent0pt
+ \readindex}
+\def\fin{\par\vfill\eject % this is done when we are ending the index
+ \ifpagesaved\null\vfill\eject\fi % output a null index column
+ \if L\lr\else\null\vfill\eject\fi % finish the current page
+ \parfillskip 0pt plus 1fil
+ \def\grouptitle{NAMES OF THE SECTIONS}
+ \let\topsecno=\nullsec
+ \message{Section names:}
+ \output={\normaloutput\page\lheader\rheader}
+ \setpage
+ \def\note##1##2.{\quad{\eightrm##1~##2.}}
+ \def\Q{\note{Cited in section}} % crossref for mention of a section
+ \def\Qs{\note{Cited in sections}} % crossref for mentions of a section
+ \def\U{\note{Used in section}} % crossref for use of a section
+ \def\Us{\note{Used in sections}} % crossref for uses of a section
+ \def\I{\par\hangindent 2em}\let\*=*
+ \readsections}
+\def\con{\par\vfill\eject % finish the section names
+% \ifodd\pageno\else\titletrue\null\vfill\eject\fi % for duplex printers
+ \rightskip 0pt \hyphenpenalty 50 \tolerance 200
+ \setpage \output={\normaloutput\page\lheader\rheader}
+ \titletrue % prepare to output the table of contents
+ \pageno=\contentspagenumber
+ \def\grouptitle{TABLE OF CONTENTS}
+ \message{Table of contents:}
+ \topofcontents
+ \line{\hfil Section\hbox to3em{\hss Page}}
+ \let\ZZ=\contentsline
+ \readcontents\relax % read the contents info
+ \botofcontents \end} % print the contents page(s) and terminate
+\def\contentsline#1#2#3#4{\ifnum#2=0 \smallbreak\fi
+ \line{\consetup{#2}#1
+ \rm\leaders\hbox to .5em{.\hfil}\hfil\ #3\hbox to3em{\hss#4}}}
+\def\consetup#1{\ifcase#1 \bf % depth -1 (@**)
+ \or % depth 0 (@*)
+ \or \hskip2em % depth 1 (@*1)
+ \or \hskip4em % depth 2 (@*2)
+ \or \hskip6em % depth 3 (@*3)
+ \or \hskip8em % depth 4 (@*4)
+ \or \hskip10em % depth 5 (@*5)
+ \else \hskip12em \fi} % depth 6 or more
+\def\noinx{\let\inx=\end} % no indexes or table of contents
+\def\nosecs{\let\FIN=\fin \def\fin{\let\parfillskip=\end \FIN}}
+ % no index of section names or table of contents
+\def\nocon{\let\con=\end} % no table of contents
+\def\today{\ifcase\month\or
+ January\or February\or March\or April\or May\or June\or
+ July\or August\or September\or October\or November\or December\fi
+ \space\number\day, \number\year}
+\newcount\twodigits
+\def\hours{\twodigits=\time \divide\twodigits by 60 \printtwodigits
+ \multiply\twodigits by-60 \advance\twodigits by\time :\printtwodigits}
+\def\gobbleone1{}
+\def\printtwodigits{\advance\twodigits100
+ \expandafter\gobbleone\number\twodigits
+ \advance\twodigits-100 }
+\def\TeX{{\ifmmode\it\fi
+ \leavevmode\hbox{T\kern-.1667em\lower.424ex\hbox{E}\hskip-.125em X}}}
+\def\,{\relax\ifmmode\mskip\thinmuskip\else\thinspace\fi}
+\def\datethis{\def\startsection{\leftline{\sc\today\ at \hours}\bigskip
+ \let\startsection=\stsec\stsec}}
+ % say `\datethis' in limbo, to get your listing timestamped before section 1
+\def\datecontentspage{%
+ \def\topofcontents{\leftline{\sc\today\ at \hours}\bigskip
+ \centerline{\titlefont\title}\vfill}} % timestamps the contents page
+
+
+% end of cwebmac.tex
diff --git a/web/c_cpp/c2cweb/cweb/cwebmac.tex b/web/c_cpp/c2cweb/cweb/cwebmac.tex
new file mode 100644
index 0000000000..8682fb7372
--- /dev/null
+++ b/web/c_cpp/c2cweb/cweb/cwebmac.tex
@@ -0,0 +1,375 @@
+% This file is part of c2cweb package Version 1.5
+
+% standard macros for CWEB listings (in addition to plain.tex)
+% Version 3.0 --- June 1993
+
+% modified by Werner Lemberg (a7971428@unet.univie.ac.at) 10-Nov-1996
+
+\ifx\documentstyle\undefined\else\endinput\fi % LaTeX will use other macros
+\xdef\fmtversion{\fmtversion+CWEB3.2}
+
+\let\:=\. % preserve a way to get the dot accent
+ % (all other accents will still work as usual)
+
+%\parskip 0pt % no stretch between paragraphs
+%\parindent 1em % for paragraphs and for the first line of C text
+
+\font\ninerm=cmr9
+\let\mc=\ninerm % medium caps
+\def\CEE/{{\mc C\spacefactor1000}}
+\def\UNIX/{{\mc U\kern-.05emNIX\spacefactor1000}}
+\def\TEX/{\TeX}
+\def\CPLUSPLUS/{{\mc C\PP\spacefactor1000}}
+\def\Cee{\CEE/} % for backward compatibility
+\def\9#1{}
+\font\eightrm=cmr8
+\let\sc=\eightrm % small caps (NOT a caps-and-small-caps font)
+\let\mainfont=\tenrm
+\let\cmntfont\tenrm
+%\font\tenss=cmss10 \let\cmntfont\tenss % alternative comment font
+%\font\titlefont=cmr7 scaled\magstep4 % title on the contents page
+\font\titlefont=cmssbx10 scaled\magstep2 % title on the contents page
+\font\ttitlefont=cmtt10 scaled\magstep2 % typewriter type in title
+\font\tentex=cmtex10 % TeX extended character set (used in strings)
+\fontdimen7\tentex=0pt % no double space after sentences
+
+\font\sectionfont=cmssbx10 scaled\magstephalf
+
+\def\${\ifmmode \hbox{\sl \char`\$}
+ \else \hbox{\ifdim \fontdimen1\font > 0pt \sl \fi \char`\$}\fi}
+
+\def\\#1{\leavevmode\hbox{\it#1\/\kern.05em}} % italic type for identifiers
+\def\|#1{\leavevmode\hbox{$#1$}} % one-letter identifiers look better this way
+\def\&#1{\leavevmode\hbox{\bf
+ \def\_{\kern.04em\vbox{\hrule width.3em height .6pt}\kern.08em}%
+ #1\/\kern.05em}} % boldface type for reserved words
+\def\.#1{\leavevmode\hbox{\tentex % typewriter type for strings
+ \let\\=\BS % backslash in a string
+ \let\{=\LB % left brace in a string
+ \let\}=\RB % right brace in a string
+ \let\~=\TL % tilde in a string
+ \let\ =\SP % space in a string
+ \let\_=\UL % underline in a string
+ \let\&=\AM % ampersand in a string
+ \let\^=\CF % circumflex in a string
+ #1\kern.05em}}
+\def\){\discretionary{\hbox{\tentex\BS}}{}{}}
+\def\AT{@} % at sign for control text (not needed in versions >= 2.9)
+\def\ATL{\par\noindent\bgroup\catcode`\_=12 \postATL} % print @l in limbo
+\def\postATL#1 #2 {\bf letter \\{\uppercase{\char"#1}}
+ tangles as \tentex "#2"\egroup\par}
+\def\noATL#1 #2 {}
+\def\noatl{\let\ATL=\noATL} % suppress output from @l
+\def\ATH{\X\kern-.5em:Preprocessor definitions\X}
+\let\PB=\relax % hook for program brackets |...| in TeX part or section name
+
+\chardef\AM=`\& % ampersand character in a string
+\chardef\BS=`\\ % backslash in a string
+\chardef\LB=`\{ % left brace in a string
+\chardef\RB=`\} % right brace in a string
+\def\SP{{\tt\char`\ }} % (visible) space in a string
+\chardef\TL=`\~ % tilde in a string
+\chardef\UL=`\_ % underline character in a string
+\chardef\CF=`\^ % circumflex character in a string
+
+\newbox\PPbox % symbol for ++
+\setbox\PPbox=\hbox{\kern.5pt\raise1pt\hbox{\sevenrm+\kern-1pt+}\kern.5pt}
+\def\PP{\copy\PPbox}
+\newbox\MMbox \setbox\MMbox=\hbox{\kern.5pt\raise1pt\hbox{\sevensy\char0
+ \kern-1pt\char0}\kern.5pt}
+\def\MM{\copy\MMbox}
+\newbox\MGbox % symbol for ->
+\setbox\MGbox=\hbox{\kern-2pt\lower3pt\hbox{\teni\char'176}\kern1pt}
+\def\MG{\copy\MGbox}
+\newbox\NNbox % symbol for ##
+\setbox\NNbox=\hbox{\kern.5pt\raise2pt\hbox{\#}\kern-4pt
+ \lower2pt\hbox{\#}\kern.5pt}
+\def\NN{\copy\NNbox}
+\def\MRL#1{\mathrel{\let\K==#1}}
+%\def\MRL#1{\KK#1}\def\KK#1#2{\buildrel\;#1\over{#2}}
+\let\GG=\gg
+\let\LL=\ll
+\let\NULL=\Lambda
+\mathchardef\AND="2026 % bitwise and; also \& (unary operator)
+\let\OR=\mid % bitwise or
+\let\XOR=\oplus % bitwise exclusive or
+\def\CM{{\sim}} % bitwise complement
+\newbox\MODbox \setbox\MODbox=\hbox{\eightrm\%}
+\def\MOD{\mathbin{\copy\MODbox}}
+\def\DC{\kern.1em{::}\kern.1em} % symbol for ::
+\def\PA{\mathbin{.*}} % symbol for .*
+\def\MGA{\mathbin{\MG*}} % symbol for ->*
+\def\this{\&{this}}
+
+\newbox\bak \setbox\bak=\hbox to -1em{} % backspace one em
+\newbox\bakk\setbox\bakk=\hbox to -2em{} % backspace two ems
+
+\newcount\ind % current indentation in ems
+\def\1{\global\advance\ind by1\hangindent\ind em} % indent one more notch
+\def\2{\global\advance\ind by-1} % indent one less notch
+\def\3#1{\hfil\penalty#10\hfilneg} % optional break within a statement
+\def\4{\copy\bak} % backspace one notch
+\def\5{\hfil\penalty-1\hfilneg\kern2.5em\copy\bakk\ignorespaces}% optional break
+\def\6{\ifmmode\else\par % forced break
+ \hangindent\ind em\noindent\kern\ind em\copy\bakk\ignorespaces\fi}
+%\def\7{\Y\6} % forced break and a little extra space
+\def\7{\Y\penalty-150\6} % forced break and a little extra space
+\def\8{\hskip-\ind em\hskip 2em} % no indentation
+
+\newcount\gdepth % depth of current major group, plus one
+\newcount\secpagedepth
+\secpagedepth=3 % page breaks will occur for depths -1, 0, and 1
+\newtoks\gtitle % title of current major group
+\newskip\intersecskip \intersecskip=12pt minus 3pt % space between sections
+%\let\yskip=\smallskip
+\def\yskip{\vskip 5pt plus 1pt minus 1pt}
+\def\?{\mathrel?}
+\def\note#1#2.{\Y\noindent{\hangindent2em\baselineskip10pt\eightrm#1~#2.\par}}
+\def\lapstar{\rlap{*}}
+%\def\stsec{\rightskip=0pt % get out of C mode (cf. \B)
+% \sfcode`;=1500 \pretolerance 200 \hyphenpenalty 50 \exhyphenpenalty 50
+% \noindent{\let\*=\lapstar\bf\secstar.\quad}}
+\def\stsec{\rightskip=0pt % get out of C mode (cf. \B)
+ \parskip=4pt \parindent=0pt
+ \sfcode`;=1500 \pretolerance 200 \hyphenpenalty 50 \exhyphenpenalty 50
+ \noindent{\let\*=\lapstar\sectionfont\secstar.\quad}}
+\let\startsection=\stsec
+\def\defin#1{\global\advance\ind by 2 \1\&{#1 } } % begin `define' or `format'
+\def\A{\note{See also section}} % xref for doubly defined section name
+\def\As{\note{See also sections}} % xref for multiply defined section name
+%\def\B{\rightskip=0pt plus 100pt minus 10pt % go into C mode
+% \sfcode`;=3000
+% \pretolerance 10000
+% \hyphenpenalty 9999 % so strings can be broken (discretionary \ is inserted)
+% \exhyphenpenalty 10000
+% \global\ind=2 \1\ \unskip}
+\def\B{\rightskip=0pt plus 100pt minus 10pt % go into C mode
+ \parskip=0pt \parindent=1em
+ \sfcode`;=3000
+ \pretolerance 10000
+ \hyphenpenalty 9999 % so strings can be broken (discretionary \ is inserted)
+ \exhyphenpenalty 10000
+ \global\ind=2 \1\ \unskip}
+%\def\C#1{\5\5\quad$/\ast\,${\cmntfont #1}$\,\ast/$}
+\def\C#1{\5\5\hfill$/\ast\,${\cmntfont #1}$\,\ast/$}
+\let\SHC\C % "// short comments" treated like "/* ordinary comments */"
+%\def\C#1{\5\5\quad$\triangleright\,${\cmntfont#1}$\,\triangleleft$}
+%\def\SHC#1{\5\5\quad$\diamond\,${\cmntfont#1}}
+\def\D{\defin{\#define}} % macro definition
+\let\E=\equiv % equivalence sign
+\def\ET{ and~} % conjunction between two section numbers
+\def\ETs{, and~} % conjunction between the last two of several section numbers
+\def\F{\defin{format}} % format definition
+\let\G=\ge % greater than or equal sign
+% \H is long Hungarian umlaut accent
+\let\I=\ne % unequal sign
+\def\J{\.{@\&}} % TANGLE's join operation
+\let\K== % assignment operator
+%\let\K=\leftarrow % "honest" alternative to standard assignment operator
+% \L is Polish letter suppressed-L
+%\outer\def\M#1{\MN{#1}\ifon\vfil\penalty-100\vfilneg % beginning of section
+% \vskip\intersecskip\startsection\ignorespaces}
+\outer\def\M#1{\MN{#1}\ifon\vfil\penalty-100\vfilneg % beginning of section
+ \vskip\intersecskip\startsection\smallskip\noindent\ignorespaces}
+%\outer\def\N#1#2#3.{\gdepth=#1\gtitle={#3}\MN{#2}% beginning of starred section
+% \ifon\ifnum#1<\secpagedepth \vfil\eject % force page break if depth is small
+% \else\vfil\penalty-100\vfilneg\vskip\intersecskip\fi\fi
+% \message{*\secno} % progress report
+% \edef\next{\write\cont{\ZZ{#3}{#1}{\secno}% write to contents file
+% {\noexpand\the\pageno}}}\next % \ZZ{title}{depth}{sec}{page}
+% \ifon\startsection{\bf#3.\quad}\ignorespaces}
+\outer\def\N#1#2#3.{\gdepth=#1\gtitle={#3}\MN{#2}% beginning of starred section
+ \ifon\ifnum#1<\secpagedepth \vfil\eject % force page break if depth is small
+ \else\vfil\penalty-100\vfilneg\vskip\intersecskip\fi\fi
+ \message{*\secno} % progress report
+ \edef\next{\write\cont{\ZZ{#3}{#1}{\secno}% write to contents file
+ {\noexpand\the\pageno}}}\next % \ZZ{title}{depth}{sec}{page}
+ \ifon\startsection{\sectionfont#3.}\bigskip\noindent\ignorespaces}
+\def\MN#1{\par % common code for \M, \N
+ {\xdef\secstar{#1}\let\*=\empty\xdef\secno{#1}}% remove \* from section name
+ \ifx\secno\secstar \onmaybe \else\ontrue \fi
+ \mark{{{\tensy x}\secno}{\the\gdepth}{\the\gtitle}}}
+% each \mark is {section reference or null}{depth plus 1}{group title}
+% \O is Scandinavian letter O-with-slash
+% \P is paragraph sign
+\def\Q{\note{This code is cited in section}} % xref for mention of a section
+\def\Qs{\note{This code is cited in sections}} % xref for mentions of a section
+%\let\R=\lnot % logical not
+\def\R{\mathord ! \,} % logical not
+% \S is section sign
+\def\T#1{\leavevmode % octal, hex or decimal constant
+ \hbox{$\def\?{\kern.2em}%
+ \def\$##1{\egroup_{\,\rm##1}\bgroup}% suffix to constant
+ \def\_{\cdot 10^{\aftergroup}}% power of ten (via dirty trick)
+ \let\~=\oct \let\^=\hex {#1}$}}
+\def\U{\note{This code is used in section}} % xref for use of a section
+\def\Us{\note{This code is used in sections}} % xref for uses of a section
+\let\V=\lor % logical or
+\let\W=\land % logical and
+\def\X#1:#2\X{\ifmmode\gdef\XX{\null$\null}\else\gdef\XX{}\fi % section name
+ \XX$\langle\,${#2\eightrm\kern.5em#1}$\,\rangle$\XX}
+\def\Y{\par\yskip}
+\let\Z=\le
+\let\ZZ=\let % now you can \write the control sequence \ZZ
+\let\*=*
+
+%\def\oct{\hbox{\rm\char'23\kern-.2em\it\aftergroup\?\aftergroup}} % WEB style
+%\def\hex{\hbox{\rm\char"7D\tt\aftergroup}} % WEB style
+\def\oct{\hbox{$^\circ$\kern-.1em\it\aftergroup\?\aftergroup}}% CWEB style
+\def\hex{\hbox{$^{\scriptscriptstyle\#}$\tt\aftergroup}} % CWEB style
+\def\vb#1{\leavevmode\hbox{\kern2pt\vrule\vtop{\vbox{\hrule
+ \hbox{\strut\kern2pt\.{#1}\kern2pt}}
+ \hrule}\vrule\kern2pt}} % verbatim string
+
+\def\onmaybe{\let\ifon=\maybe} \let\maybe=\iftrue
+\newif\ifon \newif\iftitle \newif\ifpagesaved
+
+\def\lheader{\mainfont\the\pageno\eightrm\qquad\grouptitle\hfill\title\qquad
+ \mainfont\topsecno} % top line on left-hand pages
+\def\rheader{\mainfont\topsecno\eightrm\qquad\title\hfill\grouptitle
+ \qquad\mainfont\the\pageno} % top line on right-hand pages
+\def\grouptitle{\let\i=I\let\j=J\uppercase\expandafter{\expandafter
+ \takethree\topmark}}
+\def\topsecno{\expandafter\takeone\topmark}
+\def\takeone#1#2#3{#1}
+\def\taketwo#1#2#3{#2}
+\def\takethree#1#2#3{#3}
+\def\nullsec{\eightrm\kern-2em} % the \kern-2em cancels \qquad in headers
+
+\let\page=\pagebody \raggedbottom
+% \def\page{\box255 }\normalbottom % faster, but loses plain TeX footnotes
+\def\normaloutput#1#2#3{\ifodd\pageno\hoffset=\pageshift\fi
+ \shipout\vbox{
+ \vbox to\fullpageheight{
+ \iftitle\global\titlefalse
+ \else\hbox to\pagewidth{\vbox to10pt{}\ifodd\pageno #3\else#2\fi}\fi
+ \vfill#1}} % parameter #1 is the page itself
+ \global\advance\pageno by1}
+
+\gtitle={\.{CWEB} output} % this running head is reset by starred sections
+\mark{\noexpand\nullsec0{\the\gtitle}}
+\def\title{\expandafter\uppercase\expandafter{\jobname}}
+\def\topofcontents{\centerline{\titlefont\title}\vskip.7in
+ \vfill} % this material will start the table of contents page
+\def\botofcontents{\vfill
+ \centerline{\covernote}} % this material will end the table of contents page
+\def\covernote{}
+\def\contentspagenumber{0} % default page number for table of contents
+\newdimen\pagewidth \pagewidth=6.5in % the width of each page
+\newdimen\pageheight \pageheight=8.7in % the height of each page
+\newdimen\fullpageheight \fullpageheight=9in % page height including headlines
+\newdimen\pageshift \pageshift=0in % shift righthand pages wrt lefthand ones
+\def\magnify#1{\mag=#1\pagewidth=6.5truein\pageheight=8.7truein
+ \fullpageheight=9truein\setpage}
+\def\setpage{\hsize\pagewidth\vsize\pageheight} % use after changing page size
+\def\contentsfile{\jobname.toc} % file that gets table of contents info
+\def\readcontents{\input \contentsfile}
+\def\readindex{\input \jobname.idx}
+\def\readsections{\input \jobname.scn}
+
+\newwrite\cont
+\output{\setbox0=\page % the first page is garbage
+ \openout\cont=\contentsfile
+ \write\cont{\catcode `\noexpand\@=11\relax} % \makeatletter
+ \global\output{\normaloutput\page\lheader\rheader}}
+\setpage
+\vbox to \vsize{} % the first \topmark won't be null
+
+\def\ch{\note{The following sections were changed by the change file:}
+ \let\*=\relax}
+\newbox\sbox % saved box preceding the index
+\newbox\lbox % lefthand column in the index
+\def\inx{\par\vskip6pt plus 1fil % we are beginning the index
+ \def\page{\box255 } \normalbottom
+ \write\cont{} % ensure that the contents file isn't empty
+ \write\cont{\catcode `\noexpand\@=12\relax} % \makeatother
+ \closeout\cont % the contents information has been fully gathered
+ \output{\ifpagesaved\normaloutput{\box\sbox}\lheader\rheader\fi
+ \global\setbox\sbox=\page \global\pagesavedtrue}
+ \pagesavedfalse \eject % eject the page-so-far and predecessors
+ \setbox\sbox\vbox{\unvbox\sbox} % take it out of its box
+ \vsize=\pageheight \advance\vsize by -\ht\sbox % the remaining height
+ \hsize=.5\pagewidth \advance\hsize by -10pt
+ % column width for the index (20pt between cols)
+ \parfillskip 0pt plus .6\hsize % try to avoid almost empty lines
+ \def\lr{L} % this tells whether the left or right column is next
+ \output{\if L\lr\global\setbox\lbox=\page \gdef\lr{R}
+ \else\normaloutput{\vbox to\pageheight{\box\sbox\vss
+ \hbox to\pagewidth{\box\lbox\hfil\page}}}\lheader\rheader
+ \global\vsize\pageheight\gdef\lr{L}\global\pagesavedfalse\fi}
+ \message{Index:}
+ \parskip 0pt plus .5pt
+ \outer\def\I##1, {\par\hangindent2em\noindent##1:\kern1em} % index entry
+ \def\[##1]{$\underline{##1}$} % underlined index item
+ \rm \rightskip0pt plus 2.5em \tolerance 10000 \let\*=\lapstar
+ \hyphenpenalty 10000 \parindent0pt
+ \readindex}
+\def\fin{\par\vfill\eject % this is done when we are ending the index
+ \ifpagesaved\null\vfill\eject\fi % output a null index column
+ \if L\lr\else\null\vfill\eject\fi % finish the current page
+ \parfillskip 0pt plus 1fil
+ \def\grouptitle{NAMES OF THE SECTIONS}
+ \let\topsecno=\nullsec
+ \message{Section names:}
+ \output={\normaloutput\page\lheader\rheader}
+ \setpage
+ \def\note##1##2.{\quad{\eightrm##1~##2.}}
+ \def\Q{\note{Cited in section}} % crossref for mention of a section
+ \def\Qs{\note{Cited in sections}} % crossref for mentions of a section
+ \def\U{\note{Used in section}} % crossref for use of a section
+ \def\Us{\note{Used in sections}} % crossref for uses of a section
+ \def\I{\par\hangindent 2em}\let\*=*
+ \readsections}
+\def\con{\par\vfill\eject % finish the section names
+% \ifodd\pageno\else\titletrue\null\vfill\eject\fi % for duplex printers
+ \rightskip 0pt \hyphenpenalty 50 \tolerance 200
+ \setpage \output={\normaloutput\page\lheader\rheader}
+ \titletrue % prepare to output the table of contents
+ \pageno=\contentspagenumber
+ \def\grouptitle{TABLE OF CONTENTS}
+ \message{Table of contents:}
+ \topofcontents
+ \line{\hfil Section\hbox to3em{\hss Page}}
+ \let\ZZ=\contentsline
+ \readcontents\relax % read the contents info
+ \botofcontents \end} % print the contents page(s) and terminate
+\def\contentsline#1#2#3#4{\ifnum#2=0 \smallbreak\fi
+ \line{\consetup{#2}#1
+ \rm\leaders\hbox to .5em{.\hfil}\hfil\ #3\hbox to3em{\hss#4}}}
+\def\consetup#1{\ifcase#1 \bf % depth -1 (@**)
+ \or % depth 0 (@*)
+ \or \hskip2em % depth 1 (@*1)
+ \or \hskip4em % depth 2 (@*2)
+ \or \hskip6em % depth 3 (@*3)
+ \or \hskip8em % depth 4 (@*4)
+ \or \hskip10em % depth 5 (@*5)
+ \else \hskip12em \fi} % depth 6 or more
+\def\noinx{\let\inx=\end} % no indexes or table of contents
+\def\nosecs{\let\FIN=\fin \def\fin{\let\parfillskip=\end \FIN}}
+ % no index of section names or table of contents
+\def\nocon{\let\con=\end} % no table of contents
+\def\today{\ifcase\month\or
+ January\or February\or March\or April\or May\or June\or
+ July\or August\or September\or October\or November\or December\fi
+ \space\number\day, \number\year}
+\newcount\twodigits
+\def\hours{\twodigits=\time \divide\twodigits by 60 \printtwodigits
+ \multiply\twodigits by-60 \advance\twodigits by\time :\printtwodigits}
+\def\gobbleone1{}
+\def\printtwodigits{\advance\twodigits100
+ \expandafter\gobbleone\number\twodigits
+ \advance\twodigits-100 }
+\def\TeX{{\ifmmode\it\fi
+ \leavevmode\hbox{T\kern-.1667em\lower.424ex\hbox{E}\hskip-.125em X}}}
+\def\,{\relax\ifmmode\mskip\thinmuskip\else\thinspace\fi}
+\def\datethis{\def\startsection{\leftline{\sc\today\ at \hours}\bigskip
+ \let\startsection=\stsec\stsec}}
+ % say `\datethis' in limbo, to get your listing timestamped before section 1
+\def\datecontentspage{%
+ \def\topofcontents{\leftline{\sc\today\ at \hours}\bigskip
+ \centerline{\titlefont\title}\vfill}} % timestamps the contents page
+
+\endinput
+
+
+% end of cwebmac.tex
diff --git a/web/c_cpp/c2cweb/cweb/cwebmaca.tex b/web/c_cpp/c2cweb/cweb/cwebmaca.tex
new file mode 100644
index 0000000000..307063f863
--- /dev/null
+++ b/web/c_cpp/c2cweb/cweb/cwebmaca.tex
@@ -0,0 +1,381 @@
+% This file is part of c2cweb package Version 1.5
+
+% standard macros for CWEB listings (in addition to plain.tex)
+% Version 3.0 --- June 1993
+
+% modified by Werner Lemberg (a7971428@unet.univie.ac.at) 10-Nov-1996
+% to use with CWEAVE +a
+
+\ifx\documentstyle\undefined\else\endinput\fi % LaTeX will use other macros
+\xdef\fmtversion{\fmtversion+CWEB3.2}
+
+\let\:=\. % preserve a way to get the dot accent
+ % (all other accents will still work as usual)
+
+%\parskip 0pt % no stretch between paragraphs
+%\parindent 1em % for paragraphs and for the first line of C text
+
+\font\ninerm=cmr9
+\let\mc=\ninerm % medium caps
+\def\CEE/{{\mc C\spacefactor1000}}
+\def\UNIX/{{\mc U\kern-.05emNIX\spacefactor1000}}
+\def\TEX/{\TeX}
+\def\CPLUSPLUS/{{\mc C\PP\spacefactor1000}}
+\def\Cee{\CEE/} % for backward compatibility
+\def\9#1{}
+\font\eightrm=cmr8
+\let\sc=\eightrm % small caps (NOT a caps-and-small-caps font)
+\let\mainfont=\tenrm
+\let\cmntfont\tenrm
+%\font\tenss=cmss10 \let\cmntfont\tenss % alternative comment font
+%\font\titlefont=cmr7 scaled\magstep4 % title on the contents page
+\font\titlefont=cmssbx10 scaled\magstep2 % title on the contents page
+\font\ttitlefont=cmtt10 scaled\magstep2 % typewriter type in title
+\font\tentex=cmtex10 % TeX extended character set (used in strings)
+\fontdimen7\tentex=0pt % no double space after sentences
+
+\font\sectionfont=cmssbx10 scaled\magstephalf
+
+\def\${\ifmmode \hbox{\sl \char`\$}
+ \else \hbox{\ifdim \fontdimen1\font > 0pt \sl \fi \char`\$}\fi}
+
+\def\\#1{\leavevmode\hbox{\it#1\/\kern.05em}} % italic type for identifiers
+\def\|#1{\leavevmode\hbox{$#1$}} % one-letter identifiers look better this way
+\def\&#1{\leavevmode\hbox{\bf
+ \def\_{\kern.04em\vbox{\hrule width.3em height .6pt}\kern.08em}%
+ #1\/\kern.05em}} % boldface type for reserved words
+\def\.#1{\leavevmode\hbox{\tentex % typewriter type for strings
+ \let\\=\BS % backslash in a string
+ \let\{=\LB % left brace in a string
+ \let\}=\RB % right brace in a string
+ \let\~=\TL % tilde in a string
+ \let\ =\SP % space in a string
+ \let\_=\UL % underline in a string
+ \let\&=\AM % ampersand in a string
+ \let\^=\CF % circumflex in a string
+ #1\kern.05em}}
+\def\){\discretionary{\hbox{\tentex\BS}}{}{}}
+\def\AT{@} % at sign for control text (not needed in versions >= 2.9)
+\def\ATL{\par\noindent\bgroup\catcode`\_=12 \postATL} % print @l in limbo
+\def\postATL#1 #2 {\bf letter \\{\uppercase{\char"#1}}
+ tangles as \tentex "#2"\egroup\par}
+\def\noATL#1 #2 {}
+\def\noatl{\let\ATL=\noATL} % suppress output from @l
+\def\ATH{\X\kern-.5em:Preprocessor definitions\X}
+%\let\PB=\relax % hook for program brackets |...| in TeX part or section name
+\def\PB#1{{\def\LBR{\LB}\def\RBR{\RB}#1}}
+
+\chardef\AM=`\& % ampersand character in a string
+\chardef\BS=`\\ % backslash in a string
+\chardef\LB=`\{ % left brace in a string
+\chardef\RB=`\} % right brace in a string
+\def\SP{{\tt\char`\ }} % (visible) space in a string
+\chardef\TL=`\~ % tilde in a string
+\chardef\UL=`\_ % underline character in a string
+\chardef\CF=`\^ % circumflex character in a string
+
+\newbox\PPbox % symbol for ++
+\setbox\PPbox=\hbox{\kern.5pt\raise1pt\hbox{\sevenrm+\kern-1pt+}\kern.5pt}
+\def\PP{\copy\PPbox}
+\newbox\MMbox \setbox\MMbox=\hbox{\kern.5pt\raise1pt\hbox{\sevensy\char0
+ \kern-1pt\char0}\kern.5pt}
+\def\MM{\copy\MMbox}
+\newbox\MGbox % symbol for ->
+\setbox\MGbox=\hbox{\kern-2pt\lower3pt\hbox{\teni\char'176}\kern1pt}
+\def\MG{\copy\MGbox}
+\newbox\NNbox % symbol for ##
+\setbox\NNbox=\hbox{\kern.5pt\raise2pt\hbox{\#}\kern-4pt
+ \lower2pt\hbox{\#}\kern.5pt}
+\def\NN{\copy\NNbox}
+\def\MRL#1{\mathrel{\let\K==#1}}
+%\def\MRL#1{\KK#1}\def\KK#1#2{\buildrel\;#1\over{#2}}
+\let\GG=\gg
+\let\LL=\ll
+\let\NULL=\Lambda
+\mathchardef\AND="2026 % bitwise and; also \& (unary operator)
+\let\OR=\mid % bitwise or
+\let\XOR=\oplus % bitwise exclusive or
+\def\CM{{\sim}} % bitwise complement
+\newbox\MODbox \setbox\MODbox=\hbox{\eightrm\%}
+\def\MOD{\mathbin{\copy\MODbox}}
+\def\DC{\kern.1em{::}\kern.1em} % symbol for ::
+\def\PA{\mathbin{.*}} % symbol for .*
+\def\MGA{\mathbin{\MG*}} % symbol for ->*
+\def\this{\&{this}}
+
+\newbox\bak \setbox\bak=\hbox to -1em{} % backspace one em
+\newbox\bakk\setbox\bakk=\hbox to -2em{} % backspace two ems
+
+\newbox\LBRbox \setbox\LBRbox=\hbox to 1em{\hss$\{$}
+\newbox\RBRbox \setbox\RBRbox=\hbox to 1em{\hss$\}$}
+\def\LBR{\copy\LBRbox}
+\def\RBR{\copy\RBRbox}
+
+\newcount\ind % current indentation in ems
+\def\1{\global\advance\ind by1\hangindent\ind em} % indent one more notch
+\def\2{\global\advance\ind by-1} % indent one less notch
+\def\3#1{\hfil\penalty#10\hfilneg} % optional break within a statement
+\def\4{\copy\bak} % backspace one notch
+\def\5{\hfil\penalty-1\hfilneg\kern2.5em\copy\bakk\ignorespaces}% optional break
+\def\6{\ifmmode\else\par % forced break
+ \hangindent\ind em\noindent\kern\ind em\copy\bakk\ignorespaces\fi}
+%\def\7{\Y\6} % forced break and a little extra space
+\def\7{\Y\penalty-150\6} % forced break and a little extra space
+\def\8{\hskip-\ind em\hskip 2em} % no indentation
+
+\newcount\gdepth % depth of current major group, plus one
+\newcount\secpagedepth
+\secpagedepth=3 % page breaks will occur for depths -1, 0, and 1
+\newtoks\gtitle % title of current major group
+\newskip\intersecskip \intersecskip=12pt minus 3pt % space between sections
+%\let\yskip=\smallskip
+\def\yskip{\vskip 5pt plus 1pt minus 1pt}
+\def\?{\mathrel?}
+\def\note#1#2.{\Y\noindent{\hangindent2em\baselineskip10pt\eightrm#1~#2.\par}}
+\def\lapstar{\rlap{*}}
+%\def\stsec{\rightskip=0pt % get out of C mode (cf. \B)
+% \sfcode`;=1500 \pretolerance 200 \hyphenpenalty 50 \exhyphenpenalty 50
+% \noindent{\let\*=\lapstar\bf\secstar.\quad}}
+\def\stsec{\rightskip=0pt % get out of C mode (cf. \B)
+ \parskip=4pt \parindent=0pt
+ \sfcode`;=1500 \pretolerance 200 \hyphenpenalty 50 \exhyphenpenalty 50
+ \noindent{\let\*=\lapstar\sectionfont\secstar.\quad}}
+\let\startsection=\stsec
+\def\defin#1{\global\advance\ind by 2 \1\&{#1 } } % begin `define' or `format'
+\def\A{\note{See also section}} % xref for doubly defined section name
+\def\As{\note{See also sections}} % xref for multiply defined section name
+%\def\B{\rightskip=0pt plus 100pt minus 10pt % go into C mode
+% \sfcode`;=3000
+% \pretolerance 10000
+% \hyphenpenalty 9999 % so strings can be broken (discretionary \ is inserted)
+% \exhyphenpenalty 10000
+% \global\ind=2 \1\ \unskip}
+\def\B{\rightskip=0pt plus 100pt minus 10pt % go into C mode
+ \parskip=0pt \parindent=1em
+ \sfcode`;=3000
+ \pretolerance 10000
+ \hyphenpenalty 9999 % so strings can be broken (discretionary \ is inserted)
+ \exhyphenpenalty 10000
+ \global\ind=2 \1\ \unskip}
+%\def\C#1{\5\5\quad$/\ast\,${\cmntfont #1}$\,\ast/$}
+\def\C#1{\5\5\hfill$/\ast\,${\cmntfont #1}$\,\ast/$}
+\let\SHC\C % "// short comments" treated like "/* ordinary comments */"
+%\def\C#1{\5\5\quad$\triangleright\,${\cmntfont#1}$\,\triangleleft$}
+%\def\SHC#1{\5\5\quad$\diamond\,${\cmntfont#1}}
+\def\D{\defin{\#define}} % macro definition
+\let\E=\equiv % equivalence sign
+\def\ET{ and~} % conjunction between two section numbers
+\def\ETs{, and~} % conjunction between the last two of several section numbers
+\def\F{\defin{format}} % format definition
+\let\G=\ge % greater than or equal sign
+% \H is long Hungarian umlaut accent
+\let\I=\ne % unequal sign
+\def\J{\.{@\&}} % TANGLE's join operation
+\let\K== % assignment operator
+%\let\K=\leftarrow % "honest" alternative to standard assignment operator
+% \L is Polish letter suppressed-L
+%\outer\def\M#1{\MN{#1}\ifon\vfil\penalty-100\vfilneg % beginning of section
+% \vskip\intersecskip\startsection\ignorespaces}
+\outer\def\M#1{\MN{#1}\ifon\vfil\penalty-100\vfilneg % beginning of section
+ \vskip\intersecskip\startsection\smallskip\noindent\ignorespaces}
+%\outer\def\N#1#2#3.{\gdepth=#1\gtitle={#3}\MN{#2}% beginning of starred section
+% \ifon\ifnum#1<\secpagedepth \vfil\eject % force page break if depth is small
+% \else\vfil\penalty-100\vfilneg\vskip\intersecskip\fi\fi
+% \message{*\secno} % progress report
+% \edef\next{\write\cont{\ZZ{#3}{#1}{\secno}% write to contents file
+% {\noexpand\the\pageno}}}\next % \ZZ{title}{depth}{sec}{page}
+% \ifon\startsection{\bf#3.\quad}\ignorespaces}
+\outer\def\N#1#2#3.{\gdepth=#1\gtitle={#3}\MN{#2}% beginning of starred section
+ \ifon\ifnum#1<\secpagedepth \vfil\eject % force page break if depth is small
+ \else\vfil\penalty-100\vfilneg\vskip\intersecskip\fi\fi
+ \message{*\secno} % progress report
+ \edef\next{\write\cont{\ZZ{#3}{#1}{\secno}% write to contents file
+ {\noexpand\the\pageno}}}\next % \ZZ{title}{depth}{sec}{page}
+ \ifon\startsection{\sectionfont#3.}\bigskip\noindent\ignorespaces}
+\def\MN#1{\par % common code for \M, \N
+ {\xdef\secstar{#1}\let\*=\empty\xdef\secno{#1}}% remove \* from section name
+ \ifx\secno\secstar \onmaybe \else\ontrue \fi
+ \mark{{{\tensy x}\secno}{\the\gdepth}{\the\gtitle}}}
+% each \mark is {section reference or null}{depth plus 1}{group title}
+% \O is Scandinavian letter O-with-slash
+% \P is paragraph sign
+\def\Q{\note{This code is cited in section}} % xref for mention of a section
+\def\Qs{\note{This code is cited in sections}} % xref for mentions of a section
+%\let\R=\lnot % logical not
+\def\R{\mathord ! \,} % logical not
+% \S is section sign
+\def\T#1{\leavevmode % octal, hex or decimal constant
+ \hbox{$\def\?{\kern.2em}%
+ \def\$##1{\egroup_{\,\rm##1}\bgroup}% suffix to constant
+ \def\_{\cdot 10^{\aftergroup}}% power of ten (via dirty trick)
+ \let\~=\oct \let\^=\hex {#1}$}}
+\def\U{\note{This code is used in section}} % xref for use of a section
+\def\Us{\note{This code is used in sections}} % xref for uses of a section
+\let\V=\lor % logical or
+\let\W=\land % logical and
+\def\X#1:#2\X{\ifmmode\gdef\XX{\null$\null}\else\gdef\XX{}\fi % section name
+ \XX$\langle\,${#2\eightrm\kern.5em#1}$\,\rangle$\XX}
+\def\Y{\par\yskip}
+\let\Z=\le
+\let\ZZ=\let % now you can \write the control sequence \ZZ
+\let\*=*
+
+%\def\oct{\hbox{\rm\char'23\kern-.2em\it\aftergroup\?\aftergroup}} % WEB style
+%\def\hex{\hbox{\rm\char"7D\tt\aftergroup}} % WEB style
+\def\oct{\hbox{$^\circ$\kern-.1em\it\aftergroup\?\aftergroup}}% CWEB style
+\def\hex{\hbox{$^{\scriptscriptstyle\#}$\tt\aftergroup}} % CWEB style
+\def\vb#1{\leavevmode\hbox{\kern2pt\vrule\vtop{\vbox{\hrule
+ \hbox{\strut\kern2pt\.{#1}\kern2pt}}
+ \hrule}\vrule\kern2pt}} % verbatim string
+
+\def\onmaybe{\let\ifon=\maybe} \let\maybe=\iftrue
+\newif\ifon \newif\iftitle \newif\ifpagesaved
+
+\def\lheader{\mainfont\the\pageno\eightrm\qquad\grouptitle\hfill\title\qquad
+ \mainfont\topsecno} % top line on left-hand pages
+\def\rheader{\mainfont\topsecno\eightrm\qquad\title\hfill\grouptitle
+ \qquad\mainfont\the\pageno} % top line on right-hand pages
+\def\grouptitle{\let\i=I\let\j=J\uppercase\expandafter{\expandafter
+ \takethree\topmark}}
+\def\topsecno{\expandafter\takeone\topmark}
+\def\takeone#1#2#3{#1}
+\def\taketwo#1#2#3{#2}
+\def\takethree#1#2#3{#3}
+\def\nullsec{\eightrm\kern-2em} % the \kern-2em cancels \qquad in headers
+
+\let\page=\pagebody \raggedbottom
+% \def\page{\box255 }\normalbottom % faster, but loses plain TeX footnotes
+\def\normaloutput#1#2#3{\ifodd\pageno\hoffset=\pageshift\fi
+ \shipout\vbox{
+ \vbox to\fullpageheight{
+ \iftitle\global\titlefalse
+ \else\hbox to\pagewidth{\vbox to10pt{}\ifodd\pageno #3\else#2\fi}\fi
+ \vfill#1}} % parameter #1 is the page itself
+ \global\advance\pageno by1}
+
+\gtitle={\.{CWEB} output} % this running head is reset by starred sections
+\mark{\noexpand\nullsec0{\the\gtitle}}
+\def\title{\expandafter\uppercase\expandafter{\jobname}}
+\def\topofcontents{\centerline{\titlefont\title}\vskip.7in
+ \vfill} % this material will start the table of contents page
+\def\botofcontents{\vfill
+ \centerline{\covernote}} % this material will end the table of contents page
+\def\covernote{}
+\def\contentspagenumber{0} % default page number for table of contents
+\newdimen\pagewidth \pagewidth=6.5in % the width of each page
+\newdimen\pageheight \pageheight=8.7in % the height of each page
+\newdimen\fullpageheight \fullpageheight=9in % page height including headlines
+\newdimen\pageshift \pageshift=0in % shift righthand pages wrt lefthand ones
+\def\magnify#1{\mag=#1\pagewidth=6.5truein\pageheight=8.7truein
+ \fullpageheight=9truein\setpage}
+\def\setpage{\hsize\pagewidth\vsize\pageheight} % use after changing page size
+\def\contentsfile{\jobname.toc} % file that gets table of contents info
+\def\readcontents{\input \contentsfile}
+\def\readindex{\input \jobname.idx}
+\def\readsections{\input \jobname.scn}
+
+\newwrite\cont
+\output{\setbox0=\page % the first page is garbage
+ \openout\cont=\contentsfile
+ \write\cont{\catcode `\noexpand\@=11\relax} % \makeatletter
+ \global\output{\normaloutput\page\lheader\rheader}}
+\setpage
+\vbox to \vsize{} % the first \topmark won't be null
+
+\def\ch{\note{The following sections were changed by the change file:}
+ \let\*=\relax}
+\newbox\sbox % saved box preceding the index
+\newbox\lbox % lefthand column in the index
+\def\inx{\par\vskip6pt plus 1fil % we are beginning the index
+ \def\page{\box255 } \normalbottom
+ \write\cont{} % ensure that the contents file isn't empty
+ \write\cont{\catcode `\noexpand\@=12\relax} % \makeatother
+ \closeout\cont % the contents information has been fully gathered
+ \output{\ifpagesaved\normaloutput{\box\sbox}\lheader\rheader\fi
+ \global\setbox\sbox=\page \global\pagesavedtrue}
+ \pagesavedfalse \eject % eject the page-so-far and predecessors
+ \setbox\sbox\vbox{\unvbox\sbox} % take it out of its box
+ \vsize=\pageheight \advance\vsize by -\ht\sbox % the remaining height
+ \hsize=.5\pagewidth \advance\hsize by -10pt
+ % column width for the index (20pt between cols)
+ \parfillskip 0pt plus .6\hsize % try to avoid almost empty lines
+ \def\lr{L} % this tells whether the left or right column is next
+ \output{\if L\lr\global\setbox\lbox=\page \gdef\lr{R}
+ \else\normaloutput{\vbox to\pageheight{\box\sbox\vss
+ \hbox to\pagewidth{\box\lbox\hfil\page}}}\lheader\rheader
+ \global\vsize\pageheight\gdef\lr{L}\global\pagesavedfalse\fi}
+ \message{Index:}
+ \parskip 0pt plus .5pt
+ \outer\def\I##1, {\par\hangindent2em\noindent##1:\kern1em} % index entry
+ \def\[##1]{$\underline{##1}$} % underlined index item
+ \rm \rightskip0pt plus 2.5em \tolerance 10000 \let\*=\lapstar
+ \hyphenpenalty 10000 \parindent0pt
+ \readindex}
+\def\fin{\par\vfill\eject % this is done when we are ending the index
+ \ifpagesaved\null\vfill\eject\fi % output a null index column
+ \if L\lr\else\null\vfill\eject\fi % finish the current page
+ \parfillskip 0pt plus 1fil
+ \def\grouptitle{NAMES OF THE SECTIONS}
+ \let\topsecno=\nullsec
+ \message{Section names:}
+ \output={\normaloutput\page\lheader\rheader}
+ \setpage
+ \def\note##1##2.{\quad{\eightrm##1~##2.}}
+ \def\Q{\note{Cited in section}} % crossref for mention of a section
+ \def\Qs{\note{Cited in sections}} % crossref for mentions of a section
+ \def\U{\note{Used in section}} % crossref for use of a section
+ \def\Us{\note{Used in sections}} % crossref for uses of a section
+ \def\I{\par\hangindent 2em}\let\*=*
+ \readsections}
+\def\con{\par\vfill\eject % finish the section names
+% \ifodd\pageno\else\titletrue\null\vfill\eject\fi % for duplex printers
+ \rightskip 0pt \hyphenpenalty 50 \tolerance 200
+ \setpage \output={\normaloutput\page\lheader\rheader}
+ \titletrue % prepare to output the table of contents
+ \pageno=\contentspagenumber
+ \def\grouptitle{TABLE OF CONTENTS}
+ \message{Table of contents:}
+ \topofcontents
+ \line{\hfil Section\hbox to3em{\hss Page}}
+ \let\ZZ=\contentsline
+ \readcontents\relax % read the contents info
+ \botofcontents \end} % print the contents page(s) and terminate
+\def\contentsline#1#2#3#4{\ifnum#2=0 \smallbreak\fi
+ \line{\consetup{#2}#1
+ \rm\leaders\hbox to .5em{.\hfil}\hfil\ #3\hbox to3em{\hss#4}}}
+\def\consetup#1{\ifcase#1 \bf % depth -1 (@**)
+ \or % depth 0 (@*)
+ \or \hskip2em % depth 1 (@*1)
+ \or \hskip4em % depth 2 (@*2)
+ \or \hskip6em % depth 3 (@*3)
+ \or \hskip8em % depth 4 (@*4)
+ \or \hskip10em % depth 5 (@*5)
+ \else \hskip12em \fi} % depth 6 or more
+\def\noinx{\let\inx=\end} % no indexes or table of contents
+\def\nosecs{\let\FIN=\fin \def\fin{\let\parfillskip=\end \FIN}}
+ % no index of section names or table of contents
+\def\nocon{\let\con=\end} % no table of contents
+\def\today{\ifcase\month\or
+ January\or February\or March\or April\or May\or June\or
+ July\or August\or September\or October\or November\or December\fi
+ \space\number\day, \number\year}
+\newcount\twodigits
+\def\hours{\twodigits=\time \divide\twodigits by 60 \printtwodigits
+ \multiply\twodigits by-60 \advance\twodigits by\time :\printtwodigits}
+\def\gobbleone1{}
+\def\printtwodigits{\advance\twodigits100
+ \expandafter\gobbleone\number\twodigits
+ \advance\twodigits-100 }
+\def\TeX{{\ifmmode\it\fi
+ \leavevmode\hbox{T\kern-.1667em\lower.424ex\hbox{E}\hskip-.125em X}}}
+\def\,{\relax\ifmmode\mskip\thinmuskip\else\thinspace\fi}
+\def\datethis{\def\startsection{\leftline{\sc\today\ at \hours}\bigskip
+ \let\startsection=\stsec\stsec}}
+ % say `\datethis' in limbo, to get your listing timestamped before section 1
+\def\datecontentspage{%
+ \def\topofcontents{\leftline{\sc\today\ at \hours}\bigskip
+ \centerline{\titlefont\title}\vfill}} % timestamps the contents page
+
+\endinput
+
+% end of cwebmaca.tex
diff --git a/web/c_cpp/c2cweb/cweb/prod-alt.w b/web/c_cpp/c2cweb/cweb/prod-alt.w
new file mode 100644
index 0000000000..f7849d830a
--- /dev/null
+++ b/web/c_cpp/c2cweb/cweb/prod-alt.w
@@ -0,0 +1,303 @@
+% This file is part of CWEB.
+% This program by Silvio Levy and Donald E. Knuth
+% is based on a program by Knuth.
+% It is distributed WITHOUT ANY WARRANTY, express or implied.
+% Version 3.0 --- June 1993
+
+% this file is part of the c2cweb package Version 1.5
+% modified by Werner Lemberg (a7971428@@unet.univie.ac.at) 10-Nov-1996
+
+@
+\def\v{\char'174}
+\mathchardef\RA="3221 % right arrow
+\mathchardef\BA="3224 % double arrow
+Here is a table of all the productions if you use the \.{a} switch.
+Each production that combines two or more consecutive scraps implicitly
+inserts a {\tt \$} where necessary, that is, between scraps whose abutting
+boundaries have different |mathness|. In this way we never get double
+{\tt\$\$}.
+
+A translation is provided when the resulting scrap is not merely a
+juxtaposition of the scraps it comes from. An asterisk$^*$ next to a scrap
+means that its first identifier gets an underlined entry in the index,
+via the function |make_underlined|. Two asterisks$^{**}$ means that both
+|make_underlined| and |make_reserved| are called; that is, the
+identifier's ilk becomes |raw_int|. A dagger \dag\ before the
+production number refers to the notes at the end of this section,
+which deal with various exceptional cases.
+
+We use \\{in}, \\{out}, \\{back} and
+\\{bsp} as shorthands for |indent|, |outdent|, |backup| and
+|break_space|, respectively.
+
+\begingroup \lineskip=4pt
+\def\alt #1 #2
+{$\displaystyle\Bigl\{\!\matrix{\strut\hbox{#1}\cr
+ \strut\hbox{#2}\cr}\!\Bigr\}$ }
+\def\altt #1 #2 #3
+{$\displaystyle\Biggl\{\!\matrix{\strut\hbox{#1}\cr\hbox{#2}\cr
+ \strut\hbox{#3}\cr}\!\Biggr\}$ }
+\def\altq #1 #2 #3 #4
+{$\displaystyle\left\{\!\matrix{\strut\hbox{#1}\cr\hbox{#2}\cr
+ \hbox{#3}\cr\strut\hbox{#4}\cr}\!\right\}$ }
+\def\malt #1 #2
+{$\displaystyle\matrix{\strut\hbox{#1}\hfill\cr\strut\hbox{#2}\hfill\cr}$}
+\def\maltt #1 #2 #3
+{$\displaystyle\matrix{\strut\hbox{#1}\hfill\cr\hbox{#2}\hfill\cr
+ \strut\hbox{#3}\hfill\cr}$}
+\yskip\newcount\prodno\prodno=0
+\newdimen\midcol \midcol=2.5in
+\def\theprodno{\number\prodno \global\advance\prodno by1\enspace}
+\def\+#1&#2&#3&#4\cr{\def\next{#1}%
+ \line{\hbox to 2em{\hss
+ \ifx\next\empty\theprodno\else\next\fi}\strut
+ \ignorespaces#2\hfil\hbox to\midcol{$\RA$
+ \ignorespaces#3\hfil}\quad \hbox to1.45in{\ignorespaces#4\hfil}}}
+\+\relax & LHS & RHS \hfill Translation & Example\cr
+\yskip
+\+& \altt\\{any} {\\{any} \\{any}} {\\{any} \\{any} \\{any}}
+|insert| & \altt\\{any} {\\{any} \\{any}} {\\{any} \\{any} \\{any}}
+& stmt; \ /$\ast\,$comment$\,*$/\cr
+\+& |exp| \altt|lbrace| |int_like| |decl|
+ & |fn_decl| \altt|lbrace| |int_like| |decl|
+ \hfill $F=E^*\,|in|\,|in|$ & \malt {\\{main}()$\{$}
+ {\\{main}$(\\{ac},\\{av})$ \&{int} \\{ac};} \cr
+\+& |exp| |unop| & |exp| & |x++|\cr
+\+& |exp| \alt |binop| |unorbinop| |exp| & |exp| & \malt {|x/y|} {|x+y|} \cr
+\+& |exp| |comma| |exp| & |exp| \hfill $EC\,|opt|9\,E$& |f(x,y)|\cr
+\+& |exp| \alt |exp| |cast| & |exp| & |time()|\cr
+\+& |exp| |semi| & |stmt| & |x=0;|\cr
+\+& |exp| |colon| & |label| \hfill $E^*C$ & |found:|\cr
+\+& |exp| |base| |int_like| |comma| & |base| \hfill $B\.\ IC$\,|opt|9
+ & \&D : \&C,\cr
+\+& |exp| |base| |int_like| |lbrace| & |exp| |lbrace| \hfill
+ $E=E\.\ B\.\ I$ & \&D : \&C $\{$\cr
+\+& |exp| |rbrace| & |stmt| |rbrace| & end of \&{enum} list\cr
+\+& |lpar| \alt |exp| |unorbinop| |rpar| & |exp| & \malt{|(x)|} {|(*)|} \cr
+\+& |lpar| |rpar| & |exp| \hfill $L\.{\\,}R$ & functions, declarations\cr
+\+& |lpar| \alt |decl_head| |int_like| |rpar| & |cast| & |(char*)|\cr
+\+& |lpar| \altt |decl_head| |int_like| |exp| |comma| & |lpar| \hfill
+ L\,\altt $D$ $I$ $E$ C\,|opt|9 & |(int,|\cr
+\+& |lpar| \alt |stmt| |decl| & |lpar| \hfill \alt {$LS\.\ $} {$LD\.\ $} &
+ \alt {|(k=5;|} {|(int k=5;|} \cr
+\+& |question| |exp| |colon| & |binop| & |?x:|\cr
+\+& |unop| \alt |exp| |int_like| & \alt |exp| |int_like| &
+ \malt |!x| |~|\&C \cr
+\+& |unorbinop| \alt|exp| |int_like| & \alt|exp| |int_like| \hfill
+ $\.\{U\.\}E$ & |*x|\cr
+\+& |unorbinop| |binop| & |binop| \hfill $|math_rel|\,U\.\{B\.\}\.\}$ & |*=|\cr
+\+& |binop| |binop| & |binop| \hfill
+ $|math_rel|\,\.\{B_1\.\}\.\{B_2\.\}\.\}$ & |>>=|\cr
+\+& |cast| |exp| & |exp| \hfill $C\.\ E$ & |(double)x|\cr
+\+& |cast| |semi| & |exp| |semi| & |(int);|\cr
+\+& |sizeof_like| |cast| & |exp| & |sizeof (double)|\cr
+\+& |sizeof_like| |exp| & |exp| \hfill $S\.\ E$ & |sizeof x|\cr
+\+& |int_like| \alt|int_like| |struct_like| &
+ \alt|int_like| |struct_like| \hfill $I\.\ $\alt $I$ $S$
+ \unskip& |extern char|\cr
+\+& |int_like| |exp| \alt|raw_int| |struct_like| &
+ |int_like| \alt|int_like| |struct_like| & |extern "Ada" int|\cr
+\+& |int_like| \altt|exp| |unorbinop| |semi| & |decl_head|
+ \altt|exp| |unorbinop| |semi| \hfill
+ $D=I$\altt{\.\ } {\.\ } {} \unskip & |int x|\cr
+\+& |int_like| |colon| & |decl_head| |colon| \hfill $D=I\.\ $ & |unsigned:|\cr
+\+& |int_like| |prelangle| & |int_like| |langle| & \&C$\langle$\cr
+\+& |int_like| |colcol| \alt |exp| |int_like| & \alt |exp| |int_like| &
+ \malt {\&C\DC$x$} {\&C\DC\&B} \cr
+\+& |int_like| |cast| |lbrace| & |fn_decl| |lbrace| \hfill $IC\,|in|\,|in|$&
+ \&C$\langle\&{void}\ast\rangle\{$\cr
+\+& |int_like| |cast| & |int_like| & \&C$\langle\&{class}\ \&T\rangle$\cr
+\+& |decl_head| |comma| & |decl_head| \hfill $DC\.\ $ & |int x,|\cr
+\+& |decl_head| |unorbinop| & |decl_head| \hfill $D\.\{U\.\}$ & |int *|\cr
+\+\dag\theprodno& |decl_head| |exp| & |decl_head| \hfill $DE^*$ & |int x|\cr
+\+& |decl_head| \alt|binop| |colon| |exp| \altt|comma| |semi| |rpar| &
+ |decl_head| \altt|comma| |semi| |rpar| \hfill
+ $D=D$\alt $B$ $C$ \unskip$E$ & \maltt initialization {fields or}
+ {default argument} \cr
+\+& |decl_head| |cast| & |decl_head| & |int f(int)|\cr
+\+\dag\theprodno& |decl_head| \altt|int_like| |lbrace| |decl| & |fn_decl|
+ \altt|int_like| |lbrace| |decl| \hfill $F=D\,|in|\,|in|$
+ & |long time () {|\cr
+\+& |decl_head| |semi| & |decl| & |int n;|\cr
+\+& |decl| |decl| & |decl| \hfill $D\,|force|\,D$ & |int n;double x;|\cr
+\+& |decl| \alt|stmt| |function| & \alt|stmt| |function|
+ \hfill $D\,|big_force|\,$\alt $S$ $F$ \unskip& \&{extern} $n$;
+ \\{main} ()|{}|\cr
+\+\dag\theprodno& |typedef_like| |decl_head| \alt|exp| |int_like| &
+ |typedef_like| |decl_head| \hfill $D=D$\alt $E^{**}$ $I^{**}$ \unskip &
+ \&{typedef} \&{char} \&{ch};\cr
+\+& |typedef_like| |decl_head| |semi| & |decl| \hfill $T\.\ D$ &
+ \&{typedef} \&{int} $\&x,\&y$;\cr
+\+& |struct_like| |lbrace| & |struct_head| \hfill
+ $S\,\\{in}\,|force|\\{back}\,L$ & |struct {|\cr
+\+& |struct_like| \alt|exp| |int_like| |semi| & |decl_head|
+ \hfill $S\.\ $\alt $E^{**}$ $I^{**}$ & \&{struct} \&{forward};\cr
+\+& |struct_like| \alt|exp| |int_like| |lbrace| & |struct_head| \hfill
+ $S\.\ $\alt $E^{**}$ $I^{**}$ \unskip $\\{in}\,|force|\,\\{back}\,L$ &
+ \&{struct} \&{name\_info} $\{$\cr
+\+& |struct_like| \alt|exp| |int_like| |colon| &
+ |struct_like| \alt|exp| |int_like| |base| & |class| \&C :\cr
+\+\dag\theprodno& |struct_like| \alt|exp| |int_like| & |int_like|
+ \hfill $S\.\ $\alt$E$ $I$ & \&{struct} \&{name\_info} $z$;\cr
+\+& |struct_head| \altt|decl| |stmt| |function| |rbrace| & |int_like|\hfill
+ $SD\,|force|\,\\{back}\,R\,\.\ |out|$ &
+ |struct {| declaration |}|\cr
+\+& |struct_head| |rbrace| & |int_like|\hfill $S\.{\\,}R$ & |class C{}|\cr
+\+& |fn_decl| |decl| & |fn_decl| \hfill $F\,|force|\,D$
+ & $f(z)$ \&{double} $z$; \cr
+\+& |fn_decl| |stmt| & |function| \hfill $F\,|out|\,|out|\,|force|\,S$
+ & \\{main}() {\dots}\cr
+\+& |function| \altt|stmt| |decl| |function| & \altt |stmt| |decl| |function|
+ \hfill $F\,|big_force|\,$\altt $S$ $D$ $F$ & outer block\cr
+\+& |lbrace| |rbrace| & |stmt| \hfill $L\.{\\,}R$ & empty statement\cr
+\advance\midcol15pt
+\+& |lbrace| \altt|stmt| |decl| |function| |rbrace| & |stmt| \hfill
+ $\matrix{\\{in}\,|force|\,\\{back}\,L\,|noop|\,|cancel|\,S\cr
+ |force|\,\\{back}\,R\,\\{out}\,|force|}$ & compound statement\cr
+\+& |lbrace| |exp| [|comma|] |rbrace| & |exp| & initializer\cr
+\+& |if_like| |exp| & |if_clause| \hfill $I\.{\ }E$ & |if (z)|\cr
+\+& |for_like| |exp| & |else_like| \hfill $F\.{\ }E$ & |while (1)|\cr
+\+& |else_like| |lbrace| & |else_head| |lbrace| & \&{else} $\{$\cr
+\+& |else_like| |stmt| & |stmt| \hfill
+ $|force|\,E\,\\{in}\,|force|\,S\,\\{out}\,|force|$ & |else x=0;|\cr
+\+& |else_head| \alt|stmt| |exp| & |stmt| \hfill
+ $|force|\,E\,\\{bsp}\,S\,\\{force}$ & |else{x=0;}|\cr
+\+& |if_clause| |lbrace| & |if_head| |lbrace| & |if (x) {|\cr
+\+& |if_clause| |stmt| |else_like| |if_like| & |if_like| \hfill
+ $|force|\,I\,\\{in}\,|force|\,S\,\\{out}\,|force|\,E\,\.\ I$ &
+ |if (x) y; else if|\cr
+\+& |if_clause| |stmt| |else_like| & |else_like| \hfill
+ $|force|\,I\,\\{in}\,|force|\,S\,\\{out}\,|force|\,E$ &
+ |if (x) y; else|\cr
+\+& |if_clause| |stmt| & |else_like| |stmt| & |if (x)|\cr
+\+& |if_head| \alt|stmt| |exp| |else_like| |if_like| & |if_like| \hfill
+ $|force|\,I\,\\{bsp}\,S\,|force|\,E\,\.\ I$ &
+ |if (x){y;}else if|\cr
+\+& |if_head| \alt|stmt| |exp| |else_like| & |else_like| \hfill
+ $|force|\,I\,\\{bsp}\,S\,|force|\,E$ &
+ |if (x){y;}else|\cr
+\+& |if_head| \alt|stmt| |exp| & |else_head| \alt|stmt| |exp| & |if (x){y;}|\cr
+\+& |do_like| |stmt| |else_like| |semi| & |stmt| \hfill
+ $\matrix{|force|\,D\,\\{in}\,|force|\,S\,|cancel|\,|noop|\cr
+ \,\\{bsp}\,ES\,\\{out}\,|force|}$ & |do f(x); while (g(x));|\cr
+\+& |case_like| |semi| & |stmt| & |return;|\cr
+\+& |case_like| |colon| & |tag| & |default:|\cr
+\+& |case_like| |exp| |semi| & |stmt| \hfill $C\.\ ES$ & |return 0;|\cr
+\+& |case_like| |exp| |colon| & |tag| \hfill $C\.\ EC$ & |case 0:|\cr
+\+& |tag| |tag| & |tag| \hfill $T_1\,|force|\,T_2$ & |case 0: case 1:|\cr
+\advance\midcol20pt
+\+& |tag| \altt|stmt| |decl| |function| \alt|rbrace| |tag|
+ & \altt|stmt| |decl| |function| \alt|rbrace| |tag|
+ \hfill $|force|\,T\,\\{in}\,|force|\,S\,\\{out}$ & |case 0: z=0;|\cr
+\advance\midcol-20pt
+\+\dag\theprodno& |stmt| \altt|stmt| |decl| |function| &
+ \altt|stmt| |decl| |function|
+ \hfill $S\,$\altt$|force|\,S$ $|big_force|\,D$ $|big_force|\,F$ &
+ |x=1;y=2;|\cr
+\+& |semi| & |stmt| \hfill \.\ $S$& empty statement\cr
+\+\dag\theprodno& |lproc| \altt |if_like| |else_like| |define_like| & |lproc| &
+ \maltt {{\bf \#include}} {\bf\#else} {\bf\#define} \cr
+\+& |lproc| |rproc| & |insert| & {\bf\#endif} \cr
+\+\dag\theprodno& |lproc| \altt|exp| |function| |int_like| |rproc| &
+ |insert| \hfill
+ $I$\.\ \altt {$E$} {$F$} {$I$} & {\bf\#define} $a$\enspace 1 \cr
+\+& |section_scrap| |semi| & |stmt|\hfill $MS$ |force|
+ &$\langle\,$section name$\,\rangle$;\cr
+\+& |section_scrap| & |exp| &$\langle\,$section name$\,\rangle$\cr
+\+& |insert| |any| & |any| & \.{\v\#include\v}\cr
+\+& |prelangle| & |binop| \hfill $<$ & $<$ not in template\cr
+\+& |prerangle| & |binop| \hfill $>$ & $>$ not in template\cr
+\+& |langle| |exp| |prerangle| & |cast| & $\langle\,0\,\rangle$\cr
+\+& |langle| |prerangle| & |cast| \hfill $L\.{\\,}P$ & $\langle\,\rangle$\cr
+\+& |langle| \alt|decl_head| |int_like| |prerangle| & |cast| &
+ $\langle\&{class}\,\&C\rangle$\cr
+\+& |langle| \alt|decl_head| |int_like| |comma| & |langle| \hfill
+ L\,\alt $D$ $I$ C\,|opt|9 & $\langle\&{class}\,\&C,$\cr
+\+& |public_like| |colon| & |tag| & \&{private}:\cr
+\+& |public_like| & |int_like| & \&{private}\cr
+\+& |colcol| \alt|exp| |int_like| & \alt|exp| |int_like| & |::x|\cr
+\+\dag\theprodno&
+ |new_like| \alt|exp| |raw_int| & |new_like| \hfill $N\.\ E$ & |new(1)|\cr
+\+& |new_like| \alt|raw_unorbin| |colcol| & |new_like| & |new ::*|\cr
+\+& |new_like| |cast| & |exp| & |new(*)|\cr
+\+\dag\theprodno& |new_like| & |exp| & |new|\cr
+\+\dag\theprodno& |operator_like| \altq|binop| |unop| |unorbinop| |raw_unorbin|
+ & |exp| \hfill $O$\.\{\altq $B$ $U$ $U$ $R$ \unskip \.\} & |operator+|\cr
+\+& |operator_like| \alt|new_like| |sizeof_like| & |exp| \hfill $O\.\ N$
+ & |operator delete|\cr
+\+& |operator_like| & |new_like| & conversion operator\cr
+\+& |catch_like| \alt|cast| |exp| & |fn_decl| \hfill $CE\,\\{in}\,\\{in}$ &
+ |catch (...)|\cr
+\+& |base| |public_like| |exp| |comma| & |base| \hfill $BP\.\ EC$ &
+ : \&{public} $a$,\cr
+\+& |base| |public_like| |exp| & |base| |int_like| \hfill $I=P\.\ E$ &
+ : \&{public} $a$\cr
+\+& |raw_rpar| |const_like| & |raw_rpar| \hfill $R\.\ C$ & ) \&{const};\cr
+\+& |raw_rpar| & |rpar| & );\cr
+\+& |raw_unorbin| |const_like| & |raw_unorbin| \hfill $RC$\.{\\\ }
+ & $*$\&{const} |x|\cr
+\+& |raw_unorbin| & |unorbinop| & $*$ |x|\cr
+\+& |const_like| & |int_like| & \&{const} |x|\cr
+\+& |raw_int| |lpar| & |exp| |lpar| & \&{complex}$(x,y)$\cr
+\+& |raw_int| & |int_like| & \&{complex} |z|\cr
+\+& |begin_arg| |end_arg| & |exp| & \.{@@[}\&{char}$*$\.{@@]}\cr
+\+& |any_other| |end_arg| & |end_arg| & \&{char}$*$\.{@@]}\cr
+\+& |label| |label| & |label| \hfill $L_1\,|force|\,L_2$ & cf. tags\cr
+\+& |label| \altt|stmt| |decl| |function| & \altt|stmt| |decl| |function|
+ \hfill $\matrix{|cancel|\,|noop|\,\\{out}\,\\{out}\,|force|\cr
+ L\,\\{in}\,\\{in}\,|force|\,S}$ & cf. tags\cr
+\+& |do_like| |lbrace| & |do_head| |lbrace| & \&{do} $\{$ \cr
+\+& |do_head| |stmt| |else_like| |semi| & |stmt| \hfill
+ $D\,\\{bsp}\,S\,|cancel|\,|noop|\,\\{bsp}\,ES$ & |do {x;} while(y);|\cr
+\+\dag\theprodno& |typedef_like| |exp| & |typedef_like| |raw_int| &
+ \&{typedef} \&{?} \&{type} \cr
+\+& |int_like| |binop| |exp| & |int_like| & ? (\CPLUSPLUS/)\cr
+\+& |operator_like| \altt|raw_int| |int_like| |const_like| &
+ |operator_like| \hfill $O$\.{\ }$R$ & \&{operator} \&{name\_info} \cr
+\+\dag\theprodno& |lproc| \altt|exp| |int_like| |const_like| |pp_space| &
+ |lproc| \hfill $I\.\ E\.{\ \\5}$ & {\bf\#define} $a$ $\ldots$ \cr
+\+& |lproc| |exp| |exp| |pp_space| & |lproc| \hfill $I\.\ E_1 E_2\.{\ \\5}$
+ & {\bf\#define} $a(b)$ $\ldots$\cr
+\yskip
+\yskip
+\yskip
+\parindent=0pt
+\dag{\bf Notes}
+\yskip
+Rule 35: The |exp| must not be immediately followed by |lpar| or~|exp|.
+
+Rule 38: The |int_like| must not be immediately followed by |colcol|.
+
+Rule 42: The |exp| must not be immediately followed by |lpar| or~|exp|.
+
+Rule 48: The |exp| or |int_like| must not be immediately followed by |base|,
+|raw_int|, |int_like|, or |const_like|.
+
+Rule 76: The |force| in the |stmt| line becomes \\{bsp} if \.{CWEAVE} has
+been invoked with the \.{-f} option.
+
+Rule 78: The |define_like| case calls |make_underlined| on the following scrap.
+
+Rule 80: Makes the scrap following |lproc| reserved without changing the
+category.
+
+Rule 93: The |raw_int| must not be immediately followed by
+|prelangle| or |langle|.
+
+Rule 96: The |new_like| must not be immediately followed by |lpar|,
+|raw_int|, or |struct_like|.
+
+Rule 97: The operator after |operator_like|
+must not be immediately followed by a |binop|.
+
+Rule 116: This rule only holds outside of {\bf\#define} lines; |exp| must not
+be followed by a |lpar|.
+
+Rule 119: Makes the scrap following |lproc| reserved using the category
+of the scrap following |pp_space| if this scrap is |int_like|, |const_like|,
+or |raw_int|.
+
+\endgroup
+
+
+@q end of prod-alt.w @>
diff --git a/web/c_cpp/c2cweb/example.c b/web/c_cpp/c2cweb/example.c
new file mode 100644
index 0000000000..5d3529fa33
--- /dev/null
+++ b/web/c_cpp/c2cweb/example.c
@@ -0,0 +1,98 @@
+/* This file is part of the c2cweb package Version 1.5 */
+/* written by Werner Lemberg (a7971428@unet.univie.ac.at) 10-Nov-1996 */
+
+/* Grá Gott! */
+
+/* this is an artificial example C-file to demonstrate how c2cweb works. Please
+ note the insertions of @ and @@ `commands' into the C code. You should try
+ the various switches to see how they influence the output */
+
+/* Say
+
+ c2cweb [options] example.h example.c
+
+ to process this example. */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "example.h"
+
+/*@*/
+
+#define MAX_ARRAY 123
+#define test_function(a, b, c) (a+b+c)
+
+int dummy1; /* two dummy variables */
+float dummy2;
+
+/*@*/
+
+/* Two stupid functions */
+
+#ifdef HELLO
+void say_hello(void);
+#else
+void say_goodbye(void);
+#endif
+
+/*@@*/
+
+
+void main(void)
+ {int i=10000;
+ struct Test test;
+
+ while(i--)
+ test.array[i]=i;
+
+ do_nothing(1000);
+
+#ifdef HELLO
+ say_hello();
+#else
+ say_goodbye();
+#endif
+ }
+
+/*@*/
+
+union {
+ float another_dummy1;
+ int another_dummy2;
+} AnotherTest;
+
+/*@*/
+
+#ifdef HELLO
+void say_hello(void)
+ {printf("\nHello\n");
+
+// look at the unbalanced braces!
+// without insertion of /*}*/ right here c2cweb and CWEAVE would be confused
+/*}*/
+#else
+void say_goodbye(void)
+ {printf("\nGoodbye!\n");
+#endif
+ }
+
+/*@*/
+
+// the following piece of code can often be found in source files written for
+// multiple compilers. Before the |#else| statement a /*{}*/ command is
+// inserted
+
+#ifdef __STDC__
+void do_nothing(int count)
+/*{}*/
+#else
+void do_nothing(count)
+ int count;
+#endif
+ {while(count--)
+ ;
+ }
+
+
+/* end of example.c */
diff --git a/web/c_cpp/c2cweb/example.h b/web/c_cpp/c2cweb/example.h
new file mode 100644
index 0000000000..8ab55c02a3
--- /dev/null
+++ b/web/c_cpp/c2cweb/example.h
@@ -0,0 +1,20 @@
+/* This file is part of the c2cweb package Version 1.5 */
+/* written by Werner Lemberg (a7971428@unet.univie.ac.at) 10-Nov-1996 */
+
+// Grá Gott!
+// Hello!
+
+/* this is an example header file to demonstrate how c2cweb works. */
+
+/* Say
+
+ c2cweb [options] example.h example.c
+
+ to process this example. */
+
+
+struct Test {char *pointer;
+ int array[MAX_ARRAY];}; /* a dummy structure */
+
+
+/* end of example.h */
diff --git a/web/c_cpp/c2cweb/history.txt b/web/c_cpp/c2cweb/history.txt
new file mode 100644
index 0000000000..0fc04f18d5
--- /dev/null
+++ b/web/c_cpp/c2cweb/history.txt
@@ -0,0 +1,122 @@
+This file is part of the c2cweb package 1.5
+written by Werner Lemberg (a7971428@unet.univie.ac.at) 10-Nov-1996
+
+
+
+History of the c2cweb package
+=============================
+
+
+Version 1.0 :
+1-Mar-1994 only two persons got it :-)
+
+Version 1.1 :
+8-Mar-1994 initial release
+
+ new:
+ $ in identifiers are now allowed (CWEAVE)
+
+ whitespaces before preprocessor commands are now allowed
+ (CWEAVE)
+
+ the concatenation operator ## added (CWEAVE)
+
+ option -1 added (one-sided output) (c2cweb)
+
+ minor changes affecting documentation only
+
+ errors:
+ Ver 1.0 erroneously reported `@' outside of a string
+ (c2cweb)
+
+ /*}*/ started a new code section at function block level
+ if in /*@*/-mode (c2cweb)
+
+ tabs were not handled correctly (c2cweb)
+
+Version 1.2:
+13-Apr-1994 new:
+ c2cweb and cweave should now compile smoothly under UNIX
+ (tested with Linux)
+
+ paper format definition moved from c2cweb to compiler.w
+
+ some files renamed; makefile for c2cweb added
+ errors:
+ A serious bug introduced in Ver. 1.1 caused whitespaces
+ be swallowed (c2cweb)
+
+Version 1.3:
+20-June-1994: new:
+ Makefiles enhanced
+
+ new patchlevel of emx.exe
+
+ c2cweb.dvi added
+
+ c2cweb.txt updated
+ errors:
+ '"' couldn't be used; corrected (c2cweb)
+
+ sometimes the macro `\e' was concatenated with the next
+ word; '\e ' now written (c2cweb)
+
+ wrong index entry for dollar sign corrected (CWEAVE)
+
+ bug in original CWEAVE corrected:
+ you couldn't write e.g. @<Cases for |'\''|@>
+
+Version 1.4:
+20-Aug-1994: new:
+ based now on CWEB 3.2 (July 1994)
+
+ original CWEB source files for CWEAVE added
+
+ additional cwebmac.tex style; original cwebmac.tex
+ renamed in cwebmac.ori
+
+ c2cweb.txt has now an installation section
+
+ C-code example modified
+ errors:
+ \ at the end of the line in multi-line strings will now
+ be treated correctly (c2cweb)
+
+ from 1.3 : '\e ' is of course wrong. It must be '\e{}'
+ (and sometimes '\e{}%') (c2cweb)
+
+ //-comment handling was buggy (c2cweb)
+
+ braces in comments could cause an error (c2cweb)
+
+ email address changed (same host; old address became
+ unreachable)
+
+Version 1.5:
+10-Nov-1996: new:
+ now based on CWEB 3.4g (June 1996)
+
+ option -f (to include a format file) added
+
+ new command /*{}*/ added
+
+ Makefiles enhanced (a compiling run under djgpp is
+ likely to fail since it's untested. Additionally
+ wildcard expansion is missing---any volunteers to add
+ it are welcome)
+
+ c2cweb.w more structured
+
+ new email address
+ changed:
+ runtime binaries has been removed. You should get the
+ emxrsx.zip package of the emTeX distribution instead.
+
+ minor optical corrections.
+
+Version 1.5.1:
+28-Jun-1997: errors:
+ a `char' variable corrected to `int'.
+
+
+--- end of history.txt ---